qua*_*ela 3 parsing yacc lex lexical-analysis
您好,我正在尝试制作一个简单的解析器并使用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;
}
Run Code Online (Sandbox Code Playgroud)
所以这块我添加错误声明.
single_assignment:
IDENTIFIER ASSIGNOP double SEMICOLON
|
IDENTIFIER ASSIGNOP IDENTIFIER SEMICOLON
|
error ';' { printf("You made en error"); }
;
Run Code Online (Sandbox Code Playgroud)
所以我在一行中写了一个= 7(没有';')syntax error Error at line:7.那我的错误信息在哪里?如果你能帮我解决这个问题,我将非常高兴.无论如何,谢谢
所以我在一行中写了一个= 7(没有';')它只是说行语法错误错误:7.那我的错误信息在哪里?
你的error动作告诉Yacc丢弃令牌,直到找到';'为止 令牌.在此之前,它不能通过该规则减少.
此外,您应该yyerrok;在规则主体中的某个位置执行,以向解析器发出已实现恢复的信号.或者,您也可以使用它yyclearin;来丢弃触发错误的令牌.这样做很棘手,因为您猜测令牌是不合适的.它实际上可能是正确的令牌,但在它丢失之前还有别的东西!例如,你看到一个分号,因为没有关闭括号,等等.
错误操作不会替换调用的行为yyerror.当发生语法错误时,解析器将调用yyerror消息(通常是"语法错误"),然后考虑错误产生.错误产生不像"语法错误的自定义覆盖".(看起来您期望"语法错误"被替换为您自己的一般错误消息"您犯了错误".)
在错误生成中,如果您可以猜出错误的性质,则可以打印更有用的其他诊断.
有用的一件事是yychar变量,它告诉你前瞻标记.您可以在错误恢复规则中进行检查,并尝试根据其值猜测出错的地方.您不仅可以检查自己的令牌类型,还可以检查YYEOF指示语法错误是由于未达到某些错误令牌而是输入结束的值.
我写了一个解析器,其中,在一些错误产生中,我只是从中取出令牌yychar并将其转换为其描述性名称并打印出"意外"的消息.这总比没有好; 它告诉用户哪个令牌的语法与预期的不同.
此外,即使在正确的解析中,yacc解析器也可以生成诊断信息!(显然;例如,你如何实现语言的警告.)基本上你需要一些中央错误报告功能,你可以自己调用,yyerror也可以调用.该函数应设置一个标志,指示是否发生致命错误(或保留错误,警告等数量).例如,如果存在致命错误,即使解析器从任何语法错误中恢复,您也可能希望丢弃解析树并使用失败的终止状态保存程序.