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
复制表达式 是值表达式的乘数。复制表达式具有以下格式。
- 集合中成员的算术表达式:
{v(name), L(name) , numerals, programming variables}
v(name) 是一个值运算符,它生成具名数据类型的数值;L(name) 是一个长度运算符,它生成具名字符串长度的数值。
编程变量在项格式三中描述。算术运算符如下所示,并具有其通常的含义。
{*, /, +, -}
或 2) 终结符 “#”,它表示值表达式的任意倍数。
值表达式 是以数据类型所指示的格式表示的项的单元值。 值表达式根据复制表达式重复。 值表达式具有以下格式:
- 与复制表达式的第 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,其后跟一个终结符 '?'。 这引出了三个问题:
-
任意长度的项必须以字面量分隔,因为这些数据并非特定于某种类型。
-
只能用在规则的左侧。
-
需要一种截断/填充方案。
截断/填充方案如下:
-
字符到字符(类型:A、E)输出左对齐,在右侧进行截断或填充(用空白)。
-
字符到数值(A、E 到 D、O、H、B)
-
数值到字符(D、O、H、B 到 A、E)
-
数值到数值(D、O、H、B)输出右对齐,在左侧进行填充或截断。 如果输出为数值,则填充为零。