如何解决此解析冲突?



我有一个用柠檬写的小语法,它导致了解析冲突。

这是导致冲突的语法部分:

selection_statement ::= KWD_IF LPAREN expression RPAREN statement.
selection_statement ::= KWD_IF LPAREN expression RPAREN statement KWD_ELSE statement.

我已经看到了这个答案,但它仅适用于野牛/yacc,我不知道如何在柠檬中复制它。

解决此解析冲突的最佳方法是什么?

提前谢谢。

Lemon 以与 Bison 相似但不完全相同的方式实现优先级规则,该功能可用于解决您遇到的"悬空其他"移位/减少冲突,因为它通常应用于野牛。

柠檬和野牛优先声明之间有两个主要区别:

  1. 野牛提供%precedence作为%left%right%nonassoc的替代品。但是,%nonassoc通常可以在%precedence更合适的任何地方使用。

  2. 在 Bison 中,您可以使用%prec TERMINAL显式声明生产的优先级。在Lemon中,您可以通过在生产后放置[TERMINAL]来做同样的事情。(这在上面链接的手册的优先规则部分中进行了说明。

此外,Bison允许您对终端使用双引号字符串,这是Lemon中不可用的功能。

综上所述,您可以将Bison解决方案适应柠檬,如下所示:

/* LEMON (non-terminals abbreviated) */             /* Bison (from linked answer) */
%nonassoc KWD_IF                                    %nonassoc "then"
%nonassoc KWD_ELSE                                  %nonassoc "else"
%%                                                  %%
sel: KWD_IF LPAREN exp RPAREN stm. [KWD_ELSE]       stm: "if" "(" exp ")" stm            %prec "then"
| KWD_IF LPAREN exp RPAREN stm KWD_ELSE stm.        | "if" "(" exp ")" stm "else" stm

也可以使语法明确,但这需要做更多的工作。在链接的维基百科条目中有一个关于悬空的例子。

编写的语法模棱两可且不正确,因为您实际上不想允许在另一个 ELSE 前面没有 ELSE 的选择语句。 在这种情况下,else 应绑定到内部选择语句。

你可以这样修复它:

statement ::= open_sel
statement ::= closed_sel
statement ::= other
open_sel ::= KWD_IF LPAREN expression RPAREN open_sel
open_sel ::= KWD_IF LPAREN expression RPAREN other
closed_sel ::= KWD_IF LPAREN expression RPAREN closed_sel
closed_sel ::= KWD_IF LPAREN expression RPAREN closed_sel KWD_ELSE statement
closed_sel ::= KWD_IF LPAREN expression RPAREN other KWD_ELSE statement

它既复杂又挑剔,如果你有多种陈述,比如如果......否则,这就是为什么人们通常依赖解析器生成器中的默认冲突解决。

解析器生成器工具的作者都知道这一点,因此几乎每个解析器生成器都有冲突解决规则,如果...否则无需像这样重构语法即可工作。

相关内容

  • 没有找到相关文章

最新更新