您好,我正在尝试制作一个简单的解析器并使用lex和yacc。问题是我想打印我自己的错误消息,而不是打印error
的yacc使用的syntax error
符号。例如,这是我的yacc代码;
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
extern FILE *yyin;
extern int linenum;
%}
%token INTRSW IDENTIFIER INTEGER ASSIGNOP SEMICOLON DOUBLEVAL DOUBLERSW COMMA
%token IF ELSE WHILE FOR
%token CLOSE_BRA OPEN_BRA CLOSE_PARA OPEN_PARA EQ LE GE
%token SUM MINUS MULTIP DIV
%left OPEN_BRA OPEN_PARA
%left MULTIP DIV
%left SUM MINUS
%union
{
int number;
char* string;
}
%token <number> INTEGER
%token <string> IDENTIFIER
%%
program:
statement_list
;
statement_list:
statement_list statement
|
statement
;
statement:
if_statement OPEN_BRA statement_list CLOSE_BRA
|
if_statement
|
assignment_block
|
single_assignment
;
if_statement:
IF OPEN_PARA condition_statement CLOSE_PARA
;
condition_statement:
logical_expression
;
logical_expression:
expression EQ expression
|
expression LE expression
|
expression GE expression
;
expression:
double
|
IDENTIFIER
|
OPEN_PARA expression CLOSE_PARA
|
expression MULTIP expression
|
expression DIV expression
|
expression SUM expression
|
expression MINUS expression
;
assignment_block:
integer_assignment_block
|
double_assignment_block
;
integer_assignment_block:
INTRSW integer_assignment_list SEMICOLON
;
double_assignment_block:
DOUBLERSW double_assignment_list SEMICOLON
;
integer_assignment_list:
integer_assignment
|
integer_assignment_list COMMA integer_assignment
;
double_assignment_list:
double_assignment
|
double_assignment_list COMMA double_assignment
;
single_assignment:
IDENTIFIER ASSIGNOP double SEMICOLON
|
IDENTIFIER ASSIGNOP IDENTIFIER SEMICOLON
|
error ';' { printf("You made en error"); }
;
integer_assignment:
IDENTIFIER ASSIGNOP INTEGER
|
IDENTIFIER
;
double_assignment:
IDENTIFIER ASSIGNOP double
|
IDENTIFIER
;
double:
DOUBLEVAL
|
INTEGER
;
%%
void yyerror(char *s){
fprintf(stderr,"%s Error at line: %d\n",s, linenum);
}
int yywrap(){
return 1;
}
int main(int argc, char *argv[])
{
/* Call the lexer, then quit. */
yyin=fopen(argv[1],"r");
yyparse();
fclose(yyin);
return 0;
}
所以这个块我添加了错误声明。
single_assignment:
IDENTIFIER ASSIGNOP double SEMICOLON
|
IDENTIFIER ASSIGNOP IDENTIFIER SEMICOLON
|
error ';' { printf("You made en error"); }
;
所以我在一行中写了一个= 7(没有';'),只是说syntax error Error at line:7
。那我的错误信息在哪里?如果你能帮我解决这个问题,我将非常高兴。并且还要感谢
答案 0 :(得分:5)
所以我在一行中写了一个= 7(没有';')它只是说语法错误错误 在线:7。那么我的错误信息在哪里??
您的error
操作告诉Yacc丢弃令牌,直到找到';'为止令牌。在此之前,它不能通过该规则减少。
此外,您应该在规则正文中的某处执行yyerrok;
,以向解析器发出已恢复已完成的信号。或者,您也可以使用yyclearin;
丢弃触发错误的令牌。这样做很棘手,因为您猜测令牌是不合适的。它实际上可能是正确的令牌,但在它丢失之前还有别的东西!例如,你看到一个分号,因为没有用括号括起来等等。
错误操作不会替换调用yyerror
的行为。当发生语法错误时,解析器将使用消息(通常是“语法错误”)调用yyerror
,然后考虑错误产生。错误产生不像“语法错误的自定义覆盖”。 (看起来您期望“语法错误”被替换为您自己的一般错误消息“您犯了错误”。)
在错误生成中,如果您能猜出错误的性质,则可以打印更有用的其他诊断。
有用的一件事是yychar
变量,它告诉你前瞻标记。您可以在错误恢复规则中进行检查,并尝试根据其值猜测出错的地方。您不仅可以检查自己的令牌类型,还可以检查值YYEOF
,这表示语法错误是由于未达到某些错误令牌而导致输入结束。
我编写了一个解析器,其中,在一些错误产品中,我只是从yychar
获取了令牌并将其转换为其描述性名称并打印出“意外的”消息。这总比没有好;它告诉用户哪个令牌的语法偏离了预期。
此外,即使在正确的解析中,yacc解析器也可以生成诊断信息! (显然;例如,你如何实现一种语言的警告。)基本上你需要一些你可以自己调用的中央错误报告功能,以及yyerror
也会调用。该函数应设置一个标志,指示是否发生致命错误(或保留错误,警告等数量)。例如,如果存在致命错误,即使解析器从任何语法错误中恢复,您也可能希望丢弃解析树并使用失败的终止状态保存程序。