diff --git a/TODO b/TODO index e50461e0..45263e10 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,11 @@ The calc.at test should call yyerror with location: yyerror (]AT_LOCATION_IF([[@$, ]])["calc: error: " + $1 + " != " + $3); } +** Java: EOF +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). ** doc I feel it's ugly to use the GNU style to declare functions in the doc. It diff --git a/data/skeletons/lalr1.java b/data/skeletons/lalr1.java index c5095ce1..a9725d7b 100644 --- a/data/skeletons/lalr1.java +++ b/data/skeletons/lalr1.java @@ -91,8 +91,10 @@ import java.text.MessageFormat; */ ]b4_parser_class_declaration[ { - ]b4_identification[ -]b4_error_verbose_if([[ +]b4_identification[ +][ +]m4_bmatch(b4_percent_define_get([[parse.error]]), + [detailed\|verbose], [[ /** * True if verbose error messages are enabled. */ @@ -161,9 +163,6 @@ import java.text.MessageFormat; } } -]])[ - -]b4_locations_if([[ private ]b4_location_type[ yylloc (YYStack rhs, int n) { if (0 < n) @@ -181,8 +180,8 @@ import java.text.MessageFormat; public static final int EOF = 0; ]b4_token_enums[ - -]b4_locations_if([[/** +]b4_locations_if([[ + /** * Method to retrieve the beginning position of the last scanned token. * @@return the position at which the last scanned token starts. */ @@ -217,7 +216,12 @@ import java.text.MessageFormat; * @@param msg The string for the error message. */ void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg); - } + +]m4_bmatch(b4_percent_define_get([[parse.error]]), + [custom], [[ + void yyreportSyntaxError (][Context yyctx); +]])[ +} ]b4_lexer_if([[ private class YYLexer implements Lexer { @@ -676,8 +680,9 @@ b4_dollar_popdef[]dnl yytoken = yyempty_; Context yyctx = new Context (); yyctx.yystack = yystack; - yyctx.yytoken = yytoken; - yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yyctx)); + yyctx.yytoken = yytoken;]b4_locations_if([[ + yyctx.yylocation = yylloc;]])[ + yyreportSyntaxError (yyctx); } ]b4_locations_if([[ @@ -858,13 +863,15 @@ b4_dollar_popdef[]dnl public static final class Context { public YYStack yystack; - public int yytoken; + 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). */ + be less than YYNTOKENS_). */ static int yyexpectedTokens (Context yyctx, int yyarg[], int yyoffset, int yyargn) @@ -935,13 +942,19 @@ b4_dollar_popdef[]dnl return yycount; } - // Generate an error message. - private String yysyntax_error (Context yyctx) - {]b4_error_verbose_if([[ + /** + * Report a syntax error. + */ + private void yyreportSyntaxError (Context yyctx) + {]m4_bmatch(b4_percent_define_get([parse.error]), +[custom], [[ + yylexer.yyreportSyntaxError (yyctx);]], +[detailed\|verbose], [[ if (yyErrorVerbose) { - int[] yyarg = new int[5]; - int yycount = yysyntaxErrorArguments (yyctx, yyarg, 5); + final int argmax = 5; + int[] yyarg = new int[argmax]; + int yycount = yysyntaxErrorArguments (yyctx, yyarg, argmax); String[] yystr = new String[yycount]; for (int yyi = 0; yyi < yycount; ++yyi) yystr[yyi] = yysymbolName (yyarg[yyi]); @@ -956,10 +969,12 @@ b4_dollar_popdef[]dnl case 4: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3}"])[; break; case 5: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3} or {4}"])[; break; } - return new MessageFormat (yyformat).format (yystr); + yyerror (]b4_locations_if([[yyctx.yylocation, ]])[new MessageFormat (yyformat).format (yystr)); + return; } -]])[ - return "syntax error"; + yyerror (]b4_locations_if([[yyctx.yylocation, ]])["syntax error");]], +[simple], [[ + yyerror (]b4_locations_if([[yyctx.yylocation, ]])["syntax error");]])[ } /** diff --git a/examples/c/bistromathic/bistromathic.test b/examples/c/bistromathic/bistromathic.test index 89ebcb40..116c7575 100755 --- a/examples/c/bistromathic/bistromathic.test +++ b/examples/c/bistromathic/bistromathic.test @@ -45,9 +45,9 @@ run 0 '0.16 cat >input <input <input <input < NUM "number" +%token + '\n' _("end of line") + NUM _("number") %type exp %nonassoc '=' /* comparison */ @@ -73,7 +80,6 @@ exp: | '-' error { $$ = 0; return YYERROR; } ; - %% class CalcLexer implements Calc.Lexer { @@ -100,6 +106,20 @@ class CalcLexer implements Calc.Lexer { return end; } + public void yyreportSyntaxError (Calc.Context ctx) + { + final int ARGMAX = 10; + int[] arg = new int[ARGMAX]; + int n = Calc.yysyntaxErrorArguments (ctx, 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])); + if (n != 0) + System.err.print (" before " + Calc.yysymbolName (arg[0])); + System.err.println (""); + } + public void yyerror (Calc.Location l, String s) { if (l == null) diff --git a/tests/calc.at b/tests/calc.at index 25a1c806..1754b6f8 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -1185,8 +1185,11 @@ m4_define([AT_CHECK_CALC_LALR1_JAVA], [AT_CHECK_CALC([%language "Java" $1], [$2])]) AT_CHECK_CALC_LALR1_JAVA +AT_CHECK_CALC_LALR1_JAVA([%define parse.error custom]) AT_CHECK_CALC_LALR1_JAVA([%define parse.error detailed]) AT_CHECK_CALC_LALR1_JAVA([%define parse.error verbose]) +AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error custom]) +AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error detailed]) AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error verbose]) AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose]) AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is}]) diff --git a/tests/local.at b/tests/local.at index 9b6c203f..097197d5 100644 --- a/tests/local.at +++ b/tests/local.at @@ -908,6 +908,9 @@ class PositionReader extends BufferedReader { }]]) +# AT_YYERROR_DEFINE(java) +# ----------------------- +# FIXME: We should not hard-code "Calc". m4_define([AT_YYERROR_DEFINE(java)], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String m) {]m4_bmatch(m4_defn([AT_PARSE_PARAMS]), [nerrs],[[ @@ -925,6 +928,24 @@ m4_define([AT_YYERROR_DEFINE(java)], ++*nerrs;]])[ System.err.println (m); } +]])[ + +]AT_ERROR_CUSTOM_IF([[ + public void yyreportSyntaxError (Calc.Context ctx) + { + int[] arg = new int[ctx.yyntokens]; + int n = Calc.yysyntaxErrorArguments (ctx, arg, ctx.yyntokens); + System.err.print (]AT_LOCATION_IF([[ctx.yylocation + ": "]] + + )["syntax error on token @<:@" + Calc.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 (")"); + } + System.err.println (""); + } ]]) ]) @@ -962,6 +983,8 @@ m4_define([AT_MAIN_DEFINE(java)], m4_define([AT_LANG_FOR_EACH_STD(java)], [$1]) + + ## --------------- ## ## Running Bison. ## ## --------------- ##