Parsing 如何解决移位,减少明确语法中的冲突

Parsing 如何解决移位,减少明确语法中的冲突,parsing,grammar,shift-reduce-conflict,lalr,Parsing,Grammar,Shift Reduce Conflict,Lalr,我正在尝试使用一个LALR(1)解析器生成器(Bison,但问题并不特定于该工具)解析一个简单的语法,并且我遇到了一个shift-reduce冲突。我找到的关于修复这些问题的文档和其他来源往往会说以下一个或多个: 如果语法不明确(例如If-then-else歧义),请更改语言以修复歧义 如果是运算符优先级问题,请明确指定优先级 接受默认解决方案并告诉生成器不要对此进行投诉 然而,这些似乎都不适用于我的情况:就我所知,语法是明确的(当然,它只有一个lookahead字符是不明确的),它只有一个

我正在尝试使用一个LALR(1)解析器生成器(Bison,但问题并不特定于该工具)解析一个简单的语法,并且我遇到了一个shift-reduce冲突。我找到的关于修复这些问题的文档和其他来源往往会说以下一个或多个:

  • 如果语法不明确(例如If-then-else歧义),请更改语言以修复歧义
  • 如果是运算符优先级问题,请明确指定优先级
  • 接受默认解决方案并告诉生成器不要对此进行投诉
然而,这些似乎都不适用于我的情况:就我所知,语法是明确的(当然,它只有一个lookahead字符是不明确的),它只有一个操作符,默认解析会导致正确格式输入的解析错误。是否有任何技术可以重新定义语法,以消除移位或减少不属于上述范围的冲突

具体来说,这里有语法问题:

%token LETTER

%%
%start input;
input:          /* empty */ | input input_elt;
input_elt:      rule | statement;
statement:      successor ';';
rule:           LETTER "->" successor ';';
successor:      /* empty */ | successor LETTER;
%%

其目的是解析形式为“[A-Za-z]+”或“[A-Za-z]->[A-Za-z]+”的分号分隔行

感谢您缩减语法并发布它。将继任者规则更改为-

successor:      /* empty */ | LETTER successor;

…为我工作。它的语言看起来很明确。

使用Solaris版本的
yacc
,我得到:

1: shift/reduce conflict (shift 5, red'n 7) on LETTER
state 1
    $accept :  input_$end
    input :  input_input_elt
    successor : _    (7)

    $end  accept
    LETTER  shift 5
    .  reduce 7

    input_elt  goto 2
    rule  goto 3
    statement  goto 4
    successor  goto 6
所以,问题在于,正如它经常出现的那样,空洞的规则——特别是空洞的继任者。目前还不完全清楚您是否希望允许分号作为有效输入—目前是这样。如果将继任者规则修改为:

successor: LETTER | successor LETTER;

shift/reduce冲突被消除。

呸,我对编译理论有点生疏。。。你知道你的语法中的冲突在哪里吗?Bison说“POSIX说%开始规则必须出现在%%行之前”。这是一个正确的递归规则-它具有含义(主要是在堆栈溢出之前可以找到的字母数)。不过,它确实解决了转移/减少冲突。