c: don't emit an error message when the scanner returns YYERRCODE

* data/skeletons/yacc.c (yyparse): When the scanner returns YYERRCODE,
go directly to error recovery (yyerrlab1).
However, don't keep the error token as lookahead, that token is too
special.
* data/skeletons/lalr1.cc: Likewise.

* examples/c/bistromathic/parse.y (yylex): Use that feature to report
nicely invalid characters.
* examples/c/bistromathic/bistromathic.test: Check that.
* examples/test: Neutralize gratuitous differences such as rule
position.

* tests/calc.at: Check that case in C only.
The other case seem to be working, but that's an illusion that the
next commit will address (in fact, they can enter endless loops, and
report the error several times anyway).
This commit is contained in:
Akim Demaille
2020-04-15 07:38:46 +02:00
parent 60366b152b
commit 58e79539fc
6 changed files with 214 additions and 22 deletions

View File

@@ -201,8 +201,8 @@ read_integer (]AT_YYLEX_FORMALS[)
/* Skip white spaces. */
do
{
]AT_LOCATION_IF(
[ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
]AT_LOCATION_IF([
AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
])[
}
@@ -220,6 +220,15 @@ read_integer (]AT_YYLEX_FORMALS[)
if (c == EOF)
return ]AT_TOKEN_PREFIX[CALC_EOF;
/* An explicit error raised by the scanner. */
if (c == '#')
{]AT_LOCATION_IF([
fprintf (stderr, "%d.%d: ",
AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN);])[
fputs ("syntax error: invalid character: '#'\n", stderr);
return ]AT_TOKEN_PREFIX[]AT_API_PREFIX[ERRCODE;
}
/* Return single chars. */
return c;
}
@@ -304,7 +313,7 @@ class CalcLexer(R) : Lexer
location.end.column += 1;]])[
}
// Handle EOF.
// EOF.
if (input.empty)
return TokenKind.CALC_EOF;
@@ -325,6 +334,14 @@ class CalcLexer(R) : Lexer
else
location.end.column += 1;]])[
input.popFront;
// An explicit error raised by the scanner. */
if (c == '#')
{
stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
return TokenKind.YYERRCODE;
}
return c;
}
}
@@ -370,9 +387,9 @@ m4_define([AT_CALC_YYLEX(java)],
public int yylex () throws IOException {;]AT_LOCATION_IF([[
start.set (reader.getPosition ());]])[
int ttype = st.nextToken ();]AT_LOCATION_IF([[
int tkind = st.nextToken ();]AT_LOCATION_IF([[
end.set (reader.getPosition ());]])[
switch (ttype)
switch (tkind)
{
case StreamTokenizer.TT_EOF:
return EOF;
@@ -386,8 +403,11 @@ m4_define([AT_CALC_YYLEX(java)],
return NUM;
case ' ': case '\t':
return yylex ();
case '#':
System.err.println(]AT_LOCATION_IF([[start + ": " + ]])["syntax error: invalid character: '#'");
return YYERRCODE;
default:
return ttype;
return tkind;
}
}
]AT_LEXPARAM_IF([], [[}]])[
@@ -1004,6 +1024,20 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
# YYERRCODE.
# ---------
# Check that returning YYERRCODE from the scanner properly enters
# error-recovery without issuing a second error message.
_AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
[[final: 2222 0 0]],
[102],
[[1.2: syntax error: invalid character: '#'
1.8: syntax error: invalid character: '#']])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP