对于以下语法,我遇到了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班/减少
如何重写语法以消除这些冲突
答案 0 :(得分: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。
您的if
陈述含糊不清。例如,在
if ( <expr> ) if ( <expr> ) <block> else <block>
语法没有指定if
应用else
。
在这种特定情况下,默认的野牛规则(有利于转换为减少)将做正确的事情(通过将else
与最里面的if
相关联),但它仍会报告转移/减少冲突。
请参阅野牛手册中的示例(在之前关联的部分中)或查看Removing shift/reduce conflict on optional else block和Reforming the grammar to remove shift reduce conflict in if-then-else