bison-patches
[Top][All Lists]
Advanced

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

[PATCH 04/12] yacc.c: add custom error message generation


From: Akim Demaille
Subject: [PATCH 04/12] yacc.c: add custom error message generation
Date: Thu, 16 Jan 2020 07:58:15 +0100

When parse.error is custom, let users define a yyreport_syntax_error
function, and use it.

* data/skeletons/bison.m4 (b4_error_verbose_if): Accept 'custom'.
* data/skeletons/yacc.c: Implement it.
* examples/c/calc/calc.y: Experiment with it.
---
 data/skeletons/bison.m4 |  5 +++--
 data/skeletons/yacc.c   | 15 ++++++++++++++-
 examples/c/calc/calc.y  | 23 +++++++++++++++++++++++
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/data/skeletons/bison.m4 b/data/skeletons/bison.m4
index c7be4037..946e7642 100644
--- a/data/skeletons/bison.m4
+++ b/data/skeletons/bison.m4
@@ -1018,13 +1018,14 @@ m4_define([b4_bison_locations_if],
 
 # b4_error_verbose_if([IF-ERRORS-ARE-VERBOSE], [IF-NOT])
 # ------------------------------------------------------
-# Map %define parse.error "(simple|verbose)" to b4_error_verbose_if and
+# Map %define parse.error "(custom|simple|verbose)" to b4_error_verbose_if and
 # b4_error_verbose_flag.
 b4_percent_define_default([[parse.error]], [[simple]])
 b4_percent_define_check_values([[[[parse.error]],
-                                 [[simple]], [[verbose]]]])
+                                 [[custom]], [[simple]], [[verbose]]]])
 m4_define([b4_error_verbose_flag],
           [m4_case(b4_percent_define_get([[parse.error]]),
+                   [custom],  [[1]],
                    [simple],  [[0]],
                    [verbose], [[1]])])
 b4_define_flag_if([error_verbose])
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index ff53b8d0..022b01de 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -1136,7 +1136,11 @@ yysyntax_error_arguments (const yyparse_context_t *yyctx,
 }
 ]])[
 
-]m4_case(b4_percent_define_get([[parse.error]]), [verbose],
+]m4_case(b4_percent_define_get([[parse.error]]),
+         [custom],
+[[static int
+yyreport_syntax_error (const yyparse_context_t *yyctx);]],
+         [verbose],
 [[# ifndef yystrlen
 #  if defined __GLIBC__ && defined _STRING_H
 #   define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
@@ -1786,6 +1790,15 @@ yyerrlab:
     {
       ++yynerrs;
 ]m4_case(b4_percent_define_get([[parse.error]]),
+         [custom],
+[[      {
+        yyparse_context_t yyctx
+          = {yyssp, yytoken]b4_lac_if([[, yyesa, &yyes, 
&yyes_capacity]])[};]b4_lac_if([[
+        if (yychar != YYEMPTY)
+          YY_LAC_ESTABLISH;]])[
+        if (yyreport_syntax_error (]b4_yyerror_args[&yyctx) == 2)
+          goto yyexhaustedlab;
+      }]],
          [simple],
 [[      yyerror (]b4_yyerror_args[YY_("syntax error"));]],
          [verbose],
diff --git a/examples/c/calc/calc.y b/examples/c/calc/calc.y
index a9896e43..0ba74da6 100644
--- a/examples/c/calc/calc.y
+++ b/examples/c/calc/calc.y
@@ -9,6 +9,7 @@
 
 %define api.header.include {"calc.h"}
 %define api.value.type union /* Generate YYSTYPE from these types:  */
+%define parse.error custom
 %token <double> NUM "number"
 %type  <double> expr term fact
 
@@ -51,6 +52,28 @@ fact:
 
 %%
 
+int
+yyreport_syntax_error (const yyparse_context_t *ctx)
+{
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 10 };
+  /* Arguments of yyformat: reported tokens (one for the "unexpected",
+     one per "expected"). */
+  int arg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  int n = yysyntax_error_arguments (ctx, arg, sizeof arg / sizeof *arg);
+  if (n == -2)
+    return 2;
+  fprintf (stderr, "SYNTAX ERROR on token [%s]", yysymbol_name (arg[0]));
+  if (1 < n)
+    {
+      fprintf (stderr, " (expected:");
+      for (int i = 1; i < n; ++i)
+        fprintf (stderr, " [%s]", yysymbol_name (arg[i]));
+      fprintf (stderr, ")");
+    }
+  fprintf (stderr, "\n");
+  return 0;
+}
+
 int
 yylex (void)
 {
-- 
2.24.1




reply via email to

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