From: Akim Demaille Date: Mon, 26 Nov 2012 08:05:28 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/branch-2.6' into maint X-Git-Tag: v2.6.90~33 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/c6bf97ccb45672a004ef376b9f3e578d2f558d5f?hp=fb4c8a7cb97844f6c66921a77e79311a19d12fc2 Merge remote-tracking branch 'origin/branch-2.6' into maint * origin/branch-2.6: yacc.c: always initialize yylloc doc: one of the fixes for an ambiguous grammar was ambiguous too doc: fix the dangling else with precedence directives doc: prefer "token" to TOKEN doc: formatting changes Conflicts: NEWS doc/bison.texi --- diff --git a/NEWS b/NEWS index 393b8924..3789e92d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,62 @@ GNU Bison NEWS * Noteworthy changes in release ?.? (????-??-??) [?] +** Changes in the format of error messages + + This used to be the format of many error reports: + + foo.y:5.10-24: result type clash on merge function 'merge': != + foo.y:4.13-27: previous declaration + + It is now: + + foo.y:5.10-25: result type clash on merge function 'merge': != + foo.y:4.13-27: previous declaration + +** Exception safety (lalr1.cc) + + The parse function now catches exceptions, uses the %destructors to + release memory (the lookahead symbol and the symbols pushed on the stack) + before re-throwing the exception. + + This feature is somewhat experimental. User feedback would be + appreciated. + +** New %define variable: api.location.type (glr.cc, lalr1.cc, lalr1.java) + + The %define variable api.location.type defines the name of the type to use + for locations. When defined, Bison no longer generates the position.hh + and location.hh files, nor does the parser will include them: the user is + then responsible to define her type. + + This can be used in programs with several parsers to factor their location + and position files: let one of them generate them, and the others just use + them. + + This feature was actually introduced, but not documented, in Bison 2.5, + under the name "location_type" (which is maintained for backward + compatibility). + + For consistency, lalr1.java's %define variables location_type and + position_type are deprecated in favor of api.location.type and + api.position.type. + +** Graph improvements in DOT and XSLT + + The graphical presentation of the states is more readable: their shape is + now rectangular, the state number is clearly displayed, and the items are + numbered and left-justified. + + The reductions are now explicitly represented as transitions to other + diamond shaped nodes. + + These changes are present in both --graph output and xml2dot.xsl XSLT + processing, with minor (documented) differences. + + Two nodes were added to the documentation: Xml and Graphviz. + +* Noteworthy changes in release ?.? (????-??-??) [?] + ** Bug fixes Warnings about uninitialized yylloc in yyparse have been fixed. @@ -96,7 +152,7 @@ GNU Bison NEWS * Noteworthy changes in release 2.6.1 (2012-07-30) [stable] - Bison no longer executes user-specified M4 code when processing a grammar. + Bison no longer executes user-specified M4 code when processing a grammar. ** Future Changes @@ -1935,7 +1991,8 @@ along with this program. If not, see . LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf - LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp calc yyo fval + LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp calc yyo fval Wmaybe + LocalWords: yyvsp pragmas noreturn java's Local Variables: mode: outline diff --git a/README-hacking b/README-hacking index 26391e98..11b9f82a 100644 --- a/README-hacking +++ b/README-hacking @@ -43,16 +43,17 @@ These requirements do not apply when building from a distribution tarball. ** Requirements -We've opted to keep only the highest-level sources in the repository. -This eases our maintenance burden, (fewer merges etc.), but imposes more +We've opted to keep only the highest-level sources in the repository. This +eases our maintenance burden, (fewer merges etc.), but imposes more requirements on anyone wishing to build from the just-checked-out sources. For example, you have to use the latest stable versions of the maintainer tools we depend upon, including: -- Automake - Autoconf +- Automake - Flex - Gettext +- Graphviz - Gzip - Perl - Rsync @@ -61,16 +62,16 @@ tools we depend upon, including: Valgrind is also highly recommended, if it supports your architecture. -Bison is written using Bison grammars, so there are bootstrapping -issues. The bootstrap script attempts to discover when the C code -generated from the grammars is out of date, and to bootstrap with an -out-of-date version of the C code, but the process is not foolproof. -Also, you may run into similar problems yourself if you modify Bison. +Bison is written using Bison grammars, so there are bootstrapping issues. +The bootstrap script attempts to discover when the C code generated from the +grammars is out of date, and to bootstrap with an out-of-date version of the +C code, but the process is not foolproof. Also, you may run into similar +problems yourself if you modify Bison. -Only building the initial full source tree will be a bit painful. -Later, after synchronizing from the repository a plain 'make' should -be sufficient. Note, however, that when gnulib is updated, running -'./bootstrap' again might be needed. +Only building the initial full source tree will be a bit painful. Later, +after synchronizing from the repository a plain 'make' should be sufficient. +Note, however, that when gnulib is updated, running './bootstrap' again +might be needed. ** First checkout diff --git a/THANKS b/THANKS index e87568d5..8ae024fb 100644 --- a/THANKS +++ b/THANKS @@ -83,6 +83,7 @@ Nicolas Tisserand nicolas.tisserand@epita.fr Noah Friedman friedman@gnu.org Odd Arild Olsen oao@fibula.no Oleg Smolsky oleg.smolsky@pacific-simulators.co.nz +Oleksii Taran oleksii.taran@gmail.com Paolo Bonzini bonzini@gnu.org Pascal Bart pascal.bart@epita.fr Paul Eggert eggert@cs.ucla.edu @@ -132,6 +133,7 @@ thank them! Please, help us keeping this list up to date. Local Variables: mode: text +coding: utf-8 End: ----- diff --git a/TODO b/TODO index 4f628a20..978b5c6f 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,17 @@ * Short term +** Graphviz display code thoughts +The code for the --graph option is over two files: print_graph, and +graphviz. I believe this is because Bison used to also produce VCG graphs, +but since this is no longer true, maybe we could consider these files for +fusion. + +Little effort factoring seems to have been given to factoring in these files, +and their print-xml and print counterpart. We would very much like to re-use +the pretty format of states from .output in the .dot + +Also, the underscore in print_graph.[ch] isn't very fitting considering +the dashes in the other filenames. + ** Variable names. What should we name `variant' and `lex_symbol'? diff --git a/cfg.mk b/cfg.mk index 3a70379c..3f244aab 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, @@ -60,6 +61,18 @@ update-copyright: update-b4-copyright update-package-copyright-year update-copyright-env = \ UPDATE_COPYRIGHT_FORCE=1 UPDATE_COPYRIGHT_USE_INTERVALS=1 +# At least for Mac OS X's grep, the order between . and [ in "[^.[]" +# matters: +# $ LC_ALL=fr_FR grep -nE '[^[.]' /dev/null +# $ LC_ALL=C grep -nE '[^[.]' /dev/null +# grep: invalid collating element or class +# $ LC_ALL=fr_FR grep -nE '[^.[]' /dev/null +# $ LC_ALL=C grep -nE '[^.[]' /dev/null +sc_at_parser_check: + @prohibit='AT_PARSER_CHECK\(\[+[^.[]|AT_CHECK\(\[+\./' \ + halt='use AT_PARSER_CHECK for and only for generated parsers' \ + $(_sc_search_regexp) + exclude = \ $(foreach a,$(1),$(eval $(subst $$,$$$$,exclude_file_name_regexp--sc_$(a)))) $(call exclude, \ @@ -75,5 +88,5 @@ $(call exclude, \ require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$ \ space_tab=^tests/(input|c\+\+)\.at$$ \ trailing_blank=^src/parse-gram.[ch]$$ \ - unmarked_diagnostics=^(djgpp/|doc/bison.texi$$) \ + unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$) \ ) diff --git a/configure.ac b/configure.ac index 86783d52..83e20acb 100644 --- a/configure.ac +++ b/configure.ac @@ -132,6 +132,7 @@ AC_SUBST([YACC_SCRIPT]) AC_SUBST([YACC_LIBRARY]) # Checks for programs. +AM_MISSING_PROG([DOT], [dot]) AC_PROG_LEX $LEX_IS_FLEX || AC_MSG_ERROR([Flex is required]) AC_PROG_YACC diff --git a/data/c++.m4 b/data/c++.m4 index 45c4ddaf..8b98b8c1 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -29,7 +29,7 @@ b4_percent_define_default([[parser_class_name]], [[parser]]) # Don't do that so that we remember whether we're using a user # request, or the default value. # -# b4_percent_define_default([[location_type]], [[location]]) +# b4_percent_define_default([[api.location.type]], [[location]]) b4_percent_define_default([[filename_type]], [[std::string]]) b4_percent_define_default([[namespace]], m4_defn([b4_prefix])) diff --git a/data/glr.cc b/data/glr.cc index 104bf785..0e53d619 100644 --- a/data/glr.cc +++ b/data/glr.cc @@ -54,7 +54,7 @@ b4_defines_if([], [b4_fatal([b4_skeleton[: using %%defines is mandatory]])]) m4_include(b4_pkgdatadir/[c++.m4]) -b4_percent_define_ifdef([[location_type]], [], +b4_percent_define_ifdef([[api.location.type]], [], [m4_include(b4_pkgdatadir/[location.cc])]) m4_define([b4_parser_class_name], @@ -90,7 +90,7 @@ m4_define([b4_yy_symbol_print_generate], ]])[ # Hijack the initial action to initialize the locations. -]b4_locations_if([b4_percent_define_ifdef([[location_type]], [], +]b4_locations_if([b4_percent_define_ifdef([[api.location.type]], [], [m4_define([b4_initial_action], [yylloc.initialize ();]m4_ifdef([b4_initial_action], [ m4_defn([b4_initial_action])]))])])[ @@ -243,7 +243,7 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++], # include # include -]b4_percent_define_ifdef([[location_type]], [], +]b4_percent_define_ifdef([[api.location.type]], [], [[# include "location.hh"]])[ ]b4_YYDEBUG_define[ @@ -267,7 +267,7 @@ b4_user_stype typedef ]b4_api_PREFIX[STYPE semantic_type; # endif /// Symbol locations. - typedef ]b4_percent_define_get([[location_type]], + typedef ]b4_percent_define_get([[api.location.type]], [[location]])[ location_type; /// Tokens. struct token diff --git a/data/java.m4 b/data/java.m4 index 18ea30b5..627028b3 100644 --- a/data/java.m4 +++ b/data/java.m4 @@ -155,25 +155,25 @@ m4_define([b4_case], [ case $1: ## ---------------- ## m4_define([b4_yystype], [b4_percent_define_get([[stype]])]) -b4_percent_define_default([[stype]], [[Object]])]) +b4_percent_define_default([[stype]], [[Object]]) # %name-prefix m4_define_default([b4_prefix], [[YY]]) -b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])]) +b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser]) m4_define([b4_parser_class_name], [b4_percent_define_get([[parser_class_name]])]) -b4_percent_define_default([[lex_throws]], [[java.io.IOException]])]) +b4_percent_define_default([[lex_throws]], [[java.io.IOException]]) m4_define([b4_lex_throws], [b4_percent_define_get([[lex_throws]])]) -b4_percent_define_default([[throws]], [])]) +b4_percent_define_default([[throws]], []) m4_define([b4_throws], [b4_percent_define_get([[throws]])]) -b4_percent_define_default([[location_type]], [Location])]) -m4_define([b4_location_type], [b4_percent_define_get([[location_type]])]) +b4_percent_define_default([[api.location.type]], [Location]) +m4_define([b4_location_type], [b4_percent_define_get([[api.location.type]])]) -b4_percent_define_default([[position_type]], [Position])]) -m4_define([b4_position_type], [b4_percent_define_get([[position_type]])]) +b4_percent_define_default([[api.position.type]], [Position]) +m4_define([b4_position_type], [b4_percent_define_get([[api.position.type]])]) ## ----------------- ## @@ -219,9 +219,9 @@ m4_define([b4_rhs_location], # it to be single quoted. Same for b4_parse_param. # TODO: should be in bison.m4 -m4_define_default([b4_lex_param], [[]])) -m4_define([b4_lex_param], b4_lex_param)) -m4_define([b4_parse_param], b4_parse_param)) +m4_define_default([b4_lex_param], [[]]) +m4_define([b4_lex_param], b4_lex_param) +m4_define([b4_parse_param], b4_parse_param) # b4_lex_param_decl # ------------------- diff --git a/data/lalr1.cc b/data/lalr1.cc index 2fe8d4cb..e45b2e1f 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -24,7 +24,7 @@ m4_define([b4_parser_class_name], b4_defines_if([], [b4_fatal([b4_skeleton[: using %%defines is mandatory]])]) -b4_percent_define_ifdef([[location_type]], [], +b4_percent_define_ifdef([[api.location.type]], [], [# Backward compatibility. m4_define([b4_location_constructors]) m4_include(b4_pkgdatadir/[location.cc])]) @@ -52,7 +52,7 @@ b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++], #include #include #include "stack.hh" -]b4_percent_define_ifdef([[location_type]], [], +]b4_percent_define_ifdef([[api.location.type]], [], [[#include "location.hh"]])[ ]b4_YYDEBUG_define[ @@ -77,7 +77,7 @@ b4_user_stype typedef ]b4_api_PREFIX[STYPE semantic_type; #endif /// Symbol locations. - typedef ]b4_percent_define_get([[location_type]], + typedef ]b4_percent_define_get([[api.location.type]], [[location]])[ location_type; /// Tokens. struct token @@ -227,6 +227,7 @@ b4_user_stype /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. + /// If null, do not display the symbol, just free it. /// \param yytype The symbol type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. @@ -335,9 +336,9 @@ do { \ #else /* !]b4_api_PREFIX[DEBUG */ # define YYCDEBUG if (false) std::cerr -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_REDUCE_PRINT(Rule) -# define YY_STACK_PRINT() +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) YYUSE(Type) +# define YY_REDUCE_PRINT(Rule) static_cast(0) +# define YY_STACK_PRINT() static_cast(0) #endif /* !]b4_api_PREFIX[DEBUG */ @@ -446,7 +447,8 @@ do { \ YYUSE (yymsg); YYUSE (yyvaluep); - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + if (yymsg) + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { @@ -534,6 +536,10 @@ do { \ int yyresult; + // FIXME: This shoud be completely indented. It is not yet to + // avoid gratuitous conflicts when merging into the master branch. + try + { YYCDEBUG << "Starting parse" << std::endl; ]m4_ifdef([b4_initial_action], [ @@ -574,9 +580,9 @@ b4_dollar_popdef])[]dnl /* Read a lookahead token. */ if (yychar == yyempty_) { - YYCDEBUG << "Reading a token: "; - yychar = ]b4_c_function_call([yylex], [int], - [b4_api_PREFIX[STYPE*], [&yylval]][]dnl + YYCDEBUG << "Reading a token: "; + yychar = ]b4_c_function_call([yylex], [int], + [b4_api_PREFIX[STYPE*], [&yylval]][]dnl b4_locations_if([, [[location*], [&yylloc]]])dnl m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; } @@ -651,17 +657,21 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; else yyval = yysemantic_stack_[0]; + // Compute the default @@$. { slice slice (yylocation_stack_, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen); } + + // Perform the reduction. YY_REDUCE_PRINT (yyn); switch (yyn) { - ]b4_user_actions[ - default: - break; + ]b4_user_actions[ + default: + break; } + /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. @@ -712,20 +722,19 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; yyerror_range[1] = yylloc; if (yyerrstatus_ == 3) { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= yyeof_) - { - /* Return failure if at end of input. */ - if (yychar == yyeof_) - YYABORT; - } - else - { - yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); - yychar = yyempty_; - } + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + if (yychar <= yyeof_) + { + /* Return failure if at end of input. */ + if (yychar == yyeof_) + YYABORT; + } + else + { + yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); + yychar = yyempty_; + } } /* Else will try to reuse lookahead token after shifting the error @@ -774,7 +783,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; /* Pop the current state because it cannot handle the error token. */ if (yystate_stack_.height () == 1) - YYABORT; + YYABORT; yyerror_range[1] = yylocation_stack_[0]; yydestruct_ ("Error: popping", @@ -822,16 +831,42 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ yypop_ (yylen); - while (yystate_stack_.height () != 1) + while (1 < yystate_stack_.height ()) { - yydestruct_ ("Cleanup: popping", - yystos_[yystate_stack_[0]], - &yysemantic_stack_[0], - &yylocation_stack_[0]); - yypop_ (); + yydestruct_ ("Cleanup: popping", + yystos_[yystate_stack_[0]], + &yysemantic_stack_[0], + &yylocation_stack_[0]); + yypop_ (); } return yyresult; + } + catch (...) + { + YYCDEBUG << "Exception caught: cleaning lookahead and stack" + << std::endl; + // Do not try to display the values of the reclaimed symbols, + // as their printer might throw an exception. + if (yychar != yyempty_) + { + /* Make sure we have latest lookahead translation. See + comments at user semantic actions for why this is + necessary. */ + yytoken = yytranslate_ (yychar); + yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc); + } + + while (1 < yystate_stack_.height ()) + { + yydestruct_ (YY_NULL, + yystos_[yystate_stack_[0]], + &yysemantic_stack_[0], + &yylocation_stack_[0]); + yypop_ (); + } + throw; + } } // Generate an error message. diff --git a/data/xslt/bison.xsl b/data/xslt/bison.xsl index 353c75a0..40575efd 100644 --- a/data/xslt/bison.xsl +++ b/data/xslt/bison.xsl @@ -90,4 +90,16 @@ + + 0 + + + + + + + + + + diff --git a/data/xslt/xml2dot.xsl b/data/xslt/xml2dot.xsl index 219faa2f..dceb8e1e 100644 --- a/data/xslt/xml2dot.xsl +++ b/data/xslt/xml2dot.xsl @@ -55,7 +55,11 @@ - " { + " { + node [fontname = courier, shape = box, colorscheme = paired6] + edge [fontname = courier] + + } @@ -64,11 +68,87 @@ - + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + label="[ + + + + + + , + + + ]", + + + + style=solid] + + + + + + + + + 3 + + + 5 + + + + + + @@ -76,17 +156,48 @@ + + + + + - - -> + + + + + + + + + + + + + + + + + + + + + + + : + + . @@ -106,7 +217,7 @@ - [ + [ ] @@ -118,6 +229,50 @@ + + + + + + + + -> " + + R + + + d + + " [ + + + + + + + + " + + R + + + d + + " [label=" + + + Acc", fillcolor=1 + + + R + + ", fillcolor= + + + + , shape=diamond, style=filled] + + @@ -149,10 +304,13 @@ [label=" + State + + \n - "] + \l"] @@ -193,7 +351,7 @@ - + @@ -219,4 +377,21 @@ + + + + + + + + + + + + + + + + + diff --git a/data/xslt/xml2text.xsl b/data/xslt/xml2text.xsl index d14f1be5..8b3f5ae4 100644 --- a/data/xslt/xml2text.xsl +++ b/data/xslt/xml2text.xsl @@ -230,7 +230,7 @@ - state + State @@ -522,18 +522,6 @@ - - 0 - - - - - - - - - - diff --git a/doc/Makefile.am b/doc/Makefile.am index f695e22d..9c9c24ca 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -96,6 +96,36 @@ PREPATH = $(top_builddir)/src nodist_man_MANS = yacc.1 +## ----------------------------- ## +## Graphviz examples generation. ## +## ----------------------------- ## + +CLEANDIRS += figs +FIGS_DOT = figs/example-reduce.dot figs/example-shift.dot +EXTRA_DIST += \ + $(FIGS_DOT) \ + $(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png) +SUFFIXES += .dot .eps .pdf .png + +bison.dvi: $(FIGS_DOT:.dot=.eps) +bison.html: $(FIGS_DOT:.dot=.png) +bison.pdf: $(FIGS_DOT:.dot=.pdf) + +.dot.eps: + $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` + $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp + $(AM_V_at) mv $@.tmp $@ + +.dot.pdf: + $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` + $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp + $(AM_V_at) mv $@.tmp $@ + +.dot.png: + $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` + $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp + $(AM_V_at) mv $@.tmp $@ + ## -------------- ## ## Doxygenation. ## ## -------------- ## diff --git a/doc/bison.texi b/doc/bison.texi index 8e257a60..f2d3dbc5 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -295,6 +295,8 @@ Handling Context Dependencies Debugging Your Parser * Understanding:: Understanding the structure of your parser. +* Graphviz:: Getting a visual representation of the parser. +* Xml:: Getting a markup representation of the parser. * Tracing:: Tracing the execution of your parser. Tracing Your Parser @@ -328,6 +330,7 @@ C++ Location Values * C++ position:: One point in the source file * C++ location:: Two points in the source file +* User Defined Location Type:: Required interface for locations A Complete C++ Example @@ -4702,6 +4705,10 @@ incoming terminals during the second phase of error recovery, the current lookahead and the entire stack (except the current right-hand side symbols) when the parser returns immediately, and @item +the current lookahead and the entire stack (including the current right-hand +side symbols) when the C++ parser (@file{lalr1.cc}) catches an exception in +@code{parse}, +@item the start symbol, when the parser succeeds. @end itemize @@ -5322,6 +5329,23 @@ Unaccepted @var{variable}s produce an error. Some of the accepted @var{variable}s are: @itemize @bullet +@c ================================================== api.location.type +@item @code{api.location.type} +@findex %define api.location.type + +@itemize @bullet +@item Language(s): C++, Java + +@item Purpose: Define the location type. +@xref{User Defined Location Type}. + +@item Accepted Values: String + +@item Default Value: none + +@item History: introduced in Bison 2.7 +@end itemize + @c ================================================== api.prefix @item @code{api.prefix} @findex %define api.prefix @@ -5329,7 +5353,7 @@ Some of the accepted @var{variable}s are: @itemize @bullet @item Language(s): All -@item Purpose: Rename exported symbols +@item Purpose: Rename exported symbols. @xref{Multiple Parsers, ,Multiple Parsers in the Same Program}. @item Accepted Values: String @@ -8165,6 +8189,8 @@ automaton, and how to enable and understand the parser run-time traces. @menu * Understanding:: Understanding the structure of your parser. +* Graphviz:: Getting a visual representation of the parser. +* Xml:: Getting a markup representation of the parser. * Tracing:: Tracing the execution of your parser. @end menu @@ -8581,6 +8607,165 @@ precedence of @samp{/} with respect to @samp{+}, @samp{-}, and @samp{*}, but also because the associativity of @samp{/} is not specified. +Note that Bison may also produce an HTML version of this output, via an XML +file and XSLT processing (@pxref{Xml}). + +@c ================================================= Graphical Representation + +@node Graphviz +@section Visualizing Your Parser +@cindex dot + +As another means to gain better understanding of the shift/reduce +automaton corresponding to the Bison parser, a DOT file can be generated. Note +that debugging a real grammar with this is tedious at best, and impractical +most of the times, because the generated files are huge (the generation of +a PDF or PNG file from it will take very long, and more often than not it will +fail due to memory exhaustion). This option was rather designed for beginners, +to help them understand LR parsers. + +This file is generated when the @option{--graph} option is specified +(@pxref{Invocation, , Invoking Bison}). Its name is made by removing +@samp{.tab.c} or @samp{.c} from the parser implementation file name, and +adding @samp{.dot} instead. If the grammar file is @file{foo.y}, the +Graphviz output file is called @file{foo.dot}. + +The following grammar file, @file{rr.y}, will be used in the sequel: + +@example +%% +@group +exp: a ";" | b "."; +a: "0"; +b: "0"; +@end group +@end example + +The graphical output is very similar to the textual one, and as such it is +easier understood by making direct comparisons between them. See +@ref{Debugging, , Debugging Your Parser} for a detailled analysis of the +textual report. + +@subheading Graphical Representation of States + +The items (pointed rules) for each state are grouped together in graph nodes. +Their numbering is the same as in the verbose file. See the following points, +about transitions, for examples + +When invoked with @option{--report=lookaheads}, the lookahead tokens, when +needed, are shown next to the relevant rule between square brackets as a +comma separated list. This is the case in the figure for the representation of +reductions, below. + +@sp 1 + +The transitions are represented as directed edges between the current and +the target states. + +@subheading Graphical Representation of Shifts + +Shifts are shown as solid arrows, labelled with the lookahead token for that +shift. The following describes a reduction in the @file{rr.output} file: + +@example +@group +state 3 + + 1 exp: a . ";" + + ";" shift, and go to state 6 +@end group +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-shift, 100pt} + +@subheading Graphical Representation of Reductions + +Reductions are shown as solid arrows, leading to a diamond-shaped node +bearing the number of the reduction rule. The arrow is labelled with the +appropriate comma separated lookahead tokens. If the reduction is the default +action for the given state, there is no such label. + +This is how reductions are represented in the verbose file @file{rr.output}: +@example +state 1 + + 3 a: "0" . [";"] + 4 b: "0" . ["."] + + "." reduce using rule 4 (b) + $default reduce using rule 3 (a) +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-reduce, 120pt} + +When unresolved conflicts are present, because in deterministic parsing +a single decision can be made, Bison can arbitrarily choose to disable a +reduction, see @ref{Shift/Reduce, , Shift/Reduce Conflicts}. Discarded actions +are distinguished by a red filling color on these nodes, just like how they are +reported between square brackets in the verbose file. + +The reduction corresponding to the rule number 0 is the acceptation state. It +is shown as a blue diamond, labelled "Acc". + +@subheading Graphical representation of go tos + +The @samp{go to} jump transitions are represented as dotted lines bearing +the name of the rule being jumped to. + +Note that a DOT file may also be produced via an XML file and XSLT +processing (@pxref{Xml}). + +@c ================================================= XML + +@node Xml +@section Visualizing your parser in multiple formats +@cindex xml + +Bison supports two major report formats: textual output +(@pxref{Understanding}) when invoked with option @option{--verbose}, and DOT +(@pxref{Graphviz}) when invoked with option @option{--graph}. However, +another alternative is to output an XML file that may then be, with +@command{xsltproc}, rendered as either a raw text format equivalent to the +verbose file, or as an HTML version of the same file, with clickable +transitions, or even as a DOT. The @file{.output} and DOT files obtained via +XSLT have no difference whatsoever with those obtained by invoking +@command{bison} with options @option{--verbose} or @option{--graph}. + +The textual file is generated when the options @option{-x} or +@option{--xml[=FILE]} are specified, see @ref{Invocation,,Invoking Bison}. +If not specified, its name is made by removing @samp{.tab.c} or @samp{.c} +from the parser implementation file name, and adding @samp{.xml} instead. +For instance, if the grammar file is @file{foo.y}, the default XML output +file is @file{foo.xml}. + +Bison ships with a @file{data/xslt} directory, containing XSL Transformation +files to apply to the XML file. Their names are non-ambiguous: + +@table @file +@item xml2dot.xsl +Used to output a copy of the DOT visualization of the automaton. +@item xml2text.xsl +Used to output a copy of the .output file. +@item xml2xhtml.xsl +Used to output an xhtml enhancement of the .output file. +@end table + +Sample usage (requires @code{xsltproc}): +@example +$ bison -x input.y +@group +$ bison --print-datadir +/usr/local/share/bison +@end group +$ xsltproc /usr/local/share/bison/xslt/xml2xhtml.xsl input.xml > input.html +@end example + +@c ================================================= Tracing @node Tracing @section Tracing Your Parser @@ -9300,8 +9485,9 @@ generated in the following files: @table @file @item position.hh @itemx location.hh -The definition of the classes @code{position} and @code{location}, -used for location tracking. @xref{C++ Location Values}. +The definition of the classes @code{position} and @code{location}, used for +location tracking. These files are not generated if the @code{%define} +variable @code{api.location.type} is defined. @xref{C++ Location Values}. @item stack.hh An auxiliary class @code{stack} used by the parser. @@ -9357,18 +9543,22 @@ Symbols}. @c - %define filename_type "const symbol::Symbol" When the directive @code{%locations} is used, the C++ parser supports -location tracking, see @ref{Tracking Locations}. Two auxiliary classes -define a @code{position}, a single point in a file, and a @code{location}, a -range composed of a pair of @code{position}s (possibly spanning several -files). +location tracking, see @ref{Tracking Locations}. + +By default, two auxiliary classes define a @code{position}, a single point +in a file, and a @code{location}, a range composed of a pair of +@code{position}s (possibly spanning several files). But if the +@code{%define} variable @code{api.location.type} is defined, then these +classes will not be generated, and the user defined type will be used. @tindex uint In this section @code{uint} is an abbreviation for @code{unsigned int}: in genuine code only the latter is used. @menu -* C++ position:: One point in the source file -* C++ location:: Two points in the source file +* C++ position:: One point in the source file +* C++ location:: Two points in the source file +* User Defined Location Type:: Required interface for locations @end menu @node C++ position @@ -9472,6 +9662,63 @@ Report @var{p} on @var{o}, taking care of special cases such as: no @code{filename} defined, or equal filename/line or column. @end deftypefun +@node User Defined Location Type +@subsubsection User Defined Location Type +@findex %define api.location.type + +Instead of using the built-in types you may use the @code{%define} variable +@code{api.location.type} to specify your own type: + +@example +%define api.location.type @var{LocationType} +@end example + +The requirements over your @var{LocationType} are: +@itemize +@item +it must be copyable; + +@item +in order to compute the (default) value of @code{@@$} in a reduction, the +parser basically runs +@example +@@$.begin = @@$1.begin; +@@$.end = @@$@var{N}.end; // The location of last right-hand side symbol. +@end example +@noindent +so there must be copyable @code{begin} and @code{end} members; + +@item +alternatively you may redefine the computation of the default location, in +which case these members are not required (@pxref{Location Default Action}); + +@item +if traces are enabled, then there must exist an @samp{std::ostream& + operator<< (std::ostream& o, const @var{LocationType}& s)} function. +@end itemize + +@sp 1 + +In programs with several C++ parsers, you may also use the @code{%define} +variable @code{api.location.type} to share a common set of built-in +definitions for @code{position} and @code{location}. For instance, one +parser @file{master/parser.yy} might use: + +@example +%defines +%locations +%define namespace "master::" +@end example + +@noindent +to generate the @file{master/position.hh} and @file{master/location.hh} +files, reused by other parsers as follows: + +@example +%define api.location.type "master::location" +%code requires @{ #include @} +@end example + @node C++ Parser Interface @subsection C++ Parser Interface @c - define parser_class_name @@ -9509,6 +9756,11 @@ Build a new parser object. There are no arguments by default, unless @deftypemethod {parser} {int} parse () Run the syntactic analysis, and return 0 on success, 1 otherwise. + +@cindex exceptions +The whole function is wrapped in a @code{try}/@code{catch} block, so that +when an exception is thrown, the @code{%destructor}s are called to release +the lookahead symbol, and the symbols pushed on the stack. @end deftypemethod @deftypemethod {parser} {std::ostream&} debug_stream () @@ -9622,8 +9874,8 @@ factor both as follows. // Tell Flex the lexer's prototype ... # define YY_DECL \ yy::calcxx_parser::token_type \ - yylex (yy::calcxx_parser::semantic_type *yylval, \ - yy::calcxx_parser::location_type *yylloc, \ + yylex (yy::calcxx_parser::semantic_type* yylval, \ + yy::calcxx_parser::location_type* yylloc, \ calcxx_driver& driver) // ... and declare it for the parser's sake. YY_DECL; @@ -10180,11 +10432,11 @@ class defines a @dfn{position}, a single point in a file; Bison itself defines a class representing a @dfn{location}, a range composed of a pair of positions (possibly spanning several files). The location class is an inner class of the parser; the name is @code{Location} by default, and may also be -renamed using @code{%define location_type "@var{class-name}"}. +renamed using @code{%define api.location.type "@var{class-name}"}. The location class treats the position as a completely opaque value. By default, the class name is @code{Position}, but this can be changed -with @code{%define position_type "@var{class-name}"}. This class must +with @code{%define api.position.type "@var{class-name}"}. This class must be supplied by the user. @@ -10319,7 +10571,7 @@ In both cases, the scanner has to implement the following methods. @deftypemethod {Lexer} {void} yyerror (Location @var{loc}, String @var{msg}) This method is defined by the user to emit an error message. The first parameter is omitted if location tracking is not active. Its type can be -changed using @code{%define location_type "@var{class-name}".} +changed using @code{%define api.location.type "@var{class-name}".} @end deftypemethod @deftypemethod {Lexer} {int} yylex () @@ -10337,7 +10589,7 @@ Return respectively the first position of the last token that @code{yylex} returned, and the first position beyond it. These methods are not needed unless location tracking is active. -The return type can be changed using @code{%define position_type +The return type can be changed using @code{%define api.position.type "@var{class-name}".} @end deftypemethod @@ -10582,10 +10834,11 @@ comma-separated list. Default is @code{java.io.IOException}. @xref{Java Scanner Interface}. @end deffn -@deffn {Directive} {%define location_type} "@var{class}" +@deffn {Directive} {%define api.location.type} "@var{class}" The name of the class used for locations (a range between two positions). This class is generated as an inner class of the parser class by @command{bison}. Default is @code{Location}. +Formerly named @code{location_type}. @xref{Java Location Values}. @end deffn @@ -10600,9 +10853,10 @@ The name of the parser class. Default is @code{YYParser} or @xref{Java Bison Interface}. @end deffn -@deffn {Directive} {%define position_type} "@var{class}" +@deffn {Directive} {%define api.position.type} "@var{class}" The name of the class used for positions. This class must be supplied by the user. Default is @code{Position}. +Formerly named @code{position_type}. @xref{Java Location Values}. @end deffn @@ -11886,7 +12140,7 @@ London, Department of Computer Science, TR-00-12 (December 2000). @c LocalWords: getLVal defvar deftypefn deftypefnx gotos msgfmt Corbett LALR's @c LocalWords: subdirectory Solaris nonassociativity perror schemas Malloy ints @c LocalWords: Scannerless ispell american ChangeLog smallexample CSTYPE CLTYPE -@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate +@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate LocationType @c LocalWords: parsers parser's @c LocalWords: associativity subclasses precedences unresolvable runnable @c LocalWords: allocators subunit initializations unreferenced untyped diff --git a/doc/figs/example-reduce.dot b/doc/figs/example-reduce.dot new file mode 100644 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/po/POTFILES.in b/po/POTFILES.in index 0908f506..ee34879a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/main.c src/muscle-tab.c src/parse-gram.y src/print.c +src/print_graph.c src/reader.c src/reduce.c src/scan-code.l diff --git a/src/complain.c b/src/complain.c index dee3c3bb..b063c6b6 100644 --- a/src/complain.c +++ b/src/complain.c @@ -124,7 +124,7 @@ warn_at_indent (location loc, unsigned *indent, return; set_warning_issued (); indent_ptr = indent; - ERROR_MESSAGE (&loc, _("warning"), message); + ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message); } void @@ -144,7 +144,7 @@ warn (const char *message, ...) void complain_at (location loc, const char *message, ...) { - ERROR_MESSAGE (&loc, NULL, message); + ERROR_MESSAGE (&loc, _("error"), message); complaint_issued = true; } @@ -153,14 +153,14 @@ complain_at_indent (location loc, unsigned *indent, const char *message, ...) { indent_ptr = indent; - ERROR_MESSAGE (&loc, NULL, message); + ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message); complaint_issued = true; } void complain (const char *message, ...) { - ERROR_MESSAGE (NULL, NULL, message); + ERROR_MESSAGE (NULL, _("error"), message); complaint_issued = true; } diff --git a/src/complain.h b/src/complain.h index b8935645..997d577b 100644 --- a/src/complain.h +++ b/src/complain.h @@ -25,6 +25,9 @@ extern "C" { # endif +/* Sub-messages indent. */ +#define SUB_INDENT (4) + /** Record that a warning is about to be issued, and treat it as an error if warnings_flag & warnings_error. This is exported only for the sake of Yacc-compatible conflict reports in conflicts.c. diff --git a/src/getargs.c b/src/getargs.c index 64905694..226e6de0 100644 --- a/src/getargs.c +++ b/src/getargs.c @@ -343,13 +343,14 @@ Warning categories include:\n\ `yacc' incompatibilities with POSIX Yacc\n\ `conflicts-sr' S/R conflicts (enabled by default)\n\ `conflicts-rr' R/R conflicts (enabled by default)\n\ + `deprecated' obsolete constructs\n\ `other' all other warnings (enabled by default)\n\ `all' all the warnings\n\ `no-CATEGORY' turn off warnings in CATEGORY\n\ `none' turn off all the warnings\n\ `error' treat warnings as errors\n\ -\n\ "), stdout); + putc ('\n', stdout); fputs (_("\ THINGS is a list of comma separated words that can include:\n\ diff --git a/src/graphviz.c b/src/graphviz.c index 46c22a8c..16ea8b9e 100644 --- a/src/graphviz.c +++ b/src/graphviz.c @@ -25,12 +25,14 @@ #include #include "files.h" +#include "gram.h" #include "graphviz.h" +#include "tables.h" /* Return an unambiguous printable representation for NAME, suitable for C strings. Use slot 2 since the user may use slots 0 and 1. */ -static char const * +static char * quote (char const *name) { return quotearg_n_style (2, c_quoting_style, name); @@ -51,17 +53,21 @@ start_graph (FILE *fout) "digraph %s\n" "{\n", quote (grammar_file)); + fprintf (fout, + " node [fontname = courier, shape = box, colorscheme = paired6]\n" + " edge [fontname = courier]\n" + "\n"); } void output_node (int id, char const *label, FILE *fout) { - fprintf (fout, " %d [label=%s]\n", id, quote (label)); + fprintf (fout, " %d [label=\"%s\"]\n", id, label); } void output_edge (int source, int destination, char const *label, - char const *style, FILE *fout) + char const *style, FILE *fout) { fprintf (fout, " %d -> %d [style=%s", source, destination, style); if (label) @@ -69,6 +75,142 @@ output_edge (int source, int destination, char const *label, fputs ("]\n", fout); } +char const * +escape (char const *name) +{ + char *q = quote (name); + q[strlen (q) - 1] = '\0'; + return q + 1; +} + +static void +no_reduce_bitset_init (state const *s, bitset *no_reduce_set) +{ + int n; + *no_reduce_set = bitset_create (ntokens, BITSET_FIXED); + bitset_zero (*no_reduce_set); + FOR_EACH_SHIFT (s->transitions, n) + bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n)); + for (n = 0; n < s->errs->num; ++n) + if (s->errs->symbols[n]) + bitset_set (*no_reduce_set, s->errs->symbols[n]->number); +} + +static void +conclude_red (struct obstack *out, int source, rule_number ruleno, + bool enabled, bool first, FILE *fout) +{ + /* If no lookahead tokens were valid transitions, this reduction is + actually hidden, so cancel everything. */ + if (first) + return (void) obstack_finish0 (out); + else + { + char const *ed = enabled ? "" : "d"; + char const *color = enabled ? ruleno ? "3" : "1" : "5"; + + /* First, build the edge's head. The name of reduction nodes is "nRm", + with n the source state and m the rule number. This is because we + don't want all the reductions bearing a same rule number to point to + the same state, since that is not the desired format. */ + fprintf (fout, " %1$d -> \"%1$dR%2$d%3$s\" [", + source, ruleno, ed); + + /* (The lookahead tokens have been added to the beginning of the + obstack, in the caller function.) */ + if (! obstack_empty_p (out)) + { + char *label = obstack_finish0 (out); + fprintf (fout, "label=\"[%s]\", ", label); + obstack_free (out, label); + } + + /* Then, the edge's tail. */ + fprintf (fout, "style=solid]\n"); + + /* Build the associated diamond representation of the target rule. */ + fprintf (fout, " \"%dR%d%s\" [label=\"", + source, ruleno, ed); + if (ruleno) + fprintf (fout, "R%d", ruleno); + else + fprintf (fout, "Acc"); + + fprintf (fout, "\", fillcolor=%s, shape=diamond, style=filled]\n", + color); + } +} + +static bool +print_token (struct obstack *out, bool first, char const *tok) +{ + char const *q = escape (tok); + + if (! first) + obstack_sgrow (out, ", "); + obstack_sgrow (out, q); + return false; +} + +void +output_red (state const *s, reductions const *reds, FILE *fout) +{ + bitset no_reduce_set; + int j; + int source = s->number; + + /* Two obstacks are needed: one for the enabled reductions, and one + for the disabled reductions, because in the end we want two + separate edges, even though in most cases only one will actually + be printed. */ + struct obstack dout; + struct obstack eout; + + no_reduce_bitset_init (s, &no_reduce_set); + obstack_init (&dout); + obstack_init (&eout); + + for (j = 0; j < reds->num; ++j) + { + bool defaulted = false; + bool firstd = true; + bool firste = true; + rule_number ruleno = reds->rules[j]->number; + rule *default_reduction = NULL; + + if (yydefact[s->number] != 0) + default_reduction = &rules[yydefact[s->number] - 1]; + + /* Build the lookahead tokens lists, one for enabled transitions and one + for disabled transistions. */ + if (default_reduction && default_reduction == reds->rules[j]) + defaulted = true; + if (reds->lookahead_tokens) + { + int i; + for (i = 0; i < ntokens; i++) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (bitset_test (no_reduce_set, i)) + firstd = print_token (&dout, firstd, symbols[i]->tag); + else + { + if (! defaulted) + firste = print_token (&eout, firste, symbols[i]->tag); + bitset_set (no_reduce_set, i); + } + } + } + + /* Do the actual output. */ + conclude_red (&dout, source, ruleno, false, firstd, fout); + conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout); + } + obstack_free (&dout, 0); + obstack_free (&eout, 0); + bitset_free (no_reduce_set); +} + void finish_graph (FILE *fout) { diff --git a/src/graphviz.h b/src/graphviz.h index 556fdda1..371b15c5 100644 --- a/src/graphviz.h +++ b/src/graphviz.h @@ -22,6 +22,8 @@ #ifndef GRAPHVIZ_H_ # define GRAPHVIZ_H_ +#include "state.h" + /// Begin a Dot graph. /// \param fout output stream. void start_graph (FILE *fout); @@ -40,10 +42,20 @@ void output_node (int id, char const *label, FILE *fout); /// \param style Dot style of the edge (e.g., "dotted" or "solid"). /// \param fout output stream. void output_edge (int source, int destination, char const *label, - char const *style, FILE *fout); + char const *style, FILE *fout); + +/// Output a reduction. +/// \param s current state +/// \param reds the set of reductions +/// \param fout output stream. +void output_red (state const *s, reductions const *reds, FILE *fout); /// End a Dot graph. /// \param fout output stream. void finish_graph (FILE *fout); +/// Escape a lookahead token. +/// \param name the token. +char const *escape (char const *name); + #endif /* ! GRAPHVIZ_H_ */ diff --git a/src/muscle-tab.c b/src/muscle-tab.c index bd1fd174..936af700 100644 --- a/src/muscle-tab.c +++ b/src/muscle-tab.c @@ -396,47 +396,61 @@ muscle_user_name_list_grow (char const *key, char const *user_name, muscle_grow (key, "]]", ""); } +/** If the \a variable name is obsolete, return the name to use, + * otherwise \a variable. */ +static +char const * +muscle_percent_variable_update (char const *variable) +{ + typedef struct + { + const char *obsolete; + const char *updated; + } conversion_type; + const conversion_type conversion[] = + { + { "api.push_pull", "api.push-pull", }, + { "location_type", "api.location.type", }, + { "lr.keep_unreachable_states", "lr.keep-unreachable-states", }, + }; + char const *res = variable; + int i; + for (i = 0; i < ARRAY_CARDINALITY (conversion); ++i) + if (STREQ (conversion[i].obsolete, variable)) + { + res = conversion[i].updated; + break; + } + return res; +} + void -muscle_percent_define_insert (char const *variable, location variable_loc, +muscle_percent_define_insert (char const *var, location variable_loc, char const *value, muscle_percent_define_how how) { - char *variable_tr = NULL; - char const *name; - char const *loc_name; - char const *syncline_name; - char const *how_name; - - /* Permit certain names with underscores for backward compatibility. */ - if (0 == strcmp (variable, "api.push_pull") - || 0 == strcmp (variable, "lr.keep_unreachable_states")) - { - variable_tr = strdup (variable); - tr (variable_tr, '_', '-'); - variable = variable_tr; - } - - name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); - loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); - syncline_name = + /* Backward compatibility. */ + char const *variable = muscle_percent_variable_update (var); + char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); + char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); + char const *syncline_name = UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); - how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")"); + char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")"); /* Command-line options are processed before the grammar file. */ if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE && muscle_find_const (name)) { + unsigned i = 0; muscle_percent_define_how how_old = atoi (muscle_find_const (how_name)); if (how_old == MUSCLE_PERCENT_DEFINE_F) - { - free (variable_tr); - return; - } - complain_at (variable_loc, _("%%define variable %s redefined"), - quote (variable)); - complain_at (muscle_percent_define_get_loc (variable), - _("previous definition")); + return; + complain_at_indent (variable_loc, &i, + _("%%define variable %s redefined"), quote (variable)); + i += SUB_INDENT; + complain_at_indent (muscle_percent_define_get_loc (variable), &i, + _("previous definition")); } MUSCLE_INSERT_STRING (name, value); @@ -447,8 +461,6 @@ muscle_percent_define_insert (char const *variable, location variable_loc, muscle_user_name_list_grow ("percent_define_user_variables", variable, variable_loc); MUSCLE_INSERT_INT (how_name, how); - - free (variable_tr); } char * @@ -591,12 +603,15 @@ muscle_percent_define_check_values (char const * const *values) } if (!*values) { + unsigned i = 0; location loc = muscle_percent_define_get_loc (*variablep); - complain_at(loc, - _("invalid value for %%define variable %s: %s"), - quote (*variablep), quote_n (1, value)); + complain_at_indent (loc, &i, + _("invalid value for %%define variable %s: %s"), + quote (*variablep), quote_n (1, value)); + i += SUB_INDENT; for (values = variablep + 1; *values; ++values) - complain_at (loc, _("accepted value: %s"), quote (*values)); + complain_at_indent (loc, &i, _("accepted value: %s"), + quote (*values)); } else { diff --git a/src/output.c b/src/output.c index 4a4d62d1..3852729b 100644 --- a/src/output.c +++ b/src/output.c @@ -41,8 +41,6 @@ #include "symtab.h" #include "tables.h" -# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) - static struct obstack format_obstack; diff --git a/src/parse-gram.c b/src/parse-gram.c index c2711ac3..5633b4e0 100644 --- a/src/parse-gram.c +++ b/src/parse-gram.c @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.6.4.37-63951. */ +/* A Bison parser, made by GNU Bison 2.6.5.63-3ada. */ /* Bison implementation for Yacc-like parsers in C @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.6.4.37-63951" +#define YYBISON_VERSION "2.6.5.63-3ada" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" diff --git a/src/parse-gram.h b/src/parse-gram.h index 7f37630f..c709098f 100644 --- a/src/parse-gram.h +++ b/src/parse-gram.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.6.4.37-63951. */ +/* A Bison parser, made by GNU Bison 2.6.5.63-3ada. */ /* Bison interface for Yacc-like parsers in C diff --git a/src/print.c b/src/print.c index cb227aa5..5fdb28b5 100644 --- a/src/print.c +++ b/src/print.c @@ -370,7 +370,7 @@ static void print_state (FILE *out, state *s) { fputs ("\n\n", out); - fprintf (out, _("state %d"), s->number); + fprintf (out, _("State %d"), s->number); fputc ('\n', out); print_core (out, s); print_actions (out, s); diff --git a/src/print_graph.c b/src/print_graph.c index f5695a7a..f4742b16 100644 --- a/src/print_graph.c +++ b/src/print_graph.c @@ -39,11 +39,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. */ @@ -54,7 +75,8 @@ print_core (struct obstack *oout, state *s) snritems = nitemset; } - obstack_printf (oout, "%d", s->number); + obstack_printf (oout, _("State %d"), s->number); + obstack_sgrow (oout, "\\n\\l"); for (i = 0; i < snritems; i++) { item_number *sp; @@ -64,43 +86,47 @@ print_core (struct obstack *oout, state *s) sp1 = sp = ritem + sitems[i]; while (*sp >= 0) - sp++; + sp++; r = item_number_as_rule_number (*sp); - obstack_printf (oout, "\n%s -> ", rules[r].lhs->tag); + obstack_printf (oout, "%3d ", r); + print_lhs (oout, previous_rule, &rules[r]); + previous_rule = &rules[r]; for (sp = rules[r].rhs; sp < sp1; sp++) - obstack_printf (oout, "%s ", symbols[*sp]->tag); + obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); - obstack_1grow (oout, '.'); + obstack_sgrow (oout, " ."); for (/* Nothing */; *sp >= 0; ++sp) - obstack_printf (oout, " %s", symbols[*sp]->tag); + obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); /* Experimental feature: display the lookahead tokens. */ if (report_flag & report_lookahead_tokens && item_number_is_rule_number (*sp1)) - { - /* Find the reduction we are handling. */ - reductions *reds = s->reductions; - int redno = state_reduction_find (s, &rules[r]); - - /* Print them if there are. */ - if (reds->lookahead_tokens && redno != -1) - { - bitset_iterator biter; - int k; - char const *sep = ""; - obstack_sgrow (oout, "["); - BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) - { - obstack_printf (oout, "%s%s", sep, symbols[k]->tag); - sep = ", "; - } - obstack_sgrow (oout, "]"); - } - } + { + /* Find the reduction we are handling. */ + reductions *reds = s->reductions; + int redno = state_reduction_find (s, &rules[r]); + + /* Print them if there are. */ + if (reds->lookahead_tokens && redno != -1) + { + bitset_iterator biter; + int k; + char const *sep = ""; + obstack_sgrow (oout, " ["); + BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) + { + obstack_sgrow (oout, sep); + obstack_sgrow (oout, escape (symbols[k]->tag)); + sep = ", "; + } + obstack_1grow (oout, ']'); + } + } + obstack_sgrow (oout, "\\l"); } } @@ -113,9 +139,8 @@ print_core (struct obstack *oout, state *s) static void print_actions (state const *s, FILE *fgraph) { - int i; - transitions const *trans = s->transitions; + int i; if (!trans->num && !s->reductions) return; @@ -139,6 +164,8 @@ print_actions (state const *s, FILE *fgraph) TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag, style, fgraph); } + /* Display reductions. */ + output_red (s, s->reductions, fgraph); } diff --git a/src/reader.c b/src/reader.c index 7dd0aaa4..86fde7b2 100644 --- a/src/reader.c +++ b/src/reader.c @@ -128,12 +128,16 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc) aver (merge_function != NULL && merger_find == merger); if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type)) { - complain_at (declaration_loc, - _("result type clash on merge function %s: <%s> != <%s>"), - quote (merge_function->name), type, merge_function->type); - complain_at (merge_function->type_declaration_location, - _("previous declaration")); - } + unsigned indent = 0; + complain_at_indent (declaration_loc, &indent, + _("result type clash on merge function %s: " + "<%s> != <%s>"), + quote (merge_function->name), type, + merge_function->type); + indent += SUB_INDENT; + complain_at_indent (merge_function->type_declaration_location, &indent, + _("previous declaration")); + } merge_function->type = uniqstr_new (type); merge_function->type_declaration_location = declaration_loc; } diff --git a/src/scan-gram.l b/src/scan-gram.l index ad061cc6..fd6458fa 100644 --- a/src/scan-gram.l +++ b/src/scan-gram.l @@ -103,9 +103,9 @@ static void unexpected_newline (boundary, char const *); /* Bracketed identifiers support. */ %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID -letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_] +letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_] +notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{] id {letter}({letter}|[-0-9])* -directive %{id} int [0-9]+ /* POSIX says that a tag must be both an id and a C union member, but @@ -148,7 +148,7 @@ splice (\\[ \f\t\v]*\n)* /* Comments and white space. */ "," warn_at (*loc, _("stray ',' treated as white space")); [ \f\n\t\v] | - "//".* ; + "//".* continue; "/*" { token_start = loc->start; context_state = YY_START; @@ -218,7 +218,7 @@ splice (\\[ \f\t\v]*\n)* "%verbose" return PERCENT_VERBOSE; "%yacc" return PERCENT_YACC; - {directive} { + "%"{id}|"%"{notletter}([[:graph:]])+ { complain_at (*loc, _("invalid directive: %s"), quote (yytext)); } @@ -290,8 +290,10 @@ splice (\\[ \f\t\v]*\n)* BEGIN SC_BRACKETED_ID; } - . { - complain_at (*loc, _("invalid character: %s"), quote_mem (yytext, yyleng)); + [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. { + complain_at (*loc, "%s: %s", + ngettext ("invalid character", "invalid characters", yyleng), + quote_mem (yytext, yyleng)); } <> { @@ -373,10 +375,14 @@ splice (\\[ \f\t\v]*\n)* else complain_at (*loc, _("an identifier expected")); } - . { - complain_at (*loc, _("invalid character in bracketed name: %s"), - quote_mem (yytext, yyleng)); + + [^\].A-Za-z0-9_/ \f\n\t\v]+|. { + complain_at (*loc, "%s: %s", + ngettext ("invalid character in bracketed name", + "invalid characters in bracketed name", yyleng), + quote_mem (yytext, yyleng)); } + <> { BEGIN bracketed_id_context_state; unexpected_eof (bracketed_id_start, "]"); @@ -403,7 +409,7 @@ splice (\\[ \f\t\v]*\n)* { "*/" BEGIN context_state; - .|\n ; + .|\n continue; <> unexpected_eof (token_start, "*/"); BEGIN context_state; } diff --git a/src/symtab.c b/src/symtab.c index 002f6e37..56cfe511 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -150,16 +150,20 @@ static void symbol_redeclaration (symbol *s, const char *what, location first, location second) { - complain_at (second, _("%s redeclaration for %s"), what, s->tag); - complain_at (first, _("previous declaration")); + unsigned i = 0; + complain_at_indent (second, &i, _("%s redeclaration for %s"), what, s->tag); + i += SUB_INDENT; + complain_at_indent (first, &i, _("previous declaration")); } static void semantic_type_redeclaration (semantic_type *s, const char *what, location first, location second) { - complain_at (second, _("%s redeclaration for <%s>"), what, s->tag); - complain_at (first, _("previous declaration")); + unsigned i = 0; + complain_at_indent (second, &i, _("%s redeclaration for <%s>"), what, s->tag); + i += SUB_INDENT; + complain_at_indent (first, &i, _("previous declaration")); } @@ -515,6 +519,7 @@ symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED) static void user_token_number_redeclaration (int num, symbol *first, symbol *second) { + unsigned i = 0; /* User token numbers are not assigned during the parsing, but in a second step, via a traversal of the symbol table sorted on tag. @@ -526,11 +531,13 @@ user_token_number_redeclaration (int num, symbol *first, symbol *second) first = second; second = tmp; } - complain_at (second->location, - _("user token number %d redeclaration for %s"), - num, second->tag); - complain_at (first->location, _("previous declaration for %s"), - first->tag); + complain_at_indent (second->location, &i, + _("user token number %d redeclaration for %s"), + num, second->tag); + i += SUB_INDENT; + complain_at_indent (first->location, &i, + _("previous declaration for %s"), + first->tag); } /*--------------------------------------------------. @@ -923,10 +930,12 @@ default_tagged_destructor_set (code_props const *destructor) { if (default_tagged_destructor.code) { - complain_at (destructor->location, - _("redeclaration for default tagged %%destructor")); - complain_at (default_tagged_destructor.location, - _("previous declaration")); + unsigned i = 0; + complain_at_indent (destructor->location, &i, + _("redeclaration for default tagged %%destructor")); + i += SUB_INDENT; + complain_at_indent (default_tagged_destructor.location, &i, + _("previous declaration")); } default_tagged_destructor = *destructor; } @@ -936,10 +945,12 @@ default_tagless_destructor_set (code_props const *destructor) { if (default_tagless_destructor.code) { - complain_at (destructor->location, - _("redeclaration for default tagless %%destructor")); - complain_at (default_tagless_destructor.location, - _("previous declaration")); + unsigned i = 0; + complain_at_indent (destructor->location, &i, + _("redeclaration for default tagless %%destructor")); + i += SUB_INDENT; + complain_at_indent (default_tagless_destructor.location, &i, + _("previous declaration")); } default_tagless_destructor = *destructor; } @@ -949,10 +960,12 @@ default_tagged_printer_set (code_props const *printer) { if (default_tagged_printer.code) { - complain_at (printer->location, - _("redeclaration for default tagged %%printer")); - complain_at (default_tagged_printer.location, - _("previous declaration")); + unsigned i = 0; + complain_at_indent (printer->location, &i, + _("redeclaration for default tagged %%printer")); + i += SUB_INDENT; + complain_at_indent (default_tagged_printer.location, &i, + _("previous declaration")); } default_tagged_printer = *printer; } @@ -962,10 +975,12 @@ default_tagless_printer_set (code_props const *printer) { if (default_tagless_printer.code) { - complain_at (printer->location, - _("redeclaration for default tagless %%printer")); - complain_at (default_tagless_printer.location, - _("previous declaration")); + unsigned i = 0; + complain_at_indent (printer->location, &i, + _("redeclaration for default tagless %%printer")); + i += SUB_INDENT; + complain_at_indent (default_tagless_printer.location, &i, + _("previous declaration")); } default_tagless_printer = *printer; } diff --git a/src/system.h b/src/system.h index bf7f59f9..3a82e7f3 100644 --- a/src/system.h +++ b/src/system.h @@ -41,6 +41,10 @@ # include # include +#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) +#define STREQ(L, R) (strcmp(L, R) == 0) +#define STRNEQ(L, R) (!STREQ(L, R)) + # ifndef UINTPTR_MAX /* This isn't perfect, but it's good enough for Bison, which needs only to hash pointers. */ @@ -198,7 +202,10 @@ typedef size_t uintptr_t; } while (0) +/* Append the ending 0, finish Obs, and return the string. */ +# define obstack_finish0(Obs) \ + (obstack_1grow (Obs, '\0'), (char *) obstack_finish (Obs)) /*-----------------------------------------. diff --git a/tests/c++.at b/tests/c++.at index c44a2a59..a5d83853 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -181,3 +181,237 @@ AT_CHECK_NAMESPACE([[foo[3]::bar::baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar,baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar::(baz]], [[-]]) AT_CLEANUP + + +## ------------------ ## +## Exception safety. ## +## ------------------ ## + +AT_SETUP([[Exception safety]]) + +AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"]) + +AT_DATA_GRAMMAR([[input.yy]], +[[%skeleton "lalr1.cc" +%defines // FIXME: Mandated in 2.6. +%debug +%error-verbose + +%code requires +{ + #include + #include // size_t and getenv. + #include + #include + + bool debug = false; + + /// A class that counts its number of instances. + struct Object + { + typedef std::list objects; + static objects instances; + char val; + + static bool + empty () + { + return instances.empty(); + } + + static void + log (Object const *o, const std::string& msg) + { + if (debug) + { + if (o) + std::cerr << o << "->"; + std::cerr << msg << " {"; + const char* sep = " "; + for (objects::const_iterator i = instances.begin(), + i_end = instances.end(); + i != i_end; + ++i) + { + std::cerr << sep << *i; + sep = ", "; + } + std::cerr << " }" << std::endl; + } + } + + Object (char v) + : val (v) + { + instances.push_back(this); + log (this, "Object::Object"); + } + + ~Object () + { + instances.remove(this); + log (this, "Object::~Object"); + } + }; +} + +%code +{ + #include + #include // strchr + #include + int yylex (yy::parser::semantic_type *); + Object::objects Object::instances; + static char const *input; +} + +%union +{ + Object *obj; +} + +%initial-action +{ + if (strchr (input, 'i')) + throw std::runtime_error ("initial-action"); +} + +%destructor { delete $$; } ; +%printer +{ + yyo << $$ << " '" << $$->val << '\''; + if ($$->val == 'p') + throw std::runtime_error ("printer"); +} ; + +%token 'a' 'E' 'e' 'p' 'R' 's' 'T' +%type list item + +%% + +start: list { delete $1; }; + +list: + item { $$ = $1; } +| item list { $$ = $1; delete $2; } // Right recursion to load the stack. +; + +item: + 'a' { $$ = $1; } +| 'e' { YYUSE ($$); YYUSE($1); error (location_type(), "syntax error"); } +// Not just 'E', otherwise we reduce when 'E' is the lookahead, and +// then the stack is emptied, defeating the point of the test. +| 'E' 'a' { YYUSE($1); $$ = $2; } +| 'R' { $$ = YY_NULL; delete $1; YYERROR; } +| 'p' { $$ = $1; } +| 's' { $$ = $1; throw std::runtime_error ("reduction"); } +| 'T' { $$ = YY_NULL; delete $1; YYABORT; } +| error { $$ = YY_NULL; yyerrok; } +; +%% + +int +yylex (yy::parser::semantic_type *lvalp) +{ + // 'a': no error. + // 'e': user action calls error. + // 'E': syntax error, with yyerror that throws. + // 'i': initial action throws. + // 'l': yylex throws. + // 'R': call YYERROR in the action + // 's': reduction throws. + // 'T': call YYABORT in the action + switch (int res = *input++) + { + case 'l': + throw std::runtime_error ("yylex"); + default: + lvalp->obj = new Object (res); + // Fall through. + case 0: + return res; + } +} + +/* A C++ error reporting function. */ +void +yy::parser::error (const location_type& l, const std::string& m) +{ + YYUSE (l); + throw std::runtime_error (m); +} + +int +main (int argc, const char *argv[]) +{ + switch (argc) + { + case 2: + input = argv[1]; + break; + case 3: + assert (!strcmp (argv[1], "--debug")); + debug = 1; + input = argv[2]; + break; + default: + abort (); + } + + yy::parser parser; + debug |= !!getenv ("YYDEBUG"); + parser.set_debug_level (debug); + int res = 2; + try + { + res = parser.parse (); + } + catch (const std::exception& e) + { + std::cerr << "exception caught: " << e.what () << std::endl; + } + catch (...) + { + std::cerr << "unknown exception caught" << std::endl; + } + Object::log (YY_NULL, "end"); + assert (Object::empty()); + return res; +} +]]) +AT_BISON_CHECK([[-o input.cc --report=all input.yy]]) +AT_COMPILE_CXX([[input]]) + +AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]], +[[exception caught: reduction +]]) + +AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]], +[[exception caught: yylex +]]) + +AT_PARSER_CHECK([[./input i]], [[2]], [[]], +[[exception caught: initial-action +]]) + +AT_PARSER_CHECK([[./input aaaap]]) + +AT_PARSER_CHECK([[./input --debug aaaap]], [[2]], [[]], [[stderr]]) +AT_CHECK([[grep '^exception caught: printer$' stderr]], [], [ignore]) + +AT_PARSER_CHECK([[./input aaaae]], [[2]], [[]], +[[exception caught: syntax error +]]) + +AT_PARSER_CHECK([[./input aaaaE]], [[2]], [[]], +[[exception caught: syntax error, unexpected $end, expecting 'a' +]]) + +AT_PARSER_CHECK([[./input aaaaT]], [[1]]) + +# There is error-recovery, so exit success. +AT_PARSER_CHECK([[./input aaaaR]], [[0]]) + +AT_BISON_OPTION_POPDEFS + +AT_CLEANUP diff --git a/tests/calc.at b/tests/calc.at index 062bb45b..4ab725b3 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -677,7 +677,7 @@ m4_define([AT_CHECK_CALC_LALR1_CC], [AT_CHECK_CALC([%language "C++" %defines %locations] $@)]) AT_CHECK_CALC_LALR1_CC([]) -AT_CHECK_CALC_LALR1_CC([%define location_type Span]) +AT_CHECK_CALC_LALR1_CC([%define api.location.type Span]) AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%error-verbose %define api.prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc]) @@ -706,7 +706,7 @@ m4_define([AT_CHECK_CALC_GLR_CC], [AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)]) AT_CHECK_CALC_GLR_CC([]) -AT_CHECK_CALC_GLR_CC([%define location_type Span]) +AT_CHECK_CALC_GLR_CC([%define api.location.type Span]) AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR_CC([%error-verbose %define api.prefix "calc" %verbose %yacc]) diff --git a/tests/conflicts.at b/tests/conflicts.at index a46acc5a..a13d7546 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -580,7 +580,7 @@ exp (6) on left: 1 2, on right: 0 1 -state 0 +State 0 0 $accept: . exp $end 1 exp: . exp OP exp @@ -591,14 +591,14 @@ state 0 exp go to state 2 -state 1 +State 1 2 exp: NUM . $default reduce using rule 2 (exp) -state 2 +State 2 0 $accept: exp . $end 1 exp: exp . OP exp @@ -607,14 +607,14 @@ state 2 OP shift, and go to state 4 -state 3 +State 3 0 $accept: exp $end . $default accept -state 4 +State 4 1 exp: . exp OP exp 1 | exp OP . exp @@ -625,7 +625,7 @@ state 4 exp go to state 5 -state 5 +State 5 1 exp: exp . OP exp 1 | exp OP exp . [$end, OP] @@ -683,7 +683,7 @@ exp (6) on left: 1 2, on right: 0 1 -state 0 +State 0 0 $accept: . exp $end 1 exp: . exp OP exp @@ -694,14 +694,14 @@ state 0 exp go to state 2 -state 1 +State 1 2 exp: NUM . $default reduce using rule 2 (exp) -state 2 +State 2 0 $accept: exp . $end 1 exp: exp . OP exp @@ -710,14 +710,14 @@ state 2 OP shift, and go to state 4 -state 3 +State 3 0 $accept: exp $end . $default accept -state 4 +State 4 1 exp: . exp OP exp 1 | exp OP . exp @@ -728,7 +728,7 @@ state 4 exp go to state 5 -state 5 +State 5 1 exp: exp . OP exp 1 | exp OP exp . [$end, OP] @@ -823,7 +823,7 @@ id (7) on left: 4, on right: 2 -state 0 +State 0 0 $accept: . exp $end 1 exp: . num @@ -838,7 +838,7 @@ state 0 id go to state 4 -state 1 +State 1 3 num: '0' . [$end] 4 id: '0' . [$end] @@ -848,28 +848,28 @@ state 1 $default reduce using rule 3 (num) -state 2 +State 2 0 $accept: exp . $end $end shift, and go to state 5 -state 3 +State 3 1 exp: num . $default reduce using rule 1 (exp) -state 4 +State 4 2 exp: id . $default reduce using rule 2 (exp) -state 5 +State 5 0 $accept: exp $end . @@ -896,7 +896,7 @@ exp: exp OP exp | NUM; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce -input.y: expected 0 shift/reduce conflicts +input.y: error: expected 0 shift/reduce conflicts ]) AT_CLEANUP @@ -933,7 +933,7 @@ exp: exp OP exp | NUM; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce -input.y: expected 2 shift/reduce conflicts +input.y: error: expected 2 shift/reduce conflicts ]) AT_CLEANUP @@ -953,7 +953,7 @@ a: 'a'; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 reduce/reduce -input.y: expected 0 reduce/reduce conflicts +input.y: error: expected 0 reduce/reduce conflicts ]) AT_CLEANUP @@ -1170,7 +1170,7 @@ reported_conflicts (9) on left: 8 9 10, on right: 1 -state 0 +State 0 0 $accept: . start $end 1 start: . resolved_conflict 'a' reported_conflicts 'a' @@ -1185,28 +1185,28 @@ state 0 Conflict between rule 3 and token 'a' resolved as reduce (%left 'a'). -state 1 +State 1 0 $accept: start . $end $end shift, and go to state 3 -state 2 +State 2 1 start: resolved_conflict . 'a' reported_conflicts 'a' 'a' shift, and go to state 4 -state 3 +State 3 0 $accept: start $end . $default accept -state 4 +State 4 1 start: resolved_conflict 'a' . reported_conflicts 'a' 8 reported_conflicts: . 'a' @@ -1220,7 +1220,7 @@ state 4 reported_conflicts go to state 6 -state 5 +State 5 8 reported_conflicts: 'a' . ['a'] 9 | 'a' . ['a'] @@ -1230,14 +1230,14 @@ state 5 $default reduce using rule 8 (reported_conflicts) -state 6 +State 6 1 start: resolved_conflict 'a' reported_conflicts . 'a' 'a' shift, and go to state 7 -state 7 +State 7 1 start: resolved_conflict 'a' reported_conflicts 'a' . @@ -1291,8 +1291,8 @@ empty_c2: %prec 'c' ; empty_c3: %prec 'd' ; ]]) AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) -AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, -[[state 0 +AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0, +[[State 0 0 $accept: . start $end 1 start: . 'a' @@ -1328,7 +1328,7 @@ AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd'). -state 1 +State 1 ]]) AT_CLEANUP @@ -1367,8 +1367,8 @@ empty_c3: %prec 'c' ; ]]) AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) -AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, -[[state 0 +AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0, +[[State 0 0 $accept: . start $end 1 start: . 'a' @@ -1404,7 +1404,7 @@ AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c'). -state 1 +State 1 ]]) AT_CLEANUP @@ -1494,11 +1494,11 @@ AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]], echo "$file: conflicts: $conflicts" > experr if test $sr_count -ne $sr_exp; then if test $sr_exp -ne 1; then s=s; else s= ; fi - echo "$file: expected $sr_exp shift/reduce conflict$s" >> experr + echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr fi if test $rr_count -ne $rr_exp; then if test $rr_exp -ne 1; then s=s; else s= ; fi - echo "$file: expected $rr_exp reduce/reduce conflict$s" >> experr + echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr fi ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[ ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[ diff --git a/tests/existing.at b/tests/existing.at index 149499d4..1b6fa4d1 100644 --- a/tests/existing.at +++ b/tests/existing.at @@ -489,7 +489,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' $default reduce using rule 45 (statement) + + -+state 320 ++State 320 + + 139 non_post_simp_exp: . '!' simp_exp + 140 | . '(' exp r_paren @@ -527,7 +527,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 63 + + -+state 321 ++State 321 + + 146 non_post_simp_exp: INCREMENT . variable + 154 variable: . NAME @@ -540,7 +540,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 50 + + -+state 322 ++State 322 + + 147 non_post_simp_exp: DECREMENT . variable + 154 variable: . NAME @@ -553,7 +553,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 51 + + -+state 323 ++State 323 + + 130 simp_exp: . non_post_simp_exp + 131 | . simp_exp '^' simp_exp @@ -601,7 +601,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 57 + + -+state 324 ++State 324 + + 130 simp_exp: . non_post_simp_exp + 131 | . simp_exp '^' simp_exp @@ -649,7 +649,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 57 + + -+state 325 ++State 325 + + 130 simp_exp: . non_post_simp_exp + 131 | . simp_exp '^' simp_exp @@ -697,7 +697,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + variable go to state 57 + + -+state 326 ++State 326 + + 131 simp_exp: simp_exp . '^' simp_exp + 132 | simp_exp . '*' simp_exp @@ -718,7 +718,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + Conflict between rule 151 and token '-' resolved as reduce ('-' < UNARY). + + -+state 327 ++State 327 + + 131 simp_exp: simp_exp . '^' simp_exp + 132 | simp_exp . '*' simp_exp @@ -739,7 +739,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%' + Conflict between rule 150 and token '-' resolved as reduce ('-' < UNARY). + + -+state 328 ++State 328 + + 131 simp_exp: simp_exp . '^' simp_exp + 132 | simp_exp . '*' simp_exp @@ -2040,7 +2040,7 @@ dnl - 383 -> 427 nth_primitive go to state 105 @@ -3256,7 +3256,7 @@ - state 102 + State 102 - 146 place: label . [$end, LABEL, VARIABLE, NUMBER, TEXT, ORDINAL, LEFT_ARROW_HEAD, RIGHT_ARROW_HEAD, DOUBLE_ARROW_HEAD, LAST, UP, DOWN, LEFT, RIGHT, HEIGHT, RADIUS, WIDTH, DIAMETER, FROM, TO, AT, WITH, BY, THEN, SOLID, DOTTED, DASHED, CHOP, SAME, INVISIBLE, LJUST, RJUST, ABOVE, BELOW, AND, HERE, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, SIN, COS, ATAN2, LOG, EXP, SQRT, K_MAX, K_MIN, INT, RAND, SRAND, CW, CCW, THICKNESS, FILL, COLORED, OUTLINED, SHADED, ALIGNED, SPRINTF, '(', '`', ',', '>', '+', '-', '!', ';', '}', '@:>@', ')'] + 146 place: label . [$end, LABEL, VARIABLE, NUMBER, TEXT, ORDINAL, LEFT_ARROW_HEAD, RIGHT_ARROW_HEAD, DOUBLE_ARROW_HEAD, LAST, UP, DOWN, LEFT, RIGHT, HEIGHT, RADIUS, WIDTH, DIAMETER, FROM, TO, AT, WITH, BY, THEN, SOLID, DOTTED, DASHED, CHOP, SAME, INVISIBLE, LJUST, RJUST, ABOVE, BELOW, HERE, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, SIN, COS, ATAN2, LOG, EXP, SQRT, K_MAX, K_MIN, INT, RAND, SRAND, CW, CCW, THICKNESS, FILL, COLORED, OUTLINED, SHADED, ALIGNED, SPRINTF, '(', '`', '+', '-', '!', ';', '}', '@:>@'] @@ -2205,7 +2205,7 @@ dnl - 383 -> 427 + expr go to state 424 - state 165 + State 165 @@ -7987,7 +7987,7 @@ text_expr go to state 112 text go to state 113 @@ -2322,7 +2322,7 @@ dnl - 383 -> 427 + between go to state 425 - state 193 + State 193 @@ -10152,7 +10152,7 @@ expr_pair go to state 317 @@ -2490,7 +2490,7 @@ dnl - 383 -> 427 + expr go to state 424 - state 238 + State 238 @@ -12937,7 +12937,7 @@ '!' shift, and go to state 94 @@ -2577,7 +2577,7 @@ dnl - 383 -> 427 + expr go to state 424 - state 315 + State 315 @@ -16124,7 +16124,7 @@ $default reduce using rule 239 (expr) @@ -2628,7 +2628,7 @@ dnl - 383 -> 427 + expr go to state 424 - state 383 + State 383 @@ -18071,7 +18071,7 @@ '!' shift, and go to state 94 @@ -2671,7 +2671,7 @@ dnl - 383 -> 427 $default reduce using rule 29 (placeless_element) + + -+state 423 ++State 423 + + 146 place: label . [$end, AND, DOT_X, DOT_Y, DOT_HT, DOT_WID, DOT_RAD, ',', '>', '+', '-', ';', '}', '@:>@', ')'] + 147 | label . corner @@ -2742,7 +2742,7 @@ dnl - 383 -> 427 + corner go to state 205 + + -+state 424 ++State 424 + + 140 position_not_place: expr . between position AND position + 141 | expr . '<' position ',' position '>' @@ -2785,7 +2785,7 @@ dnl - 383 -> 427 + between go to state 425 + + -+state 425 ++State 425 + + 134 position: . position_not_place + 135 | . place @@ -2941,7 +2941,7 @@ dnl - 383 -> 427 + expr go to state 424 + + -+state 426 ++State 426 + + 137 position_not_place: position . '+' expr_pair + 138 | position . '-' expr_pair @@ -2952,7 +2952,7 @@ dnl - 383 -> 427 + '-' shift, and go to state 198 + + -+state 427 ++State 427 + + 134 position: . position_not_place + 135 | . place diff --git a/tests/glr-regression.at b/tests/glr-regression.at index aab0369f..6ca021f9 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -196,8 +196,12 @@ int main (int argc, char **argv) { input = stdin; - if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3; - return yyparse (); + if (argc == 2 && !(input = fopen (argv[1], "r"))) + return 3; + int res = yyparse (); + if (argc == 2 && fclose (input)) + return 4; + return res; } ]]) AT_BISON_OPTION_POPDEFS @@ -324,8 +328,12 @@ int main(int argc, char* argv[]) { input = stdin; - if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3; - return yyparse (); + if (argc == 2 && !(input = fopen (argv[1], "r"))) + return 3; + int res = yyparse (); + if (argc == 2 && fclose (input)) + return 4; + return res; } ]]) AT_BISON_OPTION_POPDEFS @@ -1652,10 +1660,10 @@ main (void) AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [], -[glr-regr18.y:26.18-24: result type clash on merge function 'merge': != -glr-regr18.y:25.18-24: previous declaration -glr-regr18.y:27.13-19: result type clash on merge function 'merge': != -glr-regr18.y:26.18-24: previous declaration +[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': != +glr-regr18.y:25.18-24: previous declaration +glr-regr18.y:27.13-19: error: result type clash on merge function 'merge': != +glr-regr18.y:26.18-24: previous declaration ]) AT_CLEANUP diff --git a/tests/headers.at b/tests/headers.at index b53ee8a0..dcf09a72 100644 --- a/tests/headers.at +++ b/tests/headers.at @@ -131,7 +131,7 @@ AT_SETUP([Several parsers]) # self-contained, and can be compiled by a C++ compiler. m4_pushdef([AT_TEST], [AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2]) -AT_DATA_GRAMMAR([$1.AT_SKEL_CC_IF([yy], [y])], +AT_DATA_GRAMMAR([$1.y], [[%define api.prefix "$1_" $2 %error-verbose @@ -161,7 +161,7 @@ exp: ]AT_YYLEX_DEFINE(["$1"])[ ]]) -AT_BISON_CHECK([-d -o AT_SKEL_CC_IF([$1.cc $1.yy], [$1.c $1.y])]) +AT_BISON_CHECK([-d -o $1.AT_SKEL_CC_IF([cc], [c]) $1.y]) AT_LANG_COMPILE([$1.o]) AT_CHECK([[echo "$1" >>expout]]) diff --git a/tests/input.at b/tests/input.at index 2848562d..faa939c1 100644 --- a/tests/input.at +++ b/tests/input.at @@ -39,20 +39,16 @@ default: 'a' } AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1: invalid character: '\0' -input.y:1.1: invalid character: '\001' -input.y:1.1: invalid character: '\002' -input.y:1.1: invalid character: '\377' -input.y:1.2: invalid character: '?' -input.y:3.1: invalid character: '?' -input.y:4.14: invalid character: '}' -input.y:5.1: invalid character: '%' -input.y:5.2: invalid character: '&' -input.y:6.1-17: invalid directive: '%a-does-not-exist' -input.y:7.1: invalid character: '%' -input.y:7.2: invalid character: '-' -input.y:8.1-9.0: missing '%}' at end of file -input.y:8.1-9.0: syntax error, unexpected %{...%} +[[input.y:1.1-2: error: invalid characters: '\0\001\002\377?' +input.y:3.1: error: invalid character: '?' +input.y:4.14: error: invalid character: '}' +input.y:5.1: error: invalid character: '%' +input.y:5.2: error: invalid character: '&' +input.y:6.1-17: error: invalid directive: '%a-does-not-exist' +input.y:7.1: error: invalid character: '%' +input.y:7.2: error: invalid character: '-' +input.y:8.1-9.0: error: missing '%}' at end of file +input.y:8.1-9.0: error: syntax error, unexpected %{...%} ]]) AT_CLEANUP @@ -74,7 +70,7 @@ AT_DATA([input.y], ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...} +[[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...} ]]) AT_CLEANUP @@ -94,8 +90,8 @@ exp: { @$ = @1 ; }; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:2.13-14: integer out of range: '$1' -input.y:3.13-14: integer out of range: '@1' +[[input.y:2.13-14: error: integer out of range: '$1' +input.y:3.13-14: error: integer out of range: '@1' ]]) AT_CLEANUP @@ -119,8 +115,8 @@ exp: foo { $$; } foo { $2; } foo ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:5.12-13: $$ for the midrule at $2 of 'exp' has no declared type -input.y:5.24-25: $2 of 'exp' has no declared type +[[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type +input.y:5.24-25: error: $2 of 'exp' has no declared type input.y:5.6-32: warning: type clash on default action: != <> input.y:6.6-8: warning: type clash on default action: != <> input.y:7.5: warning: empty rule for typed nonterminal, and no action @@ -266,30 +262,30 @@ start: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.13-29: redeclaration for default tagged %destructor -input.y:1.13-29: previous declaration -input.y:2.10-24: redeclaration for default tagged %printer -input.y:2.10-24: previous declaration -input.y:4.13-29: redeclaration for default tagged %destructor -input.y:1.13-29: previous declaration -input.y:5.10-24: redeclaration for default tagged %printer -input.y:2.10-24: previous declaration -input.y:7.13-29: redeclaration for default tagless %destructor -input.y:7.13-29: previous declaration -input.y:8.10-24: redeclaration for default tagless %printer -input.y:8.10-24: previous declaration -input.y:10.13-29: redeclaration for default tagless %destructor -input.y:7.13-29: previous declaration -input.y:11.10-24: redeclaration for default tagless %printer -input.y:8.10-24: previous declaration -input.y:17.13-29: redeclaration for default tagged %destructor -input.y:4.13-29: previous declaration -input.y:18.10-24: redeclaration for default tagged %printer -input.y:5.10-24: previous declaration -input.y:20.13-29: redeclaration for default tagless %destructor -input.y:10.13-29: previous declaration -input.y:21.10-24: redeclaration for default tagless %printer -input.y:11.10-24: previous declaration +[[input.y:1.13-29: error: redeclaration for default tagged %destructor +input.y:1.13-29: previous declaration +input.y:2.10-24: error: redeclaration for default tagged %printer +input.y:2.10-24: previous declaration +input.y:4.13-29: error: redeclaration for default tagged %destructor +input.y:1.13-29: previous declaration +input.y:5.10-24: error: redeclaration for default tagged %printer +input.y:2.10-24: previous declaration +input.y:7.13-29: error: redeclaration for default tagless %destructor +input.y:7.13-29: previous declaration +input.y:8.10-24: error: redeclaration for default tagless %printer +input.y:8.10-24: previous declaration +input.y:10.13-29: error: redeclaration for default tagless %destructor +input.y:7.13-29: previous declaration +input.y:11.10-24: error: redeclaration for default tagless %printer +input.y:8.10-24: previous declaration +input.y:17.13-29: error: redeclaration for default tagged %destructor +input.y:4.13-29: previous declaration +input.y:18.10-24: error: redeclaration for default tagged %printer +input.y:5.10-24: previous declaration +input.y:20.13-29: error: redeclaration for default tagless %destructor +input.y:10.13-29: previous declaration +input.y:21.10-24: error: redeclaration for default tagless %printer +input.y:11.10-24: previous declaration ]]) AT_CLEANUP @@ -317,22 +313,22 @@ start: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:4.13-29: %destructor redeclaration for -input.y:1.13-29: previous declaration -input.y:4.13-29: %destructor redeclaration for -input.y:4.13-29: previous declaration -input.y:5.10-24: %printer redeclaration for -input.y:2.10-24: previous declaration -input.y:5.10-24: %printer redeclaration for -input.y:5.10-24: previous declaration -input.y:11.13-29: %destructor redeclaration for -input.y:4.13-29: previous declaration -input.y:11.13-29: %destructor redeclaration for -input.y:1.13-29: previous declaration -input.y:12.10-24: %printer redeclaration for -input.y:2.10-24: previous declaration -input.y:12.10-24: %printer redeclaration for -input.y:5.10-24: previous declaration +[[input.y:4.13-29: error: %destructor redeclaration for +input.y:1.13-29: previous declaration +input.y:4.13-29: error: %destructor redeclaration for +input.y:4.13-29: previous declaration +input.y:5.10-24: error: %printer redeclaration for +input.y:2.10-24: previous declaration +input.y:5.10-24: error: %printer redeclaration for +input.y:5.10-24: previous declaration +input.y:11.13-29: error: %destructor redeclaration for +input.y:4.13-29: previous declaration +input.y:11.13-29: error: %destructor redeclaration for +input.y:1.13-29: previous declaration +input.y:12.10-24: error: %printer redeclaration for +input.y:2.10-24: previous declaration +input.y:12.10-24: error: %printer redeclaration for +input.y:5.10-24: previous declaration ]]) AT_CLEANUP @@ -429,14 +425,14 @@ exp: foo; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:8.7-11: %type redeclaration for foo -input.y:3.7-11: previous declaration -input.y:10.13-17: %destructor redeclaration for foo -input.y:5.13-17: previous declaration -input.y:9.10-14: %printer redeclaration for foo -input.y:4.10-14: previous declaration -input.y:11.1-5: %left redeclaration for foo -input.y:6.1-5: previous declaration +[[input.y:8.7-11: error: %type redeclaration for foo +input.y:3.7-11: previous declaration +input.y:10.13-17: error: %destructor redeclaration for foo +input.y:5.13-17: previous declaration +input.y:9.10-14: error: %printer redeclaration for foo +input.y:4.10-14: previous declaration +input.y:11.1-5: error: %left redeclaration for foo +input.y:6.1-5: previous declaration ]]) AT_CLEANUP @@ -455,7 +451,7 @@ AT_SETUP([Torturing the Scanner]) AT_BISON_OPTION_PUSHDEFS AT_DATA([input.y], []) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1: syntax error, unexpected end of file +[[input.y:1.1: error: syntax error, unexpected end of file ]]) @@ -463,7 +459,7 @@ AT_DATA([input.y], [{} ]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1-2: syntax error, unexpected {...} +[[input.y:1.1-2: error: syntax error, unexpected {...} ]]) @@ -729,9 +725,9 @@ AT_DATA_GRAMMAR([input.y], start: .GOOD GOOD ]]) AT_BISON_CHECK([-o input.c input.y], [1], [], -[[input.y:10.10: invalid character: '-' -input.y:11.10-16: invalid identifier: '1NV4L1D' -input.y:12.10: invalid character: '-' +[[input.y:10.10: error: invalid character: '-' +input.y:11.10-16: error: invalid identifier: '1NV4L1D' +input.y:12.10: error: invalid character: '-' ]]) AT_CLEANUP @@ -753,10 +749,10 @@ start: DECIMAL_1 HEXADECIMAL_2; ]]) AT_BISON_CHECK([redecl.y], [1], [], -[[redecl.y:10.10-22: user token number 11259375 redeclaration for HEXADECIMAL_1 -redecl.y:9.8-16: previous declaration for DECIMAL_1 -redecl.y:12.10-18: user token number 16702650 redeclaration for DECIMAL_2 -redecl.y:11.10-22: previous declaration for HEXADECIMAL_2 +[[redecl.y:10.10-22: error: user token number 11259375 redeclaration for HEXADECIMAL_1 +redecl.y:9.8-16: previous declaration for DECIMAL_1 +redecl.y:12.10-18: error: user token number 16702650 redeclaration for DECIMAL_2 +redecl.y:11.10-22: previous declaration for HEXADECIMAL_2 ]]) AT_DATA_GRAMMAR([too-large.y], @@ -768,8 +764,8 @@ start: TOO_LARGE_DEC TOO_LARGE_HEX ]]) AT_BISON_CHECK([too-large.y], [1], [], -[[too-large.y:9.22-42: integer out of range: '999999999999999999999' -too-large.y:10.24-44: integer out of range: '0xFFFFFFFFFFFFFFFFFFF' +[[too-large.y:9.22-42: error: integer out of range: '999999999999999999999' +too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF' ]]) AT_CLEANUP @@ -809,12 +805,12 @@ start: ; ]]) AT_BISON_CHECK([-o input.c input.y], 1, [], -[[input.y:1.10-2.0: missing '"' at end of line -input.y:4.10-5.0: missing "'" at end of line -input.y:14.11-15.0: missing "'" at end of line -input.y:16.11-17.0: missing '"' at end of line -input.y:19.13-20.0: missing '}' at end of file -input.y:20.1: syntax error, unexpected end of file +[[input.y:1.10-2.0: error: missing '"' at end of line +input.y:4.10-5.0: error: missing "'" at end of line +input.y:14.11-15.0: error: missing "'" at end of line +input.y:16.11-17.0: error: missing '"' at end of line +input.y:19.13-20.0: error: missing '}' at end of file +input.y:20.1: error: syntax error, unexpected end of file ]]) AT_CLEANUP @@ -856,7 +852,7 @@ PREC: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:3.1-4: rule given for PREC, which is a token +[[input.y:3.1-4: error: rule given for PREC, which is a token ]]) AT_CLEANUP @@ -897,10 +893,10 @@ AT_DATA([input-c.y], start: ; ]]) AT_BISON_CHECK([[input-c.y]], [[1]], [], -[[input-c.y:1.7: %code qualifier 'q' is not used -input-c.y:2.7-9: %code qualifier 'bad' is not used -input-c.y:3.7-9: %code qualifier 'bad' is not used -input-c.y:4.7-12: %code qualifier 'format' is not used +[[input-c.y:1.7: error: %code qualifier 'q' is not used +input-c.y:2.7-9: error: %code qualifier 'bad' is not used +input-c.y:3.7-9: error: %code qualifier 'bad' is not used +input-c.y:4.7-12: error: %code qualifier 'format' is not used ]]) AT_DATA([input-c-glr.y], @@ -911,9 +907,9 @@ AT_DATA([input-c-glr.y], start: ; ]]) AT_BISON_CHECK([[input-c-glr.y]], [[1]], [], -[[input-c-glr.y:1.7: %code qualifier 'q' is not used -input-c-glr.y:2.7-9: %code qualifier 'bad' is not used -input-c-glr.y:3.8-10: %code qualifier 'bad' is not used +[[input-c-glr.y:1.7: error: %code qualifier 'q' is not used +input-c-glr.y:2.7-9: error: %code qualifier 'bad' is not used +input-c-glr.y:3.8-10: error: %code qualifier 'bad' is not used ]]) AT_DATA([input-c++.y], @@ -924,9 +920,9 @@ AT_DATA([input-c++.y], start: ; ]]) AT_BISON_CHECK([[input-c++.y]], [[1]], [], -[[input-c++.y:1.7: %code qualifier 'q' is not used -input-c++.y:2.7-9: %code qualifier 'bad' is not used -input-c++.y:3.8: %code qualifier 'q' is not used +[[input-c++.y:1.7: error: %code qualifier 'q' is not used +input-c++.y:2.7-9: error: %code qualifier 'bad' is not used +input-c++.y:3.8: error: %code qualifier 'q' is not used ]]) AT_DATA([input-c++-glr.y], @@ -937,9 +933,9 @@ AT_DATA([input-c++-glr.y], start: ; ]]) AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [], -[[input-c++-glr.y:1.7-9: %code qualifier 'bad' is not used -input-c++-glr.y:2.7: %code qualifier 'q' is not used -input-c++-glr.y:3.7: %code qualifier 'q' is not used +[[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used +input-c++-glr.y:2.7: error: %code qualifier 'q' is not used +input-c++-glr.y:3.7: error: %code qualifier 'q' is not used ]]) AT_DATA([special-char-@@.y], @@ -950,9 +946,9 @@ AT_DATA([special-char-@@.y], start: ; ]]) AT_BISON_CHECK([[special-char-@@.y]], [[1]], [], -[[special-char-@@.y:1.7-9: %code qualifier 'bad' is not used -special-char-@@.y:2.7: %code qualifier 'q' is not used -special-char-@@.y:3.7: %code qualifier 'q' is not used +[[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used +special-char-@@.y:2.7: error: %code qualifier 'q' is not used +special-char-@@.y:3.7: error: %code qualifier 'q' is not used ]]) AT_DATA([special-char-@:>@.y], @@ -963,9 +959,9 @@ AT_DATA([special-char-@:>@.y], start: ; ]]) AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [], -[[special-char-@:>@.y:1.7-9: %code qualifier 'bad' is not used -special-char-@:>@.y:2.7: %code qualifier 'q' is not used -special-char-@:>@.y:3.7: %code qualifier 'q' is not used +[[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used +special-char-@:>@.y:2.7: error: %code qualifier 'q' is not used +special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used ]]) AT_CLEANUP @@ -988,10 +984,10 @@ start: ; ]]) AT_BISON_CHECK([[input-redefined.y]], [[1]], [], -[[input-redefined.y:2.9-11: %define variable 'var' redefined -input-redefined.y:1.9-11: previous definition -input-redefined.y:3.10-12: %define variable 'var' redefined -input-redefined.y:2.9-11: previous definition +[[input-redefined.y:2.9-11: error: %define variable 'var' redefined +input-redefined.y:1.9-11: previous definition +input-redefined.y:3.10-12: error: %define variable 'var' redefined +input-redefined.y:2.9-11: previous definition ]]) AT_DATA([input-unused.y], @@ -1001,7 +997,7 @@ start: ; ]]) AT_BISON_CHECK([[input-unused.y]], [[1]], [], -[[input-unused.y:1.9-11: %define variable 'var' is not used +[[input-unused.y:1.9-11: error: %define variable 'var' is not used ]]) AT_CLEANUP @@ -1045,8 +1041,8 @@ AT_DATA([[input-dg.y]], start: ; ]]) AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [], -[[input-dg.y:1.9-11: %define variable 'var' redefined -:2: previous definition +[[input-dg.y:1.9-11: error: %define variable 'var' redefined +:2: previous definition ]]) AT_DATA([[input-unused.y]], @@ -1054,8 +1050,8 @@ AT_DATA([[input-unused.y]], start: ; ]]) AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [], -[[:2: %define variable 'unused-d' is not used -:3: %define variable 'unused-f' is not used +[[:2: error: %define variable 'unused-d' is not used +:3: error: %define variable 'unused-f' is not used ]]) AT_CLEANUP @@ -1075,7 +1071,7 @@ start: ; ]]) AT_BISON_CHECK([[Input.y]], [1], [], -[[Input.y:2.9-14: invalid value for %define Boolean variable 'public' +[[Input.y:2.9-14: error: invalid value for %define Boolean variable 'public' ]]) AT_CLEANUP @@ -1093,23 +1089,24 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [[]], -[[input.y:1.9-29: invalid value for %define variable 'lr.default-reductions': 'bogus' -input.y:1.9-29: accepted value: 'most' -input.y:1.9-29: accepted value: 'consistent' -input.y:1.9-29: accepted value: 'accepting' +[[input.y:1.9-29: error: invalid value for %define variable 'lr.default-reductions': 'bogus' +input.y:1.9-29: accepted value: 'most' +input.y:1.9-29: accepted value: 'consistent' +input.y:1.9-29: accepted value: 'accepting' ]]) # Back-end. +# FIXME: these should be indented, but we shouldn't mess with the m4 yet AT_DATA([[input.y]], [[%define api.push-pull neither %% start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither' -input.y:1.9-21: accepted value: 'pull' -input.y:1.9-21: accepted value: 'push' -input.y:1.9-21: accepted value: 'both' +[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither' +input.y:1.9-21: error: accepted value: 'pull' +input.y:1.9-21: error: accepted value: 'push' +input.y:1.9-21: error: accepted value: 'both' ]]) AT_CLEANUP @@ -1129,10 +1126,10 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither' -input.y:1.9-21: accepted value: 'pull' -input.y:1.9-21: accepted value: 'push' -input.y:1.9-21: accepted value: 'both' +[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither' +input.y:1.9-21: error: accepted value: 'pull' +input.y:1.9-21: error: accepted value: 'push' +input.y:1.9-21: error: accepted value: 'both' ]]) AT_DATA([[input.y]], @@ -1141,7 +1138,7 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-34: invalid value for %define Boolean variable 'lr.keep-unreachable-states' +[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states' ]]) AT_DATA([[input.y]], @@ -1150,7 +1147,7 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [], -[[input.y:1.9-15: %define variable 'foo_bar' is not used +[[input.y:1.9-15: error: %define variable 'foo_bar' is not used ]]) AT_CLEANUP @@ -1175,7 +1172,7 @@ start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [], -[[input.y:1.9-16: %define variable 'api.pure' is not used +[[input.y:1.9-16: error: %define variable 'api.pure' is not used ]]) ]) @@ -1209,7 +1206,7 @@ start: ; AT_BISON_CHECK([[input.y]], [1], [], [m4_foreach([b4_arg], m4_dquote(m4_shift($@)), -[[input.y:3.9-17: ]b4_arg[ +[[input.y:3.9-17: error: ]b4_arg[ ]])]) ]) @@ -1260,9 +1257,9 @@ AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]]) AT_BISON_CHECK([empty.y], [1], [], [[empty.y:2.8-9: warning: empty character literal empty.y:3.8-4.0: warning: empty character literal -empty.y:3.8-4.0: missing "'" at end of line +empty.y:3.8-4.0: error: missing "'" at end of line empty.y:4.8: warning: empty character literal -empty.y:4.8: missing "'" at end of file +empty.y:4.8: error: missing "'" at end of file ]]) AT_DATA([two.y], @@ -1275,9 +1272,9 @@ AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]]) AT_BISON_CHECK([two.y], [1], [], [[two.y:2.8-11: warning: extra characters in character literal two.y:3.8-4.0: warning: extra characters in character literal -two.y:3.8-4.0: missing "'" at end of line +two.y:3.8-4.0: error: missing "'" at end of line two.y:4.8-10: warning: extra characters in character literal -two.y:4.8-10: missing "'" at end of file +two.y:4.8-10: error: missing "'" at end of file ]]) AT_DATA([three.y], @@ -1290,9 +1287,9 @@ AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]]) AT_BISON_CHECK([three.y], [1], [], [[three.y:2.8-12: warning: extra characters in character literal three.y:3.8-4.0: warning: extra characters in character literal -three.y:3.8-4.0: missing "'" at end of line +three.y:3.8-4.0: error: missing "'" at end of line three.y:4.8-11: warning: extra characters in character literal -three.y:4.8-11: missing "'" at end of file +three.y:4.8-11: error: missing "'" at end of file ]]) AT_CLEANUP @@ -1318,30 +1315,30 @@ AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \ || exit 77]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:2.9-12: invalid number after \-escape: 777 +[[input.y:2.9-12: error: invalid number after \-escape: 777 input.y:2.8-13: warning: empty character literal -input.y:2.16-17: invalid number after \-escape: 0 +input.y:2.16-17: error: invalid number after \-escape: 0 input.y:2.15-18: warning: empty character literal -input.y:2.21-25: invalid number after \-escape: xfff +input.y:2.21-25: error: invalid number after \-escape: xfff input.y:2.20-26: warning: empty character literal -input.y:2.29-31: invalid number after \-escape: x0 +input.y:2.29-31: error: invalid number after \-escape: x0 input.y:2.28-32: warning: empty character literal -input.y:3.9-14: invalid number after \-escape: uffff +input.y:3.9-14: error: invalid number after \-escape: uffff input.y:3.8-15: warning: empty character literal -input.y:3.18-23: invalid number after \-escape: u0000 +input.y:3.18-23: error: invalid number after \-escape: u0000 input.y:3.17-24: warning: empty character literal -input.y:3.27-36: invalid number after \-escape: Uffffffff +input.y:3.27-36: error: invalid number after \-escape: Uffffffff input.y:3.26-37: warning: empty character literal -input.y:3.40-49: invalid number after \-escape: U00000000 +input.y:3.40-49: error: invalid number after \-escape: U00000000 input.y:3.39-50: warning: empty character literal -input.y:4.9-10: invalid character after \-escape: ' ' +input.y:4.9-10: error: invalid character after \-escape: ' ' input.y:4.8-11: warning: empty character literal -input.y:4.14-15: invalid character after \-escape: A +input.y:4.14-15: error: invalid character after \-escape: A input.y:4.13-16: warning: empty character literal -input.y:5.9-16: invalid character after \-escape: \t -input.y:5.17: invalid character after \-escape: \f -input.y:5.18: invalid character after \-escape: \0 -input.y:5.19: invalid character after \-escape: \001 +input.y:5.9-16: error: invalid character after \-escape: \t +input.y:5.17: error: invalid character after \-escape: \f +input.y:5.18: error: invalid character after \-escape: \0 +input.y:5.19: error: invalid character after \-escape: \001 ]]) AT_CLEANUP @@ -1360,11 +1357,11 @@ start: ; # parse.lac.* options are useless if LAC isn't actually activated. AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]], [[1]], [], -[[:2: %define variable 'parse.lac.es-capacity-initial' is not used +[[:2: error: %define variable 'parse.lac.es-capacity-initial' is not used ]]) AT_BISON_CHECK([[-Dparse.lac.memory-trace=full input.y]], [[1]], [], -[[:2: %define variable 'parse.lac.memory-trace' is not used +[[:2: error: %define variable 'parse.lac.memory-trace' is not used ]]) AT_CLEANUP @@ -1418,7 +1415,7 @@ m4_pushdef([AT_TEST], exp:; ]]) AT_BISON_CHECK([[$2 input.y]], [[1]], [[]], -[[$3: '%name-prefix' and '%define api.prefix' cannot be used together +[[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together ]]) ]) diff --git a/tests/java.at b/tests/java.at index f822ec6e..db3f5000 100644 --- a/tests/java.at +++ b/tests/java.at @@ -719,8 +719,8 @@ AT_SETUP([Java stype, position_class and location_class]) AT_CHECK_JAVA_MINIMAL([[ %define stype "java.awt.Color" %type start; -%define location_type "MyLoc" -%define position_type "MyPos" +%define api.location.type "MyLoc" +%define api.position.type "MyPos" %code { class MyPos {} }]], [[$$ = $1;]], [[MyPos]]) AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore]) AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore]) @@ -729,8 +729,8 @@ AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore]) AT_CHECK_JAVA_MINIMAL_W_LEXER([[ %define stype "java.awt.Color" %type start; -%define location_type "MyLoc" -%define position_type "MyPos" +%define api.location.type "MyLoc" +%define api.position.type "MyPos" %code { class MyPos {} }]], [], [[return EOF;]], [], [[$$ = $1;]], [[java.awt.Color]], [[MyPos]], [[MyLoc]]) diff --git a/tests/local.at b/tests/local.at index a5dde80a..efba29dc 100644 --- a/tests/local.at +++ b/tests/local.at @@ -138,7 +138,7 @@ m4_pushdef([AT_LEXPARAM_IF], m4_pushdef([AT_LOCATION_IF], [m4_bmatch([$3], [%locations], [$1], [$2])]) m4_pushdef([AT_LOCATION_TYPE_IF], -[m4_bmatch([$3], [%define location_type], [$1], [$2])]) +[m4_bmatch([$3], [%define \(api\.location\.type\|location_type\)], [$1], [$2])]) m4_pushdef([AT_PARAM_IF], [m4_bmatch([$3], [%parse-param], [$1], [$2])]) # Comma-terminated list of formals parse-parameters. @@ -556,10 +556,10 @@ m4_define([AT_BISON_CHECK_XML], AT_CHECK([[$XSLTPROC \ `]]AT_QUELL_VALGRIND[[ bison --print-datadir`/xslt/xml2text.xsl \ xml-tests/test.xml]], [[0]], [expout]) - [cp xml-tests/test.dot expout] + [sort xml-tests/test.dot > expout] AT_CHECK([[$XSLTPROC \ `]]AT_QUELL_VALGRIND[[ bison --print-datadir`/xslt/xml2dot.xsl \ - xml-tests/test.xml]], [[0]], [expout]) + xml-tests/test.xml | sort]], [[0]], [expout]) [rm -rf xml-tests expout] AT_RESTORE_SPECIAL_FILES [fi]]) @@ -868,9 +868,9 @@ m4_if(m4_index(m4_quote($3), [no-xml]), -1, [0], [], m4_dquote($7)) m4_if(m4_index(m4_quote($3), [last-state]), -1, - [AT_CHECK([[sed -n '/^state 0$/,$p' input.output]], [[0]], + [AT_CHECK([[sed -n '/^State 0$/,$p' input.output]], [[0]], m4_dquote($8))], - [AT_CHECK([[sed -n 's/^state //p' input.output | tail -1]], [[0]], + [AT_CHECK([[sed -n 's/^State //p' input.output | tail -1]], [[0]], m4_dquote($8)[[ ]])]) diff --git a/tests/named-refs.at b/tests/named-refs.at index 744eab82..de48e0f7 100644 --- a/tests/named-refs.at +++ b/tests/named-refs.at @@ -49,18 +49,18 @@ static int power (int base, int exponent); %nonassoc '=' /* comparison */ %left '-' '+' %left '*' '/' -%left NEG /* negation--unary minus */ +%left NEG /* negation--unary minus */ %right '^' /* exponentiation */ %% input: line -| input line { } +| input line {} ; line: '\n' -| exp '\n' { } +| exp '\n' {} ; exp: @@ -69,15 +69,15 @@ exp: { if ($l != $r) fprintf (stderr, "calc: error: %d != %d\n", $l, $r); - $$ = $l; + $$ = $l; } | exp[x] '+' { $$ = $x; } [l] exp[r] { $$ = $l + $r; } -| exp[l] '-' exp[r] { $$ = $l - $r; } -| exp[l] '*' exp[r] { $$ = $l * $r; } +| exp[l] '-' exp[r] { $$ = $l - $r; } +| exp[l] '*' exp[r] { $$ = $l * $r; } | exp[l] '/' exp[r] { $$ = $l / $r; } | '-' exp %prec NEG { $$ = -$2; } -| exp[l] '^' exp[r] { $$ = power ($l, $r); } -| '(' exp[e] ')' { $$ = $e; } +| exp[l] '^' exp[r] { $$ = power ($l, $r); } +| '(' exp[e] ')' { $$ = $e; } | '(' error ')' { $$ = 1111; yyerrok; } | '!' { $$ = 0; YYERROR; } | '-' error { $$ = 0; YYERROR; } @@ -214,18 +214,18 @@ static int power (int base, int exponent); %nonassoc '=' /* comparison */ %left '-' '+' %left '*' '/' -%left NEG /* negation--unary minus */ +%left NEG /* negation--unary minus */ %right '^' /* exponentiation */ %% input: line -| input line { } +| input line {} ; line: '\n' -| exp '\n' { } +| exp '\n' {} ; exp: @@ -234,14 +234,14 @@ exp: { if ($l != $r) fprintf (stderr, "calc: error: %d != %d\n", $l, $r); - $$ = $l; + $$ = $l; } | exp[x] '+' { $$ = $x; } [l] exp[r] { $$ = $lo9 + $r; } | exp[x] '-' { $$ = $x; } [l] exp[r] { $$ = $exp - $r; } | exp[x] '*' { $$ = $x; } [l] exp[r] { $$ = $l * $r; } | exp[l] '/' exp[r] { $$ = $l / $r; } | '-' exp %prec NEG { $$ = -$2; } -| exp[l] '^' exp[r] { $$ = power ($l, $r12); } +| exp[l] '^' exp[r] { $$ = power ($l, $r12); } | '(' exp ')' { $$ = $expo; } | '(' error ')' { $$ = 1111; yyerrok; } | '!' { $$ = 0; YYERROR; } @@ -251,16 +251,16 @@ exp: ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:50.51-60: invalid reference: '$lo9' +[[test.y:50.51-60: error: invalid reference: '$lo9' test.y:50.3-68: symbol not found in production: lo9 test.y:51.51-60: warning: misleading reference: '$exp' -test.y:42.1-3: warning: refers to: $exp at $$ -test.y:51.7: warning: possibly meant: $x, hiding $exp at $1 -test.y:51.41: warning: possibly meant: $r, hiding $exp at $4 -test.y:52.51-52: $l of 'exp' has no declared type -test.y:55.46-49: invalid reference: '$r12' -test.y:55.3-53: symbol not found in production: r12 -test.y:56.29-33: invalid reference: '$expo' +test.y:42.1-3: refers to: $exp at $$ +test.y:51.7: possibly meant: $x, hiding $exp at $1 +test.y:51.41: possibly meant: $r, hiding $exp at $4 +test.y:52.51-52: error: $l of 'exp' has no declared type +test.y:55.40-43: error: invalid reference: '$r12' +test.y:55.3-47: symbol not found in production: r12 +test.y:56.29-33: error: invalid reference: '$expo' test.y:56.3-46: symbol not found in production: expo ]]) AT_BISON_OPTION_POPDEFS @@ -278,8 +278,8 @@ foo.bar: '2' ]]) AT_BISON_CHECK([-o test.c test.y], 0, [], [[test.y:11.22-29: warning: misleading reference: '$foo.bar' -test.y:11.8-10: warning: refers to: $foo at $1 -test.y:11.12-18: warning: possibly meant: $[foo.bar] at $2 +test.y:11.8-10: refers to: $foo at $1 +test.y:11.12-18: possibly meant: $[foo.bar] at $2 ]]) AT_CLEANUP @@ -353,43 +353,43 @@ factor: '(' expr ')' { $$ = $2; } ; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:24.36-41: invalid reference: '$cond1' +[[test.y:24.36-41: error: invalid reference: '$cond1' test.y:23.11-24.62: symbol not found in production: cond1 -test.y:26.43-53: invalid reference: '$stmt.field' +test.y:26.43-53: error: invalid reference: '$stmt.field' test.y:25.11-26.60: symbol not found in production: stmt test.y:25.35-38: possibly meant: $then.field, hiding $stmt.field at $4 -test.y:28.43-52: invalid reference: '$stmt.list' +test.y:28.43-52: error: invalid reference: '$stmt.list' test.y:27.11-28.59: symbol not found in production: stmt test.y:27.30-38: possibly meant: $[stmt.list] at $4 -test.y:30.43-46: ambiguous reference: '$xyz' +test.y:30.43-46: error: ambiguous reference: '$xyz' test.y:29.35-37: refers to: $xyz at $4 test.y:29.50-52: refers to: $xyz at $6 -test.y:32.43-52: invalid reference: '$stmt.list' +test.y:32.43-52: error: invalid reference: '$stmt.list' test.y:31.11-32.63: symbol not found in production: stmt test.y:31.40-43: possibly meant: $then, hiding $[stmt.list] at $4 test.y:31.61-64: possibly meant: $else, hiding $[stmt.list] at $6 -test.y:34.43-58: invalid reference: '$stmt.list.field' +test.y:34.43-58: error: invalid reference: '$stmt.list.field' test.y:33.11-34.69: symbol not found in production: stmt test.y:33.40-43: possibly meant: $then.field, hiding $[stmt.list].field at $4 test.y:33.61-64: possibly meant: $else.field, hiding $[stmt.list].field at $6 -test.y:36.43-54: invalid reference: '$[stmt.list]' +test.y:36.43-54: error: invalid reference: '$[stmt.list]' test.y:35.11-36.71: symbol not found in production: stmt.list test.y:35.40-43: possibly meant: $then, hiding $[stmt.list] at $4 test.y:35.61-64: possibly meant: $else, hiding $[stmt.list] at $6 -test.y:38.43-49: invalid reference: '$then.1' +test.y:38.43-49: error: invalid reference: '$then.1' test.y:37.11-38.60: symbol not found in production: then test.y:37.40-45: possibly meant: $[then.1] at $4 -test.y:40.43-55: invalid reference: '$then.1.field' +test.y:40.43-55: error: invalid reference: '$then.1.field' test.y:39.11-40.66: symbol not found in production: then test.y:39.40-45: possibly meant: $[then.1].field at $4 -test.y:42.44-50: invalid reference: '$stmt.x' +test.y:42.44-50: error: invalid reference: '$stmt.x' test.y:41.12-42.57: symbol not found in production: stmt test.y:41.36-41: possibly meant: $[stmt.x].x, hiding $stmt.x at $4 test.y:41.36-41: possibly meant: $[stmt.x] at $4 -test.y:44.13-22: invalid reference: '$if-stmt-a' +test.y:44.13-22: error: invalid reference: '$if-stmt-a' test.y:43.12-44.59: symbol not found in production: if test.y:43.1-9: possibly meant: $[if-stmt-a] at $$ -test.y:46.46-54: invalid reference: '$then-a.f' +test.y:46.46-54: error: invalid reference: '$then-a.f' test.y:45.12-46.65: symbol not found in production: then test.y:45.41-46: possibly meant: $[then-a].f at $4 ]]) @@ -405,7 +405,7 @@ start: foo[] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.12: an identifier expected +[[test.y:11.12: error: an identifier expected ]]) AT_CLEANUP @@ -419,7 +419,7 @@ start: foo[ a d ] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.15: unexpected identifier in bracketed name: 'd' +[[test.y:11.15: error: unexpected identifier in bracketed name: 'd' ]]) AT_CLEANUP @@ -433,7 +433,7 @@ start: foo[/* comment */] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.25: an identifier expected +[[test.y:11.25: error: an identifier expected ]]) AT_CLEANUP @@ -443,19 +443,14 @@ AT_SETUP([Stray symbols in brackets]) AT_DATA_GRAMMAR([test.y], [[ %% -start: foo[ /* aaa */ *&-.+\000\001\002\377 ] bar +start: foo[ % /* aaa */ *&-.+\000\001\002\377 ] bar { s = $foo; } ]]) AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' test.y || exit 77]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.23: invalid character in bracketed name: '*' -test.y:11.24: invalid character in bracketed name: '&' -test.y:11.25: invalid character in bracketed name: '-' -test.y:11.27: invalid character in bracketed name: '+' -test.y:11.28: invalid character in bracketed name: '\0' -test.y:11.28: invalid character in bracketed name: '\001' -test.y:11.28: invalid character in bracketed name: '\002' -test.y:11.28: invalid character in bracketed name: '\377' +[[test.y:11.13: error: invalid character in bracketed name: '%' +test.y:11.25-27: error: invalid characters in bracketed name: '*&-' +test.y:11.29-30: error: invalid characters in bracketed name: '+\0\001\002\377' ]]) AT_CLEANUP @@ -468,7 +463,7 @@ AT_DATA_GRAMMAR([test.y], start[a s]: foo; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.9: unexpected identifier in bracketed name: 's' +[[test.y:11.9: error: unexpected identifier in bracketed name: 's' ]]) AT_CLEANUP @@ -515,37 +510,37 @@ sym_a: 'a'; sym_b: 'b'; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:12.22-31: invalid reference: '$sym.field' +[[test.y:12.22-31: error: invalid reference: '$sym.field' test.y:12.3-35: symbol not found in production: sym -test.y:13.22-35: invalid reference: '$sym.field' +test.y:13.22-35: error: invalid reference: '$sym.field' test.y:13.3-39: symbol not found in production: sym -test.y:14.22-33: invalid reference: '$[sym.field]' +test.y:14.22-33: error: invalid reference: '$[sym.field]' test.y:14.3-37: symbol not found in production: sym.field -test.y:15.22-37: invalid reference: '$[sym.field]' +test.y:15.22-37: error: invalid reference: '$[sym.field]' test.y:15.3-41: symbol not found in production: sym.field -test.y:16.22-25: invalid reference: '$sym' +test.y:16.22-25: error: invalid reference: '$sym' test.y:16.3-29: symbol not found in production: sym -test.y:17.22-29: invalid reference: '$sym' +test.y:17.22-29: error: invalid reference: '$sym' test.y:17.3-33: symbol not found in production: sym -test.y:18.22-27: invalid reference: '$[sym]' +test.y:18.22-27: error: invalid reference: '$[sym]' test.y:18.3-65: symbol not found in production before $3: sym -test.y:18.52-61: invalid reference: '$[sym]' +test.y:18.52-61: error: invalid reference: '$[sym]' test.y:18.3-65: symbol not found in production: sym -test.y:22.22-31: invalid reference: '$sym-field' +test.y:22.22-31: error: invalid reference: '$sym-field' test.y:22.3-35: symbol not found in production: sym -test.y:23.22-35: invalid reference: '$sym-field' +test.y:23.22-35: error: invalid reference: '$sym-field' test.y:23.3-39: symbol not found in production: sym -test.y:24.22-33: invalid reference: '$[sym-field]' +test.y:24.22-33: error: invalid reference: '$[sym-field]' test.y:24.3-37: symbol not found in production: sym-field -test.y:25.22-37: invalid reference: '$[sym-field]' +test.y:25.22-37: error: invalid reference: '$[sym-field]' test.y:25.3-41: symbol not found in production: sym-field -test.y:26.22-25: invalid reference: '$sym' +test.y:26.22-25: error: invalid reference: '$sym' test.y:26.3-29: symbol not found in production: sym -test.y:27.22-29: invalid reference: '$sym' +test.y:27.22-29: error: invalid reference: '$sym' test.y:27.3-33: symbol not found in production: sym -test.y:28.22-27: invalid reference: '$[sym]' +test.y:28.22-27: error: invalid reference: '$[sym]' test.y:28.3-65: symbol not found in production before $3: sym -test.y:28.52-61: invalid reference: '$[sym]' +test.y:28.52-61: error: invalid reference: '$[sym]' test.y:28.3-65: symbol not found in production: sym ]]) AT_CLEANUP @@ -563,10 +558,10 @@ start: .field: ; ]]) AT_BISON_CHECK([[test.y]], [[1]], [], -[[test.y:4.12-18: invalid reference: '$.field' +[[test.y:4.12-18: error: invalid reference: '$.field' test.y:4.13: syntax error after '$', expecting integer, letter, '_', '@<:@', or '$' test.y:4.3-8: possibly meant: $[.field] at $1 -test.y:5.12-18: invalid reference: '@.field' +test.y:5.12-18: error: invalid reference: '@.field' test.y:5.13: syntax error after '@', expecting integer, letter, '_', '@<:@', or '$' ]]) AT_DATA([[test.y]], diff --git a/tests/output.at b/tests/output.at index f7a7d8e5..657903a5 100644 --- a/tests/output.at +++ b/tests/output.at @@ -171,7 +171,7 @@ AT_CHECK_CONFLICTING_OUTPUT([foo.y], ]) AT_CHECK_CONFLICTING_OUTPUT([foo.y], [], [-o foo.y], -[foo.y: refusing to overwrite the input file 'foo.y' +[foo.y: error: refusing to overwrite the input file 'foo.y' ], 1) @@ -231,3 +231,368 @@ AT_CHECK_OUTPUT_FILE_NAME([[@{]]) AT_CHECK_OUTPUT_FILE_NAME([[@}]]) AT_CHECK_OUTPUT_FILE_NAME([[@<:@]]) AT_CHECK_OUTPUT_FILE_NAME([[@:>@]]) + + +# AT_TEST(SETUP-NAME, GRAMMAR, DOT-BODY) +# -------------------------------------- +# Check that the DOT graph for GRAMMAR is DOT-BODY. +m4_pushdef([AT_TEST], +[AT_SETUP([$1]) +AT_KEYWORDS([[graph]]) +AT_DATA([[input.y]], [$2]) +AT_BISON_CHECK([[-rall --graph input.y]], [0], [[]], [[ignore]]) +AT_CHECK([[grep -v // input.dot]], [0], +[[ +digraph "input.y" +{ + node [fontname = courier, shape = box, colorscheme = paired6] + edge [fontname = courier] + ]$3[} +]]) +AT_CLEANUP +]) + + +## ------------------------ ## +## Graph with no conflicts. ## +## ------------------------ ## + +AT_TEST([Graph with no conflicts], +[[%% +exp: a '?' b; +a: ; +b: 'b'; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . a '?' b\l 2 a: .\l"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> "0R2" [style=solid] + "0R2" [label="R2", fillcolor=3, shape=diamond, style=filled] + 1 [label="State 1\n\l 0 $accept: exp . $end\l"] + 1 -> 3 [style=solid label="$end"] + 2 [label="State 2\n\l 1 exp: a . '?' b\l"] + 2 -> 4 [style=solid label="'?'"] + 3 [label="State 3\n\l 0 $accept: exp $end .\l"] + 3 -> "3R0" [style=solid] + "3R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] + 4 [label="State 4\n\l 1 exp: a '?' . b\l 3 b: . 'b'\l"] + 4 -> 5 [style=solid label="'b'"] + 4 -> 6 [style=dashed label="b"] + 5 [label="State 5\n\l 3 b: 'b' .\l"] + 5 -> "5R3" [style=solid] + "5R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 6 [label="State 6\n\l 1 exp: a '?' b .\l"] + 6 -> "6R1" [style=solid] + "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled] +]]) + +## ------------------------ ## +## Graph with unsolved S/R. ## +## ------------------------ ## + +AT_TEST([Graph with unsolved S/R], +[[%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . ['b']\l 9 empty_c: . ['c']\l"] + 0 -> 1 [style=solid label="'a'"] + 0 -> 2 [style=solid label="'b'"] + 0 -> 3 [style=solid label="'c'"] + 0 -> 4 [style=dashed label="start"] + 0 -> 5 [style=dashed label="empty_a"] + 0 -> 6 [style=dashed label="empty_b"] + 0 -> 7 [style=dashed label="empty_c"] + 0 -> "0R7d" [label="['a']", style=solid] + "0R7d" [label="R7", fillcolor=5, shape=diamond, style=filled] + 0 -> "0R8d" [label="['b']", style=solid] + "0R8d" [label="R8", fillcolor=5, shape=diamond, style=filled] + 0 -> "0R9d" [label="['c']", style=solid] + "0R9d" [label="R9", fillcolor=5, shape=diamond, style=filled] + 1 [label="State 1\n\l 1 start: 'a' .\l"] + 1 -> "1R1" [style=solid] + "1R1" [label="R1", fillcolor=3, shape=diamond, style=filled] + 2 [label="State 2\n\l 3 start: 'b' .\l"] + 2 -> "2R3" [style=solid] + "2R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 3 [label="State 3\n\l 5 start: 'c' .\l"] + 3 -> "3R5" [style=solid] + "3R5" [label="R5", fillcolor=3, shape=diamond, style=filled] + 4 [label="State 4\n\l 0 $accept: start . $end\l"] + 4 -> 8 [style=solid label="$end"] + 5 [label="State 5\n\l 2 start: empty_a . 'a'\l"] + 5 -> 9 [style=solid label="'a'"] + 6 [label="State 6\n\l 4 start: empty_b . 'b'\l"] + 6 -> 10 [style=solid label="'b'"] + 7 [label="State 7\n\l 6 start: empty_c . 'c'\l"] + 7 -> 11 [style=solid label="'c'"] + 8 [label="State 8\n\l 0 $accept: start $end .\l"] + 8 -> "8R0" [style=solid] + "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] + 9 [label="State 9\n\l 2 start: empty_a 'a' .\l"] + 9 -> "9R2" [style=solid] + "9R2" [label="R2", fillcolor=3, shape=diamond, style=filled] + 10 [label="State 10\n\l 4 start: empty_b 'b' .\l"] + 10 -> "10R4" [style=solid] + "10R4" [label="R4", fillcolor=3, shape=diamond, style=filled] + 11 [label="State 11\n\l 6 start: empty_c 'c' .\l"] + 11 -> "11R6" [style=solid] + "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled] +]]) + +## ---------------------- ## +## Graph with solved S/R. ## +## ---------------------- ## + +AT_TEST([Graph with solved S/R], +[[%left 'a' +%right 'b' +%right 'c' +%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . []\l 9 empty_c: . []\l"] + 0 -> 1 [style=solid label="'b'"] + 0 -> 2 [style=solid label="'c'"] + 0 -> 3 [style=dashed label="start"] + 0 -> 4 [style=dashed label="empty_a"] + 0 -> 5 [style=dashed label="empty_b"] + 0 -> 6 [style=dashed label="empty_c"] + 0 -> "0R7" [style=solid] + "0R7" [label="R7", fillcolor=3, shape=diamond, style=filled] + 1 [label="State 1\n\l 3 start: 'b' .\l"] + 1 -> "1R3" [style=solid] + "1R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 2 [label="State 2\n\l 5 start: 'c' .\l"] + 2 -> "2R5" [style=solid] + "2R5" [label="R5", fillcolor=3, shape=diamond, style=filled] + 3 [label="State 3\n\l 0 $accept: start . $end\l"] + 3 -> 7 [style=solid label="$end"] + 4 [label="State 4\n\l 2 start: empty_a . 'a'\l"] + 4 -> 8 [style=solid label="'a'"] + 5 [label="State 5\n\l 4 start: empty_b . 'b'\l"] + 5 -> 9 [style=solid label="'b'"] + 6 [label="State 6\n\l 6 start: empty_c . 'c'\l"] + 6 -> 10 [style=solid label="'c'"] + 7 [label="State 7\n\l 0 $accept: start $end .\l"] + 7 -> "7R0" [style=solid] + "7R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] + 8 [label="State 8\n\l 2 start: empty_a 'a' .\l"] + 8 -> "8R2" [style=solid] + "8R2" [label="R2", fillcolor=3, shape=diamond, style=filled] + 9 [label="State 9\n\l 4 start: empty_b 'b' .\l"] + 9 -> "9R4" [style=solid] + "9R4" [label="R4", fillcolor=3, shape=diamond, style=filled] + 10 [label="State 10\n\l 6 start: empty_c 'c' .\l"] + 10 -> "10R6" [style=solid] + "10R6" [label="R6", fillcolor=3, shape=diamond, style=filled] +]]) + +## ---------------- ## +## Graph with R/R. ## +## ---------------- ## + +AT_TEST([Graph with R/R], +[[%% +exp: a | b; +a: ; +b: ; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . a\l 2 | . b\l 3 a: . [$end]\l 4 b: . [$end]\l"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 0 -> "0R3" [style=solid] + "0R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 0 -> "0R4d" [label="[$end]", style=solid] + "0R4d" [label="R4", fillcolor=5, shape=diamond, style=filled] + 1 [label="State 1\n\l 0 $accept: exp . $end\l"] + 1 -> 4 [style=solid label="$end"] + 2 [label="State 2\n\l 1 exp: a .\l"] + 2 -> "2R1" [style=solid] + "2R1" [label="R1", fillcolor=3, shape=diamond, style=filled] + 3 [label="State 3\n\l 2 exp: b .\l"] + 3 -> "3R2" [style=solid] + "3R2" [label="R2", fillcolor=3, shape=diamond, style=filled] + 4 [label="State 4\n\l 0 $accept: exp $end .\l"] + 4 -> "4R0" [style=solid] + "4R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] +]]) + +## ---------------------------------------- ## +## Graph with reductions with multiple LAT. ## +## ---------------------------------------- ## + +AT_TEST([Graph with reductions with multiple LAT], +[[%% +exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';'; +a: ; +b: ; +c: ; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . a ';'\l 2 | . a ';'\l 3 | . a '.'\l 4 | . b '?'\l 5 | . b '!'\l 6 | . c '?'\l 7 | . c ';'\l 8 a: . [';', '.']\l 9 b: . ['?', '!']\l 10 c: . [';', '?']\l"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 0 -> 4 [style=dashed label="c"] + 0 -> "0R8" [style=solid] + "0R8" [label="R8", fillcolor=3, shape=diamond, style=filled] + 0 -> "0R9" [label="['?', '!']", style=solid] + "0R9" [label="R9", fillcolor=3, shape=diamond, style=filled] + 0 -> "0R10d" [label="[';', '?']", style=solid] + "0R10d" [label="R10", fillcolor=5, shape=diamond, style=filled] + 1 [label="State 1\n\l 0 $accept: exp . $end\l"] + 1 -> 5 [style=solid label="$end"] + 2 [label="State 2\n\l 1 exp: a . ';'\l 2 | a . ';'\l 3 | a . '.'\l"] + 2 -> 6 [style=solid label="';'"] + 2 -> 7 [style=solid label="'.'"] + 3 [label="State 3\n\l 4 exp: b . '?'\l 5 | b . '!'\l"] + 3 -> 8 [style=solid label="'?'"] + 3 -> 9 [style=solid label="'!'"] + 4 [label="State 4\n\l 6 exp: c . '?'\l 7 | c . ';'\l"] + 4 -> 10 [style=solid label="';'"] + 4 -> 11 [style=solid label="'?'"] + 5 [label="State 5\n\l 0 $accept: exp $end .\l"] + 5 -> "5R0" [style=solid] + "5R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] + 6 [label="State 6\n\l 1 exp: a ';' . [$end]\l 2 | a ';' . [$end]\l"] + 6 -> "6R1" [style=solid] + "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled] + 6 -> "6R2d" [label="[$end]", style=solid] + "6R2d" [label="R2", fillcolor=5, shape=diamond, style=filled] + 7 [label="State 7\n\l 3 exp: a '.' .\l"] + 7 -> "7R3" [style=solid] + "7R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 8 [label="State 8\n\l 4 exp: b '?' .\l"] + 8 -> "8R4" [style=solid] + "8R4" [label="R4", fillcolor=3, shape=diamond, style=filled] + 9 [label="State 9\n\l 5 exp: b '!' .\l"] + 9 -> "9R5" [style=solid] + "9R5" [label="R5", fillcolor=3, shape=diamond, style=filled] + 10 [label="State 10\n\l 7 exp: c ';' .\l"] + 10 -> "10R7" [style=solid] + "10R7" [label="R7", fillcolor=3, shape=diamond, style=filled] + 11 [label="State 11\n\l 6 exp: c '?' .\l"] + 11 -> "11R6" [style=solid] + "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled] +]]) + +## ------------------------------------------------------ ## +## Graph with a reduction rule both enabled and disabled. ## +## ------------------------------------------------------ ## + +AT_TEST([Graph with a reduction rule both enabled and disabled], +[[%% +exp: ifexp | opexp | imm; +ifexp: "if" exp "then" exp elseexp; +elseexp: "else" exp | ; +opexp: exp '+' exp; +imm: '0'; +]], +[[ + 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 0 -> 1 [style=solid label="\"if\""] + 0 -> 2 [style=solid label="'0'"] + 0 -> 3 [style=dashed label="exp"] + 0 -> 4 [style=dashed label="ifexp"] + 0 -> 5 [style=dashed label="opexp"] + 0 -> 6 [style=dashed label="imm"] + 1 [label="State 1\n\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" . exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 1 -> 1 [style=solid label="\"if\""] + 1 -> 2 [style=solid label="'0'"] + 1 -> 7 [style=dashed label="exp"] + 1 -> 4 [style=dashed label="ifexp"] + 1 -> 5 [style=dashed label="opexp"] + 1 -> 6 [style=dashed label="imm"] + 2 [label="State 2\n\l 8 imm: '0' .\l"] + 2 -> "2R8" [style=solid] + "2R8" [label="R8", fillcolor=3, shape=diamond, style=filled] + 3 [label="State 3\n\l 0 $accept: exp . $end\l 7 opexp: exp . '+' exp\l"] + 3 -> 8 [style=solid label="$end"] + 3 -> 9 [style=solid label="'+'"] + 4 [label="State 4\n\l 1 exp: ifexp .\l"] + 4 -> "4R1" [style=solid] + "4R1" [label="R1", fillcolor=3, shape=diamond, style=filled] + 5 [label="State 5\n\l 2 exp: opexp .\l"] + 5 -> "5R2" [style=solid] + "5R2" [label="R2", fillcolor=3, shape=diamond, style=filled] + 6 [label="State 6\n\l 3 exp: imm .\l"] + 6 -> "6R3" [style=solid] + "6R3" [label="R3", fillcolor=3, shape=diamond, style=filled] + 7 [label="State 7\n\l 4 ifexp: \"if\" exp . \"then\" exp elseexp\l 7 opexp: exp . '+' exp\l"] + 7 -> 10 [style=solid label="\"then\""] + 7 -> 9 [style=solid label="'+'"] + 8 [label="State 8\n\l 0 $accept: exp $end .\l"] + 8 -> "8R0" [style=solid] + "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] + 9 [label="State 9\n\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 7 | exp '+' . exp\l 8 imm: . '0'\l"] + 9 -> 1 [style=solid label="\"if\""] + 9 -> 2 [style=solid label="'0'"] + 9 -> 11 [style=dashed label="exp"] + 9 -> 4 [style=dashed label="ifexp"] + 9 -> 5 [style=dashed label="opexp"] + 9 -> 6 [style=dashed label="imm"] + 10 [label="State 10\n\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" exp \"then\" . exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 10 -> 1 [style=solid label="\"if\""] + 10 -> 2 [style=solid label="'0'"] + 10 -> 12 [style=dashed label="exp"] + 10 -> 4 [style=dashed label="ifexp"] + 10 -> 5 [style=dashed label="opexp"] + 10 -> 6 [style=dashed label="imm"] + 11 [label="State 11\n\l 7 opexp: exp . '+' exp\l 7 | exp '+' exp . [$end, \"then\", \"else\", '+']\l"] + 11 -> 9 [style=solid label="'+'"] + 11 -> "11R7d" [label="['+']", style=solid] + "11R7d" [label="R7", fillcolor=5, shape=diamond, style=filled] + 11 -> "11R7" [style=solid] + "11R7" [label="R7", fillcolor=3, shape=diamond, style=filled] + 12 [label="State 12\n\l 4 ifexp: \"if\" exp \"then\" exp . elseexp\l 5 elseexp: . \"else\" exp\l 6 | . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 12 -> 13 [style=solid label="\"else\""] + 12 -> 9 [style=solid label="'+'"] + 12 -> 14 [style=dashed label="elseexp"] + 12 -> "12R6d" [label="[\"else\", '+']", style=solid] + "12R6d" [label="R6", fillcolor=5, shape=diamond, style=filled] + 12 -> "12R6" [style=solid] + "12R6" [label="R6", fillcolor=3, shape=diamond, style=filled] + 13 [label="State 13\n\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 5 elseexp: \"else\" . exp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 13 -> 1 [style=solid label="\"if\""] + 13 -> 2 [style=solid label="'0'"] + 13 -> 15 [style=dashed label="exp"] + 13 -> 4 [style=dashed label="ifexp"] + 13 -> 5 [style=dashed label="opexp"] + 13 -> 6 [style=dashed label="imm"] + 14 [label="State 14\n\l 4 ifexp: \"if\" exp \"then\" exp elseexp .\l"] + 14 -> "14R4" [style=solid] + "14R4" [label="R4", fillcolor=3, shape=diamond, style=filled] + 15 [label="State 15\n\l 5 elseexp: \"else\" exp . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 15 -> 9 [style=solid label="'+'"] + 15 -> "15R5d" [label="['+']", style=solid] + "15R5d" [label="R5", fillcolor=5, shape=diamond, style=filled] + 15 -> "15R5" [style=solid] + "15R5" [label="R5", fillcolor=3, shape=diamond, style=filled] +]]) + +m4_popdef([AT_TEST]) diff --git a/tests/push.at b/tests/push.at index d2c09263..1b993971 100644 --- a/tests/push.at +++ b/tests/push.at @@ -153,7 +153,7 @@ start: ; AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[input.y]], [[1]], [], -[[input.y:2.9-21: %define variable 'api.push-pull' is not used +[[input.y:2.9-21: error: %define variable 'api.push-pull' is not used ]]) AT_CLEANUP diff --git a/tests/reduce.at b/tests/reduce.at index c528eed8..bf43bf9d 100644 --- a/tests/reduce.at +++ b/tests/reduce.at @@ -437,7 +437,7 @@ dnl BISON-STDERR [], dnl TABLES -[[state 0 +[[State 0 0 $accept: . S $end 1 S: . 'a' A 'a' @@ -451,7 +451,7 @@ dnl TABLES S go to state 4 -state 1 +State 1 1 S: 'a' . A 'a' 4 A: . 'a' 'a' @@ -462,7 +462,7 @@ state 1 A go to state 6 -state 2 +State 2 2 S: 'b' . A 'b' 4 A: . 'a' 'a' @@ -473,7 +473,7 @@ state 2 A go to state 7 -state 3 +State 3 3 S: 'c' . c 4 A: . 'a' 'a' @@ -487,14 +487,14 @@ state 3 c go to state 10 -state 4 +State 4 0 $accept: S . $end $end shift, and go to state 11 -state 5 +State 5 4 A: 'a' . 'a' 5 | 'a' . ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[ @@ -505,21 +505,21 @@ state 5 Conflict between rule 5 and token 'a' resolved as reduce (%left 'a'). -state 6 +State 6 1 S: 'a' A . 'a' 'a' shift, and go to state 13 -state 7 +State 7 2 S: 'b' A . 'b' 'b' shift, and go to state 14 -state 8 +State 8 4 A: 'a' . 'a' 5 | 'a' . [$end] @@ -533,7 +533,7 @@ state 8 [[$default]])[ reduce using rule 5 (A) -state 9 +State 9 7 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -541,7 +541,7 @@ state 9 [[$default]])[ reduce using rule 7 (c) -state 10 +State 10 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -549,14 +549,14 @@ state 10 [[$default]])[ reduce using rule 3 (S) -state 11 +State 11 0 $accept: S $end . $default accept -state 12 +State 12 4 A: 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[ @@ -564,7 +564,7 @@ state 12 [[$default]])[ reduce using rule 4 (A) -state 13 +State 13 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -572,7 +572,7 @@ state 13 [[$default]])[ reduce using rule 1 (S) -state 14 +State 14 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -580,7 +580,7 @@ state 14 [[$default]])[ reduce using rule 2 (S) -state 15 +State 15 6 c: 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -589,7 +589,7 @@ state 15 [[]], [[ -state 16 +State 16 4 A: 'a' . 'a' 5 | 'a' . ['b'] @@ -601,14 +601,14 @@ state 16 [[$default]])[ reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[ -state 17 +State 17 4 A: 'a' 'a' . [$end] $end reduce using rule 4 (A) -state 18 +State 18 4 A: 'a' 'a' . ['b'] @@ -653,7 +653,7 @@ dnl BISON-STDERR [], dnl TABLES -[[state 0 +[[State 0 0 $accept: . S $end 1 S: . 'a' A 'a' @@ -667,7 +667,7 @@ dnl TABLES S go to state 4 -state 1 +State 1 1 S: 'a' . A 'a' 4 A: . 'a' 'a' 'a' @@ -678,7 +678,7 @@ state 1 A go to state 6 -state 2 +State 2 2 S: 'b' . A 'b' 4 A: . 'a' 'a' 'a' @@ -689,7 +689,7 @@ state 2 A go to state 7 -state 3 +State 3 3 S: 'c' . c 4 A: . 'a' 'a' 'a' @@ -703,14 +703,14 @@ state 3 c go to state 10 -state 4 +State 4 0 $accept: S . $end $end shift, and go to state 11 -state 5 +State 5 4 A: 'a' . 'a' 'a' 5 | 'a' . 'a' @@ -718,21 +718,21 @@ state 5 'a' shift, and go to state 12 -state 6 +State 6 1 S: 'a' A . 'a' 'a' shift, and go to state 13 -state 7 +State 7 2 S: 'b' A . 'b' 'b' shift, and go to state 14 -state 8 +State 8 4 A: 'a' . 'a' 'a' 5 | 'a' . 'a' @@ -741,7 +741,7 @@ state 8 'a' shift, and go to state 15 -state 9 +State 9 7 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -749,7 +749,7 @@ state 9 [[$default]])[ reduce using rule 7 (c) -state 10 +State 10 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -757,14 +757,14 @@ state 10 [[$default]])[ reduce using rule 3 (S) -state 11 +State 11 0 $accept: S $end . $default accept -state 12 +State 12 4 A: 'a' 'a' . 'a' 5 | 'a' 'a' . ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[ @@ -775,7 +775,7 @@ state 12 Conflict between rule 5 and token 'a' resolved as reduce (%left 'a'). -state 13 +State 13 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -783,7 +783,7 @@ state 13 [[$default]])[ reduce using rule 1 (S) -state 14 +State 14 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -791,7 +791,7 @@ state 14 [[$default]])[ reduce using rule 2 (S) -state 15 +State 15 4 A: 'a' 'a' . 'a' 5 | 'a' 'a' . [$end] @@ -805,7 +805,7 @@ state 15 [[$default]])[ reduce using rule 5 (A) -state 16 +State 16 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[ @@ -813,7 +813,7 @@ state 16 [[$default]])[ reduce using rule 4 (A) -state 17 +State 17 6 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -822,7 +822,7 @@ state 17 [[]], [[ -state 18 +State 18 4 A: 'a' . 'a' 'a' 5 | 'a' . 'a' @@ -831,7 +831,7 @@ state 18 [[19]])[ -state 19]AT_COND_CASE([[canonical LR]], [[ +State 19]AT_COND_CASE([[canonical LR]], [[ 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -839,7 +839,7 @@ state 19]AT_COND_CASE([[canonical LR]], [[ [[$default]])[ reduce using rule 4 (A) -state 20]])[ +State 20]])[ 4 A: 'a' 'a' . 'a' 5 | 'a' 'a' . ['b'] @@ -851,7 +851,7 @@ state 20]])[ [[$default]])[ reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[ -state 21 +State 21 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['b']]])[ @@ -900,7 +900,7 @@ dnl BISON-STDERR [], dnl TABLES -[[state 0 +[[State 0 0 $accept: . S $end 1 S: . 'a' A 'a' @@ -914,7 +914,7 @@ dnl TABLES S go to state 4 -state 1 +State 1 1 S: 'a' . A 'a' 4 A: . 'a' 'a' B @@ -924,7 +924,7 @@ state 1 A go to state 6 -state 2 +State 2 2 S: 'b' . A 'b' 4 A: . 'a' 'a' B @@ -934,7 +934,7 @@ state 2 A go to state 7 -state 3 +State 3 3 S: 'c' . c 4 A: . 'a' 'a' B @@ -947,35 +947,35 @@ state 3 c go to state 10 -state 4 +State 4 0 $accept: S . $end $end shift, and go to state 11 -state 5 +State 5 4 A: 'a' . 'a' B 'a' shift, and go to state 12 -state 6 +State 6 1 S: 'a' A . 'a' 'a' shift, and go to state 13 -state 7 +State 7 2 S: 'b' A . 'b' 'b' shift, and go to state 14 -state 8 +State 8 4 A: 'a' . 'a' B 7 c: 'a' . 'a' 'b' @@ -983,7 +983,7 @@ state 8 'a' shift, and go to state 15 -state 9 +State 9 8 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -991,7 +991,7 @@ state 9 [[$default]])[ reduce using rule 8 (c) -state 10 +State 10 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -999,14 +999,14 @@ state 10 [[$default]])[ reduce using rule 3 (S) -state 11 +State 11 0 $accept: S $end . $default accept -state 12 +State 12 4 A: 'a' 'a' . B 5 B: . 'a' @@ -1020,7 +1020,7 @@ state 12 Conflict between rule 6 and token 'a' resolved as reduce (%left 'a'). -state 13 +State 13 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1028,7 +1028,7 @@ state 13 [[$default]])[ reduce using rule 1 (S) -state 14 +State 14 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1036,7 +1036,7 @@ state 14 [[$default]])[ reduce using rule 2 (S) -state 15 +State 15 4 A: 'a' 'a' . B 5 B: . 'a' @@ -1053,7 +1053,7 @@ state 15 B go to state ]AT_COND_CASE([[canonical LR]], [[21]], [[17]])[ -state 16 +State 16 5 B: 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[ @@ -1061,7 +1061,7 @@ state 16 [[$default]])[ reduce using rule 5 (B) -state 17 +State 17 4 A: 'a' 'a' B .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[ @@ -1069,7 +1069,7 @@ state 17 [[$default]])[ reduce using rule 4 (A) -state 18 +State 18 7 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1077,7 +1077,7 @@ state 18 [[$default]])[ reduce using rule 7 (c)]AT_COND_CASE([[LALR]], [], [[ -state 19 +State 19 4 A: 'a' . 'a' B @@ -1085,21 +1085,21 @@ state 19 [[20]])[ -state 20]AT_COND_CASE([[canonical LR]], [[ +State 20]AT_COND_CASE([[canonical LR]], [[ 5 B: 'a' . [$end] $end reduce using rule 5 (B) -state 21 +State 21 4 A: 'a' 'a' B . [$end] $end reduce using rule 4 (A) -state 22]])[ +State 22]])[ 4 A: 'a' 'a' . B 5 B: . 'a' @@ -1114,14 +1114,14 @@ state 22]])[ B go to state ]AT_COND_CASE([[canonical LR]], [[24 -state 23 +State 23 5 B: 'a' . ['b'] 'b' reduce using rule 5 (B) -state 24 +State 24 4 A: 'a' 'a' B . ['b'] @@ -1195,7 +1195,7 @@ dnl BISON-STDERR ]], [])], dnl TABLES -[[state 0 +[[State 0 0 $accept: . S $end 1 S: . 'a' A 'f' @@ -1213,7 +1213,7 @@ dnl TABLES S go to state 4 -state 1 +State 1 1 S: 'a' . A 'f' 2 | 'a' . B @@ -1226,7 +1226,7 @@ state 1 B go to state 7 -state 2 +State 2 3 S: 'b' . A 'f' 4 | 'b' . B 'g' @@ -1240,7 +1240,7 @@ state 2 B go to state 10 -state 3 +State 3 6 S: 'c' . 'c' A 'g' 7 | 'c' . 'c' B @@ -1248,14 +1248,14 @@ state 3 'c' shift, and go to state 11 -state 4 +State 4 0 $accept: S . $end $end shift, and go to state 12 -state 5 +State 5 8 A: 'd' . 'e' 9 B: 'd' . 'e' @@ -1265,14 +1265,14 @@ state 5 [[20]])[ -state 6 +State 6 1 S: 'a' A . 'f' 'f' shift, and go to state 14 -state 7 +State 7 2 S: 'a' B .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1280,7 +1280,7 @@ state 7 [[$default]])[ reduce using rule 2 (S) -state 8 +State 8 5 S: 'b' 'd' . [$end] 8 A: 'd' . 'e' @@ -1293,21 +1293,21 @@ state 8 [[$default]])[ reduce using rule 5 (S) -state 9 +State 9 3 S: 'b' A . 'f' 'f' shift, and go to state 15 -state 10 +State 10 4 S: 'b' B . 'g' 'g' shift, and go to state 16 -state 11 +State 11 6 S: 'c' 'c' . A 'g' 7 | 'c' 'c' . B @@ -1321,14 +1321,14 @@ state 11 B go to state 18 -state 12 +State 12 0 $accept: S $end . $default accept]AT_COND_CASE([[LALR]], [[ -state 13 +State 13 8 A: 'd' 'e' . ['f', 'g'] 9 B: 'd' 'e' . [$end, 'g'] @@ -1339,7 +1339,7 @@ state 13 $default reduce using rule 8 (A)]], [[ -state 13 +State 13 8 A: 'd' 'e' . ['f'] 9 B: 'd' 'e' . ]AT_COND_CASE([[canonical LR]], [[[$end]]], [[['g']]])[ @@ -1350,7 +1350,7 @@ state 13 [[$default]])[ reduce using rule 8 (A)]])[ -state 14 +State 14 1 S: 'a' A 'f' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1358,7 +1358,7 @@ state 14 [[$default]])[ reduce using rule 1 (S) -state 15 +State 15 3 S: 'b' A 'f' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1366,7 +1366,7 @@ state 15 [[$default]])[ reduce using rule 3 (S) -state 16 +State 16 4 S: 'b' B 'g' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1374,14 +1374,14 @@ state 16 [[$default]])[ reduce using rule 4 (S) -state 17 +State 17 6 S: 'c' 'c' A . 'g' 'g' shift, and go to state 19 -state 18 +State 18 7 S: 'c' 'c' B .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1389,7 +1389,7 @@ state 18 [[$default]])[ reduce using rule 7 (S) -state 19 +State 19 6 S: 'c' 'c' A 'g' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[ @@ -1398,7 +1398,7 @@ state 19 [[]], [[ -state 20]AT_COND_CASE([[canonical LR]], [[ +State 20]AT_COND_CASE([[canonical LR]], [[ 8 A: 'd' 'e' . ['f'] 9 B: 'd' 'e' . ['g'] @@ -1407,7 +1407,7 @@ state 20]AT_COND_CASE([[canonical LR]], [[ 'g' reduce using rule 9 (B) -state 21 +State 21 8 A: 'd' . 'e' 9 B: 'd' . 'e' @@ -1415,7 +1415,7 @@ state 21 'e' shift, and go to state 22 -state 22 +State 22 8 A: 'd' 'e' . ['g'] 9 B: 'd' 'e' . [$end] @@ -1491,7 +1491,7 @@ c: ; ]], dnl Visit each state mentioned above. [['a', 'a']], -[[state 0 +[[State 0 0 $accept: . start $end 1 start: . a b @@ -1505,7 +1505,7 @@ dnl Visit each state mentioned above. a go to state 3 -state 1 +State 1 4 a: 'a' .]AT_COND_CASE([[accepting]], [[ [$end, 'a', 'b'] @@ -1516,14 +1516,14 @@ state 1 $default reduce using rule 4 (a)]])[ -state 2 +State 2 0 $accept: start . $end $end shift, and go to state 4 -state 3 +State 3 1 start: a . b 2 | a . b 'a' @@ -1542,14 +1542,14 @@ state 3 c go to state 6 -state 4 +State 4 0 $accept: start $end . $default accept -state 5 +State 5 1 start: a b . [$end] 2 | a b . 'a' @@ -1560,14 +1560,14 @@ state 5 [[$end]])[ reduce using rule 1 (start) -state 6 +State 6 3 start: a c . 'b' 'b' shift, and go to state 8 -state 7 +State 7 2 start: a b 'a' .]AT_COND_CASE([[accepting]], [[ [$end] @@ -1576,7 +1576,7 @@ state 7 $default reduce using rule 2 (start)]])[ -state 8 +State 8 3 start: a c 'b' .]AT_COND_CASE([[accepting]], [[ [$end] diff --git a/tests/regression.at b/tests/regression.at index 03c4b808..3fa20e27 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -293,7 +293,7 @@ $@2 (9) on left: 3, on right: 4 -state 0 +State 0 0 $accept: . expr $end @@ -305,7 +305,7 @@ state 0 $@2 go to state 3 -state 1 +State 1 2 expr: 'a' . $@1 'b' @@ -314,42 +314,42 @@ state 1 $@1 go to state 4 -state 2 +State 2 0 $accept: expr . $end $end shift, and go to state 5 -state 3 +State 3 4 expr: $@2 . 'c' 'c' shift, and go to state 6 -state 4 +State 4 2 expr: 'a' $@1 . 'b' 'b' shift, and go to state 7 -state 5 +State 5 0 $accept: expr $end . $default accept -state 6 +State 6 4 expr: $@2 'c' . $default reduce using rule 4 (expr) -state 7 +State 7 2 expr: 'a' $@1 'b' . @@ -383,6 +383,58 @@ AT_CLEANUP +## ---------------- ## +## Invalid inputs. ## +## ---------------- ## + + +AT_SETUP([Invalid inputs]) + +AT_DATA([input.y], +[[%% +? +default: 'a' } +%& +%a-does-not-exist +%- +%{ +]]) + +AT_BISON_CHECK([input.y], [1], [], +[[input.y:2.1: error: invalid character: '?' +input.y:3.14: error: invalid character: '}' +input.y:4.1: error: invalid character: '%' +input.y:4.2: error: invalid character: '&' +input.y:5.1-17: error: invalid directive: '%a-does-not-exist' +input.y:6.1: error: invalid character: '%' +input.y:6.2: error: invalid character: '-' +input.y:7.1-8.0: error: missing '%}' at end of file +input.y:7.1-8.0: error: syntax error, unexpected %{...%} +]]) + +AT_CLEANUP + + +AT_SETUP([Invalid inputs with {}]) + +AT_DATA([input.y], +[[ +%destructor +%initial-action +%lex-param +%parse-param +%printer +%union +]]) + +AT_BISON_CHECK([input.y], [1], [], +[[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...} +]]) + +AT_CLEANUP + + + ## ------------------- ## ## Token definitions. ## ## ------------------- ## @@ -546,7 +598,7 @@ $@1 (11) on left: 4, on right: 5 -state 0 +State 0 0 $accept: . CONST_DEC_PART $end @@ -558,14 +610,14 @@ state 0 $@1 go to state 4 -state 1 +State 1 0 $accept: CONST_DEC_PART . $end $end shift, and go to state 5 -state 2 +State 2 1 CONST_DEC_PART: CONST_DEC_LIST . 3 CONST_DEC_LIST: CONST_DEC_LIST . CONST_DEC @@ -577,56 +629,56 @@ state 2 $@1 go to state 4 -state 3 +State 3 2 CONST_DEC_LIST: CONST_DEC . $default reduce using rule 2 (CONST_DEC_LIST) -state 4 +State 4 5 CONST_DEC: $@1 . undef_id_tok '=' const_id_tok ';' undef_id_tok shift, and go to state 7 -state 5 +State 5 0 $accept: CONST_DEC_PART $end . $default accept -state 6 +State 6 3 CONST_DEC_LIST: CONST_DEC_LIST CONST_DEC . $default reduce using rule 3 (CONST_DEC_LIST) -state 7 +State 7 5 CONST_DEC: $@1 undef_id_tok . '=' const_id_tok ';' '=' shift, and go to state 8 -state 8 +State 8 5 CONST_DEC: $@1 undef_id_tok '=' . const_id_tok ';' const_id_tok shift, and go to state 9 -state 9 +State 9 5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok . ';' ';' shift, and go to state 10 -state 10 +State 10 5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';' . @@ -1073,8 +1125,8 @@ a: 'a' ; ]]) AT_BISON_CHECK([[--report=all input.y]]) -AT_CHECK([[sed -n '/^state 1$/,/^state 2$/p' input.output]], [[0]], -[[state 1 +AT_CHECK([[sed -n '/^State 1$/,/^State 2$/p' input.output]], [[0]], +[[State 1 2 start: 'a' . a 'a' 3 a: . 'a' @@ -1087,7 +1139,7 @@ AT_CHECK([[sed -n '/^state 1$/,/^state 2$/p' input.output]], [[0]], a go to state 5 -state 2 +State 2 ]]) AT_CLEANUP diff --git a/tests/sets.at b/tests/sets.at index 388ee099..4cbdfd62 100644 --- a/tests/sets.at +++ b/tests/sets.at @@ -287,7 +287,7 @@ mv stdout expout # Get the final state in the report, from the "accept" action.. AT_CHECK([sed -n ' - /^state \(.*\)/{ + /^State \(.*\)/{ s//final state \1/ x } diff --git a/tests/skeletons.at b/tests/skeletons.at index e23c3bb0..7b5b8f27 100644 --- a/tests/skeletons.at +++ b/tests/skeletons.at @@ -157,7 +157,7 @@ start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [[]], -[[: invalid value for %define Boolean variable 'foo' +[[: error: invalid value for %define Boolean variable 'foo' ]]) AT_CLEANUP @@ -193,8 +193,8 @@ start: ; AT_BISON_CHECK([[input1.y]], [[1]], [[]], [[input1.y: warning: foow fubar foow.y:2.3-5.3: warning: foowat fubar -input1.y: fooc fubar -fooc.y:1.1-10.5: foocat fubar +input1.y: error: fooc fubar +fooc.y:1.1-10.5: error: foocat fubar input1.y: fatal error: foof fubar ]]) @@ -264,7 +264,7 @@ start: ; ]]) AT_BISON_CHECK([[input1.y]], [[1]], [[]], -[[input1.y: non-fatal error +[[input1.y: error: non-fatal error input1.y: fatal error: M4 should exit immediately here ]]) diff --git a/tests/synclines.at b/tests/synclines.at index 63ae6858..751db7c6 100644 --- a/tests/synclines.at +++ b/tests/synclines.at @@ -47,7 +47,8 @@ m4_define([AT_SYNCLINES_COMPILE], # => # input.y:4: #error "8" # -# The message may include a caret-error: +# The message may include a caret-error (indented by GCC 4.8, +# not by clang 3.2): # # input.y:1:2: error: #error "1" # #error "1" @@ -63,13 +64,31 @@ m4_define([AT_SYNCLINES_COMPILE], # # distcc[35882] (dcc_connect_by_name) ERROR: failed to look up host "chrisimac": Unknown host # distcc[35882] Warning: failed to distribute input.c to chrisimac/4, running locally instead - +# +# The compiler might end by the number of messages issued (Clang 3.2): +# +# syncline.c:1:2: error: "1" +# #error "1" +# ^ +# 1 error generated. AT_CHECK([[$PERL -p -0777 - stderr <<\EOF + # 1. Remove useless lines. + + # distcc clutter. s/^distcc\[\d+\] .*\n//gm; - s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm; - s/^([^:]+:\d+):[^#]*( #error)/$][1:$][2/gm; + # Function context. s/^[^:]*: In function '[^']+':\n//gm; - s/^\ +#error.*\n\ *\^\n//gm; + # Caret error. + s/^ *#error.*\n *\^\n//gm; + # Number of errors. + s/^1 error generated\.\n//gm; + + # 2. Normalize the lines we kept. + + # Remove column. + s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm; + # Map all combinations of "error: " and "#error: " to "#error ". + s/^([^:]+:\d+):( |#error|error|:)+/$][1: #error /gm; EOF ]], 0, [stdout])