mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-13 22:33:03 +00:00
d: make enum SymbolKind idiomatic D
Taking into account comments from H. S. Teoh. https://lists.gnu.org/r/bison-patches/2020-09/msg00021.html * data/skeletons/d.m4, data/skeletons/lalr1.d (SymbolKind): Wrap the enum in a structure that contains its string representation.
This commit is contained in:
committed by
Akim Demaille
parent
b5e6d9c4ca
commit
2bc886dc02
84
TODO
84
TODO
@@ -242,90 +242,6 @@ are. Keep the same variable names. If you change the wording in one place,
|
|||||||
do it in the others too. In other words: make sure to keep the
|
do it in the others too. In other words: make sure to keep the
|
||||||
maintenance *simple* by avoiding any gratuitous difference.
|
maintenance *simple* by avoiding any gratuitous difference.
|
||||||
|
|
||||||
** Rename the D example
|
|
||||||
Move the current content of examples/d into examples/d/simple.
|
|
||||||
|
|
||||||
** Create a second example
|
|
||||||
Duplicate examples/d/simple into examples/d/calc.
|
|
||||||
|
|
||||||
** Add location tracking to d/calc
|
|
||||||
Look at the examples in the other languages to see how to do that.
|
|
||||||
|
|
||||||
** yysymbol_name
|
|
||||||
The SymbolKind is an enum. For a given SymbolKind we want to get its string
|
|
||||||
representation. Currently it's a separate table in the parser that does
|
|
||||||
that:
|
|
||||||
|
|
||||||
/* Symbol kinds. */
|
|
||||||
public enum SymbolKind
|
|
||||||
{
|
|
||||||
S_YYEMPTY = -2, /* No symbol. */
|
|
||||||
S_YYEOF = 0, /* "end of file" */
|
|
||||||
S_YYerror = 1, /* error */
|
|
||||||
S_YYUNDEF = 2, /* "invalid token" */
|
|
||||||
S_EQ = 3, /* "=" */
|
|
||||||
...
|
|
||||||
S_input = 14, /* input */
|
|
||||||
S_line = 15, /* line */
|
|
||||||
S_exp = 16, /* exp */
|
|
||||||
};
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
|
||||||
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
|
|
||||||
private static immutable string[] yytname_ =
|
|
||||||
[
|
|
||||||
"\"end of file\"", "error", "\"invalid token\"", "\"=\"", "\"+\"",
|
|
||||||
"\"-\"", "\"*\"", "\"/\"", "\"(\"", "\")\"", "\"end of line\"",
|
|
||||||
"\"number\"", "UNARY", "$accept", "input", "line", "exp", null
|
|
||||||
];
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
So to get a symbol kind, one runs `yytname_[yykind]`.
|
|
||||||
|
|
||||||
Is there a way to attach this conversion to string to SymbolKind? In Java
|
|
||||||
for instance, we have:
|
|
||||||
|
|
||||||
public enum SymbolKind
|
|
||||||
{
|
|
||||||
S_YYEOF(0), /* "end of file" */
|
|
||||||
S_YYerror(1), /* error */
|
|
||||||
S_YYUNDEF(2), /* "invalid token" */
|
|
||||||
...
|
|
||||||
S_input(16), /* input */
|
|
||||||
S_line(17), /* line */
|
|
||||||
S_exp(18); /* exp */
|
|
||||||
|
|
||||||
private final int yycode_;
|
|
||||||
|
|
||||||
SymbolKind (int n) {
|
|
||||||
this.yycode_ = n;
|
|
||||||
}
|
|
||||||
...
|
|
||||||
/* YYNAMES_[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
|
||||||
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
|
|
||||||
private static final String[] yynames_ = yynames_init();
|
|
||||||
private static final String[] yynames_init()
|
|
||||||
{
|
|
||||||
return new String[]
|
|
||||||
{
|
|
||||||
i18n("end of file"), i18n("error"), i18n("invalid token"), "!", "+", "-", "*",
|
|
||||||
"/", "^", "(", ")", "=", i18n("end of line"), i18n("number"), "NEG",
|
|
||||||
"$accept", "input", "line", "exp", null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The user-facing name of this symbol. */
|
|
||||||
public final String getName() {
|
|
||||||
return yynames_[yycode_];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
which allows to write more naturally `yykind.getName()` rather than
|
|
||||||
`yytname_[yykind]`. Is there something comparable in (idiomatic) D?
|
|
||||||
|
|
||||||
** Change the return value of yylex
|
** Change the return value of yylex
|
||||||
Historically people were allowed to return any int from the scanner (which
|
Historically people were allowed to return any int from the scanner (which
|
||||||
is convenient and allows `return '+'` from the scanner). Akim tends to see
|
is convenient and allows `return '+'` from the scanner). Akim tends to see
|
||||||
|
|||||||
@@ -204,13 +204,72 @@ m4_define([b4_symbol_enum],
|
|||||||
# to use a signed type, which matters for yytoken.
|
# to use a signed type, which matters for yytoken.
|
||||||
m4_define([b4_declare_symbol_enum],
|
m4_define([b4_declare_symbol_enum],
|
||||||
[[ /* Symbol kinds. */
|
[[ /* Symbol kinds. */
|
||||||
public enum SymbolKind
|
struct SymbolKind
|
||||||
{
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
]b4_symbol(-2, kind_base)[ = -2, /* No symbol. */
|
]b4_symbol(-2, kind_base)[ = -2, /* No symbol. */
|
||||||
]b4_symbol_foreach([b4_symbol_enum])dnl
|
]b4_symbol_foreach([b4_symbol_enum])dnl
|
||||||
[ };
|
[ }
|
||||||
]])])
|
|
||||||
|
|
||||||
|
private int yycode_;
|
||||||
|
alias yycode_ this;
|
||||||
|
|
||||||
|
this(int code)
|
||||||
|
{
|
||||||
|
yycode_ = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
||||||
|
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
|
||||||
|
static immutable string[] yytname_ = @{
|
||||||
|
]b4_tname[
|
||||||
|
@};
|
||||||
|
|
||||||
|
/* Return YYSTR after stripping away unnecessary quotes and
|
||||||
|
backslashes, so that it's suitable for yyerror. The heuristic is
|
||||||
|
that double-quoting is unnecessary unless the string contains an
|
||||||
|
apostrophe, a comma, or backslash (other than backslash-backslash).
|
||||||
|
YYSTR is taken from yytname. */
|
||||||
|
final void toString(W)(W sink) const
|
||||||
|
if (isOutputRange!(W, char))
|
||||||
|
{
|
||||||
|
string yystr = yytname_[yycode_];
|
||||||
|
|
||||||
|
if (yystr[0] == '"')
|
||||||
|
{
|
||||||
|
string yyr;
|
||||||
|
strip_quotes:
|
||||||
|
for (int i = 1; i < yystr.length; i++)
|
||||||
|
switch (yystr[i])
|
||||||
|
{
|
||||||
|
case '\'':
|
||||||
|
case ',':
|
||||||
|
break strip_quotes;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
if (yystr[++i] != '\\')
|
||||||
|
break strip_quotes;
|
||||||
|
goto default;
|
||||||
|
default:
|
||||||
|
yyr ~= yystr[i];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
put(sink, yyr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (yystr == "$end")
|
||||||
|
{
|
||||||
|
put(sink, "end of input");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
put(sink, yystr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
# b4-case(ID, CODE, [COMMENTS])
|
# b4-case(ID, CODE, [COMMENTS])
|
||||||
|
|||||||
@@ -361,41 +361,6 @@ b4_user_union_members
|
|||||||
return YYNEWSTATE;
|
return YYNEWSTATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return YYSTR after stripping away unnecessary quotes and
|
|
||||||
backslashes, so that it's suitable for yyerror. The heuristic is
|
|
||||||
that double-quoting is unnecessary unless the string contains an
|
|
||||||
apostrophe, a comma, or backslash (other than backslash-backslash).
|
|
||||||
YYSTR is taken from yytname. */
|
|
||||||
private final string yytnamerr_ (string yystr)
|
|
||||||
{
|
|
||||||
if (yystr[0] == '"')
|
|
||||||
{
|
|
||||||
string yyr;
|
|
||||||
strip_quotes:
|
|
||||||
for (int i = 1; i < yystr.length; i++)
|
|
||||||
switch (yystr[i])
|
|
||||||
{
|
|
||||||
case '\'':
|
|
||||||
case ',':
|
|
||||||
break strip_quotes;
|
|
||||||
|
|
||||||
case '\\':
|
|
||||||
if (yystr[++i] != '\\')
|
|
||||||
break strip_quotes;
|
|
||||||
goto default;
|
|
||||||
default:
|
|
||||||
yyr ~= yystr[i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
return yyr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (yystr == "$end")
|
|
||||||
return "end of input";
|
|
||||||
|
|
||||||
return yystr;
|
|
||||||
}
|
|
||||||
]b4_parse_trace_if([[
|
]b4_parse_trace_if([[
|
||||||
/*--------------------------------.
|
/*--------------------------------.
|
||||||
| Print this symbol on YYOUTPUT. |
|
| Print this symbol on YYOUTPUT. |
|
||||||
@@ -408,12 +373,12 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
|
|||||||
if (0 < yydebug)
|
if (0 < yydebug)
|
||||||
{
|
{
|
||||||
string message = s ~ (yykind < yyntokens_ ? " token " : " nterm ")
|
string message = s ~ (yykind < yyntokens_ ? " token " : " nterm ")
|
||||||
~ yytname_[yykind] ~ " ("]b4_locations_if([
|
~ format("%s", yykind) ~ " ("]b4_locations_if([
|
||||||
~ yylocationp.toString() ~ ": "])[;
|
~ yylocationp.toString() ~ ": "])[;
|
||||||
static if (__traits(compiles, message ~= yyvaluep.toString ()))
|
static if (__traits(compiles, message ~= yyvaluep.toString()))
|
||||||
message ~= yyvaluep.toString ();
|
message ~= yyvaluep.toString();
|
||||||
else
|
else
|
||||||
message ~= format ("%s", &yyvaluep);
|
message ~= format("%s", &yyvaluep);
|
||||||
message ~= ")";
|
message ~= ")";
|
||||||
yycdebugln (message);
|
yycdebugln (message);
|
||||||
}
|
}
|
||||||
@@ -732,7 +697,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
// 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 ~= yytnamerr_ (yytname_[tok]);
|
res ~= format!"%s"(tok);
|
||||||
int yyn = yypact_[yystate];
|
int yyn = yypact_[yystate];
|
||||||
if (!yy_pact_value_is_default_ (yyn))
|
if (!yy_pact_value_is_default_ (yyn))
|
||||||
{
|
{
|
||||||
@@ -757,7 +722,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
||||||
{
|
{
|
||||||
res ~= count++ == 0 ? ", expecting " : " or ";
|
res ~= count++ == 0 ? ", expecting " : " or ";
|
||||||
res ~= yytnamerr_ (yytname_[x]);
|
res ~= format!"%s"(SymbolKind(x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -795,13 +760,6 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
|
|
||||||
]b4_parser_tables_define[
|
]b4_parser_tables_define[
|
||||||
|
|
||||||
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
|
||||||
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
|
|
||||||
private static immutable string[] yytname_ =
|
|
||||||
@{
|
|
||||||
]b4_tname[
|
|
||||||
@};
|
|
||||||
|
|
||||||
]b4_parse_trace_if([[
|
]b4_parse_trace_if([[
|
||||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||||
private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
|
private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
|
||||||
@@ -831,11 +789,10 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
}
|
}
|
||||||
]])[
|
]])[
|
||||||
|
|
||||||
private static SymbolKind yytranslate_ (int t)
|
private static auto yytranslate_ (int t)
|
||||||
{
|
{
|
||||||
]b4_api_token_raw_if(
|
]b4_api_token_raw_if(
|
||||||
[[ import std.conv : to;
|
[[ return SymbolKind(t);]],
|
||||||
return to!SymbolKind (t);]],
|
|
||||||
[[ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
|
[[ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
|
||||||
immutable ]b4_int_type_for([b4_translate])[[] translate_table =
|
immutable ]b4_int_type_for([b4_translate])[[] translate_table =
|
||||||
@{
|
@{
|
||||||
@@ -848,10 +805,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
return ]b4_symbol(0, kind)[;
|
return ]b4_symbol(0, kind)[;
|
||||||
else if (t <= code_max)
|
else if (t <= code_max)
|
||||||
{
|
return SymbolKind(translate_table[t]);
|
||||||
import std.conv : to;
|
|
||||||
return to!SymbolKind (translate_table[t]);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return ]b4_symbol(2, kind)[;]])[
|
return ]b4_symbol(2, kind)[;]])[
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user