YACC中的错误处理 [英] error handling in YACC

查看:818
本文介绍了YACC中的错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个简单的解析器,并使用lex和yacc.问题是我想打印我自己的错误消息,而不是yacc使用的error符号打印syntax error.例如,这是我的yacc代码;

hi there i'm trying to make a simple parser and using lex and yacc. the thing is i wanna print my own error messages rather than error symbol used by yacc which prints syntax error. for example this is my yacc code;

%{
#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;
}

所以这是我添加错误声明的地方.

so this the block i add error statement.

single_assignment:
    IDENTIFIER ASSIGNOP double SEMICOLON
    |
    IDENTIFIER ASSIGNOP IDENTIFIER SEMICOLON
    |
    error ';' { printf("You made en error"); }  
    ;

所以我在只说syntax error Error at line:7的行中写了a = 7(不带';').所以我的错误消息在哪里?如果您能在这个问题上帮助我,我将非常高兴.还是谢谢你

so i write a=7 (without ';') in a line it just says syntax error Error at line:7. so where is my error message_? i will be very very glad if you can help me about this issue. and thanks anyway

推荐答案

所以我在一行中写了a = 7(不带';'),只是说语法错误错误 在第7行.所以我的错误消息在哪里?

so i write a=7 (without ';') in a line it just says syntax error Error at line:7. so where is my error message_?

您的error动作告诉Yacc丢弃令牌,直到找到';'.令牌.在这种情况发生之前,它无法按照该规则减少.

Your error action tells Yacc to discard tokens until it finds a ';' token. Until that happens, it cannot reduce by that rule.

此外,您应该在规则正文中的某处执行yyerrok;,以向解析器发送信号,告知已完成恢复. (可选)您可以使用yyclearin;丢弃引发错误的令牌.这样做很棘手,因为您猜测令牌是不合适的.它实际上可以是正确的令牌,但是在它丢失之前还有其他东西!例如,您看到了分号,因为省略了右括号,等等.

Also, you should execute yyerrok; somewhere in the rule body to signal to the parser that recovery has been achieved. Optionally, you can use yyclearin; to also throw away the token that triggered the error. Doing this is tricky because you're guessing that the token is inappropriate. It can actually be the right token, but something else before it is missing! E.g you're seeing a semicolon, because a closing brace was left out, etc.

错误操作不会替换调用yyerror的行为.发生语法错误时,解析器将使用一条消息(通常为语法错误")调用yyerror,然后考虑产生错误的原因.错误产生类似于语法错误的自定义替代". (您似乎希望将语法错误"替换为您自己的通用错误消息您犯了错误".)

Error actions will not replace the behavior of calling yyerror. When a syntax error occurs, the parser will call yyerror with a message (usually "syntax error"), and then are the error productions considered. Error productions are not anything like "custom overrides for syntax errors". (It looks like you're expecting "syntax error" to be replaced with your own generic error message "You made an error".)

在错误产生中,如果您可以猜测错误的性质,则可以打印出更有用的附加诊断.

In the error production, if you can guess the nature of the error, you can print an additional diagnostic that is more helpful.

有用的一件事是yychar变量,它告诉您超前标记.您可以在错误恢复规则中进行检查,并尝试根据其值猜测出了什么问题.您不仅可以检查自己的令牌类型,还可以检查值YYEOF,该值指示语法错误不是由于到达某些错误的令牌,而是由于输入的末尾.

One thing that is useful is the yychar variable which tells you the lookahead token. You can check this in the error recovery rule and try to guess what went wrong based on its value. You can check this not only for your own token types but for the value YYEOF which indicates that the syntax error is due to reaching not some bad token, but the end of input.

我编写了一个解析器,在其中,由于某些错误产生,我只是从yychar中获取了令牌并将其转换为描述性名称,并显示了消息"unexpected in".总比没有好.它告诉用户语法与预期令牌在哪个标记处出现.

I wrote a parser in which, in some error productions, I simply took the token from yychar and converted it to its descriptive name and printed the message "unexpected in ". This is better than nothing; it tells the user at which token does the syntax depart from what is expected.

此外,即使是正确的解析,yacc解析器也可以产生诊断信息! (很明显;例如,您将如何对语言进行警告.)基本上,您需要一些可以自己调用的中央错误报告功能,并且还会调用yyerror.该功能应设置一个标志,以指示是否发生致命错误(或记录错误,警告等的数量).例如,即使存在致命错误,即使解析器已从任何语法错误中恢复过来,您也可能希望丢弃解析树并以失败的终止状态来阻止程序运行.

Also, yacc parsers can produce diagnostics even in a correct parse! (Obviously; for instance, how else would you implement warnings for a language.) Basically you need some central error reporting function that you can call yourself, and which yyerror will also call. That function should set a flag indicating whether or not fatal errors occurred (or keep a count of how many errors, warnings, etc). You may want to, for instance, throw away the parse tree and bail the program with a failed termination status, if there were fatal errors, even if the parser recovered from any syntax errors.

这篇关于YACC中的错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆