[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for Dlang support 1/2] d: create the Parser.Context class
From: |
Adela Vais |
Subject: |
[PATCH for Dlang support 1/2] d: create the Parser.Context class |
Date: |
Sun, 25 Oct 2020 16:19:55 +0200 |
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.
---
data/skeletons/lalr1.d | 112 ++++++++++++++++++++++++++++++-----------
doc/bison.texi | 21 +++++++-
2 files changed, 102 insertions(+), 31 deletions(-)
diff --git a/data/skeletons/lalr1.d b/data/skeletons/lalr1.d
index 9e0095f3..9b7c786c 100644
--- a/data/skeletons/lalr1.d
+++ b/data/skeletons/lalr1.d
@@ -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_;
}
diff --git a/doc/bison.texi b/doc/bison.texi
index 67494d35..e49828c9 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -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 ???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
--
2.17.1
- [PATCH for Dlang support 1/2] d: create the Parser.Context class,
Adela Vais <=