0

尝试编译语法时出现 2 个 shift/reduce 错误:

program : declaration_list ;
declaration_list : declaration_list declaration | declaration ;
declaration : var_declaration | fun_declaration ; 

var_declaration: type_specifier var_decl_list ;
scoped_var_declaration: scoped_type_specifier var_decl_list;
var_decl_list : var_decl_list "," var_decl_initialize | var_decl_initialize ;
var_decl_initialize : var_decl_id ;
var_decl_id : ID | ID "[" INT_NUM "]" ;
scoped_type_specifier : type_specifier;
type_specifier: INT | CHAR ;
fun_declaration: type_specifier ID "(" params ")" statement | ID "(" params ")" statement ;
params : | param_list ;
param_list: param_list ";" param_type_list | param_type_list ;
param_type_list : type_specifier param_id_list ; 
param_id_list : param_id_list "," param_id | param_id ; 
param_id : ID | ID "[" "]" ;


statement: expression_stmt | compound_stmt | selection_stmt | iteration_stmt | return_stmt | break_stmt ;

compound_stmt : "{" local_declaration statement_list "}" ;
local_declaration : | local_declaration scoped_var_declaration ;
statement_list : | statement_list statement ;
expression_stmt : expression ";" | ";" ;
selection_stmt : "if" "(" simple_expression ")" statement | "if" "(" simple_expression ")" statement "else" statement ;
iteration_stmt: "while" "(" simple_expression ")" statement ;
return_stmt : "return" ";" | "return" expression ;
break_stmt : "break" ;


expression : mutable ASSIGN expression | mutable EINC expression | mutable EDEC expression | mutable INC | mutable DEC | simple_expression ;

simple_expression: simple_expression OR and_expression | and_expression ; 

and_expression: and_expression AND unary_rel_expression | unary_rel_expression ;

unary_rel_expression: "!" unary_rel_expression | rel_expression ;

rel_expression : sum_expression relop sum_expression | sum_expression ;

relop: "<" | ">" | LE | GE | COMP_OP | NE ;

sum_expression : sum_expression sumop term | term ; 

sumop : ADD | SUB ;

term: term mulop unary_expression | unary_expression ;

mulop: MULT | DIV | REM ;

unary_expression : unaryop unary_expression | factor ;

unaryop : "-" | "*" ;

factor : immutable | mutable ;

mutable : ID | ID "[" expression "]" ;

immutable : "(" expression ")" | call | constant ; 

call: ID "(" args ")" ;

args:  | arg_list;

arg_list : arg_list","expression | expression ;

constant : INT_NUM | STRINGCONST | CHARCONST | 'true' | 'false' ;

我得到 2 班次/减少

状态 38 冲突:1 次移位/减少 状态 139 冲突:1 次移位/减少

具体状态是:

state 38

   81 mutable: ID .  [$end, ADD, SUB, DIV, MULT, COMP_OP, INT, CHAR, CHARCONST, STRINGCONST, GE, LE, NE, EINC, EDEC, INC, DEC, AND, OR, REM, ASSIGN, INT_NUM, ID, ",", "]", "(", ")", ";", "{", "}", "if", "else", "while", "return", "break", "!", "<", ">", "-", "*", 't', 'f']
   82        | ID . "[" expression "]"
   86 call: ID . "(" args ")"

    "["  shift, and go to state 77
    "("  shift, and go to state 78

    "("       [reduce using rule 81 (mutable)]
    $default  reduce using rule 81 (mutable)




state 139

   40 selection_stmt: "if" "(" simple_expression ")" statement .  [$end, INT, CHAR, CHARCONST, STRINGCONST, INT_NUM, ID, "(", ";", "{", "}", "if", "else", "while", "return", "break", "!", "-", "*", 't', 'f']
   41               | "if" "(" simple_expression ")" statement . "else" statement

    "else"  shift, and go to state 141

    "else"    [reduce using rule 40 (selection_stmt)]
    $default  reduce using rule 40 (selection_stmt)

有人可以解释一下如何解决这个错误,我知道它与优先级有关。

4

2 回答 2

4

状态 38 中的 shift-reduce 冲突是以下产生式的结果:

return_stmt : "return" ";"
            | "return" expression
            ;

请注意,此产生式允许语句以表达式结尾。除了这个产生式之外,语句必须以;or结尾}。如果语句可以以表达式结尾,那么语法就会变得模棱两可。例如,考虑:

return a
(1+1);

它可以是一个 return_stmt(返回 的值a),后跟一个 expression_stmt,也可以是一个 return_stmt,返回函数调用的值a(1+1)

很可能,这只是您的语法中的一个错字,您打算:

 return_stmt : "return" ";"
            | "return" expression ";"
            ;

(但请参阅下面关于引号的注释。)


状态 139 处的 shift-reduce 冲突是经典的 C 风格if冲突,这是语言中歧义的结果:

if (c1) if(c2) s1; else s2;

适用于哪个ifelse当然,我们都希望它是 inner if,这是唯一明智的答案(因为当我们查看 时,else我们不知道是否有另一个else后续),但语法本身也允许。

bison如您所见,在这种情况下会做正确的事情。(它选择移位else,这意味着它不会在if没有 的情况下减少内部else。)因此,最简单的可能解决方案是忽略这种特殊的移位减少冲突。(参见%expect指令。)

如果这对您没有吸引力,您有两种选择:一种是使用优先级声明来明确赋予移位优先级,另一种是在语法中更加明确,以便强制进行正确的解析。这两种可能性都在这个问题的两个答案中得到了很好的探索,具有非常相似的语法。(要查看优先解决方案,您必须点击 Akim 答案中的链接。)


如果您正在使用bison,您应该知道"word"并且'x'是完全不同的语法。第一个使用已被赋予人类可读名称的令牌,通常使用如下声明:

%token TOKEN_RETURN "return"

您需要扫描仪的全大写枚举名称,以便您可以编写(假设您的扫描仪是用 flex 编写的):

"return" { return TOKEN_RETURN; }

但是使用带引号的字符串语法更具可读性。(例如,EINC你的语言是什么意思?我不知道......)

如果你不为令牌声明枚举名称,bison 不会抱怨,它仍然会为令牌分配一个代号,但你要弄清楚代号是什么要困难得多。

另一方面,'('表示单个字符标记,其代码号是字符的 ascii 代码。(因此它对应(于 C 中的用法。)在这种情况下,代码号是已知的,您可以在 flex 中编写:

"(" { return '('; }

尽管您最好使用后备规则执行此操作:

 . { return yytext[0]; }

简而言之,您可能想要更改所有用法,例如";"to ';',并且还将'true'and更改'false'"true"and "false"。并且您可能还希望将一些其他关键字标记(如“LE”和“INC”)替换为"<="and ,但还需要为所有双引号标记"++"添加适当的声明。%token

于 2015-03-16T21:22:54.587 回答
-2

#include <gerald.h>在顶部添加

于 2015-03-16T20:29:55.090 回答