0

考虑以下语法:

%start stmt;
%right "else";

stmt: "foo"
   | "if" "(" exp ")" stmt
   | "if" "(" exp ")" stmt "else" stmt 

exp: "foo2"

在运行野牛(带有反例)时,我得到:

parser.yy: warning: 1 shift/reduce conflict [-Wconflicts-sr]
parser.yy: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
  Example: "if" "(" exp ")" "if" "(" exp ")" stmt • "else" stmt
  Shift derivation
    stmt
    ↳ 2: "if" "(" exp ")" stmt
                          ↳ 3: "if" "(" exp ")" stmt • "else" stmt
  Reduce derivation
    stmt
    ↳ 3: "if" "(" exp ")" stmt                         "else" stmt
                          ↳ 2: "if" "(" exp ")" stmt •

这在某种程度上是野牛手册here中表示的移位/减少。但是在这个语法之后我没有“then”。该手册说,这个问题可以通过定义左右关联性和优先级来解决。在上面,我为“else”定义了右关联性,但它对这种转变减少问题没有影响。
我不想通过移位/减少计数来抑制警告,因为它太危险了,因为我的语法太大了。
我能做些什么 ?

4

1 回答 1

1

在你的反例中,你可以看到 bison 不知道它是否应该移动或减少你 first 之后的"if" "(" exp ")"那个。换句话说,如果它应该将您的第一个 if 与 else 分组:stmt")"

if(exp) (if(exp) stmt) else stmt

或第二个 if 与 else:

if(exp) (if(exp) stmt else stmt)

为了解决这个问题,例如,您还可以为 if 的最后一个终端符号提供优先级,例如%right "else" ")".
或者,您也可以修改语法以具有语句终止符,例如:

stmt: "foo"
   | "if" "(" exp ")" stmt ";"
   | "if" "(" exp ")" stmt "else" stmt ";"
于 2022-02-05T13:45:54.530 回答