Related articles |
---|
Error recovery using flex and yacc HARVEYF1@WESTAT.com (Francis Harvey) (2001-03-04) |
From: | Francis Harvey <HARVEYF1@WESTAT.com> |
Newsgroups: | comp.compilers |
Date: | 4 Mar 2001 01:50:56 -0500 |
Organization: | Compilers Central |
Keywords: | yacc, errors |
Posted-Date: | 04 Mar 2001 01:50:56 EST |
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;
}
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
harveyf1@westat.com
[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]
Return to the
comp.compilers page.
Search the
comp.compilers archives again.