如何解决此解析冲突?

时间:2019-08-13 12:25:37

标签: parsing lemon

我有一个用柠檬写的小语法,该语法引起解析冲突。

这是引起冲突的语法部分:

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

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

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

谢谢。

2 个答案:

答案 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优先声明之间有两个主要区别:

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

  2. 在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条目中有一个如何执行此操作的示例。