【问题标题】:Using precedence in Bison for unary minus doesn't solve shift/reduce conflict在 Bison 中使用优先级作为一元减号并不能解决移位/减少冲突
【发布时间】:2012-05-27 07:57:48
【问题描述】:

我正在设计一个非常简单的语法,我使用一元减号操作数。但是,我遇到了转变/减少冲突。在 Bison 手册以及我查看的其他任何地方,它都说我应该定义一个新标记并赋予它比二进制减操作数更高的优先级,然后在规则中使用“%prec TOKEN”。

我已经这样做了,但我仍然收到警告。为什么?

我正在使用野牛 (GNU Bison) 2.4.1。语法如下图:

%{
#include <string>
extern "C" int yylex(void);
%}

%union {
    std::string token;
}

%token <token> T_IDENTIFIER T_NUMBER
%token T_EQUAL T_LPAREN T_RPAREN

%right T_EQUAL
%left T_PLUS T_MINUS
%left T_MUL T_DIV
%left UNARY

%start program

%%

program : statements expr
;

statements : '\n'
           | statements line
;

line : assignment
     | expr
;

assignment : T_IDENTIFIER T_EQUAL expr
;

expr : T_NUMBER
     | T_IDENTIFIER
     | expr T_PLUS expr
     | expr T_MINUS expr
     | expr T_MUL expr
     | expr T_DIV expr
     | T_MINUS expr   %prec UNARY
     | T_LPAREN expr T_RPAREN
;

【问题讨论】:

    标签: grammar bison unary-operator shift-reduce-conflict


    【解决方案1】:

    %prec 并没有你希望的那么多。它告诉 Bison,在您拥有 - a * b 的情况下,您希望将其解析为 (- a) * b 而不是 - (a * b)。换句话说,在这里它将更喜欢UNARY 规则而不是T_MUL 规则。无论哪种情况,您都可以确定UNARY 规则最终会得到应用,而这只是输入减少为一元参数的顺序问题。

    在你的语法中,情况大不相同。任何line 非终结符序列都将组成一个sequence,没有什么可以说line 非终结符必须在行尾结束。事实上,任何表达式都可以是line。所以这里基本上有两种解析a - b的方法:或者作为带有二进制减号的单行,或者作为两个“行”,第二种以一元减号开头。没有什么可以决定哪些规则将适用,因此基于规则的优先级在这里还行不通。

    您的解决方案是通过要求每个 line 实际上以行尾符号结尾或后跟一个行尾符号来纠正您的行拆分。

    如果你真的想要你的语法关于行尾的行为,你需要两个单独的非终结符来表示可以和不能以T_MINUS 开头的表达式。您必须将其传播到树上:第一个 line 可能以一元减号开头,但后续的不能。在括号内,再以减号开头就可以了。

    【讨论】:

    • 我忘记了这个问题,因为一旦我添加了动作,它就会自行“修复”。虽然它不应该重要,但它现在起作用了,我不再关心它了。然而,回顾我的语法,我意识到我一定是提交了一个过时的版本或什么,因为一行应该以分号结尾。我相信我一定是在添加动作时添加了这些,从而解决了冲突。感谢您指出这一点。
    【解决方案2】:

    expr 规则没问题(没有 %prec UNARY)。您的移位/减少冲突来自规则:

    statements : '\n'
               | statements line
    ;
    

    规则不是你想的那样。例如你可以写:

    a + b c + d
    

    我认为这不应该是有效的输入。

    但程序规则也不是很理智:

    program : statements expr
    ;
    

    规则应该是这样的:

    program: lines;
    
    lines: line | lines line;
    
    line: statement "\n" | "\n";
    
    statement: assignment | expr;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多