bison-patches
[Top][All Lists]
Advanced

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

FYI: merge branch-2.6 into maint, and maint into master


From: Akim Demaille
Subject: FYI: merge branch-2.6 into maint, and maint into master
Date: Fri, 26 Oct 2012 17:01:47 +0200

This is the result of the final merge.

commit d0a304384f4207bdf7f8b1038c2226c312f5e954
Merge: 6b1cbda 71cb558
Author: Akim Demaille <address@hidden>
Date:   Fri Oct 26 16:50:26 2012 +0200

    Merge remote-tracking branch 'origin/maint'
    
    * origin/maint: (46 commits)
      doc: minor style change
      maint: use gendocs's new -I option
      regen
      yacc.c: do not define location support when not using locations
      maint: be compilable with GCC 4.0
      tests: address a warning from GCC 4.4
      tests: don't use options that Clang does not support
      tests: restore the tests on -Werror
      regen
      parse-gram: update the Bison interface
      fix comment
      maint: post-release administrivia
      version 2.6.4
      regen
      2.6.4: botched 2.6.3
      maint: post-release administrivia
      version 2.6.3
      gnulib: update
      tests: check %no-lines
      NEWS: warnings with clang
      ...

diff --git a/.prev-version b/.prev-version
index 097a15a..2714f53 100644
--- a/.prev-version
+++ b/.prev-version
@@ -1 +1 @@
-2.6.2
+2.6.4
diff --git a/NEWS b/NEWS
index 346c4da..a2ea735 100644
--- a/NEWS
+++ b/NEWS
@@ -242,6 +242,61 @@ GNU Bison NEWS
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Changes in the format of error messages
+
+  This used to be the format of many error reports:
+
+    foo.y:5.10-24: result type clash on merge function 'merge': <t3> != <t2>
+    foo.y:4.13-27: previous declaration
+
+  It is now:
+
+    foo.y:5.10-25: result type clash on merge function 'merge': <t3> != <t2>
+    foo.y:4.13-27:     previous declaration
+
+** Exception safety (lalr1.cc)
+
+  The parse function now catches exceptions, uses the %destructors to
+  release memory (the lookahead symbol and the symbols pushed on the stack)
+  before re-throwing the exception.
+
+  This feature is somewhat experimental.  User feedback would be
+  appreciated.
+
+** New %define variable: api.location.type (glr.cc, lalr1.cc, lalr1.java)
+
+  The %define variable api.location.type defines the name of the type to use
+  for locations.  When defined, Bison no longer generates the position.hh
+  and location.hh files, nor does the parser will include them: the user is
+  then responsible to define her type.
+
+  This can be used in programs with several parsers to factor their location
+  and position files: let one of them generate them, and the others just use
+  them.
+
+  This feature was actually introduced, but not documented, in Bison 2.5,
+  under the name "location_type" (which is maintained for backward
+  compatibility).
+
+  For consistency, lalr1.java's %define variables location_type and
+  position_type are deprecated in favor of api.location.type and
+  api.position.type.
+
+** Graphviz improvements
+
+  The graphical presentation of the states is more readable: their shape is
+  now rectangular, the state number is clearly displayed, and the items are
+  numbered and left-justified.
+
+  The reductions are now explicitly represented as transitions to other
+  diamond shaped nodes.
+
+* Noteworthy changes in release 2.6.4 (2012-10-23) [stable]
+
+  Bison 2.6.3's --version was incorrect.  This release fixes this issue.
+
+* Noteworthy changes in release 2.6.3 (2012-10-22) [stable]
+
 ** Bug fixes
 
   Bugs and portability issues in the test suite have been fixed.
@@ -256,18 +311,6 @@ GNU Bison NEWS
 
   All the generated headers are self-contained.
 
-** 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
-
 ** Header guards (yacc.c, glr.c, glr.cc)
 
   In order to avoid collisions, the header guards are now
@@ -279,15 +322,6 @@ GNU Bison NEWS
 
   will use YY_CALC_LIB_PARSE_H_INCLUDED as guard.
 
-** 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.
-
 ** Fix compiler warnings in the generated parser (yacc.c, glr.c)
 
   The compilation of pure parsers (%define api.pure) can trigger GCC
@@ -305,25 +339,6 @@ GNU Bison NEWS
   "function declared 'noreturn' should not return") have also been
   addressed.
 
-** 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.
-
 * Noteworthy changes in release 2.6.2 (2012-08-03) [stable]
 
 ** Bug fixes
@@ -380,7 +395,7 @@ GNU Bison NEWS
 
 * Noteworthy changes in release 2.6 (2012-07-19) [stable]
 
-** Future changes:
+** Future changes
 
   The next major release of Bison will drop support for the following
   deprecated features.  Please report disagreements to address@hidden
diff --git a/README-hacking b/README-hacking
index ff5b434..7168010 100644
--- a/README-hacking
+++ b/README-hacking
@@ -50,16 +50,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/>
@@ -68,16 +69,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/TODO b/TODO
index 4012746..e8509e3 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,16 @@
 * 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.
 
 ** push-parser
 Check it too when checking the different kinds of parsers.  And be
diff --git a/cfg.mk b/cfg.mk
index e50c629..8e5a8e1 100644
--- 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,
diff --git a/configure.ac b/configure.ac
index d6a86a7..8a297ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,18 @@ if test "$enable_gcc_warnings" = yes; then
   warn_cxx='-Wnoexcept'
 
   AC_LANG_PUSH([C])
+  # Clang supports many of GCC's -W options, but only issues warnings
+  # on the ones it does not recognize.  In that case, gl_WARN_ADD
+  # thinks the option is supported, and unknown options are then added
+  # to CFLAGS.  But then, when -Werror is added in the test suite for
+  # instance, the warning about the unknown option turns into an
+  # error.
+  #
+  # This should be addressed by gnulib's gl_WARN_ADD, but in the
+  # meanwhile, turn warnings about unknown options into errors in
+  # CFLAGS, and restore CFLAGS after the tests.
+  save_CFLAGS=$CFLAGS
+  gl_WARN_ADD([-Werror=unknown-warning-option], [CFLAGS])
   for i in $warn_common $warn_c;
   do
     gl_WARN_ADD([$i], [WARN_CFLAGS])
@@ -83,9 +95,12 @@ if test "$enable_gcc_warnings" = yes; then
   # Warnings for the test suite only.
   gl_WARN_ADD([-Wundef], [WARN_CFLAGS_TEST])
   gl_WARN_ADD([-pedantic], [WARN_CFLAGS_TEST])
+  CFLAGS=$save_CFLAGS
   AC_LANG_POP([C])
 
   AC_LANG_PUSH([C++])
+  save_CXXFLAGS=$CXXFLAGS
+  gl_WARN_ADD([-Werror=unknown-warning-option], [CXXFLAGS])
   for i in $warn_common $warn_cxx;
   do
     gl_WARN_ADD([$i], [WARN_CXXFLAGS])
@@ -96,6 +111,7 @@ if test "$enable_gcc_warnings" = yes; then
   # Warnings for the test suite only.
   gl_WARN_ADD([-Wundef], [WARN_CXXFLAGS_TEST])
   gl_WARN_ADD([-pedantic], [WARN_CXXFLAGS_TEST])
+  CXXFLAGS=$save_CXXFLAGS
   AC_LANG_POP([C++])
 fi
 
@@ -118,6 +134,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
diff --git a/data/c.m4 b/data/c.m4
index 179743c..51ffbe3 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -557,7 +557,7 @@ m4_define([b4_YYDEBUG_define],
 #  endif
 # else /* ! defined YYDEBUG */
 #  define ]b4_api_PREFIX[DEBUG ]b4_parse_trace_if([1], [0])[
-# endif /* ! defined ]b4_api_PREFIX[DEBUG */
+# endif /* ! defined YYDEBUG */
 #endif  /* ! defined ]b4_api_PREFIX[DEBUG */]])[]dnl
 ])
 
diff --git a/data/java.m4 b/data/java.m4
index 2bbd09a..90d01b3 100644
--- a/data/java.m4
+++ b/data/java.m4
@@ -200,7 +200,7 @@ m4_define([b4_init_throws], 
[b4_percent_define_get([[init_throws]])])
 b4_percent_define_default([[api.location.type]], [Location])
 m4_define([b4_location_type], [b4_percent_define_get([[api.location.type]])])
 
-b4_percent_define_default([[api.position.type]], [Position])])
+b4_percent_define_default([[api.position.type]], [Position])
 m4_define([b4_position_type], [b4_percent_define_get([[api.position.type]])])
 
 
diff --git a/data/xslt/xml2dot.xsl b/data/xslt/xml2dot.xsl
index 49f454b..111613c 100644
--- a/data/xslt/xml2dot.xsl
+++ b/data/xslt/xml2dot.xsl
@@ -55,7 +55,11 @@
   <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>
@@ -124,20 +128,20 @@
     <xsl:with-param name="dst" select="@state"/>
     <xsl:with-param name="style">
       <xsl:choose>
-        <xsl:when test="@symbol = 'error'">
-          <xsl:text>dotted</xsl:text>
-        </xsl:when>
-        <xsl:when test="@type = 'shift'">
-          <xsl:text>solid</xsl:text>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:text>dashed</xsl:text>
-        </xsl:otherwise>
+       <xsl:when test="@symbol = 'error'">
+         <xsl:text>dotted</xsl:text>
+       </xsl:when>
+       <xsl:when test="@type = 'shift'">
+         <xsl:text>solid</xsl:text>
+       </xsl:when>
+       <xsl:otherwise>
+         <xsl:text>dashed</xsl:text>
+       </xsl:otherwise>
       </xsl:choose>
     </xsl:with-param>
     <xsl:with-param name="label">
       <xsl:if test="not(@symbol = 'error')">
-        <xsl:value-of select="@symbol"/>
+       <xsl:value-of select="@symbol"/>
       </xsl:if>
     </xsl:with-param>
   </xsl:call-template>
diff --git a/data/yacc.c b/data/yacc.c
index a1d45c4..9ff2032 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -685,18 +685,14 @@ while (0)
 # else
 #  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 # endif
-#endif]], [[
-
-
-/* This macro is provided for backward compatibility. */
-
+#endif]],
+[[/* This macro is provided for backward compatibility. */
 #ifndef YY_LOCATION_PRINT
 # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 #endif]])[
 
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
-
 #ifdef YYLEX_PARAM
 # define YYLEX yylex (]b4_pure_if([&yylval[]b4_locations_if([, &yylloc]), 
])[YYLEX_PARAM)
 #else
diff --git a/doc/bison.texi b/doc/bison.texi
index 84ec16d..3b9f2da 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -298,6 +298,7 @@ Handling Context Dependencies
 Debugging Your Parser
 
 * Understanding::     Understanding the structure of your parser.
+* Graphviz::          Getting a visual representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 
 Tracing Your Parser
@@ -8422,6 +8423,7 @@ automaton, and how to enable and understand the parser 
run-time traces.
 
 @menu
 * Understanding::     Understanding the structure of your parser.
+* Graphviz::          Getting a visual representation of the parser.
 * Tracing::           Tracing the execution of your parser.
 @end menu
 
@@ -8838,6 +8840,114 @@ precedence of @samp{/} with respect to @samp{+}, 
@samp{-}, and
 @samp{*}, but also because the
 associativity of @samp{/} is not specified.
 
address@hidden ================================================= Graphical 
Representation
+
address@hidden Graphviz
address@hidden Visualizing Your Parser
address@hidden dot
+
+As another means to gain better understanding of the shift/reduce
+automaton corresponding to the Bison parser, a DOT file can be generated. Note
+that debugging a real grammar with this is tedious at best, and impractical
+most of the times, because the generated files are huge (the generation of
+a PDF or PNG file from it will take very long, and more often than not it will
+fail due to memory exhaustion). This option was rather designed for beginners,
+to help them understand LR parsers.
+
+This file is generated when the @option{--graph} option is specified (see
address@hidden, , Invoking Bison}).  Its name is made by removing
address@hidden 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:
+
address@hidden
+%%
address@hidden
+exp: a ";" | b ".";
+a: "0";
+b: "0";
address@hidden group
address@hidden 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
address@hidden, , Debugging Your Parser} for a detailled analysis of the
+textual report.
+
address@hidden 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.
+
address@hidden 1
+
+The transitions are represented as directed edges between the current and
+the target states.
+
address@hidden 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:
+
address@hidden
address@hidden
+state 3
+
+    1 exp: a . ";"
+
+    ";"  shift, and go to state 6
address@hidden group
address@hidden example
+
+A Graphviz rendering of this portion of the graph could be:
+
address@hidden @image{figs/example-shift, 100pt}
+
address@hidden 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}:
address@hidden
+state 1
+
+    3 a: "0" .  [";"]
+    4 b: "0" .  ["."]
+
+    "."       reduce using rule 4 (b)
+    $default  reduce using rule 3 (a)
address@hidden example
+
+A Graphviz rendering of this portion of the graph could be:
+
address@hidden @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".
+
address@hidden 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.
+
address@hidden ================================================= Tracing
 
 @node Tracing
 @section Tracing Your Parser
@@ -12580,9 +12690,9 @@ London, Department of Computer Science, TR-00-12 
(December 2000).
 @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 LocationType
address@hidden LocalWords: errorVerbose
 
 @c Local Variables:
 @c ispell-dictionary: "american"
 @c fill-column: 76
 @c End:
address@hidden  LocalWords:  errorVerbose
diff --git a/doc/figs/example-reduce.dot b/doc/figs/example-reduce.dot
new file mode 100644
index 0000000..fdd99c5
--- /dev/null
+++ b/doc/figs/example-reduce.dot
@@ -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
index 0000000..d4e8219
--- /dev/null
+++ b/doc/figs/example-reduce.txt
@@ -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
index 0000000..995ba0e
--- /dev/null
+++ b/doc/figs/example-shift.dot
@@ -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
index 0000000..43b1412
--- /dev/null
+++ b/doc/figs/example-shift.txt
@@ -0,0 +1,12 @@
+.----------------.
+|    State 3     |
+| 1 exp: a . ";" |
+`----------------'
+        |
+        | ";"
+        |
+        v
+.----------------.
+|    State 6     |
+| 1 exp: a ";" . |
+`----------------'
diff --git a/doc/local.mk b/doc/local.mk
index 54c03eb..53c0142 100644
--- a/doc/local.mk
+++ b/doc/local.mk
@@ -112,6 +112,36 @@ $(top_srcdir)/doc/bison.1: doc/bison.help doc/bison.x 
$(top_srcdir)/configure
 
 nodist_man_MANS = doc/yacc.1
 
+## ----------------------------- ##
+## Graphviz examples generation. ##
+## ----------------------------- ##
+
+CLEANDIRS += doc/figs
+FIGS_DOT = doc/figs/example-reduce.dot doc/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 $< >address@hidden
+       $(AM_V_at) mv address@hidden $@
+
+.dot.pdf:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >address@hidden
+       $(AM_V_at) mv address@hidden $@
+
+.dot.png:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >address@hidden
+       $(AM_V_at) mv address@hidden $@
+
 ## -------------- ##
 ## Doxygenation.  ##
 ## -------------- ##
diff --git a/gnulib b/gnulib
index dcf27be..6061979 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit dcf27bef48c9800d5a2be8349226f73f1b8ff2e5
+Subproject commit 6061979365c067965ee376b3d0a65819779a89c5-dirty
diff --git a/src/graphviz.c b/src/graphviz.c
index e62ee1d..3ae0b54 100644
--- a/src/graphviz.c
+++ b/src/graphviz.c
@@ -53,7 +53,10 @@ start_graph (FILE *fout)
            "digraph %s\n"
            "{\n",
            quote (grammar_file));
-  fprintf (fout, "node [shape=box]\n");
+  fprintf (fout,
+           "  node [fontname = courier, shape = box, colorscheme = paired6]\n"
+           "  edge [fontname = courier]\n"
+           "\n");
 }
 
 void
@@ -93,13 +96,54 @@ no_reduce_bitset_init (state const *s, bitset 
*no_reduce_set)
       bitset_set (*no_reduce_set, s->errs->symbols[n]->number);
 }
 
+static void
+conclude_red (struct obstack *out, int source, rule_number ruleno,
+              bool enabled, bool first, FILE *fout)
+{
+  /* If no lookahead tokens were valid transitions, this reduction is
+     actually hidden, so cancel everything. */
+  if (first)
+    return (void) obstack_finish0 (out);
+  else
+    {
+      char const *ed = enabled ? "e" : "d";
+      char const *color = enabled ? ruleno ? "3" : "1" : "5";
+
+      /* First, build the edge's head. The name of reduction nodes is "nRm",
+         with n the source state and m the rule number. This is because we
+         don't want all the reductions bearing a same rule number to point to
+         the same state, since that is not the desired format. */
+      fprintf (fout, "  %1$d -> \"%1$dR%2$d%3$s\" [",
+               source, ruleno, ed);
+
+      if (! obstack_empty_p (out))
+        /* (The lookahead tokens have been added to the beginning of the
+           obstack, in the caller function.) */
+        fprintf (fout, "label = \"[%s]\" ", obstack_finish0 (out));
+
+      /* Then, the edge's tail. */
+      fprintf (fout, "style = solid]\n");
+
+      /* Build the associated diamond representation of the target rule. */
+      fprintf (fout, " \"%dR%d%s\" [style = filled, "
+                    "shape = diamond, fillcolor = %s, ",
+               source, ruleno, ed, color);
+
+     if (ruleno)
+        fprintf (fout, "label = \"R%d\"]\n", ruleno);
+      else
+        fprintf (fout, "label = \"Acc\"]\n");
+
+    }
+}
+
 static bool
 print_token (struct obstack *out, bool first, char const *tok)
 {
   char const *q = escape (tok);
 
   if (! first)
-    obstack_sgrow (out, ",");
+    obstack_sgrow (out, ", ");
   obstack_sgrow (out, q);
   return false;
 }
@@ -110,58 +154,56 @@ output_red (state const *s, reductions const *reds, FILE 
*fout)
   bitset no_reduce_set;
   int j;
   int source = s->number;
-  struct obstack oout;
+
+  /* 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 (&oout);
+  obstack_init (&dout);
+  obstack_init (&eout);
 
   for (j = 0; j < reds->num; ++j)
     {
-      bool disabled = false;
-      bool first = true;
-      int ruleno = reds->rules[j]->user_number;
+      bool defaulted = false;
+      bool firstd = true;
+      bool firste = true;
+      rule_number ruleno = reds->rules[j]->user_number;
       rule *default_reduction = NULL;
 
       if (yydefact[s->number] != 0)
         default_reduction = &rules[yydefact[s->number] - 1];
 
-      /* First, print the edges that represent each possible reduction for
-         the given state. */
-      obstack_printf (&oout, "  %1$d -> \"%1$dR%2$d\" [label=\"",
-                      source, ruleno);
+      /* Build the lookahead tokens lists, one for enabled transitions and one
+         for disabled transistions. */
       if (default_reduction && default_reduction == reds->rules[j])
-        first = print_token (&oout, true, "$default");
-      else
+        defaulted = true;
+      if (reds->lookahead_tokens)
         {
           int i;
           for (i = 0; i < ntokens; i++)
             if (bitset_test (reds->lookahead_tokens[j], i))
               {
-                first = print_token (&oout, first, symbols[i]->tag);
                 if (bitset_test (no_reduce_set, i))
-                  disabled = true;
+                  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);
+                  }
               }
         }
-      obstack_sgrow (&oout, "\" style=solid]\n");
-
-      /* Then, print the reduction's representation. Done later since
-         we need to know whether this reduction is disabled. */
-      obstack_printf (&oout,
-                      " \"%dR%d\" "
-                      "[style=filled shape=diamond fillcolor=%s "
-                      "label=\"R%d\"]\n",
-                      source, ruleno,
-                      disabled ? "firebrick1" : "yellowgreen",
-                      ruleno);
-
-      /* If no lookahead tokens were valid transitions, this reduction is
-         actually disabled, so don't print it. */
-      if (first)
-        (void) obstack_finish0 (&oout);
-      else
-        fprintf (fout, obstack_finish0 (&oout));
+
+      /* Do the actual output. */
+      conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout);
+      conclude_red (&dout, source, ruleno, false, firstd, fout);
     }
-  obstack_free (&oout, 0);
+  obstack_free (&eout, 0);
+  obstack_free (&dout, 0);
 }
 
 void
diff --git a/src/location.h b/src/location.h
index 17da73c..369125b 100644
--- a/src/location.h
+++ b/src/location.h
@@ -88,7 +88,7 @@ typedef struct
 
 } location;
 
-#define YYLTYPE location
+#define GRAM_LTYPE location
 
 #define EMPTY_LOCATION_INIT {{NULL, 0, 0}, {NULL, 0, 0}}
 extern location const empty_location;
diff --git a/src/parse-gram.y b/src/parse-gram.y
index 1624dde..6e58835 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -87,15 +87,15 @@ static char const *char_name (char);
   #define YYTYPE_UINT8 uint_fast8_t
 }
 
-%verbose
-%defines
-%define locations
+%define api.prefix "gram_"
 %define api.pure
+%define locations
 %define parse.error verbose
 %define parse.lac full
 %define parse.trace
-%name-prefix "gram_"
+%defines
 %expect 0
+%verbose
 
 %initial-action
 {
diff --git a/src/print_graph.c b/src/print_graph.c
index ca1dc24..5aa3cc6 100644
--- a/src/print_graph.c
+++ b/src/print_graph.c
@@ -40,11 +40,32 @@
 | 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.  */
@@ -55,7 +76,8 @@ print_core (struct obstack *oout, state *s)
       snritems = nitemset;
     }
 
-  obstack_printf (oout, "state %d\\n", s->number);
+  obstack_printf (oout, _("State %d"), s->number);
+  obstack_sgrow (oout, "\\n");
   for (i = 0; i < snritems; i++)
     {
       item_number *sp;
@@ -69,12 +91,14 @@ print_core (struct obstack *oout, state *s)
 
       r = item_number_as_rule_number (*sp);
 
-      obstack_printf (oout, "%d: %s -> ", r, escape (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 ", escape (symbols[*sp]->tag));
 
-      obstack_1grow (oout, '.');
+      obstack_sgrow (oout, " .");
 
       for (/* Nothing */; *sp >= 0; ++sp)
         obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
@@ -93,7 +117,7 @@ print_core (struct obstack *oout, state *s)
               bitset_iterator biter;
               int k;
               char const *sep = "";
-              obstack_1grow (oout, '[');
+              obstack_sgrow (oout, "  [");
               BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
                 {
                   obstack_sgrow (oout, sep);
@@ -116,9 +140,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;
 
   /* Display reductions. */
   output_red (s, s->reductions, fgraph);
diff --git a/src/reader.h b/src/reader.h
index 2a78f30..badd372 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -51,9 +51,9 @@ void grammar_current_rule_prec_set (symbol *precsym, location 
loc);
 void grammar_current_rule_dprec_set (int dprec, location loc);
 void grammar_current_rule_merge_set (uniqstr name, location loc);
 void grammar_current_rule_symbol_append (symbol *sym, location loc,
-                                         named_ref *named_ref);
+                                         named_ref *nref);
 void grammar_current_rule_action_append (const char *action, location loc,
-                                         named_ref *named_ref, bool);
+                                         named_ref *nref, bool);
 void reader (void);
 void free_merger_functions (void);
 
diff --git a/src/scan-gram.h b/src/scan-gram.h
index ed973c7..72138a2 100644
--- a/src/scan-gram.h
+++ b/src/scan-gram.h
@@ -32,7 +32,7 @@ void gram_scanner_last_string_free (void);
 extern FILE *gram_out;
 extern int gram_lineno;
 
-# define GRAM_LEX_DECL int gram_lex (YYSTYPE *val, location *loc)
+# define GRAM_LEX_DECL int gram_lex (GRAM_STYPE *val, location *loc)
 GRAM_LEX_DECL;
 
 #endif /* !SCAN_GRAM_H_ */
diff --git a/tests/local.at b/tests/local.at
index ac266da..bddcb00 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -465,10 +465,14 @@ m4_define([AT_BISON_CHECK_WARNINGS],
       [m4_null_if([$2], [AT_BISON_CHECK_WARNINGS_($@)])])])
 
 m4_define([AT_BISON_CHECK_WARNINGS_],
-[[# Defining POSIXLY_CORRECT causes bison to complain if options
-        # are added after the grammar file name, so skip these checks
-        # in that case.
-        if test -z "${POSIXLY_CORRECT+set}"; then
+[[# Defining POSIXLY_CORRECT causes bison to complain if options are
+# added after the grammar file name, so skip these checks in that
+# case.
+#
+# Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched
+# as /bin/sh, sets the shell variable POSIXLY_CORRECT to y, but not
+# the environment variable.
+if env | grep '^POSIXLY_CORRECT=' >/dev/null; then :; else
           ]AT_SAVE_SPECIAL_FILES[
 
           # To avoid expanding it repeatedly, store specified stdout.
diff --git a/tests/output.at b/tests/output.at
index d3e3e6e..8171024 100644
--- a/tests/output.at
+++ b/tests/output.at
@@ -251,3 +251,368 @@ AT_CHECK_OUTPUT_FILE_NAME(address@hidden)
 AT_CHECK_OUTPUT_FILE_NAME(address@hidden)
 AT_CHECK_OUTPUT_FILE_NAME([[@<:@]])
 AT_CHECK_OUTPUT_FILE_NAME([[@:>@]])
+
+
+# AT_TEST(SETUP-NAME, GRAMMAR, DOT-BODY)
+# --------------------------------------
+# Check that the DOT graph for GRAMMAR is DOT-BODY.
+m4_pushdef([AT_TEST],
+[AT_SETUP([$1])
+AT_KEYWORDS([[graph]])
+AT_DATA([[input.y]], [$2])
+AT_BISON_CHECK([[-rall --graph input.y]], [0], [[]], [[ignore]])
+AT_CHECK([[grep -v // input.dot]], [0],
+[[
+digraph "input.y"
+{
+  node [fontname = courier, shape = box, colorscheme = paired6]
+  edge [fontname = courier]
+  ]$3[}
+]])
+AT_CLEANUP
+])
+
+
+## ------------------------ ##
+## Graph with no conflicts. ##
+## ------------------------ ##
+
+AT_TEST([Graph with no conflicts],
+[[%%
+exp: a '?' b;
+a: ;
+b: 'b';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a '?' b\l  2 a: .\l"]
+  0 -> "0R2e" [style = solid]
+ "0R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 3 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a . '?' b\l"]
+  2 -> 4 [style=solid label="'?'"]
+  3 [label="State 3\n  0 $accept: exp $end .\l"]
+  3 -> "3R0e" [style = solid]
+ "3R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  4 [label="State 4\n  1 exp: a '?' . b\l  3 b: . 'b'\l"]
+  4 -> 5 [style=solid label="'b'"]
+  4 -> 6 [style=dashed label="b"]
+  5 [label="State 5\n  3 b: 'b' .\l"]
+  5 -> "5R3e" [style = solid]
+ "5R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  6 [label="State 6\n  1 exp: a '?' b .\l"]
+  6 -> "6R1e" [style = solid]
+ "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+]])
+
+## ------------------------ ##
+## Graph with unsolved S/R. ##
+## ------------------------ ##
+
+AT_TEST([Graph with unsolved S/R],
+[[%%
+start:
+    'a'
+  | empty_a 'a'
+  | 'b'
+  | empty_b 'b'
+  | 'c'
+  | empty_c 'c'
+  ;
+empty_a: %prec 'a';
+empty_b: %prec 'b';
+empty_c: %prec 'c';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . 
empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6  
    | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  ['b']\l  9 empty_c: 
.  ['c']\l"]
+  0 -> "0R7d" [label = "['a']" style = solid]
+ "0R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"]
+  0 -> "0R8d" [label = "['b']" style = solid]
+ "0R8d" [style = filled, shape = diamond, fillcolor = 5, label = "R8"]
+  0 -> "0R9d" [label = "['c']" style = solid]
+ "0R9d" [style = filled, shape = diamond, fillcolor = 5, label = "R9"]
+  0 -> 1 [style=solid label="'a'"]
+  0 -> 2 [style=solid label="'b'"]
+  0 -> 3 [style=solid label="'c'"]
+  0 -> 4 [style=dashed label="start"]
+  0 -> 5 [style=dashed label="empty_a"]
+  0 -> 6 [style=dashed label="empty_b"]
+  0 -> 7 [style=dashed label="empty_c"]
+  1 [label="State 1\n  1 start: 'a' .\l"]
+  1 -> "1R1e" [style = solid]
+ "1R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  2 [label="State 2\n  3 start: 'b' .\l"]
+  2 -> "2R3e" [style = solid]
+ "2R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  3 [label="State 3\n  5 start: 'c' .\l"]
+  3 -> "3R5e" [style = solid]
+ "3R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  4 [label="State 4\n  0 $accept: start . $end\l"]
+  4 -> 8 [style=solid label="$end"]
+  5 [label="State 5\n  2 start: empty_a . 'a'\l"]
+  5 -> 9 [style=solid label="'a'"]
+  6 [label="State 6\n  4 start: empty_b . 'b'\l"]
+  6 -> 10 [style=solid label="'b'"]
+  7 [label="State 7\n  6 start: empty_c . 'c'\l"]
+  7 -> 11 [style=solid label="'c'"]
+  8 [label="State 8\n  0 $accept: start $end .\l"]
+  8 -> "8R0e" [style = solid]
+ "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  9 [label="State 9\n  2 start: empty_a 'a' .\l"]
+  9 -> "9R2e" [style = solid]
+ "9R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  10 [label="State 10\n  4 start: empty_b 'b' .\l"]
+  10 -> "10R4e" [style = solid]
+ "10R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  11 [label="State 11\n  6 start: empty_c 'c' .\l"]
+  11 -> "11R6e" [style = solid]
+ "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ---------------------- ##
+## Graph with solved S/R. ##
+## ---------------------- ##
+
+AT_TEST([Graph with solved S/R],
+[[%left 'a'
+%right 'b'
+%right 'c'
+%%
+start:
+    'a'
+  | empty_a 'a'
+  | 'b'
+  | empty_b 'b'
+  | 'c'
+  | empty_c 'c'
+  ;
+empty_a: %prec 'a';
+empty_b: %prec 'b';
+empty_c: %prec 'c';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . 
empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6  
    | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  []\l  9 empty_c: .  
[]\l"]
+  0 -> "0R7e" [style = solid]
+ "0R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  0 -> 1 [style=solid label="'b'"]
+  0 -> 2 [style=solid label="'c'"]
+  0 -> 3 [style=dashed label="start"]
+  0 -> 4 [style=dashed label="empty_a"]
+  0 -> 5 [style=dashed label="empty_b"]
+  0 -> 6 [style=dashed label="empty_c"]
+  1 [label="State 1\n  3 start: 'b' .\l"]
+  1 -> "1R3e" [style = solid]
+ "1R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  2 [label="State 2\n  5 start: 'c' .\l"]
+  2 -> "2R5e" [style = solid]
+ "2R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  3 [label="State 3\n  0 $accept: start . $end\l"]
+  3 -> 7 [style=solid label="$end"]
+  4 [label="State 4\n  2 start: empty_a . 'a'\l"]
+  4 -> 8 [style=solid label="'a'"]
+  5 [label="State 5\n  4 start: empty_b . 'b'\l"]
+  5 -> 9 [style=solid label="'b'"]
+  6 [label="State 6\n  6 start: empty_c . 'c'\l"]
+  6 -> 10 [style=solid label="'c'"]
+  7 [label="State 7\n  0 $accept: start $end .\l"]
+  7 -> "7R0e" [style = solid]
+ "7R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  8 [label="State 8\n  2 start: empty_a 'a' .\l"]
+  8 -> "8R2e" [style = solid]
+ "8R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  9 [label="State 9\n  4 start: empty_b 'b' .\l"]
+  9 -> "9R4e" [style = solid]
+ "9R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  10 [label="State 10\n  6 start: empty_c 'c' .\l"]
+  10 -> "10R6e" [style = solid]
+ "10R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ---------------- ##
+## Graph with  R/R. ##
+## ---------------- ##
+
+AT_TEST([Graph with R/R],
+[[%%
+exp: a | b;
+a: ;
+b: ;
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a\l  2    | . b\l  3 
a: .  [$end]\l  4 b: .  [$end]\l"]
+  0 -> "0R3e" [style = solid]
+ "0R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  0 -> "0R4d" [label = "[$end]" style = solid]
+ "0R4d" [style = filled, shape = diamond, fillcolor = 5, label = "R4"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 4 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a .\l"]
+  2 -> "2R1e" [style = solid]
+ "2R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  3 [label="State 3\n  2 exp: b .\l"]
+  3 -> "3R2e" [style = solid]
+ "3R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  4 [label="State 4\n  0 $accept: exp $end .\l"]
+  4 -> "4R0e" [style = solid]
+ "4R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+]])
+
+## ---------------------------------------- ##
+## Graph with reductions with multiple LAT. ##
+## ---------------------------------------- ##
+
+AT_TEST([Graph with reductions with multiple LAT],
+[[%%
+exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';';
+a: ;
+b: ;
+c: ;
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . a ';'\l  2    | . a 
';'\l  3    | . a '.'\l  4    | . b '?'\l  5    | . b '!'\l  6    | . c '?'\l  
7    | . c ';'\l  8 a: .  [';', '.']\l  9 b: .  ['?', '!']\l 10 c: .  [';', 
'?']\l"]
+  0 -> "0R8e" [style = solid]
+ "0R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"]
+  0 -> "0R9e" [label = "['?', '!']" style = solid]
+ "0R9e" [style = filled, shape = diamond, fillcolor = 3, label = "R9"]
+  0 -> "0R10d" [label = "[';', '?']" style = solid]
+ "0R10d" [style = filled, shape = diamond, fillcolor = 5, label = "R10"]
+  0 -> 1 [style=dashed label="exp"]
+  0 -> 2 [style=dashed label="a"]
+  0 -> 3 [style=dashed label="b"]
+  0 -> 4 [style=dashed label="c"]
+  1 [label="State 1\n  0 $accept: exp . $end\l"]
+  1 -> 5 [style=solid label="$end"]
+  2 [label="State 2\n  1 exp: a . ';'\l  2    | a . ';'\l  3    | a . '.'\l"]
+  2 -> 6 [style=solid label="';'"]
+  2 -> 7 [style=solid label="'.'"]
+  3 [label="State 3\n  4 exp: b . '?'\l  5    | b . '!'\l"]
+  3 -> 8 [style=solid label="'?'"]
+  3 -> 9 [style=solid label="'!'"]
+  4 [label="State 4\n  6 exp: c . '?'\l  7    | c . ';'\l"]
+  4 -> 10 [style=solid label="';'"]
+  4 -> 11 [style=solid label="'?'"]
+  5 [label="State 5\n  0 $accept: exp $end .\l"]
+  5 -> "5R0e" [style = solid]
+ "5R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  6 [label="State 6\n  1 exp: a ';' .  [$end]\l  2    | a ';' .  [$end]\l"]
+  6 -> "6R1e" [style = solid]
+ "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  6 -> "6R2d" [label = "[$end]" style = solid]
+ "6R2d" [style = filled, shape = diamond, fillcolor = 5, label = "R2"]
+  7 [label="State 7\n  3 exp: a '.' .\l"]
+  7 -> "7R3e" [style = solid]
+ "7R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  8 [label="State 8\n  4 exp: b '?' .\l"]
+  8 -> "8R4e" [style = solid]
+ "8R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  9 [label="State 9\n  5 exp: b '!' .\l"]
+  9 -> "9R5e" [style = solid]
+ "9R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  10 [label="State 10\n  7 exp: c ';' .\l"]
+  10 -> "10R7e" [style = solid]
+ "10R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  11 [label="State 11\n  6 exp: c '?' .\l"]
+  11 -> "11R6e" [style = solid]
+ "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+]])
+
+## ------------------------------------------------------ ##
+## Graph with a reduction rule both enabled and disabled. ##
+## ------------------------------------------------------ ##
+
+AT_TEST([Graph with a reduction rule both enabled and disabled],
+[[%%
+exp: ifexp | opexp | imm;
+ifexp: "if" exp "then" exp elseexp;
+elseexp: "else" exp | ;
+opexp: exp '+' exp;
+imm: '0';
+]],
+[[
+  0 [label="State 0\n  0 $accept: . exp $end\l  1 exp: . ifexp\l  2    | . 
opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: 
. exp '+' exp\l  8 imm: . '0'\l"]
+  0 -> 1 [style=solid label="\"if\""]
+  0 -> 2 [style=solid label="'0'"]
+  0 -> 3 [style=dashed label="exp"]
+  0 -> 4 [style=dashed label="ifexp"]
+  0 -> 5 [style=dashed label="opexp"]
+  0 -> 6 [style=dashed label="imm"]
+  1 [label="State 1\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 
ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" . exp \"then\" exp 
elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  1 -> 1 [style=solid label="\"if\""]
+  1 -> 2 [style=solid label="'0'"]
+  1 -> 7 [style=dashed label="exp"]
+  1 -> 4 [style=dashed label="ifexp"]
+  1 -> 5 [style=dashed label="opexp"]
+  1 -> 6 [style=dashed label="imm"]
+  2 [label="State 2\n  8 imm: '0' .\l"]
+  2 -> "2R8e" [style = solid]
+ "2R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"]
+  3 [label="State 3\n  0 $accept: exp . $end\l  7 opexp: exp . '+' exp\l"]
+  3 -> 8 [style=solid label="$end"]
+  3 -> 9 [style=solid label="'+'"]
+  4 [label="State 4\n  1 exp: ifexp .\l"]
+  4 -> "4R1e" [style = solid]
+ "4R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"]
+  5 [label="State 5\n  2 exp: opexp .\l"]
+  5 -> "5R2e" [style = solid]
+ "5R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"]
+  6 [label="State 6\n  3 exp: imm .\l"]
+  6 -> "6R3e" [style = solid]
+ "6R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"]
+  7 [label="State 7\n  4 ifexp: \"if\" exp . \"then\" exp elseexp\l  7 opexp: 
exp . '+' exp\l"]
+  7 -> 10 [style=solid label="\"then\""]
+  7 -> 9 [style=solid label="'+'"]
+  8 [label="State 8\n  0 $accept: exp $end .\l"]
+  8 -> "8R0e" [style = solid]
+ "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"]
+  9 [label="State 9\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 
ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  7      | 
exp '+' . exp\l  8 imm: . '0'\l"]
+  9 -> 1 [style=solid label="\"if\""]
+  9 -> 2 [style=solid label="'0'"]
+  9 -> 11 [style=dashed label="exp"]
+  9 -> 4 [style=dashed label="ifexp"]
+  9 -> 5 [style=dashed label="opexp"]
+  9 -> 6 [style=dashed label="imm"]
+  10 [label="State 10\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 
ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" exp \"then\" . exp 
elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  10 -> 1 [style=solid label="\"if\""]
+  10 -> 2 [style=solid label="'0'"]
+  10 -> 12 [style=dashed label="exp"]
+  10 -> 4 [style=dashed label="ifexp"]
+  10 -> 5 [style=dashed label="opexp"]
+  10 -> 6 [style=dashed label="imm"]
+  11 [label="State 11\n  7 opexp: exp . '+' exp\l  7      | exp '+' exp .  
[$end, \"then\", \"else\", '+']\l"]
+  11 -> "11R7e" [style = solid]
+ "11R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"]
+  11 -> "11R7d" [label = "['+']" style = solid]
+ "11R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"]
+  11 -> 9 [style=solid label="'+'"]
+  12 [label="State 12\n  4 ifexp: \"if\" exp \"then\" exp . elseexp\l  5 
elseexp: . \"else\" exp\l  6        | .  [$end, \"then\", \"else\", '+']\l  7 
opexp: exp . '+' exp\l"]
+  12 -> "12R6e" [style = solid]
+ "12R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"]
+  12 -> "12R6d" [label = "[\"else\", '+']" style = solid]
+ "12R6d" [style = filled, shape = diamond, fillcolor = 5, label = "R6"]
+  12 -> 13 [style=solid label="\"else\""]
+  12 -> 9 [style=solid label="'+'"]
+  12 -> 14 [style=dashed label="elseexp"]
+  13 [label="State 13\n  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 
ifexp: . \"if\" exp \"then\" exp elseexp\l  5 elseexp: \"else\" . exp\l  7 
opexp: . exp '+' exp\l  8 imm: . '0'\l"]
+  13 -> 1 [style=solid label="\"if\""]
+  13 -> 2 [style=solid label="'0'"]
+  13 -> 15 [style=dashed label="exp"]
+  13 -> 4 [style=dashed label="ifexp"]
+  13 -> 5 [style=dashed label="opexp"]
+  13 -> 6 [style=dashed label="imm"]
+  14 [label="State 14\n  4 ifexp: \"if\" exp \"then\" exp elseexp .\l"]
+  14 -> "14R4e" [style = solid]
+ "14R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"]
+  15 [label="State 15\n  5 elseexp: \"else\" exp .  [$end, \"then\", \"else\", 
'+']\l  7 opexp: exp . '+' exp\l"]
+  15 -> "15R5e" [style = solid]
+ "15R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"]
+  15 -> "15R5d" [label = "['+']" style = solid]
+ "15R5d" [style = filled, shape = diamond, fillcolor = 5, label = "R5"]
+  15 -> 9 [style=solid label="'+'"]
+]])
+
+m4_popdef([AT_TEST])
diff --git a/tests/torture.at b/tests/torture.at
index a5e244b..5aa1890 100644
--- a/tests/torture.at
+++ b/tests/torture.at
@@ -431,7 +431,7 @@ int
 main (int argc, const char **argv)
 {
   YYSTYPE yylval_init = get_args (argc, argv);
-  int status;
+  int status = 0;
   int count;
 ]m4_bmatch([$2], [api.push-pull both],
 [[  yypstate *ps = yypstate_new ();




reply via email to

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