Bison 野牛减少/减少,转移/减少冲突

Bison 野牛减少/减少,转移/减少冲突,bison,Bison,嘿,伙计们,我遇到了一些野牛代码的问题。。。编译完这段代码后,我得到58个shift/reduce和40个reduce/reduce冲突。。。有没有关于如何约束它们的提示,或者给我一个关于如何约束它们的好指南?提前谢谢!!(以T_开头的所有内容,如T_get,都是此代码上面定义的标记) 即使您没有时间研究代码中的逻辑,我也希望您能在这些冲突中提供一般性的帮助,例如它们是如何生成的等等。请使用bison的-v选项获得详细的输出,给出生成的解析器中的所有状态和冲突。如果您这样做,您将看到一种类似以下

嘿,伙计们,我遇到了一些野牛代码的问题。。。编译完这段代码后,我得到58个shift/reduce和40个reduce/reduce冲突。。。有没有关于如何约束它们的提示,或者给我一个关于如何约束它们的好指南?提前谢谢!!(以T_开头的所有内容,如T_get,都是此代码上面定义的标记)


即使您没有时间研究代码中的逻辑,我也希望您能在这些冲突中提供一般性的帮助,例如它们是如何生成的等等。请使用bison的
-v
选项获得详细的输出,给出生成的解析器中的所有状态和冲突。如果您这样做,您将看到一种类似以下情况的状态:

state 7

    4 G: url . canon

    T_acc      shift, and go to state 12
        :
    T_trans    shift, and go to state 19
    T_user     shift, and go to state 20

    $end       reduce using rule 13 (GH)
    $end       [reduce using rule 21 (RH)]
    $end       [reduce using rule 24 (EH)]
    $end       [reduce using rule 26 (MB)]
    T_acc      [reduce using rule 13 (GH)]
         :
这告诉你,当解析器看到一个
url
并且想要识别一个
canon
时,它不知道该怎么做——它应该识别一个空的
GH
RH
EH
,或者
MB
,还是应该移动一个标记来识别其中的一个非空的

这些冲突都源于语法中的基本歧义——你有一个
canon
规则,其中包含0个或更多重复的
GH
RH
、和/或
EH
,而这些规则中的每一个都包含0个或更多重复的内容。因此,它无法判断要插入到解析树中的空内容有多少(因为它们不消耗输入,可以添加任意数量),也不知道是将类似的内容分组到单个
GH
(或
RH
EH
)还是多个不同的内容中

所以要解决这个问题,你需要决定你想要什么。最可能的情况是,您不关心
GH
/
RH
/
EH
结构的分组,也不关心空结构,因此您应该摆脱这些规则的递归:

GH:T_con T_akt T_seq|T_date T_akt D|T_trans T;
RH:T_acc T_akt T_seq|T_ref T_akt T_seq|T_user T_akt T_seq;
EH:T_content T_akt T_seq|T_exp T_akt T_seq;
现在,这些规则中的每一个都将匹配一个构造,如果有多个,它们将按照
canon
规则分组在一起。这修复了所有的冲突,但仍然留下了一个潜在的问题——您的
canon
规则是右递归的,因此将在减少任何规则之前将整个输入吸到堆栈上(因为对于右递归,它从右向左减少)。您可能希望将规则改为左递归——bison中的一般规则是始终使用左递归而不是右递归,除非出于某种原因需要右递归。这将为您提供语法:

start : T_get G | T_head G | T_post G ;
G : url canon MB ;
url : T_http T_dslash T_host T_abs_path ;
canon : canon GH | canon RH | canon EH | ;
GH : T_con T_akt T_seq | T_date T_akt D | T_trans T ;
D : T_day T_slash T_month T_slash T_year T_hour T_akt T_min ;
T : T_chunked | T_gzip  | T_deflate ;
RH : T_acc T_akt T_seq | T_ref T_akt T_seq | T_user T_akt T_seq ;
EH : T_content T_akt T_seq | T_exp T_akt T_seq ;
MB : T_seq | ;

使用bison的
-v
选项获得详细的输出,给出生成的解析器中的所有状态和冲突。如果您这样做,您将看到一种类似以下情况的状态:

state 7

    4 G: url . canon

    T_acc      shift, and go to state 12
        :
    T_trans    shift, and go to state 19
    T_user     shift, and go to state 20

    $end       reduce using rule 13 (GH)
    $end       [reduce using rule 21 (RH)]
    $end       [reduce using rule 24 (EH)]
    $end       [reduce using rule 26 (MB)]
    T_acc      [reduce using rule 13 (GH)]
         :
这告诉你,当解析器看到一个
url
并且想要识别一个
canon
时,它不知道该怎么做——它应该识别一个空的
GH
RH
EH
,或者
MB
,还是应该移动一个标记来识别其中的一个非空的

这些冲突都源于语法中的基本歧义——你有一个
canon
规则,其中包含0个或更多重复的
GH
RH
、和/或
EH
,而这些规则中的每一个都包含0个或更多重复的内容。因此,它无法判断要插入到解析树中的空内容有多少(因为它们不消耗输入,可以添加任意数量),也不知道是将类似的内容分组到单个
GH
(或
RH
EH
)还是多个不同的内容中

所以要解决这个问题,你需要决定你想要什么。最可能的情况是,您不关心
GH
/
RH
/
EH
结构的分组,也不关心空结构,因此您应该摆脱这些规则的递归:

GH:T_con T_akt T_seq|T_date T_akt D|T_trans T;
RH:T_acc T_akt T_seq|T_ref T_akt T_seq|T_user T_akt T_seq;
EH:T_content T_akt T_seq|T_exp T_akt T_seq;
现在,这些规则中的每一个都将匹配一个构造,如果有多个,它们将按照
canon
规则分组在一起。这修复了所有的冲突,但仍然留下了一个潜在的问题——您的
canon
规则是右递归的,因此将在减少任何规则之前将整个输入吸到堆栈上(因为对于右递归,它从右向左减少)。您可能希望将规则改为左递归——bison中的一般规则是始终使用左递归而不是右递归,除非出于某种原因需要右递归。这将为您提供语法:

start : T_get G | T_head G | T_post G ;
G : url canon MB ;
url : T_http T_dslash T_host T_abs_path ;
canon : canon GH | canon RH | canon EH | ;
GH : T_con T_akt T_seq | T_date T_akt D | T_trans T ;
D : T_day T_slash T_month T_slash T_year T_hour T_akt T_min ;
T : T_chunked | T_gzip  | T_deflate ;
RH : T_acc T_akt T_seq | T_ref T_akt T_seq | T_user T_akt T_seq ;
EH : T_content T_akt T_seq | T_exp T_akt T_seq ;
MB : T_seq | ;