mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13: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. */
|
/* Take a decision. First try without lookahead. */
|
||||||
yyn = yypact_[yystate];
|
yyn = yypact_[yystate];
|
||||||
if (yy_pact_value_is_default_ (yyn))
|
if (yyPactValueIsDefault(yyn))
|
||||||
{
|
{
|
||||||
label = YYDEFAULT;
|
label = YYDEFAULT;
|
||||||
break;
|
break;
|
||||||
@@ -497,7 +497,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
/* <= 0 means reduce or error. */
|
/* <= 0 means reduce or error. */
|
||||||
else if ((yyn = yytable_[yyn]) <= 0)
|
else if ((yyn = yytable_[yyn]) <= 0)
|
||||||
{
|
{
|
||||||
if (yy_table_value_is_error_ (yyn))
|
if (yyTableValueIsError(yyn))
|
||||||
label = YYERRLAB;
|
label = YYERRLAB;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -555,7 +555,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
++yynerrs_;
|
++yynerrs_;
|
||||||
if (yychar == TokenKind.]b4_symbol(empty, id)[)
|
if (yychar == TokenKind.]b4_symbol(empty, id)[)
|
||||||
yytoken = ]b4_symbol(empty, kind)[;
|
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([
|
]b4_locations_if([
|
||||||
yyerrloc = yylloc;])[
|
yyerrloc = yylloc;])[
|
||||||
@@ -602,7 +602,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
yyn = yypact_[yystate];
|
yyn = yypact_[yystate];
|
||||||
if (!yy_pact_value_is_default_ (yyn))
|
if (!yyPactValueIsDefault(yyn))
|
||||||
{
|
{
|
||||||
yyn += ]b4_symbol(1, kind)[;
|
yyn += ]b4_symbol(1, kind)[;
|
||||||
if (0 <= yyn && yyn <= yylast_ && yycheck_[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.
|
// 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], [[
|
{]b4_parse_error_case([verbose], [[
|
||||||
/* There are many possibilities here to consider:
|
/* There are many possibilities here to consider:
|
||||||
- Assume YYFAIL is not used. It's too flawed 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
|
will still contain any token that will not be accepted due
|
||||||
to an error action in a later state.
|
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
|
// FIXME: This method of building the message is not compatible
|
||||||
// with internationalization.
|
// with internationalization.
|
||||||
string res = "syntax error, unexpected ";
|
string res = "syntax error, unexpected ";
|
||||||
res ~= format!"%s"(tok);
|
res ~= format!"%s"(yyctx.getToken);
|
||||||
int yyn = yypact_[yystate];
|
immutable int argmax = 5;
|
||||||
if (!yy_pact_value_is_default_ (yyn))
|
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
|
/* Start YYX at -YYN if negative to avoid negative
|
||||||
indexes in YYCHECK. In other words, skip the first
|
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. */
|
/* Stay within bounds of both yycheck and yytname. */
|
||||||
int yychecklim = yylast_ - yyn + 1;
|
int yychecklim = yylast_ - yyn + 1;
|
||||||
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
|
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
|
||||||
int count = 0;
|
for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
|
||||||
for (int x = yyxbegin; x < yyxend; ++x)
|
if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[
|
||||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
&& !yyTableValueIsError(yytable_[yyx + yyn]))
|
||||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
yycount++;
|
||||||
++count;
|
if (yycount < yyargn)
|
||||||
if (count < 5)
|
{
|
||||||
{
|
yycount = 0;
|
||||||
count = 0;
|
for (int x = yyxbegin; x < yyxend; ++x)
|
||||||
for (int x = yyxbegin; x < yyxend; ++x)
|
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
&& !yyTableValueIsError(yytable_[x + yyn]))
|
||||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
yyarg[yycount++] = SymbolKind(x);
|
||||||
{
|
}
|
||||||
res ~= count++ == 0 ? ", expecting " : " or ";
|
|
||||||
res ~= format!"%s"(SymbolKind(x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
return yycount - yyoffset;
|
||||||
}]])[
|
}
|
||||||
return "syntax error";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the given <code>yypact_</code> value indicates a defaulted state.
|
* Whether the given <code>yypact_</code> value indicates a defaulted state.
|
||||||
* @@param yyvalue the value to check
|
* @@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_;
|
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.
|
* Whether the given <code>yytable_</code> value indicates a syntax error.
|
||||||
* @@param yyvalue the value to check
|
* @@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_;
|
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.
|
the symbol names.
|
||||||
@end defcv
|
@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.
|
The location of the lookahead.
|
||||||
@end deftypemethod
|
@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
|
@node D Scanner Interface
|
||||||
@subsection D Scanner Interface
|
@subsection D Scanner Interface
|
||||||
@c - %code lexer
|
@c - %code lexer
|
||||||
|
|||||||
Reference in New Issue
Block a user