【发布时间】:2013-05-31 11:48:25
【问题描述】:
标题中简洁地给出了我想问的问题。让我举一个有问题的语法的例子:
identifier_list
: identifier
| identifier_list identifier;
lambda_arguments
: '(' identifier_list ')'
| identifier;
lambda
: lambda_arguments '=>' expression
然后我们添加正常的 C 表达式语法 - 特别是,
primary_expression
: '(' expression ')'
| identifier
| lambda;
真正的问题是,这个语法 LALR(1) 是否可解析,即能够被自动解析器生成器解析?还是需要手动或 GLR 解析器?请注意,我希望具体了解本小节,而不是上下文相关的关键字或任何其他部分。
我现在在想的是,如果解析器看到'(' identifier ')',这有两个有效的解析,所以如果解析器看到identifier,向前看')',它将无法决定哪个解析树下去。不过,这可能只是一个移位/减少冲突,我可以通过分配一些任意优先级来消除它(可能有利于'(' identifier ')')。
编辑:实际上,我正在考虑 stealing 使用语法的这个小节来实现新语言中的类似功能。我已经有语法形式类似于 JavaScript 的匿名函数,但我的 gunea pigs squeaks 反馈抱怨它们对于许多用途来说过于冗长,并指出 C# lambda 表达式是更理想的解决方案。我担心此解决方案可能导致歧义。所以,真的,我只对那个小节感兴趣。泛型和演员表等其他东西对我来说不是问题。
我以前的语法版本是可机械解析的,我不想失去这个属性,而我之前使用机械生成器的经验告诉我,最好在这里检查而不是自己尝试。对于我的手动解析器,我当然可以简单地使用特殊情况 '(' identifier 来比正常情况更进一步。
【问题讨论】:
-
@EricLippert 或许可以回答这个问题。
-
这是一个@JonSkeet 问题
-
虽然 Eric 和 Jon 真的很聪明并且知道很多(有时是内部的)东西,但似乎这个语法问题可以由没有“内部知识”的人来回答(阅读:远高于我的)对语法和解析器的理解..
-
LALR(1)、手辊和 GLR 不是唯一的选择。只要语法是明确的,只要语法不包含间接或隐藏的左递归,ANTLR 4 就能够生成有效的解析器。