summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-02-08 14:19:03 +0100
committerAkim Demaille <akim.demaille@gmail.com>2020-02-08 16:03:50 +0100
commitef097719eaf5ca80c18c101f21d57741f8178be9 (patch)
tree46fcf499033b8fbae1456d94c4716aee5ca661a1
parent0c90c597950759573ec08fd6669425bd41083e5e (diff)
downloadbison-ef097719eaf5ca80c18c101f21d57741f8178be9.tar.gz
java: add support for parse.error custom
* data/skeletons/lalr1.java: Add support for custom parse errors. (yyntokens_): Make it public. Under... (yyntokens): this name. (Context): Capture the location too. * examples/c/bistromathic/parse.y, * examples/c/bistromathic/bistromathic.test: Improve error message. * examples/java/calc/Calc.test, examples/java/calc/Calc.y: Use custom error messages. * tests/calc.at, tests/local.at: Check custom error messages.
-rw-r--r--TODO5
-rw-r--r--data/skeletons/lalr1.java55
-rwxr-xr-xexamples/c/bistromathic/bistromathic.test4
-rw-r--r--examples/c/bistromathic/parse.y4
-rw-r--r--examples/java/calc/Calc.test4
-rw-r--r--examples/java/calc/Calc.y26
-rw-r--r--tests/calc.at3
-rw-r--r--tests/local.at23
8 files changed, 95 insertions, 29 deletions
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 <<EOF
*
EOF
-run 0 "err: 1.1: syntax error expected end of file or - or ( or end of line or double precision number or function or variable before *"
+run 0 "err: 1.1: syntax error: expected end of file or - or ( or end of line or double precision number or function or variable before *"
cat >input <<EOF
1 + 2 * * 3
EOF
-run 0 "err: 1.9: syntax error expected - or ( or double precision number or function or variable before *"
+run 0 "err: 1.9: syntax error: expected - or ( or double precision number or function or variable before *"
diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y
index cac38f32..1fa9c081 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -200,8 +200,8 @@ yyreport_syntax_error (const yyparse_context_t *ctx)
YY_LOCATION_PRINT (stderr, *yyparse_context_location (ctx));
fprintf (stderr, ": syntax error");
for (int i = 1; i < n; ++i)
- fprintf (stderr, " %s %s",
- i == 1 ? "expected" : "or", yysymbol_name (arg[i]));
+ fprintf (stderr, "%s %s",
+ i == 1 ? ": expected" : " or", yysymbol_name (arg[i]));
if (n)
fprintf (stderr, " before %s", yysymbol_name (arg[0]));
fprintf (stderr, "\n");
diff --git a/examples/java/calc/Calc.test b/examples/java/calc/Calc.test
index 8664e314..7d96015a 100644
--- a/examples/java/calc/Calc.test
+++ b/examples/java/calc/Calc.test
@@ -30,9 +30,9 @@ run 0 '7
cat >input <<EOF
1 + 2 * * 3
EOF
-run 0 "err: 1.9-1.10: syntax error, unexpected '*', expecting number or '-' or '(' or '!'"
+run 0 "err: 1.9-1.10: syntax error: expected number or '-' or '(' or '!' before '*'"
cat >input <<EOF
12 222
EOF
-run 0 "err: 1.6-1.9: syntax error, unexpected number"
+run 0 "err: 1.6-1.9: syntax error: expected end of line or '=' or '-' or '+' or '*' or '/' or '^' before number"
diff --git a/examples/java/calc/Calc.y b/examples/java/calc/Calc.y
index 2ae09bad..bc832aba 100644
--- a/examples/java/calc/Calc.y
+++ b/examples/java/calc/Calc.y
@@ -3,7 +3,7 @@
%define api.parser.class {Calc}
%define api.parser.public
-%define parse.error detailed
+%define parse.error custom
%define parse.trace
%locations
@@ -29,10 +29,17 @@
if (!p.parse ())
System.exit (1);
}
+
+ static String _ (String s)
+ {
+ return s;
+ }
}
/* Bison Declarations */
-%token <Integer> NUM "number"
+%token
+ '\n' _("end of line")
+ <Integer> NUM _("number")
%type <Integer> 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. ##
## --------------- ##