yacc Shift /减少冲突

时间:2014-11-04 09:04:14

标签: bison yacc

对于以下语法,我遇到了SR错误。

这是我的语法

program : CLASS Program '{' field_decl '}'
        ;    
field_decl : type field_part ';'
           | field_part field_fact
           | meth_decl
           |
           ;    
field_fact : ',' field_decl
           | field_part
           ;    
field_part  : IDENTIFIER field_part2
            ;    
field_part2 :
            | '[' int_literal ']' field_decl
            ;    
meth_decl   : type meth_decl1
            | VOID meth_decl1
            ;    
meth_decl1  : IDENTIFIER '(' meth_part ')' block 
            ;    
meth_part   : type meth_part1
            |
            ;    
meth_part1  : IDENTIFIER meth_part2
            ;                
meth_part2  :
            | ',' meth_part
            ;    
block       : '{' block_list '}'
            ;    
type        : INT
            | BOOLEAN
            ;    
block_list  : var_decl
            |
            ;    
var_decl    : type ids ';'
            | statement
            ;    
ids         : IDENTIFIER ids_part
            ;    
ids_part    :
            | ',' ids
            ;    
statement   : location ASSIGNMENT_OPERATOR expr ';'
            | method_call ';'
            | IF '(' expr ')' block ELSE block 
            | IF '(' expr ')' block
            | FOR IDENTIFIER '=' expr ',' expr block
            | RETURN expr ';'
            | RETURN ';'
            | BREAK ';'
            | CONTINUE ';'
            | block
            ;    
location    : IDENTIFIER loc_part
            ;               
loc_part    : 
            | '[' expr ']'
            ;    
method_call : IDENTIFIER '(' ')'
            | IDENTIFIER '(' expr_block ')'
            | CALLOUT '(' STRING_LITERAL ')'
            | CALLOUT '(' STRING_LITERAL ',' callout_arg_block ')'
            ;    
callout_arg_block : callout_arg
                  | callout_arg ',' callout_arg_block
                  ;    
callout_arg : expr
            | STRING_LITERAL
            ;    
expr        : location
            | method_call
            | literal
            | expr bin_op expr
            | MINUS expr
            | '!' expr
            | '(' expr ')'
            ;    
expr_block  : expr expr_fact
            ;    
expr_fact   : 
            |  ',' expr_block
            ;
bin_op      : ARITHEMATIC_OPERATOR
            | EQUALS_OPERATOR
            | RELATIONAL_OPERATOR
            | CONDITIONAL_OPERATOR
            ;
literal     : int_literal
            | bool_literal
            ;
int_literal : DIGIT
            | HEXADECIMAL_VALUE
            ;
bool_literal    : TRUE
                | FALSE
                ;

和输出野牛节目是

州19冲突:1班/减少

状态33冲突:1班/减少

状态87冲突:4班/减少

状态107冲突:4班/减少

如何重写语法以消除这些冲突

1 个答案:

答案 0 :(得分:1)

我实际上并没有编译语法来检查,所以以下内容可能并不详尽。

基本上,您有两种经典的转换/减少冲突:

  1. 你的表达语法含糊不清:

    expr: expr bin_op expr
    

    语法不允许解析器决定哪个bin_op在任何给定表达式中具有优先权,因此它允许(例如)3 + 4 * 5被解析为expr(3 + 4) bin_op(*) expr(5)或者expr(3) bin_op(+) expr(4 * 5)。这个问题的通常解决方案是使用优先级声明,但这些解决方案与将所有二元运算符聚合成单个生成不兼容。

    请参阅Yacc/Bison, minimize amount by grouping math ops并阅读bison manual section on precedence

  2. 您的if陈述含糊不清。例如,在

    if ( <expr> ) if ( <expr> ) <block> else <block>
    

    语法没有指定if应用else

    在这种特定情况下,默认的野牛规则(有利于转换为减少)将做正确的事情(通过将else与最里面的if相关联),但它仍会报告转移/减少冲突。

    请参阅野牛手册中的示例(在之前关联的部分中)或查看Removing shift/reduce conflict on optional else blockReforming the grammar to remove shift reduce conflict in if-then-else