开发起始,花了一定的时间调研寻找一个好的语法解析器,因为在表格安全性检查过程中需要解析各种形式灵活的检查规则,所以需要一个类似lex/yacc这样具有强大语言解析功能,但语法规则又可以轻量级配置的解析器,最后选择了一种近似上下文无关CFG(context-free-grammar)的语言PEG(parsing-expression-grammar),作为我们编写检查规则的基础文法。
- PEG文法
V = {a, b},
有限递归级联合并规则就是
S <-- ab
S <-- aSb
这两条规则产生的语言S 就等于{a nb n, n >= 1}。而语言{a nb n c n, n >= 1}虽然也具备有限的确定元素集合,但不能由递归级联合并规则所产生,所以其不属于上下文无关语言。
然而上下文无关文法(CFG)却因为其规则的灵活性和语法解析的多样性,在工程运用上存在着障碍。CFG文法属于一种可以自顶向下解析的语言,如果一个字符串属于一种CFG语言,那么可以将这个字符串自顶向下逆向推导出构建的过程,产生一个语法解析树,而对于大多数CFG语言来说,其合法字符串可以被解析成多个不同结构的语法树,譬如如下的CFG语言(例子2)S <-- a
S <-- S+S
解析字符串a+a+a就会得到两种不同的语法解析树,如下所示:
S/ | \
/ | \
/ | \
S + S
| / | \
| / | \
a S + S
| |
a a
S
/ | \
/ | \
/ | \
S + S
/ | \ |
/ | \ |
S + S a
| |
a a
正是为了消除 CFG 语言在语义上的歧义性,工程中引入了 PEG 这种也可以自顶向下解析的语言。 PEG 在尽量保持 CFG 语言解析能力的同时,还可以保证语法解析树的唯一性,计算理论对 PEG 与 CFG 之间的差异进行了详细的阐述。就个人理解而言, PEG 的本质就是对 CFG 语言的级联 规则做了相应的限制,使 PEG 在解析语言的时候有了一定的顺序性 (ordering) ,从而保证了语法解析树的唯一性。
相比灵活的 CFG 语法级联规则, PEG 只支持以下的几种级联操作:
• Sequence: e 1 e 2
• Ordered choice: e 1 | e 2
• Zero-or-more: e*
• One-or-more: e+
• Optional: e?
对于上面提到的 CFG 语法(例子 2 ),只需将对应的规则进行稍稍的修改就可以转化成 PEG 文法(例子 3 ):
S1 <-- a
S2 <-- S3
S3 <-- (S1 | S2 ) + ZeroOrMore( ‘ + ’ + (S1 | S2))
对于 a+a+a,就只能解析成为如下语法解析树: <