Related articles |
---|
LEX/YACC - grammar problems and printing error messages nett@technix.mn.org (1992-05-28) |
Re: LEX/YACC - grammar problems and printing error messages johnl@iecc.cambridge.ma.us (1992-05-28) |
Re: LEX/YACC - grammar problems and printing error messages craig@comp.lancs.ac.uk (1992-05-29) |
LEX/YACC - grammar problems and printing error messages thiemann@informatik.uni-tuebingen.de (1992-06-02) |
Newsgroups: | comp.unix.programmer,comp.compilers |
From: | johnl@iecc.cambridge.ma.us (John R. Levine) |
Keywords: | lex, errors |
Organization: | I.E.C.C. |
References: | 92-05-148 |
Date: | Thu, 28 May 1992 18:38:40 GMT |
In article 92-05-148 you write:
>[how can I get the entire line where an error occurs into an error message?]
Yacc promises to complain as soon as it sees a token you can't parse so it's
mostly a matter of having the current line available when the error occurs.
Basically, you have to buffer the line yourself. In AT&T lex one
possibility is to rewrite the input() macro to do line buffering, but
here's a sketch of how to do it in a portable way that should work with
flex, the version of lex that all sensible people use. This should extend
in a straightforward way to multi-line records so long as the lexer can
tell where the record boundaries are.
---begin untested lex code---
%{
char linebuf[500]; /* line buffer for tokens */
int curoffs; /* start of current token */
int clear_on_next = 0;
%}
%%
/* clear buffer after end of line */
\n { add_linebuf(); clear_on_next = 1; return(EOL); }
/* real token */
foo { add_linebuf(); return(FOO); }
/* ignored white space still needs to go in the buffer */
[ \t]+ { add_linebuf(); }
%%
/* initialize the line buffer */
clr_linebuf()
{
linebuf[0] = '\0';
curoffs = 0;
clear_on_next = 0;
}
/* add the current token to the current line */
add_linebuf()
{
if(clear_on_next)
clr_linebuf();
curoffs = strlen(linebuf); /* start of current */
strcpy(linebuf+curoffs, yytext); /* append current */
/* strcpy is faster than strcat */
}
/* report an error */
yyerror(char *errmsg)
{
int curend = linebuf+strlen(linebuf); /* current buf end */
char *p;
/* get the rest of the line if not at end */
if(!clear_on_next) {
for(p = curend; ; ) {
int c = input();
*p++ = c;
if(c == '\n')
break;
}
*p = 0;
/* now give it back so lex can scan it later */
while(p > curend)
unput(*--p);
}
/* linebuf[] now has the whole line, with the current token */
/* at curoffs */
/* print error message and current line */
printf("%s\n%s", errmsg, linebuf);
/* print an X under the most recent token */
printf("%*sX\n", curoffs , ""); /* curoffs spaces, then X */
}
--end untested lex code---
Here's a slightly easier approach which pre-reads the next line after
every newline, but doesn't keep track of the location of the current
token.
--begin more untested lex code---
%%
\n.* { strcpy(linebuf, yytext+1); /* save the next line */
yyless(1); /* give back all but the \n to rescan */
}
--begin more untested lex code---
Regards,
John Levine, johnl@iecc.cambridge.ma.us, {spdcc|ima|world}!iecc!johnl
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.