]> git.saurik.com Git - bison.git/commitdiff
Merge branch 'branch-2.6' into maint
authorAkim Demaille <akim@lrde.epita.fr>
Tue, 6 Nov 2012 17:00:33 +0000 (18:00 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Tue, 6 Nov 2012 17:12:05 +0000 (18:12 +0100)
* origin/branch-2.6: (24 commits)
  tests: calc: modernize the use of locations
  tests: remove useless location initializations
  lalr1.cc: always initialize yylval.
  tests: check that C and C++ objects can be linked together.
  yacc.c: also disable -Wuninitialized.
  glr.cc, yacc.c: initialize yylloc properly
  yacc.c, glr.c: a better YY_LOCATION_PRINT
  yacc.c: simplify initialization
  doc: formatting changes
  c++: fix position operator signatures
  tests: remove useless location initialization.
  tests: fix locations in C
  tests: handle %parse-param in the generated yyerror
  tests: simplifications
  grammars: fix display of nul character in error message
  tests: sort
  tests: cosmetic changes
  comment changes
  autoconf: update
  gnulib: update
  ...

Conflicts:
NEWS
gnulib
tests/named-refs.at
tests/regression.at

44 files changed:
NEWS
README-hacking
THANKS
TODO
cfg.mk
configure.ac
data/c++.m4
data/glr.cc
data/java.m4
data/lalr1.cc
data/xslt/xml2dot.xsl
doc/Makefile.am
doc/bison.texi
doc/figs/example-reduce.dot [new file with mode: 0644]
doc/figs/example-reduce.txt [new file with mode: 0644]
doc/figs/example-shift.dot [new file with mode: 0644]
doc/figs/example-shift.txt [new file with mode: 0644]
gnulib
src/complain.c
src/complain.h
src/getargs.c
src/graphviz.c
src/graphviz.h
src/muscle-tab.c
src/output.c
src/parse-gram.c
src/parse-gram.h
src/print_graph.c
src/reader.c
src/symtab.c
src/system.h
tests/c++.at
tests/calc.at
tests/conflicts.at
tests/glr-regression.at
tests/headers.at
tests/input.at
tests/java.at
tests/local.at
tests/named-refs.at
tests/output.at
tests/push.at
tests/regression.at
tests/skeletons.at

diff --git a/NEWS b/NEWS
index 3d21470a0685fa0c929a3ae1508c0b3c1e15d7ba..b7a1a727d9d9b888ff410a3a7c62426d28fdfec6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,56 @@
 GNU Bison NEWS
 
+* Noteworthy changes in release ?.? (????-??-??) [?]
+
+** Changes in the format of error messages
+
+  This used to be the format of many error reports:
+
+    foo.y:5.10-24: result type clash on merge function 'merge': <t3> != <t2>
+    foo.y:4.13-27: previous declaration
+
+  It is now:
+
+    foo.y:5.10-25: result type clash on merge function 'merge': <t3> != <t2>
+    foo.y:4.13-27:     previous declaration
+
+** Exception safety (lalr1.cc)
+
+  The parse function now catches exceptions, uses the %destructors to
+  release memory (the lookahead symbol and the symbols pushed on the stack)
+  before re-throwing the exception.
+
+  This feature is somewhat experimental.  User feedback would be
+  appreciated.
+
+** New %define variable: api.location.type (glr.cc, lalr1.cc, lalr1.java)
+
+  The %define variable api.location.type defines the name of the type to use
+  for locations.  When defined, Bison no longer generates the position.hh
+  and location.hh files, nor does the parser will include them: the user is
+  then responsible to define her type.
+
+  This can be used in programs with several parsers to factor their location
+  and position files: let one of them generate them, and the others just use
+  them.
+
+  This feature was actually introduced, but not documented, in Bison 2.5,
+  under the name "location_type" (which is maintained for backward
+  compatibility).
+
+  For consistency, lalr1.java's %define variables location_type and
+  position_type are deprecated in favor of api.location.type and
+  api.position.type.
+
+** Graphviz improvements
+
+  The graphical presentation of the states is more readable: their shape is
+  now rectangular, the state number is clearly displayed, and the items are
+  numbered and left-justified.
+
+  The reductions are now explicitly represented as transitions to other
+  diamond shaped nodes.
+
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
   We consider compiler warnings about Bison generated parsers to be bugs.
@@ -85,7 +136,7 @@ GNU Bison NEWS
 
 * Noteworthy changes in release 2.6.1 (2012-07-30) [stable]
 
- Bison no longer executes user-specified M4 code when processing a grammar.
 Bison no longer executes user-specified M4 code when processing a grammar.
 
 ** Future Changes
 
@@ -1924,7 +1975,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  LocalWords:  namespaces strerror const autoconfiguration Dconst Autoconf's FDL
  LocalWords:  Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
  LocalWords:  extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
- LocalWords:  lang yyoutput dvi html ps POSIX lvalp llocp calc yyo fval
+ LocalWords:  lang yyoutput dvi html ps POSIX lvalp llocp calc yyo fval Wmaybe
+ LocalWords:  yyvsp pragmas noreturn java's
 
 Local Variables:
 mode: outline
index 26391e98f7cd256b04ae950d4721c1f6c260fc19..11b9f82a39fc78dccec2e8f2f179bd380ddbe8c6 100644 (file)
@@ -43,16 +43,17 @@ These requirements do not apply when building from a distribution tarball.
 
 ** Requirements
 
-We've opted to keep only the highest-level sources in the repository.
-This eases our maintenance burden, (fewer merges etc.), but imposes more
+We've opted to keep only the highest-level sources in the repository.  This
+eases our maintenance burden, (fewer merges etc.), but imposes more
 requirements on anyone wishing to build from the just-checked-out sources.
 For example, you have to use the latest stable versions of the maintainer
 tools we depend upon, including:
 
-- Automake <http://www.gnu.org/software/automake/>
 - Autoconf <http://www.gnu.org/software/autoconf/>
+- Automake <http://www.gnu.org/software/automake/>
 - Flex <http://www.gnu.org/software/flex/>
 - Gettext <http://www.gnu.org/software/gettext/>
+- Graphviz <http://www.graphviz.org>
 - Gzip <http://www.gnu.org/software/gzip/>
 - Perl <http://www.cpan.org/>
 - Rsync <http://samba.anu.edu.au/rsync/>
@@ -61,16 +62,16 @@ tools we depend upon, including:
 Valgrind <http://valgrind.org/> is also highly recommended, if it supports
 your architecture.
 
-Bison is written using Bison grammars, so there are bootstrapping
-issues.  The bootstrap script attempts to discover when the C code
-generated from the grammars is out of date, and to bootstrap with an
-out-of-date version of the C code, but the process is not foolproof.
-Also, you may run into similar problems yourself if you modify Bison.
+Bison is written using Bison grammars, so there are bootstrapping issues.
+The bootstrap script attempts to discover when the C code generated from the
+grammars is out of date, and to bootstrap with an out-of-date version of the
+C code, but the process is not foolproof.  Also, you may run into similar
+problems yourself if you modify Bison.
 
-Only building the initial full source tree will be a bit painful.
-Later, after synchronizing from the repository a plain 'make' should
-be sufficient.  Note, however, that when gnulib is updated, running
-'./bootstrap' again might be needed.
+Only building the initial full source tree will be a bit painful.  Later,
+after synchronizing from the repository a plain 'make' should be sufficient.
+Note, however, that when gnulib is updated, running './bootstrap' again
+might be needed.
 
 ** First checkout
 
diff --git a/THANKS b/THANKS
index 77d35be7d8d460644ccb013a3a9fcf7469ee3622..21e7a1dd855ffc4e98cd6096629dab010d77cbe3 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -81,6 +81,7 @@ Nicolas Tisserand         nicolas.tisserand@epita.fr
 Noah Friedman             friedman@gnu.org
 Odd Arild Olsen           oao@fibula.no
 Oleg Smolsky              oleg.smolsky@pacific-simulators.co.nz
+Oleksii Taran             oleksii.taran@gmail.com
 Paolo Bonzini             bonzini@gnu.org
 Pascal Bart               pascal.bart@epita.fr
 Paul Eggert               eggert@cs.ucla.edu
@@ -105,6 +106,7 @@ Shura                     debil_urod@ngs.ru
 Stefano Lattarini         stefano.lattarini@gmail.com
 Steve Murphy              murf@parsetree.com
 Sum Wu                    sum@geekhouse.org
+Théophile Ranquet         theophile.ranquet@gmail.com
 Thiru Ramakrishnan        thiru.ramakrishnan@gmail.com
 Tim Josling               tej@melbpc.org.au
 Tim Landscheidt           tim@tim-landscheidt.de
@@ -128,6 +130,7 @@ thank them!  Please, help us keeping this list up to date.
 
 Local Variables:
 mode: text
+coding: utf-8
 End:
 
 -----
diff --git a/TODO b/TODO
index 4f628a20aa4f3577ffc1a004030587c4395e17a8..978b5c6f4d45fb3664a39e00cd06ec41051e5181 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,17 @@
 * Short term
+** Graphviz display code thoughts
+The code for the --graph option is over two files: print_graph, and
+graphviz. I believe this is because Bison used to also produce VCG graphs,
+but since this is no longer true, maybe we could consider these files for
+fusion.
+
+Little effort factoring seems to have been given to factoring in these files,
+and their print-xml and print counterpart. We would very much like to re-use
+the pretty format of states from .output in the .dot
+
+Also, the underscore in print_graph.[ch] isn't very fitting considering
+the dashes in the other filenames.
+
 ** Variable names.
 What should we name `variant' and `lex_symbol'?
 
diff --git a/cfg.mk b/cfg.mk
index 3a70379ceff32ac9cc53b0bd7c977366b4262593..9f11f3774aa15fa7ab32c8d7d91a115e8833e7c2 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -24,6 +24,7 @@ regen: _version
 
 # Used in maint.mk's web-manual rule
 manual_title = The Yacc-compatible Parser Generator
+gendocs_options_ = -I $(abs_top_srcdir)/doc -I $(abs_top_builddir)/doc
 
 # It's useful to run maintainer-*check* targets during development, but we
 # don't want to wait on a recompile because of an update to $(VERSION).  Thus,
index 651fa1397eab9c715ae1281b90cdc3a8cd25968d..955f56ef790afaf18d96dd625e155d2ea9c1af29 100644 (file)
@@ -131,6 +131,7 @@ AC_SUBST([YACC_SCRIPT])
 AC_SUBST([YACC_LIBRARY])
 
 # Checks for programs.
+AM_MISSING_PROG([DOT], [dot])
 AC_PROG_LEX
 $LEX_IS_FLEX || AC_MSG_ERROR([Flex is required])
 AC_PROG_YACC
index 45c4ddaf1f81331cd5e253a03320216398ee5473..8b98b8c1b47dfae443748e793f000d854a0d19f9 100644 (file)
@@ -29,7 +29,7 @@ b4_percent_define_default([[parser_class_name]], [[parser]])
 # Don't do that so that we remember whether we're using a user
 # request, or the default value.
 #
-# b4_percent_define_default([[location_type]], [[location]])
+# b4_percent_define_default([[api.location.type]], [[location]])
 
 b4_percent_define_default([[filename_type]], [[std::string]])
 b4_percent_define_default([[namespace]], m4_defn([b4_prefix]))
index 104bf785b66d5fd9d20c51124a011b8e4306ac3c..0e53d61915833343458c5c49022fb35a397c0e3a 100644 (file)
@@ -54,7 +54,7 @@ b4_defines_if([],
               [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
 
 m4_include(b4_pkgdatadir/[c++.m4])
-b4_percent_define_ifdef([[location_type]], [],
+b4_percent_define_ifdef([[api.location.type]], [],
                         [m4_include(b4_pkgdatadir/[location.cc])])
 
 m4_define([b4_parser_class_name],
@@ -90,7 +90,7 @@ m4_define([b4_yy_symbol_print_generate],
 ]])[
 
 # Hijack the initial action to initialize the locations.
-]b4_locations_if([b4_percent_define_ifdef([[location_type]], [],
+]b4_locations_if([b4_percent_define_ifdef([[api.location.type]], [],
 [m4_define([b4_initial_action],
 [yylloc.initialize ();]m4_ifdef([b4_initial_action], [
 m4_defn([b4_initial_action])]))])])[
@@ -243,7 +243,7 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++],
 
 # include <string>
 # include <iostream>
-]b4_percent_define_ifdef([[location_type]], [],
+]b4_percent_define_ifdef([[api.location.type]], [],
                          [[# include "location.hh"]])[
 
 ]b4_YYDEBUG_define[
@@ -267,7 +267,7 @@ b4_user_stype
     typedef ]b4_api_PREFIX[STYPE semantic_type;
 # endif
     /// Symbol locations.
-    typedef ]b4_percent_define_get([[location_type]],
+    typedef ]b4_percent_define_get([[api.location.type]],
                                    [[location]])[ location_type;
     /// Tokens.
     struct token
index 18ea30b5086b379ecc794a746dd4718daaa18528..627028b36c8d9252c4c1e7cbc7b774cc87c2a0ab 100644 (file)
@@ -155,25 +155,25 @@ m4_define([b4_case], [  case $1:
 ## ---------------- ##
 
 m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
-b4_percent_define_default([[stype]], [[Object]])])
+b4_percent_define_default([[stype]], [[Object]])
 
 # %name-prefix
 m4_define_default([b4_prefix], [[YY]])
 
-b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])])
+b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])
 m4_define([b4_parser_class_name], [b4_percent_define_get([[parser_class_name]])])
 
-b4_percent_define_default([[lex_throws]], [[java.io.IOException]])])
+b4_percent_define_default([[lex_throws]], [[java.io.IOException]])
 m4_define([b4_lex_throws], [b4_percent_define_get([[lex_throws]])])
 
-b4_percent_define_default([[throws]], [])])
+b4_percent_define_default([[throws]], [])
 m4_define([b4_throws], [b4_percent_define_get([[throws]])])
 
-b4_percent_define_default([[location_type]], [Location])])
-m4_define([b4_location_type], [b4_percent_define_get([[location_type]])])
+b4_percent_define_default([[api.location.type]], [Location])
+m4_define([b4_location_type], [b4_percent_define_get([[api.location.type]])])
 
-b4_percent_define_default([[position_type]], [Position])])
-m4_define([b4_position_type], [b4_percent_define_get([[position_type]])])
+b4_percent_define_default([[api.position.type]], [Position])
+m4_define([b4_position_type], [b4_percent_define_get([[api.position.type]])])
 
 
 ## ----------------- ##
@@ -219,9 +219,9 @@ m4_define([b4_rhs_location],
 # it to be single quoted.  Same for b4_parse_param.
 
 # TODO: should be in bison.m4
-m4_define_default([b4_lex_param], [[]]))
-m4_define([b4_lex_param], b4_lex_param))
-m4_define([b4_parse_param], b4_parse_param))
+m4_define_default([b4_lex_param], [[]])
+m4_define([b4_lex_param], b4_lex_param)
+m4_define([b4_parse_param], b4_parse_param)
 
 # b4_lex_param_decl
 # -------------------
index 2fe8d4cbd84de5f4a9b2f278aa70f3bb8e4b50a8..e45b2e1f860cf48ff9c66be677b5f20001008240 100644 (file)
@@ -24,7 +24,7 @@ m4_define([b4_parser_class_name],
 b4_defines_if([],
               [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
 
-b4_percent_define_ifdef([[location_type]], [],
+b4_percent_define_ifdef([[api.location.type]], [],
   [# Backward compatibility.
   m4_define([b4_location_constructors])
   m4_include(b4_pkgdatadir/[location.cc])])
@@ -52,7 +52,7 @@ b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++],
 #include <string>
 #include <iostream>
 #include "stack.hh"
-]b4_percent_define_ifdef([[location_type]], [],
+]b4_percent_define_ifdef([[api.location.type]], [],
                          [[#include "location.hh"]])[
 
 ]b4_YYDEBUG_define[
@@ -77,7 +77,7 @@ b4_user_stype
     typedef ]b4_api_PREFIX[STYPE semantic_type;
 #endif
     /// Symbol locations.
-    typedef ]b4_percent_define_get([[location_type]],
+    typedef ]b4_percent_define_get([[api.location.type]],
                                    [[location]])[ location_type;
     /// Tokens.
     struct token
@@ -227,6 +227,7 @@ b4_user_stype
 
     /// \brief Reclaim the memory associated to a symbol.
     /// \param yymsg        Why this token is reclaimed.
+    ///                     If null, do not display the symbol, just free it.
     /// \param yytype       The symbol type.
     /// \param yyvaluep     Its semantic value.
     /// \param yylocationp  Its location.
@@ -335,9 +336,9 @@ do {                                        \
 #else /* !]b4_api_PREFIX[DEBUG */
 
 # define YYCDEBUG if (false) std::cerr
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_REDUCE_PRINT(Rule)
-# define YY_STACK_PRINT()
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) YYUSE(Type)
+# define YY_REDUCE_PRINT(Rule)        static_cast<void>(0)
+# define YY_STACK_PRINT()             static_cast<void>(0)
 
 #endif /* !]b4_api_PREFIX[DEBUG */
 
@@ -446,7 +447,8 @@ do {                                        \
     YYUSE (yymsg);
     YYUSE (yyvaluep);
 
-    YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+    if (yymsg)
+      YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
     switch (yytype)
       {
@@ -534,6 +536,10 @@ do {                                       \
 
     int yyresult;
 
+    // FIXME: This shoud be completely indented.  It is not yet to
+    // avoid gratuitous conflicts when merging into the master branch.
+    try
+      {
     YYCDEBUG << "Starting parse" << std::endl;
 
 ]m4_ifdef([b4_initial_action], [
@@ -574,9 +580,9 @@ b4_dollar_popdef])[]dnl
     /* Read a lookahead token.  */
     if (yychar == yyempty_)
       {
-       YYCDEBUG << "Reading a token: ";
-       yychar = ]b4_c_function_call([yylex], [int],
-                                    [b4_api_PREFIX[STYPE*], [&yylval]][]dnl
+        YYCDEBUG << "Reading a token: ";
+        yychar = ]b4_c_function_call([yylex], [int],
+                                     [b4_api_PREFIX[STYPE*], [&yylval]][]dnl
 b4_locations_if([, [[location*], [&yylloc]]])dnl
 m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
       }
@@ -651,17 +657,21 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
     else
       yyval = yysemantic_stack_[0];
 
+    // Compute the default @@$.
     {
       slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
       YYLLOC_DEFAULT (yyloc, slice, yylen);
     }
+
+    // Perform the reduction.
     YY_REDUCE_PRINT (yyn);
     switch (yyn)
       {
-       ]b4_user_actions[
-       default:
-          break;
+        ]b4_user_actions[
+      default:
+        break;
       }
+
     /* User semantic actions sometimes alter yychar, and that requires
        that yytoken be updated with the new translation.  We take the
        approach of translating immediately before every use of yytoken.
@@ -712,20 +722,19 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
     yyerror_range[1] = yylloc;
     if (yyerrstatus_ == 3)
       {
-       /* If just tried and failed to reuse lookahead token after an
-        error, discard it.  */
-
-       if (yychar <= yyeof_)
-         {
-         /* Return failure if at end of input.  */
-         if (yychar == yyeof_)
-           YYABORT;
-         }
-       else
-         {
-           yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
-           yychar = yyempty_;
-         }
+        /* If just tried and failed to reuse lookahead token after an
+           error, discard it.  */
+        if (yychar <= yyeof_)
+          {
+            /* Return failure if at end of input.  */
+            if (yychar == yyeof_)
+              YYABORT;
+          }
+        else
+          {
+            yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
+            yychar = yyempty_;
+          }
       }
 
     /* Else will try to reuse lookahead token after shifting the error
@@ -774,7 +783,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
 
        /* Pop the current state because it cannot handle the error token.  */
        if (yystate_stack_.height () == 1)
-       YYABORT;
+         YYABORT;
 
        yyerror_range[1] = yylocation_stack_[0];
        yydestruct_ ("Error: popping",
@@ -822,16 +831,42 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
     /* Do not reclaim the symbols of the rule which action triggered
        this YYABORT or YYACCEPT.  */
     yypop_ (yylen);
-    while (yystate_stack_.height () != 1)
+    while (1 < yystate_stack_.height ())
       {
-       yydestruct_ ("Cleanup: popping",
-                  yystos_[yystate_stack_[0]],
-                  &yysemantic_stack_[0],
-                  &yylocation_stack_[0]);
-       yypop_ ();
+        yydestruct_ ("Cleanup: popping",
+                     yystos_[yystate_stack_[0]],
+                     &yysemantic_stack_[0],
+                     &yylocation_stack_[0]);
+        yypop_ ();
       }
 
     return yyresult;
+    }
+    catch (...)
+      {
+        YYCDEBUG << "Exception caught: cleaning lookahead and stack"
+                 << std::endl;
+        // Do not try to display the values of the reclaimed symbols,
+        // as their printer might throw an exception.
+        if (yychar != yyempty_)
+          {
+            /* Make sure we have latest lookahead translation.  See
+               comments at user semantic actions for why this is
+               necessary.  */
+            yytoken = yytranslate_ (yychar);
+            yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc);
+          }
+
+        while (1 < yystate_stack_.height ())
+          {
+            yydestruct_ (YY_NULL,
+                         yystos_[yystate_stack_[0]],
+                         &yysemantic_stack_[0],
+                         &yylocation_stack_[0]);
+            yypop_ ();
+          }
+        throw;
+      }
   }
 
   // Generate an error message.
index 219faa2f1e77cf738cac5031edd090d05d555640..111613cedb52d464a7a3df5c26c455edf41b594f 100644 (file)
   <xsl:call-template name="escape">
     <xsl:with-param name="subject" select="$filename"/>
   </xsl:call-template>
-  <xsl:text>"&#10;{&#10;</xsl:text>
+  <xsl:text>&#10;{
+  node [fontname = courier, shape = box, colorscheme = paired6]
+  edge [fontname = courier]
+
+</xsl:text>
   <xsl:apply-templates select="state"/>
   <xsl:text>}&#10;</xsl:text>
 </xsl:template>
index f695e22dfecc8d70e76328a0ed87a8b7b30d4c63..9c9c24ca77794e5bd09eadebd56b7c56e3b32b90 100644 (file)
@@ -96,6 +96,36 @@ PREPATH = $(top_builddir)/src
 
 nodist_man_MANS = yacc.1
 
+## ----------------------------- ##
+## Graphviz examples generation. ##
+## ----------------------------- ##
+
+CLEANDIRS += figs
+FIGS_DOT = figs/example-reduce.dot figs/example-shift.dot
+EXTRA_DIST +=                                                          \
+  $(FIGS_DOT)                                                          \
+  $(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png)
+SUFFIXES += .dot .eps .pdf .png
+
+bison.dvi:  $(FIGS_DOT:.dot=.eps)
+bison.html: $(FIGS_DOT:.dot=.png)
+bison.pdf:  $(FIGS_DOT:.dot=.pdf)
+
+.dot.eps:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
+.dot.pdf:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
+.dot.png:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
 ## -------------- ##
 ## Doxygenation.  ##
 ## -------------- ##
index 18d3bb051bfadef114ad7e888eed6e25febc311e..8f98aa5e421744eb0f9089a148a2200a5f6120b3 100644 (file)
@@ -294,6 +294,7 @@ Handling Context Dependencies
 Debugging Your Parser
 
 * Understanding::     Understanding the structure of your parser.
+* Graphviz::          Getting a visual representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 
 Tracing Your Parser
@@ -327,6 +328,7 @@ C++ Location Values
 
 * C++ position::                One point in the source file
 * C++ location::                Two points in the source file
+* User Defined Location Type::  Required interface for locations
 
 A Complete C++ Example
 
@@ -4701,6 +4703,10 @@ incoming terminals during the second phase of error recovery,
 the current lookahead and the entire stack (except the current
 right-hand side symbols) when the parser returns immediately, and
 @item
+the current lookahead and the entire stack (including the current right-hand
+side symbols) when the C++ parser (@file{lalr1.cc}) catches an exception in
+@code{parse},
+@item
 the start symbol, when the parser succeeds.
 @end itemize
 
@@ -5321,6 +5327,23 @@ Unaccepted @var{variable}s produce an error.
 Some of the accepted @var{variable}s are:
 
 @itemize @bullet
+@c ================================================== api.location.type
+@item @code{api.location.type}
+@findex %define api.location.type
+
+@itemize @bullet
+@item Language(s): C++, Java
+
+@item Purpose: Define the location type.
+@xref{User Defined Location Type}.
+
+@item Accepted Values: String
+
+@item Default Value: none
+
+@item History: introduced in Bison 2.7
+@end itemize
+
 @c ================================================== api.prefix
 @item @code{api.prefix}
 @findex %define api.prefix
@@ -5328,7 +5351,7 @@ Some of the accepted @var{variable}s are:
 @itemize @bullet
 @item Language(s): All
 
-@item Purpose: Rename exported symbols
+@item Purpose: Rename exported symbols.
 @xref{Multiple Parsers, ,Multiple Parsers in the Same Program}.
 
 @item Accepted Values: String
@@ -8071,6 +8094,7 @@ automaton, and how to enable and understand the parser run-time traces.
 
 @menu
 * Understanding::     Understanding the structure of your parser.
+* Graphviz::          Getting a visual representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 @end menu
 
@@ -8487,6 +8511,114 @@ precedence of @samp{/} with respect to @samp{+}, @samp{-}, and
 @samp{*}, but also because the
 associativity of @samp{/} is not specified.
 
+@c ================================================= Graphical Representation
+
+@node Graphviz
+@section Visualizing Your Parser
+@cindex dot
+
+As another means to gain better understanding of the shift/reduce
+automaton corresponding to the Bison parser, a DOT file can be generated. Note
+that debugging a real grammar with this is tedious at best, and impractical
+most of the times, because the generated files are huge (the generation of
+a PDF or PNG file from it will take very long, and more often than not it will
+fail due to memory exhaustion). This option was rather designed for beginners,
+to help them understand LR parsers.
+
+This file is generated when the @option{--graph} option is specified (see
+@pxref{Invocation, , Invoking Bison}).  Its name is made by removing
+@samp{.tab.c} or @samp{.c} from the parser implementation file name, and
+adding @samp{.dot} instead.  If the grammar file is @file{foo.y}, the
+Graphviz output file is called @file{foo.dot}.
+
+The following grammar file, @file{rr.y}, will be used in the sequel:
+
+@example
+%%
+@group
+exp: a ";" | b ".";
+a: "0";
+b: "0";
+@end group
+@end example
+
+The graphical output is very similar to the textual one, and as such it is
+easier understood by making direct comparisons between them. See
+@ref{Debugging, , Debugging Your Parser} for a detailled analysis of the
+textual report.
+
+@subheading Graphical Representation of States
+
+The items (pointed rules) for each state are grouped together in graph nodes.
+Their numbering is the same as in the verbose file. See the following points,
+about transitions, for examples
+
+When invoked with @option{--report=lookaheads}, the lookahead tokens, when
+needed, are shown next to the relevant rule between square brackets as a
+comma separated list. This is the case in the figure for the representation of
+reductions, below.
+
+@sp 1
+
+The transitions are represented as directed edges between the current and
+the target states.
+
+@subheading Graphical Representation of Shifts
+
+Shifts are shown as solid arrows, labelled with the lookahead token for that
+shift. The following describes a reduction in the @file{rr.output} file:
+
+@example
+@group
+state 3
+
+    1 exp: a . ";"
+
+    ";"  shift, and go to state 6
+@end group
+@end example
+
+A Graphviz rendering of this portion of the graph could be:
+
+@center @image{figs/example-shift, 100pt}
+
+@subheading Graphical Representation of Reductions
+
+Reductions are shown as solid arrows, leading to a diamond-shaped node
+bearing the number of the reduction rule. The arrow is labelled with the
+appropriate comma separated lookahead tokens. If the reduction is the default
+action for the given state, there is no such label.
+
+This is how reductions are represented in the verbose file @file{rr.output}:
+@example
+state 1
+
+    3 a: "0" .  [";"]
+    4 b: "0" .  ["."]
+
+    "."       reduce using rule 4 (b)
+    $default  reduce using rule 3 (a)
+@end example
+
+A Graphviz rendering of this portion of the graph could be:
+
+@center @image{figs/example-reduce, 120pt}
+
+When unresolved conflicts are present, because in deterministic parsing
+a single decision can be made, Bison can arbitrarily choose to disable a
+reduction, see @ref{Shift/Reduce, , Shift/Reduce Conflicts}.  Discarded actions
+are distinguished by a red filling color on these nodes, just like how they are
+reported between square brackets in the verbose file.
+
+The reduction corresponding to the rule number 0 is the acceptation state. It
+is shown as a blue diamond, labelled "Acc".
+
+@subheading Graphical representation of go tos
+
+The @samp{go to} jump transitions are represented as dotted lines bearing
+the name of the rule being jumped to.
+
+@c ================================================= Tracing
 
 @node Tracing
 @section Tracing Your Parser
@@ -9206,8 +9338,9 @@ generated in the following files:
 @table @file
 @item position.hh
 @itemx location.hh
-The definition of the classes @code{position} and @code{location},
-used for location tracking.  @xref{C++ Location Values}.
+The definition of the classes @code{position} and @code{location}, used for
+location tracking.  These files are not generated if the @code{%define}
+variable @code{api.location.type} is defined.  @xref{C++ Location Values}.
 
 @item stack.hh
 An auxiliary class @code{stack} used by the parser.
@@ -9263,18 +9396,22 @@ Symbols}.
 @c - %define filename_type "const symbol::Symbol"
 
 When the directive @code{%locations} is used, the C++ parser supports
-location tracking, see @ref{Tracking Locations}.  Two auxiliary classes
-define a @code{position}, a single point in a file, and a @code{location}, a
-range composed of a pair of @code{position}s (possibly spanning several
-files).
+location tracking, see @ref{Tracking Locations}.
+
+By default, two auxiliary classes define a @code{position}, a single point
+in a file, and a @code{location}, a range composed of a pair of
+@code{position}s (possibly spanning several files).  But if the
+@code{%define} variable @code{api.location.type} is defined, then these
+classes will not be generated, and the user defined type will be used.
 
 @tindex uint
 In this section @code{uint} is an abbreviation for @code{unsigned int}: in
 genuine code only the latter is used.
 
 @menu
-* C++ position::         One point in the source file
-* C++ location::         Two points in the source file
+* C++ position::                One point in the source file
+* C++ location::                Two points in the source file
+* User Defined Location Type::  Required interface for locations
 @end menu
 
 @node C++ position
@@ -9378,6 +9515,63 @@ Report @var{p} on @var{o}, taking care of special cases such as: no
 @code{filename} defined, or equal filename/line or column.
 @end deftypefun
 
+@node User Defined Location Type
+@subsubsection User Defined Location Type
+@findex %define api.location.type
+
+Instead of using the built-in types you may use the @code{%define} variable
+@code{api.location.type} to specify your own type:
+
+@example
+%define api.location.type @var{LocationType}
+@end example
+
+The requirements over your @var{LocationType} are:
+@itemize
+@item
+it must be copyable;
+
+@item
+in order to compute the (default) value of @code{@@$} in a reduction, the
+parser basically runs
+@example
+@@$.begin = @@$1.begin;
+@@$.end   = @@$@var{N}.end; // The location of last right-hand side symbol.
+@end example
+@noindent
+so there must be copyable @code{begin} and @code{end} members;
+
+@item
+alternatively you may redefine the computation of the default location, in
+which case these members are not required (@pxref{Location Default Action});
+
+@item
+if traces are enabled, then there must exist an @samp{std::ostream&
+  operator<< (std::ostream& o, const @var{LocationType}& s)} function.
+@end itemize
+
+@sp 1
+
+In programs with several C++ parsers, you may also use the @code{%define}
+variable @code{api.location.type} to share a common set of built-in
+definitions for @code{position} and @code{location}.  For instance, one
+parser @file{master/parser.yy} might use:
+
+@example
+%defines
+%locations
+%define namespace "master::"
+@end example
+
+@noindent
+to generate the @file{master/position.hh} and @file{master/location.hh}
+files, reused by other parsers as follows:
+
+@example
+%define api.location.type "master::location"
+%code requires @{ #include <master/location.hh> @}
+@end example
+
 @node C++ Parser Interface
 @subsection C++ Parser Interface
 @c - define parser_class_name
@@ -9415,6 +9609,11 @@ Build a new parser object.  There are no arguments by default, unless
 
 @deftypemethod {parser} {int} parse ()
 Run the syntactic analysis, and return 0 on success, 1 otherwise.
+
+@cindex exceptions
+The whole function is wrapped in a @code{try}/@code{catch} block, so that
+when an exception is thrown, the @code{%destructor}s are called to release
+the lookahead symbol, and the symbols pushed on the stack.
 @end deftypemethod
 
 @deftypemethod {parser} {std::ostream&} debug_stream ()
@@ -9528,8 +9727,8 @@ factor both as follows.
 // Tell Flex the lexer's prototype ...
 # define YY_DECL                                        \
   yy::calcxx_parser::token_type                         \
-  yylex (yy::calcxx_parser::semantic_type *yylval,      \
-         yy::calcxx_parser::location_type *yylloc,      \
+  yylex (yy::calcxx_parser::semantic_typeyylval,      \
+         yy::calcxx_parser::location_typeyylloc,      \
          calcxx_driver& driver)
 // ... and declare it for the parser's sake.
 YY_DECL;
@@ -10086,11 +10285,11 @@ class defines a @dfn{position}, a single point in a file; Bison itself
 defines a class representing a @dfn{location}, a range composed of a pair of
 positions (possibly spanning several files).  The location class is an inner
 class of the parser; the name is @code{Location} by default, and may also be
-renamed using @code{%define location_type "@var{class-name}"}.
+renamed using @code{%define api.location.type "@var{class-name}"}.
 
 The location class treats the position as a completely opaque value.
 By default, the class name is @code{Position}, but this can be changed
-with @code{%define position_type "@var{class-name}"}.  This class must
+with @code{%define api.position.type "@var{class-name}"}.  This class must
 be supplied by the user.
 
 
@@ -10225,7 +10424,7 @@ In both cases, the scanner has to implement the following methods.
 @deftypemethod {Lexer} {void} yyerror (Location @var{loc}, String @var{msg})
 This method is defined by the user to emit an error message.  The first
 parameter is omitted if location tracking is not active.  Its type can be
-changed using @code{%define location_type "@var{class-name}".}
+changed using @code{%define api.location.type "@var{class-name}".}
 @end deftypemethod
 
 @deftypemethod {Lexer} {int} yylex ()
@@ -10243,7 +10442,7 @@ Return respectively the first position of the last token that
 @code{yylex} returned, and the first position beyond it.  These
 methods are not needed unless location tracking is active.
 
-The return type can be changed using @code{%define position_type
+The return type can be changed using @code{%define api.position.type
 "@var{class-name}".}
 @end deftypemethod
 
@@ -10488,10 +10687,11 @@ comma-separated list.  Default is @code{java.io.IOException}.
 @xref{Java Scanner Interface}.
 @end deffn
 
-@deffn {Directive} {%define location_type} "@var{class}"
+@deffn {Directive} {%define api.location.type} "@var{class}"
 The name of the class used for locations (a range between two
 positions).  This class is generated as an inner class of the parser
 class by @command{bison}.  Default is @code{Location}.
+Formerly named @code{location_type}.
 @xref{Java Location Values}.
 @end deffn
 
@@ -10506,9 +10706,10 @@ The name of the parser class.  Default is @code{YYParser} or
 @xref{Java Bison Interface}.
 @end deffn
 
-@deffn {Directive} {%define position_type} "@var{class}"
+@deffn {Directive} {%define api.position.type} "@var{class}"
 The name of the class used for positions. This class must be supplied by
 the user.  Default is @code{Position}.
+Formerly named @code{position_type}.
 @xref{Java Location Values}.
 @end deffn
 
@@ -11792,7 +11993,8 @@ London, Department of Computer Science, TR-00-12 (December 2000).
 @c LocalWords: getLVal defvar deftypefn deftypefnx gotos msgfmt Corbett LALR's
 @c LocalWords: subdirectory Solaris nonassociativity perror schemas Malloy ints
 @c LocalWords: Scannerless ispell american ChangeLog smallexample CSTYPE CLTYPE
-@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate
+@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate LocationType
+@c LocalWords: errorVerbose
 
 @c Local Variables:
 @c ispell-dictionary: "american"
diff --git a/doc/figs/example-reduce.dot b/doc/figs/example-reduce.dot
new file mode 100644 (file)
index 0000000..fdd99c5
--- /dev/null
@@ -0,0 +1,11 @@
+digraph "reduce.y"
+{
+  node [fontname=courier shape=box]
+  edge [fontname=courier]
+
+  1 [label="State 1\n  3 a: \"0\" .  [\".\"]\l  4 b: \"0\" .  [\";\"]\l"]
+  1 -> "1R3" [label="" style=solid]
+ "1R3" [style=filled shape=diamond fillcolor=yellowgreen label="R3"]
+  1 -> "1R4" [label="[\";\"]" style=solid]
+ "1R4" [style=filled shape=diamond fillcolor=yellowgreen label="R4"]
+}
diff --git a/doc/figs/example-reduce.txt b/doc/figs/example-reduce.txt
new file mode 100644 (file)
index 0000000..d4e8219
--- /dev/null
@@ -0,0 +1,13 @@
+       .------------------.
+       |     State 1      |
+       | 3 a: "0" . [";"] |
+       | 4 b: "0" . ["."] |
+       `------------------'
+             /     \
+            /       \ ["."]
+           /         \
+          v           v
+         / \         / \
+        / R \       / R \
+(green) \ 3 /       \ 4 / (green)
+         \ /         \ /
diff --git a/doc/figs/example-shift.dot b/doc/figs/example-shift.dot
new file mode 100644 (file)
index 0000000..995ba0e
--- /dev/null
@@ -0,0 +1,9 @@
+digraph "shift.y"
+{
+  node [fontname=courier shape=box]
+  edge [fontname=courier]
+
+  3 [label="State 3\n  1 exp: a . \".\"\l"]
+  3 -> 6 [style=solid label="\".\""]
+  6 [label="State 6\n  1 exp: a \".\" .\l"]
+}
diff --git a/doc/figs/example-shift.txt b/doc/figs/example-shift.txt
new file mode 100644 (file)
index 0000000..43b1412
--- /dev/null
@@ -0,0 +1,12 @@
+.----------------.
+|    State 3     |
+| 1 exp: a . ";" |
+`----------------'
+        |
+        | ";"
+        |
+        v
+.----------------.
+|    State 6     |
+| 1 exp: a ";" . |
+`----------------'
diff --git a/gnulib b/gnulib
index 0dbbe3f55352241d290403577dfebed802d6fd9a..daf7f8c02242c535d596231e2f655109b97fa2bc 160000 (submodule)
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 0dbbe3f55352241d290403577dfebed802d6fd9a
+Subproject commit daf7f8c02242c535d596231e2f655109b97fa2bc
index dee3c3bbfed0ef52facee10c4ee36a77609b6731..b063c6b622b38cb036b03cb1a5b6762f10507487 100644 (file)
@@ -124,7 +124,7 @@ warn_at_indent (location loc, unsigned *indent,
     return;
   set_warning_issued ();
   indent_ptr = indent;
-  ERROR_MESSAGE (&loc, _("warning"), message);
+  ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message);
 }
 
 void
@@ -144,7 +144,7 @@ warn (const char *message, ...)
 void
 complain_at (location loc, const char *message, ...)
 {
-  ERROR_MESSAGE (&loc, NULL, message);
+  ERROR_MESSAGE (&loc, _("error"), message);
   complaint_issued = true;
 }
 
@@ -153,14 +153,14 @@ complain_at_indent (location loc, unsigned *indent,
                     const char *message, ...)
 {
   indent_ptr = indent;
-  ERROR_MESSAGE (&loc, NULL, message);
+  ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message);
   complaint_issued = true;
 }
 
 void
 complain (const char *message, ...)
 {
-  ERROR_MESSAGE (NULL, NULL, message);
+  ERROR_MESSAGE (NULL, _("error"), message);
   complaint_issued = true;
 }
 
index b893564573415a045f98bdf2822386c59182e95b..997d577b6ff05ae74bb0d32d12e6846408b25fe5 100644 (file)
@@ -25,6 +25,9 @@
 extern "C" {
 # endif
 
+/* Sub-messages indent. */
+#define SUB_INDENT (4)
+
 /** Record that a warning is about to be issued, and treat it as an
     error if <tt>warnings_flag & warnings_error</tt>.  This is exported
     only for the sake of Yacc-compatible conflict reports in conflicts.c.
index 649056943d99bb5653a04aedab25fa0473e977d3..226e6de0f6aff21e43f0118f6cf3ce68606a835b 100644 (file)
@@ -343,13 +343,14 @@ Warning categories include:\n\
   `yacc'            incompatibilities with POSIX Yacc\n\
   `conflicts-sr'    S/R conflicts (enabled by default)\n\
   `conflicts-rr'    R/R conflicts (enabled by default)\n\
+  `deprecated'      obsolete constructs\n\
   `other'           all other warnings (enabled by default)\n\
   `all'             all the warnings\n\
   `no-CATEGORY'     turn off warnings in CATEGORY\n\
   `none'            turn off all the warnings\n\
   `error'           treat warnings as errors\n\
-\n\
 "), stdout);
+      putc ('\n', stdout);
 
       fputs (_("\
 THINGS is a list of comma separated words that can include:\n\
index 46c22a8c99423675383a4e6b970c815395e1af8b..3ae0b54660a3c9d2eb63204800cdc7b56f90aea5 100644 (file)
 #include <quotearg.h>
 
 #include "files.h"
+#include "gram.h"
 #include "graphviz.h"
+#include "tables.h"
 
 /* Return an unambiguous printable representation for NAME, suitable
    for C strings.  Use slot 2 since the user may use slots 0 and 1.  */
 
-static char const *
+static char *
 quote (char const *name)
 {
   return quotearg_n_style (2, c_quoting_style, name);
@@ -51,17 +53,21 @@ start_graph (FILE *fout)
            "digraph %s\n"
            "{\n",
            quote (grammar_file));
+  fprintf (fout,
+           "  node [fontname = courier, shape = box, colorscheme = paired6]\n"
+           "  edge [fontname = courier]\n"
+           "\n");
 }
 
 void
 output_node (int id, char const *label, FILE *fout)
 {
-  fprintf (fout, "  %d [label=%s]\n", id, quote (label));
+  fprintf (fout, "  %d [label=\"%s\"]\n", id, label);
 }
 
 void
 output_edge (int source, int destination, char const *label,
-            char const *style, FILE *fout)
+             char const *style, FILE *fout)
 {
   fprintf (fout, "  %d -> %d [style=%s", source, destination, style);
   if (label)
@@ -69,6 +75,137 @@ output_edge (int source, int destination, char const *label,
   fputs ("]\n", fout);
 }
 
+char const *
+escape (char const *name)
+{
+  char *q = quote (name);
+  q[strlen (q) - 1] = '\0';
+  return q + 1;
+}
+
+static void
+no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
+{
+  int n;
+  *no_reduce_set = bitset_create (ntokens, BITSET_FIXED);
+  bitset_zero (*no_reduce_set);
+  FOR_EACH_SHIFT (s->transitions, n)
+    bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n));
+  for (n = 0; n < s->errs->num; ++n)
+    if (s->errs->symbols[n])
+      bitset_set (*no_reduce_set, s->errs->symbols[n]->number);
+}
+
+static void
+conclude_red (struct obstack *out, int source, rule_number ruleno,
+              bool enabled, bool first, FILE *fout)
+{
+  /* If no lookahead tokens were valid transitions, this reduction is
+     actually hidden, so cancel everything. */
+  if (first)
+    return (void) obstack_finish0 (out);
+  else
+    {
+      char const *ed = enabled ? "e" : "d";
+      char const *color = enabled ? ruleno ? "3" : "1" : "5";
+
+      /* First, build the edge's head. The name of reduction nodes is "nRm",
+         with n the source state and m the rule number. This is because we
+         don't want all the reductions bearing a same rule number to point to
+         the same state, since that is not the desired format. */
+      fprintf (fout, "  %1$d -> \"%1$dR%2$d%3$s\" [",
+               source, ruleno, ed);
+
+      if (! obstack_empty_p (out))
+        /* (The lookahead tokens have been added to the beginning of the
+           obstack, in the caller function.) */
+        fprintf (fout, "label = \"[%s]\" ", obstack_finish0 (out));
+
+      /* Then, the edge's tail. */
+      fprintf (fout, "style = solid]\n");
+
+      /* Build the associated diamond representation of the target rule. */
+      fprintf (fout, " \"%dR%d%s\" [style = filled, "
+                    "shape = diamond, fillcolor = %s, ",
+               source, ruleno, ed, color);
+
+     if (ruleno)
+        fprintf (fout, "label = \"R%d\"]\n", ruleno);
+      else
+        fprintf (fout, "label = \"Acc\"]\n");
+
+    }
+}
+
+static bool
+print_token (struct obstack *out, bool first, char const *tok)
+{
+  char const *q = escape (tok);
+
+  if (! first)
+    obstack_sgrow (out, ", ");
+  obstack_sgrow (out, q);
+  return false;
+}
+
+void
+output_red (state const *s, reductions const *reds, FILE *fout)
+{
+  bitset no_reduce_set;
+  int j;
+  int source = s->number;
+
+  /* Two obstacks are needed: one for the enabled reductions, and one
+     for the disabled reductions, because in the end we want two
+     separate edges, even though in most cases only one will actually
+     be printed. */
+  struct obstack dout;
+  struct obstack eout;
+
+  no_reduce_bitset_init (s, &no_reduce_set);
+  obstack_init (&dout);
+  obstack_init (&eout);
+
+  for (j = 0; j < reds->num; ++j)
+    {
+      bool defaulted = false;
+      bool firstd = true;
+      bool firste = true;
+      rule_number ruleno = reds->rules[j]->user_number;
+      rule *default_reduction = NULL;
+
+      if (yydefact[s->number] != 0)
+        default_reduction = &rules[yydefact[s->number] - 1];
+
+      /* Build the lookahead tokens lists, one for enabled transitions and one
+         for disabled transistions. */
+      if (default_reduction && default_reduction == reds->rules[j])
+        defaulted = true;
+      if (reds->lookahead_tokens)
+        {
+          int i;
+          for (i = 0; i < ntokens; i++)
+            if (bitset_test (reds->lookahead_tokens[j], i))
+              {
+                if (bitset_test (no_reduce_set, i))
+                  firstd = print_token (&dout, firstd, symbols[i]->tag);
+                else
+                  {
+                    if (! defaulted)
+                      firste = print_token (&eout, firste, symbols[i]->tag);
+                    bitset_set (no_reduce_set, i);
+                  }
+              }
+        }
+
+      /* Do the actual output. */
+      conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout);
+      conclude_red (&dout, source, ruleno, false, firstd, fout);
+    }
+  obstack_free (&eout, 0);
+  obstack_free (&dout, 0);
+}
+
 void
 finish_graph (FILE *fout)
 {
index 556fdda1bbaa9bfa0f5fa2a510000e8a384722e3..371b15c5c288021b5cc1215c5227f37044788838 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef GRAPHVIZ_H_
 # define GRAPHVIZ_H_
 
+#include "state.h"
+
 /// Begin a Dot graph.
 /// \param fout   output stream.
 void start_graph (FILE *fout);
@@ -40,10 +42,20 @@ void output_node (int id, char const *label, FILE *fout);
 /// \param style        Dot style of the edge (e.g., "dotted" or "solid").
 /// \param fout         output stream.
 void output_edge (int source, int destination, char const *label,
-                 char const *style, FILE *fout);
+                  char const *style, FILE *fout);
+
+/// Output a reduction.
+/// \param s            current state
+/// \param reds         the set of reductions
+/// \param fout         output stream.
+void output_red (state const *s, reductions const *reds, FILE *fout);
 
 /// End a Dot graph.
 /// \param fout  output stream.
 void finish_graph (FILE *fout);
 
+/// Escape a lookahead token.
+/// \param name         the token.
+char const *escape (char const *name);
+
 #endif /* ! GRAPHVIZ_H_ */
index bd1fd174719941c0ea86b2e727e34404d6dbf13f..936af700af534582e167a15e3c962c2399a26b2a 100644 (file)
@@ -396,47 +396,61 @@ muscle_user_name_list_grow (char const *key, char const *user_name,
   muscle_grow (key, "]]", "");
 }
 
+/** If the \a variable name is obsolete, return the name to use,
+ * otherwise \a variable. */
+static
+char const *
+muscle_percent_variable_update (char const *variable)
+{
+  typedef struct
+  {
+    const char *obsolete;
+    const char *updated;
+  } conversion_type;
+  const conversion_type conversion[] =
+    {
+      { "api.push_pull", "api.push-pull", },
+      { "location_type", "api.location.type", },
+      { "lr.keep_unreachable_states", "lr.keep-unreachable-states", },
+    };
+  char const *res = variable;
+  int i;
+  for (i = 0; i < ARRAY_CARDINALITY (conversion); ++i)
+    if (STREQ (conversion[i].obsolete, variable))
+      {
+        res = conversion[i].updated;
+        break;
+      }
+  return res;
+}
+
 void
-muscle_percent_define_insert (char const *variable, location variable_loc,
+muscle_percent_define_insert (char const *var, location variable_loc,
                               char const *value,
                               muscle_percent_define_how how)
 {
-  char *variable_tr = NULL;
-  char const *name;
-  char const *loc_name;
-  char const *syncline_name;
-  char const *how_name;
-
-  /* Permit certain names with underscores for backward compatibility.  */
-  if (0 == strcmp (variable, "api.push_pull")
-      || 0 == strcmp (variable, "lr.keep_unreachable_states"))
-    {
-      variable_tr = strdup (variable);
-      tr (variable_tr, '_', '-');
-      variable = variable_tr;
-    }
-
-  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
-  syncline_name =
+  /* Backward compatibility.  */
+  char const *variable = muscle_percent_variable_update (var);
+  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
+  char const *syncline_name =
     UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
-  how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
+  char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
 
   /* Command-line options are processed before the grammar file.  */
   if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
       && muscle_find_const (name))
     {
+      unsigned i = 0;
       muscle_percent_define_how how_old =
         atoi (muscle_find_const (how_name));
       if (how_old == MUSCLE_PERCENT_DEFINE_F)
-        {
-          free (variable_tr);
-          return;
-        }
-      complain_at (variable_loc, _("%%define variable %s redefined"),
-                   quote (variable));
-      complain_at (muscle_percent_define_get_loc (variable),
-                   _("previous definition"));
+        return;
+      complain_at_indent (variable_loc, &i,
+                          _("%%define variable %s redefined"), quote (variable));
+      i += SUB_INDENT;
+      complain_at_indent (muscle_percent_define_get_loc (variable), &i,
+                          _("previous definition"));
     }
 
   MUSCLE_INSERT_STRING (name, value);
@@ -447,8 +461,6 @@ muscle_percent_define_insert (char const *variable, location variable_loc,
   muscle_user_name_list_grow ("percent_define_user_variables", variable,
                               variable_loc);
   MUSCLE_INSERT_INT (how_name, how);
-
-  free (variable_tr);
 }
 
 char *
@@ -591,12 +603,15 @@ muscle_percent_define_check_values (char const * const *values)
             }
           if (!*values)
             {
+              unsigned i = 0;
               location loc = muscle_percent_define_get_loc (*variablep);
-              complain_at(loc,
-                          _("invalid value for %%define variable %s: %s"),
-                          quote (*variablep), quote_n (1, value));
+              complain_at_indent (loc, &i,
+                                _("invalid value for %%define variable %s: %s"),
+                                  quote (*variablep), quote_n (1, value));
+              i += SUB_INDENT;
               for (values = variablep + 1; *values; ++values)
-                complain_at (loc, _("accepted value: %s"), quote (*values));
+                complain_at_indent (loc, &i, _("accepted value: %s"),
+                                    quote (*values));
             }
           else
             {
index 4a4d62d1a8ece8d4d208b7d3c98c5e1a1e1d2405..3852729bb7694436a238e282c1c33fa6c83cd4f9 100644 (file)
@@ -41,8 +41,6 @@
 #include "symtab.h"
 #include "tables.h"
 
-# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
-
 static struct obstack format_obstack;
 
 
index a02e68b669a2a290c415a8c223a3878c48330951..2c08b106ffeee24c865cc5b19f8fadbdf4ef3bb2 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.6.4.15-c3a5a-dirty.  */
+/* A Bison parser, made by GNU Bison 2.6.4.11-d01f-dirty.  */
 
 /* Bison implementation for Yacc-like parsers in C
    
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.6.4.15-c3a5a-dirty"
+#define YYBISON_VERSION "2.6.4.11-d01f-dirty"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -72,7 +72,7 @@
 #define yylloc          gram_lloc
 
 /* Copy the first part of user declarations.  */
-/* Line 359 of yacc.c  */
+/* Line 358 of yacc.c  */
 #line 1 "parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
@@ -168,7 +168,7 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 #define YYTYPE_UINT16 uint_fast16_t
 #define YYTYPE_UINT8 uint_fast8_t
 
-/* Line 359 of yacc.c  */
+/* Line 358 of yacc.c  */
 #line 173 "parse-gram.c"
 
 # ifndef YY_NULL
@@ -334,7 +334,7 @@ extern int gram_debug;
 #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
 typedef union GRAM_STYPE
 {
-/* Line 375 of yacc.c  */
+/* Line 374 of yacc.c  */
 #line 115 "parse-gram.y"
 
   symbol *symbol;
@@ -348,7 +348,7 @@ typedef union GRAM_STYPE
   named_ref *named_ref;
 
 
-/* Line 375 of yacc.c  */
+/* Line 374 of yacc.c  */
 #line 353 "parse-gram.c"
 } GRAM_STYPE;
 # define GRAM_STYPE_IS_TRIVIAL 1
@@ -388,7 +388,7 @@ int gram_parse ();
 
 /* Copy the second part of user declarations.  */
 
-/* Line 378 of yacc.c  */
+/* Line 377 of yacc.c  */
 #line 393 "parse-gram.c"
 
 #ifdef short
@@ -1078,129 +1078,129 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
   switch (yytype)
     {
       case 3: /* "string" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 205 "parse-gram.y"
        { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1086 "parse-gram.c"
        break;
       case 4: /* "integer" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 217 "parse-gram.y"
        { fprintf (stderr, "%d", ((*yyvaluep).integer)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1093 "parse-gram.c"
        break;
       case 43: /* "{...}" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 207 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1100 "parse-gram.c"
        break;
       case 44: /* "[identifier]" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 212 "parse-gram.y"
        { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1107 "parse-gram.c"
        break;
       case 45: /* "char" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 199 "parse-gram.y"
        { fputs (char_name (((*yyvaluep).character)), stderr); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1114 "parse-gram.c"
        break;
       case 46: /* "epilogue" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 207 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1121 "parse-gram.c"
        break;
       case 48: /* "identifier" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 211 "parse-gram.y"
        { fputs (((*yyvaluep).uniqstr), stderr); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1128 "parse-gram.c"
        break;
       case 49: /* "identifier:" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 213 "parse-gram.y"
        { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1135 "parse-gram.c"
        break;
       case 52: /* "%{...%}" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 207 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1142 "parse-gram.c"
        break;
       case 54: /* "type" */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 214 "parse-gram.y"
        { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1149 "parse-gram.c"
        break;
       case 71: /* symbol.prec */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 220 "parse-gram.y"
        { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1156 "parse-gram.c"
        break;
       case 84: /* variable */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 211 "parse-gram.y"
        { fputs (((*yyvaluep).uniqstr), stderr); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1163 "parse-gram.c"
        break;
       case 85: /* content.opt */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 207 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1170 "parse-gram.c"
        break;
       case 86: /* braceless */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 207 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1177 "parse-gram.c"
        break;
       case 87: /* id */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 220 "parse-gram.y"
        { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1184 "parse-gram.c"
        break;
       case 88: /* id_colon */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 221 "parse-gram.y"
        { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1191 "parse-gram.c"
        break;
       case 89: /* symbol */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 220 "parse-gram.y"
        { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1198 "parse-gram.c"
        break;
       case 90: /* string_as_id */
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 220 "parse-gram.y"
        { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 829 of yacc.c  */
+/* Line 828 of yacc.c  */
 #line 1205 "parse-gram.c"
        break;
       default:
@@ -1877,7 +1877,7 @@ yyparse ()
 int yychar;
 
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__))
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
     _Pragma ("GCC diagnostic push") \
@@ -1888,26 +1888,21 @@ int yychar;
 /* Default value used for initialization, for pacifying older GCCs
    or non-GCC compilers.  */
 static YYSTYPE yyval_default;
-static YYLTYPE yyloc_default
-# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
-  = { 1, 1, 1, 1 }
-# endif
-  ;
-# define YY_INITIAL_VALUE(Value) = Value
+# define YYLVAL_INITIALIZE() (yylval = yyval_default)
+#endif
+#ifndef YYLVAL_INITIALIZE
+# define YYLVAL_INITIALIZE()
 #endif
 #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
 # define YY_IGNORE_MAYBE_UNINITIALIZED_END
 #endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
 
 /* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+YYSTYPE yylval;
 
 /* Location data for the lookahead symbol.  */
-YYLTYPE yylloc YY_INITIAL_VALUE(yyloc_default);
+YYLTYPE yylloc;
 
     /* Number of syntax errors so far.  */
     int yynerrs;
@@ -1996,8 +1991,15 @@ YYLTYPE yylloc YY_INITIAL_VALUE(yyloc_default);
   yyvsp = yyvs;
   yylsp = yyls;
 
+  YYLVAL_INITIALIZE ();
+#if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 1;
+#endif
+
 /* User initialization code.  */
-/* Line 1585 of yacc.c  */
+/* Line 1591 of yacc.c  */
 #line 107 "parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
@@ -2005,8 +2007,8 @@ YYLTYPE yylloc YY_INITIAL_VALUE(yyloc_default);
   boundary_set (&yylloc.start, current_file, 1, 1);
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
-/* Line 1585 of yacc.c  */
-#line 2010 "parse-gram.c"
+/* Line 1591 of yacc.c  */
+#line 2012 "parse-gram.c"
   yylsp[0] = yylloc;
   goto yysetstate;
 
@@ -2200,7 +2202,7 @@ yyreduce:
     switch (yyn)
       {
           case 6:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 246 "parse-gram.y"
     {
       code_props plain_code;
@@ -2214,13 +2216,13 @@ yyreduce:
     break;
 
   case 7:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 255 "parse-gram.y"
     { debug = true; }
     break;
 
   case 8:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 257 "parse-gram.y"
     {
       muscle_percent_define_insert ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars),
@@ -2229,13 +2231,13 @@ yyreduce:
     break;
 
   case 9:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 261 "parse-gram.y"
     { defines_flag = true; }
     break;
 
   case 10:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 263 "parse-gram.y"
     {
       defines_flag = true;
@@ -2244,37 +2246,37 @@ yyreduce:
     break;
 
   case 11:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 267 "parse-gram.y"
     { error_verbose = true; }
     break;
 
   case 12:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 268 "parse-gram.y"
     { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 13:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 269 "parse-gram.y"
     { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 14:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 270 "parse-gram.y"
     { spec_file_prefix = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 15:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 271 "parse-gram.y"
     { spec_file_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 16:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 273 "parse-gram.y"
     {
       nondeterministic_parser = true;
@@ -2283,7 +2285,7 @@ yyreduce:
     break;
 
   case 17:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 278 "parse-gram.y"
     {
       code_props action;
@@ -2296,67 +2298,67 @@ yyreduce:
     break;
 
   case 18:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 286 "parse-gram.y"
     { language_argmatch ((yyvsp[(2) - (2)].chars), grammar_prio, (yylsp[(1) - (2)])); }
     break;
 
   case 19:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 287 "parse-gram.y"
     { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
     break;
 
   case 20:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 288 "parse-gram.y"
     { locations_flag = true; }
     break;
 
   case 21:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 289 "parse-gram.y"
     { spec_name_prefix = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 22:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 290 "parse-gram.y"
     { spec_name_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 23:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 291 "parse-gram.y"
     { no_lines_flag = true; }
     break;
 
   case 24:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 292 "parse-gram.y"
     { nondeterministic_parser = true; }
     break;
 
   case 25:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 293 "parse-gram.y"
     { spec_outfile = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 26:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 294 "parse-gram.y"
     { spec_outfile = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 27:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 295 "parse-gram.y"
     { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
     break;
 
   case 28:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 297 "parse-gram.y"
     {
       /* %pure-parser is deprecated in favor of `%define api.pure', so use
@@ -2375,13 +2377,13 @@ yyreduce:
     break;
 
   case 29:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 311 "parse-gram.y"
     { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); }
     break;
 
   case 30:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 313 "parse-gram.y"
     {
       char const *skeleton_user = (yyvsp[(2) - (2)].chars);
@@ -2409,25 +2411,25 @@ yyreduce:
     break;
 
   case 31:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 336 "parse-gram.y"
     { token_table_flag = true; }
     break;
 
   case 32:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 337 "parse-gram.y"
     { report_flag |= report_states; }
     break;
 
   case 33:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 338 "parse-gram.y"
     { yacc_flag = true; }
     break;
 
   case 37:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 346 "parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]));
@@ -2435,7 +2437,7 @@ yyreduce:
     break;
 
   case 38:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 350 "parse-gram.y"
     {
       code_props code;
@@ -2451,7 +2453,7 @@ yyreduce:
     break;
 
   case 39:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 362 "parse-gram.y"
     {
       code_props code;
@@ -2467,7 +2469,7 @@ yyreduce:
     break;
 
   case 40:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 374 "parse-gram.y"
     {
       default_prec = true;
@@ -2475,7 +2477,7 @@ yyreduce:
     break;
 
   case 41:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 378 "parse-gram.y"
     {
       default_prec = false;
@@ -2483,7 +2485,7 @@ yyreduce:
     break;
 
   case 42:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 382 "parse-gram.y"
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
@@ -2494,7 +2496,7 @@ yyreduce:
     break;
 
   case 43:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 389 "parse-gram.y"
     {
       muscle_percent_code_grow ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)]));
@@ -2503,19 +2505,19 @@ yyreduce:
     break;
 
   case 44:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 403 "parse-gram.y"
     {}
     break;
 
   case 45:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 404 "parse-gram.y"
     { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 46:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 409 "parse-gram.y"
     {
       union_seen = true;
@@ -2525,13 +2527,13 @@ yyreduce:
     break;
 
   case 47:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 420 "parse-gram.y"
     { current_class = nterm_sym; }
     break;
 
   case 48:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 421 "parse-gram.y"
     {
       current_class = unknown_sym;
@@ -2540,13 +2542,13 @@ yyreduce:
     break;
 
   case 49:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 425 "parse-gram.y"
     { current_class = token_sym; }
     break;
 
   case 50:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 426 "parse-gram.y"
     {
       current_class = unknown_sym;
@@ -2555,7 +2557,7 @@ yyreduce:
     break;
 
   case 51:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 431 "parse-gram.y"
     {
       symbol_list *list;
@@ -2567,7 +2569,7 @@ yyreduce:
     break;
 
   case 52:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 442 "parse-gram.y"
     {
       symbol_list *list;
@@ -2583,109 +2585,109 @@ yyreduce:
     break;
 
   case 53:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 456 "parse-gram.y"
     { (yyval.assoc) = left_assoc; }
     break;
 
   case 54:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 457 "parse-gram.y"
     { (yyval.assoc) = right_assoc; }
     break;
 
   case 55:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 458 "parse-gram.y"
     { (yyval.assoc) = non_assoc; }
     break;
 
   case 56:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 462 "parse-gram.y"
     { current_type = NULL; }
     break;
 
   case 57:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 463 "parse-gram.y"
     { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; }
     break;
 
   case 58:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 469 "parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 59:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 471 "parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); }
     break;
 
   case 60:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 475 "parse-gram.y"
     { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
     break;
 
   case 61:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 476 "parse-gram.y"
     { (yyval.symbol) = (yyvsp[(1) - (2)].symbol); symbol_user_token_number_set ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].integer), (yylsp[(2) - (2)])); }
     break;
 
   case 62:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 482 "parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 63:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 484 "parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); }
     break;
 
   case 64:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 488 "parse-gram.y"
     { (yyval.list) = (yyvsp[(1) - (1)].list); }
     break;
 
   case 65:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 489 "parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); }
     break;
 
   case 66:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 493 "parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 67:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 494 "parse-gram.y"
     { (yyval.list) = symbol_list_type_new ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 68:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 495 "parse-gram.y"
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); }
     break;
 
   case 69:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 496 "parse-gram.y"
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); }
     break;
 
   case 70:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 502 "parse-gram.y"
     {
        current_type = (yyvsp[(1) - (1)].uniqstr);
@@ -2694,7 +2696,7 @@ yyreduce:
     break;
 
   case 71:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 507 "parse-gram.y"
     {
        symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true);
@@ -2703,7 +2705,7 @@ yyreduce:
     break;
 
   case 72:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 512 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
@@ -2713,7 +2715,7 @@ yyreduce:
     break;
 
   case 73:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 518 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
@@ -2723,7 +2725,7 @@ yyreduce:
     break;
 
   case 74:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 524 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true);
@@ -2734,7 +2736,7 @@ yyreduce:
     break;
 
   case 81:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 554 "parse-gram.y"
     {
       yyerrok;
@@ -2742,13 +2744,13 @@ yyreduce:
     break;
 
   case 82:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 560 "parse-gram.y"
     { current_lhs ((yyvsp[(1) - (2)].symbol), (yylsp[(1) - (2)]), (yyvsp[(2) - (2)].named_ref)); }
     break;
 
   case 83:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 561 "parse-gram.y"
     {
     /* Free the current lhs. */
@@ -2757,86 +2759,86 @@ yyreduce:
     break;
 
   case 84:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 568 "parse-gram.y"
     { grammar_current_rule_end ((yylsp[(1) - (1)])); }
     break;
 
   case 85:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 569 "parse-gram.y"
     { grammar_current_rule_end ((yylsp[(3) - (3)])); }
     break;
 
   case 87:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 575 "parse-gram.y"
     { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
                                  current_lhs_named_ref); }
     break;
 
   case 88:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 578 "parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[(2) - (3)].symbol), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); }
     break;
 
   case 89:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 580 "parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); }
     break;
 
   case 90:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 582 "parse-gram.y"
     { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
     break;
 
   case 91:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 584 "parse-gram.y"
     { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
     break;
 
   case 92:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 586 "parse-gram.y"
     { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
     break;
 
   case 93:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 590 "parse-gram.y"
     { (yyval.named_ref) = 0; }
     break;
 
   case 94:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 592 "parse-gram.y"
     { (yyval.named_ref) = named_ref_new((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 96:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 604 "parse-gram.y"
     { (yyval.uniqstr) = uniqstr_new ((yyvsp[(1) - (1)].chars)); }
     break;
 
   case 97:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 609 "parse-gram.y"
     { (yyval.chars) = ""; }
     break;
 
   case 98:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 610 "parse-gram.y"
     { (yyval.chars) = (yyvsp[(1) - (1)].uniqstr); }
     break;
 
   case 100:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 621 "parse-gram.y"
     {
       code_props plain_code;
@@ -2849,13 +2851,13 @@ yyreduce:
     break;
 
   case 101:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 641 "parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 102:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 643 "parse-gram.y"
     {
       (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
@@ -2865,13 +2867,13 @@ yyreduce:
     break;
 
   case 103:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 651 "parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 106:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 663 "parse-gram.y"
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
@@ -2880,7 +2882,7 @@ yyreduce:
     break;
 
   case 108:
-/* Line 1802 of yacc.c  */
+/* Line 1808 of yacc.c  */
 #line 672 "parse-gram.y"
     {
       code_props plain_code;
@@ -2893,8 +2895,8 @@ yyreduce:
     break;
 
 
-/* Line 1802 of yacc.c  */
-#line 2898 "parse-gram.c"
+/* Line 1808 of yacc.c  */
+#line 2900 "parse-gram.c"
         default: break;
       }
     if (yychar_backup != yychar)
@@ -3144,7 +3146,7 @@ yyreturn:
 }
 
 
-/* Line 2065 of yacc.c  */
+/* Line 2071 of yacc.c  */
 #line 682 "parse-gram.y"
 
 
index 22b467e0d9f1b7014b428b77b423cd67fa5d5b1d..39e299866a3239011aff3a137689d06d706a558b 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.6.4.15-c3a5a-dirty.  */
+/* A Bison parser, made by GNU Bison 2.6.4.11-d01f-dirty.  */
 
 /* Bison interface for Yacc-like parsers in C
    
@@ -175,7 +175,7 @@ extern int gram_debug;
 #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
 typedef union GRAM_STYPE
 {
-/* Line 2066 of yacc.c  */
+/* Line 2072 of yacc.c  */
 #line 115 "parse-gram.y"
 
   symbol *symbol;
@@ -189,7 +189,7 @@ typedef union GRAM_STYPE
   named_ref *named_ref;
 
 
-/* Line 2066 of yacc.c  */
+/* Line 2072 of yacc.c  */
 #line 194 "parse-gram.h"
 } GRAM_STYPE;
 # define GRAM_STYPE_IS_TRIVIAL 1
index f5695a7a734951fe65d5d498359f3fd66522292f..d5ec5fb4212497fe2ddd865786e4951f23fcc581 100644 (file)
@@ -18,6 +18,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
+#include <quotearg.h>
 #include "system.h"
 
 #include "LR0.h"
 | Construct the node labels.  |
 `----------------------------*/
 
+/* Print the lhs of a rule in such a manner that there is no vertical
+   repetition, like in *.output files. */
+
+static void
+print_lhs (struct obstack *oout, rule *previous_rule, rule *r)
+{
+  if (previous_rule && STREQ (previous_rule->lhs->tag, r->lhs->tag))
+    {
+      int i;
+      for (i = 0; i < strlen (r->lhs->tag); ++i)
+        obstack_1grow (oout, ' ');
+      obstack_1grow (oout, '|');
+    }
+  else
+    {
+      obstack_sgrow (oout, escape (r->lhs->tag));
+      obstack_1grow (oout, ':');
+    }
+}
+
 static void
 print_core (struct obstack *oout, state *s)
 {
-  size_t i;
   item_number *sitems = s->items;
+  rule *previous_rule = NULL;
+  size_t i;
   size_t snritems = s->nitems;
 
   /* Output all the items of a state, not only its kernel.  */
@@ -54,7 +76,8 @@ print_core (struct obstack *oout, state *s)
       snritems = nitemset;
     }
 
-  obstack_printf (oout, "%d", s->number);
+  obstack_printf (oout, _("State %d"), s->number);
+  obstack_sgrow (oout, "\\n");
   for (i = 0; i < snritems; i++)
     {
       item_number *sp;
@@ -64,43 +87,47 @@ print_core (struct obstack *oout, state *s)
       sp1 = sp = ritem + sitems[i];
 
       while (*sp >= 0)
-       sp++;
+        sp++;
 
       r = item_number_as_rule_number (*sp);
 
-      obstack_printf (oout, "\n%s -> ", rules[r].lhs->tag);
+      obstack_printf (oout, "%3d ", r);
+      print_lhs (oout, previous_rule, &rules[r]);
+      previous_rule = &rules[r];
 
       for (sp = rules[r].rhs; sp < sp1; sp++)
-       obstack_printf (oout, "%s ", symbols[*sp]->tag);
+        obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
 
-      obstack_1grow (oout, '.');
+      obstack_sgrow (oout, " .");
 
       for (/* Nothing */; *sp >= 0; ++sp)
-       obstack_printf (oout, " %s", symbols[*sp]->tag);
+        obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
 
       /* Experimental feature: display the lookahead tokens. */
       if (report_flag & report_lookahead_tokens
           && item_number_is_rule_number (*sp1))
-       {
-         /* Find the reduction we are handling.  */
-         reductions *reds = s->reductions;
-         int redno = state_reduction_find (s, &rules[r]);
-
-         /* Print them if there are.  */
-         if (reds->lookahead_tokens && redno != -1)
-           {
-             bitset_iterator biter;
-             int k;
-             char const *sep = "";
-             obstack_sgrow (oout, "[");
-             BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
-               {
-                 obstack_printf (oout, "%s%s", sep, symbols[k]->tag);
-                 sep = ", ";
-               }
-             obstack_sgrow (oout, "]");
-           }
-       }
+        {
+          /* Find the reduction we are handling.  */
+          reductions *reds = s->reductions;
+          int redno = state_reduction_find (s, &rules[r]);
+
+          /* Print them if there are.  */
+          if (reds->lookahead_tokens && redno != -1)
+            {
+              bitset_iterator biter;
+              int k;
+              char const *sep = "";
+              obstack_sgrow (oout, "  [");
+              BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
+                {
+                  obstack_sgrow (oout, sep);
+                  obstack_sgrow (oout, escape (symbols[k]->tag));
+                  sep = ", ";
+                }
+              obstack_1grow (oout, ']');
+            }
+        }
+      obstack_sgrow (oout, "\\l");
     }
 }
 
@@ -113,9 +140,11 @@ print_core (struct obstack *oout, state *s)
 static void
 print_actions (state const *s, FILE *fgraph)
 {
+  transitions const *trans = s->transitions;
   int i;
 
-  transitions const *trans = s->transitions;
+  /* Display reductions. */
+  output_red (s, s->reductions, fgraph);
 
   if (!trans->num && !s->reductions)
     return;
index 7dd0aaa46c7b13d528e31a18746a4501175bd945..86fde7b2e4303b3371b233a48a9da98673e2a27b 100644 (file)
@@ -128,12 +128,16 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc)
   aver (merge_function != NULL && merger_find == merger);
   if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
     {
-      complain_at (declaration_loc,
-                   _("result type clash on merge function %s: <%s> != <%s>"),
-                   quote (merge_function->name), type, merge_function->type);
-      complain_at (merge_function->type_declaration_location,
-                  _("previous declaration"));
-    }
+      unsigned indent = 0;
+      complain_at_indent (declaration_loc, &indent,
+                          _("result type clash on merge function %s: "
+                            "<%s> != <%s>"),
+                          quote (merge_function->name), type,
+                          merge_function->type);
+      indent += SUB_INDENT;
+      complain_at_indent (merge_function->type_declaration_location, &indent,
+                          _("previous declaration"));
+   }
   merge_function->type = uniqstr_new (type);
   merge_function->type_declaration_location = declaration_loc;
 }
index 002f6e37f84e346b274813eaaf77fcd28923ba12..56cfe5118d1dd145a81ed81777752ba82b8671f0 100644 (file)
@@ -150,16 +150,20 @@ static void
 symbol_redeclaration (symbol *s, const char *what, location first,
                       location second)
 {
-  complain_at (second, _("%s redeclaration for %s"), what, s->tag);
-  complain_at (first, _("previous declaration"));
+  unsigned i = 0;
+  complain_at_indent (second, &i, _("%s redeclaration for %s"), what, s->tag);
+  i += SUB_INDENT;
+  complain_at_indent (first, &i, _("previous declaration"));
 }
 
 static void
 semantic_type_redeclaration (semantic_type *s, const char *what, location first,
                              location second)
 {
-  complain_at (second, _("%s redeclaration for <%s>"), what, s->tag);
-  complain_at (first, _("previous declaration"));
+  unsigned i = 0;
+  complain_at_indent (second, &i, _("%s redeclaration for <%s>"), what, s->tag);
+  i += SUB_INDENT;
+  complain_at_indent (first, &i, _("previous declaration"));
 }
 
 
@@ -515,6 +519,7 @@ symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
 static void
 user_token_number_redeclaration (int num, symbol *first, symbol *second)
 {
+  unsigned i = 0;
   /* User token numbers are not assigned during the parsing, but in a
      second step, via a traversal of the symbol table sorted on tag.
 
@@ -526,11 +531,13 @@ user_token_number_redeclaration (int num, symbol *first, symbol *second)
       first = second;
       second = tmp;
     }
-  complain_at (second->location,
-               _("user token number %d redeclaration for %s"),
-               num, second->tag);
-  complain_at (first->location, _("previous declaration for %s"),
-               first->tag);
+  complain_at_indent (second->location, &i,
+                      _("user token number %d redeclaration for %s"),
+                      num, second->tag);
+  i += SUB_INDENT;
+  complain_at_indent (first->location, &i,
+                      _("previous declaration for %s"),
+                      first->tag);
 }
 
 /*--------------------------------------------------.
@@ -923,10 +930,12 @@ default_tagged_destructor_set (code_props const *destructor)
 {
   if (default_tagged_destructor.code)
     {
-      complain_at (destructor->location,
-                   _("redeclaration for default tagged %%destructor"));
-      complain_at (default_tagged_destructor.location,
-                  _("previous declaration"));
+      unsigned i = 0;
+      complain_at_indent (destructor->location, &i,
+                          _("redeclaration for default tagged %%destructor"));
+      i += SUB_INDENT;
+      complain_at_indent (default_tagged_destructor.location, &i,
+                         _("previous declaration"));
     }
   default_tagged_destructor = *destructor;
 }
@@ -936,10 +945,12 @@ default_tagless_destructor_set (code_props const *destructor)
 {
   if (default_tagless_destructor.code)
     {
-      complain_at (destructor->location,
-                   _("redeclaration for default tagless %%destructor"));
-      complain_at (default_tagless_destructor.location,
-                  _("previous declaration"));
+      unsigned i = 0;
+      complain_at_indent (destructor->location, &i,
+                          _("redeclaration for default tagless %%destructor"));
+      i += SUB_INDENT;
+      complain_at_indent (default_tagless_destructor.location, &i,
+                          _("previous declaration"));
     }
   default_tagless_destructor = *destructor;
 }
@@ -949,10 +960,12 @@ default_tagged_printer_set (code_props const *printer)
 {
   if (default_tagged_printer.code)
     {
-      complain_at (printer->location,
-                   _("redeclaration for default tagged %%printer"));
-      complain_at (default_tagged_printer.location,
-                  _("previous declaration"));
+      unsigned i = 0;
+      complain_at_indent (printer->location, &i,
+                          _("redeclaration for default tagged %%printer"));
+      i += SUB_INDENT;
+      complain_at_indent (default_tagged_printer.location, &i,
+                         _("previous declaration"));
     }
   default_tagged_printer = *printer;
 }
@@ -962,10 +975,12 @@ default_tagless_printer_set (code_props const *printer)
 {
   if (default_tagless_printer.code)
     {
-      complain_at (printer->location,
-                   _("redeclaration for default tagless %%printer"));
-      complain_at (default_tagless_printer.location,
-                  _("previous declaration"));
+      unsigned i = 0;
+      complain_at_indent (printer->location, &i,
+                          _("redeclaration for default tagless %%printer"));
+      i += SUB_INDENT;
+      complain_at_indent (default_tagless_printer.location, &i,
+                         _("previous declaration"));
     }
   default_tagless_printer = *printer;
 }
index bf7f59f9dbb66ab718f148e81517aacf7efbd50b..3a82e7f3fcde9ae94760531345c15cdf2c29bbbf 100644 (file)
 # include <unistd.h>
 # include <inttypes.h>
 
+#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
+#define STREQ(L, R)  (strcmp(L, R) == 0)
+#define STRNEQ(L, R) (!STREQ(L, R))
+
 # ifndef UINTPTR_MAX
 /* This isn't perfect, but it's good enough for Bison, which needs
    only to hash pointers.  */
@@ -198,7 +202,10 @@ typedef size_t uintptr_t;
   } while (0)
 
 
+/* Append the ending 0, finish Obs, and return the string.  */
 
+# define obstack_finish0(Obs)                           \
+  (obstack_1grow (Obs, '\0'), (char *) obstack_finish (Obs))
 
 
 /*-----------------------------------------.
index c44a2a5963d467e809a6994013e61cbd0eef4b11..dba7a758d53c07b8ac7c2ca7e8bf2c5755ff019a 100644 (file)
@@ -181,3 +181,237 @@ AT_CHECK_NAMESPACE([[foo[3]::bar::baz]], [[-]])
 AT_CHECK_NAMESPACE([[foo::bar,baz]], [[-]])
 AT_CHECK_NAMESPACE([[foo::bar::(baz]], [[-]])
 AT_CLEANUP
+
+
+## ------------------ ##
+## Exception safety.  ##
+## ------------------ ##
+
+AT_SETUP([[Exception safety]])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+
+AT_DATA_GRAMMAR([[input.yy]],
+[[%skeleton "lalr1.cc"
+%defines // FIXME: Mandated in 2.6.
+%debug
+%error-verbose
+
+%code requires
+{
+  #include <cassert>
+  #include <cstdlib> // size_t and getenv.
+  #include <iostream>
+  #include <list>
+
+  bool debug = false;
+
+  /// A class that counts its number of instances.
+  struct Object
+  {
+    typedef std::list<const Object*> objects;
+    static objects instances;
+    char val;
+
+    static bool
+    empty ()
+    {
+      return instances.empty();
+    }
+
+    static void
+    log (Object const *o, const std::string& msg)
+    {
+      if (debug)
+        {
+          if (o)
+            std::cerr << o << "->";
+          std::cerr << msg << " {";
+          const char* sep = " ";
+          for (objects::const_iterator i = instances.begin(),
+                                       i_end = instances.end();
+               i != i_end;
+               ++i)
+            {
+              std::cerr << sep << *i;
+              sep = ", ";
+            }
+          std::cerr << " }" << std::endl;
+        }
+    }
+
+    Object (char v)
+      : val (v)
+    {
+      instances.push_back(this);
+      log (this, "Object::Object");
+    }
+
+    ~Object ()
+    {
+      instances.remove(this);
+      log (this, "Object::~Object");
+    }
+  };
+}
+
+%code
+{
+  #include <cassert>
+  #include <cstring> // strchr
+  #include <stdexcept>
+  int yylex (yy::parser::semantic_type *);
+  Object::objects Object::instances;
+  static char const *input;
+}
+
+%union
+{
+  Object *obj;
+}
+
+%initial-action
+{
+  if (strchr (input, 'i'))
+    throw std::runtime_error ("initial-action");
+}
+
+%destructor { delete $$; } <obj>;
+%printer
+{
+  yyo << $$ << " '" << $$->val << '\'';
+  if ($$->val == 'p')
+    throw std::runtime_error ("printer");
+} <obj>;
+
+%token <obj> 'a' 'E' 'e' 'p' 'R' 's' 'T'
+%type  <obj> list item
+
+%%
+
+start: list { delete $1; };
+
+list:
+  item       { $$ = $1; }
+| item list  { $$ = $1; delete $2; } // Right recursion to load the stack.
+;
+
+item:
+  'a'  { $$ = $1; }
+| 'e'  { YYUSE ($$); YYUSE($1); error (location_type(), "syntax error"); }
+// Not just 'E', otherwise we reduce when 'E' is the lookahead, and
+// then the stack is emptied, defeating the point of the test.
+| 'E' 'a' { YYUSE($1); $$ = $2; }
+| 'R'  { $$ = YY_NULL; delete $1; YYERROR; }
+| 'p'  { $$ = $1; }
+| 's'  { $$ = $1; throw std::runtime_error ("reduction"); }
+| 'T'  { $$ = YY_NULL; delete $1; YYABORT; }
+| error { $$ = YY_NULL; yyerrok; }
+;
+%%
+
+int
+yylex (yy::parser::semantic_type *lvalp)
+{
+  // 'a': no error.
+  // 'e': user action calls error.
+  // 'E': syntax error, with yyerror that throws.
+  // 'i': initial action throws.
+  // 'l': yylex throws.
+  // 'R': call YYERROR in the action
+  // 's': reduction throws.
+  // 'T': call YYABORT in the action
+  switch (int res = *input++)
+  {
+    case 'l':
+      throw std::runtime_error ("yylex");
+    default:
+      lvalp->obj = new Object (res);
+      // Fall through.
+    case 0:
+      return res;
+  }
+}
+
+/* A C++ error reporting function.  */
+void
+yy::parser::error (const location_type& l, const std::string& m)
+{
+  YYUSE (l);
+  throw std::runtime_error (m);
+}
+
+int
+main (int argc, const char *argv[])
+{
+  switch (argc)
+  {
+    case 2:
+      input = argv[1];
+      break;
+    case 3:
+      assert (!strcmp (argv[1], "--debug"));
+      debug = 1;
+      input = argv[2];
+      break;
+    default:
+      abort ();
+  }
+
+  yy::parser parser;
+  debug |= !!getenv ("YYDEBUG");
+  parser.set_debug_level (debug);
+  int res = 2;
+  try
+  {
+    res = parser.parse ();
+  }
+  catch (const std::exception& e)
+  {
+    std::cerr << "exception caught: " << e.what () << std::endl;
+  }
+  catch (...)
+  {
+    std::cerr << "unknown exception caught" << std::endl;
+  }
+  Object::log (YY_NULL, "end");
+  assert (Object::empty());
+  return res;
+}
+]])
+AT_BISON_CHECK([[-o input.cc --report=all input.yy]])
+AT_COMPILE_CXX([[input]])
+
+AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]],
+[[exception caught: reduction
+]])
+
+AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]],
+[[exception caught: yylex
+]])
+
+AT_PARSER_CHECK([[./input i]], [[2]], [[]],
+[[exception caught: initial-action
+]])
+
+AT_PARSER_CHECK([[./input aaaap]])
+
+AT_PARSER_CHECK([[./input --debug aaaap]], [[2]], [[]], [[stderr]])
+AT_PARSER_CHECK([[grep '^exception caught: printer$' stderr]], [], [ignore])
+
+AT_PARSER_CHECK([[./input aaaae]], [[2]], [[]],
+[[exception caught: syntax error
+]])
+
+AT_PARSER_CHECK([[./input aaaaE]], [[2]], [[]],
+[[exception caught: syntax error, unexpected $end, expecting 'a'
+]])
+
+AT_PARSER_CHECK([[./input aaaaT]], [[1]])
+
+# There is error-recovery, so exit success.
+AT_PARSER_CHECK([[./input aaaaR]], [[0]])
+
+AT_BISON_OPTION_POPDEFS
+
+AT_CLEANUP
index 062bb45ba2958c72926f8e75adeb47fa007ecec2..4ab725b38930879f0c39177fd451411015c82098 100644 (file)
@@ -677,7 +677,7 @@ m4_define([AT_CHECK_CALC_LALR1_CC],
 [AT_CHECK_CALC([%language "C++" %defines %locations] $@)])
 
 AT_CHECK_CALC_LALR1_CC([])
-AT_CHECK_CALC_LALR1_CC([%define location_type Span])
+AT_CHECK_CALC_LALR1_CC([%define api.location.type Span])
 AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
 AT_CHECK_CALC_LALR1_CC([%error-verbose %define api.prefix "calc" %verbose %yacc])
 AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
@@ -706,7 +706,7 @@ m4_define([AT_CHECK_CALC_GLR_CC],
 [AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
 
 AT_CHECK_CALC_GLR_CC([])
-AT_CHECK_CALC_GLR_CC([%define location_type Span])
+AT_CHECK_CALC_GLR_CC([%define api.location.type Span])
 AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
 AT_CHECK_CALC_GLR_CC([%error-verbose %define api.prefix "calc" %verbose %yacc])
 
index a46acc5ad74d1722de91e6c3ba225c4230bff272..3934a6cf13b4bb97a5d87017eeb6cc48940498e8 100644 (file)
@@ -896,7 +896,7 @@ exp: exp OP exp | NUM;
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
 [input.y: conflicts: 1 shift/reduce
-input.y: expected 0 shift/reduce conflicts
+input.y: error: expected 0 shift/reduce conflicts
 ])
 AT_CLEANUP
 
@@ -933,7 +933,7 @@ exp: exp OP exp | NUM;
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
 [input.y: conflicts: 1 shift/reduce
-input.y: expected 2 shift/reduce conflicts
+input.y: error: expected 2 shift/reduce conflicts
 ])
 AT_CLEANUP
 
@@ -953,7 +953,7 @@ a: 'a';
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
 [input.y: conflicts: 1 reduce/reduce
-input.y: expected 0 reduce/reduce conflicts
+input.y: error: expected 0 reduce/reduce conflicts
 ])
 AT_CLEANUP
 
@@ -1494,11 +1494,11 @@ AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
         echo "$file: conflicts: $conflicts" > experr
         if test $sr_count -ne $sr_exp; then
           if test $sr_exp -ne 1; then s=s; else s= ; fi
-          echo "$file: expected $sr_exp shift/reduce conflict$s" >> experr
+          echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr
         fi
         if test $rr_count -ne $rr_exp; then
           if test $rr_exp -ne 1; then s=s; else s= ; fi
-          echo "$file: expected $rr_exp reduce/reduce conflict$s" >> experr
+          echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr
         fi
         ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[
         ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[
index 8570b19d77082c9a3da9b276157a6ff6f9da9535..ad93d40e1b5519379b9a8ad11ebd44c0f550f650 100644 (file)
@@ -1643,10 +1643,10 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [],
-[glr-regr18.y:26.18-24: result type clash on merge function 'merge': <type2> != <type1>
-glr-regr18.y:25.18-24: previous declaration
-glr-regr18.y:27.13-19: result type clash on merge function 'merge': <type3> != <type2>
-glr-regr18.y:26.18-24: previous declaration
+[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
+glr-regr18.y:25.18-24:     previous declaration
+glr-regr18.y:27.13-19: error: result type clash on merge function 'merge': <type3> != <type2>
+glr-regr18.y:26.18-24:     previous declaration
 ])
 
 AT_CLEANUP
index a60e3153d7f198dd893c5884faa4a0ee620b52f7..8a05d34d8ddfe1cb314aa430ced0d19a30093290 100644 (file)
@@ -131,7 +131,7 @@ AT_SETUP([Several parsers])
 # self-contained, and can be compiled by a C++ compiler.
 m4_pushdef([AT_TEST],
 [AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2])
-AT_DATA_GRAMMAR([$1.AT_SKEL_CC_IF([yy], [y])],
+AT_DATA_GRAMMAR([$1.y],
 [[%define api.prefix "$1_"
 $2
 %error-verbose
@@ -161,7 +161,7 @@ exp:
 ]AT_YYLEX_DEFINE(["$1"])[
 ]])
 
-AT_BISON_CHECK([-d -o AT_SKEL_CC_IF([$1.cc $1.yy], [$1.c $1.y])])
+AT_BISON_CHECK([-d -o $1.AT_SKEL_CC_IF([cc], [c]) $1.y])
 
 # Check there is no 'yy' left.
 # C++ output relies on namespaces and still uses yy a lot.
index 2848562d9e4c6e1e56b2ba08a87afb38446f8f32..35812c807be1c4b4114d8c8d208ae3dd9ee9724e 100644 (file)
@@ -39,20 +39,20 @@ default: 'a' }
 AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:1.1: invalid character: '\0'
-input.y:1.1: invalid character: '\001'
-input.y:1.1: invalid character: '\002'
-input.y:1.1: invalid character: '\377'
-input.y:1.2: invalid character: '?'
-input.y:3.1: invalid character: '?'
-input.y:4.14: invalid character: '}'
-input.y:5.1: invalid character: '%'
-input.y:5.2: invalid character: '&'
-input.y:6.1-17: invalid directive: '%a-does-not-exist'
-input.y:7.1: invalid character: '%'
-input.y:7.2: invalid character: '-'
-input.y:8.1-9.0: missing '%}' at end of file
-input.y:8.1-9.0: syntax error, unexpected %{...%}
+[[input.y:1.1: error: invalid character: '\0'
+input.y:1.1: error: invalid character: '\001'
+input.y:1.1: error: invalid character: '\002'
+input.y:1.1: error: invalid character: '\377'
+input.y:1.2: error: invalid character: '?'
+input.y:3.1: error: invalid character: '?'
+input.y:4.14: error: invalid character: '}'
+input.y:5.1: error: invalid character: '%'
+input.y:5.2: error: invalid character: '&'
+input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
+input.y:7.1: error: invalid character: '%'
+input.y:7.2: error: invalid character: '-'
+input.y:8.1-9.0: error: missing '%}' at end of file
+input.y:8.1-9.0: error: syntax error, unexpected %{...%}
 ]])
 
 AT_CLEANUP
@@ -74,7 +74,7 @@ AT_DATA([input.y],
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...}
+[[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...}
 ]])
 
 AT_CLEANUP
@@ -94,8 +94,8 @@ exp: { @$ = @1 ; };
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:2.13-14: integer out of range: '$1'
-input.y:3.13-14: integer out of range: '@1'
+[[input.y:2.13-14: error: integer out of range: '$1'
+input.y:3.13-14: error: integer out of range: '@1'
 ]])
 
 AT_CLEANUP
@@ -119,8 +119,8 @@ exp: foo { $$; } foo { $2; } foo
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:5.12-13: $$ for the midrule at $2 of 'exp' has no declared type
-input.y:5.24-25: $2 of 'exp' has no declared type
+[[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type
+input.y:5.24-25: error: $2 of 'exp' has no declared type
 input.y:5.6-32: warning: type clash on default action: <bar> != <>
 input.y:6.6-8: warning: type clash on default action: <bar> != <>
 input.y:7.5: warning: empty rule for typed nonterminal, and no action
@@ -266,30 +266,30 @@ start: ;
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:1.13-29: redeclaration for default tagged %destructor
-input.y:1.13-29: previous declaration
-input.y:2.10-24: redeclaration for default tagged %printer
-input.y:2.10-24: previous declaration
-input.y:4.13-29: redeclaration for default tagged %destructor
-input.y:1.13-29: previous declaration
-input.y:5.10-24: redeclaration for default tagged %printer
-input.y:2.10-24: previous declaration
-input.y:7.13-29: redeclaration for default tagless %destructor
-input.y:7.13-29: previous declaration
-input.y:8.10-24: redeclaration for default tagless %printer
-input.y:8.10-24: previous declaration
-input.y:10.13-29: redeclaration for default tagless %destructor
-input.y:7.13-29: previous declaration
-input.y:11.10-24: redeclaration for default tagless %printer
-input.y:8.10-24: previous declaration
-input.y:17.13-29: redeclaration for default tagged %destructor
-input.y:4.13-29: previous declaration
-input.y:18.10-24: redeclaration for default tagged %printer
-input.y:5.10-24: previous declaration
-input.y:20.13-29: redeclaration for default tagless %destructor
-input.y:10.13-29: previous declaration
-input.y:21.10-24: redeclaration for default tagless %printer
-input.y:11.10-24: previous declaration
+[[input.y:1.13-29: error: redeclaration for default tagged %destructor
+input.y:1.13-29:     previous declaration
+input.y:2.10-24: error: redeclaration for default tagged %printer
+input.y:2.10-24:     previous declaration
+input.y:4.13-29: error: redeclaration for default tagged %destructor
+input.y:1.13-29:     previous declaration
+input.y:5.10-24: error: redeclaration for default tagged %printer
+input.y:2.10-24:     previous declaration
+input.y:7.13-29: error: redeclaration for default tagless %destructor
+input.y:7.13-29:     previous declaration
+input.y:8.10-24: error: redeclaration for default tagless %printer
+input.y:8.10-24:     previous declaration
+input.y:10.13-29: error: redeclaration for default tagless %destructor
+input.y:7.13-29:      previous declaration
+input.y:11.10-24: error: redeclaration for default tagless %printer
+input.y:8.10-24:      previous declaration
+input.y:17.13-29: error: redeclaration for default tagged %destructor
+input.y:4.13-29:      previous declaration
+input.y:18.10-24: error: redeclaration for default tagged %printer
+input.y:5.10-24:      previous declaration
+input.y:20.13-29: error: redeclaration for default tagless %destructor
+input.y:10.13-29:     previous declaration
+input.y:21.10-24: error: redeclaration for default tagless %printer
+input.y:11.10-24:     previous declaration
 ]])
 
 AT_CLEANUP
@@ -317,22 +317,22 @@ start: ;
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:4.13-29: %destructor redeclaration for <field1>
-input.y:1.13-29: previous declaration
-input.y:4.13-29: %destructor redeclaration for <field1>
-input.y:4.13-29: previous declaration
-input.y:5.10-24: %printer redeclaration for <field2>
-input.y:2.10-24: previous declaration
-input.y:5.10-24: %printer redeclaration for <field2>
-input.y:5.10-24: previous declaration
-input.y:11.13-29: %destructor redeclaration for <field1>
-input.y:4.13-29: previous declaration
-input.y:11.13-29: %destructor redeclaration for <field2>
-input.y:1.13-29: previous declaration
-input.y:12.10-24: %printer redeclaration for <field1>
-input.y:2.10-24: previous declaration
-input.y:12.10-24: %printer redeclaration for <field2>
-input.y:5.10-24: previous declaration
+[[input.y:4.13-29: error: %destructor redeclaration for <field1>
+input.y:1.13-29:     previous declaration
+input.y:4.13-29: error: %destructor redeclaration for <field1>
+input.y:4.13-29:     previous declaration
+input.y:5.10-24: error: %printer redeclaration for <field2>
+input.y:2.10-24:     previous declaration
+input.y:5.10-24: error: %printer redeclaration for <field2>
+input.y:5.10-24:     previous declaration
+input.y:11.13-29: error: %destructor redeclaration for <field1>
+input.y:4.13-29:      previous declaration
+input.y:11.13-29: error: %destructor redeclaration for <field2>
+input.y:1.13-29:      previous declaration
+input.y:12.10-24: error: %printer redeclaration for <field1>
+input.y:2.10-24:      previous declaration
+input.y:12.10-24: error: %printer redeclaration for <field2>
+input.y:5.10-24:      previous declaration
 ]])
 
 AT_CLEANUP
@@ -429,14 +429,14 @@ exp: foo;
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:8.7-11: %type redeclaration for foo
-input.y:3.7-11: previous declaration
-input.y:10.13-17: %destructor redeclaration for foo
-input.y:5.13-17: previous declaration
-input.y:9.10-14: %printer redeclaration for foo
-input.y:4.10-14: previous declaration
-input.y:11.1-5: %left redeclaration for foo
-input.y:6.1-5: previous declaration
+[[input.y:8.7-11: error: %type redeclaration for foo
+input.y:3.7-11:     previous declaration
+input.y:10.13-17: error: %destructor redeclaration for foo
+input.y:5.13-17:      previous declaration
+input.y:9.10-14: error: %printer redeclaration for foo
+input.y:4.10-14:     previous declaration
+input.y:11.1-5: error: %left redeclaration for foo
+input.y:6.1-5:      previous declaration
 ]])
 
 AT_CLEANUP
@@ -455,7 +455,7 @@ AT_SETUP([Torturing the Scanner])
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA([input.y], [])
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:1.1: syntax error, unexpected end of file
+[[input.y:1.1: error: syntax error, unexpected end of file
 ]])
 
 
@@ -463,7 +463,7 @@ AT_DATA([input.y],
 [{}
 ])
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:1.1-2: syntax error, unexpected {...}
+[[input.y:1.1-2: error: syntax error, unexpected {...}
 ]])
 
 
@@ -729,9 +729,9 @@ AT_DATA_GRAMMAR([input.y],
 start: .GOOD GOOD
 ]])
 AT_BISON_CHECK([-o input.c input.y], [1], [],
-[[input.y:10.10: invalid character: '-'
-input.y:11.10-16: invalid identifier: '1NV4L1D'
-input.y:12.10: invalid character: '-'
+[[input.y:10.10: error: invalid character: '-'
+input.y:11.10-16: error: invalid identifier: '1NV4L1D'
+input.y:12.10: error: invalid character: '-'
 ]])
 
 AT_CLEANUP
@@ -753,10 +753,10 @@ start: DECIMAL_1 HEXADECIMAL_2;
 ]])
 
 AT_BISON_CHECK([redecl.y], [1], [],
-[[redecl.y:10.10-22: user token number 11259375 redeclaration for HEXADECIMAL_1
-redecl.y:9.8-16: previous declaration for DECIMAL_1
-redecl.y:12.10-18: user token number 16702650 redeclaration for DECIMAL_2
-redecl.y:11.10-22: previous declaration for HEXADECIMAL_2
+[[redecl.y:10.10-22: error: user token number 11259375 redeclaration for HEXADECIMAL_1
+redecl.y:9.8-16:       previous declaration for DECIMAL_1
+redecl.y:12.10-18: error: user token number 16702650 redeclaration for DECIMAL_2
+redecl.y:11.10-22:     previous declaration for HEXADECIMAL_2
 ]])
 
 AT_DATA_GRAMMAR([too-large.y],
@@ -768,8 +768,8 @@ start: TOO_LARGE_DEC TOO_LARGE_HEX
 ]])
 
 AT_BISON_CHECK([too-large.y], [1], [],
-[[too-large.y:9.22-42: integer out of range: '999999999999999999999'
-too-large.y:10.24-44: integer out of range: '0xFFFFFFFFFFFFFFFFFFF'
+[[too-large.y:9.22-42: error: integer out of range: '999999999999999999999'
+too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF'
 ]])
 
 AT_CLEANUP
@@ -809,12 +809,12 @@ start: ;
 ]])
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
-[[input.y:1.10-2.0: missing '"' at end of line
-input.y:4.10-5.0: missing "'" at end of line
-input.y:14.11-15.0: missing "'" at end of line
-input.y:16.11-17.0: missing '"' at end of line
-input.y:19.13-20.0: missing '}' at end of file
-input.y:20.1: syntax error, unexpected end of file
+[[input.y:1.10-2.0: error: missing '"' at end of line
+input.y:4.10-5.0: error: missing "'" at end of line
+input.y:14.11-15.0: error: missing "'" at end of line
+input.y:16.11-17.0: error: missing '"' at end of line
+input.y:19.13-20.0: error: missing '}' at end of file
+input.y:20.1: error: syntax error, unexpected end of file
 ]])
 
 AT_CLEANUP
@@ -856,7 +856,7 @@ PREC: ;
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:3.1-4: rule given for PREC, which is a token
+[[input.y:3.1-4: error: rule given for PREC, which is a token
 ]])
 
 AT_CLEANUP
@@ -897,10 +897,10 @@ AT_DATA([input-c.y],
 start: ;
 ]])
 AT_BISON_CHECK([[input-c.y]], [[1]], [],
-[[input-c.y:1.7: %code qualifier 'q' is not used
-input-c.y:2.7-9: %code qualifier 'bad' is not used
-input-c.y:3.7-9: %code qualifier 'bad' is not used
-input-c.y:4.7-12: %code qualifier 'format' is not used
+[[input-c.y:1.7: error: %code qualifier 'q' is not used
+input-c.y:2.7-9: error: %code qualifier 'bad' is not used
+input-c.y:3.7-9: error: %code qualifier 'bad' is not used
+input-c.y:4.7-12: error: %code qualifier 'format' is not used
 ]])
 
 AT_DATA([input-c-glr.y],
@@ -911,9 +911,9 @@ AT_DATA([input-c-glr.y],
 start: ;
 ]])
 AT_BISON_CHECK([[input-c-glr.y]], [[1]], [],
-[[input-c-glr.y:1.7: %code qualifier 'q' is not used
-input-c-glr.y:2.7-9: %code qualifier 'bad' is not used
-input-c-glr.y:3.8-10: %code qualifier 'bad' is not used
+[[input-c-glr.y:1.7: error: %code qualifier 'q' is not used
+input-c-glr.y:2.7-9: error: %code qualifier 'bad' is not used
+input-c-glr.y:3.8-10: error: %code qualifier 'bad' is not used
 ]])
 
 AT_DATA([input-c++.y],
@@ -924,9 +924,9 @@ AT_DATA([input-c++.y],
 start: ;
 ]])
 AT_BISON_CHECK([[input-c++.y]], [[1]], [],
-[[input-c++.y:1.7: %code qualifier 'q' is not used
-input-c++.y:2.7-9: %code qualifier 'bad' is not used
-input-c++.y:3.8: %code qualifier 'q' is not used
+[[input-c++.y:1.7: error: %code qualifier 'q' is not used
+input-c++.y:2.7-9: error: %code qualifier 'bad' is not used
+input-c++.y:3.8: error: %code qualifier 'q' is not used
 ]])
 
 AT_DATA([input-c++-glr.y],
@@ -937,9 +937,9 @@ AT_DATA([input-c++-glr.y],
 start: ;
 ]])
 AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [],
-[[input-c++-glr.y:1.7-9: %code qualifier 'bad' is not used
-input-c++-glr.y:2.7: %code qualifier 'q' is not used
-input-c++-glr.y:3.7: %code qualifier 'q' is not used
+[[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used
+input-c++-glr.y:2.7: error: %code qualifier 'q' is not used
+input-c++-glr.y:3.7: error: %code qualifier 'q' is not used
 ]])
 
 AT_DATA([special-char-@@.y],
@@ -950,9 +950,9 @@ AT_DATA([special-char-@@.y],
 start: ;
 ]])
 AT_BISON_CHECK([[special-char-@@.y]], [[1]], [],
-[[special-char-@@.y:1.7-9: %code qualifier 'bad' is not used
-special-char-@@.y:2.7: %code qualifier 'q' is not used
-special-char-@@.y:3.7: %code qualifier 'q' is not used
+[[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used
+special-char-@@.y:2.7: error: %code qualifier 'q' is not used
+special-char-@@.y:3.7: error: %code qualifier 'q' is not used
 ]])
 
 AT_DATA([special-char-@:>@.y],
@@ -963,9 +963,9 @@ AT_DATA([special-char-@:>@.y],
 start: ;
 ]])
 AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [],
-[[special-char-@:>@.y:1.7-9: %code qualifier 'bad' is not used
-special-char-@:>@.y:2.7: %code qualifier 'q' is not used
-special-char-@:>@.y:3.7: %code qualifier 'q' is not used
+[[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used
+special-char-@:>@.y:2.7: error: %code qualifier 'q' is not used
+special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used
 ]])
 
 AT_CLEANUP
@@ -988,10 +988,10 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
-[[input-redefined.y:2.9-11: %define variable 'var' redefined
-input-redefined.y:1.9-11: previous definition
-input-redefined.y:3.10-12: %define variable 'var' redefined
-input-redefined.y:2.9-11: previous definition
+[[input-redefined.y:2.9-11: error: %define variable 'var' redefined
+input-redefined.y:1.9-11:     previous definition
+input-redefined.y:3.10-12: error: %define variable 'var' redefined
+input-redefined.y:2.9-11:      previous definition
 ]])
 
 AT_DATA([input-unused.y],
@@ -1001,7 +1001,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input-unused.y]], [[1]], [],
-[[input-unused.y:1.9-11: %define variable 'var' is not used
+[[input-unused.y:1.9-11: error: %define variable 'var' is not used
 ]])
 
 AT_CLEANUP
@@ -1045,8 +1045,8 @@ AT_DATA([[input-dg.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
-[[input-dg.y:1.9-11: %define variable 'var' redefined
-<command line>:2: previous definition
+[[input-dg.y:1.9-11: error: %define variable 'var' redefined
+<command line>:2:      previous definition
 ]])
 
 AT_DATA([[input-unused.y]],
@@ -1054,8 +1054,8 @@ AT_DATA([[input-unused.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [],
-[[<command line>:2: %define variable 'unused-d' is not used
-<command line>:3: %define variable 'unused-f' is not used
+[[<command line>:2: error: %define variable 'unused-d' is not used
+<command line>:3: error: %define variable 'unused-f' is not used
 ]])
 
 AT_CLEANUP
@@ -1075,7 +1075,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[Input.y]], [1], [],
-[[Input.y:2.9-14: invalid value for %define Boolean variable 'public'
+[[Input.y:2.9-14: error: invalid value for %define Boolean variable 'public'
 ]])
 
 AT_CLEANUP
@@ -1093,23 +1093,24 @@ AT_DATA([[input.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[input.y]], [[1]], [[]],
-[[input.y:1.9-29: invalid value for %define variable 'lr.default-reductions': 'bogus'
-input.y:1.9-29: accepted value: 'most'
-input.y:1.9-29: accepted value: 'consistent'
-input.y:1.9-29: accepted value: 'accepting'
+[[input.y:1.9-29: error: invalid value for %define variable 'lr.default-reductions': 'bogus'
+input.y:1.9-29:     accepted value: 'most'
+input.y:1.9-29:     accepted value: 'consistent'
+input.y:1.9-29:     accepted value: 'accepting'
 ]])
 
 # Back-end.
+# FIXME: these should be indented, but we shouldn't mess with the m4 yet
 AT_DATA([[input.y]],
 [[%define api.push-pull neither
 %%
 start: ;
 ]])
 AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither'
-input.y:1.9-21: accepted value: 'pull'
-input.y:1.9-21: accepted value: 'push'
-input.y:1.9-21: accepted value: 'both'
+[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
+input.y:1.9-21: error: accepted value: 'pull'
+input.y:1.9-21: error: accepted value: 'push'
+input.y:1.9-21: error: accepted value: 'both'
 ]])
 
 AT_CLEANUP
@@ -1129,10 +1130,10 @@ AT_DATA([[input.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither'
-input.y:1.9-21: accepted value: 'pull'
-input.y:1.9-21: accepted value: 'push'
-input.y:1.9-21: accepted value: 'both'
+[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
+input.y:1.9-21: error: accepted value: 'pull'
+input.y:1.9-21: error: accepted value: 'push'
+input.y:1.9-21: error: accepted value: 'both'
 ]])
 
 AT_DATA([[input.y]],
@@ -1141,7 +1142,7 @@ AT_DATA([[input.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-34: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
+[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
 ]])
 
 AT_DATA([[input.y]],
@@ -1150,7 +1151,7 @@ AT_DATA([[input.y]],
 start: ;
 ]])
 AT_BISON_CHECK([[input.y]], [[1]], [],
-[[input.y:1.9-15: %define variable 'foo_bar' is not used
+[[input.y:1.9-15: error: %define variable 'foo_bar' is not used
 ]])
 
 AT_CLEANUP
@@ -1175,7 +1176,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input.y]], [[1]], [],
-[[input.y:1.9-16: %define variable 'api.pure' is not used
+[[input.y:1.9-16: error: %define variable 'api.pure' is not used
 ]])
 ])
 
@@ -1209,7 +1210,7 @@ start: ;
 
 AT_BISON_CHECK([[input.y]], [1], [],
 [m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
-[[input.y:3.9-17: ]b4_arg[
+[[input.y:3.9-17: error: ]b4_arg[
 ]])])
 ])
 
@@ -1260,9 +1261,9 @@ AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]])
 AT_BISON_CHECK([empty.y], [1], [],
 [[empty.y:2.8-9: warning: empty character literal
 empty.y:3.8-4.0: warning: empty character literal
-empty.y:3.8-4.0: missing "'" at end of line
+empty.y:3.8-4.0: error: missing "'" at end of line
 empty.y:4.8: warning: empty character literal
-empty.y:4.8: missing "'" at end of file
+empty.y:4.8: error: missing "'" at end of file
 ]])
 
 AT_DATA([two.y],
@@ -1275,9 +1276,9 @@ AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]])
 AT_BISON_CHECK([two.y], [1], [],
 [[two.y:2.8-11: warning: extra characters in character literal
 two.y:3.8-4.0: warning: extra characters in character literal
-two.y:3.8-4.0: missing "'" at end of line
+two.y:3.8-4.0: error: missing "'" at end of line
 two.y:4.8-10: warning: extra characters in character literal
-two.y:4.8-10: missing "'" at end of file
+two.y:4.8-10: error: missing "'" at end of file
 ]])
 
 AT_DATA([three.y],
@@ -1290,9 +1291,9 @@ AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]])
 AT_BISON_CHECK([three.y], [1], [],
 [[three.y:2.8-12: warning: extra characters in character literal
 three.y:3.8-4.0: warning: extra characters in character literal
-three.y:3.8-4.0: missing "'" at end of line
+three.y:3.8-4.0: error: missing "'" at end of line
 three.y:4.8-11: warning: extra characters in character literal
-three.y:4.8-11: missing "'" at end of file
+three.y:4.8-11: error: missing "'" at end of file
 ]])
 
 AT_CLEANUP
@@ -1318,30 +1319,30 @@ AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
            || exit 77]])
 
 AT_BISON_CHECK([input.y], [1], [],
-[[input.y:2.9-12: invalid number after \-escape: 777
+[[input.y:2.9-12: error: invalid number after \-escape: 777
 input.y:2.8-13: warning: empty character literal
-input.y:2.16-17: invalid number after \-escape: 0
+input.y:2.16-17: error: invalid number after \-escape: 0
 input.y:2.15-18: warning: empty character literal
-input.y:2.21-25: invalid number after \-escape: xfff
+input.y:2.21-25: error: invalid number after \-escape: xfff
 input.y:2.20-26: warning: empty character literal
-input.y:2.29-31: invalid number after \-escape: x0
+input.y:2.29-31: error: invalid number after \-escape: x0
 input.y:2.28-32: warning: empty character literal
-input.y:3.9-14: invalid number after \-escape: uffff
+input.y:3.9-14: error: invalid number after \-escape: uffff
 input.y:3.8-15: warning: empty character literal
-input.y:3.18-23: invalid number after \-escape: u0000
+input.y:3.18-23: error: invalid number after \-escape: u0000
 input.y:3.17-24: warning: empty character literal
-input.y:3.27-36: invalid number after \-escape: Uffffffff
+input.y:3.27-36: error: invalid number after \-escape: Uffffffff
 input.y:3.26-37: warning: empty character literal
-input.y:3.40-49: invalid number after \-escape: U00000000
+input.y:3.40-49: error: invalid number after \-escape: U00000000
 input.y:3.39-50: warning: empty character literal
-input.y:4.9-10: invalid character after \-escape: ' '
+input.y:4.9-10: error: invalid character after \-escape: ' '
 input.y:4.8-11: warning: empty character literal
-input.y:4.14-15: invalid character after \-escape: A
+input.y:4.14-15: error: invalid character after \-escape: A
 input.y:4.13-16: warning: empty character literal
-input.y:5.9-16: invalid character after \-escape: \t
-input.y:5.17: invalid character after \-escape: \f
-input.y:5.18: invalid character after \-escape: \0
-input.y:5.19: invalid character after \-escape: \001
+input.y:5.9-16: error: invalid character after \-escape: \t
+input.y:5.17: error: invalid character after \-escape: \f
+input.y:5.18: error: invalid character after \-escape: \0
+input.y:5.19: error: invalid character after \-escape: \001
 ]])
 
 AT_CLEANUP
@@ -1360,11 +1361,11 @@ start: ;
 # parse.lac.* options are useless if LAC isn't actually activated.
 AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]],
                [[1]], [],
-[[<command line>:2: %define variable 'parse.lac.es-capacity-initial' is not used
+[[<command line>:2: error: %define variable 'parse.lac.es-capacity-initial' is not used
 ]])
 AT_BISON_CHECK([[-Dparse.lac.memory-trace=full input.y]],
                [[1]], [],
-[[<command line>:2: %define variable 'parse.lac.memory-trace' is not used
+[[<command line>:2: error: %define variable 'parse.lac.memory-trace' is not used
 ]])
 
 AT_CLEANUP
@@ -1418,7 +1419,7 @@ m4_pushdef([AT_TEST],
 exp:;
 ]])
 AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
-[[$3: '%name-prefix' and '%define api.prefix' cannot be used together
+[[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together
 ]])
 ])
 
index f822ec6e1c490c8829cdcf2843308ca5fe12dd07..db3f5000e979313fd9cc5d81a36daeca83fecea2 100644 (file)
@@ -719,8 +719,8 @@ AT_SETUP([Java stype, position_class and location_class])
 AT_CHECK_JAVA_MINIMAL([[
 %define stype "java.awt.Color"
 %type<java.awt.Color> start;
-%define location_type "MyLoc"
-%define position_type "MyPos"
+%define api.location.type "MyLoc"
+%define api.position.type "MyPos"
 %code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]])
 AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore])
 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
@@ -729,8 +729,8 @@ AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
 %define stype "java.awt.Color"
 %type<java.awt.Color> start;
-%define location_type "MyLoc"
-%define position_type "MyPos"
+%define api.location.type "MyLoc"
+%define api.position.type "MyPos"
 %code { class MyPos {} }]], [], [[return EOF;]], [],
 [[$$ = $<java.awt.Color>1;]],
 [[java.awt.Color]], [[MyPos]], [[MyLoc]])
index 88825210e7c0b5d39bed4b291a899eead3cd401f..e2fd1beb5a31e1febf0b0b8834df700e54bc312d 100644 (file)
@@ -138,7 +138,7 @@ m4_pushdef([AT_LEXPARAM_IF],
 m4_pushdef([AT_LOCATION_IF],
 [m4_bmatch([$3], [%locations], [$1], [$2])])
 m4_pushdef([AT_LOCATION_TYPE_IF],
-[m4_bmatch([$3], [%define location_type], [$1], [$2])])
+[m4_bmatch([$3], [%define \(api\.location\.type\|location_type\)], [$1], [$2])])
 m4_pushdef([AT_PARAM_IF],
 [m4_bmatch([$3], [%parse-param], [$1], [$2])])
 # Comma-terminated list of formals parse-parameters.
index 744eab823e8087097e673ce6c473e0f0c3f3a1ba..9582c01d16260bd34f76d0f781bf1756ffc10c38 100644 (file)
@@ -251,16 +251,16 @@ exp:
 ]])
 
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:50.51-60: invalid reference: '$<ival>lo9'
+[[test.y:50.51-60: error: invalid reference: '$<ival>lo9'
 test.y:50.3-68:      symbol not found in production: lo9
 test.y:51.51-60: warning: misleading reference: '$<ival>exp'
-test.y:42.1-3:       warning: refers to: $exp at $$
-test.y:51.7:         warning: possibly meant: $x, hiding $exp at $1
-test.y:51.41:        warning: possibly meant: $r, hiding $exp at $4
-test.y:52.51-52: $l of 'exp' has no declared type
-test.y:55.46-49: invalid reference: '$r12'
+test.y:42.1-3:       refers to: $exp at $$
+test.y:51.7:         possibly meant: $x, hiding $exp at $1
+test.y:51.41:        possibly meant: $r, hiding $exp at $4
+test.y:52.51-52: error: $l of 'exp' has no declared type
+test.y:55.46-49: error: invalid reference: '$r12'
 test.y:55.3-53:      symbol not found in production: r12
-test.y:56.29-33: invalid reference: '$expo'
+test.y:56.29-33: error: invalid reference: '$expo'
 test.y:56.3-46:      symbol not found in production: expo
 ]])
 AT_BISON_OPTION_POPDEFS
@@ -278,8 +278,8 @@ foo.bar: '2'
 ]])
 AT_BISON_CHECK([-o test.c test.y], 0, [],
 [[test.y:11.22-29: warning: misleading reference: '$foo.bar'
-test.y:11.8-10:      warning: refers to: $foo at $1
-test.y:11.12-18:     warning: possibly meant: $[foo.bar] at $2
+test.y:11.8-10:      refers to: $foo at $1
+test.y:11.12-18:     possibly meant: $[foo.bar] at $2
 ]])
 AT_CLEANUP
 
@@ -353,43 +353,43 @@ factor:     '(' expr ')'  { $$ = $2; }
     ;
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:24.36-41: invalid reference: '$cond1'
+[[test.y:24.36-41: error: invalid reference: '$cond1'
 test.y:23.11-24.62:  symbol not found in production: cond1
-test.y:26.43-53: invalid reference: '$stmt.field'
+test.y:26.43-53: error: invalid reference: '$stmt.field'
 test.y:25.11-26.60:  symbol not found in production: stmt
 test.y:25.35-38:     possibly meant: $then.field, hiding $stmt.field at $4
-test.y:28.43-52: invalid reference: '$stmt.list'
+test.y:28.43-52: error: invalid reference: '$stmt.list'
 test.y:27.11-28.59:  symbol not found in production: stmt
 test.y:27.30-38:     possibly meant: $[stmt.list] at $4
-test.y:30.43-46: ambiguous reference: '$xyz'
+test.y:30.43-46: error: ambiguous reference: '$xyz'
 test.y:29.35-37:     refers to: $xyz at $4
 test.y:29.50-52:     refers to: $xyz at $6
-test.y:32.43-52: invalid reference: '$stmt.list'
+test.y:32.43-52: error: invalid reference: '$stmt.list'
 test.y:31.11-32.63:  symbol not found in production: stmt
 test.y:31.40-43:     possibly meant: $then, hiding $[stmt.list] at $4
 test.y:31.61-64:     possibly meant: $else, hiding $[stmt.list] at $6
-test.y:34.43-58: invalid reference: '$stmt.list.field'
+test.y:34.43-58: error: invalid reference: '$stmt.list.field'
 test.y:33.11-34.69:  symbol not found in production: stmt
 test.y:33.40-43:     possibly meant: $then.field, hiding $[stmt.list].field at $4
 test.y:33.61-64:     possibly meant: $else.field, hiding $[stmt.list].field at $6
-test.y:36.43-54: invalid reference: '$[stmt.list]'
+test.y:36.43-54: error: invalid reference: '$[stmt.list]'
 test.y:35.11-36.71:  symbol not found in production: stmt.list
 test.y:35.40-43:     possibly meant: $then, hiding $[stmt.list] at $4
 test.y:35.61-64:     possibly meant: $else, hiding $[stmt.list] at $6
-test.y:38.43-49: invalid reference: '$then.1'
+test.y:38.43-49: error: invalid reference: '$then.1'
 test.y:37.11-38.60:  symbol not found in production: then
 test.y:37.40-45:     possibly meant: $[then.1] at $4
-test.y:40.43-55: invalid reference: '$then.1.field'
+test.y:40.43-55: error: invalid reference: '$then.1.field'
 test.y:39.11-40.66:  symbol not found in production: then
 test.y:39.40-45:     possibly meant: $[then.1].field at $4
-test.y:42.44-50: invalid reference: '$stmt.x'
+test.y:42.44-50: error: invalid reference: '$stmt.x'
 test.y:41.12-42.57:  symbol not found in production: stmt
 test.y:41.36-41:     possibly meant: $[stmt.x].x, hiding $stmt.x at $4
 test.y:41.36-41:     possibly meant: $[stmt.x] at $4
-test.y:44.13-22: invalid reference: '$if-stmt-a'
+test.y:44.13-22: error: invalid reference: '$if-stmt-a'
 test.y:43.12-44.59:  symbol not found in production: if
 test.y:43.1-9:       possibly meant: $[if-stmt-a] at $$
-test.y:46.46-54: invalid reference: '$then-a.f'
+test.y:46.46-54: error: invalid reference: '$then-a.f'
 test.y:45.12-46.65:  symbol not found in production: then
 test.y:45.41-46:     possibly meant: $[then-a].f at $4
 ]])
@@ -405,7 +405,7 @@ start: foo[] bar
   { s = $foo; }
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:11.12: an identifier expected
+[[test.y:11.12: error: an identifier expected
 ]])
 AT_CLEANUP
 
@@ -419,7 +419,7 @@ start: foo[ a d ] bar
   { s = $foo; }
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:11.15: unexpected identifier in bracketed name: 'd'
+[[test.y:11.15: error: unexpected identifier in bracketed name: 'd'
 ]])
 AT_CLEANUP
 
@@ -433,7 +433,7 @@ start: foo[/* comment */] bar
   { s = $foo; }
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:11.25: an identifier expected
+[[test.y:11.25: error: an identifier expected
 ]])
 AT_CLEANUP
 
@@ -448,14 +448,14 @@ start: foo[ /* aaa */ *&-.+\000\001\002\377 ] bar
 ]])
 AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' test.y || exit 77]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:11.23: invalid character in bracketed name: '*'
-test.y:11.24: invalid character in bracketed name: '&'
-test.y:11.25: invalid character in bracketed name: '-'
-test.y:11.27: invalid character in bracketed name: '+'
-test.y:11.28: invalid character in bracketed name: '\0'
-test.y:11.28: invalid character in bracketed name: '\001'
-test.y:11.28: invalid character in bracketed name: '\002'
-test.y:11.28: invalid character in bracketed name: '\377'
+[[test.y:11.23: error: invalid character in bracketed name: '*'
+test.y:11.24: error: invalid character in bracketed name: '&'
+test.y:11.25: error: invalid character in bracketed name: '-'
+test.y:11.27: error: invalid character in bracketed name: '+'
+test.y:11.28: error: invalid character in bracketed name: '\0'
+test.y:11.28: error: invalid character in bracketed name: '\001'
+test.y:11.28: error: invalid character in bracketed name: '\002'
+test.y:11.28: error: invalid character in bracketed name: '\377'
 ]])
 AT_CLEANUP
 
@@ -468,7 +468,7 @@ AT_DATA_GRAMMAR([test.y],
 start[a s]: foo;
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:11.9: unexpected identifier in bracketed name: 's'
+[[test.y:11.9: error: unexpected identifier in bracketed name: 's'
 ]])
 AT_CLEANUP
 
@@ -515,37 +515,37 @@ sym_a: 'a';
 sym_b: 'b';
 ]])
 AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:12.22-31: invalid reference: '$sym.field'
+[[test.y:12.22-31: error: invalid reference: '$sym.field'
 test.y:12.3-35:      symbol not found in production: sym
-test.y:13.22-35: invalid reference: '$<aa>sym.field'
+test.y:13.22-35: error: invalid reference: '$<aa>sym.field'
 test.y:13.3-39:      symbol not found in production: sym
-test.y:14.22-33: invalid reference: '$[sym.field]'
+test.y:14.22-33: error: invalid reference: '$[sym.field]'
 test.y:14.3-37:      symbol not found in production: sym.field
-test.y:15.22-37: invalid reference: '$<aa>[sym.field]'
+test.y:15.22-37: error: invalid reference: '$<aa>[sym.field]'
 test.y:15.3-41:      symbol not found in production: sym.field
-test.y:16.22-25: invalid reference: '$sym'
+test.y:16.22-25: error: invalid reference: '$sym'
 test.y:16.3-29:      symbol not found in production: sym
-test.y:17.22-29: invalid reference: '$<aa>sym'
+test.y:17.22-29: error: invalid reference: '$<aa>sym'
 test.y:17.3-33:      symbol not found in production: sym
-test.y:18.22-27: invalid reference: '$[sym]'
+test.y:18.22-27: error: invalid reference: '$[sym]'
 test.y:18.3-65:      symbol not found in production before $3: sym
-test.y:18.52-61: invalid reference: '$<aa>[sym]'
+test.y:18.52-61: error: invalid reference: '$<aa>[sym]'
 test.y:18.3-65:      symbol not found in production: sym
-test.y:22.22-31: invalid reference: '$sym-field'
+test.y:22.22-31: error: invalid reference: '$sym-field'
 test.y:22.3-35:      symbol not found in production: sym
-test.y:23.22-35: invalid reference: '$<aa>sym-field'
+test.y:23.22-35: error: invalid reference: '$<aa>sym-field'
 test.y:23.3-39:      symbol not found in production: sym
-test.y:24.22-33: invalid reference: '$[sym-field]'
+test.y:24.22-33: error: invalid reference: '$[sym-field]'
 test.y:24.3-37:      symbol not found in production: sym-field
-test.y:25.22-37: invalid reference: '$<aa>[sym-field]'
+test.y:25.22-37: error: invalid reference: '$<aa>[sym-field]'
 test.y:25.3-41:      symbol not found in production: sym-field
-test.y:26.22-25: invalid reference: '$sym'
+test.y:26.22-25: error: invalid reference: '$sym'
 test.y:26.3-29:      symbol not found in production: sym
-test.y:27.22-29: invalid reference: '$<aa>sym'
+test.y:27.22-29: error: invalid reference: '$<aa>sym'
 test.y:27.3-33:      symbol not found in production: sym
-test.y:28.22-27: invalid reference: '$[sym]'
+test.y:28.22-27: error: invalid reference: '$[sym]'
 test.y:28.3-65:      symbol not found in production before $3: sym
-test.y:28.52-61: invalid reference: '$<aa>[sym]'
+test.y:28.52-61: error: invalid reference: '$<aa>[sym]'
 test.y:28.3-65:      symbol not found in production: sym
 ]])
 AT_CLEANUP
@@ -563,10 +563,10 @@ start:
 .field: ;
 ]])
 AT_BISON_CHECK([[test.y]], [[1]], [],
-[[test.y:4.12-18: invalid reference: '$.field'
+[[test.y:4.12-18: error: invalid reference: '$.field'
 test.y:4.13:        syntax error after '$', expecting integer, letter, '_', '@<:@', or '$'
 test.y:4.3-8:       possibly meant: $[.field] at $1
-test.y:5.12-18: invalid reference: '@.field'
+test.y:5.12-18: error: invalid reference: '@.field'
 test.y:5.13:        syntax error after '@', expecting integer, letter, '_', '@<:@', or '$'
 ]])
 AT_DATA([[test.y]],
index f7a7d8e57ed59ba2ee948b017df0c96cb9b9a1c9..37d2c3da6bf5acb63989761c775703587bb3ebd8 100644 (file)
@@ -171,7 +171,7 @@ AT_CHECK_CONFLICTING_OUTPUT([foo.y],
 ])
 
 AT_CHECK_CONFLICTING_OUTPUT([foo.y], [], [-o foo.y],
-[foo.y: refusing to overwrite the input file 'foo.y'
+[foo.y: error: refusing to overwrite the input file 'foo.y'
 ], 1)
 
 
@@ -231,3 +231,368 @@ AT_CHECK_OUTPUT_FILE_NAME([[@{]])
 AT_CHECK_OUTPUT_FILE_NAME([[@}]])
 AT_CHECK_OUTPUT_FILE_NAME([[@<:@]])
 AT_CHECK_OUTPUT_FILE_NAME([[@:>@]])
+
+
+# AT_TEST(SETUP-NAME, GRAMMAR, DOT-BODY)
+# --------------------------------------
+# Check that the DOT graph for GRAMMAR is DOT-BODY.
+m4_pushdef([AT_TEST],
+[AT_SETUP([$1])
+AT_KEYWORDS([[graph]])
+AT_DATA([[input.y]], [$2])
+AT_BISON_CHECK([[-rall --graph input.y]], [0], [[]], [[ignore]])
+AT_CHECK([[grep -v // input.dot]], [0],
+[[
+digraph "input.y"
+{
+  node [fontname = courier, shape = box, colorscheme = paired6]
+  edge [fontname = courier]
+  ]$3[}
+]])
+AT_CLEANUP
+])
+
+
+## ------------------------ ##
+## Graph with no conflicts. ##
+## ------------------------ ##
+
+AT_TEST([Graph with no conflicts],
+[[%%
+exp: a '?' b;
+a: ;
+b: 'b';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a '?' b\l  2 a: .\l"]
+  0 -> "0R2e" [style = solid]
+ "0R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 3 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a . '?' b\l"]
+  2 -> 4 [style=solid label="'?'"]
+  3 [label="State 3\n  0 $accept: exp $end .\l"]
+  3 -> "3R0e" [style = solid]
+ "3R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  4 [label="State 4\n  1 exp: a '?' . b\l  3 b: . 'b'\l"]
+  4 -> 5 [style=solid label="'b'"]
+  4 -> 6 [style=dashed label="b"]
+  5 [label="State 5\n  3 b: 'b' .\l"]
+  5 -> "5R3e" [style = solid]
+ "5R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  6 [label="State 6\n  1 exp: a '?' b .\l"]
+  6 -> "6R1e" [style = solid]
+ "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+]])
+
+## ------------------------ ##
+## Graph with unsolved S/R. ##
+## ------------------------ ##
+
+AT_TEST([Graph with unsolved S/R],
+[[%%
+start:
+    'a'
+  | empty_a 'a'
+  | 'b'
+  | empty_b 'b'
+  | 'c'
+  | empty_c 'c'
+  ;
+empty_a: %prec 'a';
+empty_b: %prec 'b';
+empty_c: %prec 'c';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6      | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  ['b']\l  9 empty_c: .  ['c']\l"]
+  0 -> "0R7d" [label = "['a']" style = solid]
+ "0R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"]
+  0 -> "0R8d" [label = "['b']" style = solid]
+ "0R8d" [style = filled, shape = diamond, fillcolor = 5, label = "R8"]
+  0 -> "0R9d" [label = "['c']" style = solid]
+ "0R9d" [style = filled, shape = diamond, fillcolor = 5, label = "R9"]
+  0 -> 1 [style=solid label="'a'"]
+  0 -> 2 [style=solid label="'b'"]
+  0 -> 3 [style=solid label="'c'"]
+  0 -> 4 [style=dashed label="start"]
+  0 -> 5 [style=dashed label="empty_a"]
+  0 -> 6 [style=dashed label="empty_b"]
+  0 -> 7 [style=dashed label="empty_c"]
+  1 [label="State 1\n  1 start: 'a' .\l"]
+  1 -> "1R1e" [style = solid]
+ "1R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  2 [label="State 2\n  3 start: 'b' .\l"]
+  2 -> "2R3e" [style = solid]
+ "2R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  3 [label="State 3\n  5 start: 'c' .\l"]
+  3 -> "3R5e" [style = solid]
+ "3R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  4 [label="State 4\n  0 $accept: start . $end\l"]
+  4 -> 8 [style=solid label="$end"]
+  5 [label="State 5\n  2 start: empty_a . 'a'\l"]
+  5 -> 9 [style=solid label="'a'"]
+  6 [label="State 6\n  4 start: empty_b . 'b'\l"]
+  6 -> 10 [style=solid label="'b'"]
+  7 [label="State 7\n  6 start: empty_c . 'c'\l"]
+  7 -> 11 [style=solid label="'c'"]
+  8 [label="State 8\n  0 $accept: start $end .\l"]
+  8 -> "8R0e" [style = solid]
+ "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  9 [label="State 9\n  2 start: empty_a 'a' .\l"]
+  9 -> "9R2e" [style = solid]
+ "9R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  10 [label="State 10\n  4 start: empty_b 'b' .\l"]
+  10 -> "10R4e" [style = solid]
+ "10R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  11 [label="State 11\n  6 start: empty_c 'c' .\l"]
+  11 -> "11R6e" [style = solid]
+ "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ---------------------- ##
+## Graph with solved S/R. ##
+## ---------------------- ##
+
+AT_TEST([Graph with solved S/R],
+[[%left 'a'
+%right 'b'
+%right 'c'
+%%
+start:
+    'a'
+  | empty_a 'a'
+  | 'b'
+  | empty_b 'b'
+  | 'c'
+  | empty_c 'c'
+  ;
+empty_a: %prec 'a';
+empty_b: %prec 'b';
+empty_c: %prec 'c';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6      | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  []\l  9 empty_c: .  []\l"]
+  0 -> "0R7e" [style = solid]
+ "0R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  0 -> 1 [style=solid label="'b'"]
+  0 -> 2 [style=solid label="'c'"]
+  0 -> 3 [style=dashed label="start"]
+  0 -> 4 [style=dashed label="empty_a"]
+  0 -> 5 [style=dashed label="empty_b"]
+  0 -> 6 [style=dashed label="empty_c"]
+  1 [label="State 1\n  3 start: 'b' .\l"]
+  1 -> "1R3e" [style = solid]
+ "1R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  2 [label="State 2\n  5 start: 'c' .\l"]
+  2 -> "2R5e" [style = solid]
+ "2R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  3 [label="State 3\n  0 $accept: start . $end\l"]
+  3 -> 7 [style=solid label="$end"]
+  4 [label="State 4\n  2 start: empty_a . 'a'\l"]
+  4 -> 8 [style=solid label="'a'"]
+  5 [label="State 5\n  4 start: empty_b . 'b'\l"]
+  5 -> 9 [style=solid label="'b'"]
+  6 [label="State 6\n  6 start: empty_c . 'c'\l"]
+  6 -> 10 [style=solid label="'c'"]
+  7 [label="State 7\n  0 $accept: start $end .\l"]
+  7 -> "7R0e" [style = solid]
+ "7R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  8 [label="State 8\n  2 start: empty_a 'a' .\l"]
+  8 -> "8R2e" [style = solid]
+ "8R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  9 [label="State 9\n  4 start: empty_b 'b' .\l"]
+  9 -> "9R4e" [style = solid]
+ "9R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  10 [label="State 10\n  6 start: empty_c 'c' .\l"]
+  10 -> "10R6e" [style = solid]
+ "10R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ---------------- ##
+## Graph with  R/R. ##
+## ---------------- ##
+
+AT_TEST([Graph with R/R],
+[[%%
+exp: a | b;
+a: ;
+b: ;
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a\l  2    | . b\l  3 a: .  [$end]\l  4 b: .  [$end]\l"]
+  0 -> "0R3e" [style = solid]
+ "0R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  0 -> "0R4d" [label = "[$end]" style = solid]
+ "0R4d" [style = filled, shape = diamond, fillcolor = 5, label = "R4"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 4 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a .\l"]
+  2 -> "2R1e" [style = solid]
+ "2R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  3 [label="State 3\n  2 exp: b .\l"]
+  3 -> "3R2e" [style = solid]
+ "3R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  4 [label="State 4\n  0 $accept: exp $end .\l"]
+  4 -> "4R0e" [style = solid]
+ "4R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+]])
+
+## ---------------------------------------- ##
+## Graph with reductions with multiple LAT. ##
+## ---------------------------------------- ##
+
+AT_TEST([Graph with reductions with multiple LAT],
+[[%%
+exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';';
+a: ;
+b: ;
+c: ;
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a ';'\l  2    | . a ';'\l  3    | . a '.'\l  4    | . b '?'\l  5    | . b '!'\l  6    | . c '?'\l  7    | . c ';'\l  8 a: .  [';', '.']\l  9 b: .  ['?', '!']\l 10 c: .  [';', '?']\l"]
+  0 -> "0R8e" [style = solid]
+ "0R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"]
+  0 -> "0R9e" [label = "['?', '!']" style = solid]
+ "0R9e" [style = filled, shape = diamond, fillcolor = 3, label = "R9"]
+  0 -> "0R10d" [label = "[';', '?']" style = solid]
+ "0R10d" [style = filled, shape = diamond, fillcolor = 5, label = "R10"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  0 -> 4 [style=dashed label="c"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 5 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a . ';'\l  2    | a . ';'\l  3    | a . '.'\l"]
+  2 -> 6 [style=solid label="';'"]
+  2 -> 7 [style=solid label="'.'"]
+  3 [label="State 3\n  4 exp: b . '?'\l  5    | b . '!'\l"]
+  3 -> 8 [style=solid label="'?'"]
+  3 -> 9 [style=solid label="'!'"]
+  4 [label="State 4\n  6 exp: c . '?'\l  7    | c . ';'\l"]
+  4 -> 10 [style=solid label="';'"]
+  4 -> 11 [style=solid label="'?'"]
+  5 [label="State 5\n  0 $accept: exp $end .\l"]
+  5 -> "5R0e" [style = solid]
+ "5R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  6 [label="State 6\n  1 exp: a ';' .  [$end]\l  2    | a ';' .  [$end]\l"]
+  6 -> "6R1e" [style = solid]
+ "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  6 -> "6R2d" [label = "[$end]" style = solid]
+ "6R2d" [style = filled, shape = diamond, fillcolor = 5, label = "R2"]
+  7 [label="State 7\n  3 exp: a '.' .\l"]
+  7 -> "7R3e" [style = solid]
+ "7R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  8 [label="State 8\n  4 exp: b '?' .\l"]
+  8 -> "8R4e" [style = solid]
+ "8R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  9 [label="State 9\n  5 exp: b '!' .\l"]
+  9 -> "9R5e" [style = solid]
+ "9R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  10 [label="State 10\n  7 exp: c ';' .\l"]
+  10 -> "10R7e" [style = solid]
+ "10R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  11 [label="State 11\n  6 exp: c '?' .\l"]
+  11 -> "11R6e" [style = solid]
+ "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ------------------------------------------------------ ##
+## Graph with a reduction rule both enabled and disabled. ##
+## ------------------------------------------------------ ##
+
+AT_TEST([Graph with a reduction rule both enabled and disabled],
+[[%%
+exp: ifexp | opexp | imm;
+ifexp: "if" exp "then" exp elseexp;
+elseexp: "else" exp | ;
+opexp: exp '+' exp;
+imm: '0';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  0 -> 1 [style=solid label="\"if\""]
+  0 -> 2 [style=solid label="'0'"]
+  0 -> 3 [style=dashed label="exp"]
+  0 -> 4 [style=dashed label="ifexp"]
+  0 -> 5 [style=dashed label="opexp"]
+  0 -> 6 [style=dashed label="imm"]
+  1 [label="State 1\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" . exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  1 -> 1 [style=solid label="\"if\""]
+  1 -> 2 [style=solid label="'0'"]
+  1 -> 7 [style=dashed label="exp"]
+  1 -> 4 [style=dashed label="ifexp"]
+  1 -> 5 [style=dashed label="opexp"]
+  1 -> 6 [style=dashed label="imm"]
+  2 [label="State 2\n  8 imm: '0' .\l"]
+  2 -> "2R8e" [style = solid]
+ "2R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"]
+  3 [label="State 3\n  0 $accept: exp . $end\l  7 opexp: exp . '+' exp\l"]
+  3 -> 8 [style=solid label="$end"]
+  3 -> 9 [style=solid label="'+'"]
+  4 [label="State 4\n  1 exp: ifexp .\l"]
+  4 -> "4R1e" [style = solid]
+ "4R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  5 [label="State 5\n  2 exp: opexp .\l"]
+  5 -> "5R2e" [style = solid]
+ "5R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  6 [label="State 6\n  3 exp: imm .\l"]
+  6 -> "6R3e" [style = solid]
+ "6R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  7 [label="State 7\n  4 ifexp: \"if\" exp . \"then\" exp elseexp\l  7 opexp: exp . '+' exp\l"]
+  7 -> 10 [style=solid label="\"then\""]
+  7 -> 9 [style=solid label="'+'"]
+  8 [label="State 8\n  0 $accept: exp $end .\l"]
+  8 -> "8R0e" [style = solid]
+ "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  9 [label="State 9\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  7      | exp '+' . exp\l  8 imm: . '0'\l"]
+  9 -> 1 [style=solid label="\"if\""]
+  9 -> 2 [style=solid label="'0'"]
+  9 -> 11 [style=dashed label="exp"]
+  9 -> 4 [style=dashed label="ifexp"]
+  9 -> 5 [style=dashed label="opexp"]
+  9 -> 6 [style=dashed label="imm"]
+  10 [label="State 10\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" exp \"then\" . exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  10 -> 1 [style=solid label="\"if\""]
+  10 -> 2 [style=solid label="'0'"]
+  10 -> 12 [style=dashed label="exp"]
+  10 -> 4 [style=dashed label="ifexp"]
+  10 -> 5 [style=dashed label="opexp"]
+  10 -> 6 [style=dashed label="imm"]
+  11 [label="State 11\n  7 opexp: exp . '+' exp\l  7      | exp '+' exp .  [$end, \"then\", \"else\", '+']\l"]
+  11 -> "11R7e" [style = solid]
+ "11R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  11 -> "11R7d" [label = "['+']" style = solid]
+ "11R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"]
+  11 -> 9 [style=solid label="'+'"]
+  12 [label="State 12\n  4 ifexp: \"if\" exp \"then\" exp . elseexp\l  5 elseexp: . \"else\" exp\l  6        | .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
+  12 -> "12R6e" [style = solid]
+ "12R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+  12 -> "12R6d" [label = "[\"else\", '+']" style = solid]
+ "12R6d" [style = filled, shape = diamond, fillcolor = 5, label = "R6"]
+  12 -> 13 [style=solid label="\"else\""]
+  12 -> 9 [style=solid label="'+'"]
+  12 -> 14 [style=dashed label="elseexp"]
+  13 [label="State 13\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  5 elseexp: \"else\" . exp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  13 -> 1 [style=solid label="\"if\""]
+  13 -> 2 [style=solid label="'0'"]
+  13 -> 15 [style=dashed label="exp"]
+  13 -> 4 [style=dashed label="ifexp"]
+  13 -> 5 [style=dashed label="opexp"]
+  13 -> 6 [style=dashed label="imm"]
+  14 [label="State 14\n  4 ifexp: \"if\" exp \"then\" exp elseexp .\l"]
+  14 -> "14R4e" [style = solid]
+ "14R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  15 [label="State 15\n  5 elseexp: \"else\" exp .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
+  15 -> "15R5e" [style = solid]
+ "15R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  15 -> "15R5d" [label = "['+']" style = solid]
+ "15R5d" [style = filled, shape = diamond, fillcolor = 5, label = "R5"]
+  15 -> 9 [style=solid label="'+'"]
+]])
+
+m4_popdef([AT_TEST])
index d2c09263a56b212b5917f5c890dec0cd7f4ac499..1b99397175c95c7a535f6ceffd9bdb96d5e7fe27 100644 (file)
@@ -153,7 +153,7 @@ start: ;
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[input.y]], [[1]], [],
-[[input.y:2.9-21: %define variable 'api.push-pull' is not used
+[[input.y:2.9-21: error: %define variable 'api.push-pull' is not used
 ]])
 
 AT_CLEANUP
index 6cf226859bdf6610e78e1420ffd3812ad3bdab1b..b6bff17cb0743128f82bc74360e74f54b48baba4 100644 (file)
@@ -383,6 +383,58 @@ AT_CLEANUP
 
 
 
+## ---------------- ##
+## Invalid inputs.  ##
+## ---------------- ##
+
+
+AT_SETUP([Invalid inputs])
+
+AT_DATA([input.y],
+[[%%
+?
+default: 'a' }
+%&
+%a-does-not-exist
+%-
+%{
+]])
+
+AT_BISON_CHECK([input.y], [1], [],
+[[input.y:2.1: error: invalid character: '?'
+input.y:3.14: error: invalid character: '}'
+input.y:4.1: error: invalid character: '%'
+input.y:4.2: error: invalid character: '&'
+input.y:5.1-17: error: invalid directive: '%a-does-not-exist'
+input.y:6.1: error: invalid character: '%'
+input.y:6.2: error: invalid character: '-'
+input.y:7.1-8.0: error: missing '%}' at end of file
+input.y:7.1-8.0: error: syntax error, unexpected %{...%}
+]])
+
+AT_CLEANUP
+
+
+AT_SETUP([Invalid inputs with {}])
+
+AT_DATA([input.y],
+[[
+%destructor
+%initial-action
+%lex-param
+%parse-param
+%printer
+%union
+]])
+
+AT_BISON_CHECK([input.y], [1], [],
+[[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...}
+]])
+
+AT_CLEANUP
+
+
+
 ## ------------------- ##
 ## Token definitions.  ##
 ## ------------------- ##
index e23c3bb0301fd8300eb39712edcb790f2a1619a2..7b5b8f27695ac847d366f1481f22ebadf3b20f80 100644 (file)
@@ -157,7 +157,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input.y]], [[1]], [[]],
-[[<skeleton default value>: invalid value for %define Boolean variable 'foo'
+[[<skeleton default value>: error: invalid value for %define Boolean variable 'foo'
 ]])
 
 AT_CLEANUP
@@ -193,8 +193,8 @@ start: ;
 AT_BISON_CHECK([[input1.y]], [[1]], [[]],
 [[input1.y: warning: foow fubar
 foow.y:2.3-5.3: warning: foowat fubar
-input1.y: fooc fubar
-fooc.y:1.1-10.5: foocat fubar
+input1.y: error: fooc fubar
+fooc.y:1.1-10.5: error: foocat fubar
 input1.y: fatal error: foof fubar
 ]])
 
@@ -264,7 +264,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input1.y]], [[1]], [[]],
-[[input1.y: non-fatal error
+[[input1.y: error: non-fatal error
 input1.y: fatal error: M4 should exit immediately here
 ]])