规则永远不会减少,理解为什么

时间:2015-05-26 00:51:59

标签: bison yacc

我正在学习与YACC合作,我真的无法理解一些错误。我想知道为什么当我尝试使用.y文件生成解析器时出现此错误。这是我的.y文件,它代表Pascal语言的无上下文语法:

%%


Program : program ident ';' declaration_opc compound_stmt '.'
    ;

declaration_opc : var declaration_list
    |
    ;

declaration_list : declaration ';' declaration_list 
     | declaration ';'
     ;

declaration : id_list ':' type
    ;

id_list : ident 
   | ident ',' id_list
   ;

type : integer
   | BOOLEAN
   ;

proc_dec : proc_header forward ';'
    | proc_header declaration_list compound_stmt
    | func_header forward ';'
    | func_header declaration_list compound_stmt
    ;

proc_header : procedure ident parametros ';'
    ;

func_header : function ident parametros : type
    ;

parametros : '(' param_list ')' 
    |
    ;

param_list : arg 
    | arg ';' param_list
    ;

arg : id_list ':' type
    | var id_list ':' type
    ;

compound_stmt : begin statement_list end
    ;

statement_list : statement ';' statement_list
    | statement
    ;

statement : ident attrib expression
 | IF expression then statement         
 | IF expression then statement ELSE statement
 | WHILE expression DO statement
 | compound_stmt
 | readln ident
 | writeln print_list
 | 
 ;

print_list : literal print_list2
 | expression print_list2
 ;

print_list2 : ',' print_list 
 | 
 ;

expression : add_expression relop add_expression
 | add_expression
 ;

relop : lessequal
 | '<'
 | '>'
 | moreequal
 | '='
 | notequal
 ;

add_expression : add_expression addop term 
 ;

addop : '+' 
 |  '-'
 | or
 ;

term : term mulop unary_exp 
     |  unary_exp
     ;

mulop : '*' 
  | div
  | mod
  | and
  ;

unary_exp : not unary_exp 
  |  factor
  ;

factor : '(' expression ')'
  |  ident
  |  num
  |  TRUE
  |  FALSE
  ;


%%

我总是得到这个:

byaccj: 19 rules never reduced 
byaccj: 1 shift/reduce conflict.

这可能是什么解决方案?我发现其他人有同样的错误,但我找不到对我的问题有用的东西。如果需要更多信息,我提供。我还读到“规则永不减少”的错误意味着我的语法中的某些规则从未被使用过,但我无法用我的规则来看这一点。

3 个答案:

答案 0 :(得分:4)

在您的情况下,规则proc_dec永远不会出现在任何其他规则的右侧,因此永远无法从您开始符号(Program)到达。 Yacc只是告诉你这个规则(以及它使用的所有规则,没有别的)是不可达的。

通常,您希望使用-v选项让yacc生成y.output文件,其中包含有关语法的详细信息。该文件将具体告诉您所有冲突和未使用的规则 - 它们是什么以及它们是如何产生的 - 而这些消息只是为您提供问题的摘要。

答案 1 :(得分:2)

在这种情况下,您有两个基本的问题来源。一个是你根本没有在程序的语法中包含程序。你可能会用以下的东西解决这个问题:

Program : program ident ';' declaration_opc procedures compound_stmt '.'
    ;

procedures: proc_dec
    | procedures ';' proc_dec
    ;

[我写了任何Pascal已经有一段时间了 - 我不记得你是否真的需要分号来分离程序,但如果没有,那么移除它是微不足道的。]

第二个问题是你add_expression的语法总是无限递归:

add_expression : add_expression addop term 
     ;

你没有包含任何东西来阻止左侧的递归。你可能想要这样的东西:

add_expression : add_expression addop term
               | term addop term
               ;

对于像a + b - c这样的表达式,它将匹配第一个选项:(a + b) add_expression - addop c term < / sub>,第二个替代方案将仅用于匹配a + b部分:a term + addop b term

答案 2 :(得分:0)

文件不完整,因为有许多从未定义过的令牌(例如BOOLEAN)。如果完整,我们可以给出更好的答案。

通常,非减少的规则不是(根据yacc可以确定)通过任何一系列步骤连接到开始状态。所以它们是你应该重新设计或移除的碎片。

以下讨论了以下几个地方: