我正在学习与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.
这可能是什么解决方案?我发现其他人有同样的错误,但我找不到对我的问题有用的东西。如果需要更多信息,我提供。我还读到“规则永不减少”的错误意味着我的语法中的某些规则从未被使用过,但我无法用我的规则来看这一点。
答案 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可以确定)通过任何一系列步骤连接到开始状态。所以它们是你应该重新设计或移除的碎片。
以下讨论了以下几个地方: