跳到主要内容

Form Machine

I. 形式​

一个形式是一个有序的规则集合。

      F = {R1, ...,Rn}

第一条规则(R1)是优先级最高的规则;最后一条规则(Rn)是优先级最低的规则。

Form Machine 作为输入接收:1) 一份界定输入流的地址与长度列表;2) 一份界定输出区的地址与长度列表;3) 一个指向形式列表的指针;4) 一个指向输入流起始位置的指针;5) 一个指向输出区起始位置的指针。 Form Machine 将一个形式应用于输入串,在输出区中产生一个输出串。 形式按如下方式应用:

步骤 1: 将 R1 设为当前规则。

步骤 2: 将当前规则应用于输入数据。

步骤 3: a) 如果规则失败,则将优先级低一级的规则设为当前规则。

b) 如果规则成功,则将优先级最高的规则设为当前规则

c) 当优先级最低的规则失败时,形式失败,形式对输入数据的应用终止。

步骤 4: 继续执行步骤 2。

此外,在步骤 2 期间,如果输入串的剩余部分不足以满足某条规则,那么该规则失败,且不会产生部分结果。 如果某条规则填满了输出串,形式的应用即终止。

II. 规则​

一条规则是如下形式的替换操作:

      left-hand-side -> right-hand-side

规则的两侧各由一系列零个或多个 项(见下文)组成,各项之间以逗号分隔。

规则的左侧在当前位置上作为模式匹配操作应用于输入串。 如果它精确描述了输入,则 1) 当前输入位置指针越过已匹配的输入向前推进,2) 右侧在输出串的当前位置产生数据,3) 当前输出位置指针越过已产生的数据向前推进。

III. 项​

一个项是一个变量,用于描述待匹配的输入串或待产生的输出串。 一个项有三种格式。

项格式 1​

+---------------------------------------------------------------------+
| |
| name ( data replication . value : length ) |
| type expression expression expression |
| |
|_____________________________________________________________________|

这些字段中的任何一个都可以缺省。

在通常的编程语言意义上,名称 是该项的符号名。 它是单个小写字母,在一条规则内唯一。

数据类型 描述该项所表示的数据种类。它是集合中的一个成员:

         {D, O, X, A, E, B}

数据类型具有以下含义和隐含的单位长度:

      Char.       Meaning               Length
----- -------- -------
D decimal number 1 bit
O octal number 3 bits
X hexadecimal number 4 bits
A ASCII character 8 bits
E EBCDIC character 8 bits
B binary number 1 bit

复制表达式 是值表达式的乘数。复制表达式具有以下格式。

  1. 集合中成员的算术表达式:
          {v(name), L(name) , numerals, programming variables}

v(name) 是一个值运算符,它生成具名数据类型的数值;L(name) 是一个长度运算符,它生成具名字符串长度的数值。

编程变量在项格式三中描述。算术运算符如下所示,并具有其通常的含义。

         {*, /, +, -}

或 2) 终结符 “#”,它表示值表达式的任意倍数。

值表达式 是以数据类型所指示的格式表示的项的单元值。 值表达式根据复制表达式重复。 值表达式具有以下格式:

  1. 与复制表达式的第 1) 部分相同,其中 v(name) 同样产生一个数值

或 2) 集合中的单个成员

         {v(name), quoted literal}

其中 v(name) 产生一个数据类型(E 或 A)的值)。 (注意,拼接是通过多个项完成的。)

长度表达式 是包含值表达式的字段(经复制表达式修改后)的长度。 它具有与复制表达式相同的格式。

因此,该项

x(E(7.'F'):L(x)) 名为 x,类型为 EBCDIC,值为 'FFFFFFF',长度为 7。

该项

规则左侧的 y(A:8) 会以接下来的 64 位输入作为其值被赋值;在右侧,它只会使输出指针向前推进 64 位的位置,因为它没有值表达式(内容)来在输出区中产生数据。

项格式 2​

+---------------------------------------------------------------------+
| |
| name (label) |
| |
+---------------------------------------------------------------------+

标号 是对规则中先前已命名的项的符号引用。 它与该名称所指的项具有相同的值。

下面的恒等操作说明了 标号 记法的用法。

      a(A:10) -> (a)

右侧的 (a) 使项 a 在输出区中被输出。 它等价于下面的规则。

      a(A:10) -> (Av(a):L(a))

项格式 3​

+---------------------------------------------------------------------+
| |
| name ( programming connective operand ) |
| variable expression |
| |
+---------------------------------------------------------------------+

编程变量 是一种由用户控制的数据项,它并不显式地出现在输入/输出流中。 它的值可以与输入数据、常量相比较,并可用于生成输出数据。编程变量是单个小写希腊字母。

它们用于:在输出区中生成下标、计数器等;在输入区中比较下标、计数器等;以及在数据与上下文相关时绑定替换规则(稍后解释)。

连接词 是集合中的一个成员:

         {<-, =, !=, >=, <=, <, >}

左箭头表示用右侧部分替换左侧部分;其他连接词是比较符。

操作数表达式 是集合中成员的算术表达式:

         {programming variables, v(name), l(name), numerals}

例如,如果编程变量 [alpha] 的值为 0,且规则

      a(H[alpha]:1) -> (a), ([alpha]<-[alpha]+1), (H[alpha]:1)

被穷尽地应用于一串十六进制数字

      0 1 2 3 4 5

则输出将是该十六进制字符串

      0 1 1 2 2 3 3 4 4 5 5 6 .

注意: 上述规则等价于

      a(B[alpha]:4) -> (a), ([alpha]<-[alpha]+1), (B[alpha]:4)

IV. 项函数的限制与解释​

当一条规则成功时,将产生输出。 在规则

      a(A:#),(A'/':1)->(Ev(a):74),(E'?':1)

输入串中被搜索任意数量的 ASCII 字符后跟一个终结符 '/'。 这些 ASCII 字符 (a) 在一个 74 字节的字段中被转换为 EBCDIC,其后跟一个终结符 '?'。 这引出了三个问题:

  1. 任意长度的项必须以字面量分隔,因为这些数据并非特定于某种类型。

  2. 只能用在规则的左侧。

  3. 需要一种截断/填充方案。

截断/填充方案如下:

  1. 字符到字符(类型:A、E)输出左对齐,在右侧进行截断或填充(用空白)。

  2. 字符到数值(A、E 到 D、O、H、B)

  3. 数值到字符(D、O、H、B 到 A、E)

  4. 数值到数值(D、O、H、B)输出右对齐,在左侧进行填充或截断。 如果输出为数值,则填充为零。