Error recovery using flex and yacc

Error recovery using flex and yacc

Post by Francis Harve » Mon, 05 Mar 2001 15:50:56



Greetings,

Using Flex 2.5.4 and Berkeley Yacc, I have been trying to create an
error recovery method for my grammar.  In a nutshell, I have succeeded
to a certain extent, but I am worried about having to change the
generated lex.yy.c input and yyunput declarations from using static to
extern.

Each line of my source file is identified by a category symbol and
these should occur in certain set groups.  In the simple case of
trying to deal with an unknown symbol, I use the rule:

source: ErrGroup Pgroup ErrGroup statement ErrGroup

where ErrGroup is defined as being:

ErrGroup:
                | error
                        {
                        recover();
                        yyclearin;
                        yyerrok;
                        error_handler(11);
                        }
                        NEWLINE
                ;

which recognizes the unknown token and then expects to recover to a
state where a NEWLINE token will be recognized.

Basically, I just plan to throw away the entire line when an error
occurs and hope that recovers to a useful state, otherwise, I'll throw
away the next line, etc.

My recover routine is simply:

recover() {
        int c;

        for (;;) {
                c = input();
                if (c == EOF || (char) c == '\n') break;
        }
        yyunput(c, yytext);
        return 1;

Quote:}

which works as long as I go into lex.yy.c and redefine the input and
yyunput functions to be extern rather than static functions.  There
lies the heart of my problem.  When I read O'Reilly, it seems to me
that these functions should be available in my grammar, but my version
of flex keeps creating these as static functions.  Should I be using
another function serving as a wrapper for these functions or using
some command line parameter to alter the behavior of flex?  The only
option I use on flex now is the -I option, and on yacc I only use the
-d option.  TIA for your help.

Francis R. Harvey III
WB303, x3952

[Put the recover routine at the end of your lexer.  But if you just want
to throw away the input up to a new line, that's easier to do by using
an exclusive start state, e.g.

<RECOVER>.*\n     { BEGIN NORMAL; }
...

recover() { BEGIN RECOVER; }

 -John]