Compiler construction 这是生产吗;expr->;{print(';+;';)}expr+;术语;左递归?

Compiler construction 这是生产吗;expr->;{print(';+;';)}expr+;术语;左递归?,compiler-construction,context-free-grammar,Compiler Construction,Context Free Grammar,我想知道这个产品是否是左递归的:“expr->{print(+')}expr+term”。所以如果它是左递归的,我需要消除左递归,这样它就会陷入循环中。我在这里不确定,因为声明: “{print(+')}”出现在“expr”之前。不,它不是左递归的,因为派生的最左边的东西不是产品左边的非终结符。左递归的一个例子是: expr -> expr '+' term 因为第一个被派生的东西就是被定义的东西。对于某些解析算法来说,这可能会有问题(请参阅此问题了解详细信息:),因为它可能会导致无限循

我想知道这个产品是否是左递归的:“expr->{print(+')}expr+term”。所以如果它是左递归的,我需要消除左递归,这样它就会陷入循环中。我在这里不确定,因为声明:
“{print(+')}”出现在“expr”之前。

不,它不是左递归的,因为派生的最左边的东西不是产品左边的非终结符。左递归的一个例子是:

expr -> expr '+' term

因为第一个被派生的东西就是被定义的东西。对于某些解析算法来说,这可能会有问题(请参阅此问题了解详细信息:),因为它可能会导致无限循环。如果确实遇到左递归,并希望消除它,可以通过左分解语法来消除它。有关左因子分解的更多详细信息可以找到(或通过谷歌搜索“左因子语法”)

我在这里假设,
{print(+')}
的含义是“输入此产品时将“+”输出到屏幕”。ª

在这种情况下,与识别左递归无关,因为找到左递归的相关问题不是“在递归之前是否执行了任何代码?”,而是“在递归之前是否使用了任何标记?”。由于执行嵌入式代码不会消耗任何令牌,因此这个问题的答案是“否”,因此确实存在左递归


我之所以这样假设,是因为
{…}
是在解析器生成器中嵌入代码的常用语法(事实上,这是我见过的唯一语法),
print('x')
看起来确实像是要嵌入的代码,如果
print('x')
是指一系列终端,它更可能被写为
'print'('x')”
(因为为什么要在x周围加引号,而不是其他?。

规则最左边的术语是一个终端,它不能是左递归的。如果
{..}
这里有零次或多次重复的传统含义,那么我想我不同意其他两张海报:产品是递归的,因为
expr
可以从自身到达,其间不消耗任何标记。是否愿意透露您使用的解析器生成器?如果没有这个上下文,您问题中显示的语法很混乱。如果我知道您使用的是哪个解析器生成器,我可能会尝试实际的答案。然而,如果
{print(+')}
被认为是一个中间规则操作,那么实际上没有解析器生成器会使用该规则,这不是因为左递归,而是因为它需要一个水晶球来知道缩减是适当的。(您可以将解析器生成器用于延迟操作,但我认为您实际上不想延迟该操作,除非您也延迟所有其他操作。)我正在使用解析器将表达式从中缀符号转换为前缀符号。是的,您的假设是正确的。这个print语句的原因是生成输入的前缀符号,如:5+2->+52。