error handling in YACC

15,439

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

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

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.

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.

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.

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.

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.

Share:
15,439
quartaela
Author by

quartaela

always curious...

Updated on June 07, 2022

Comments

  • quartaela
    quartaela almost 2 years

    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"); }  
        ;
    

    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