我有一个用柠檬写的小语法,该语法引起解析冲突。
这是引起冲突的语法部分:
selection_statement ::= KWD_IF LPAREN expression RPAREN statement.
selection_statement ::= KWD_IF LPAREN expression RPAREN statement KWD_ELSE statement.
我看到了this的答案,但它仅适用于野牛/野牛,我不知道如何在柠檬中复制它。
解决此解析冲突的最佳方法是什么?
谢谢。
答案 0 :(得分:1)
所写的语法是模棱两可且不正确的,因为您实际上不希望在没有另一个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
这很复杂而且很挑剔,如果您有多种语句(例如if ... else),情况会变得更糟,这就是为什么人们通常依赖解析器生成器中的默认冲突解决方案。
解析器生成器工具的作者知道这一点,因此几乎每个解析器生成器都有解决冲突的规则,这些规则使if ... else在不重构语法的情况下工作。
答案 1 :(得分:1)
柠檬以与Bison类似但不太完全的方式实现precedence rules,并且该功能可用于解决您遇到的"dangling else"移位/减少冲突,因为它是通常用于野牛。
Lemon和Bison优先声明之间有两个主要区别:
Bison提供了%precedence
作为%left
,%right
和%nonassoc
的替代。但是,%nonassoc
通常可以在%precedence
更合适的任何地方使用。
在Bison中,您可以使用%prec TERMINAL
显式声明生产的优先级。在Lemon中,您可以通过在制作后放置[TERMINAL]
来执行相同的操作。 (这在上面链接的手册的优先级规则部分中进行了说明。)
此外,Bison允许您在终端中使用双引号引起来的字符串,Lemon不提供此功能。
将它们组合在一起,就可以使Bison solution适应柠檬,如下所示:
/* 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
也可以使语法明确,但这需要更多工作。在悬而未决的其他链接的Wikipedia条目中有一个如何执行此操作的示例。