我有一个无法解决的 LR(1) 冲突的语法;然而,语法应该是明确的。我将首先用五个标记的简化语法来演示这个问题:(
、)
、{}
和。,
id
EBNF 看起来像这样:
args = ( id ',' )*
expression = id
| '(' expression ')'
| '(' args ')' '{}'
语法是明确的,最多需要两个前瞻标记。当(
移位时,只有五种可能:
(
→ 重复。)
→ 减少为'(' args ')'
。id
)
不{}
→ 减少为'(' expression ')'
。id
)
{}
→ 减少为'(' args ')' '{}'
id
,
→ 减少为'(' args ')' '{}'
(最终)。
天真的翻译会产生以下结果(和冲突):
formal_arg: Ident
{}
formal_args: formal_arg Comma formal_args
| formal_arg
| /* nothing */
{}
primary: Ident
| LParen formal_args Curly
| LParen primary RParen
{}
因此,语法最多需要三个前瞻标记来决定。我知道 LR(3) 语法可以转换为 LR(1) 语法。
但是,我不太明白在这种特殊情况下如何进行转换。请注意,上面的简化语法是从大量代码中提取的;primary
特别是,是否有可能在不触摸和上述所有内容的情况下进行转换 expr
?