Bison 规则永远不会减少,明白为什么吗

Bison 规则永远不会减少,明白为什么吗,bison,yacc,Bison,Yacc,我正在学习与YACC合作,我真的无法理解一些错误。我想知道当我试图用.y文件生成解析器时,为什么会出现这个错误。这是my.y文件,它表示Pascal语言的上下文无关语法: %% Program : program ident ';' declaration_opc compound_stmt '.' ; declaration_opc : var declaration_list | ; declaration_list : declaration ';' dec

我正在学习与YACC合作,我真的无法理解一些错误。我想知道当我试图用.y文件生成解析器时,为什么会出现这个错误。这是my.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
  ;


%%

有什么可能的解决办法?我发现其他人也有同样的错误,但我没能找到对我的问题有用的东西。如果需要更多信息,我将提供。我还读到“Rules never reduced”错误意味着我的语法中的一些规则从未被使用过,但我无法从我的规则中看出这一点

文件不完整,因为有许多从未定义过的标记(例如
布尔值
)。如果它是完整的,我们可以给出一个更好的答案

一般来说,未简化的规则(就yacc所能确定的范围而言)不会通过任何一系列步骤连接到启动状态。所以它们是你应该重新设计或移除的碎片

以下是一些以前讨论过的地方:


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


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

在本例中,您有两个基本的问题来源。一个是你根本没有在你的程序语法中包含过程。您可能会通过以下方式解决此问题:

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

procedures: proc_dec
    | procedures ';' proc_dec
    ;
add_expression : add_expression addop term
               | term addop term
               ;
[我已经有一段时间没有编写任何Pascal了——我不记得是否需要分号来分隔过程,但如果不需要,就可以删除它。]

第二个问题是
add\u表达式的语法总是无限递归的:

add_expression : add_expression addop term 
     ;
您没有在左侧包含任何停止递归的内容。您可能需要以下内容:

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

procedures: proc_dec
    | procedures ';' proc_dec
    ;
add_expression : add_expression addop term
               | term addop term
               ;

对于像
a+b-c
这样的表达式,它将匹配第一个选项为:(a+b)add_expression-addop字符m,第二个选项将用于仅匹配
a+b
部分为:aterm+addop bterm。

我已经编辑了您的标题。请参阅“”,其中的共识是“不,他们不应该”。使用
yacc-v foo.y
,它将生成一个名为
y.output
的文件。在该文件的结尾将是一个“从不减少的规则”列表。就目前而言,这是正确的,但仍然没有涵盖六个“从不减少的”规则…,谢谢,我不敢相信我看不到,没有减少的19个规则与proc_dec和参数有关,所以我肯定不是从开始符号开始调用它们。