bison-patches
[Top][All Lists]
Advanced

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

[PATCH 03/13] yacc.c: add support for parse.error detailed


From: Akim Demaille
Subject: [PATCH 03/13] yacc.c: add support for parse.error detailed
Date: Sat, 18 Jan 2020 16:40:02 +0100

"detailed" error messages are almost like "verbose", except that we
don't double escape them, they don't get inner quotes, we don't use
yytnamerr, and we hide the table.

"custom" is exposed with the "detailed" tokens, not the "verbose"
ones: they are not double-quoted.

Because there's a risk that some people use yytname even without
"verbose", let's keep yytname (instead of yys_name) in "simple"
parse.error.

* src/output.c (prepare_symbol_names): Be ready to output symbol names
unquoted.
(prepare_symbol_names): Output both the old tname table, and the new
symbol_names one.
* data/skeletons/bison.m4: Accept 'detailed'.
* data/skeletons/yacc.c: When parse.error is 'detailed', don't emit
yytname and yytnamerr, just yysymbol_name with the table inside.
* tests/calc.at: Adjust.
---
 data/skeletons/bison.m4 | 13 ++++++------
 data/skeletons/yacc.c   | 47 +++++++++++++++++++++++++++++------------
 src/output.c            |  7 +++++-
 tests/calc.at           | 34 ++++++++++++++---------------
 4 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/data/skeletons/bison.m4 b/data/skeletons/bison.m4
index 946e7642..5c7af1e1 100644
--- a/data/skeletons/bison.m4
+++ b/data/skeletons/bison.m4
@@ -1018,16 +1018,17 @@ m4_define([b4_bison_locations_if],
 
 # b4_error_verbose_if([IF-ERRORS-ARE-VERBOSE], [IF-NOT])
 # ------------------------------------------------------
-# Map %define parse.error "(custom|simple|verbose)" to b4_error_verbose_if and
-# b4_error_verbose_flag.
+# Map %define parse.error "(custom|detailed|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]],
-                                 [[custom]], [[simple]], [[verbose]]]])
+                                 [[custom]], [[detailed]], [[simple]], 
[[verbose]]]])
 m4_define([b4_error_verbose_flag],
           [m4_case(b4_percent_define_get([[parse.error]]),
-                   [custom],  [[1]],
-                   [simple],  [[0]],
-                   [verbose], [[1]])])
+                   [custom],   [[1]],
+                   [detailed], [[1]],
+                   [simple],   [[0]],
+                   [verbose],  [[1]])])
 b4_define_flag_if([error_verbose])
 
 # yytoken_table is needed to support verbose errors.
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 23f078f4..83777ebb 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -603,21 +603,37 @@ static const ]b4_int_type_for([b4_translate])[ 
yytranslate[] =
 #endif
 
 #if ]b4_error_verbose_if([[1]], [b4_api_PREFIX[DEBUG || ]b4_token_table_flag])[
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+/* The user-facing name of the symbol whose (internal) number is
+   YYSYMBOL.  No bounds checking.  */
+static const char *yysymbol_name (int yysymbol) YY_ATTRIBUTE_UNUSED;
+
+]m4_bmatch(b4_percent_define_get([[parse.error]]),
+           [simple\|verbose],
+[[/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
   ]b4_tname[
 };
 
-/* The user-facing name of the symbol whose (internal) number is
+static const char *
+yysymbol_name (int yysymbol)
+{
+  return yytname[yysymbol];
+}]],
+[[/* The user-facing name of the symbol whose (internal) number is
    YYSYMBOL.  No bounds checking.  */
 static const char *yysymbol_name (int yysymbol) YY_ATTRIBUTE_UNUSED;
+
 static const char *
 yysymbol_name (int yysymbol)
 {
-  return yytname[yysymbol];
-}
+  static const char *const yy_sname[] =
+  {
+  ]b4_symbol_names[
+  };
+  return yy_sname[yysymbol];
+}]])[
 #endif
 
 # ifdef YYPRINT
@@ -1177,7 +1193,8 @@ yyparse_context_location (const yyparse_context_t *yyctx)
 ]b4_function_declare([yyreport_syntax_error], [static int],
                      [[[const yyparse_context_t *yyctx]], [[yyctx]]],
                      b4_parse_param)],
-         [verbose],
+         [simple],
+[[]],
 [[# ifndef yystrlen
 #  if defined __GLIBC__ && defined _STRING_H
 #   define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
@@ -1214,7 +1231,9 @@ yyparse_context_location (const yyparse_context_t *yyctx)
 #  endif
 # endif
 
-# ifndef yytnamerr
+]m4_case(b4_percent_define_get([[parse.error]]),
+         [verbose],
+[[# ifndef yytnamerr
 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
    quotes and backslashes, so that it's suitable for yyerror.  The
    heuristic is that double-quoting is unnecessary unless the string
@@ -1264,7 +1283,7 @@ yytnamerr (char *yyres, const char *yystr)
     return yystrlen (yystr);
 }
 # endif
-
+]])[
 
 /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
    about the unexpected token YYTOKEN for the state stack whose top is
@@ -1319,7 +1338,9 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
     for (yyi = 0; yyi < yycount; ++yyi)
       {
         YYPTRDIFF_T yysize1
-          = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
+          = yysize + ]m4_case(b4_percent_define_get([[parse.error]]),
+                              [verbose], [[yytnamerr (YY_NULLPTR, 
yytname[yyarg[yyi]])]],
+                              [[yystrlen (yysymbol_name (yyarg[yyi]))]]);[
         if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
           yysize = yysize1;
         else
@@ -1344,8 +1365,9 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
     int yyi = 0;
     while ((*yyp = *yyformat) != '\0')
       if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
+        {]m4_case(b4_percent_define_get([[parse.error]]), [verbose], [[
+          yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);]], [[
+          yyp = yystpcpy (yyp, yysymbol_name (yyarg[yyi++]));]])[
           yyformat += 2;
         }
       else
@@ -1499,7 +1521,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[
   YYSTYPE yyval;]b4_locations_if([[
   YYLTYPE yyloc;]])[
 
-]m4_case(b4_percent_define_get([[parse.error]]), [verbose],
+]m4_bmatch(b4_percent_define_get([[parse.error]]), [detailed\|verbose],
 [[  /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
   char *yymsg = yymsgbuf;
@@ -1833,7 +1855,6 @@ yyerrlab:
       }]],
          [simple],
 [[      yyerror (]b4_yyerror_args[YY_("syntax error"));]],
-         [verbose],
 [[      {
         char const *yymsgp = YY_("syntax error");
         yyparse_context_t yyctx
@@ -2028,7 +2049,7 @@ yyreturn:
 | yypushreturn -- ask for the next token.  |
 `-----------------------------------------*/
 yypushreturn:]])[
-]m4_case(b4_percent_define_get([[parse.error]]), [verbose],
+]m4_bmatch(b4_percent_define_get([[parse.error]]), [detailed\|verbose],
 [[  if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);]])[
   return yyresult;
diff --git a/src/output.c b/src/output.c
index 5eccea49..9d597e2d 100644
--- a/src/output.c
+++ b/src/output.c
@@ -139,13 +139,17 @@ static void
 prepare_symbol_names (char const *muscle_name)
 {
   /* We assume that the table will be output starting at column 2. */
+  const bool quote = STREQ (muscle_name, "tname");
   int j = 2;
   struct quoting_options *qo = clone_quoting_options (0);
   set_quoting_style (qo, c_quoting_style);
   set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS);
   for (int i = 0; i < nsyms; i++)
     {
-      char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
+      char *cp =
+        symbols[i]->tag[0] == '"' && !quote
+        ? xstrdup (symbols[i]->tag)
+        : quotearg_alloc (symbols[i]->tag, -1, qo);
       /* Width of the next token, including the two quotes, the
          comma and the space.  */
       int width = strlen (cp) + 2;
@@ -192,6 +196,7 @@ prepare_symbols (void)
 
   /* tname -- token names.  */
   prepare_symbol_names ("tname");
+  prepare_symbol_names ("symbol_names");
 
   /* Output YYTOKNUM. */
   {
diff --git a/tests/calc.at b/tests/calc.at
index 58526d99..d309acb8 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -616,10 +616,10 @@ mv at-expout expout]])
 # the traditional one.
 AT_ERROR_CUSTOM_IF([], [
 AT_PERL_REQUIRE([[-pi -e 'use strict;
-  s{syntax error on token \["?(.*?)"?\] \(expected: (.*)\)}
+  s{syntax error on token \[(.*?)\] \(expected: (.*)\)}
   {
     my $unexp = $][1;
-    my @exps = $][2 =~ /\["?(.*?)"?\]/g;
+    my @exps = $][2 =~ /\[(.*?)\]/g;
     ($][#exps && $][#exps < 4)
     ? "syntax error, unexpected $unexp, expecting @{[join(\" or \", @exps)]}"
     : "syntax error, unexpected $unexp";
@@ -694,15 +694,15 @@ _AT_CHECK_CALC([$1],
 _AT_CHECK_CALC_ERROR([$1], [1], [1 2],
                      [[final: 0 0 1]],
                      [15],
-                     [[1.3: syntax error on token ["number"] (expected: ['='] 
['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
+                     [[1.3: syntax error on token [number] (expected: ['='] 
['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [1//2],
                      [[final: 0 0 1]],
                      [20],
-                     [[1.3: syntax error on token ['/'] (expected: ["number"] 
['-'] ['('] ['!'])]])
+                     [[1.3: syntax error on token ['/'] (expected: [number] 
['-'] ['('] ['!'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [error],
                      [[final: 0 0 1]],
                      [5],
-                     [[1.1: syntax error on token [$undefined] (expected: 
["number"] ['-'] ['\n'] ['('] ['!'])]])
+                     [[1.1: syntax error on token [$undefined] (expected: 
[number] ['-'] ['\n'] ['('] ['!'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
                      [[final: 0 0 1]],
                      [30],
@@ -712,12 +712,12 @@ _AT_CHECK_CALC_ERROR([$1], [1],
 +1],
                      [[final: 0 0 1]],
                      [20],
-                     [[2.1: syntax error on token ['+'] (expected: ["end of 
input"] ["number"] ['-'] ['\n'] ['('] ['!'])]])
+                     [[2.1: syntax error on token ['+'] (expected: [end of 
input] [number] ['-'] ['\n'] ['('] ['!'])]])
 # Exercise error messages with EOF: work on an empty file.
 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
                      [[final: 0 0 1]],
                      [4],
-                     [[1.1: syntax error on token ["end of input"] (expected: 
["number"] ['-'] ['\n'] ['('] ['!'])]])
+                     [[1.1: syntax error on token [end of input] (expected: 
[number] ['-'] ['\n'] ['('] ['!'])]])
 
 # Exercise the error token: without it, we die at the first error,
 # hence be sure to
@@ -739,10 +739,10 @@ _AT_CHECK_CALC_ERROR([$1], [0],
                      [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
                      [[final: 4444 0 4]],
                      [250],
-[[1.2: syntax error on token [')'] (expected: ["number"] ['-'] ['('] ['!'])
-1.18: syntax error on token [')'] (expected: ["number"] ['-'] ['('] ['!'])
-1.23: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])
-1.41: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])
+[[1.2: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
+1.18: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
+1.23: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
+1.41: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
 calc: error: 4444 != 1]])
 
 # The same, but this time exercising explicitly triggered syntax errors.
@@ -750,13 +750,13 @@ calc: error: 4444 != 1]])
 _AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1],
                      [[final: 2222 0 1]],
                      [102],
-[[1.10: syntax error on token ["number"] (expected: ['='] ['-'] ['+'] ['*'] 
['/'] ['^'] [')'])
+[[1.10: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] 
['/'] ['^'] [')'])
 calc: error: 2222 != 1]])
 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
                      [[final: 2222 0 2]],
                      [113],
-[[1.4: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])
-1.12: syntax error on token ["number"] (expected: ['='] ['-'] ['+'] ['*'] 
['/'] ['^'] [')'])
+[[1.4: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
+1.12: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] 
['^'] [')'])
 calc: error: 2222 != 1]])
 
 # Check that yyerrok works properly: second error is not reported,
@@ -764,9 +764,9 @@ calc: error: 2222 != 1]])
 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
                      [[final: 3333 0 3]],
                      [113],
-[[1.2: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])
-1.10: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])
-1.16: syntax error on token ['*'] (expected: ["number"] ['-'] ['('] ['!'])]])
+[[1.2: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
+1.10: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
+1.16: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
 
 AT_BISON_OPTION_POPDEFS
 
-- 
2.24.1




reply via email to

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