bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 6/7] java: add support for parse.error custom


From: Akim Demaille
Subject: [PATCH 6/7] java: add support for parse.error custom
Date: Sun, 9 Feb 2020 14:02:26 +0100

* 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.
---
 TODO                                      |  5 +++
 data/skeletons/lalr1.java                 | 55 ++++++++++++++---------
 examples/c/bistromathic/bistromathic.test |  4 +-
 examples/c/bistromathic/parse.y           |  4 +-
 examples/java/calc/Calc.test              |  4 +-
 examples/java/calc/Calc.y                 | 26 +++++++++--
 tests/calc.at                             |  3 ++
 tests/local.at                            | 23 ++++++++++
 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.  ##
 ## --------------- ##
-- 
2.25.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]