我对形式语言和编译器理论的了解有限。所以我正在通过 Terence Parr 的书The Definitive ANTLR 4 Reference
学习。
在书中,它说:
现在,使用v4,您可以将表达式与看起来像的规则匹配 这样:
expr : expr '*' expr // match subexpressions joined with '*' operator | expr '+' expr // match subexpressions joined with '+' operator | INT // matches simple integer atom ;
像expr这样的自引用规则是递归的,特别是, 左递归,因为它至少有一个替代品 指自己。
但我认为大胆的部分是不正确的。如果右侧最左边的符号与左侧的非终端符号相同,则生成为here,生成为左递归。例如,
expr → expr + term.
回到Terence的书中,既没有递归也没有递归。它只是递归的。
我是对的吗?或者我误解了作者?
感谢目前为止的回复。对不起,我没有让自己清楚。
我的理解是:left-recursive
表示右侧的left-most
部分与左侧的非终端相同。 AND 右侧的剩余部分是仅后缀 NOT 左侧。
在Parr的书籍样本中,右侧的重新部分不是后缀,而是另一个 expr
,所以我不# 39;认为严格符合左递归规则。
答案 0 :(得分:1)
让我们比较一下这本书给出的左递归规则的例子:
expr → expr + term.
使用您正在检查的复合规则的第一部分:
expr : expr '*' expr // match subexpressions joined with '*' operator
这里左侧是expr
;右侧是expr '*' expr
,右侧最左侧的符号是expr
。由于右侧最左边的符号expr
与左侧的符号相同,也是expr
,因此规则的这一部分是递归的。
复合规则的第二部分也将是左递归的,原因相同:
expr : expr '+' expr
复合规则的第三部分不是递归的,因为INT是一个原子:
expr : INT // matches simple integer atom
当您使用expr
运算符将|
的这三个不同表达式合并为一个表达式时,您会在问题中得到原始表达式:
expr : expr '*' expr // match subexpressions joined with '*' operator
| expr '+' expr // match subexpressions joined with '+' operator
| INT // matches simple integer atom
;
其中,由于其三个选项中至少有一个是左递归的,因此本身是左递归的。
答案 1 :(得分:1)
“如果右侧最左边的符号与左侧的非终端符号相同,则生产是递归的。”
在您的示例中,“expr - > expr + term”右侧最左侧的符号为“expr”,左侧的非终端符号为“expr”,因此它们是相同的。制作是左递归的。您的替代品是“expr * expr”和“expr + expr”没有区别;你的定义仍然是左递归的。
如果您认为您正在创建解析器来解析此语言,那么您将拥有一个名为“parseExpr”的函数来解析“expr”。根据定义,为了评估“expr +(anything)”,首先必须做的是解析“expr”。因此它应该调用函数来解析“expr”,这当然是本身。这基本上就是左递归的意思。