我有一个LR(1)冲突的语法,我无法解决;但是,语法应该是明确的。我将首先用五个令牌简化语法来演示问题:(
,)
,{}
,,
和id
。如何将此语法转换为LR(1)?
的EBNF是这样的:
args = (id ',')*
expression = id
| '(' expression ')'
| '(' args ')' '{}'
语法是明确的,需要前瞻的最多两个令牌。当(
移位时,只有五种可能性:
(
→重复。)
→减少为'(' args ')'
。id
)
不是{}
→缩小为'(' expression ')'
。id
)
{}
→降低作为'(' args ')' '{}'
id
,
→降低作为'(' args ')' '{}'
(最终)。
一个天真的翻译产生以下结果(和conflicts):
formal_arg: Ident
{}
formal_args: formal_arg Comma formal_args
| formal_arg
| /* nothing */
{}
primary: Ident
| LParen formal_args Curly
| LParen primary RParen
{}
所以,语法要求先行决定的最多三个令牌。我知道一个LR(3)语法为can be transformed LR(1)语法。
但是,我不太了解如何在这种特殊情况下进行转换。请注意,上面的简化语法是从larger body of code中提取的;特别是有可能变换primary
而不碰expr
以及上述所有内容?
事实上我刚刚得出了和你一样的结论。然而,我的解析器生成器(menhir)具有更高阶的规则,所以我可以让它为我做出咕噜的工作。我可能会自己回答这个问题(如果它适用于我),抱歉不接受! – whitequark
最有趣的部分是我知道你链接到的问题的作者。 – whitequark
我刚刚与你的转换一起工作,虽然需要一套奇怪的语法转换。真棒。 – whitequark