mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
d: create the Parser.Context class
This will provide the user an interface for creating custom error messages. * data/skeletons/lalr1.d: Add the Context class. * doc/bison.texi: Document it.
This commit is contained in:
committed by
Akim Demaille
parent
98691fcd2d
commit
0cd16ae964
@@ -452,7 +452,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
|
||||
/* Take a decision. First try without lookahead. */
|
||||
yyn = yypact_[yystate];
|
||||
if (yy_pact_value_is_default_ (yyn))
|
||||
if (yyPactValueIsDefault(yyn))
|
||||
{
|
||||
label = YYDEFAULT;
|
||||
break;
|
||||
@@ -497,7 +497,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
/* <= 0 means reduce or error. */
|
||||
else if ((yyn = yytable_[yyn]) <= 0)
|
||||
{
|
||||
if (yy_table_value_is_error_ (yyn))
|
||||
if (yyTableValueIsError(yyn))
|
||||
label = YYERRLAB;
|
||||
else
|
||||
{
|
||||
@@ -555,7 +555,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
++yynerrs_;
|
||||
if (yychar == TokenKind.]b4_symbol(empty, id)[)
|
||||
yytoken = ]b4_symbol(empty, kind)[;
|
||||
yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken));
|
||||
yyerror (]b4_locations_if([yylloc, ])[yysyntax_error(new Context(yystack, yytoken]b4_locations_if([[, yylloc]])[)));
|
||||
}
|
||||
]b4_locations_if([
|
||||
yyerrloc = yylloc;])[
|
||||
@@ -602,7 +602,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
for (;;)
|
||||
{
|
||||
yyn = yypact_[yystate];
|
||||
if (!yy_pact_value_is_default_ (yyn))
|
||||
if (!yyPactValueIsDefault(yyn))
|
||||
{
|
||||
yyn += ]b4_symbol(1, kind)[;
|
||||
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(1, kind)[)
|
||||
@@ -659,7 +659,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
}
|
||||
|
||||
// Generate an error message.
|
||||
private final string yysyntax_error (int yystate, SymbolKind tok)
|
||||
private final string yysyntax_error(Context yyctx)
|
||||
{]b4_parse_error_case([verbose], [[
|
||||
/* There are many possibilities here to consider:
|
||||
- Assume YYFAIL is not used. It's too flawed to consider.
|
||||
@@ -692,14 +692,71 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
will still contain any token that will not be accepted due
|
||||
to an error action in a later state.
|
||||
*/
|
||||
if (tok != ]b4_symbol(empty, kind)[)
|
||||
if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
|
||||
{
|
||||
// FIXME: This method of building the message is not compatible
|
||||
// with internationalization.
|
||||
string res = "syntax error, unexpected ";
|
||||
res ~= format!"%s"(tok);
|
||||
int yyn = yypact_[yystate];
|
||||
if (!yy_pact_value_is_default_ (yyn))
|
||||
res ~= format!"%s"(yyctx.getToken);
|
||||
immutable int argmax = 5;
|
||||
SymbolKind[] yyarg = new SymbolKind[argmax];
|
||||
int yycount = yyctx.getExpectedTokens(yyarg, argmax);
|
||||
if (yycount < argmax)
|
||||
{
|
||||
for (int yyi = 0; yyi < yycount; yyi++)
|
||||
{
|
||||
res ~= yyi == 0 ? ", expecting " : " or ";
|
||||
res ~= format!"%s"(SymbolKind(yyarg[yyi]));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}]])[
|
||||
return "syntax error";
|
||||
}
|
||||
|
||||
/**
|
||||
* Information needed to get the list of expected tokens and to forge
|
||||
* a syntax error diagnostic.
|
||||
*/
|
||||
public static final class Context
|
||||
{
|
||||
|
||||
private YYStack yystack;
|
||||
private SymbolKind yytoken;]b4_locations_if([[
|
||||
private ]b4_location_type[ yylocation;]])[
|
||||
|
||||
this(YYStack stack, SymbolKind kind]b4_locations_if([[, ]b4_location_type[ loc]])[)
|
||||
{
|
||||
yystack = stack;
|
||||
yytoken = kind;]b4_locations_if([[
|
||||
yylocation = loc;]])[
|
||||
}
|
||||
|
||||
final SymbolKind getToken() const
|
||||
{
|
||||
return yytoken;
|
||||
}]b4_locations_if([[
|
||||
|
||||
final ]b4_location_type[ getLocation()
|
||||
{
|
||||
return yylocation;
|
||||
}]])[
|
||||
/**
|
||||
* Put in YYARG at most YYARGN of the expected tokens given the
|
||||
* current YYCTX, and return the number of tokens stored in YYARG. If
|
||||
* YYARG is null, return the number of expected tokens (guaranteed to
|
||||
* be less than YYNTOKENS).
|
||||
*/
|
||||
int getExpectedTokens(SymbolKind[] yyarg, int yyargn)
|
||||
{
|
||||
return getExpectedTokens(yyarg, 0, yyargn);
|
||||
}
|
||||
|
||||
int getExpectedTokens(SymbolKind[] yyarg, int yyoffset, int yyargn)
|
||||
{
|
||||
int yycount = yyoffset;
|
||||
int yyn = yypact_[this.yystack.stateAt(0)];
|
||||
if (!yyPactValueIsDefault(yyn))
|
||||
{
|
||||
/* Start YYX at -YYN if negative to avoid negative
|
||||
indexes in YYCHECK. In other words, skip the first
|
||||
@@ -709,33 +766,28 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
/* Stay within bounds of both yycheck and yytname. */
|
||||
int yychecklim = yylast_ - yyn + 1;
|
||||
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
|
||||
int count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
||||
++count;
|
||||
if (count < 5)
|
||||
{
|
||||
count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
||||
{
|
||||
res ~= count++ == 0 ? ", expecting " : " or ";
|
||||
res ~= format!"%s"(SymbolKind(x));
|
||||
}
|
||||
}
|
||||
for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
|
||||
if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[
|
||||
&& !yyTableValueIsError(yytable_[yyx + yyn]))
|
||||
yycount++;
|
||||
if (yycount < yyargn)
|
||||
{
|
||||
yycount = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||
&& !yyTableValueIsError(yytable_[x + yyn]))
|
||||
yyarg[yycount++] = SymbolKind(x);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}]])[
|
||||
return "syntax error";
|
||||
return yycount - yyoffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given <code>yypact_</code> value indicates a defaulted state.
|
||||
* @@param yyvalue the value to check
|
||||
*/
|
||||
private static bool yy_pact_value_is_default_ (int yyvalue)
|
||||
private static bool yyPactValueIsDefault(int yyvalue)
|
||||
{
|
||||
return yyvalue == yypact_ninf_;
|
||||
}
|
||||
@@ -744,7 +796,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
* Whether the given <code>yytable_</code> value indicates a syntax error.
|
||||
* @@param yyvalue the value to check
|
||||
*/
|
||||
private static bool yy_table_value_is_error_ (int yyvalue)
|
||||
private static bool yyTableValueIsError(int yyvalue)
|
||||
{
|
||||
return yyvalue == yytable_ninf_;
|
||||
}
|
||||
|
||||
@@ -13948,10 +13948,29 @@ enumerators are forged from the symbol names. Use void toString(W)(W sink) to g
|
||||
the symbol names.
|
||||
@end defcv
|
||||
|
||||
@deftypemethod {YYParser.Context} {YYParser.Location} yylloc_from_stack()
|
||||
@deftypemethod {YYParser.Context} {YYParser.SymbolKind} getToken()
|
||||
The kind of the lookahead. Return @code{null} iff there is no lookahead.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {YYParser.Context} {YYParser.Location} getLocation()
|
||||
The location of the lookahead.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {YYParser.Context} {int} getExpectedTokens(@code{YYParser.SymbolKind[]} @var{argv}, @code{int} @var{argc})
|
||||
Fill @var{argv} with the expected tokens, which never includes
|
||||
@code{SymbolKind.YYERROR}, or @code{SymbolKind.YYUNDEF}.
|
||||
|
||||
Never put more than @var{argc} elements into @var{argv}, and on success
|
||||
return the number of tokens stored in @var{argv}. If there are more
|
||||
expected tokens than @var{argc}, fill @var{argv} up to @var{argc} and return
|
||||
0. If there are no expected tokens, also return 0, but set @code{argv[0]}
|
||||
to @code{null}.
|
||||
|
||||
If @var{argv} is null, return the size needed to store all the possible
|
||||
values, which is always less than @code{YYNTOKENS}.
|
||||
@end deftypemethod
|
||||
|
||||
|
||||
@node D Scanner Interface
|
||||
@subsection D Scanner Interface
|
||||
@c - %code lexer
|
||||
|
||||
Reference in New Issue
Block a user