java: use SymbolType

The Java enums are very different from the C model.  As a consequence,
one cannot "build" an enum directly from an integer, we must retrieve
it.  That's the purpose of the SymbolType.get class method.

* data/skeletons/java.m4 (b4_symbol_enum, b4_case_code_symbol)
(b4_declare_symbol_enum): New.
* data/skeletons/lalr1.java: Use SymbolType,
SymbolType.YYSYMBOL_YYEMPTY, etc.
* examples/java/calc/Calc.y, tests/local.at: Adjust.
This commit is contained in:
Akim Demaille
2020-03-30 07:45:01 +02:00
parent 7fa23136ca
commit ad31c3cdf4
5 changed files with 102 additions and 48 deletions

3
TODO
View File

@@ -5,6 +5,9 @@
- YYNOMEM - YYNOMEM
- i18n in Java - i18n in Java
** Java
Check api.token.raw
** Naming conventions ** Naming conventions
yysyntax_error_arguments should be yy_syntax_error_arguments, since it's a yysyntax_error_arguments should be yy_syntax_error_arguments, since it's a
private implementation detail. private implementation detail.

View File

@@ -128,9 +128,9 @@ m4_define([b4_integral_parser_table_define],
[b4_typed_parser_table_define([b4_int_type_for([$2])], [$1], [$2], [$3])]) [b4_typed_parser_table_define([b4_int_type_for([$2])], [$1], [$2], [$3])])
## ------------------------- ## ## -------------------------- ##
## Assigning token numbers. ## ## (External) token numbers. ##
## ------------------------- ## ## -------------------------- ##
# b4_token_enum(TOKEN-NUM) # b4_token_enum(TOKEN-NUM)
# ------------------------ # ------------------------
@@ -147,7 +147,58 @@ m4_define([b4_token_enums],
[b4_any_token_visible_if([/* Tokens. */ [b4_any_token_visible_if([/* Tokens. */
b4_symbol_foreach([b4_token_enum])])]) b4_symbol_foreach([b4_token_enum])])])
# b4-case(ID, CODE)
## --------------------------- ##
## (Internal) symbol numbers. ##
## --------------------------- ##
# b4_symbol_enum(SYMBOL-NUM)
# --------------------------
# Output the definition of this symbol as an enum.
m4_define([b4_symbol_enum],
[m4_ifval(b4_symbol([$1], [sid]),
[m4_format([[%s(%s)]],
b4_symbol([$1], [sid]),
b4_symbol([$1], [number]))])])
m4_define([b4_case_code_symbol],
[[ case $1: return SymbolType.]b4_symbol([$1], [sid]);
])
# b4_declare_symbol_enum
# ----------------------
# The definition of the symbol internal numbers as an enum.
m4_define([b4_declare_symbol_enum],
[[ public enum SymbolType
{
]m4_join([,
],
]b4_symbol_sid([-2])[(-2),
b4_symbol_map([b4_symbol_enum]),
[YYNTOKENS(]b4_tokens_number[); ///< Number of tokens.])[
private int code;
SymbolType (int n) {
this.code = n;
}
static SymbolType get (int code) {
switch (code) {
default: return YYSYMBOL_YYUNDEF;
]b4_symbol_foreach([b4_case_code_symbol])[
}
}
int getCode () {
return this.code;
}
};
]])])
# b4_case(ID, CODE)
# ----------------- # -----------------
# We need to fool Java's stupid unreachable code detection. # We need to fool Java's stupid unreachable code detection.
m4_define([b4_case], m4_define([b4_case],
@@ -157,6 +208,7 @@ m4_define([b4_case],
break; break;
]) ])
# b4_predicate_case(LABEL, CONDITIONS) # b4_predicate_case(LABEL, CONDITIONS)
# ------------------------------------ # ------------------------------------
m4_define([b4_predicate_case], m4_define([b4_predicate_case],

View File

@@ -55,7 +55,7 @@ b4_use_push_for_pull_if([
m4_define([b4_define_state],[[ m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */ /* Lookahead and lookahead in internal form. */
int yychar = yyempty_; int yychar = yyempty_;
int yytoken = 0; SymbolType yytoken = SymbolType.YYSYMBOL_YYEMPTY;
/* State. */ /* State. */
int yyn = 0; int yyn = 0;
@@ -171,6 +171,8 @@ import java.text.MessageFormat;
return new ]b4_location_type[ (rhs.locationAt (0).end); return new ]b4_location_type[ (rhs.locationAt (0).end);
}]])[ }]])[
]b4_declare_symbol_enum[
/** /**
* Communication interface between the scanner and the Bison-generated * Communication interface between the scanner and the Bison-generated
* parser <tt>]b4_parser_class[</tt>. * parser <tt>]b4_parser_class[</tt>.
@@ -482,7 +484,7 @@ import java.text.MessageFormat;
default: break; default: break;
}]b4_parse_trace_if([[ }]b4_parse_trace_if([[
yySymbolPrint ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);]])[ yySymbolPrint ("-> $$ =", SymbolType.get (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
yystack.pop (yylen); yystack.pop (yylen);
yylen = 0; yylen = 0;
@@ -497,11 +499,11 @@ import java.text.MessageFormat;
| Print this symbol on YYOUTPUT. | | Print this symbol on YYOUTPUT. |
`--------------------------------*/ `--------------------------------*/
private void yySymbolPrint (String s, int yytype, private void yySymbolPrint (String s, SymbolType yytype,
]b4_yystype[ yyvaluep]dnl ]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[) b4_locations_if([, Object yylocationp])[)
{ {
yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ") yycdebug (s + (yytype.getCode () < yyntokens_ ? " token " : " nterm ")
+ yysymbolName (yytype) + " ("]b4_locations_if([ + yysymbolName (yytype) + " ("]b4_locations_if([
+ yylocationp + ": "])[ + yylocationp + ": "])[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")"); + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
@@ -611,8 +613,8 @@ b4_dollar_popdef[]dnl
/* If the proper action on seeing token YYTOKEN is to reduce or to /* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */ detect an error, take that action. */
yyn += yytoken; yyn += yytoken.getCode ();
if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken.getCode ())
label = YYDEFAULT; label = YYDEFAULT;
/* <= 0 means reduce or error. */ /* <= 0 means reduce or error. */
@@ -676,7 +678,7 @@ b4_dollar_popdef[]dnl
{ {
++yynerrs; ++yynerrs;
if (yychar == yyempty_) if (yychar == yyempty_)
yytoken = yyempty_; yytoken = SymbolType.YYSYMBOL_YYEMPTY;
yyreportSyntaxError (new Context (yystack, yytoken]b4_locations_if([[, yylloc]])[)); yyreportSyntaxError (new Context (yystack, yytoken]b4_locations_if([[, yylloc]])[));
} }
@@ -726,8 +728,9 @@ b4_dollar_popdef[]dnl
yyn = yypact_[yystate]; yyn = yypact_[yystate];
if (!yyPactValueIsDefault (yyn)) if (!yyPactValueIsDefault (yyn))
{ {
yyn += yy_error_token_; yyn += SymbolType.YYSYMBOL_YYERROR.getCode ();
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yy_error_token_) if (0 <= yyn && yyn <= yylast_
&& yycheck_[yyn] == SymbolType.YYSYMBOL_YYERROR.getCode ())
{ {
yyn = yytable_[yyn]; yyn = yytable_[yyn];
if (0 < yyn) if (0 < yyn)
@@ -760,7 +763,7 @@ b4_dollar_popdef[]dnl
yystack.pop (2);]])[ yystack.pop (2);]])[
/* Shift the error token. */]b4_parse_trace_if([[ /* Shift the error token. */]b4_parse_trace_if([[
yySymbolPrint ("Shifting", yystos_[yyn], yySymbolPrint ("Shifting", SymbolType.get (yystos_[yyn]),
yylval]b4_locations_if([, yyloc])[);]])[ yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn; yystate = yyn;
@@ -789,7 +792,7 @@ b4_dollar_popdef[]dnl
{ {
/* Lookahead and lookahead in internal form. */ /* Lookahead and lookahead in internal form. */
this.yychar = yyempty_; this.yychar = yyempty_;
this.yytoken = 0; this.yytoken = SymbolType.YYSYMBOL_YYEMPTY;
/* State. */ /* State. */
this.yyn = 0; this.yyn = 0;
@@ -861,7 +864,7 @@ b4_dollar_popdef[]dnl
*/ */
public static final class Context public static final class Context
{ {
Context (YYStack stack, int token]b4_locations_if([[, ]b4_location_type[ loc]])[) Context (YYStack stack, SymbolType token]b4_locations_if([[, ]b4_location_type[ loc]])[)
{ {
yystack = stack; yystack = stack;
yytoken = token;]b4_locations_if([[ yytoken = token;]b4_locations_if([[
@@ -870,7 +873,7 @@ b4_dollar_popdef[]dnl
private YYStack yystack; private YYStack yystack;
public int getToken () public SymbolType getToken ()
{ {
return yytoken; return yytoken;
} }
@@ -880,7 +883,7 @@ b4_dollar_popdef[]dnl
*/ */
public static final int EMPTY = ]b4_parser_class[.yyempty_; public static final int EMPTY = ]b4_parser_class[.yyempty_;
private int yytoken;]b4_locations_if([[ private SymbolType yytoken;]b4_locations_if([[
public ]b4_location_type[ getLocation () public ]b4_location_type[ getLocation ()
{ {
return yylocation; return yylocation;
@@ -893,12 +896,12 @@ b4_dollar_popdef[]dnl
current YYCTX, and return the number of tokens stored in YYARG. If current YYCTX, and return the number of tokens stored in YYARG. If
YYARG is null, return the number of expected tokens (guaranteed to YYARG is null, return the number of expected tokens (guaranteed to
be less than YYNTOKENS). */ be less than YYNTOKENS). */
int yyexpectedTokens (int yyarg[], int yyargn) int yyexpectedTokens (SymbolType yyarg[], int yyargn)
{ {
return yyexpectedTokens (yyarg, 0, yyargn); return yyexpectedTokens (yyarg, 0, yyargn);
} }
int yyexpectedTokens (int yyarg[], int yyoffset, int yyargn) int yyexpectedTokens (SymbolType yyarg[], int yyoffset, int yyargn)
{ {
int yycount = yyoffset; int yycount = yyoffset;
int yyn = yypact_[this.yystack.stateAt (0)]; int yyn = yypact_[this.yystack.stateAt (0)];
@@ -912,16 +915,16 @@ b4_dollar_popdef[]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 < NTOKENS ? yychecklim : NTOKENS; int yyxend = yychecklim < NTOKENS ? yychecklim : NTOKENS;
for (int x = yyxbegin; x < yyxend; ++x) for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck_[x + yyn] == x && x != yy_error_token_ if (yycheck_[yyx + yyn] == yyx && yyx != SymbolType.YYSYMBOL_YYERROR.getCode ()
&& !yyTableValueIsError (yytable_[x + yyn])) && !yyTableValueIsError (yytable_[yyx + yyn]))
{ {
if (yyarg == null) if (yyarg == null)
yycount += 1; yycount += 1;
else if (yycount == yyargn) else if (yycount == yyargn)
return 0; // FIXME: this is incorrect. return 0; // FIXME: this is incorrect.
else else
yyarg[yycount++] = x; yyarg[yycount++] = SymbolType.get (yyx);
} }
} }
return yycount - yyoffset; return yycount - yyoffset;
@@ -929,7 +932,7 @@ b4_dollar_popdef[]dnl
/* The user-facing name of the symbol whose (internal) number is /* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */ YYSYMBOL. No bounds checking. */
static String yysymbolName (int yysymbol) static String yysymbolName (SymbolType yysymbol)
{ {
return ]b4_parser_class[.yysymbolName (yysymbol); return ]b4_parser_class[.yysymbolName (yysymbol);
} }
@@ -937,7 +940,7 @@ b4_dollar_popdef[]dnl
]b4_parse_error_bmatch( ]b4_parse_error_bmatch(
[detailed\|verbose], [[ [detailed\|verbose], [[
private int yysyntaxErrorArguments (Context yyctx, int[] yyarg, int yyargn) private int yysyntaxErrorArguments (Context yyctx, SymbolType[] yyarg, int yyargn)
{ {
/* There are many possibilities here to consider: /* There are many possibilities here to consider:
- If this state is a consistent state with a default action, - If this state is a consistent state with a default action,
@@ -966,7 +969,7 @@ b4_dollar_popdef[]dnl
to an error action in a later state. to an error action in a later state.
*/ */
int yycount = 0; int yycount = 0;
if (yyctx.getToken () != yyempty_) if (yyctx.getToken () != SymbolType.YYSYMBOL_YYEMPTY)
{ {
yyarg[yycount++] = yyctx.getToken (); yyarg[yycount++] = yyctx.getToken ();
yycount += yyctx.yyexpectedTokens (yyarg, 1, yyargn); yycount += yyctx.yyexpectedTokens (yyarg, 1, yyargn);
@@ -986,7 +989,7 @@ b4_dollar_popdef[]dnl
if (yyErrorVerbose) if (yyErrorVerbose)
{ {
final int argmax = 5; final int argmax = 5;
int[] yyarg = new int[argmax]; SymbolType[] yyarg = new SymbolType[argmax];
int yycount = yysyntaxErrorArguments (yyctx, yyarg, argmax); int yycount = yysyntaxErrorArguments (yyctx, yyarg, argmax);
String[] yystr = new String[yycount]; String[] yystr = new String[yycount];
for (int yyi = 0; yyi < yycount; ++yyi) for (int yyi = 0; yyi < yycount; ++yyi)
@@ -1077,21 +1080,21 @@ b4_dollar_popdef[]dnl
/* The user-facing name of the symbol whose (internal) number is /* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */ YYSYMBOL. No bounds checking. */
static String yysymbolName (int yysymbol) static String yysymbolName (SymbolType yysymbol)
{ {
return yytnamerr_ (yytname_[yysymbol]); return yytnamerr_ (yytname_[yysymbol.getCode ()]);
} }
]], ]],
[custom\|detailed], [custom\|detailed],
[[ /* The user-facing name of the symbol whose (internal) number is [[ /* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */ YYSYMBOL. No bounds checking. */
static String yysymbolName (int yysymbol) static String yysymbolName (SymbolType yysymbol)
{ {
String[] yy_sname = String[] yy_sname =
{ {
]b4_symbol_names[ ]b4_symbol_names[
}; };
return yy_sname[yysymbol]; return yy_sname[yysymbol.getCode ()];
}]])[ }]])[
]b4_parse_trace_if([[ ]b4_parse_trace_if([[
@@ -1114,35 +1117,31 @@ b4_dollar_popdef[]dnl
/* The symbols being reduced. */ /* The symbols being reduced. */
for (int yyi = 0; yyi < yynrhs; yyi++) for (int yyi = 0; yyi < yynrhs; yyi++)
yySymbolPrint (" $" + (yyi + 1) + " =", yySymbolPrint (" $" + (yyi + 1) + " =",
yystos_[yystack.stateAt (yynrhs - (yyi + 1))], SymbolType.get (yystos_[yystack.stateAt (yynrhs - (yyi + 1))]),
]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([, ]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[); b4_rhs_location(yynrhs, yyi + 1)])[);
}]])[ }]])[
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t) private static final SymbolType yytranslate_ (int t)
]b4_api_token_raw_if(dnl ]b4_api_token_raw_if(dnl
[[ { [[ {
return t; return SymbolType.get (t);
} }
]], ]],
[[ { [[ {
int user_token_number_max_ = ]b4_user_token_number_max[; int user_token_number_max_ = ]b4_user_token_number_max[;
]b4_int_type_for([b4_translate])[ undef_token_ = ]b4_undef_token_number[;
if (t <= 0) if (t <= 0)
return Lexer.EOF; return SymbolType.YYSYMBOL_YYEOF;
else if (t <= user_token_number_max_) else if (t <= user_token_number_max_)
return yytranslate_table_[t]; return SymbolType.get (yytranslate_table_[t]);
else else
return undef_token_; return SymbolType.YYSYMBOL_YYUNDEF;
} }
]b4_integral_parser_table_define([translate_table], [b4_translate])[ ]b4_integral_parser_table_define([translate_table], [b4_translate])[
]])[ ]])[
private static final ]b4_int_type_for([b4_translate])[ yy_error_token_ = 1;
private static final int yylast_ = ]b4_last[; private static final int yylast_ = ]b4_last[;
private static final int yynnts_ = ]b4_nterms_number[; private static final int yynnts_ = ]b4_nterms_number[;
private static final int yyempty_ = -2; private static final int yyempty_ = -2;

View File

@@ -121,15 +121,15 @@ class CalcLexer implements Calc.Lexer {
System.err.print (ctx.getLocation () + ": syntax error"); System.err.print (ctx.getLocation () + ": syntax error");
{ {
final int TOKENMAX = 10; final int TOKENMAX = 10;
int[] arg = new int[TOKENMAX]; Calc.SymbolType[] arg = new Calc.SymbolType[TOKENMAX];
int n = ctx.yyexpectedTokens (arg, TOKENMAX); int n = ctx.yyexpectedTokens (arg, TOKENMAX);
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
System.err.print ((i == 0 ? ": expected " : " or ") System.err.print ((i == 0 ? ": expected " : " or ")
+ ctx.yysymbolName (arg[i])); + ctx.yysymbolName (arg[i]));
} }
{ {
int lookahead = ctx.getToken (); Calc.SymbolType lookahead = ctx.getToken ();
if (lookahead != ctx.EMPTY) if (lookahead != Calc.SymbolType.YYSYMBOL_YYEMPTY)
System.err.print (" before " + ctx.yysymbolName (lookahead)); System.err.print (" before " + ctx.yysymbolName (lookahead));
} }
System.err.println (""); System.err.println ("");

View File

@@ -975,12 +975,12 @@ m4_define([AT_YYERROR_DEFINE(java)],
System.err.print (]AT_LOCATION_IF([[ctx.getLocation () + ": "]] System.err.print (]AT_LOCATION_IF([[ctx.getLocation () + ": "]]
+ )["syntax error"); + )["syntax error");
{ {
int token = ctx.getToken (); Calc.SymbolType token = ctx.getToken ();
if (token != ctx.EMPTY) if (token != Calc.SymbolType.YYSYMBOL_YYEMPTY)
System.err.print (" on token @<:@" + ctx.yysymbolName (token) + "@:>@"); System.err.print (" on token @<:@" + ctx.yysymbolName (token) + "@:>@");
} }
{ {
int[] arg = new int[ctx.NTOKENS]; Calc.SymbolType[] arg = new Calc.SymbolType[ctx.NTOKENS];
int n = ctx.yyexpectedTokens (arg, ctx.NTOKENS); int n = ctx.yyexpectedTokens (arg, ctx.NTOKENS);
if (0 < n) if (0 < n)
{ {