我正在尝试为C编写一个编译器(虽然简单的语法)。
有些事情我已经坚持了一段时间。如果我没有正确理解,所有二进制操作都是关联的。因此,如果我们有“x + y + z”,则首先出现x + y,然后出现加号z。
但是,不执行左关联会导致无限左递归吗?
到目前为止,我检查过的所有解决方案都是左关联的,或者没有左递归,但都不是。是否可以使用具有这两种属性的语法。它甚至可能吗?
示例:
左关联:
Expr = Term | Expr + Term
Term = Element | Term ∗ Element
Element = x|y|z|(Expr)
消除左递归:
Expr = Term ExprTail
ExprTail = epsilon | + Term ExprTail
Term = Element TermTail
TermTail = epsilon | * Element TermTail
Element = x|y|z|(Expr)
有什么想法吗?
答案 0 :(得分:5)
如果操作符是左关联的,则相应的生成将保持递归。
如果您使用LR解析器生成器,那么没有问题。 LR算法在处理左递归方面没有问题(并且任何其他类型的递归都没有问题,尽管它可能需要更多的堆栈空间)。
您还可以使用其他自下而上的技术,例如经典的运算符优先算法(即shunting yard),但LR解析严格更具表现力,解析器生成器使实现相对简单。
如果你坚持递归下降解析,那是可能的,因为你可以使用循环解析重复的模式(理论上是正确的递归),但是从左到右组合元素。在某种理论意义上,这是对AST的树重写,但我怀疑很多程序员编写了这些代码而没有注意到树的修复。