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

@@ -868,10 +868,50 @@ m4_define([AT_YYERROR_DECLARE_EXTERN(d)], [])
m4_define([AT_YYERROR_DEFINE(d)],
[[/* An error reporting function. */
public void yyerror (]AT_LOCATION_IF([[YYLocation l, ]])[string m)
public void yyerror (]AT_LOCATION_IF([[const YYLocation l, ]])[string m)
{
stderr.writeln (]AT_LOCATION_IF([[l, ": ", ]])[m);
}]])
}
]AT_ERROR_CUSTOM_IF([[
// In the case of D, there are no single quotes around the symbols
// so they need to be added here
public string transformToken(]AT_API_PREFIX[Parser.SymbolKind token)
{
string res;
foreach (i; format("%s", token))
{
if (i == '\"')
res ~= '\'';
else
res ~= i;
}
if (res.length == 1)
return '\'' ~ res ~ '\'';
else
return res;
}
public void syntax_error(]AT_API_PREFIX[Parser.Context ctx)
{
stderr.write(]AT_LOCATION_IF([[ctx.getLocation(), ": ",]])["syntax error");
{
]AT_API_PREFIX[Parser.SymbolKind token = ctx.getToken();
stderr.write(" on token @<:@", transformToken(token), "@:>@");
}
{
immutable int argmax = 7;
]AT_API_PREFIX[Parser.SymbolKind[] arg = new ]AT_API_PREFIX[Parser.SymbolKind[argmax];
int n = ctx.getExpectedTokens(arg, argmax);
if (0 < n)
{
stderr.write(" (expected:");
for (int i = 0; i < n; ++i)
stderr.write(" @<:@", transformToken(arg[i]), "@:>@");
stderr.writeln(")");
}
}
}
]])[]])
m4_define([AT_MAIN_DEFINE(d)],