Bison解析器无法识别替代语法

时间:2015-07-06 08:31:10

标签: grammar bison yacc

我正在尝试编写一个识别特定语法的解析器。我很远,大多数东西都有效。我遇到了Bison解析器的一个问题,但试图让它识别两个相似但不同的结构。 以下是我希望它识别的两种结构:

type_1 IS ENUMERATION OF 
BEGIN
    element_1,
    element_2 := 4
END type_1;

type_2 IS ENUMERATION SIZE 8 OF 
BEGIN
    element_1,
    element_2 := 4
END type_2;

基本上这是针对类似枚举的声明,可以在有或没有元素的bitsize参数的情况下给出。

我写的Bison文件包含两个版本的两个替代品。它们中的每一个都是独立的,或者当它们在另一个之前分开时,它们运作良好。但是,当我将两个描述放入Y文件时,它只识别我的一个声明或另一个。

以下是野牛代码:

    enum_type : sized_enum_type                 { $$=$1; P3; }
          | nonsized_enum_type              { $$=$1; P3; }
          ;

sized_enum_type : identifier[L]             {P1(37,$L->Get_Line(),$L->Get_Column());} 
                IS[I]                       {P2(38,$I.ln,$I.clmn);} 
                ENUMERATION[N]              {P2(43,$N.ln,$N.clmn);} 
                SIZE[Z]                     {P2(42,$Z.ln,$Z.clmn);} 
                INTEGER_VALUE[V]            {P2(39,$V.ln,$V.clmn);} 
                OF[O]                       {P2(40,$O.ln,$O.clmn);} 
                TBEGIN[B]                   {P2(16,$B.ln,$B.clmn);} 
                enum_element_list[S]        {P2(41,$S->Get_Line(),$S->Get_Column());} 
                TEND[E]                     {P2(16,$E.ln,$E.clmn);} 
                identifier[R]               {P2(15,$R->Get_Line(),$R->Get_Column());}
                SEMICOLON                   {$$= new AST::AST_Type_Enum( (AST::AST_Code_Identifier *) $L, $V.value ); $$->_Set_Line_And_Column(  $I.ln, $I.clmn); P3;}
                ;

nonsized_enum_type : identifier[L]              {P1(37,$L->Get_Line(),$L->Get_Column());} 
                     IS[I]                       {P2(38,$I.ln,$I.clmn);} 
                     ENUMERATION[N]              {P2(39,$N.ln,$N.clmn);} 
                     OF[O]                       {P2(40,$O.ln,$O.clmn);} 
                     TBEGIN[B]                   {P2(16,$B.ln,$B.clmn);} 
                     enum_element_list[S]        {P2(41,$S->Get_Line(),$S->Get_Column());} 
                     TEND[E]                        {P2(16,$E.ln,$E.clmn);} 
                     identifier[R]              {P2(15,$R->Get_Line(),$R->Get_Column());}

                     SEMICOLON                  {$$= new AST::AST_Type_Enum( (AST::AST_Code_Identifier *) $L, -1 ); $$->_Set_Line_And_Column(  $I.ln, $I.clmn); P3;}
                     ;
enum_element_list   : one_enum                                                          { $$=$1; }
                   | one_enum COMMA enum_element_list                                   { ((AST::AST_Enum_Value *)$1)->Append( (AST::AST_Enum_Value *) $3); $$=$1; }
                   ;

one_enum    : identifier[L]                 {$$= new AST::AST_Enum_Value( (AST::AST_Code_Identifier *) $L, -1 ); $$->_Set_Line_And_Column( $L->Get_Line(),$L->Get_Column()); P3;}
           | identifier[L]                  {P1(17,$L->Get_Line(),$L->Get_Column());} 
             ASSIGNMENT_SHALLOW_COPY[A]    {P2(42,$A.ln, $A.clmn);} 
             INTEGER_VALUE[I]               {$$= new AST::AST_Enum_Value( (AST::AST_Code_Identifier *) $L, $I.value ); $$->_Set_Line_And_Column( $L->Get_Line(),$L->Get_Column()); P3;}
             ;

我不认为每个规则部分右侧的C语句是必要的,但我仍然将它们包括在内。

当我在源代码上运行编译的解析器时,它抱怨它期望令牌SIZE。当我交换nonsized_enum_type和sized_enum_type的规则(不是enum_type规则的右边,规则的完整源代码顺序,将一个规则移到另一个规则之下),然后它识别没有大小的另一个形式。当我在我的代码中包含SIZE 8部分时,它会抱怨它期待另一种形式(OF expected)。

所以我的问题是:如何编写一个解析两个部分的解析器规则?

生成的代码不应该识别出一条规则无处可去,然后尝试另一条规则吗?似乎第二条规则从未尝试过。

谢谢大家

1 个答案:

答案 0 :(得分:1)

将所有这些中规则操作(MRA)插入到语法中会削弱解析器。由于您未包含P1P2的定义,因此很难知道您为何需要MRA,但实际上不太可能需要执行特定的减少操作在令牌ISENUMERATION之间,而不是稍后执行缩减操作。

具体地,问题可以减少到以下。考虑两个产品(仅限于他们的第一个MRA):

sized_enum_type : identifier[L]     {P1(37,$L->Get_Line(),$L->Get_Column());} 
nonsized_enum_type : identifier[L]  {P1(37,$L->Get_Line(),$L->Get_Column());}

每个MRA都使用标签生成实现。从左到右解析的逻辑是在移位下一个令牌之前必须执行所有缩减。在上述两种情况下,下一个令牌都是IS,但看到IS并未说明应执行哪个缩减。因此,野牛将报告减少/减少冲突,然后选择定义文件中首先出现的生产。另一个减少将被有效地消除,这使得其余的生产无法实现。

两种减少行动恰好相同,但野牛不知道。从野牛的角度来看,所有的MRA都是独一无二的。实际上,MRA的使用要求语法 - 至少在该特定点 - 是LL(1),从而消除了LR(1)解析算法的所有优点。

你可以通过左因素来避免这个问题,但我强烈建议你尽量减少对MRAs的依赖。对于构建AST,MRA几乎不需要,并且它们具有非平凡的成本以及降低解析器处理非LL(1)语法的能力。