diff options
-rw-r--r-- | .prev-version | 2 | ||||
-rw-r--r-- | NEWS | 97 | ||||
-rw-r--r-- | README-hacking | 25 | ||||
-rw-r--r-- | TODO | 12 | ||||
-rw-r--r-- | cfg.mk | 1 | ||||
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | data/c.m4 | 2 | ||||
-rw-r--r-- | data/java.m4 | 2 | ||||
-rw-r--r-- | data/xslt/xml2dot.xsl | 26 | ||||
-rw-r--r-- | data/yacc.c | 8 | ||||
-rw-r--r-- | doc/bison.texi | 112 | ||||
-rw-r--r-- | doc/figs/example-reduce.dot | 11 | ||||
-rw-r--r-- | doc/figs/example-reduce.txt | 13 | ||||
-rw-r--r-- | doc/figs/example-shift.dot | 9 | ||||
-rw-r--r-- | doc/figs/example-shift.txt | 12 | ||||
-rw-r--r-- | doc/local.mk | 30 | ||||
m--------- | gnulib | 0 | ||||
-rw-r--r-- | src/graphviz.c | 110 | ||||
-rw-r--r-- | src/location.h | 2 | ||||
-rw-r--r-- | src/parse-gram.y | 8 | ||||
-rw-r--r-- | src/print_graph.c | 37 | ||||
-rw-r--r-- | src/reader.h | 4 | ||||
-rw-r--r-- | src/scan-gram.h | 2 | ||||
-rw-r--r-- | tests/local.at | 12 | ||||
-rw-r--r-- | tests/output.at | 365 | ||||
-rw-r--r-- | tests/torture.at | 2 |
26 files changed, 793 insertions, 128 deletions
diff --git a/.prev-version b/.prev-version index 097a15a2..2714f531 100644 --- a/.prev-version +++ b/.prev-version @@ -1 +1 @@ -2.6.2 +2.6.4 @@ -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 bug-bison@gnu.org. diff --git a/README-hacking b/README-hacking index ff5b4345..71680100 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 @@ -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 @@ -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 d6a86a73..8a297ff5 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 @@ -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 2bbd09ac..90d01b33 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 49f454bb..111613ce 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>" { </xsl:text> + <xsl:text> { + node [fontname = courier, shape = box, colorscheme = paired6] + edge [fontname = courier] + +</xsl:text> <xsl:apply-templates select="state"/> <xsl:text>} </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 a1d45c43..9ff20322 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 84ec16d9..3b9f2da2 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. +@c ================================================= Graphical Representation + +@node Graphviz +@section Visualizing Your Parser +@cindex dot + +As another means to gain better understanding of the shift/reduce +automaton corresponding to the Bison parser, a DOT file can be generated. Note +that debugging a real grammar with this is tedious at best, and impractical +most of the times, because the generated files are huge (the generation of +a PDF or PNG file from it will take very long, and more often than not it will +fail due to memory exhaustion). This option was rather designed for beginners, +to help them understand LR parsers. + +This file is generated when the @option{--graph} option is specified (see +@pxref{Invocation, , Invoking Bison}). Its name is made by removing +@samp{.tab.c} or @samp{.c} from the parser implementation file name, and +adding @samp{.dot} instead. If the grammar file is @file{foo.y}, the +Graphviz output file is called @file{foo.dot}. + +The following grammar file, @file{rr.y}, will be used in the sequel: + +@example +%% +@group +exp: a ";" | b "."; +a: "0"; +b: "0"; +@end group +@end example + +The graphical output is very similar to the textual one, and as such it is +easier understood by making direct comparisons between them. See +@ref{Debugging, , Debugging Your Parser} for a detailled analysis of the +textual report. + +@subheading Graphical Representation of States + +The items (pointed rules) for each state are grouped together in graph nodes. +Their numbering is the same as in the verbose file. See the following points, +about transitions, for examples + +When invoked with @option{--report=lookaheads}, the lookahead tokens, when +needed, are shown next to the relevant rule between square brackets as a +comma separated list. This is the case in the figure for the representation of +reductions, below. + +@sp 1 + +The transitions are represented as directed edges between the current and +the target states. + +@subheading Graphical Representation of Shifts + +Shifts are shown as solid arrows, labelled with the lookahead token for that +shift. The following describes a reduction in the @file{rr.output} file: + +@example +@group +state 3 + + 1 exp: a . ";" + + ";" shift, and go to state 6 +@end group +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-shift, 100pt} + +@subheading Graphical Representation of Reductions + +Reductions are shown as solid arrows, leading to a diamond-shaped node +bearing the number of the reduction rule. The arrow is labelled with the +appropriate comma separated lookahead tokens. If the reduction is the default +action for the given state, there is no such label. + +This is how reductions are represented in the verbose file @file{rr.output}: +@example +state 1 + + 3 a: "0" . [";"] + 4 b: "0" . ["."] + + "." reduce using rule 4 (b) + $default reduce using rule 3 (a) +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-reduce, 120pt} + +When unresolved conflicts are present, because in deterministic parsing +a single decision can be made, Bison can arbitrarily choose to disable a +reduction, see @ref{Shift/Reduce, , Shift/Reduce Conflicts}. Discarded actions +are distinguished by a red filling color on these nodes, just like how they are +reported between square brackets in the verbose file. + +The reduction corresponding to the rule number 0 is the acceptation state. It +is shown as a blue diamond, labelled "Acc". + +@subheading Graphical representation of go tos + +The @samp{go to} jump transitions are represented as dotted lines bearing +the name of the rule being jumped to. + +@c ================================================= Tracing @node Tracing @section Tracing Your Parser @@ -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 +@c LocalWords: errorVerbose @c Local Variables: @c ispell-dictionary: "american" @c fill-column: 76 @c End: -@c LocalWords: errorVerbose diff --git a/doc/figs/example-reduce.dot b/doc/figs/example-reduce.dot new file mode 100644 index 00000000..fdd99c5d --- /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 00000000..d4e8219f --- /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 00000000..995ba0e4 --- /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 00000000..43b14122 --- /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 54c03ebf..53c0142d 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 $< >$@.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. ## ## -------------- ## diff --git a/gnulib b/gnulib -Subproject dcf27bef48c9800d5a2be8349226f73f1b8ff2e +Subproject 6061979365c067965ee376b3d0a65819779a89c diff --git a/src/graphviz.c b/src/graphviz.c index e62ee1d4..3ae0b546 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 17da73ca..369125b7 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 1624dde5..6e58835a 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 ca1dc24e..5aa3cc62 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 2a78f30a..badd372d 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 ed973c78..72138a27 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 ac266daa..bddcb00e 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 d3e3e6e8..81710245 100644 --- a/tests/output.at +++ b/tests/output.at @@ -251,3 +251,368 @@ AT_CHECK_OUTPUT_FILE_NAME([[@{]]) AT_CHECK_OUTPUT_FILE_NAME([[@}]]) AT_CHECK_OUTPUT_FILE_NAME([[@<:@]]) AT_CHECK_OUTPUT_FILE_NAME([[@:>@]]) + + +# AT_TEST(SETUP-NAME, GRAMMAR, DOT-BODY) +# -------------------------------------- +# Check that the DOT graph for GRAMMAR is DOT-BODY. +m4_pushdef([AT_TEST], +[AT_SETUP([$1]) +AT_KEYWORDS([[graph]]) +AT_DATA([[input.y]], [$2]) +AT_BISON_CHECK([[-rall --graph input.y]], [0], [[]], [[ignore]]) +AT_CHECK([[grep -v // input.dot]], [0], +[[ +digraph "input.y" +{ + node [fontname = courier, shape = box, colorscheme = paired6] + edge [fontname = courier] + ]$3[} +]]) +AT_CLEANUP +]) + + +## ------------------------ ## +## Graph with no conflicts. ## +## ------------------------ ## + +AT_TEST([Graph with no conflicts], +[[%% +exp: a '?' b; +a: ; +b: 'b'; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . a '?' b\l 2 a: .\l"] + 0 -> "0R2e" [style = solid] + "0R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 3 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a . '?' b\l"] + 2 -> 4 [style=solid label="'?'"] + 3 [label="State 3\n 0 $accept: exp $end .\l"] + 3 -> "3R0e" [style = solid] + "3R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 4 [label="State 4\n 1 exp: a '?' . b\l 3 b: . 'b'\l"] + 4 -> 5 [style=solid label="'b'"] + 4 -> 6 [style=dashed label="b"] + 5 [label="State 5\n 3 b: 'b' .\l"] + 5 -> "5R3e" [style = solid] + "5R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 6 [label="State 6\n 1 exp: a '?' b .\l"] + 6 -> "6R1e" [style = solid] + "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] +]]) + +## ------------------------ ## +## Graph with unsolved S/R. ## +## ------------------------ ## + +AT_TEST([Graph with unsolved S/R], +[[%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . ['b']\l 9 empty_c: . ['c']\l"] + 0 -> "0R7d" [label = "['a']" style = solid] + "0R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"] + 0 -> "0R8d" [label = "['b']" style = solid] + "0R8d" [style = filled, shape = diamond, fillcolor = 5, label = "R8"] + 0 -> "0R9d" [label = "['c']" style = solid] + "0R9d" [style = filled, shape = diamond, fillcolor = 5, label = "R9"] + 0 -> 1 [style=solid label="'a'"] + 0 -> 2 [style=solid label="'b'"] + 0 -> 3 [style=solid label="'c'"] + 0 -> 4 [style=dashed label="start"] + 0 -> 5 [style=dashed label="empty_a"] + 0 -> 6 [style=dashed label="empty_b"] + 0 -> 7 [style=dashed label="empty_c"] + 1 [label="State 1\n 1 start: 'a' .\l"] + 1 -> "1R1e" [style = solid] + "1R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 2 [label="State 2\n 3 start: 'b' .\l"] + 2 -> "2R3e" [style = solid] + "2R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 3 [label="State 3\n 5 start: 'c' .\l"] + 3 -> "3R5e" [style = solid] + "3R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 4 [label="State 4\n 0 $accept: start . $end\l"] + 4 -> 8 [style=solid label="$end"] + 5 [label="State 5\n 2 start: empty_a . 'a'\l"] + 5 -> 9 [style=solid label="'a'"] + 6 [label="State 6\n 4 start: empty_b . 'b'\l"] + 6 -> 10 [style=solid label="'b'"] + 7 [label="State 7\n 6 start: empty_c . 'c'\l"] + 7 -> 11 [style=solid label="'c'"] + 8 [label="State 8\n 0 $accept: start $end .\l"] + 8 -> "8R0e" [style = solid] + "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 9 [label="State 9\n 2 start: empty_a 'a' .\l"] + 9 -> "9R2e" [style = solid] + "9R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 10 [label="State 10\n 4 start: empty_b 'b' .\l"] + 10 -> "10R4e" [style = solid] + "10R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 11 [label="State 11\n 6 start: empty_c 'c' .\l"] + 11 -> "11R6e" [style = solid] + "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ---------------------- ## +## Graph with solved S/R. ## +## ---------------------- ## + +AT_TEST([Graph with solved S/R], +[[%left 'a' +%right 'b' +%right 'c' +%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . []\l 9 empty_c: . []\l"] + 0 -> "0R7e" [style = solid] + "0R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 0 -> 1 [style=solid label="'b'"] + 0 -> 2 [style=solid label="'c'"] + 0 -> 3 [style=dashed label="start"] + 0 -> 4 [style=dashed label="empty_a"] + 0 -> 5 [style=dashed label="empty_b"] + 0 -> 6 [style=dashed label="empty_c"] + 1 [label="State 1\n 3 start: 'b' .\l"] + 1 -> "1R3e" [style = solid] + "1R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 2 [label="State 2\n 5 start: 'c' .\l"] + 2 -> "2R5e" [style = solid] + "2R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 3 [label="State 3\n 0 $accept: start . $end\l"] + 3 -> 7 [style=solid label="$end"] + 4 [label="State 4\n 2 start: empty_a . 'a'\l"] + 4 -> 8 [style=solid label="'a'"] + 5 [label="State 5\n 4 start: empty_b . 'b'\l"] + 5 -> 9 [style=solid label="'b'"] + 6 [label="State 6\n 6 start: empty_c . 'c'\l"] + 6 -> 10 [style=solid label="'c'"] + 7 [label="State 7\n 0 $accept: start $end .\l"] + 7 -> "7R0e" [style = solid] + "7R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 8 [label="State 8\n 2 start: empty_a 'a' .\l"] + 8 -> "8R2e" [style = solid] + "8R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 9 [label="State 9\n 4 start: empty_b 'b' .\l"] + 9 -> "9R4e" [style = solid] + "9R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 10 [label="State 10\n 6 start: empty_c 'c' .\l"] + 10 -> "10R6e" [style = solid] + "10R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ---------------- ## +## Graph with R/R. ## +## ---------------- ## + +AT_TEST([Graph with R/R], +[[%% +exp: a | b; +a: ; +b: ; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . a\l 2 | . b\l 3 a: . [$end]\l 4 b: . [$end]\l"] + 0 -> "0R3e" [style = solid] + "0R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 0 -> "0R4d" [label = "[$end]" style = solid] + "0R4d" [style = filled, shape = diamond, fillcolor = 5, label = "R4"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 4 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a .\l"] + 2 -> "2R1e" [style = solid] + "2R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 3 [label="State 3\n 2 exp: b .\l"] + 3 -> "3R2e" [style = solid] + "3R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 4 [label="State 4\n 0 $accept: exp $end .\l"] + 4 -> "4R0e" [style = solid] + "4R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] +]]) + +## ---------------------------------------- ## +## Graph with reductions with multiple LAT. ## +## ---------------------------------------- ## + +AT_TEST([Graph with reductions with multiple LAT], +[[%% +exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';'; +a: ; +b: ; +c: ; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . a ';'\l 2 | . a ';'\l 3 | . a '.'\l 4 | . b '?'\l 5 | . b '!'\l 6 | . c '?'\l 7 | . c ';'\l 8 a: . [';', '.']\l 9 b: . ['?', '!']\l 10 c: . [';', '?']\l"] + 0 -> "0R8e" [style = solid] + "0R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"] + 0 -> "0R9e" [label = "['?', '!']" style = solid] + "0R9e" [style = filled, shape = diamond, fillcolor = 3, label = "R9"] + 0 -> "0R10d" [label = "[';', '?']" style = solid] + "0R10d" [style = filled, shape = diamond, fillcolor = 5, label = "R10"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 0 -> 4 [style=dashed label="c"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 5 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a . ';'\l 2 | a . ';'\l 3 | a . '.'\l"] + 2 -> 6 [style=solid label="';'"] + 2 -> 7 [style=solid label="'.'"] + 3 [label="State 3\n 4 exp: b . '?'\l 5 | b . '!'\l"] + 3 -> 8 [style=solid label="'?'"] + 3 -> 9 [style=solid label="'!'"] + 4 [label="State 4\n 6 exp: c . '?'\l 7 | c . ';'\l"] + 4 -> 10 [style=solid label="';'"] + 4 -> 11 [style=solid label="'?'"] + 5 [label="State 5\n 0 $accept: exp $end .\l"] + 5 -> "5R0e" [style = solid] + "5R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 6 [label="State 6\n 1 exp: a ';' . [$end]\l 2 | a ';' . [$end]\l"] + 6 -> "6R1e" [style = solid] + "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 6 -> "6R2d" [label = "[$end]" style = solid] + "6R2d" [style = filled, shape = diamond, fillcolor = 5, label = "R2"] + 7 [label="State 7\n 3 exp: a '.' .\l"] + 7 -> "7R3e" [style = solid] + "7R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 8 [label="State 8\n 4 exp: b '?' .\l"] + 8 -> "8R4e" [style = solid] + "8R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 9 [label="State 9\n 5 exp: b '!' .\l"] + 9 -> "9R5e" [style = solid] + "9R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 10 [label="State 10\n 7 exp: c ';' .\l"] + 10 -> "10R7e" [style = solid] + "10R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 11 [label="State 11\n 6 exp: c '?' .\l"] + 11 -> "11R6e" [style = solid] + "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ------------------------------------------------------ ## +## Graph with a reduction rule both enabled and disabled. ## +## ------------------------------------------------------ ## + +AT_TEST([Graph with a reduction rule both enabled and disabled], +[[%% +exp: ifexp | opexp | imm; +ifexp: "if" exp "then" exp elseexp; +elseexp: "else" exp | ; +opexp: exp '+' exp; +imm: '0'; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 0 -> 1 [style=solid label="\"if\""] + 0 -> 2 [style=solid label="'0'"] + 0 -> 3 [style=dashed label="exp"] + 0 -> 4 [style=dashed label="ifexp"] + 0 -> 5 [style=dashed label="opexp"] + 0 -> 6 [style=dashed label="imm"] + 1 [label="State 1\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" . exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 1 -> 1 [style=solid label="\"if\""] + 1 -> 2 [style=solid label="'0'"] + 1 -> 7 [style=dashed label="exp"] + 1 -> 4 [style=dashed label="ifexp"] + 1 -> 5 [style=dashed label="opexp"] + 1 -> 6 [style=dashed label="imm"] + 2 [label="State 2\n 8 imm: '0' .\l"] + 2 -> "2R8e" [style = solid] + "2R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"] + 3 [label="State 3\n 0 $accept: exp . $end\l 7 opexp: exp . '+' exp\l"] + 3 -> 8 [style=solid label="$end"] + 3 -> 9 [style=solid label="'+'"] + 4 [label="State 4\n 1 exp: ifexp .\l"] + 4 -> "4R1e" [style = solid] + "4R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 5 [label="State 5\n 2 exp: opexp .\l"] + 5 -> "5R2e" [style = solid] + "5R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 6 [label="State 6\n 3 exp: imm .\l"] + 6 -> "6R3e" [style = solid] + "6R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 7 [label="State 7\n 4 ifexp: \"if\" exp . \"then\" exp elseexp\l 7 opexp: exp . '+' exp\l"] + 7 -> 10 [style=solid label="\"then\""] + 7 -> 9 [style=solid label="'+'"] + 8 [label="State 8\n 0 $accept: exp $end .\l"] + 8 -> "8R0e" [style = solid] + "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 9 [label="State 9\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 7 | exp '+' . exp\l 8 imm: . '0'\l"] + 9 -> 1 [style=solid label="\"if\""] + 9 -> 2 [style=solid label="'0'"] + 9 -> 11 [style=dashed label="exp"] + 9 -> 4 [style=dashed label="ifexp"] + 9 -> 5 [style=dashed label="opexp"] + 9 -> 6 [style=dashed label="imm"] + 10 [label="State 10\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" exp \"then\" . exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 10 -> 1 [style=solid label="\"if\""] + 10 -> 2 [style=solid label="'0'"] + 10 -> 12 [style=dashed label="exp"] + 10 -> 4 [style=dashed label="ifexp"] + 10 -> 5 [style=dashed label="opexp"] + 10 -> 6 [style=dashed label="imm"] + 11 [label="State 11\n 7 opexp: exp . '+' exp\l 7 | exp '+' exp . [$end, \"then\", \"else\", '+']\l"] + 11 -> "11R7e" [style = solid] + "11R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 11 -> "11R7d" [label = "['+']" style = solid] + "11R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"] + 11 -> 9 [style=solid label="'+'"] + 12 [label="State 12\n 4 ifexp: \"if\" exp \"then\" exp . elseexp\l 5 elseexp: . \"else\" exp\l 6 | . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 12 -> "12R6e" [style = solid] + "12R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] + 12 -> "12R6d" [label = "[\"else\", '+']" style = solid] + "12R6d" [style = filled, shape = diamond, fillcolor = 5, label = "R6"] + 12 -> 13 [style=solid label="\"else\""] + 12 -> 9 [style=solid label="'+'"] + 12 -> 14 [style=dashed label="elseexp"] + 13 [label="State 13\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 5 elseexp: \"else\" . exp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 13 -> 1 [style=solid label="\"if\""] + 13 -> 2 [style=solid label="'0'"] + 13 -> 15 [style=dashed label="exp"] + 13 -> 4 [style=dashed label="ifexp"] + 13 -> 5 [style=dashed label="opexp"] + 13 -> 6 [style=dashed label="imm"] + 14 [label="State 14\n 4 ifexp: \"if\" exp \"then\" exp elseexp .\l"] + 14 -> "14R4e" [style = solid] + "14R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 15 [label="State 15\n 5 elseexp: \"else\" exp . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 15 -> "15R5e" [style = solid] + "15R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 15 -> "15R5d" [label = "['+']" style = solid] + "15R5d" [style = filled, shape = diamond, fillcolor = 5, label = "R5"] + 15 -> 9 [style=solid label="'+'"] +]]) + +m4_popdef([AT_TEST]) diff --git a/tests/torture.at b/tests/torture.at index a5e244b6..5aa18900 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 (); |