【问题标题】:Why does this yacc code generate shift/reduce conflicts为什么这个 yacc 代码会产生移位/减少冲突
【发布时间】:2020-01-26 22:53:23
【问题描述】:

不知道为什么下面的代码会产生移位/减少冲突

primary_no_literal_expression
    : IDENTIFIER 
    {
        $$ = mioc_create_identifier_expression($1);
    }
    | IDENTIFIER LC RC      // shift/reduce conflicts
    {

    }
    | function_no_argument_call_expression
    | function_with_argument_call_expression
    | primary_no_literal_expression slice_index_expression
    | primary_no_literal_expression DOT IDENTIFIER
    | primary_no_literal_expression DOT IDENTIFIER LP RP
    | primary_no_literal_expression DOT function_with_argument_call_expression
    ;

显示状态 53 冲突:1 班次/减少

y.output 处于状态 53

state 53

   95 primary_no_literal_expression: IDENTIFIER .
   96                              | IDENTIFIER . LC RC
  103 function_no_argument_call_expression: IDENTIFIER . LP RP
  107 function_with_argument_list: IDENTIFIER . LP argument_list RP

    LP  shift, and go to state 105
    LC  shift, and go to state 106

    LC        [reduce using rule 95 (primary_no_literal_expression)]
    $default  reduce using rule 95 (primary_no_literal_expression)
state 106

   96 primary_no_literal_expression: IDENTIFIER LC . RC

    RC  shift, and go to state 159
...
state 159

   96 primary_no_literal_expression: IDENTIFIER LC RC .

    $default  reduce using rule 96 (primary_no_literal_expression)

规则 95

   95 primary_no_literal_expression: IDENTIFIER
   96                              | IDENTIFIER LC RC
   97                              | function_no_argument_call_expression
   98                              | function_with_argument_call_expression
   99                              | primary_no_literal_expression slice_index_expression
  100                              | primary_no_literal_expression DOT IDENTIFIER
  101                              | primary_no_literal_expression DOT IDENTIFIER LP RP
  102                              | primary_no_literal_expression DOT function_with_argument_call_expression

LC [减少使用规则 95 (primary_no_literal_expression)] primary_no_literal_expression 规则是“IDENTIFIER LC RC”(规则 95)为什么只读取 LC 来减少?

完整代码

y.output https://controlc.com/56d66aea/fullscreen.php?hash=4f3bc1c214e1f3347b3a64df69a9b519&toolbar=true&linenum=false

test.y https://controlc.com/04d49e1b/fullscreen.php?hash=6dde9e69b9ea5873ff6ac234474a5927&toolbar=true&linenum=false

【问题讨论】:

  • 你确定primary_expression_list assignment_operator right_expression 吗?虽然我听说 yacc 已经十年了,但我认为您的冲突是因为解析器无法判断 a, b = 1 应该是 (a), (b=1) 还是 (a, b) = 1。而且我不知道您正在构建的语言,但多重分配 (a=1, b=2) 不是您在这里所做的。
  • 是的,我需要 primary_expression_list assignment_operator right_expression,但我对 primary_expression assignment_operator right_expression 的修改并没有消除 状态 53 冲突:1 班次/减少
  • 删除primary_expression|primary_no_literal_expression| DOT primary_no_literal_expression可以消除primary_no_literal_expression| IDENTIFIER LC RC冲突不知道问题出在哪里?

标签: yacc


【解决方案1】:

移位/减少冲突的出现是因为在某些上下文中使用了primary_no_literal_expression(在某些规则的右侧),它后面可以跟一个LC 标记。这意味着在看到IDENTIFIER 标记后,当下一个标记(前瞻)是LC 时,解析器不知道它是否应该将LC 转换为(最终匹配primary_no_literal_expression: IDENTIFIER LC RC 规则)或减少@ 987654327@ 规则(匹配允许LCprimary_no_literal_expression 之后的任何内容

您需要找到该规则并弄清楚如何处理它 - 要么摆脱其中一个规则(如果事情不明确),要么弄清楚如何知道要匹配哪个规则(基于额外的前瞻和/或词法分析器反馈,或其他)

在您的情况下,罪魁祸首(至少是其中一个)可能是规则 if_statement: IF logical_or_expression block,因为 logical_or_expression 可以扩展为(或结尾)primary_no_literal_expression,而 block 可以以LC。所以冲突告诉你解析器无法判断像这样的表达式在哪里结束,而块开始。

【讨论】:

  • 非常感谢,正如你所说,我找到了原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多