【问题标题】:bison shift/reduce conflict with the same token appear in the same rule相同token的bison shift/reduce冲突出现在相同的规则中
【发布时间】:2016-03-25 12:17:30
【问题描述】:

鉴于以下野牛规则,我不明白为什么 INTO 令牌可以在相同的野牛状态下移动和归约并导致 1 移动/归约冲突。如何解决?大写字母都是代币。

select_condition: SELECT opt_select fields
                  FROM from_clause
                  opt_into_table
                  opt_into_graph
                  opt_where_expr

opt_into_table: { $$ = 0; }
              | INTO TABLE IDENTIFIER { $$ = 1; }

opt_into_graph: { $$ = 0; }
              | INTO GRAPH IDENTIFIER { $$ = 1; }

////// from the sqlparser.output //////////////////

INTO  shift, and go to state 66

INTO      [reduce using rule 31 (opt_into_table)]
$default  reduce using rule 31 (opt_into_table)

opt_into_table  go to state 67

【问题讨论】:

  • 我将第二个 INTO 替换为 'into' 并且它有效。还有其他更好的方法吗?

标签: bison reduce shift


【解决方案1】:

这里的冲突是当解析器看到标记INTO跟在from_clause之后,有两种可能:

  • 它是序列INTO TABLE IDENTIFIER 中的第一个标记。在这种情况下,它应该被移动(在减少from_clause之后)。

  • 它是序列INTO GRAPH IDENTIFIER 中的第一个标记。在这种情况下,一个空的opt_into_table 需要在移动INTO 之前减少。

因此存在移位/归约冲突,因为此时不知道是否需要归约一个空的opt_into_table 非终端。再加一个前瞻符号,答案就很清楚了,因此所写的语法是 LR(2)。不幸的是,bison 不生成 LR(2) 解析器。

在编写语义规则时(在两种情况下都忽略 IDENTIFIER 的语义值),您可以使用一个简单的实用修复:将两个可选短语组合成一个非终结符,从而创建一个位掩码两个独立的布尔值:

opt_intos: INTO TABLE IDENTIFIER { $$ = 1; }
         | INTO GRAPH IDENTIFIER { $$ = 2; }
         | INTO TABLE IDENTIFIER INTO GRAPH IDENTIFIER { $$ = 3; }

但这可能不是最好的解决方案,因为在某些时候您可能会关心IDENTIFIERs。

另一种(也有点丑陋)的可能性是删除 epsilon 产生式,通过将它们扩展为 select_condition 的四个不同产生式:

select_condition: SELECT opt_select fields
                  FROM from_clause
                  into_table
                  into_graph
                  opt_where_expr
                | SELECT opt_select fields
                  FROM from_clause
                  into_graph
                  opt_where_expr
                | SELECT opt_select fields
                  FROM from_clause
                  into_table
                  opt_where_expr
                | SELECT opt_select fields
                  FROM from_clause
                  opt_where_expr

into_table      : INTO TABLE IDENTIFIER { $$ = 1; }

into_graph      : INTO GRAPH IDENTIFIER { $$ = 1; }

另一种选择是将INTO TABLEINTO GRAPH 组合成词法分析器中的单个标记。 (对于类似 SQL 的语言,这通常可能不起作用,因为关键字是上下文相关的。但在你的情况下它可能是可行的。)

或者你可以保持语法不变,使用%glr-parser

【讨论】:

  • @user3658306:通过单击答案旁边的向上三角形进行投票。单击复选标记的轮廓接受它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多