解决Yacc / Bison语法中的移位/减少冲突

时间:2019-08-24 10:46:46

标签: bison yacc

我正在 GNU-Bison 中编写一个解析器,以解析捕获的专有协议数据位。解析器具有以下标记:

  • H .......标头
  • D .......数据
  • T .......终结者

和五个数字D,即数据令牌组成了 批量 B  即

B : DDDDD
  ;

理想情况下,输入形式应为

H DDDDD DDDDD DDDDD ... DDDDD T

aka

 H B B B ... B T

所以我写了以下语法:

%%
CAPTURE :  H PAYLOAD T     { printf("[OK]");}
        ;

PAYLOAD :  B
        |  PAYLOAD B
        ;

B       :  DDDDDD
%%        

现在,要满足一些实际条件,例如以下模式:

  1. DD H DDDDD DDDDD ... DDDDD T(前缀D开头)
  2. H DDDDD DDDDD ... DDD T(最后一个 批量 被截短,仅有3个数据D

我将语法修改为

%%
CAPTURE :  H PAYLOAD T     { printf("[OK]");}
        ;

PAYLOAD :  B
        |  PAYLOAD B
        |  D PAYLOAD
        |  PAYLOAD D
        ;

B       :  DDDDDD
%%        

但是它给出了shift/reduce conflict
需要帮助来纠正语法,以便它也可以识别上述两种情况,并且不会发生移位/减少冲突。

1 个答案:

答案 0 :(得分:1)

%%
CAPTURE : OPTD1 H PAYLOAD OPTD2 T     { printf("[OK]");}
        ;

PAYLOAD :  B
        |  PAYLOAD B
        ;

B       :  D D D D D
        ;

OPTD1   :
        |  OPTD1 D
        ;

OPTD2   :
        |  D D D
        ;
%%     

我在第一个产品的右侧添加了两个新的非终结符OPTD1OPTD2,并保持了PAYLOAD的原始规则。 OPTD1可以重写为0或多个D终端符号,OPTD2可以重写为0或3个D终端符号。

如果您的令牌,H,T和B分别只是字符“ H”,“ T”和“ B”,则可以使用以下正则表达式轻松识别有效输入:

'^D*H(DDDDD)+(DDD)?T$'

无论如何,您应该能够通过有限状态自动机识别有效输入,而无需使用YACC提供的下推自动机。