d: add the custom error message feature

Parser.Context class returns a const YYLocation, so Lexer's method
yyerror() needs to receive the location as a const parameter.

Internal error reporting flow is changed to be similar to that of
the other skeletons. Before, case YYERRLAB was calling yyerror()
with the result of yysyntax_error() as the string parameter. As the
custom error message lets the user decide if they want to use
yyerror() or not, this flow needed to be changed. Now, case YYERRLAB
calls yyreportSyntaxError(), that builds the error message using
yysyntaxErrorArguments(). Then yyreportSyntaxError() passes the
error message to the user defined syntax_error() in case of a custom
message, or to yyerror() otherwise.

In the tests in tests/calc.at, the order of the tokens needs to be
changed in order of precedence, so that the D program outputs the
expected tokens in the same order as the other parsers.

* data/skeletons/lalr1.d: Add the custom error message feature.
* doc/bison.texi: Document it.
* examples/d/calc/calc.y: Adjust.
* tests/calc.at, tests/local.at: Test it.
This commit is contained in:
Adela Vais
2020-10-24 16:43:46 +03:00
committed by Akim Demaille
parent 4252134ba4
commit dc15b62a7c
5 changed files with 159 additions and 26 deletions

View File

@@ -14026,6 +14026,42 @@ They should return new objects for each call, to avoid that all the symbol
share the same Position boundaries.
@end deftypemethod
@deftypemethod {Lexer} {void} syntax_error(@code{YYParser.Context} @var{ctx})
If you invoke @samp{%define parse.error custom} (@pxref{Bison
Declarations}), then the parser no longer passes syntax error messages to
@code{yyerror}, rather it delegates that task to the user by calling the
@code{reportSyntaxError} function.
Whether it uses @code{yyerror} is up to the user.
Here is an example of a reporting function (@pxref{D Parser Context
Interface}).
@example
public void syntax_error(YYParser.Context ctx)
@{
stderr.write(ctx.getLocation(), ": syntax error");
// Report the expected tokens.
@{
immutable int TOKENMAX = 5;
YYParser.SymbolKind[] arg = new YYParser.SymbolKind[TOKENMAX];
int n = ctx.getExpectedTokens(arg, TOKENMAX);
if (n < TOKENMAX)
for (int i = 0; i < n; ++i)
stderr.write((i == 0 ? ": expected " : " or "), arg[i]);
@}
// Report the unexpected token which triggered the error.
@{
YYParser.SymbolKind lookahead = ctx.getToken();
stderr.writeln(" before ", lookahead);
@}
@}
@end example
@noindent
This implementation is inappropriate for internationalization, see
the @file{c/bistromathic} example for a better alternative.
@end deftypemethod
@node D Action Features
@subsection Special Features for Use in D Actions
@@ -14049,7 +14085,6 @@ errors. This is useful primarily in error rules.
@xref{Error Recovery}.
@end deffn
@node Java Parsers
@section Java Parsers