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