我正在尝试解析C。我一直在查阅一些自由上下文C语法,我观察到它们通常通过使用";"链式";生产规则,例如[here][1]这样的操作是为了对逻辑或和逻辑与表达式进行建模:
<logical-or-expression> ::= <logical-and-expression>
| <logical-or-expression> || <logical-and-expression>
<logical-and-expression> ::= <inclusive-or-expression>
| <logical-and-expression> && <inclusive-or-expression>
我说这些表达式是链式的,因为它们遵循以下结构:
expression with operator(N) ::= expression with operator(N+1)
| (expression with operator(N)) operator(N) (expression with operator(N+1))
其中N是运算符的优先级。我理解目的是消除语言的歧义,并以纯粹的句法方式引入优先级和关联规则。
有什么理由在支持运算符优先级的实际解析器中对这样的表达式建模吗我最初的想法是将它们简单地实现为:
constant_expression ::= expression1 binary_op expression2
其中binary_op是任何二进制运算,然后通过设置所有运算符的优先级来消除歧义。例如:
logical_expr ::= simple_expr | logical_expr && logical_expr | logical_expr || logical_expr
然后设置&;运算符高于||。我认为这种策略会提供一个简单得多的语法,因为它会消除每个优先级都需要不同规则的必要性,但我不愿意使用它,因为我看到的所有实现都使用了前一种策略,即使在解析器有优先级支持的情况下也是如此。
提前谢谢。[1] :https://cs.wmich.edu/~gupta/taching/cs4850/sumII06/The%20syntax%20of%20C%20in%20Backus Naur%20form.htm
许多LR风格的解析器可以使用语法本身之外的一些机制来处理运算符优先级规则,部分原因是它允许您跳过这种"分层"方法来编写CFG。如果您有一个支持这一点的解析器生成器,那么可以编写一个不明确的语法,然后添加这些外部规则来获得优先级和关联性。
需要注意的是,CFG和BNF规则的解析器通常对规则的编写顺序不敏感,因此仅列出从最高优先级到最低优先级的运算符是不够的。(另一方面,PEG解析器确实表示有序的选择(。此外,由于大多数解析器生成器的工作方式(将要执行的代码与每个生产关联起来,并使用生产中的终端来确定运算符优先级(,与使用一个形式为"Expr operator Expr"的规则相比,拥有单独的规则(每个二进制运算符一个(通常更容易。但除此之外,基本方法是合理的。