]> git.saurik.com Git - bison.git/commitdiff
Merge remote-tracking branch 'origin/branch-2.6' into maint
authorAkim Demaille <akim@lrde.epita.fr>
Mon, 26 Nov 2012 08:05:28 +0000 (09:05 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Mon, 26 Nov 2012 08:05:28 +0000 (09:05 +0100)
* origin/branch-2.6:
  yacc.c: always initialize yylloc
  doc: one of the fixes for an ambiguous grammar was ambiguous too
  doc: fix the dangling else with precedence directives
  doc: prefer "token" to TOKEN
  doc: formatting changes

Conflicts:
NEWS
doc/bison.texi

52 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/bison.xsl
data/xslt/xml2dot.xsl
data/xslt/xml2text.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]
po/POTFILES.in
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.c
src/print_graph.c
src/reader.c
src/scan-gram.l
src/symtab.c
src/system.h
tests/c++.at
tests/calc.at
tests/conflicts.at
tests/existing.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/reduce.at
tests/regression.at
tests/sets.at
tests/skeletons.at
tests/synclines.at

diff --git a/NEWS b/NEWS
index 393b892414934f76aa4f95d8b7739542e3784dd8..3789e92d017ed67d695659500a7e1ecade131fe3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,62 @@ 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.
+
+** Graph improvements in DOT and XSLT
+
+  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.
+
+  These changes are present in both --graph output and xml2dot.xsl XSLT
+  processing, with minor (documented) differences.
+
+  Two nodes were added to the documentation: Xml and Graphviz.
+
+* Noteworthy changes in release ?.? (????-??-??) [?]
+
 ** Bug fixes
 
   Warnings about uninitialized yylloc in yyparse have been fixed.
@@ -96,7 +152,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
 
@@ -1935,7 +1991,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 e87568d5dddbbe4a8c59b3167f7d880e8a0e1ee5..8ae024fb26e86f695e70ba6ffa9976ba718cf162 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -83,6 +83,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
@@ -132,6 +133,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..3f244aabee421092b060a23a82199d29e224615c 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,
@@ -60,6 +61,18 @@ update-copyright: update-b4-copyright update-package-copyright-year
 update-copyright-env = \
   UPDATE_COPYRIGHT_FORCE=1 UPDATE_COPYRIGHT_USE_INTERVALS=1
 
+# At least for Mac OS X's grep, the order between . and [ in "[^.[]"
+# matters:
+# $ LC_ALL=fr_FR grep -nE '[^[.]' /dev/null
+# $ LC_ALL=C grep -nE '[^[.]' /dev/null
+# grep: invalid collating element or class
+# $ LC_ALL=fr_FR grep -nE '[^.[]' /dev/null
+# $ LC_ALL=C grep -nE '[^.[]' /dev/null
+sc_at_parser_check:
+       @prohibit='AT_PARSER_CHECK\(\[+[^.[]|AT_CHECK\(\[+\./'          \
+       halt='use AT_PARSER_CHECK for and only for generated parsers'   \
+         $(_sc_search_regexp)
+
 exclude = \
   $(foreach a,$(1),$(eval $(subst $$,$$$$,exclude_file_name_regexp--sc_$(a))))
 $(call exclude,                                                                \
@@ -75,5 +88,5 @@ $(call exclude,                                                               \
   require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$           \
   space_tab=^tests/(input|c\+\+)\.at$$                                 \
   trailing_blank=^src/parse-gram.[ch]$$                                        \
-  unmarked_diagnostics=^(djgpp/|doc/bison.texi$$)                      \
+  unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$)    \
 )
index 86783d525578f2dffd1400a9e8218bdd5896624f..83e20acb01ade45da8f32b2fd046315dd6bd1a16 100644 (file)
@@ -132,6 +132,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 353c75a017efd7fa4076ece4c789493fe80fc574..40575efdb19c0d29b0a602546fcffc8b0176692d 100644 (file)
   <xsl:value-of select="string-length(translate($conflict-data, 's', ''))"/>
 </xsl:template>
 
+<xsl:template name="space">
+  <xsl:param name="repeat">0</xsl:param>
+  <xsl:param name="fill" select="' '"/>
+  <xsl:if test="number($repeat) &gt;= 1">
+    <xsl:call-template name="space">
+      <xsl:with-param name="repeat" select="$repeat - 1"/>
+      <xsl:with-param name="fill" select="$fill"/>
+    </xsl:call-template>
+    <xsl:value-of select="$fill"/>
+  </xsl:if>
+</xsl:template>
+
 </xsl:stylesheet>
index 219faa2f1e77cf738cac5031edd090d05d555640..dceb8e1eebd3086b5d3293be5a5a568d2be2872e 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>
   <xsl:call-template name="output-node">
     <xsl:with-param name="number" select="@number"/>
     <xsl:with-param name="label">
-      <xsl:value-of select="@number"/>
       <xsl:apply-templates select="itemset/item"/>
     </xsl:with-param>
   </xsl:call-template>
   <xsl:apply-templates select="actions/transitions"/>
+  <xsl:apply-templates select="actions/reductions">
+    <xsl:with-param name="staten">
+      <xsl:value-of select="@number"/>
+    </xsl:with-param>
+  </xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="actions/reductions">
+  <xsl:param name="staten"/>
+  <xsl:for-each select='reduction'>
+    <!-- These variables are needed because the current context can't be
+         refered to directly in XPath expressions. -->
+    <xsl:variable name="rul">
+      <xsl:value-of select="@rule"/>
+    </xsl:variable>
+    <xsl:variable name="ena">
+      <xsl:value-of select="@enabled"/>
+    </xsl:variable>
+    <!-- The foreach's body is protected by this, so that we are actually
+         going to iterate once per reduction rule, and not per lookahead. -->
+    <xsl:if test='not(preceding-sibling::*[@rule=$rul and @enabled=$ena])'>
+      <xsl:variable name="rule">
+        <xsl:choose>
+          <!-- The acceptation state is refered to as 'accept' in the XML, but
+               just as '0' in the DOT. -->
+          <xsl:when test="@rule='accept'">
+            <xsl:text>0</xsl:text>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="@rule"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:variable>
+
+      <!-- The edge's beginning -->
+      <xsl:call-template name="reduction-edge-start">
+        <xsl:with-param name="state" select="$staten"/>
+        <xsl:with-param name="rule" select="$rule"/>
+        <xsl:with-param name="enabled" select="@enabled"/>
+      </xsl:call-template>
+
+      <!-- The edge's tokens -->
+      <!-- Don't show labels for the default action. In other cases, there will
+           always be at least one token, so 'label="[]"' will not occur. -->
+      <xsl:if test='$rule!=0 and not(../reduction[@enabled=$ena and @rule=$rule and @symbol="$default"])'>
+        <xsl:text>label="[</xsl:text>
+        <xsl:for-each select='../reduction[@enabled=$ena and @rule=$rule]'>
+          <xsl:call-template name="escape">
+            <xsl:with-param name="subject" select="@symbol"/>
+          </xsl:call-template>
+          <xsl:if test="position() != last ()">
+            <xsl:text>, </xsl:text>
+          </xsl:if>
+        </xsl:for-each>
+        <xsl:text>]", </xsl:text>
+      </xsl:if>
+
+      <!-- The edge's end -->
+      <xsl:text>style=solid]&#10;</xsl:text>
+
+      <!-- The diamond representing the reduction -->
+      <xsl:call-template name="reduction-node">
+        <xsl:with-param name="state" select="$staten"/>
+        <xsl:with-param name="rule" select="$rule"/>
+        <xsl:with-param name="color">
+          <xsl:choose>
+            <xsl:when test='@enabled="true"'>
+              <xsl:text>3</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:text>5</xsl:text>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:with-param>
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:for-each>
 </xsl:template>
 
 <xsl:template match="actions/transitions">
 </xsl:template>
 
 <xsl:template match="item">
+  <xsl:param name="prev-rule-number"
+    select="preceding-sibling::item[1]/@rule-number"/>
   <xsl:apply-templates select="key('bison:ruleByNumber', @rule-number)">
     <xsl:with-param name="point" select="@point"/>
+    <xsl:with-param name="num" select="@rule-number"/>
+    <xsl:with-param name="prev-lhs"
+      select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
+   />
   </xsl:apply-templates>
   <xsl:apply-templates select="lookaheads"/>
 </xsl:template>
 
 <xsl:template match="rule">
   <xsl:param name="point"/>
+  <xsl:param name="num"/>
+  <xsl:param name="prev-lhs"/>
   <xsl:text>&#10;</xsl:text>
-  <xsl:value-of select="lhs"/>
-  <xsl:text> -&gt;</xsl:text>
+  <xsl:choose>
+    <xsl:when test="$num &lt; 10">
+      <xsl:text>  </xsl:text>
+    </xsl:when>
+    <xsl:when test="$num &lt; 100">
+      <xsl:text> </xsl:text>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:text></xsl:text>
+    </xsl:otherwise>
+  </xsl:choose>
+  <xsl:value-of select="$num"/>
+  <xsl:text> </xsl:text>
+  <xsl:choose>
+  <xsl:when test="$prev-lhs = lhs[text()]">
+      <xsl:call-template name="lpad">
+        <xsl:with-param name="str" select="'|'"/>
+        <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="lhs"/>
+      <xsl:text>:</xsl:text>
+    </xsl:otherwise>
+  </xsl:choose>
   <xsl:if test="$point = 0">
     <xsl:text> .</xsl:text>
   </xsl:if>
 <xsl:template match="empty"/>
 
 <xsl:template match="lookaheads">
-  <xsl:text>[</xsl:text>
+  <xsl:text>  [</xsl:text>
   <xsl:apply-templates select="symbol"/>
   <xsl:text>]</xsl:text>
 </xsl:template>
   </xsl:if>
 </xsl:template>
 
+<xsl:template name="reduction-edge-start">
+  <xsl:param name="state"/>
+  <xsl:param name="rule"/>
+  <xsl:param name="enabled"/>
+
+  <xsl:text>  </xsl:text>
+  <xsl:value-of select="$state"/>
+  <xsl:text> -> "</xsl:text>
+  <xsl:value-of select="$state"/>
+  <xsl:text>R</xsl:text>
+  <xsl:value-of select="$rule"/>
+  <xsl:if test='$enabled = "false"'>
+    <xsl:text>d</xsl:text>
+  </xsl:if>
+  <xsl:text>" [</xsl:text>
+</xsl:template>
+
+<xsl:template name="reduction-node">
+  <xsl:param name="state"/>
+  <xsl:param name="rule"/>
+  <xsl:param name="color"/>
+
+  <xsl:text> "</xsl:text>
+  <xsl:value-of select="$state"/>
+  <xsl:text>R</xsl:text>
+  <xsl:value-of select="$rule"/>
+  <xsl:if test="$color = 5">
+    <xsl:text>d</xsl:text>
+  </xsl:if>
+  <xsl:text>" [label="</xsl:text>
+  <xsl:choose>
+  <xsl:when test="$rule = 0">
+    <xsl:text>Acc", fillcolor=1</xsl:text>
+  </xsl:when>
+  <xsl:otherwise>
+    <xsl:text>R</xsl:text>
+    <xsl:value-of select="$rule"/>
+    <xsl:text>", fillcolor=</xsl:text>
+    <xsl:value-of select="$color"/>
+  </xsl:otherwise>
+  </xsl:choose>
+  <xsl:text>, shape=diamond, style=filled]&#10;</xsl:text>
+</xsl:template>
+
 <xsl:template match="transition">
   <xsl:call-template name="output-edge">
     <xsl:with-param name="src" select="../../../@number"/>
   <xsl:text>  </xsl:text>
   <xsl:value-of select="$number"/>
   <xsl:text> [label="</xsl:text>
+  <xsl:text>State </xsl:text>
+  <xsl:value-of select="$number"/>
+  <xsl:text>\n</xsl:text>
   <xsl:call-template name="escape">
     <xsl:with-param name="subject" select="$label"/>
   </xsl:call-template>
-  <xsl:text>"]&#10;</xsl:text>
+  <xsl:text>\l"]&#10;</xsl:text>
 </xsl:template>
 
 <xsl:template name="output-edge">
       </xsl:call-template>
     </xsl:with-param>
     <xsl:with-param name="search" select="'&#10;'"/>
-    <xsl:with-param name="replace" select="'\n'"/>
+    <xsl:with-param name="replace" select="'\l'"/>
   </xsl:call-template>
 </xsl:template>
 
   </xsl:choose>
 </xsl:template>
 
+<xsl:template name="lpad">
+  <xsl:param name="str" select="''"/>
+  <xsl:param name="pad" select="0"/>
+  <xsl:variable name="diff" select="$pad - string-length($str)" />
+  <xsl:choose>
+    <xsl:when test="$diff &lt; 0">
+      <xsl:value-of select="$str"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:call-template name="space">
+        <xsl:with-param name="repeat" select="$diff"/>
+      </xsl:call-template>
+      <xsl:value-of select="$str"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
 </xsl:stylesheet>
index d14f1be5bc6385be45f0439f61f1c1dbdd192b5a..8b3f5ae4c39a4c624c164c662a497bad94a75335 100644 (file)
 <xsl:template match="automaton/state">
   <xsl:param name="pad"/>
   <xsl:text>&#10;&#10;</xsl:text>
-  <xsl:text>state </xsl:text>
+  <xsl:text>State </xsl:text>
   <xsl:value-of select="@number"/>
   <xsl:text>&#10;&#10;</xsl:text>
   <xsl:apply-templates select="itemset/item">
   </xsl:choose>
 </xsl:template>
 
-<xsl:template name="space">
-  <xsl:param name="repeat">0</xsl:param>
-  <xsl:param name="fill" select="' '"/>
-  <xsl:if test="number($repeat) &gt;= 1">
-    <xsl:call-template name="space">
-      <xsl:with-param name="repeat" select="$repeat - 1"/>
-      <xsl:with-param name="fill" select="$fill"/>
-    </xsl:call-template>
-    <xsl:value-of select="$fill"/>
-  </xsl:if>
-</xsl:template>
-
 <xsl:template name="line-wrap">
   <xsl:param name="line-length"/> <!-- required -->
   <xsl:param name="first-line-length" select="$line-length"/>
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 8e257a607af95960cb274bcafe39013c96bd2da7..f2d3dbc52dcffd3e2a275e7b3f5fad582ee89bfb 100644 (file)
@@ -295,6 +295,8 @@ Handling Context Dependencies
 Debugging Your Parser
 
 * Understanding::     Understanding the structure of your parser.
+* Graphviz::          Getting a visual representation of the parser.
+* Xml::               Getting a markup representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 
 Tracing Your Parser
@@ -328,6 +330,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
 
@@ -4702,6 +4705,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
 
@@ -5322,6 +5329,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
@@ -5329,7 +5353,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
@@ -8165,6 +8189,8 @@ 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.
+* Xml::               Getting a markup representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 @end menu
 
@@ -8581,6 +8607,165 @@ precedence of @samp{/} with respect to @samp{+}, @samp{-}, and
 @samp{*}, but also because the
 associativity of @samp{/} is not specified.
 
+Note that Bison may also produce an HTML version of this output, via an XML
+file and XSLT processing (@pxref{Xml}).
+
+@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
+(@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.
+
+Note that a DOT file may also be produced via an XML file and XSLT
+processing (@pxref{Xml}).
+
+@c ================================================= XML
+
+@node Xml
+@section Visualizing your parser in multiple formats
+@cindex xml
+
+Bison supports two major report formats: textual output
+(@pxref{Understanding}) when invoked with option @option{--verbose}, and DOT
+(@pxref{Graphviz}) when invoked with option @option{--graph}. However,
+another alternative is to output an XML file that may then be, with
+@command{xsltproc}, rendered as either a raw text format equivalent to the
+verbose file, or as an HTML version of the same file, with clickable
+transitions, or even as a DOT. The @file{.output} and DOT files obtained via
+XSLT have no difference whatsoever with those obtained by invoking
+@command{bison} with options @option{--verbose} or @option{--graph}.
+
+The textual file is generated when the options @option{-x} or
+@option{--xml[=FILE]} are specified, see @ref{Invocation,,Invoking Bison}.
+If not specified, its name is made by removing @samp{.tab.c} or @samp{.c}
+from the parser implementation file name, and adding @samp{.xml} instead.
+For instance, if the grammar file is @file{foo.y}, the default XML output
+file is @file{foo.xml}.
+
+Bison ships with a @file{data/xslt} directory, containing XSL Transformation
+files to apply to the XML file. Their names are non-ambiguous:
+
+@table @file
+@item xml2dot.xsl
+Used to output a copy of the DOT visualization of the automaton.
+@item xml2text.xsl
+Used to output a copy of the .output file.
+@item xml2xhtml.xsl
+Used to output an xhtml enhancement of the .output file.
+@end table
+
+Sample usage (requires @code{xsltproc}):
+@example
+$ bison -x input.y
+@group
+$ bison --print-datadir
+/usr/local/share/bison
+@end group
+$ xsltproc /usr/local/share/bison/xslt/xml2xhtml.xsl input.xml > input.html
+@end example
+
+@c ================================================= Tracing
 
 @node Tracing
 @section Tracing Your Parser
@@ -9300,8 +9485,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.
@@ -9357,18 +9543,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
@@ -9472,6 +9662,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
@@ -9509,6 +9756,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 ()
@@ -9622,8 +9874,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;
@@ -10180,11 +10432,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.
 
 
@@ -10319,7 +10571,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 ()
@@ -10337,7 +10589,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
 
@@ -10582,10 +10834,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
 
@@ -10600,9 +10853,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
 
@@ -11886,7 +12140,7 @@ 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: parsers parser's
 @c LocalWords: associativity subclasses precedences unresolvable runnable
 @c LocalWords: allocators subunit initializations unreferenced untyped
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 ";" . |
+`----------------'
index 0908f5067abe3eafaea5f88c39f075f980dc0d75..ee34879a8fea96ecd9c7d03419df6bf0156cea96 100644 (file)
@@ -9,6 +9,7 @@ src/main.c
 src/muscle-tab.c
 src/parse-gram.y
 src/print.c
+src/print_graph.c
 src/reader.c
 src/reduce.c
 src/scan-code.l
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..16ea8b9e6e8247d8752235fece77b3d3d68a49ff 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,142 @@ 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 ? "" : "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);
+
+      /* (The lookahead tokens have been added to the beginning of the
+         obstack, in the caller function.) */
+      if (! obstack_empty_p (out))
+        {
+          char *label = obstack_finish0 (out);
+          fprintf (fout, "label=\"[%s]\", ", label);
+          obstack_free (out, label);
+        }
+
+      /* Then, the edge's tail. */
+      fprintf (fout, "style=solid]\n");
+
+      /* Build the associated diamond representation of the target rule. */
+      fprintf (fout, " \"%dR%d%s\" [label=\"",
+               source, ruleno, ed);
+      if (ruleno)
+        fprintf (fout, "R%d", ruleno);
+      else
+        fprintf (fout, "Acc");
+
+      fprintf (fout, "\", fillcolor=%s, shape=diamond, style=filled]\n",
+               color);
+    }
+}
+
+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]->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 (&dout, source, ruleno, false, firstd, fout);
+      conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout);
+    }
+  obstack_free (&dout, 0);
+  obstack_free (&eout, 0);
+  bitset_free (no_reduce_set);
+}
+
 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 c2711ac37ece1d9e174bd9268636820bb384de8d..5633b4e025fdde16fbfde4feb9e906b968fba717 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.6.4.37-63951.  */
+/* A Bison parser, made by GNU Bison 2.6.5.63-3ada.  */
 
 /* Bison implementation for Yacc-like parsers in C
    
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.6.4.37-63951"
+#define YYBISON_VERSION "2.6.5.63-3ada"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
index 7f37630f54529f8f9cf627dc70429e78b593a097..c709098fb9c4a5ce2f05b387b5610303d8b51840 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.6.4.37-63951.  */
+/* A Bison parser, made by GNU Bison 2.6.5.63-3ada.  */
 
 /* Bison interface for Yacc-like parsers in C
    
index cb227aa513081fec25d1665b423dd02f1bc63bc6..5fdb28b580ece827d92647b94b39fe59ab029853 100644 (file)
@@ -370,7 +370,7 @@ static void
 print_state (FILE *out, state *s)
 {
   fputs ("\n\n", out);
-  fprintf (out, _("state %d"), s->number);
+  fprintf (out, _("State %d"), s->number);
   fputc ('\n', out);
   print_core (out, s);
   print_actions (out, s);
index f5695a7a734951fe65d5d498359f3fd66522292f..f4742b165876ccfe9fc45cd9136b0b7456337006 100644 (file)
 | 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 +75,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\\l");
   for (i = 0; i < snritems; i++)
     {
       item_number *sp;
@@ -64,43 +86,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 +139,8 @@ print_core (struct obstack *oout, state *s)
 static void
 print_actions (state const *s, FILE *fgraph)
 {
-  int i;
-
   transitions const *trans = s->transitions;
+  int i;
 
   if (!trans->num && !s->reductions)
     return;
@@ -139,6 +164,8 @@ print_actions (state const *s, FILE *fgraph)
                     TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag,
                     style, fgraph);
       }
+  /* Display reductions. */
+  output_red (s, s->reductions, fgraph);
 }
 
 
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 ad061cc6f86159ba93da4023e60fa326111f8b86..fd6458fa71f3640001ee9f8ef96fe096b543511c 100644 (file)
@@ -103,9 +103,9 @@ static void unexpected_newline (boundary, char const *);
  /* Bracketed identifiers support. */
 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
 
-letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+letter    [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{]
 id       {letter}({letter}|[-0-9])*
-directive %{id}
 int      [0-9]+
 
 /* POSIX says that a tag must be both an id and a C union member, but
@@ -148,7 +148,7 @@ splice       (\\[ \f\t\v]*\n)*
   /* Comments and white space.  */
   ","          warn_at (*loc, _("stray ',' treated as white space"));
   [ \f\n\t\v]  |
-  "//".*       ;
+  "//".*       continue;
   "/*" {
     token_start = loc->start;
     context_state = YY_START;
@@ -218,7 +218,7 @@ splice       (\\[ \f\t\v]*\n)*
   "%verbose"                        return PERCENT_VERBOSE;
   "%yacc"                           return PERCENT_YACC;
 
-  {directive} {
+  "%"{id}|"%"{notletter}([[:graph:]])+ {
     complain_at (*loc, _("invalid directive: %s"), quote (yytext));
   }
 
@@ -290,8 +290,10 @@ splice      (\\[ \f\t\v]*\n)*
     BEGIN SC_BRACKETED_ID;
   }
 
-  . {
-    complain_at (*loc, _("invalid character: %s"), quote_mem (yytext, yyleng));
+  [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. {
+    complain_at (*loc, "%s: %s",
+                 ngettext ("invalid character", "invalid characters", yyleng),
+                 quote_mem (yytext, yyleng));
   }
 
   <<EOF>> {
@@ -373,10 +375,14 @@ splice     (\\[ \f\t\v]*\n)*
     else
       complain_at (*loc, _("an identifier expected"));
   }
-  . {
-    complain_at (*loc, _("invalid character in bracketed name: %s"),
-                quote_mem (yytext, yyleng));
+
+  [^\].A-Za-z0-9_/ \f\n\t\v]+|. {
+    complain_at (*loc, "%s: %s",
+                 ngettext ("invalid character in bracketed name",
+                           "invalid characters in bracketed name", yyleng),
+                 quote_mem (yytext, yyleng));
   }
+
   <<EOF>> {
     BEGIN bracketed_id_context_state;
     unexpected_eof (bracketed_id_start, "]");
@@ -403,7 +409,7 @@ splice       (\\[ \f\t\v]*\n)*
 <SC_YACC_COMMENT>
 {
   "*/"     BEGIN context_state;
-  .|\n    ;
+  .|\n    continue;
   <<EOF>>  unexpected_eof (token_start, "*/"); BEGIN context_state;
 }
 
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..a5d8385397b71b4e34f47f40d030c56b1afc665a 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_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..a13d754628822f0cc9d066e04aaacd64e1eb0967 100644 (file)
@@ -580,7 +580,7 @@ exp (6)
     on left: 1 2, on right: 0 1
 
 
-state 0
+State 0
 
     0 $accept: . exp $end
     1 exp: . exp OP exp
@@ -591,14 +591,14 @@ state 0
     exp  go to state 2
 
 
-state 1
+State 1
 
     2 exp: NUM .
 
     $default  reduce using rule 2 (exp)
 
 
-state 2
+State 2
 
     0 $accept: exp . $end
     1 exp: exp . OP exp
@@ -607,14 +607,14 @@ state 2
     OP    shift, and go to state 4
 
 
-state 3
+State 3
 
     0 $accept: exp $end .
 
     $default  accept
 
 
-state 4
+State 4
 
     1 exp: . exp OP exp
     1    | exp OP . exp
@@ -625,7 +625,7 @@ state 4
     exp  go to state 5
 
 
-state 5
+State 5
 
     1 exp: exp . OP exp
     1    | exp OP exp .  [$end, OP]
@@ -683,7 +683,7 @@ exp (6)
     on left: 1 2, on right: 0 1
 
 
-state 0
+State 0
 
     0 $accept: . exp $end
     1 exp: . exp OP exp
@@ -694,14 +694,14 @@ state 0
     exp  go to state 2
 
 
-state 1
+State 1
 
     2 exp: NUM .
 
     $default  reduce using rule 2 (exp)
 
 
-state 2
+State 2
 
     0 $accept: exp . $end
     1 exp: exp . OP exp
@@ -710,14 +710,14 @@ state 2
     OP    shift, and go to state 4
 
 
-state 3
+State 3
 
     0 $accept: exp $end .
 
     $default  accept
 
 
-state 4
+State 4
 
     1 exp: . exp OP exp
     1    | exp OP . exp
@@ -728,7 +728,7 @@ state 4
     exp  go to state 5
 
 
-state 5
+State 5
 
     1 exp: exp . OP exp
     1    | exp OP exp .  [$end, OP]
@@ -823,7 +823,7 @@ id (7)
     on left: 4, on right: 2
 
 
-state 0
+State 0
 
     0 $accept: . exp $end
     1 exp: . num
@@ -838,7 +838,7 @@ state 0
     id   go to state 4
 
 
-state 1
+State 1
 
     3 num: '0' .  [$end]
     4 id: '0' .  [$end]
@@ -848,28 +848,28 @@ state 1
     $default  reduce using rule 3 (num)
 
 
-state 2
+State 2
 
     0 $accept: exp . $end
 
     $end  shift, and go to state 5
 
 
-state 3
+State 3
 
     1 exp: num .
 
     $default  reduce using rule 1 (exp)
 
 
-state 4
+State 4
 
     2 exp: id .
 
     $default  reduce using rule 2 (exp)
 
 
-state 5
+State 5
 
     0 $accept: exp $end .
 
@@ -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
 
@@ -1170,7 +1170,7 @@ reported_conflicts (9)
     on left: 8 9 10, on right: 1
 
 
-state 0
+State 0
 
     0 $accept: . start $end
     1 start: . resolved_conflict 'a' reported_conflicts 'a'
@@ -1185,28 +1185,28 @@ state 0
     Conflict between rule 3 and token 'a' resolved as reduce (%left 'a').
 
 
-state 1
+State 1
 
     0 $accept: start . $end
 
     $end  shift, and go to state 3
 
 
-state 2
+State 2
 
     1 start: resolved_conflict . 'a' reported_conflicts 'a'
 
     'a'  shift, and go to state 4
 
 
-state 3
+State 3
 
     0 $accept: start $end .
 
     $default  accept
 
 
-state 4
+State 4
 
     1 start: resolved_conflict 'a' . reported_conflicts 'a'
     8 reported_conflicts: . 'a'
@@ -1220,7 +1220,7 @@ state 4
     reported_conflicts  go to state 6
 
 
-state 5
+State 5
 
     8 reported_conflicts: 'a' .  ['a']
     9                   | 'a' .  ['a']
@@ -1230,14 +1230,14 @@ state 5
     $default  reduce using rule 8 (reported_conflicts)
 
 
-state 6
+State 6
 
     1 start: resolved_conflict 'a' reported_conflicts . 'a'
 
     'a'  shift, and go to state 7
 
 
-state 7
+State 7
 
     1 start: resolved_conflict 'a' reported_conflicts 'a' .
 
@@ -1291,8 +1291,8 @@ empty_c2: %prec 'c' ;
 empty_c3: %prec 'd' ;
 ]])
 AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
-AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
-[[state 0
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
 
     0 $accept: . start $end
     1 start: . 'a'
@@ -1328,7 +1328,7 @@ AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
     Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd').
 
 
-state 1
+State 1
 ]])
 
 AT_CLEANUP
@@ -1367,8 +1367,8 @@ empty_c3: %prec 'c' ;
 ]])
 
 AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
-AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
-[[state 0
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
 
     0 $accept: . start $end
     1 start: . 'a'
@@ -1404,7 +1404,7 @@ AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
     Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c').
 
 
-state 1
+State 1
 ]])
 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 149499d4bac90965ea4d3f874334e6530d936aea..1b6fa4d18fa213dcae46f826e05436f8da525ae4 100644 (file)
@@ -489,7 +489,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
      $default  reduce using rule 45 (statement)
 +
 +
-+state 320
++State 320
 +
 +  139 non_post_simp_exp: . '!' simp_exp
 +  140                  | . '(' exp r_paren
@@ -527,7 +527,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable           go to state 63
 +
 +
-+state 321
++State 321
 +
 +  146 non_post_simp_exp: INCREMENT . variable
 +  154 variable: . NAME
@@ -540,7 +540,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable  go to state 50
 +
 +
-+state 322
++State 322
 +
 +  147 non_post_simp_exp: DECREMENT . variable
 +  154 variable: . NAME
@@ -553,7 +553,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable  go to state 51
 +
 +
-+state 323
++State 323
 +
 +  130 simp_exp: . non_post_simp_exp
 +  131         | . simp_exp '^' simp_exp
@@ -601,7 +601,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable           go to state 57
 +
 +
-+state 324
++State 324
 +
 +  130 simp_exp: . non_post_simp_exp
 +  131         | . simp_exp '^' simp_exp
@@ -649,7 +649,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable           go to state 57
 +
 +
-+state 325
++State 325
 +
 +  130 simp_exp: . non_post_simp_exp
 +  131         | . simp_exp '^' simp_exp
@@ -697,7 +697,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    variable           go to state 57
 +
 +
-+state 326
++State 326
 +
 +  131 simp_exp: simp_exp . '^' simp_exp
 +  132         | simp_exp . '*' simp_exp
@@ -718,7 +718,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    Conflict between rule 151 and token '-' resolved as reduce ('-' < UNARY).
 +
 +
-+state 327
++State 327
 +
 +  131 simp_exp: simp_exp . '^' simp_exp
 +  132         | simp_exp . '*' simp_exp
@@ -739,7 +739,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 +    Conflict between rule 150 and token '-' resolved as reduce ('-' < UNARY).
 +
 +
-+state 328
++State 328
 +
 +  131 simp_exp: simp_exp . '^' simp_exp
 +  132         | simp_exp . '*' simp_exp
@@ -2040,7 +2040,7 @@ dnl   - 383 -> 427
      nth_primitive          go to state 105
 @@ -3256,7 +3256,7 @@
 
state 102
State 102
 
 -  146 place: label .  [$end, LABEL, VARIABLE, NUMBER, TEXT, ORDINAL, LEFT_ARROW_HEAD, RIGHT_ARROW_HEAD, DOUBLE_ARROW_HEAD, LAST, UP, DOWN, LEFT, RIGHT, HEIGHT, RADIUS, WIDTH, DIAMETER, FROM, TO, AT, WITH, BY, THEN, SOLID, DOTTED, DASHED, CHOP, SAME, INVISIBLE, LJUST, RJUST, ABOVE, BELOW, AND, HERE, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, SIN, COS, ATAN2, LOG, EXP, SQRT, K_MAX, K_MIN, INT, RAND, SRAND, CW, CCW, THICKNESS, FILL, COLORED, OUTLINED, SHADED, ALIGNED, SPRINTF, '(', '`', ',', '>', '+', '-', '!', ';', '}', '@:>@', ')']
 +  146 place: label .  [$end, LABEL, VARIABLE, NUMBER, TEXT, ORDINAL, LEFT_ARROW_HEAD, RIGHT_ARROW_HEAD, DOUBLE_ARROW_HEAD, LAST, UP, DOWN, LEFT, RIGHT, HEIGHT, RADIUS, WIDTH, DIAMETER, FROM, TO, AT, WITH, BY, THEN, SOLID, DOTTED, DASHED, CHOP, SAME, INVISIBLE, LJUST, RJUST, ABOVE, BELOW, HERE, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, SIN, COS, ATAN2, LOG, EXP, SQRT, K_MAX, K_MIN, INT, RAND, SRAND, CW, CCW, THICKNESS, FILL, COLORED, OUTLINED, SHADED, ALIGNED, SPRINTF, '(', '`', '+', '-', '!', ';', '}', '@:>@']
@@ -2205,7 +2205,7 @@ dnl   - 383 -> 427
 +    expr                   go to state 424
 
 
state 165
State 165
 @@ -7987,7 +7987,7 @@
      text_expr              go to state 112
      text                   go to state 113
@@ -2322,7 +2322,7 @@ dnl   - 383 -> 427
 +    between  go to state 425
 
 
state 193
State 193
 @@ -10152,7 +10152,7 @@
 
      expr_pair              go to state 317
@@ -2490,7 +2490,7 @@ dnl   - 383 -> 427
 +    expr                   go to state 424
 
 
state 238
State 238
 @@ -12937,7 +12937,7 @@
      '!'           shift, and go to state 94
 
@@ -2577,7 +2577,7 @@ dnl   - 383 -> 427
 +    expr                   go to state 424
 
 
state 315
State 315
 @@ -16124,7 +16124,7 @@
 
      $default  reduce using rule 239 (expr)
@@ -2628,7 +2628,7 @@ dnl   - 383 -> 427
 +    expr                   go to state 424
 
 
state 383
State 383
 @@ -18071,7 +18071,7 @@
      '!'           shift, and go to state 94
 
@@ -2671,7 +2671,7 @@ dnl   - 383 -> 427
      $default  reduce using rule 29 (placeless_element)
 +
 +
-+state 423
++State 423
 +
 +  146 place: label .  [$end, AND, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, ',', '>', '+', '-', ';', '}', '@:>@', ')']
 +  147      | label . corner
@@ -2742,7 +2742,7 @@ dnl   - 383 -> 427
 +    corner  go to state 205
 +
 +
-+state 424
++State 424
 +
 +  140 position_not_place: expr . between position AND position
 +  141                   | expr . '<' position ',' position '>'
@@ -2785,7 +2785,7 @@ dnl   - 383 -> 427
 +    between  go to state 425
 +
 +
-+state 425
++State 425
 +
 +  134 position: . position_not_place
 +  135         | . place
@@ -2941,7 +2941,7 @@ dnl   - 383 -> 427
 +    expr                   go to state 424
 +
 +
-+state 426
++State 426
 +
 +  137 position_not_place: position . '+' expr_pair
 +  138                   | position . '-' expr_pair
@@ -2952,7 +2952,7 @@ dnl   - 383 -> 427
 +    '-'  shift, and go to state 198
 +
 +
-+state 427
++State 427
 +
 +  134 position: . position_not_place
 +  135         | . place
index aab0369ffaf847da0a24b706d94c7471b9949307..6ca021f9661c7be10ac4b8d137235337618f3348 100644 (file)
@@ -196,8 +196,12 @@ int
 main (int argc, char **argv)
 {
   input = stdin;
-  if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
-  return yyparse ();
+  if (argc == 2 && !(input = fopen (argv[1], "r")))
+    return 3;
+  int res = yyparse ();
+  if (argc == 2 && fclose (input))
+    return 4;
+  return res;
 }
 ]])
 AT_BISON_OPTION_POPDEFS
@@ -324,8 +328,12 @@ int
 main(int argc, char* argv[])
 {
   input = stdin;
-  if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
-  return yyparse ();
+  if (argc == 2 && !(input = fopen (argv[1], "r")))
+    return 3;
+  int res = yyparse ();
+  if (argc == 2 && fclose (input))
+    return 4;
+  return res;
 }
 ]])
 AT_BISON_OPTION_POPDEFS
@@ -1652,10 +1660,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 b53ee8a02b56149dfba941542a4ba4bfbf785c1c..dcf09a728296d307e54029c6faa28f47b62e2546 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])
 
 AT_LANG_COMPILE([$1.o])
 AT_CHECK([[echo "$1" >>expout]])
index 2848562d9e4c6e1e56b2ba08a87afb38446f8f32..faa939c1037bb7e1aab7862d42a5325752fbf95e 100644 (file)
@@ -39,20 +39,16 @@ 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-2: error: invalid characters: '\0\001\002\377?'
+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 +70,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 +90,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 +115,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 +262,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 +313,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 +425,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 +451,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 +459,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 +725,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 +749,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 +764,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 +805,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 +852,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 +893,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 +907,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 +920,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 +933,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 +946,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 +959,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 +984,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 +997,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 +1041,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 +1050,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 +1071,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 +1089,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 +1126,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 +1138,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 +1147,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 +1172,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 +1206,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 +1257,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 +1272,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 +1287,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 +1315,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 +1357,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 +1415,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 a5dde80a9ad75c89b6c89d91edb2c9f9bb48f38d..efba29dca09d31b770d5c8e1cb6c433e1c5cbd00 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.
@@ -556,10 +556,10 @@ m4_define([AT_BISON_CHECK_XML],
   AT_CHECK([[$XSLTPROC \
              `]]AT_QUELL_VALGRIND[[ bison --print-datadir`/xslt/xml2text.xsl \
              xml-tests/test.xml]], [[0]], [expout])
-  [cp xml-tests/test.dot expout]
+  [sort xml-tests/test.dot > expout]
   AT_CHECK([[$XSLTPROC \
              `]]AT_QUELL_VALGRIND[[ bison --print-datadir`/xslt/xml2dot.xsl \
-             xml-tests/test.xml]], [[0]], [expout])
+             xml-tests/test.xml | sort]], [[0]], [expout])
   [rm -rf xml-tests expout]
   AT_RESTORE_SPECIAL_FILES
 [fi]])
@@ -868,9 +868,9 @@ m4_if(m4_index(m4_quote($3), [no-xml]), -1,
                                [0], [], m4_dquote($7))
 
 m4_if(m4_index(m4_quote($3), [last-state]), -1,
-      [AT_CHECK([[sed -n '/^state 0$/,$p' input.output]], [[0]],
+      [AT_CHECK([[sed -n '/^State 0$/,$p' input.output]], [[0]],
                 m4_dquote($8))],
-      [AT_CHECK([[sed -n 's/^state //p' input.output | tail -1]], [[0]],
+      [AT_CHECK([[sed -n 's/^State //p' input.output | tail -1]], [[0]],
                 m4_dquote($8)[[
 ]])])
 
index 744eab823e8087097e673ce6c473e0f0c3f3a1ba..de48e0f73f3e4739c254bbad13097ee027702ba4 100644 (file)
@@ -49,18 +49,18 @@ static int power (int base, int exponent);
 %nonassoc '='   /* comparison         */
 %left '-' '+'
 %left '*' '/'
-%left NEG /* negation--unary minus */
+%left NEG       /* negation--unary minus */
 %right '^'      /* exponentiation        */
 
 %%
 input:
   line
-| input line         {  }
+| input line         {}
 ;
 
 line:
   '\n'
-| exp '\n'           {  }
+| exp '\n'           {}
 ;
 
 exp:
@@ -69,15 +69,15 @@ exp:
   {
     if ($l != $r)
       fprintf (stderr, "calc: error: %d != %d\n", $l, $r);
-   $$ = $l;
+    $$ = $l;
   }
 | exp[x] '+' { $<ival>$ = $x; } [l] exp[r]  { $$ = $<ival>l + $r;    }
-| exp[l] '-' exp[r]        { $$ = $l - $r;        }
-| exp[l] '*' exp[r]        { $$ = $l * $r;        }
+| exp[l] '-' exp[r]  { $$ = $l - $r;        }
+| exp[l] '*' exp[r]  { $$ = $l * $r;        }
 | exp[l] '/' exp[r]  { $$ = $l / $r;        }
 | '-' exp  %prec NEG { $$ = -$2;            }
-| exp[l] '^' exp[r]        { $$ = power ($l, $r); }
-| '(' exp[e] ')'        { $$ = $e;           }
+| exp[l] '^' exp[r]  { $$ = power ($l, $r); }
+| '(' exp[e] ')'     { $$ = $e;           }
 | '(' error ')'      { $$ = 1111; yyerrok;  }
 | '!'                { $$ = 0; YYERROR;     }
 | '-' error          { $$ = 0; YYERROR;     }
@@ -214,18 +214,18 @@ static int power (int base, int exponent);
 %nonassoc '='   /* comparison         */
 %left '-' '+'
 %left '*' '/'
-%left NEG /* negation--unary minus */
+%left NEG       /* negation--unary minus */
 %right '^'      /* exponentiation        */
 
 %%
 input:
   line
-| input line         {  }
+| input line         {}
 ;
 
 line:
   '\n'
-| exp '\n'           {  }
+| exp '\n'           {}
 ;
 
 exp:
@@ -234,14 +234,14 @@ exp:
   {
     if ($l != $r)
       fprintf (stderr, "calc: error: %d != %d\n", $l, $r);
-   $$ = $l;
+    $$ = $l;
   }
 | exp[x] '+' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>lo9 + $r; }
 | exp[x] '-' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>exp - $r; }
 | exp[x] '*' { $<ival>$ = $x; } [l] exp[r] { $$ = $l * $r; }
 | exp[l] '/' exp[r]  { $$ = $l / $r;        }
 | '-' exp  %prec NEG { $$ = -$2;            }
-| exp[l] '^' exp[r]        { $$ = power ($l, $r12); }
+| exp[l] '^' exp[r]  { $$ = power ($l, $r12); }
 | '(' exp ')'        { $$ = $expo;           }
 | '(' error ')'      { $$ = 1111; yyerrok;  }
 | '!'                { $$ = 0; YYERROR;     }
@@ -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:55.3-53:      symbol not found in production: r12
-test.y:56.29-33: invalid reference: '$expo'
+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.40-43: error: invalid reference: '$r12'
+test.y:55.3-47:      symbol not found in production: r12
+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
 
@@ -443,19 +443,14 @@ AT_SETUP([Stray symbols in brackets])
 AT_DATA_GRAMMAR([test.y],
 [[
 %%
-start: foo[ /* aaa */ *&-.+\000\001\002\377 ] bar
+start: foo[ /* aaa */ *&-.+\000\001\002\377 ] bar
   { s = $foo; }
 ]])
 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.13: error: invalid character in bracketed name: '%'
+test.y:11.25-27: error: invalid characters in bracketed name: '*&-'
+test.y:11.29-30: error: invalid characters in bracketed name: '+\0\001\002\377'
 ]])
 AT_CLEANUP
 
@@ -468,7 +463,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 +510,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 +558,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..657903a5b55ca930d543c0fe8cbf35b90b03b5d5 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\l  0 $accept: . exp $end\l  1 exp: . a '?' b\l  2 a: .\l"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> "0R2" [style=solid]
+ "0R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
+  1 [label="State 1\n\l  0 $accept: exp . $end\l"]
+  1 -> 3 [style=solid label="$end"]
+  2 [label="State 2\n\l  1 exp: a . '?' b\l"]
+  2 -> 4 [style=solid label="'?'"]
+  3 [label="State 3\n\l  0 $accept: exp $end .\l"]
+  3 -> "3R0" [style=solid]
+ "3R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+  4 [label="State 4\n\l  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\l  3 b: 'b' .\l"]
+  5 -> "5R3" [style=solid]
+ "5R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  6 [label="State 6\n\l  1 exp: a '?' b .\l"]
+  6 -> "6R1" [style=solid]
+ "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
+]])
+
+## ------------------------ ##
+## 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\l  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 -> 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"]
+  0 -> "0R7d" [label="['a']", style=solid]
+ "0R7d" [label="R7", fillcolor=5, shape=diamond, style=filled]
+  0 -> "0R8d" [label="['b']", style=solid]
+ "0R8d" [label="R8", fillcolor=5, shape=diamond, style=filled]
+  0 -> "0R9d" [label="['c']", style=solid]
+ "0R9d" [label="R9", fillcolor=5, shape=diamond, style=filled]
+  1 [label="State 1\n\l  1 start: 'a' .\l"]
+  1 -> "1R1" [style=solid]
+ "1R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
+  2 [label="State 2\n\l  3 start: 'b' .\l"]
+  2 -> "2R3" [style=solid]
+ "2R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  3 [label="State 3\n\l  5 start: 'c' .\l"]
+  3 -> "3R5" [style=solid]
+ "3R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
+  4 [label="State 4\n\l  0 $accept: start . $end\l"]
+  4 -> 8 [style=solid label="$end"]
+  5 [label="State 5\n\l  2 start: empty_a . 'a'\l"]
+  5 -> 9 [style=solid label="'a'"]
+  6 [label="State 6\n\l  4 start: empty_b . 'b'\l"]
+  6 -> 10 [style=solid label="'b'"]
+  7 [label="State 7\n\l  6 start: empty_c . 'c'\l"]
+  7 -> 11 [style=solid label="'c'"]
+  8 [label="State 8\n\l  0 $accept: start $end .\l"]
+  8 -> "8R0" [style=solid]
+ "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+  9 [label="State 9\n\l  2 start: empty_a 'a' .\l"]
+  9 -> "9R2" [style=solid]
+ "9R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
+  10 [label="State 10\n\l  4 start: empty_b 'b' .\l"]
+  10 -> "10R4" [style=solid]
+ "10R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
+  11 [label="State 11\n\l  6 start: empty_c 'c' .\l"]
+  11 -> "11R6" [style=solid]
+ "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
+]])
+
+## ---------------------- ##
+## 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\l  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 -> 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"]
+  0 -> "0R7" [style=solid]
+ "0R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
+  1 [label="State 1\n\l  3 start: 'b' .\l"]
+  1 -> "1R3" [style=solid]
+ "1R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  2 [label="State 2\n\l  5 start: 'c' .\l"]
+  2 -> "2R5" [style=solid]
+ "2R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
+  3 [label="State 3\n\l  0 $accept: start . $end\l"]
+  3 -> 7 [style=solid label="$end"]
+  4 [label="State 4\n\l  2 start: empty_a . 'a'\l"]
+  4 -> 8 [style=solid label="'a'"]
+  5 [label="State 5\n\l  4 start: empty_b . 'b'\l"]
+  5 -> 9 [style=solid label="'b'"]
+  6 [label="State 6\n\l  6 start: empty_c . 'c'\l"]
+  6 -> 10 [style=solid label="'c'"]
+  7 [label="State 7\n\l  0 $accept: start $end .\l"]
+  7 -> "7R0" [style=solid]
+ "7R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+  8 [label="State 8\n\l  2 start: empty_a 'a' .\l"]
+  8 -> "8R2" [style=solid]
+ "8R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
+  9 [label="State 9\n\l  4 start: empty_b 'b' .\l"]
+  9 -> "9R4" [style=solid]
+ "9R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
+  10 [label="State 10\n\l  6 start: empty_c 'c' .\l"]
+  10 -> "10R6" [style=solid]
+ "10R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
+]])
+
+## ---------------- ##
+## Graph with  R/R. ##
+## ---------------- ##
+
+AT_TEST([Graph with R/R],
+[[%%
+exp: a | b;
+a: ;
+b: ;
+]],
+[[
+  0 [label="State 0\n\l  0 $accept: . exp $end\l  1 exp: . a\l  2    | . b\l  3 a: .  [$end]\l  4 b: .  [$end]\l"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  0 -> "0R3" [style=solid]
+ "0R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  0 -> "0R4d" [label="[$end]", style=solid]
+ "0R4d" [label="R4", fillcolor=5, shape=diamond, style=filled]
+  1 [label="State 1\n\l  0 $accept: exp . $end\l"]
+  1 -> 4 [style=solid label="$end"]
+  2 [label="State 2\n\l  1 exp: a .\l"]
+  2 -> "2R1" [style=solid]
+ "2R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
+  3 [label="State 3\n\l  2 exp: b .\l"]
+  3 -> "3R2" [style=solid]
+ "3R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
+  4 [label="State 4\n\l  0 $accept: exp $end .\l"]
+  4 -> "4R0" [style=solid]
+ "4R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+]])
+
+## ---------------------------------------- ##
+## 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\l  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 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  0 -> 4 [style=dashed label="c"]
+  0 -> "0R8" [style=solid]
+ "0R8" [label="R8", fillcolor=3, shape=diamond, style=filled]
+  0 -> "0R9" [label="['?', '!']", style=solid]
+ "0R9" [label="R9", fillcolor=3, shape=diamond, style=filled]
+  0 -> "0R10d" [label="[';', '?']", style=solid]
+ "0R10d" [label="R10", fillcolor=5, shape=diamond, style=filled]
+  1 [label="State 1\n\l  0 $accept: exp . $end\l"]
+  1 -> 5 [style=solid label="$end"]
+  2 [label="State 2\n\l  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\l  4 exp: b . '?'\l  5    | b . '!'\l"]
+  3 -> 8 [style=solid label="'?'"]
+  3 -> 9 [style=solid label="'!'"]
+  4 [label="State 4\n\l  6 exp: c . '?'\l  7    | c . ';'\l"]
+  4 -> 10 [style=solid label="';'"]
+  4 -> 11 [style=solid label="'?'"]
+  5 [label="State 5\n\l  0 $accept: exp $end .\l"]
+  5 -> "5R0" [style=solid]
+ "5R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+  6 [label="State 6\n\l  1 exp: a ';' .  [$end]\l  2    | a ';' .  [$end]\l"]
+  6 -> "6R1" [style=solid]
+ "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
+  6 -> "6R2d" [label="[$end]", style=solid]
+ "6R2d" [label="R2", fillcolor=5, shape=diamond, style=filled]
+  7 [label="State 7\n\l  3 exp: a '.' .\l"]
+  7 -> "7R3" [style=solid]
+ "7R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  8 [label="State 8\n\l  4 exp: b '?' .\l"]
+  8 -> "8R4" [style=solid]
+ "8R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
+  9 [label="State 9\n\l  5 exp: b '!' .\l"]
+  9 -> "9R5" [style=solid]
+ "9R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
+  10 [label="State 10\n\l  7 exp: c ';' .\l"]
+  10 -> "10R7" [style=solid]
+ "10R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
+  11 [label="State 11\n\l  6 exp: c '?' .\l"]
+  11 -> "11R6" [style=solid]
+ "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
+]])
+
+## ------------------------------------------------------ ##
+## 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\l  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\l  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\l  8 imm: '0' .\l"]
+  2 -> "2R8" [style=solid]
+ "2R8" [label="R8", fillcolor=3, shape=diamond, style=filled]
+  3 [label="State 3\n\l  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\l  1 exp: ifexp .\l"]
+  4 -> "4R1" [style=solid]
+ "4R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
+  5 [label="State 5\n\l  2 exp: opexp .\l"]
+  5 -> "5R2" [style=solid]
+ "5R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
+  6 [label="State 6\n\l  3 exp: imm .\l"]
+  6 -> "6R3" [style=solid]
+ "6R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
+  7 [label="State 7\n\l  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\l  0 $accept: exp $end .\l"]
+  8 -> "8R0" [style=solid]
+ "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
+  9 [label="State 9\n\l  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\l  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\l  7 opexp: exp . '+' exp\l  7      | exp '+' exp .  [$end, \"then\", \"else\", '+']\l"]
+  11 -> 9 [style=solid label="'+'"]
+  11 -> "11R7d" [label="['+']", style=solid]
+ "11R7d" [label="R7", fillcolor=5, shape=diamond, style=filled]
+  11 -> "11R7" [style=solid]
+ "11R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
+  12 [label="State 12\n\l  4 ifexp: \"if\" exp \"then\" exp . elseexp\l  5 elseexp: . \"else\" exp\l  6        | .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
+  12 -> 13 [style=solid label="\"else\""]
+  12 -> 9 [style=solid label="'+'"]
+  12 -> 14 [style=dashed label="elseexp"]
+  12 -> "12R6d" [label="[\"else\", '+']", style=solid]
+ "12R6d" [label="R6", fillcolor=5, shape=diamond, style=filled]
+  12 -> "12R6" [style=solid]
+ "12R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
+  13 [label="State 13\n\l  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\l  4 ifexp: \"if\" exp \"then\" exp elseexp .\l"]
+  14 -> "14R4" [style=solid]
+ "14R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
+  15 [label="State 15\n\l  5 elseexp: \"else\" exp .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
+  15 -> 9 [style=solid label="'+'"]
+  15 -> "15R5d" [label="['+']", style=solid]
+ "15R5d" [label="R5", fillcolor=5, shape=diamond, style=filled]
+  15 -> "15R5" [style=solid]
+ "15R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
+]])
+
+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 c528eed809495bebed100a69795daba3553835a8..bf43bf9dc7922175bb4b9b3f5941f4e504b79458 100644 (file)
@@ -437,7 +437,7 @@ dnl BISON-STDERR
 [],
 
 dnl TABLES
-[[state 0
+[[State 0
 
     0 $accept: . S $end
     1 S: . 'a' A 'a'
@@ -451,7 +451,7 @@ dnl TABLES
     S  go to state 4
 
 
-state 1
+State 1
 
     1 S: 'a' . A 'a'
     4 A: . 'a' 'a'
@@ -462,7 +462,7 @@ state 1
     A  go to state 6
 
 
-state 2
+State 2
 
     2 S: 'b' . A 'b'
     4 A: . 'a' 'a'
@@ -473,7 +473,7 @@ state 2
     A  go to state 7
 
 
-state 3
+State 3
 
     3 S: 'c' . c
     4 A: . 'a' 'a'
@@ -487,14 +487,14 @@ state 3
     c  go to state 10
 
 
-state 4
+State 4
 
     0 $accept: S . $end
 
     $end  shift, and go to state 11
 
 
-state 5
+State 5
 
     4 A: 'a' . 'a'
     5  | 'a' .  ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[
@@ -505,21 +505,21 @@ state 5
     Conflict between rule 5 and token 'a' resolved as reduce (%left 'a').
 
 
-state 6
+State 6
 
     1 S: 'a' A . 'a'
 
     'a'  shift, and go to state 13
 
 
-state 7
+State 7
 
     2 S: 'b' A . 'b'
 
     'b'  shift, and go to state 14
 
 
-state 8
+State 8
 
     4 A: 'a' . 'a'
     5  | 'a' .  [$end]
@@ -533,7 +533,7 @@ state 8
                   [[$default]])[  reduce using rule 5 (A)
 
 
-state 9
+State 9
 
     7 c: A .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -541,7 +541,7 @@ state 9
                   [[$default]])[  reduce using rule 7 (c)
 
 
-state 10
+State 10
 
     3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -549,14 +549,14 @@ state 10
                   [[$default]])[  reduce using rule 3 (S)
 
 
-state 11
+State 11
 
     0 $accept: S $end .
 
     $default  accept
 
 
-state 12
+State 12
 
     4 A: 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[  ['a']]])[
 
@@ -564,7 +564,7 @@ state 12
                   [[$default]])[  reduce using rule 4 (A)
 
 
-state 13
+State 13
 
     1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -572,7 +572,7 @@ state 13
                   [[$default]])[  reduce using rule 1 (S)
 
 
-state 14
+State 14
 
     2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -580,7 +580,7 @@ state 14
                   [[$default]])[  reduce using rule 2 (S)
 
 
-state 15
+State 15
 
     6 c: 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -589,7 +589,7 @@ state 15
                                                                        [[]], [[
 
 
-state 16
+State 16
 
     4 A: 'a' . 'a'
     5  | 'a' .  ['b']
@@ -601,14 +601,14 @@ state 16
                   [[$default]])[  reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[
 
 
-state 17
+State 17
 
     4 A: 'a' 'a' .  [$end]
 
     $end  reduce using rule 4 (A)
 
 
-state 18
+State 18
 
     4 A: 'a' 'a' .  ['b']
 
@@ -653,7 +653,7 @@ dnl BISON-STDERR
 [],
 
 dnl TABLES
-[[state 0
+[[State 0
 
     0 $accept: . S $end
     1 S: . 'a' A 'a'
@@ -667,7 +667,7 @@ dnl TABLES
     S  go to state 4
 
 
-state 1
+State 1
 
     1 S: 'a' . A 'a'
     4 A: . 'a' 'a' 'a'
@@ -678,7 +678,7 @@ state 1
     A  go to state 6
 
 
-state 2
+State 2
 
     2 S: 'b' . A 'b'
     4 A: . 'a' 'a' 'a'
@@ -689,7 +689,7 @@ state 2
     A  go to state 7
 
 
-state 3
+State 3
 
     3 S: 'c' . c
     4 A: . 'a' 'a' 'a'
@@ -703,14 +703,14 @@ state 3
     c  go to state 10
 
 
-state 4
+State 4
 
     0 $accept: S . $end
 
     $end  shift, and go to state 11
 
 
-state 5
+State 5
 
     4 A: 'a' . 'a' 'a'
     5  | 'a' . 'a'
@@ -718,21 +718,21 @@ state 5
     'a'  shift, and go to state 12
 
 
-state 6
+State 6
 
     1 S: 'a' A . 'a'
 
     'a'  shift, and go to state 13
 
 
-state 7
+State 7
 
     2 S: 'b' A . 'b'
 
     'b'  shift, and go to state 14
 
 
-state 8
+State 8
 
     4 A: 'a' . 'a' 'a'
     5  | 'a' . 'a'
@@ -741,7 +741,7 @@ state 8
     'a'  shift, and go to state 15
 
 
-state 9
+State 9
 
     7 c: A .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -749,7 +749,7 @@ state 9
                   [[$default]])[  reduce using rule 7 (c)
 
 
-state 10
+State 10
 
     3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -757,14 +757,14 @@ state 10
                   [[$default]])[  reduce using rule 3 (S)
 
 
-state 11
+State 11
 
     0 $accept: S $end .
 
     $default  accept
 
 
-state 12
+State 12
 
     4 A: 'a' 'a' . 'a'
     5  | 'a' 'a' .  ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[
@@ -775,7 +775,7 @@ state 12
     Conflict between rule 5 and token 'a' resolved as reduce (%left 'a').
 
 
-state 13
+State 13
 
     1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -783,7 +783,7 @@ state 13
                   [[$default]])[  reduce using rule 1 (S)
 
 
-state 14
+State 14
 
     2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -791,7 +791,7 @@ state 14
                   [[$default]])[  reduce using rule 2 (S)
 
 
-state 15
+State 15
 
     4 A: 'a' 'a' . 'a'
     5  | 'a' 'a' .  [$end]
@@ -805,7 +805,7 @@ state 15
                   [[$default]])[  reduce using rule 5 (A)
 
 
-state 16
+State 16
 
     4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[  ['a']]])[
 
@@ -813,7 +813,7 @@ state 16
                   [[$default]])[  reduce using rule 4 (A)
 
 
-state 17
+State 17
 
     6 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -822,7 +822,7 @@ state 17
                                                                        [[]], [[
 
 
-state 18
+State 18
 
     4 A: 'a' . 'a' 'a'
     5  | 'a' . 'a'
@@ -831,7 +831,7 @@ state 18
                                               [[19]])[
 
 
-state 19]AT_COND_CASE([[canonical LR]], [[
+State 19]AT_COND_CASE([[canonical LR]], [[
 
     4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -839,7 +839,7 @@ state 19]AT_COND_CASE([[canonical LR]], [[
                   [[$default]])[  reduce using rule 4 (A)
 
 
-state 20]])[
+State 20]])[
 
     4 A: 'a' 'a' . 'a'
     5  | 'a' 'a' .  ['b']
@@ -851,7 +851,7 @@ state 20]])[
                   [[$default]])[  reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[
 
 
-state 21
+State 21
 
     4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[  ['b']]])[
 
@@ -900,7 +900,7 @@ dnl BISON-STDERR
 [],
 
 dnl TABLES
-[[state 0
+[[State 0
 
     0 $accept: . S $end
     1 S: . 'a' A 'a'
@@ -914,7 +914,7 @@ dnl TABLES
     S  go to state 4
 
 
-state 1
+State 1
 
     1 S: 'a' . A 'a'
     4 A: . 'a' 'a' B
@@ -924,7 +924,7 @@ state 1
     A  go to state 6
 
 
-state 2
+State 2
 
     2 S: 'b' . A 'b'
     4 A: . 'a' 'a' B
@@ -934,7 +934,7 @@ state 2
     A  go to state 7
 
 
-state 3
+State 3
 
     3 S: 'c' . c
     4 A: . 'a' 'a' B
@@ -947,35 +947,35 @@ state 3
     c  go to state 10
 
 
-state 4
+State 4
 
     0 $accept: S . $end
 
     $end  shift, and go to state 11
 
 
-state 5
+State 5
 
     4 A: 'a' . 'a' B
 
     'a'  shift, and go to state 12
 
 
-state 6
+State 6
 
     1 S: 'a' A . 'a'
 
     'a'  shift, and go to state 13
 
 
-state 7
+State 7
 
     2 S: 'b' A . 'b'
 
     'b'  shift, and go to state 14
 
 
-state 8
+State 8
 
     4 A: 'a' . 'a' B
     7 c: 'a' . 'a' 'b'
@@ -983,7 +983,7 @@ state 8
     'a'  shift, and go to state 15
 
 
-state 9
+State 9
 
     8 c: A .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -991,7 +991,7 @@ state 9
                   [[$default]])[  reduce using rule 8 (c)
 
 
-state 10
+State 10
 
     3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -999,14 +999,14 @@ state 10
                   [[$default]])[  reduce using rule 3 (S)
 
 
-state 11
+State 11
 
     0 $accept: S $end .
 
     $default  accept
 
 
-state 12
+State 12
 
     4 A: 'a' 'a' . B
     5 B: . 'a'
@@ -1020,7 +1020,7 @@ state 12
     Conflict between rule 6 and token 'a' resolved as reduce (%left 'a').
 
 
-state 13
+State 13
 
     1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1028,7 +1028,7 @@ state 13
                   [[$default]])[  reduce using rule 1 (S)
 
 
-state 14
+State 14
 
     2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1036,7 +1036,7 @@ state 14
                   [[$default]])[  reduce using rule 2 (S)
 
 
-state 15
+State 15
 
     4 A: 'a' 'a' . B
     5 B: . 'a'
@@ -1053,7 +1053,7 @@ state 15
     B  go to state ]AT_COND_CASE([[canonical LR]], [[21]], [[17]])[
 
 
-state 16
+State 16
 
     5 B: 'a' .]AT_COND_CASE([[canonical LR]], [[  ['a']]])[
 
@@ -1061,7 +1061,7 @@ state 16
                   [[$default]])[  reduce using rule 5 (B)
 
 
-state 17
+State 17
 
     4 A: 'a' 'a' B .]AT_COND_CASE([[canonical LR]], [[  ['a']]])[
 
@@ -1069,7 +1069,7 @@ state 17
                   [[$default]])[  reduce using rule 4 (A)
 
 
-state 18
+State 18
 
     7 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1077,7 +1077,7 @@ state 18
                   [[$default]])[  reduce using rule 7 (c)]AT_COND_CASE([[LALR]], [], [[
 
 
-state 19
+State 19
 
     4 A: 'a' . 'a' B
 
@@ -1085,21 +1085,21 @@ state 19
                                               [[20]])[
 
 
-state 20]AT_COND_CASE([[canonical LR]], [[
+State 20]AT_COND_CASE([[canonical LR]], [[
 
     5 B: 'a' .  [$end]
 
     $end  reduce using rule 5 (B)
 
 
-state 21
+State 21
 
     4 A: 'a' 'a' B .  [$end]
 
     $end  reduce using rule 4 (A)
 
 
-state 22]])[
+State 22]])[
 
     4 A: 'a' 'a' . B
     5 B: . 'a'
@@ -1114,14 +1114,14 @@ state 22]])[
     B  go to state ]AT_COND_CASE([[canonical LR]], [[24
 
 
-state 23
+State 23
 
     5 B: 'a' .  ['b']
 
     'b'  reduce using rule 5 (B)
 
 
-state 24
+State 24
 
     4 A: 'a' 'a' B .  ['b']
 
@@ -1195,7 +1195,7 @@ dnl BISON-STDERR
 ]], [])],
 
 dnl TABLES
-[[state 0
+[[State 0
 
     0 $accept: . S $end
     1 S: . 'a' A 'f'
@@ -1213,7 +1213,7 @@ dnl TABLES
     S  go to state 4
 
 
-state 1
+State 1
 
     1 S: 'a' . A 'f'
     2  | 'a' . B
@@ -1226,7 +1226,7 @@ state 1
     B  go to state 7
 
 
-state 2
+State 2
 
     3 S: 'b' . A 'f'
     4  | 'b' . B 'g'
@@ -1240,7 +1240,7 @@ state 2
     B  go to state 10
 
 
-state 3
+State 3
 
     6 S: 'c' . 'c' A 'g'
     7  | 'c' . 'c' B
@@ -1248,14 +1248,14 @@ state 3
     'c'  shift, and go to state 11
 
 
-state 4
+State 4
 
     0 $accept: S . $end
 
     $end  shift, and go to state 12
 
 
-state 5
+State 5
 
     8 A: 'd' . 'e'
     9 B: 'd' . 'e'
@@ -1265,14 +1265,14 @@ state 5
                                                [[20]])[
 
 
-state 6
+State 6
 
     1 S: 'a' A . 'f'
 
     'f'  shift, and go to state 14
 
 
-state 7
+State 7
 
     2 S: 'a' B .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1280,7 +1280,7 @@ state 7
                   [[$default]])[  reduce using rule 2 (S)
 
 
-state 8
+State 8
 
     5 S: 'b' 'd' .  [$end]
     8 A: 'd' . 'e'
@@ -1293,21 +1293,21 @@ state 8
                   [[$default]])[  reduce using rule 5 (S)
 
 
-state 9
+State 9
 
     3 S: 'b' A . 'f'
 
     'f'  shift, and go to state 15
 
 
-state 10
+State 10
 
     4 S: 'b' B . 'g'
 
     'g'  shift, and go to state 16
 
 
-state 11
+State 11
 
     6 S: 'c' 'c' . A 'g'
     7  | 'c' 'c' . B
@@ -1321,14 +1321,14 @@ state 11
     B  go to state 18
 
 
-state 12
+State 12
 
     0 $accept: S $end .
 
     $default  accept]AT_COND_CASE([[LALR]], [[
 
 
-state 13
+State 13
 
     8 A: 'd' 'e' .  ['f', 'g']
     9 B: 'd' 'e' .  [$end, 'g']
@@ -1339,7 +1339,7 @@ state 13
     $default  reduce using rule 8 (A)]], [[
 
 
-state 13
+State 13
 
     8 A: 'd' 'e' .  ['f']
     9 B: 'd' 'e' .  ]AT_COND_CASE([[canonical LR]], [[[$end]]], [[['g']]])[
@@ -1350,7 +1350,7 @@ state 13
                   [[$default]])[  reduce using rule 8 (A)]])[
 
 
-state 14
+State 14
 
     1 S: 'a' A 'f' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1358,7 +1358,7 @@ state 14
                   [[$default]])[  reduce using rule 1 (S)
 
 
-state 15
+State 15
 
     3 S: 'b' A 'f' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1366,7 +1366,7 @@ state 15
                   [[$default]])[  reduce using rule 3 (S)
 
 
-state 16
+State 16
 
     4 S: 'b' B 'g' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1374,14 +1374,14 @@ state 16
                   [[$default]])[  reduce using rule 4 (S)
 
 
-state 17
+State 17
 
     6 S: 'c' 'c' A . 'g'
 
     'g'  shift, and go to state 19
 
 
-state 18
+State 18
 
     7 S: 'c' 'c' B .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1389,7 +1389,7 @@ state 18
                   [[$default]])[  reduce using rule 7 (S)
 
 
-state 19
+State 19
 
     6 S: 'c' 'c' A 'g' .]AT_COND_CASE([[canonical LR]], [[  [$end]]])[
 
@@ -1398,7 +1398,7 @@ state 19
                                                                        [[]], [[
 
 
-state 20]AT_COND_CASE([[canonical LR]], [[
+State 20]AT_COND_CASE([[canonical LR]], [[
 
     8 A: 'd' 'e' .  ['f']
     9 B: 'd' 'e' .  ['g']
@@ -1407,7 +1407,7 @@ state 20]AT_COND_CASE([[canonical LR]], [[
     'g'  reduce using rule 9 (B)
 
 
-state 21
+State 21
 
     8 A: 'd' . 'e'
     9 B: 'd' . 'e'
@@ -1415,7 +1415,7 @@ state 21
     'e'  shift, and go to state 22
 
 
-state 22
+State 22
 
     8 A: 'd' 'e' .  ['g']
     9 B: 'd' 'e' .  [$end]
@@ -1491,7 +1491,7 @@ c: ;
 ]],
 dnl Visit each state mentioned above.
 [['a', 'a']],
-[[state 0
+[[State 0
 
     0 $accept: . start $end
     1 start: . a b
@@ -1505,7 +1505,7 @@ dnl Visit each state mentioned above.
     a      go to state 3
 
 
-state 1
+State 1
 
     4 a: 'a' .]AT_COND_CASE([[accepting]], [[  [$end, 'a', 'b']
 
@@ -1516,14 +1516,14 @@ state 1
     $default  reduce using rule 4 (a)]])[
 
 
-state 2
+State 2
 
     0 $accept: start . $end
 
     $end  shift, and go to state 4
 
 
-state 3
+State 3
 
     1 start: a . b
     2      | a . b 'a'
@@ -1542,14 +1542,14 @@ state 3
     c  go to state 6
 
 
-state 4
+State 4
 
     0 $accept: start $end .
 
     $default  accept
 
 
-state 5
+State 5
 
     1 start: a b .  [$end]
     2      | a b . 'a'
@@ -1560,14 +1560,14 @@ state 5
                   [[$end]])[  reduce using rule 1 (start)
 
 
-state 6
+State 6
 
     3 start: a c . 'b'
 
     'b'  shift, and go to state 8
 
 
-state 7
+State 7
 
     2 start: a b 'a' .]AT_COND_CASE([[accepting]], [[  [$end]
 
@@ -1576,7 +1576,7 @@ state 7
     $default  reduce using rule 2 (start)]])[
 
 
-state 8
+State 8
 
     3 start: a c 'b' .]AT_COND_CASE([[accepting]], [[  [$end]
 
index 03c4b80881808cac7794e8cd42201bfad5cd6b28..3fa20e27c2ecc53ae0258f380315d2b40900e845 100644 (file)
@@ -293,7 +293,7 @@ $@2 (9)
     on left: 3, on right: 4
 
 
-state 0
+State 0
 
     0 $accept: . expr $end
 
@@ -305,7 +305,7 @@ state 0
     $@2   go to state 3
 
 
-state 1
+State 1
 
     2 expr: 'a' . $@1 'b'
 
@@ -314,42 +314,42 @@ state 1
     $@1  go to state 4
 
 
-state 2
+State 2
 
     0 $accept: expr . $end
 
     $end  shift, and go to state 5
 
 
-state 3
+State 3
 
     4 expr: $@2 . 'c'
 
     'c'  shift, and go to state 6
 
 
-state 4
+State 4
 
     2 expr: 'a' $@1 . 'b'
 
     'b'  shift, and go to state 7
 
 
-state 5
+State 5
 
     0 $accept: expr $end .
 
     $default  accept
 
 
-state 6
+State 6
 
     4 expr: $@2 'c' .
 
     $default  reduce using rule 4 (expr)
 
 
-state 7
+State 7
 
     2 expr: 'a' $@1 'b' .
 
@@ -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.  ##
 ## ------------------- ##
@@ -546,7 +598,7 @@ $@1 (11)
     on left: 4, on right: 5
 
 
-state 0
+State 0
 
     0 $accept: . CONST_DEC_PART $end
 
@@ -558,14 +610,14 @@ state 0
     $@1             go to state 4
 
 
-state 1
+State 1
 
     0 $accept: CONST_DEC_PART . $end
 
     $end  shift, and go to state 5
 
 
-state 2
+State 2
 
     1 CONST_DEC_PART: CONST_DEC_LIST .
     3 CONST_DEC_LIST: CONST_DEC_LIST . CONST_DEC
@@ -577,56 +629,56 @@ state 2
     $@1        go to state 4
 
 
-state 3
+State 3
 
     2 CONST_DEC_LIST: CONST_DEC .
 
     $default  reduce using rule 2 (CONST_DEC_LIST)
 
 
-state 4
+State 4
 
     5 CONST_DEC: $@1 . undef_id_tok '=' const_id_tok ';'
 
     undef_id_tok  shift, and go to state 7
 
 
-state 5
+State 5
 
     0 $accept: CONST_DEC_PART $end .
 
     $default  accept
 
 
-state 6
+State 6
 
     3 CONST_DEC_LIST: CONST_DEC_LIST CONST_DEC .
 
     $default  reduce using rule 3 (CONST_DEC_LIST)
 
 
-state 7
+State 7
 
     5 CONST_DEC: $@1 undef_id_tok . '=' const_id_tok ';'
 
     '='  shift, and go to state 8
 
 
-state 8
+State 8
 
     5 CONST_DEC: $@1 undef_id_tok '=' . const_id_tok ';'
 
     const_id_tok  shift, and go to state 9
 
 
-state 9
+State 9
 
     5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok . ';'
 
     ';'  shift, and go to state 10
 
 
-state 10
+State 10
 
     5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';' .
 
@@ -1073,8 +1125,8 @@ a: 'a' ;
 ]])
 
 AT_BISON_CHECK([[--report=all input.y]])
-AT_CHECK([[sed -n '/^state 1$/,/^state 2$/p' input.output]], [[0]],
-[[state 1
+AT_CHECK([[sed -n '/^State 1$/,/^State 2$/p' input.output]], [[0]],
+[[State 1
 
     2 start: 'a' . a 'a'
     3 a: . 'a'
@@ -1087,7 +1139,7 @@ AT_CHECK([[sed -n '/^state 1$/,/^state 2$/p' input.output]], [[0]],
     a  go to state 5
 
 
-state 2
+State 2
 ]])
 
 AT_CLEANUP
index 388ee09964c3b2426e7e646f9dcac57ef0e98a26..4cbdfd62633e775dc5a972f63fbd10685b1571a2 100644 (file)
@@ -287,7 +287,7 @@ mv stdout expout
 
 # Get the final state in the report, from the "accept" action..
 AT_CHECK([sed -n '
-           /^state \(.*\)/{
+           /^State \(.*\)/{
             s//final state \1/
             x
           }
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
 ]])
 
index 63ae68581c6509034fc23539214cc0ede294ff7c..751db7c659bd837f4d11e13bd16f9777995d24cd 100644 (file)
@@ -47,7 +47,8 @@ m4_define([AT_SYNCLINES_COMPILE],
 # =>
 #   input.y:4: #error "8"
 #
-# The message may include a caret-error:
+# The message may include a caret-error (indented by GCC 4.8,
+# not by clang 3.2):
 #
 #   input.y:1:2: error: #error "1"
 #    #error "1"
@@ -63,13 +64,31 @@ m4_define([AT_SYNCLINES_COMPILE],
 #
 #   distcc[35882] (dcc_connect_by_name) ERROR: failed to look up host "chrisimac": Unknown host
 #   distcc[35882] Warning: failed to distribute input.c to chrisimac/4, running locally instead
-
+#
+# The compiler might end by the number of messages issued (Clang 3.2):
+#
+#    syncline.c:1:2: error: "1"
+#    #error "1"
+#     ^
+#    1 error generated.
 AT_CHECK([[$PERL -p -0777 - stderr <<\EOF
+  # 1. Remove useless lines.
+
+  # distcc clutter.
   s/^distcc\[\d+\] .*\n//gm;
-  s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm;
-  s/^([^:]+:\d+):[^#]*( #error)/$][1:$][2/gm;
+  # Function context.
   s/^[^:]*: In function '[^']+':\n//gm;
-  s/^\ +#error.*\n\ *\^\n//gm;
+  # Caret error.
+  s/^ *#error.*\n *\^\n//gm;
+  # Number of errors.
+  s/^1 error generated\.\n//gm;
+
+  # 2. Normalize the lines we kept.
+
+  # Remove column.
+  s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm;
+  # Map all combinations of "error: " and "#error: " to "#error ".
+  s/^([^:]+:\d+):( |#error|error|:)+/$][1: #error /gm;
 EOF
 ]],
   0, [stdout])