diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-02-08 15:36:18 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-02-08 16:17:53 +0100 |
commit | 80a43893774263ad5db12883eb35af2d882898e6 (patch) | |
tree | 65e9773c9bda5ddf06049cb5ce114d07c11de63a | |
parent | ef097719eaf5ca80c18c101f21d57741f8178be9 (diff) | |
download | bison-80a43893774263ad5db12883eb35af2d882898e6.tar.gz |
java: provide Context with a more OO interface
* data/skeletons/lalr1.java (yyexpectedTokens)
(yysyntaxErrorArguments): Make them methods of Context.
(Context.yysymbolName): New.
* tests/local.at: Adjust.
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | data/skeletons/lalr1.java | 151 | ||||
-rw-r--r-- | examples/java/calc/Calc.y | 6 | ||||
-rw-r--r-- | tests/local.at | 6 |
4 files changed, 91 insertions, 80 deletions
@@ -18,6 +18,14 @@ We should be able to redefine EOF like we do in C. ** Java: calc.at Stop hard-coding "Calc". Adjust local.at (look for FIXME). +** Java: _ +We must not use _ in Java, it is becoming a keyword in Java 9. + +examples/java/calc/Calc.java:998: warning: '_' used as an identifier + "$end", "error", "$undefined", _("end of line"), _("number"), "'='", + ^ + (use of '_' as an identifier might not be supported in releases after Java SE 8) + ** doc I feel it's ugly to use the GNU style to declare functions in the doc. It generates tons of white space in the page, and may contribute to bad page diff --git a/data/skeletons/lalr1.java b/data/skeletons/lalr1.java index a9725d7b..3b476ff8 100644 --- a/data/skeletons/lalr1.java +++ b/data/skeletons/lalr1.java @@ -866,80 +866,83 @@ b4_dollar_popdef[]dnl public int yytoken;]b4_locations_if([[ public ]b4_location_type[ yylocation;]])[ public static final int yyntokens = ]b4_parser_class[.yyntokens_; - }; - - /* 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_). */ - static int - yyexpectedTokens (Context yyctx, - int yyarg[], int yyoffset, int yyargn) - { - int yycount = yyoffset; - int yyn = yypact_[yyctx.yystack.stateAt (0)]; - if (!yyPactValueIsDefault (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative - indexes in YYCHECK. In other words, skip the first - -YYN actions for this state because they are default - actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = yylast_ - yyn + 1; - int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_; - for (int x = yyxbegin; x < yyxend; ++x) - if (yycheck_[x + yyn] == x && x != yy_error_token_ - && !yyTableValueIsError (yytable_[x + yyn])) - { - if (yyarg == null) - yycount += 1; - else if (yycount == yyargn) - return 0; // FIXME: this is incorrect. - else - yyarg[yycount++] = x; - } - } - return yycount - yyoffset; - } - static int - yysyntaxErrorArguments (Context yyctx, - int[] yyarg, int yyargn) - { - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, - then the only way this function was invoked is if the - default action is an error action. In that case, don't - check for expected tokens because there are none. - - The only way there can be no lookahead present (in tok) is - if this state is a consistent state with a default action. - Thus, detecting the absence of a lookahead is sufficient to - determine that there is no unexpected or expected token to - report. In that case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this - state is a consistent state with a default action. There - might have been a previous inconsistent state, consistent - state with a non-default action, or user semantic action - that manipulated yychar. (However, yychar is currently out - of scope during semantic actions.) - - Of course, the expected token list depends on states to - have correct lookahead information, and it depends on the - parser not to perform extra reductions after fetching a - lookahead from the scanner and before detecting a syntax - error. Thus, state merging (from LALR or IELR) and default - reductions corrupt the expected token list. However, the - list is correct for canonical LR with one exception: it - will still contain any token that will not be accepted due - to an error action in a later state. - */ - int yycount = 0; - if (yyctx.yytoken != yyempty_) - { - yyarg[yycount++] = yyctx.yytoken; - yycount += yyexpectedTokens (yyctx, yyarg, 1, yyargn); - } - return yycount; + /* 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 yyexpectedTokens (int 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 + -YYN actions for this state because they are default + actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = yylast_ - yyn + 1; + int yyxend = yychecklim < yyntokens ? yychecklim : yyntokens; + for (int x = yyxbegin; x < yyxend; ++x) + if (yycheck_[x + yyn] == x && x != yy_error_token_ + && !yyTableValueIsError (yytable_[x + yyn])) + { + if (yyarg == null) + yycount += 1; + else if (yycount == yyargn) + return 0; // FIXME: this is incorrect. + else + yyarg[yycount++] = x; + } + } + return yycount - yyoffset; + } + + /* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ + static String yysymbolName (int yysymbol) + { + return ]b4_parser_class[.yysymbolName (yysymbol); + } + + int yysyntaxErrorArguments (int[] yyarg, int yyargn) + { + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, + then the only way this function was invoked is if the + default action is an error action. In that case, don't + check for expected tokens because there are none. + - The only way there can be no lookahead present (in tok) is + if this state is a consistent state with a default action. + Thus, detecting the absence of a lookahead is sufficient to + determine that there is no unexpected or expected token to + report. In that case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this + state is a consistent state with a default action. There + might have been a previous inconsistent state, consistent + state with a non-default action, or user semantic action + that manipulated yychar. (However, yychar is currently out + of scope during semantic actions.) + - Of course, the expected token list depends on states to + have correct lookahead information, and it depends on the + parser not to perform extra reductions after fetching a + lookahead from the scanner and before detecting a syntax + error. Thus, state merging (from LALR or IELR) and default + reductions corrupt the expected token list. However, the + list is correct for canonical LR with one exception: it + will still contain any token that will not be accepted due + to an error action in a later state. + */ + int yycount = 0; + if (this.yytoken != yyempty_) + { + yyarg[yycount++] = this.yytoken; + yycount += this.yyexpectedTokens (yyarg, 1, yyargn); + } + return yycount; + } } /** @@ -954,7 +957,7 @@ b4_dollar_popdef[]dnl { final int argmax = 5; int[] yyarg = new int[argmax]; - int yycount = yysyntaxErrorArguments (yyctx, yyarg, argmax); + int yycount = yyctx.yysyntaxErrorArguments (yyarg, argmax); String[] yystr = new String[yycount]; for (int yyi = 0; yyi < yycount; ++yyi) yystr[yyi] = yysymbolName (yyarg[yyi]); diff --git a/examples/java/calc/Calc.y b/examples/java/calc/Calc.y index bc832aba..b1d21ac7 100644 --- a/examples/java/calc/Calc.y +++ b/examples/java/calc/Calc.y @@ -110,13 +110,13 @@ class CalcLexer implements Calc.Lexer { { final int ARGMAX = 10; int[] arg = new int[ARGMAX]; - int n = Calc.yysyntaxErrorArguments (ctx, arg, ARGMAX); + int n = ctx.yysyntaxErrorArguments (arg, ARGMAX); System.err.print (ctx.yylocation + ": syntax error"); for (int i = 1; i < n; ++i) System.err.print ((i == 1 ? ": expected " : " or ") - + Calc.yysymbolName (arg[i])); + + ctx.yysymbolName (arg[i])); if (n != 0) - System.err.print (" before " + Calc.yysymbolName (arg[0])); + System.err.print (" before " + ctx.yysymbolName (arg[0])); System.err.println (""); } diff --git a/tests/local.at b/tests/local.at index 097197d5..d35bbf68 100644 --- a/tests/local.at +++ b/tests/local.at @@ -934,14 +934,14 @@ m4_define([AT_YYERROR_DEFINE(java)], public void yyreportSyntaxError (Calc.Context ctx) { int[] arg = new int[ctx.yyntokens]; - int n = Calc.yysyntaxErrorArguments (ctx, arg, ctx.yyntokens); + int n = ctx.yysyntaxErrorArguments (arg, ctx.yyntokens); System.err.print (]AT_LOCATION_IF([[ctx.yylocation + ": "]] - + )["syntax error on token @<:@" + Calc.yysymbolName(arg[0]) + "@:>@"); + + )["syntax error on token @<:@" + ctx.yysymbolName (arg[0]) + "@:>@"); if (1 < n) { System.err.print (" (expected:"); for (int i = 1; i < n; ++i) - System.err.print (" @<:@" + Calc.yysymbolName (arg[i]) + "@:>@"); + System.err.print (" @<:@" + ctx.yysymbolName (arg[i]) + "@:>@"); System.err.print (")"); } System.err.println (""); |