【问题标题】:Bison Shift/Reduce conflicts for small language parser小型语言解析器的 Bison Shift/Reduce 冲突
【发布时间】:2013-03-12 18:21:12
【问题描述】:

我的目标是为一种小语言创建解析器。它目前给我一个班次/减少错误。

我的 CFG 在某处模棱两可,但我不知道在哪里

prog:    PROGRAM beg                   {$$ = "program" $2;}
    |   PROGRAM stmt beg               {$$ = "program" $2 $3;}

beg:    BEG stmt END                   {$$ = "begin" $2 "end";}
    | BEG END                      {$$ = "begin" "end";}


stmt:   beg             {$$ = $1;}
    | if_stmt                   {$$ = $1;}/*
    | IF expr THEN stmt                 {$$ = $1 $2 $3 $4;}*/
    | WHILE expr beg                    {$$ = "while" $2 $3;}
    | VAR COLEQUALS arithexpr SEMI      {$$ = $1 ":=" $3 ";";}
    | VAR COLON INTEGER SEMI            {$$ = $1 ":" "integer" ";";} /*Declaring an integer */
    | VAR COLON REAL SEMI               {$$ $1 ":" "real" ";";}   /*declaring a real */

if_stmt:  IF expr THEN stmt            {$$ = "if" $2 "then" $4;}
    | IF expr THEN stmt ELSE stmt      {$$ = "if" $2 "then" $4 "else" $6;}

expr:   NOT VAR                        {$$ = "!" $2;}
| VAR GREATERTHAN arithexpr        {$$ = $1 ">" $3;}
    | VAR LESSTHAN arithexpr           {$$ = $1 "<" $3;}
    | VAR GREATERTHANEQUALTO arithexpr {$$ = $1 ">=" $3;}
    | VAR LESSTHANEQUALTO arithexpr    {$$ = $1 "<=" $3;}
    | VAR EQUALS arithexpr             {$$ = $1 "==" $3;}
    | VAR NOTEQUALS arithexpr          {$$ = $1 "!=" $3;}
    | arithexpr AND arithexpr          {$$ = $1 "&&" $3;}
    | arithexpr OR arithexpr           {$$ = $1 "||" $3;}


arithexpr:  arithexpr PLUS term            {$$ = $1 + $3;}
    |  arithexpr MINUS term            {$$ = $1 - $3;}
    |   term                   {$$ = $1;}

term:   term TIMES factor          {$$ = $1 * $3;}
    | term DIVIDE factor           {$$ = $1 / $3;}
    | factor               {$$ = $1;}

factor:   VAL                              {$$ = $1;}

【问题讨论】:

  • Bison 没有在错误消息中为您提供任何关于冲突位置的线索吗?
  • 它只告诉你有多少冲突,而不是它们在哪里。另一方面,错误是给你的
  • 使用-v 选项获取.output 文件,显示冲突的位置和内容...

标签: parsing grammar bison yacc shift-reduce-conflict


【解决方案1】:

“错误”来自if_stmt 的else 部分中的歧义:stmt 可以是 if_stmt,如果 else-part 属于哪个则不清楚,例如如果你写:

if y1 then if y2 then x=1 else x=2

那么 else 部分可以属于第一个 if 或第二个 if。

这个问题被问过很多次了,直接搜索if then else shift reduce

对于诊断(发现您也是 if then else shift reduce 问题的受害者),您可以告诉 bison 生成一个输出文件

bison -r all  myparser.y

这将生成一个文件 myparser.output,您可以在其中找到适合您的情况:

State 50 conflicts: 1 shift/reduce
....
state 50

   11 if_stmt: IF expr THEN stmt .  [ELSE, BEG, END]
   12        | IF expr THEN stmt . ELSE stmt

    ELSE  shift, and go to state 60

    ELSE      [reduce using rule 11 (if_stmt)]
    $default  reduce using rule 11 (if_stmt)


state 51
...

对此的一种解决方案是引入一个块语句,并且只在 if 和 else 部分中使用这些语句:

stmt: ...
    | blk_stmt
blk_stmt: BEGIN stmt END
if_stmt:  IF expr THEN blk_stmt
    | IF expr THEN blk_stmt ELSE blk_stmt

这对于修改后的 c 语言意味着只有

if x1 then {if x2 then {y=1}} else {y=2}

可能({ 代表 BEGIN 令牌,} 代表 END 令牌)从而解决歧义。

【讨论】:

  • 非常感谢,这真的很有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多