From: Akim Demaille Date: Thu, 8 Nov 2012 08:20:48 +0000 (+0100) Subject: Merge branch 'branch-2.6' into maint X-Git-Tag: v2.6.90~48 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/3ada39389411fa8a7739b3c855c88516463de594?hp=9d2423f55d24192abf52c69563fcaa7f8a961216 Merge branch 'branch-2.6' into maint * origin/branch-2.6: maint: post-release administrivia version 2.6.5 regen tests: syntax-check tests: beware of compilers that do not support POSIXLY_CORRECT gnulib: update Conflicts: NEWS src/parse-gram.c src/parse-gram.h --- diff --git a/NEWS b/NEWS index 59549b59..bb016bb3 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,54 @@ 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. + +** Graphviz improvements + + The graphical presentation of the states is more readable: their shape is + now rectangular, the state number is clearly displayed, and the items are + numbered and left-justified. + + The reductions are now explicitly represented as transitions to other + diamond shaped nodes. * Noteworthy changes in release 2.6.5 (2012-11-07) [stable] @@ -88,7 +136,7 @@ GNU Bison NEWS * Noteworthy changes in release 2.6.1 (2012-07-30) [stable] - Bison no longer executes user-specified M4 code when processing a grammar. + Bison no longer executes user-specified M4 code when processing a grammar. ** Future Changes @@ -1927,7 +1975,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 77d35be7..21e7a1dd 100644 --- a/THANKS +++ b/THANKS @@ -81,6 +81,7 @@ Nicolas Tisserand nicolas.tisserand@epita.fr Noah Friedman friedman@gnu.org Odd Arild Olsen oao@fibula.no Oleg Smolsky oleg.smolsky@pacific-simulators.co.nz +Oleksii Taran oleksii.taran@gmail.com Paolo Bonzini bonzini@gnu.org Pascal Bart pascal.bart@epita.fr Paul Eggert eggert@cs.ucla.edu @@ -105,6 +106,7 @@ Shura debil_urod@ngs.ru Stefano Lattarini stefano.lattarini@gmail.com Steve Murphy murf@parsetree.com Sum Wu sum@geekhouse.org +Théophile Ranquet theophile.ranquet@gmail.com Thiru Ramakrishnan thiru.ramakrishnan@gmail.com Tim Josling tej@melbpc.org.au Tim Landscheidt tim@tim-landscheidt.de @@ -128,6 +130,7 @@ thank them! Please, help us keeping this list up to date. Local Variables: mode: text +coding: utf-8 End: ----- diff --git a/TODO b/TODO index 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..9f11f377 100644 --- a/cfg.mk +++ b/cfg.mk @@ -24,6 +24,7 @@ regen: _version # Used in maint.mk's web-manual rule manual_title = The Yacc-compatible Parser Generator +gendocs_options_ = -I $(abs_top_srcdir)/doc -I $(abs_top_builddir)/doc # It's useful to run maintainer-*check* targets during development, but we # don't want to wait on a recompile because of an update to $(VERSION). Thus, diff --git a/configure.ac b/configure.ac index 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/xml2dot.xsl b/data/xslt/xml2dot.xsl index 219faa2f..111613ce 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] + + } 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 18d3bb05..8f98aa5e 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -294,6 +294,7 @@ Handling Context Dependencies Debugging Your Parser * Understanding:: Understanding the structure of your parser. +* Graphviz:: Getting a visual representation of the parser. * Tracing:: Tracing the execution of your parser. Tracing Your Parser @@ -327,6 +328,7 @@ C++ Location Values * C++ position:: One point in the source file * C++ location:: Two points in the source file +* User Defined Location Type:: Required interface for locations A Complete C++ Example @@ -4701,6 +4703,10 @@ incoming terminals during the second phase of error recovery, the current lookahead and the entire stack (except the current right-hand side symbols) when the parser returns immediately, and @item +the current lookahead and the entire stack (including the current right-hand +side symbols) when the C++ parser (@file{lalr1.cc}) catches an exception in +@code{parse}, +@item the start symbol, when the parser succeeds. @end itemize @@ -5321,6 +5327,23 @@ Unaccepted @var{variable}s produce an error. Some of the accepted @var{variable}s are: @itemize @bullet +@c ================================================== api.location.type +@item @code{api.location.type} +@findex %define api.location.type + +@itemize @bullet +@item Language(s): C++, Java + +@item Purpose: Define the location type. +@xref{User Defined Location Type}. + +@item Accepted Values: String + +@item Default Value: none + +@item History: introduced in Bison 2.7 +@end itemize + @c ================================================== api.prefix @item @code{api.prefix} @findex %define api.prefix @@ -5328,7 +5351,7 @@ Some of the accepted @var{variable}s are: @itemize @bullet @item Language(s): All -@item Purpose: Rename exported symbols +@item Purpose: Rename exported symbols. @xref{Multiple Parsers, ,Multiple Parsers in the Same Program}. @item Accepted Values: String @@ -8071,6 +8094,7 @@ automaton, and how to enable and understand the parser run-time traces. @menu * Understanding:: Understanding the structure of your parser. +* Graphviz:: Getting a visual representation of the parser. * Tracing:: Tracing the execution of your parser. @end menu @@ -8487,6 +8511,114 @@ precedence of @samp{/} with respect to @samp{+}, @samp{-}, and @samp{*}, but also because the associativity of @samp{/} is not specified. +@c ================================================= Graphical Representation + +@node Graphviz +@section Visualizing Your Parser +@cindex dot + +As another means to gain better understanding of the shift/reduce +automaton corresponding to the Bison parser, a DOT file can be generated. Note +that debugging a real grammar with this is tedious at best, and impractical +most of the times, because the generated files are huge (the generation of +a PDF or PNG file from it will take very long, and more often than not it will +fail due to memory exhaustion). This option was rather designed for beginners, +to help them understand LR parsers. + +This file is generated when the @option{--graph} option is specified (see +@pxref{Invocation, , Invoking Bison}). Its name is made by removing +@samp{.tab.c} or @samp{.c} from the parser implementation file name, and +adding @samp{.dot} instead. If the grammar file is @file{foo.y}, the +Graphviz output file is called @file{foo.dot}. + +The following grammar file, @file{rr.y}, will be used in the sequel: + +@example +%% +@group +exp: a ";" | b "."; +a: "0"; +b: "0"; +@end group +@end example + +The graphical output is very similar to the textual one, and as such it is +easier understood by making direct comparisons between them. See +@ref{Debugging, , Debugging Your Parser} for a detailled analysis of the +textual report. + +@subheading Graphical Representation of States + +The items (pointed rules) for each state are grouped together in graph nodes. +Their numbering is the same as in the verbose file. See the following points, +about transitions, for examples + +When invoked with @option{--report=lookaheads}, the lookahead tokens, when +needed, are shown next to the relevant rule between square brackets as a +comma separated list. This is the case in the figure for the representation of +reductions, below. + +@sp 1 + +The transitions are represented as directed edges between the current and +the target states. + +@subheading Graphical Representation of Shifts + +Shifts are shown as solid arrows, labelled with the lookahead token for that +shift. The following describes a reduction in the @file{rr.output} file: + +@example +@group +state 3 + + 1 exp: a . ";" + + ";" shift, and go to state 6 +@end group +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-shift, 100pt} + +@subheading Graphical Representation of Reductions + +Reductions are shown as solid arrows, leading to a diamond-shaped node +bearing the number of the reduction rule. The arrow is labelled with the +appropriate comma separated lookahead tokens. If the reduction is the default +action for the given state, there is no such label. + +This is how reductions are represented in the verbose file @file{rr.output}: +@example +state 1 + + 3 a: "0" . [";"] + 4 b: "0" . ["."] + + "." reduce using rule 4 (b) + $default reduce using rule 3 (a) +@end example + +A Graphviz rendering of this portion of the graph could be: + +@center @image{figs/example-reduce, 120pt} + +When unresolved conflicts are present, because in deterministic parsing +a single decision can be made, Bison can arbitrarily choose to disable a +reduction, see @ref{Shift/Reduce, , Shift/Reduce Conflicts}. Discarded actions +are distinguished by a red filling color on these nodes, just like how they are +reported between square brackets in the verbose file. + +The reduction corresponding to the rule number 0 is the acceptation state. It +is shown as a blue diamond, labelled "Acc". + +@subheading Graphical representation of go tos + +The @samp{go to} jump transitions are represented as dotted lines bearing +the name of the rule being jumped to. + +@c ================================================= Tracing @node Tracing @section Tracing Your Parser @@ -9206,8 +9338,9 @@ generated in the following files: @table @file @item position.hh @itemx location.hh -The definition of the classes @code{position} and @code{location}, -used for location tracking. @xref{C++ Location Values}. +The definition of the classes @code{position} and @code{location}, used for +location tracking. These files are not generated if the @code{%define} +variable @code{api.location.type} is defined. @xref{C++ Location Values}. @item stack.hh An auxiliary class @code{stack} used by the parser. @@ -9263,18 +9396,22 @@ Symbols}. @c - %define filename_type "const symbol::Symbol" When the directive @code{%locations} is used, the C++ parser supports -location tracking, see @ref{Tracking Locations}. Two auxiliary classes -define a @code{position}, a single point in a file, and a @code{location}, a -range composed of a pair of @code{position}s (possibly spanning several -files). +location tracking, see @ref{Tracking Locations}. + +By default, two auxiliary classes define a @code{position}, a single point +in a file, and a @code{location}, a range composed of a pair of +@code{position}s (possibly spanning several files). But if the +@code{%define} variable @code{api.location.type} is defined, then these +classes will not be generated, and the user defined type will be used. @tindex uint In this section @code{uint} is an abbreviation for @code{unsigned int}: in genuine code only the latter is used. @menu -* C++ position:: One point in the source file -* C++ location:: Two points in the source file +* C++ position:: One point in the source file +* C++ location:: Two points in the source file +* User Defined Location Type:: Required interface for locations @end menu @node C++ position @@ -9378,6 +9515,63 @@ Report @var{p} on @var{o}, taking care of special cases such as: no @code{filename} defined, or equal filename/line or column. @end deftypefun +@node User Defined Location Type +@subsubsection User Defined Location Type +@findex %define api.location.type + +Instead of using the built-in types you may use the @code{%define} variable +@code{api.location.type} to specify your own type: + +@example +%define api.location.type @var{LocationType} +@end example + +The requirements over your @var{LocationType} are: +@itemize +@item +it must be copyable; + +@item +in order to compute the (default) value of @code{@@$} in a reduction, the +parser basically runs +@example +@@$.begin = @@$1.begin; +@@$.end = @@$@var{N}.end; // The location of last right-hand side symbol. +@end example +@noindent +so there must be copyable @code{begin} and @code{end} members; + +@item +alternatively you may redefine the computation of the default location, in +which case these members are not required (@pxref{Location Default Action}); + +@item +if traces are enabled, then there must exist an @samp{std::ostream& + operator<< (std::ostream& o, const @var{LocationType}& s)} function. +@end itemize + +@sp 1 + +In programs with several C++ parsers, you may also use the @code{%define} +variable @code{api.location.type} to share a common set of built-in +definitions for @code{position} and @code{location}. For instance, one +parser @file{master/parser.yy} might use: + +@example +%defines +%locations +%define namespace "master::" +@end example + +@noindent +to generate the @file{master/position.hh} and @file{master/location.hh} +files, reused by other parsers as follows: + +@example +%define api.location.type "master::location" +%code requires @{ #include @} +@end example + @node C++ Parser Interface @subsection C++ Parser Interface @c - define parser_class_name @@ -9415,6 +9609,11 @@ Build a new parser object. There are no arguments by default, unless @deftypemethod {parser} {int} parse () Run the syntactic analysis, and return 0 on success, 1 otherwise. + +@cindex exceptions +The whole function is wrapped in a @code{try}/@code{catch} block, so that +when an exception is thrown, the @code{%destructor}s are called to release +the lookahead symbol, and the symbols pushed on the stack. @end deftypemethod @deftypemethod {parser} {std::ostream&} debug_stream () @@ -9528,8 +9727,8 @@ factor both as follows. // Tell Flex the lexer's prototype ... # define YY_DECL \ yy::calcxx_parser::token_type \ - yylex (yy::calcxx_parser::semantic_type *yylval, \ - yy::calcxx_parser::location_type *yylloc, \ + yylex (yy::calcxx_parser::semantic_type* yylval, \ + yy::calcxx_parser::location_type* yylloc, \ calcxx_driver& driver) // ... and declare it for the parser's sake. YY_DECL; @@ -10086,11 +10285,11 @@ class defines a @dfn{position}, a single point in a file; Bison itself defines a class representing a @dfn{location}, a range composed of a pair of positions (possibly spanning several files). The location class is an inner class of the parser; the name is @code{Location} by default, and may also be -renamed using @code{%define location_type "@var{class-name}"}. +renamed using @code{%define api.location.type "@var{class-name}"}. The location class treats the position as a completely opaque value. By default, the class name is @code{Position}, but this can be changed -with @code{%define position_type "@var{class-name}"}. This class must +with @code{%define api.position.type "@var{class-name}"}. This class must be supplied by the user. @@ -10225,7 +10424,7 @@ In both cases, the scanner has to implement the following methods. @deftypemethod {Lexer} {void} yyerror (Location @var{loc}, String @var{msg}) This method is defined by the user to emit an error message. The first parameter is omitted if location tracking is not active. Its type can be -changed using @code{%define location_type "@var{class-name}".} +changed using @code{%define api.location.type "@var{class-name}".} @end deftypemethod @deftypemethod {Lexer} {int} yylex () @@ -10243,7 +10442,7 @@ Return respectively the first position of the last token that @code{yylex} returned, and the first position beyond it. These methods are not needed unless location tracking is active. -The return type can be changed using @code{%define position_type +The return type can be changed using @code{%define api.position.type "@var{class-name}".} @end deftypemethod @@ -10488,10 +10687,11 @@ comma-separated list. Default is @code{java.io.IOException}. @xref{Java Scanner Interface}. @end deffn -@deffn {Directive} {%define location_type} "@var{class}" +@deffn {Directive} {%define api.location.type} "@var{class}" The name of the class used for locations (a range between two positions). This class is generated as an inner class of the parser class by @command{bison}. Default is @code{Location}. +Formerly named @code{location_type}. @xref{Java Location Values}. @end deffn @@ -10506,9 +10706,10 @@ The name of the parser class. Default is @code{YYParser} or @xref{Java Bison Interface}. @end deffn -@deffn {Directive} {%define position_type} "@var{class}" +@deffn {Directive} {%define api.position.type} "@var{class}" The name of the class used for positions. This class must be supplied by the user. Default is @code{Position}. +Formerly named @code{position_type}. @xref{Java Location Values}. @end deffn @@ -11792,7 +11993,8 @@ London, Department of Computer Science, TR-00-12 (December 2000). @c LocalWords: getLVal defvar deftypefn deftypefnx gotos msgfmt Corbett LALR's @c LocalWords: subdirectory Solaris nonassociativity perror schemas Malloy ints @c LocalWords: Scannerless ispell american ChangeLog smallexample CSTYPE CLTYPE -@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate +@c LocalWords: clval CDEBUG cdebug deftypeopx yyterminate LocationType +@c LocalWords: errorVerbose @c Local Variables: @c ispell-dictionary: "american" diff --git a/doc/figs/example-reduce.dot b/doc/figs/example-reduce.dot new file mode 100644 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/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..3ae0b546 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,137 @@ output_edge (int source, int destination, char const *label, fputs ("]\n", fout); } +char const * +escape (char const *name) +{ + char *q = quote (name); + q[strlen (q) - 1] = '\0'; + return q + 1; +} + +static void +no_reduce_bitset_init (state const *s, bitset *no_reduce_set) +{ + int n; + *no_reduce_set = bitset_create (ntokens, BITSET_FIXED); + bitset_zero (*no_reduce_set); + FOR_EACH_SHIFT (s->transitions, n) + bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n)); + for (n = 0; n < s->errs->num; ++n) + if (s->errs->symbols[n]) + bitset_set (*no_reduce_set, s->errs->symbols[n]->number); +} + +static void +conclude_red (struct obstack *out, int source, rule_number ruleno, + bool enabled, bool first, FILE *fout) +{ + /* If no lookahead tokens were valid transitions, this reduction is + actually hidden, so cancel everything. */ + if (first) + return (void) obstack_finish0 (out); + else + { + char const *ed = enabled ? "e" : "d"; + char const *color = enabled ? ruleno ? "3" : "1" : "5"; + + /* First, build the edge's head. The name of reduction nodes is "nRm", + with n the source state and m the rule number. This is because we + don't want all the reductions bearing a same rule number to point to + the same state, since that is not the desired format. */ + fprintf (fout, " %1$d -> \"%1$dR%2$d%3$s\" [", + source, ruleno, ed); + + if (! obstack_empty_p (out)) + /* (The lookahead tokens have been added to the beginning of the + obstack, in the caller function.) */ + fprintf (fout, "label = \"[%s]\" ", obstack_finish0 (out)); + + /* Then, the edge's tail. */ + fprintf (fout, "style = solid]\n"); + + /* Build the associated diamond representation of the target rule. */ + fprintf (fout, " \"%dR%d%s\" [style = filled, " + "shape = diamond, fillcolor = %s, ", + source, ruleno, ed, color); + + if (ruleno) + fprintf (fout, "label = \"R%d\"]\n", ruleno); + else + fprintf (fout, "label = \"Acc\"]\n"); + + } +} + +static bool +print_token (struct obstack *out, bool first, char const *tok) +{ + char const *q = escape (tok); + + if (! first) + obstack_sgrow (out, ", "); + obstack_sgrow (out, q); + return false; +} + +void +output_red (state const *s, reductions const *reds, FILE *fout) +{ + bitset no_reduce_set; + int j; + int source = s->number; + + /* Two obstacks are needed: one for the enabled reductions, and one + for the disabled reductions, because in the end we want two + separate edges, even though in most cases only one will actually + be printed. */ + struct obstack dout; + struct obstack eout; + + no_reduce_bitset_init (s, &no_reduce_set); + obstack_init (&dout); + obstack_init (&eout); + + for (j = 0; j < reds->num; ++j) + { + bool defaulted = false; + bool firstd = true; + bool firste = true; + rule_number ruleno = reds->rules[j]->user_number; + rule *default_reduction = NULL; + + if (yydefact[s->number] != 0) + default_reduction = &rules[yydefact[s->number] - 1]; + + /* Build the lookahead tokens lists, one for enabled transitions and one + for disabled transistions. */ + if (default_reduction && default_reduction == reds->rules[j]) + defaulted = true; + if (reds->lookahead_tokens) + { + int i; + for (i = 0; i < ntokens; i++) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (bitset_test (no_reduce_set, i)) + firstd = print_token (&dout, firstd, symbols[i]->tag); + else + { + if (! defaulted) + firste = print_token (&eout, firste, symbols[i]->tag); + bitset_set (no_reduce_set, i); + } + } + } + + /* Do the actual output. */ + conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout); + conclude_red (&dout, source, ruleno, false, firstd, fout); + } + obstack_free (&eout, 0); + obstack_free (&dout, 0); +} + void finish_graph (FILE *fout) { 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..2c08b106 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.4.11-d01f-dirty. */ /* Bison implementation for Yacc-like parsers in C @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.6.4.37-63951" +#define YYBISON_VERSION "2.6.4.11-d01f-dirty" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ #define yylloc gram_lloc /* Copy the first part of user declarations. */ -/* Line 360 of yacc.c */ +/* Line 358 of yacc.c */ #line 1 "parse-gram.y" /* Bison Grammar Parser -*- C -*- @@ -168,7 +168,7 @@ current_lhs(symbol *sym, location loc, named_ref *ref) #define YYTYPE_UINT16 uint_fast16_t #define YYTYPE_UINT8 uint_fast8_t -/* Line 360 of yacc.c */ +/* Line 358 of yacc.c */ #line 173 "parse-gram.c" # ifndef YY_NULL @@ -334,7 +334,7 @@ extern int gram_debug; #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED typedef union GRAM_STYPE { -/* Line 376 of yacc.c */ +/* Line 374 of yacc.c */ #line 115 "parse-gram.y" symbol *symbol; @@ -348,7 +348,7 @@ typedef union GRAM_STYPE named_ref *named_ref; -/* Line 376 of yacc.c */ +/* Line 374 of yacc.c */ #line 353 "parse-gram.c" } GRAM_STYPE; # define GRAM_STYPE_IS_TRIVIAL 1 @@ -388,7 +388,7 @@ int gram_parse (); /* Copy the second part of user declarations. */ -/* Line 379 of yacc.c */ +/* Line 377 of yacc.c */ #line 393 "parse-gram.c" #ifdef short @@ -966,7 +966,7 @@ do \ } \ while (YYID (0)) -/* Error token number */ + #define YYTERROR 1 #define YYERRCODE 256 @@ -997,21 +997,16 @@ while (YYID (0)) #define YYRHSLOC(Rhs, K) ((Rhs)[K]) - /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - do { \ - fprintf (File, "%d.%d", (Loc).first_line, (Loc).first_column); \ - if ((Loc).first_line < (Loc).last_line) \ - fprintf (File, "-%d.%d", (Loc).last_line, (Loc).last_column - 1); \ - else if ((Loc).first_column < (Loc).last_column - 1) \ - fprintf (File, "-%d", (Loc).last_column - 1); \ - } while (0) +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif @@ -1083,130 +1078,130 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) switch (yytype) { case 3: /* "string" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 205 "parse-gram.y" { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); }; -/* Line 812 of yacc.c */ -#line 1091 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1086 "parse-gram.c" break; case 4: /* "integer" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 217 "parse-gram.y" { fprintf (stderr, "%d", ((*yyvaluep).integer)); }; -/* Line 812 of yacc.c */ -#line 1098 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1093 "parse-gram.c" break; case 43: /* "{...}" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 207 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); }; -/* Line 812 of yacc.c */ -#line 1105 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1100 "parse-gram.c" break; case 44: /* "[identifier]" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 212 "parse-gram.y" { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); }; -/* Line 812 of yacc.c */ -#line 1112 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1107 "parse-gram.c" break; case 45: /* "char" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 199 "parse-gram.y" { fputs (char_name (((*yyvaluep).character)), stderr); }; -/* Line 812 of yacc.c */ -#line 1119 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1114 "parse-gram.c" break; case 46: /* "epilogue" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 207 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }; -/* Line 812 of yacc.c */ -#line 1126 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1121 "parse-gram.c" break; case 48: /* "identifier" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 211 "parse-gram.y" { fputs (((*yyvaluep).uniqstr), stderr); }; -/* Line 812 of yacc.c */ -#line 1133 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1128 "parse-gram.c" break; case 49: /* "identifier:" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 213 "parse-gram.y" { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); }; -/* Line 812 of yacc.c */ -#line 1140 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1135 "parse-gram.c" break; case 52: /* "%{...%}" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 207 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }; -/* Line 812 of yacc.c */ -#line 1147 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1142 "parse-gram.c" break; case 54: /* "type" */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 214 "parse-gram.y" { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); }; -/* Line 812 of yacc.c */ -#line 1154 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1149 "parse-gram.c" break; case 71: /* symbol.prec */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 220 "parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }; -/* Line 812 of yacc.c */ -#line 1161 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1156 "parse-gram.c" break; case 84: /* variable */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 211 "parse-gram.y" { fputs (((*yyvaluep).uniqstr), stderr); }; -/* Line 812 of yacc.c */ -#line 1168 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1163 "parse-gram.c" break; case 85: /* content.opt */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 207 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }; -/* Line 812 of yacc.c */ -#line 1175 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1170 "parse-gram.c" break; case 86: /* braceless */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 207 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }; -/* Line 812 of yacc.c */ -#line 1182 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1177 "parse-gram.c" break; case 87: /* id */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 220 "parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }; -/* Line 812 of yacc.c */ -#line 1189 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1184 "parse-gram.c" break; case 88: /* id_colon */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 221 "parse-gram.y" { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); }; -/* Line 812 of yacc.c */ -#line 1196 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1191 "parse-gram.c" break; case 89: /* symbol */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 220 "parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }; -/* Line 812 of yacc.c */ -#line 1203 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1198 "parse-gram.c" break; case 90: /* string_as_id */ -/* Line 812 of yacc.c */ +/* Line 828 of yacc.c */ #line 220 "parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }; -/* Line 812 of yacc.c */ -#line 1210 "parse-gram.c" +/* Line 828 of yacc.c */ +#line 1205 "parse-gram.c" break; default: break; @@ -1882,11 +1877,10 @@ yyparse () int yychar; -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__)) /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") @@ -1894,26 +1888,21 @@ int yychar; /* Default value used for initialization, for pacifying older GCCs or non-GCC compilers. */ static YYSTYPE yyval_default; -# define YY_INITIAL_VALUE(Value) = Value +# define YYLVAL_INITIALIZE() (yylval = yyval_default) +#endif +#ifndef YYLVAL_INITIALIZE +# define YYLVAL_INITIALIZE() #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); +YYSTYPE yylval; /* Location data for the lookahead symbol. */ -YYLTYPE yylloc -# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL - = { 1, 1, 1, 1 } -# endif -; - +YYLTYPE yylloc; /* Number of syntax errors so far. */ int yynerrs; @@ -1977,9 +1966,9 @@ YYLTYPE yylloc Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yylsp = yyls = yylsa; + yyss = yyssa; + yyvs = yyvsa; + yyls = yylsa; yystacksize = YYINITDEPTH; yyes = yyesa; @@ -1994,8 +1983,23 @@ YYLTYPE yylloc yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; + + YYLVAL_INITIALIZE (); +#if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 1; +#endif + /* User initialization code. */ -/* Line 1560 of yacc.c */ +/* Line 1591 of yacc.c */ #line 107 "parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default @@ -2003,8 +2007,8 @@ YYLTYPE yylloc boundary_set (&yylloc.start, current_file, 1, 1); boundary_set (&yylloc.end, current_file, 1, 1); } -/* Line 1560 of yacc.c */ -#line 2008 "parse-gram.c" +/* Line 1591 of yacc.c */ +#line 2012 "parse-gram.c" yylsp[0] = yylloc; goto yysetstate; @@ -2198,7 +2202,7 @@ yyreduce: switch (yyn) { case 6: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 246 "parse-gram.y" { code_props plain_code; @@ -2212,13 +2216,13 @@ yyreduce: break; case 7: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 255 "parse-gram.y" { debug = true; } break; case 8: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 257 "parse-gram.y" { muscle_percent_define_insert ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), @@ -2227,13 +2231,13 @@ yyreduce: break; case 9: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 261 "parse-gram.y" { defines_flag = true; } break; case 10: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 263 "parse-gram.y" { defines_flag = true; @@ -2242,37 +2246,37 @@ yyreduce: break; case 11: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 267 "parse-gram.y" { error_verbose = true; } break; case 12: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 268 "parse-gram.y" { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 13: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 269 "parse-gram.y" { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 14: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 270 "parse-gram.y" { spec_file_prefix = (yyvsp[(2) - (2)].chars); } break; case 15: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 271 "parse-gram.y" { spec_file_prefix = (yyvsp[(3) - (3)].chars); } break; case 16: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 273 "parse-gram.y" { nondeterministic_parser = true; @@ -2281,7 +2285,7 @@ yyreduce: break; case 17: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 278 "parse-gram.y" { code_props action; @@ -2294,67 +2298,67 @@ yyreduce: break; case 18: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 286 "parse-gram.y" { language_argmatch ((yyvsp[(2) - (2)].chars), grammar_prio, (yylsp[(1) - (2)])); } break; case 19: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 287 "parse-gram.y" { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 20: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 288 "parse-gram.y" { locations_flag = true; } break; case 21: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 289 "parse-gram.y" { spec_name_prefix = (yyvsp[(2) - (2)].chars); } break; case 22: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 290 "parse-gram.y" { spec_name_prefix = (yyvsp[(3) - (3)].chars); } break; case 23: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 291 "parse-gram.y" { no_lines_flag = true; } break; case 24: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 292 "parse-gram.y" { nondeterministic_parser = true; } break; case 25: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 293 "parse-gram.y" { spec_outfile = (yyvsp[(2) - (2)].chars); } break; case 26: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 294 "parse-gram.y" { spec_outfile = (yyvsp[(3) - (3)].chars); } break; case 27: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 295 "parse-gram.y" { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 28: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 297 "parse-gram.y" { /* %pure-parser is deprecated in favor of `%define api.pure', so use @@ -2373,13 +2377,13 @@ yyreduce: break; case 29: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 311 "parse-gram.y" { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); } break; case 30: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 313 "parse-gram.y" { char const *skeleton_user = (yyvsp[(2) - (2)].chars); @@ -2407,25 +2411,25 @@ yyreduce: break; case 31: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 336 "parse-gram.y" { token_table_flag = true; } break; case 32: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 337 "parse-gram.y" { report_flag |= report_states; } break; case 33: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 338 "parse-gram.y" { yacc_flag = true; } break; case 37: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 346 "parse-gram.y" { grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); @@ -2433,7 +2437,7 @@ yyreduce: break; case 38: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 350 "parse-gram.y" { code_props code; @@ -2449,7 +2453,7 @@ yyreduce: break; case 39: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 362 "parse-gram.y" { code_props code; @@ -2465,7 +2469,7 @@ yyreduce: break; case 40: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 374 "parse-gram.y" { default_prec = true; @@ -2473,7 +2477,7 @@ yyreduce: break; case 41: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 378 "parse-gram.y" { default_prec = false; @@ -2481,7 +2485,7 @@ yyreduce: break; case 42: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 382 "parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes @@ -2492,7 +2496,7 @@ yyreduce: break; case 43: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 389 "parse-gram.y" { muscle_percent_code_grow ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)])); @@ -2501,19 +2505,19 @@ yyreduce: break; case 44: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 403 "parse-gram.y" {} break; case 45: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 404 "parse-gram.y" { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 46: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 409 "parse-gram.y" { union_seen = true; @@ -2523,13 +2527,13 @@ yyreduce: break; case 47: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 420 "parse-gram.y" { current_class = nterm_sym; } break; case 48: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 421 "parse-gram.y" { current_class = unknown_sym; @@ -2538,13 +2542,13 @@ yyreduce: break; case 49: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 425 "parse-gram.y" { current_class = token_sym; } break; case 50: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 426 "parse-gram.y" { current_class = unknown_sym; @@ -2553,7 +2557,7 @@ yyreduce: break; case 51: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 431 "parse-gram.y" { symbol_list *list; @@ -2565,7 +2569,7 @@ yyreduce: break; case 52: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 442 "parse-gram.y" { symbol_list *list; @@ -2581,109 +2585,109 @@ yyreduce: break; case 53: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 456 "parse-gram.y" { (yyval.assoc) = left_assoc; } break; case 54: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 457 "parse-gram.y" { (yyval.assoc) = right_assoc; } break; case 55: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 458 "parse-gram.y" { (yyval.assoc) = non_assoc; } break; case 56: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 462 "parse-gram.y" { current_type = NULL; } break; case 57: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 463 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; } break; case 58: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 469 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 59: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 471 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); } break; case 60: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 475 "parse-gram.y" { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); } break; case 61: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 476 "parse-gram.y" { (yyval.symbol) = (yyvsp[(1) - (2)].symbol); symbol_user_token_number_set ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].integer), (yylsp[(2) - (2)])); } break; case 62: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 482 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 63: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 484 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); } break; case 64: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 488 "parse-gram.y" { (yyval.list) = (yyvsp[(1) - (1)].list); } break; case 65: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 489 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); } break; case 66: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 493 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 67: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 494 "parse-gram.y" { (yyval.list) = symbol_list_type_new ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 68: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 495 "parse-gram.y" { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); } break; case 69: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 496 "parse-gram.y" { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); } break; case 70: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 502 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); @@ -2692,7 +2696,7 @@ yyreduce: break; case 71: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 507 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true); @@ -2701,7 +2705,7 @@ yyreduce: break; case 72: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 512 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2711,7 +2715,7 @@ yyreduce: break; case 73: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 518 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2721,7 +2725,7 @@ yyreduce: break; case 74: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 524 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true); @@ -2732,7 +2736,7 @@ yyreduce: break; case 81: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 554 "parse-gram.y" { yyerrok; @@ -2740,13 +2744,13 @@ yyreduce: break; case 82: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 560 "parse-gram.y" { current_lhs ((yyvsp[(1) - (2)].symbol), (yylsp[(1) - (2)]), (yyvsp[(2) - (2)].named_ref)); } break; case 83: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 561 "parse-gram.y" { /* Free the current lhs. */ @@ -2755,86 +2759,86 @@ yyreduce: break; case 84: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 568 "parse-gram.y" { grammar_current_rule_end ((yylsp[(1) - (1)])); } break; case 85: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 569 "parse-gram.y" { grammar_current_rule_end ((yylsp[(3) - (3)])); } break; case 87: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 575 "parse-gram.y" { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location, current_lhs_named_ref); } break; case 88: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 578 "parse-gram.y" { grammar_current_rule_symbol_append ((yyvsp[(2) - (3)].symbol), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); } break; case 89: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 580 "parse-gram.y" { grammar_current_rule_action_append ((yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); } break; case 90: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 582 "parse-gram.y" { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); } break; case 91: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 584 "parse-gram.y" { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); } break; case 92: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 586 "parse-gram.y" { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); } break; case 93: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 590 "parse-gram.y" { (yyval.named_ref) = 0; } break; case 94: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 592 "parse-gram.y" { (yyval.named_ref) = named_ref_new((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 96: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 604 "parse-gram.y" { (yyval.uniqstr) = uniqstr_new ((yyvsp[(1) - (1)].chars)); } break; case 97: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 609 "parse-gram.y" { (yyval.chars) = ""; } break; case 98: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 610 "parse-gram.y" { (yyval.chars) = (yyvsp[(1) - (1)].uniqstr); } break; case 100: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 621 "parse-gram.y" { code_props plain_code; @@ -2847,13 +2851,13 @@ yyreduce: break; case 101: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 641 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 102: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 643 "parse-gram.y" { (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)])); @@ -2863,13 +2867,13 @@ yyreduce: break; case 103: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 651 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 106: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 663 "parse-gram.y" { (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)])); @@ -2878,7 +2882,7 @@ yyreduce: break; case 108: -/* Line 1778 of yacc.c */ +/* Line 1808 of yacc.c */ #line 672 "parse-gram.y" { code_props plain_code; @@ -2891,8 +2895,8 @@ yyreduce: break; -/* Line 1778 of yacc.c */ -#line 2896 "parse-gram.c" +/* Line 1808 of yacc.c */ +#line 2900 "parse-gram.c" default: break; } if (yychar_backup != yychar) @@ -3142,7 +3146,7 @@ yyreturn: } -/* Line 2041 of yacc.c */ +/* Line 2071 of yacc.c */ #line 682 "parse-gram.y" diff --git a/src/parse-gram.h b/src/parse-gram.h index 7f37630f..39e29986 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.4.11-d01f-dirty. */ /* Bison interface for Yacc-like parsers in C @@ -175,7 +175,7 @@ extern int gram_debug; #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED typedef union GRAM_STYPE { -/* Line 2042 of yacc.c */ +/* Line 2072 of yacc.c */ #line 115 "parse-gram.y" symbol *symbol; @@ -189,7 +189,7 @@ typedef union GRAM_STYPE named_ref *named_ref; -/* Line 2042 of yacc.c */ +/* Line 2072 of yacc.c */ #line 194 "parse-gram.h" } GRAM_STYPE; # define GRAM_STYPE_IS_TRIVIAL 1 diff --git a/src/print_graph.c b/src/print_graph.c index f5695a7a..d5ec5fb4 100644 --- a/src/print_graph.c +++ b/src/print_graph.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include +#include #include "system.h" #include "LR0.h" @@ -39,11 +40,32 @@ | Construct the node labels. | `----------------------------*/ +/* Print the lhs of a rule in such a manner that there is no vertical + repetition, like in *.output files. */ + +static void +print_lhs (struct obstack *oout, rule *previous_rule, rule *r) +{ + if (previous_rule && STREQ (previous_rule->lhs->tag, r->lhs->tag)) + { + int i; + for (i = 0; i < strlen (r->lhs->tag); ++i) + obstack_1grow (oout, ' '); + obstack_1grow (oout, '|'); + } + else + { + obstack_sgrow (oout, escape (r->lhs->tag)); + obstack_1grow (oout, ':'); + } +} + static void print_core (struct obstack *oout, state *s) { - size_t i; item_number *sitems = s->items; + rule *previous_rule = NULL; + size_t i; size_t snritems = s->nitems; /* Output all the items of a state, not only its kernel. */ @@ -54,7 +76,8 @@ print_core (struct obstack *oout, state *s) snritems = nitemset; } - obstack_printf (oout, "%d", s->number); + obstack_printf (oout, _("State %d"), s->number); + obstack_sgrow (oout, "\\n"); for (i = 0; i < snritems; i++) { item_number *sp; @@ -64,43 +87,47 @@ print_core (struct obstack *oout, state *s) sp1 = sp = ritem + sitems[i]; while (*sp >= 0) - sp++; + sp++; r = item_number_as_rule_number (*sp); - obstack_printf (oout, "\n%s -> ", rules[r].lhs->tag); + obstack_printf (oout, "%3d ", r); + print_lhs (oout, previous_rule, &rules[r]); + previous_rule = &rules[r]; for (sp = rules[r].rhs; sp < sp1; sp++) - obstack_printf (oout, "%s ", symbols[*sp]->tag); + obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); - obstack_1grow (oout, '.'); + obstack_sgrow (oout, " ."); for (/* Nothing */; *sp >= 0; ++sp) - obstack_printf (oout, " %s", symbols[*sp]->tag); + obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); /* Experimental feature: display the lookahead tokens. */ if (report_flag & report_lookahead_tokens && item_number_is_rule_number (*sp1)) - { - /* Find the reduction we are handling. */ - reductions *reds = s->reductions; - int redno = state_reduction_find (s, &rules[r]); - - /* Print them if there are. */ - if (reds->lookahead_tokens && redno != -1) - { - bitset_iterator biter; - int k; - char const *sep = ""; - obstack_sgrow (oout, "["); - BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) - { - obstack_printf (oout, "%s%s", sep, symbols[k]->tag); - sep = ", "; - } - obstack_sgrow (oout, "]"); - } - } + { + /* Find the reduction we are handling. */ + reductions *reds = s->reductions; + int redno = state_reduction_find (s, &rules[r]); + + /* Print them if there are. */ + if (reds->lookahead_tokens && redno != -1) + { + bitset_iterator biter; + int k; + char const *sep = ""; + obstack_sgrow (oout, " ["); + BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) + { + obstack_sgrow (oout, sep); + obstack_sgrow (oout, escape (symbols[k]->tag)); + sep = ", "; + } + obstack_1grow (oout, ']'); + } + } + obstack_sgrow (oout, "\\l"); } } @@ -113,9 +140,11 @@ print_core (struct obstack *oout, state *s) static void print_actions (state const *s, FILE *fgraph) { + transitions const *trans = s->transitions; int i; - transitions const *trans = s->transitions; + /* Display reductions. */ + output_red (s, s->reductions, fgraph); if (!trans->num && !s->reductions) return; 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/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..dba7a758 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_PARSER_CHECK([[grep '^exception caught: printer$' stderr]], [], [ignore]) + +AT_PARSER_CHECK([[./input aaaae]], [[2]], [[]], +[[exception caught: syntax error +]]) + +AT_PARSER_CHECK([[./input aaaaE]], [[2]], [[]], +[[exception caught: syntax error, unexpected $end, expecting 'a' +]]) + +AT_PARSER_CHECK([[./input aaaaT]], [[1]]) + +# There is error-recovery, so exit success. +AT_PARSER_CHECK([[./input aaaaR]], [[0]]) + +AT_BISON_OPTION_POPDEFS + +AT_CLEANUP 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..3934a6cf 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -896,7 +896,7 @@ exp: exp OP exp | NUM; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce -input.y: expected 0 shift/reduce conflicts +input.y: error: expected 0 shift/reduce conflicts ]) AT_CLEANUP @@ -933,7 +933,7 @@ exp: exp OP exp | NUM; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce -input.y: expected 2 shift/reduce conflicts +input.y: error: expected 2 shift/reduce conflicts ]) AT_CLEANUP @@ -953,7 +953,7 @@ a: 'a'; AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 reduce/reduce -input.y: expected 0 reduce/reduce conflicts +input.y: error: expected 0 reduce/reduce conflicts ]) AT_CLEANUP @@ -1494,11 +1494,11 @@ AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]], echo "$file: conflicts: $conflicts" > experr if test $sr_count -ne $sr_exp; then if test $sr_exp -ne 1; then s=s; else s= ; fi - echo "$file: expected $sr_exp shift/reduce conflict$s" >> experr + echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr fi if test $rr_count -ne $rr_exp; then if test $rr_exp -ne 1; then s=s; else s= ; fi - echo "$file: expected $rr_exp reduce/reduce conflict$s" >> experr + echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr fi ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[ ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[ diff --git a/tests/glr-regression.at b/tests/glr-regression.at index 8570b19d..ad93d40e 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -1643,10 +1643,10 @@ main (void) AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [], -[glr-regr18.y:26.18-24: result type clash on merge function 'merge': != -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 a60e3153..8a05d34d 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]) # Check there is no 'yy' left. # C++ output relies on namespaces and still uses yy a lot. diff --git a/tests/input.at b/tests/input.at index 2848562d..35812c80 100644 --- a/tests/input.at +++ b/tests/input.at @@ -39,20 +39,20 @@ default: 'a' } AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1: invalid character: '\0' -input.y:1.1: invalid character: '\001' -input.y:1.1: invalid character: '\002' -input.y:1.1: invalid character: '\377' -input.y:1.2: invalid character: '?' -input.y:3.1: invalid character: '?' -input.y:4.14: invalid character: '}' -input.y:5.1: invalid character: '%' -input.y:5.2: invalid character: '&' -input.y:6.1-17: invalid directive: '%a-does-not-exist' -input.y:7.1: invalid character: '%' -input.y:7.2: invalid character: '-' -input.y:8.1-9.0: missing '%}' at end of file -input.y:8.1-9.0: syntax error, unexpected %{...%} +[[input.y:1.1: error: invalid character: '\0' +input.y:1.1: error: invalid character: '\001' +input.y:1.1: error: invalid character: '\002' +input.y:1.1: error: invalid character: '\377' +input.y:1.2: error: invalid character: '?' +input.y:3.1: error: invalid character: '?' +input.y:4.14: error: invalid character: '}' +input.y:5.1: error: invalid character: '%' +input.y:5.2: error: invalid character: '&' +input.y:6.1-17: error: invalid directive: '%a-does-not-exist' +input.y:7.1: error: invalid character: '%' +input.y:7.2: error: invalid character: '-' +input.y:8.1-9.0: error: missing '%}' at end of file +input.y:8.1-9.0: error: syntax error, unexpected %{...%} ]]) AT_CLEANUP @@ -74,7 +74,7 @@ AT_DATA([input.y], ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...} +[[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...} ]]) AT_CLEANUP @@ -94,8 +94,8 @@ exp: { @$ = @1 ; }; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:2.13-14: integer out of range: '$1' -input.y:3.13-14: integer out of range: '@1' +[[input.y:2.13-14: error: integer out of range: '$1' +input.y:3.13-14: error: integer out of range: '@1' ]]) AT_CLEANUP @@ -119,8 +119,8 @@ exp: foo { $$; } foo { $2; } foo ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:5.12-13: $$ for the midrule at $2 of 'exp' has no declared type -input.y:5.24-25: $2 of 'exp' has no declared type +[[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type +input.y:5.24-25: error: $2 of 'exp' has no declared type input.y:5.6-32: warning: type clash on default action: != <> 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 +266,30 @@ start: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.13-29: redeclaration for default tagged %destructor -input.y:1.13-29: previous declaration -input.y:2.10-24: redeclaration for default tagged %printer -input.y:2.10-24: previous declaration -input.y:4.13-29: redeclaration for default tagged %destructor -input.y:1.13-29: previous declaration -input.y:5.10-24: redeclaration for default tagged %printer -input.y:2.10-24: previous declaration -input.y:7.13-29: redeclaration for default tagless %destructor -input.y:7.13-29: previous declaration -input.y:8.10-24: redeclaration for default tagless %printer -input.y:8.10-24: previous declaration -input.y:10.13-29: redeclaration for default tagless %destructor -input.y:7.13-29: previous declaration -input.y:11.10-24: redeclaration for default tagless %printer -input.y:8.10-24: previous declaration -input.y:17.13-29: redeclaration for default tagged %destructor -input.y:4.13-29: previous declaration -input.y:18.10-24: redeclaration for default tagged %printer -input.y:5.10-24: previous declaration -input.y:20.13-29: redeclaration for default tagless %destructor -input.y:10.13-29: previous declaration -input.y:21.10-24: redeclaration for default tagless %printer -input.y:11.10-24: previous declaration +[[input.y:1.13-29: error: redeclaration for default tagged %destructor +input.y:1.13-29: previous declaration +input.y:2.10-24: error: redeclaration for default tagged %printer +input.y:2.10-24: previous declaration +input.y:4.13-29: error: redeclaration for default tagged %destructor +input.y:1.13-29: previous declaration +input.y:5.10-24: error: redeclaration for default tagged %printer +input.y:2.10-24: previous declaration +input.y:7.13-29: error: redeclaration for default tagless %destructor +input.y:7.13-29: previous declaration +input.y:8.10-24: error: redeclaration for default tagless %printer +input.y:8.10-24: previous declaration +input.y:10.13-29: error: redeclaration for default tagless %destructor +input.y:7.13-29: previous declaration +input.y:11.10-24: error: redeclaration for default tagless %printer +input.y:8.10-24: previous declaration +input.y:17.13-29: error: redeclaration for default tagged %destructor +input.y:4.13-29: previous declaration +input.y:18.10-24: error: redeclaration for default tagged %printer +input.y:5.10-24: previous declaration +input.y:20.13-29: error: redeclaration for default tagless %destructor +input.y:10.13-29: previous declaration +input.y:21.10-24: error: redeclaration for default tagless %printer +input.y:11.10-24: previous declaration ]]) AT_CLEANUP @@ -317,22 +317,22 @@ start: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:4.13-29: %destructor redeclaration for -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 +429,14 @@ exp: foo; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:8.7-11: %type redeclaration for foo -input.y:3.7-11: previous declaration -input.y:10.13-17: %destructor redeclaration for foo -input.y:5.13-17: previous declaration -input.y:9.10-14: %printer redeclaration for foo -input.y:4.10-14: previous declaration -input.y:11.1-5: %left redeclaration for foo -input.y:6.1-5: previous declaration +[[input.y:8.7-11: error: %type redeclaration for foo +input.y:3.7-11: previous declaration +input.y:10.13-17: error: %destructor redeclaration for foo +input.y:5.13-17: previous declaration +input.y:9.10-14: error: %printer redeclaration for foo +input.y:4.10-14: previous declaration +input.y:11.1-5: error: %left redeclaration for foo +input.y:6.1-5: previous declaration ]]) AT_CLEANUP @@ -455,7 +455,7 @@ AT_SETUP([Torturing the Scanner]) AT_BISON_OPTION_PUSHDEFS AT_DATA([input.y], []) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1: syntax error, unexpected end of file +[[input.y:1.1: error: syntax error, unexpected end of file ]]) @@ -463,7 +463,7 @@ AT_DATA([input.y], [{} ]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:1.1-2: syntax error, unexpected {...} +[[input.y:1.1-2: error: syntax error, unexpected {...} ]]) @@ -729,9 +729,9 @@ AT_DATA_GRAMMAR([input.y], start: .GOOD GOOD ]]) AT_BISON_CHECK([-o input.c input.y], [1], [], -[[input.y:10.10: invalid character: '-' -input.y:11.10-16: invalid identifier: '1NV4L1D' -input.y:12.10: invalid character: '-' +[[input.y:10.10: error: invalid character: '-' +input.y:11.10-16: error: invalid identifier: '1NV4L1D' +input.y:12.10: error: invalid character: '-' ]]) AT_CLEANUP @@ -753,10 +753,10 @@ start: DECIMAL_1 HEXADECIMAL_2; ]]) AT_BISON_CHECK([redecl.y], [1], [], -[[redecl.y:10.10-22: user token number 11259375 redeclaration for HEXADECIMAL_1 -redecl.y:9.8-16: previous declaration for DECIMAL_1 -redecl.y:12.10-18: user token number 16702650 redeclaration for DECIMAL_2 -redecl.y:11.10-22: previous declaration for HEXADECIMAL_2 +[[redecl.y:10.10-22: error: user token number 11259375 redeclaration for HEXADECIMAL_1 +redecl.y:9.8-16: previous declaration for DECIMAL_1 +redecl.y:12.10-18: error: user token number 16702650 redeclaration for DECIMAL_2 +redecl.y:11.10-22: previous declaration for HEXADECIMAL_2 ]]) AT_DATA_GRAMMAR([too-large.y], @@ -768,8 +768,8 @@ start: TOO_LARGE_DEC TOO_LARGE_HEX ]]) AT_BISON_CHECK([too-large.y], [1], [], -[[too-large.y:9.22-42: integer out of range: '999999999999999999999' -too-large.y:10.24-44: integer out of range: '0xFFFFFFFFFFFFFFFFFFF' +[[too-large.y:9.22-42: error: integer out of range: '999999999999999999999' +too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF' ]]) AT_CLEANUP @@ -809,12 +809,12 @@ start: ; ]]) AT_BISON_CHECK([-o input.c input.y], 1, [], -[[input.y:1.10-2.0: missing '"' at end of line -input.y:4.10-5.0: missing "'" at end of line -input.y:14.11-15.0: missing "'" at end of line -input.y:16.11-17.0: missing '"' at end of line -input.y:19.13-20.0: missing '}' at end of file -input.y:20.1: syntax error, unexpected end of file +[[input.y:1.10-2.0: error: missing '"' at end of line +input.y:4.10-5.0: error: missing "'" at end of line +input.y:14.11-15.0: error: missing "'" at end of line +input.y:16.11-17.0: error: missing '"' at end of line +input.y:19.13-20.0: error: missing '}' at end of file +input.y:20.1: error: syntax error, unexpected end of file ]]) AT_CLEANUP @@ -856,7 +856,7 @@ PREC: ; ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:3.1-4: rule given for PREC, which is a token +[[input.y:3.1-4: error: rule given for PREC, which is a token ]]) AT_CLEANUP @@ -897,10 +897,10 @@ AT_DATA([input-c.y], start: ; ]]) AT_BISON_CHECK([[input-c.y]], [[1]], [], -[[input-c.y:1.7: %code qualifier 'q' is not used -input-c.y:2.7-9: %code qualifier 'bad' is not used -input-c.y:3.7-9: %code qualifier 'bad' is not used -input-c.y:4.7-12: %code qualifier 'format' is not used +[[input-c.y:1.7: error: %code qualifier 'q' is not used +input-c.y:2.7-9: error: %code qualifier 'bad' is not used +input-c.y:3.7-9: error: %code qualifier 'bad' is not used +input-c.y:4.7-12: error: %code qualifier 'format' is not used ]]) AT_DATA([input-c-glr.y], @@ -911,9 +911,9 @@ AT_DATA([input-c-glr.y], start: ; ]]) AT_BISON_CHECK([[input-c-glr.y]], [[1]], [], -[[input-c-glr.y:1.7: %code qualifier 'q' is not used -input-c-glr.y:2.7-9: %code qualifier 'bad' is not used -input-c-glr.y:3.8-10: %code qualifier 'bad' is not used +[[input-c-glr.y:1.7: error: %code qualifier 'q' is not used +input-c-glr.y:2.7-9: error: %code qualifier 'bad' is not used +input-c-glr.y:3.8-10: error: %code qualifier 'bad' is not used ]]) AT_DATA([input-c++.y], @@ -924,9 +924,9 @@ AT_DATA([input-c++.y], start: ; ]]) AT_BISON_CHECK([[input-c++.y]], [[1]], [], -[[input-c++.y:1.7: %code qualifier 'q' is not used -input-c++.y:2.7-9: %code qualifier 'bad' is not used -input-c++.y:3.8: %code qualifier 'q' is not used +[[input-c++.y:1.7: error: %code qualifier 'q' is not used +input-c++.y:2.7-9: error: %code qualifier 'bad' is not used +input-c++.y:3.8: error: %code qualifier 'q' is not used ]]) AT_DATA([input-c++-glr.y], @@ -937,9 +937,9 @@ AT_DATA([input-c++-glr.y], start: ; ]]) AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [], -[[input-c++-glr.y:1.7-9: %code qualifier 'bad' is not used -input-c++-glr.y:2.7: %code qualifier 'q' is not used -input-c++-glr.y:3.7: %code qualifier 'q' is not used +[[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used +input-c++-glr.y:2.7: error: %code qualifier 'q' is not used +input-c++-glr.y:3.7: error: %code qualifier 'q' is not used ]]) AT_DATA([special-char-@@.y], @@ -950,9 +950,9 @@ AT_DATA([special-char-@@.y], start: ; ]]) AT_BISON_CHECK([[special-char-@@.y]], [[1]], [], -[[special-char-@@.y:1.7-9: %code qualifier 'bad' is not used -special-char-@@.y:2.7: %code qualifier 'q' is not used -special-char-@@.y:3.7: %code qualifier 'q' is not used +[[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used +special-char-@@.y:2.7: error: %code qualifier 'q' is not used +special-char-@@.y:3.7: error: %code qualifier 'q' is not used ]]) AT_DATA([special-char-@:>@.y], @@ -963,9 +963,9 @@ AT_DATA([special-char-@:>@.y], start: ; ]]) AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [], -[[special-char-@:>@.y:1.7-9: %code qualifier 'bad' is not used -special-char-@:>@.y:2.7: %code qualifier 'q' is not used -special-char-@:>@.y:3.7: %code qualifier 'q' is not used +[[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used +special-char-@:>@.y:2.7: error: %code qualifier 'q' is not used +special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used ]]) AT_CLEANUP @@ -988,10 +988,10 @@ start: ; ]]) AT_BISON_CHECK([[input-redefined.y]], [[1]], [], -[[input-redefined.y:2.9-11: %define variable 'var' redefined -input-redefined.y:1.9-11: previous definition -input-redefined.y:3.10-12: %define variable 'var' redefined -input-redefined.y:2.9-11: previous definition +[[input-redefined.y:2.9-11: error: %define variable 'var' redefined +input-redefined.y:1.9-11: previous definition +input-redefined.y:3.10-12: error: %define variable 'var' redefined +input-redefined.y:2.9-11: previous definition ]]) AT_DATA([input-unused.y], @@ -1001,7 +1001,7 @@ start: ; ]]) AT_BISON_CHECK([[input-unused.y]], [[1]], [], -[[input-unused.y:1.9-11: %define variable 'var' is not used +[[input-unused.y:1.9-11: error: %define variable 'var' is not used ]]) AT_CLEANUP @@ -1045,8 +1045,8 @@ AT_DATA([[input-dg.y]], start: ; ]]) AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [], -[[input-dg.y:1.9-11: %define variable 'var' redefined -:2: previous definition +[[input-dg.y:1.9-11: error: %define variable 'var' redefined +:2: previous definition ]]) AT_DATA([[input-unused.y]], @@ -1054,8 +1054,8 @@ AT_DATA([[input-unused.y]], start: ; ]]) AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [], -[[: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 +1075,7 @@ start: ; ]]) AT_BISON_CHECK([[Input.y]], [1], [], -[[Input.y:2.9-14: invalid value for %define Boolean variable 'public' +[[Input.y:2.9-14: error: invalid value for %define Boolean variable 'public' ]]) AT_CLEANUP @@ -1093,23 +1093,24 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [[]], -[[input.y:1.9-29: invalid value for %define variable 'lr.default-reductions': 'bogus' -input.y:1.9-29: accepted value: 'most' -input.y:1.9-29: accepted value: 'consistent' -input.y:1.9-29: accepted value: 'accepting' +[[input.y:1.9-29: error: invalid value for %define variable 'lr.default-reductions': 'bogus' +input.y:1.9-29: accepted value: 'most' +input.y:1.9-29: accepted value: 'consistent' +input.y:1.9-29: accepted value: 'accepting' ]]) # Back-end. +# FIXME: these should be indented, but we shouldn't mess with the m4 yet AT_DATA([[input.y]], [[%define api.push-pull neither %% start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither' -input.y:1.9-21: accepted value: 'pull' -input.y:1.9-21: accepted value: 'push' -input.y:1.9-21: accepted value: 'both' +[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither' +input.y:1.9-21: error: accepted value: 'pull' +input.y:1.9-21: error: accepted value: 'push' +input.y:1.9-21: error: accepted value: 'both' ]]) AT_CLEANUP @@ -1129,10 +1130,10 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither' -input.y:1.9-21: accepted value: 'pull' -input.y:1.9-21: accepted value: 'push' -input.y:1.9-21: accepted value: 'both' +[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither' +input.y:1.9-21: error: accepted value: 'pull' +input.y:1.9-21: error: accepted value: 'push' +input.y:1.9-21: error: accepted value: 'both' ]]) AT_DATA([[input.y]], @@ -1141,7 +1142,7 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [1], [], -[[input.y:1.9-34: invalid value for %define Boolean variable 'lr.keep-unreachable-states' +[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states' ]]) AT_DATA([[input.y]], @@ -1150,7 +1151,7 @@ AT_DATA([[input.y]], start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [], -[[input.y:1.9-15: %define variable 'foo_bar' is not used +[[input.y:1.9-15: error: %define variable 'foo_bar' is not used ]]) AT_CLEANUP @@ -1175,7 +1176,7 @@ start: ; ]]) AT_BISON_CHECK([[input.y]], [[1]], [], -[[input.y:1.9-16: %define variable 'api.pure' is not used +[[input.y:1.9-16: error: %define variable 'api.pure' is not used ]]) ]) @@ -1209,7 +1210,7 @@ start: ; AT_BISON_CHECK([[input.y]], [1], [], [m4_foreach([b4_arg], m4_dquote(m4_shift($@)), -[[input.y:3.9-17: ]b4_arg[ +[[input.y:3.9-17: error: ]b4_arg[ ]])]) ]) @@ -1260,9 +1261,9 @@ AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]]) AT_BISON_CHECK([empty.y], [1], [], [[empty.y:2.8-9: warning: empty character literal empty.y:3.8-4.0: warning: empty character literal -empty.y:3.8-4.0: missing "'" at end of line +empty.y:3.8-4.0: error: missing "'" at end of line empty.y:4.8: warning: empty character literal -empty.y:4.8: missing "'" at end of file +empty.y:4.8: error: missing "'" at end of file ]]) AT_DATA([two.y], @@ -1275,9 +1276,9 @@ AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]]) AT_BISON_CHECK([two.y], [1], [], [[two.y:2.8-11: warning: extra characters in character literal two.y:3.8-4.0: warning: extra characters in character literal -two.y:3.8-4.0: missing "'" at end of line +two.y:3.8-4.0: error: missing "'" at end of line two.y:4.8-10: warning: extra characters in character literal -two.y:4.8-10: missing "'" at end of file +two.y:4.8-10: error: missing "'" at end of file ]]) AT_DATA([three.y], @@ -1290,9 +1291,9 @@ AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]]) AT_BISON_CHECK([three.y], [1], [], [[three.y:2.8-12: warning: extra characters in character literal three.y:3.8-4.0: warning: extra characters in character literal -three.y:3.8-4.0: missing "'" at end of line +three.y:3.8-4.0: error: missing "'" at end of line three.y:4.8-11: warning: extra characters in character literal -three.y:4.8-11: missing "'" at end of file +three.y:4.8-11: error: missing "'" at end of file ]]) AT_CLEANUP @@ -1318,30 +1319,30 @@ AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \ || exit 77]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:2.9-12: invalid number after \-escape: 777 +[[input.y:2.9-12: error: invalid number after \-escape: 777 input.y:2.8-13: warning: empty character literal -input.y:2.16-17: invalid number after \-escape: 0 +input.y:2.16-17: error: invalid number after \-escape: 0 input.y:2.15-18: warning: empty character literal -input.y:2.21-25: invalid number after \-escape: xfff +input.y:2.21-25: error: invalid number after \-escape: xfff input.y:2.20-26: warning: empty character literal -input.y:2.29-31: invalid number after \-escape: x0 +input.y:2.29-31: error: invalid number after \-escape: x0 input.y:2.28-32: warning: empty character literal -input.y:3.9-14: invalid number after \-escape: uffff +input.y:3.9-14: error: invalid number after \-escape: uffff input.y:3.8-15: warning: empty character literal -input.y:3.18-23: invalid number after \-escape: u0000 +input.y:3.18-23: error: invalid number after \-escape: u0000 input.y:3.17-24: warning: empty character literal -input.y:3.27-36: invalid number after \-escape: Uffffffff +input.y:3.27-36: error: invalid number after \-escape: Uffffffff input.y:3.26-37: warning: empty character literal -input.y:3.40-49: invalid number after \-escape: U00000000 +input.y:3.40-49: error: invalid number after \-escape: U00000000 input.y:3.39-50: warning: empty character literal -input.y:4.9-10: invalid character after \-escape: ' ' +input.y:4.9-10: error: invalid character after \-escape: ' ' input.y:4.8-11: warning: empty character literal -input.y:4.14-15: invalid character after \-escape: A +input.y:4.14-15: error: invalid character after \-escape: A input.y:4.13-16: warning: empty character literal -input.y:5.9-16: invalid character after \-escape: \t -input.y:5.17: invalid character after \-escape: \f -input.y:5.18: invalid character after \-escape: \0 -input.y:5.19: invalid character after \-escape: \001 +input.y:5.9-16: error: invalid character after \-escape: \t +input.y:5.17: error: invalid character after \-escape: \f +input.y:5.18: error: invalid character after \-escape: \0 +input.y:5.19: error: invalid character after \-escape: \001 ]]) AT_CLEANUP @@ -1360,11 +1361,11 @@ start: ; # parse.lac.* options are useless if LAC isn't actually activated. AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]], [[1]], [], -[[: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 +1419,7 @@ m4_pushdef([AT_TEST], exp:; ]]) AT_BISON_CHECK([[$2 input.y]], [[1]], [[]], -[[$3: '%name-prefix' and '%define api.prefix' cannot be used together +[[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together ]]) ]) 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 e803e57f..88e797f5 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. diff --git a/tests/named-refs.at b/tests/named-refs.at index 744eab82..9582c01d 100644 --- a/tests/named-refs.at +++ b/tests/named-refs.at @@ -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:42.1-3: refers to: $exp at $$ +test.y:51.7: possibly meant: $x, hiding $exp at $1 +test.y:51.41: possibly meant: $r, hiding $exp at $4 +test.y:52.51-52: error: $l of 'exp' has no declared type +test.y:55.46-49: error: invalid reference: '$r12' test.y:55.3-53: symbol not found in production: r12 -test.y:56.29-33: invalid reference: '$expo' +test.y:56.29-33: error: invalid reference: '$expo' test.y:56.3-46: symbol not found in production: expo ]]) AT_BISON_OPTION_POPDEFS @@ -278,8 +278,8 @@ foo.bar: '2' ]]) AT_BISON_CHECK([-o test.c test.y], 0, [], [[test.y:11.22-29: warning: misleading reference: '$foo.bar' -test.y:11.8-10: warning: refers to: $foo at $1 -test.y:11.12-18: warning: possibly meant: $[foo.bar] at $2 +test.y:11.8-10: refers to: $foo at $1 +test.y:11.12-18: possibly meant: $[foo.bar] at $2 ]]) AT_CLEANUP @@ -353,43 +353,43 @@ factor: '(' expr ')' { $$ = $2; } ; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:24.36-41: invalid reference: '$cond1' +[[test.y:24.36-41: error: invalid reference: '$cond1' test.y:23.11-24.62: symbol not found in production: cond1 -test.y:26.43-53: invalid reference: '$stmt.field' +test.y:26.43-53: error: invalid reference: '$stmt.field' test.y:25.11-26.60: symbol not found in production: stmt test.y:25.35-38: possibly meant: $then.field, hiding $stmt.field at $4 -test.y:28.43-52: invalid reference: '$stmt.list' +test.y:28.43-52: error: invalid reference: '$stmt.list' test.y:27.11-28.59: symbol not found in production: stmt test.y:27.30-38: possibly meant: $[stmt.list] at $4 -test.y:30.43-46: ambiguous reference: '$xyz' +test.y:30.43-46: error: ambiguous reference: '$xyz' test.y:29.35-37: refers to: $xyz at $4 test.y:29.50-52: refers to: $xyz at $6 -test.y:32.43-52: invalid reference: '$stmt.list' +test.y:32.43-52: error: invalid reference: '$stmt.list' test.y:31.11-32.63: symbol not found in production: stmt test.y:31.40-43: possibly meant: $then, hiding $[stmt.list] at $4 test.y:31.61-64: possibly meant: $else, hiding $[stmt.list] at $6 -test.y:34.43-58: invalid reference: '$stmt.list.field' +test.y:34.43-58: error: invalid reference: '$stmt.list.field' test.y:33.11-34.69: symbol not found in production: stmt test.y:33.40-43: possibly meant: $then.field, hiding $[stmt.list].field at $4 test.y:33.61-64: possibly meant: $else.field, hiding $[stmt.list].field at $6 -test.y:36.43-54: invalid reference: '$[stmt.list]' +test.y:36.43-54: error: invalid reference: '$[stmt.list]' test.y:35.11-36.71: symbol not found in production: stmt.list test.y:35.40-43: possibly meant: $then, hiding $[stmt.list] at $4 test.y:35.61-64: possibly meant: $else, hiding $[stmt.list] at $6 -test.y:38.43-49: invalid reference: '$then.1' +test.y:38.43-49: error: invalid reference: '$then.1' test.y:37.11-38.60: symbol not found in production: then test.y:37.40-45: possibly meant: $[then.1] at $4 -test.y:40.43-55: invalid reference: '$then.1.field' +test.y:40.43-55: error: invalid reference: '$then.1.field' test.y:39.11-40.66: symbol not found in production: then test.y:39.40-45: possibly meant: $[then.1].field at $4 -test.y:42.44-50: invalid reference: '$stmt.x' +test.y:42.44-50: error: invalid reference: '$stmt.x' test.y:41.12-42.57: symbol not found in production: stmt test.y:41.36-41: possibly meant: $[stmt.x].x, hiding $stmt.x at $4 test.y:41.36-41: possibly meant: $[stmt.x] at $4 -test.y:44.13-22: invalid reference: '$if-stmt-a' +test.y:44.13-22: error: invalid reference: '$if-stmt-a' test.y:43.12-44.59: symbol not found in production: if test.y:43.1-9: possibly meant: $[if-stmt-a] at $$ -test.y:46.46-54: invalid reference: '$then-a.f' +test.y:46.46-54: error: invalid reference: '$then-a.f' test.y:45.12-46.65: symbol not found in production: then test.y:45.41-46: possibly meant: $[then-a].f at $4 ]]) @@ -405,7 +405,7 @@ start: foo[] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.12: an identifier expected +[[test.y:11.12: error: an identifier expected ]]) AT_CLEANUP @@ -419,7 +419,7 @@ start: foo[ a d ] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.15: unexpected identifier in bracketed name: 'd' +[[test.y:11.15: error: unexpected identifier in bracketed name: 'd' ]]) AT_CLEANUP @@ -433,7 +433,7 @@ start: foo[/* comment */] bar { s = $foo; } ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.25: an identifier expected +[[test.y:11.25: error: an identifier expected ]]) AT_CLEANUP @@ -448,14 +448,14 @@ start: foo[ /* aaa */ *&-.+\000\001\002\377 ] bar ]]) AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' test.y || exit 77]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.23: invalid character in bracketed name: '*' -test.y:11.24: invalid character in bracketed name: '&' -test.y:11.25: invalid character in bracketed name: '-' -test.y:11.27: invalid character in bracketed name: '+' -test.y:11.28: invalid character in bracketed name: '\0' -test.y:11.28: invalid character in bracketed name: '\001' -test.y:11.28: invalid character in bracketed name: '\002' -test.y:11.28: invalid character in bracketed name: '\377' +[[test.y:11.23: error: invalid character in bracketed name: '*' +test.y:11.24: error: invalid character in bracketed name: '&' +test.y:11.25: error: invalid character in bracketed name: '-' +test.y:11.27: error: invalid character in bracketed name: '+' +test.y:11.28: error: invalid character in bracketed name: '\0' +test.y:11.28: error: invalid character in bracketed name: '\001' +test.y:11.28: error: invalid character in bracketed name: '\002' +test.y:11.28: error: invalid character in bracketed name: '\377' ]]) AT_CLEANUP @@ -468,7 +468,7 @@ AT_DATA_GRAMMAR([test.y], start[a s]: foo; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:11.9: unexpected identifier in bracketed name: 's' +[[test.y:11.9: error: unexpected identifier in bracketed name: 's' ]]) AT_CLEANUP @@ -515,37 +515,37 @@ sym_a: 'a'; sym_b: 'b'; ]]) AT_BISON_CHECK([-o test.c test.y], 1, [], -[[test.y:12.22-31: invalid reference: '$sym.field' +[[test.y:12.22-31: error: invalid reference: '$sym.field' test.y:12.3-35: symbol not found in production: sym -test.y:13.22-35: invalid reference: '$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 +563,10 @@ start: .field: ; ]]) AT_BISON_CHECK([[test.y]], [[1]], [], -[[test.y:4.12-18: invalid reference: '$.field' +[[test.y:4.12-18: error: invalid reference: '$.field' test.y:4.13: syntax error after '$', expecting integer, letter, '_', '@<:@', or '$' test.y:4.3-8: possibly meant: $[.field] at $1 -test.y:5.12-18: invalid reference: '@.field' +test.y:5.12-18: error: invalid reference: '@.field' test.y:5.13: syntax error after '@', expecting integer, letter, '_', '@<:@', or '$' ]]) AT_DATA([[test.y]], diff --git a/tests/output.at b/tests/output.at index f7a7d8e5..37d2c3da 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 0 $accept: . exp $end\l 1 exp: . a '?' b\l 2 a: .\l"] + 0 -> "0R2e" [style = solid] + "0R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 3 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a . '?' b\l"] + 2 -> 4 [style=solid label="'?'"] + 3 [label="State 3\n 0 $accept: exp $end .\l"] + 3 -> "3R0e" [style = solid] + "3R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 4 [label="State 4\n 1 exp: a '?' . b\l 3 b: . 'b'\l"] + 4 -> 5 [style=solid label="'b'"] + 4 -> 6 [style=dashed label="b"] + 5 [label="State 5\n 3 b: 'b' .\l"] + 5 -> "5R3e" [style = solid] + "5R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 6 [label="State 6\n 1 exp: a '?' b .\l"] + 6 -> "6R1e" [style = solid] + "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] +]]) + +## ------------------------ ## +## Graph with unsolved S/R. ## +## ------------------------ ## + +AT_TEST([Graph with unsolved S/R], +[[%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . ['b']\l 9 empty_c: . ['c']\l"] + 0 -> "0R7d" [label = "['a']" style = solid] + "0R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"] + 0 -> "0R8d" [label = "['b']" style = solid] + "0R8d" [style = filled, shape = diamond, fillcolor = 5, label = "R8"] + 0 -> "0R9d" [label = "['c']" style = solid] + "0R9d" [style = filled, shape = diamond, fillcolor = 5, label = "R9"] + 0 -> 1 [style=solid label="'a'"] + 0 -> 2 [style=solid label="'b'"] + 0 -> 3 [style=solid label="'c'"] + 0 -> 4 [style=dashed label="start"] + 0 -> 5 [style=dashed label="empty_a"] + 0 -> 6 [style=dashed label="empty_b"] + 0 -> 7 [style=dashed label="empty_c"] + 1 [label="State 1\n 1 start: 'a' .\l"] + 1 -> "1R1e" [style = solid] + "1R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 2 [label="State 2\n 3 start: 'b' .\l"] + 2 -> "2R3e" [style = solid] + "2R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 3 [label="State 3\n 5 start: 'c' .\l"] + 3 -> "3R5e" [style = solid] + "3R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 4 [label="State 4\n 0 $accept: start . $end\l"] + 4 -> 8 [style=solid label="$end"] + 5 [label="State 5\n 2 start: empty_a . 'a'\l"] + 5 -> 9 [style=solid label="'a'"] + 6 [label="State 6\n 4 start: empty_b . 'b'\l"] + 6 -> 10 [style=solid label="'b'"] + 7 [label="State 7\n 6 start: empty_c . 'c'\l"] + 7 -> 11 [style=solid label="'c'"] + 8 [label="State 8\n 0 $accept: start $end .\l"] + 8 -> "8R0e" [style = solid] + "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 9 [label="State 9\n 2 start: empty_a 'a' .\l"] + 9 -> "9R2e" [style = solid] + "9R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 10 [label="State 10\n 4 start: empty_b 'b' .\l"] + 10 -> "10R4e" [style = solid] + "10R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 11 [label="State 11\n 6 start: empty_c 'c' .\l"] + 11 -> "11R6e" [style = solid] + "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ---------------------- ## +## Graph with solved S/R. ## +## ---------------------- ## + +AT_TEST([Graph with solved S/R], +[[%left 'a' +%right 'b' +%right 'c' +%% +start: + 'a' + | empty_a 'a' + | 'b' + | empty_b 'b' + | 'c' + | empty_c 'c' + ; +empty_a: %prec 'a'; +empty_b: %prec 'b'; +empty_c: %prec 'c'; +]], +[[ + 0 [label="State 0\n 0 $accept: . start $end\l 1 start: . 'a'\l 2 | . empty_a 'a'\l 3 | . 'b'\l 4 | . empty_b 'b'\l 5 | . 'c'\l 6 | . empty_c 'c'\l 7 empty_a: . ['a']\l 8 empty_b: . []\l 9 empty_c: . []\l"] + 0 -> "0R7e" [style = solid] + "0R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 0 -> 1 [style=solid label="'b'"] + 0 -> 2 [style=solid label="'c'"] + 0 -> 3 [style=dashed label="start"] + 0 -> 4 [style=dashed label="empty_a"] + 0 -> 5 [style=dashed label="empty_b"] + 0 -> 6 [style=dashed label="empty_c"] + 1 [label="State 1\n 3 start: 'b' .\l"] + 1 -> "1R3e" [style = solid] + "1R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 2 [label="State 2\n 5 start: 'c' .\l"] + 2 -> "2R5e" [style = solid] + "2R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 3 [label="State 3\n 0 $accept: start . $end\l"] + 3 -> 7 [style=solid label="$end"] + 4 [label="State 4\n 2 start: empty_a . 'a'\l"] + 4 -> 8 [style=solid label="'a'"] + 5 [label="State 5\n 4 start: empty_b . 'b'\l"] + 5 -> 9 [style=solid label="'b'"] + 6 [label="State 6\n 6 start: empty_c . 'c'\l"] + 6 -> 10 [style=solid label="'c'"] + 7 [label="State 7\n 0 $accept: start $end .\l"] + 7 -> "7R0e" [style = solid] + "7R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 8 [label="State 8\n 2 start: empty_a 'a' .\l"] + 8 -> "8R2e" [style = solid] + "8R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 9 [label="State 9\n 4 start: empty_b 'b' .\l"] + 9 -> "9R4e" [style = solid] + "9R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 10 [label="State 10\n 6 start: empty_c 'c' .\l"] + 10 -> "10R6e" [style = solid] + "10R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ---------------- ## +## Graph with R/R. ## +## ---------------- ## + +AT_TEST([Graph with R/R], +[[%% +exp: a | b; +a: ; +b: ; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . a\l 2 | . b\l 3 a: . [$end]\l 4 b: . [$end]\l"] + 0 -> "0R3e" [style = solid] + "0R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 0 -> "0R4d" [label = "[$end]" style = solid] + "0R4d" [style = filled, shape = diamond, fillcolor = 5, label = "R4"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 4 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a .\l"] + 2 -> "2R1e" [style = solid] + "2R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 3 [label="State 3\n 2 exp: b .\l"] + 3 -> "3R2e" [style = solid] + "3R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 4 [label="State 4\n 0 $accept: exp $end .\l"] + 4 -> "4R0e" [style = solid] + "4R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] +]]) + +## ---------------------------------------- ## +## Graph with reductions with multiple LAT. ## +## ---------------------------------------- ## + +AT_TEST([Graph with reductions with multiple LAT], +[[%% +exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';'; +a: ; +b: ; +c: ; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . a ';'\l 2 | . a ';'\l 3 | . a '.'\l 4 | . b '?'\l 5 | . b '!'\l 6 | . c '?'\l 7 | . c ';'\l 8 a: . [';', '.']\l 9 b: . ['?', '!']\l 10 c: . [';', '?']\l"] + 0 -> "0R8e" [style = solid] + "0R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"] + 0 -> "0R9e" [label = "['?', '!']" style = solid] + "0R9e" [style = filled, shape = diamond, fillcolor = 3, label = "R9"] + 0 -> "0R10d" [label = "[';', '?']" style = solid] + "0R10d" [style = filled, shape = diamond, fillcolor = 5, label = "R10"] + 0 -> 1 [style=dashed label="exp"] + 0 -> 2 [style=dashed label="a"] + 0 -> 3 [style=dashed label="b"] + 0 -> 4 [style=dashed label="c"] + 1 [label="State 1\n 0 $accept: exp . $end\l"] + 1 -> 5 [style=solid label="$end"] + 2 [label="State 2\n 1 exp: a . ';'\l 2 | a . ';'\l 3 | a . '.'\l"] + 2 -> 6 [style=solid label="';'"] + 2 -> 7 [style=solid label="'.'"] + 3 [label="State 3\n 4 exp: b . '?'\l 5 | b . '!'\l"] + 3 -> 8 [style=solid label="'?'"] + 3 -> 9 [style=solid label="'!'"] + 4 [label="State 4\n 6 exp: c . '?'\l 7 | c . ';'\l"] + 4 -> 10 [style=solid label="';'"] + 4 -> 11 [style=solid label="'?'"] + 5 [label="State 5\n 0 $accept: exp $end .\l"] + 5 -> "5R0e" [style = solid] + "5R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 6 [label="State 6\n 1 exp: a ';' . [$end]\l 2 | a ';' . [$end]\l"] + 6 -> "6R1e" [style = solid] + "6R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 6 -> "6R2d" [label = "[$end]" style = solid] + "6R2d" [style = filled, shape = diamond, fillcolor = 5, label = "R2"] + 7 [label="State 7\n 3 exp: a '.' .\l"] + 7 -> "7R3e" [style = solid] + "7R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 8 [label="State 8\n 4 exp: b '?' .\l"] + 8 -> "8R4e" [style = solid] + "8R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 9 [label="State 9\n 5 exp: b '!' .\l"] + 9 -> "9R5e" [style = solid] + "9R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 10 [label="State 10\n 7 exp: c ';' .\l"] + 10 -> "10R7e" [style = solid] + "10R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 11 [label="State 11\n 6 exp: c '?' .\l"] + 11 -> "11R6e" [style = solid] + "11R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] +]]) + +## ------------------------------------------------------ ## +## Graph with a reduction rule both enabled and disabled. ## +## ------------------------------------------------------ ## + +AT_TEST([Graph with a reduction rule both enabled and disabled], +[[%% +exp: ifexp | opexp | imm; +ifexp: "if" exp "then" exp elseexp; +elseexp: "else" exp | ; +opexp: exp '+' exp; +imm: '0'; +]], +[[ + 0 [label="State 0\n 0 $accept: . exp $end\l 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 0 -> 1 [style=solid label="\"if\""] + 0 -> 2 [style=solid label="'0'"] + 0 -> 3 [style=dashed label="exp"] + 0 -> 4 [style=dashed label="ifexp"] + 0 -> 5 [style=dashed label="opexp"] + 0 -> 6 [style=dashed label="imm"] + 1 [label="State 1\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" . exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 1 -> 1 [style=solid label="\"if\""] + 1 -> 2 [style=solid label="'0'"] + 1 -> 7 [style=dashed label="exp"] + 1 -> 4 [style=dashed label="ifexp"] + 1 -> 5 [style=dashed label="opexp"] + 1 -> 6 [style=dashed label="imm"] + 2 [label="State 2\n 8 imm: '0' .\l"] + 2 -> "2R8e" [style = solid] + "2R8e" [style = filled, shape = diamond, fillcolor = 3, label = "R8"] + 3 [label="State 3\n 0 $accept: exp . $end\l 7 opexp: exp . '+' exp\l"] + 3 -> 8 [style=solid label="$end"] + 3 -> 9 [style=solid label="'+'"] + 4 [label="State 4\n 1 exp: ifexp .\l"] + 4 -> "4R1e" [style = solid] + "4R1e" [style = filled, shape = diamond, fillcolor = 3, label = "R1"] + 5 [label="State 5\n 2 exp: opexp .\l"] + 5 -> "5R2e" [style = solid] + "5R2e" [style = filled, shape = diamond, fillcolor = 3, label = "R2"] + 6 [label="State 6\n 3 exp: imm .\l"] + 6 -> "6R3e" [style = solid] + "6R3e" [style = filled, shape = diamond, fillcolor = 3, label = "R3"] + 7 [label="State 7\n 4 ifexp: \"if\" exp . \"then\" exp elseexp\l 7 opexp: exp . '+' exp\l"] + 7 -> 10 [style=solid label="\"then\""] + 7 -> 9 [style=solid label="'+'"] + 8 [label="State 8\n 0 $accept: exp $end .\l"] + 8 -> "8R0e" [style = solid] + "8R0e" [style = filled, shape = diamond, fillcolor = 1, label = "Acc"] + 9 [label="State 9\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 7 opexp: . exp '+' exp\l 7 | exp '+' . exp\l 8 imm: . '0'\l"] + 9 -> 1 [style=solid label="\"if\""] + 9 -> 2 [style=solid label="'0'"] + 9 -> 11 [style=dashed label="exp"] + 9 -> 4 [style=dashed label="ifexp"] + 9 -> 5 [style=dashed label="opexp"] + 9 -> 6 [style=dashed label="imm"] + 10 [label="State 10\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 4 | \"if\" exp \"then\" . exp elseexp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 10 -> 1 [style=solid label="\"if\""] + 10 -> 2 [style=solid label="'0'"] + 10 -> 12 [style=dashed label="exp"] + 10 -> 4 [style=dashed label="ifexp"] + 10 -> 5 [style=dashed label="opexp"] + 10 -> 6 [style=dashed label="imm"] + 11 [label="State 11\n 7 opexp: exp . '+' exp\l 7 | exp '+' exp . [$end, \"then\", \"else\", '+']\l"] + 11 -> "11R7e" [style = solid] + "11R7e" [style = filled, shape = diamond, fillcolor = 3, label = "R7"] + 11 -> "11R7d" [label = "['+']" style = solid] + "11R7d" [style = filled, shape = diamond, fillcolor = 5, label = "R7"] + 11 -> 9 [style=solid label="'+'"] + 12 [label="State 12\n 4 ifexp: \"if\" exp \"then\" exp . elseexp\l 5 elseexp: . \"else\" exp\l 6 | . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 12 -> "12R6e" [style = solid] + "12R6e" [style = filled, shape = diamond, fillcolor = 3, label = "R6"] + 12 -> "12R6d" [label = "[\"else\", '+']" style = solid] + "12R6d" [style = filled, shape = diamond, fillcolor = 5, label = "R6"] + 12 -> 13 [style=solid label="\"else\""] + 12 -> 9 [style=solid label="'+'"] + 12 -> 14 [style=dashed label="elseexp"] + 13 [label="State 13\n 1 exp: . ifexp\l 2 | . opexp\l 3 | . imm\l 4 ifexp: . \"if\" exp \"then\" exp elseexp\l 5 elseexp: \"else\" . exp\l 7 opexp: . exp '+' exp\l 8 imm: . '0'\l"] + 13 -> 1 [style=solid label="\"if\""] + 13 -> 2 [style=solid label="'0'"] + 13 -> 15 [style=dashed label="exp"] + 13 -> 4 [style=dashed label="ifexp"] + 13 -> 5 [style=dashed label="opexp"] + 13 -> 6 [style=dashed label="imm"] + 14 [label="State 14\n 4 ifexp: \"if\" exp \"then\" exp elseexp .\l"] + 14 -> "14R4e" [style = solid] + "14R4e" [style = filled, shape = diamond, fillcolor = 3, label = "R4"] + 15 [label="State 15\n 5 elseexp: \"else\" exp . [$end, \"then\", \"else\", '+']\l 7 opexp: exp . '+' exp\l"] + 15 -> "15R5e" [style = solid] + "15R5e" [style = filled, shape = diamond, fillcolor = 3, label = "R5"] + 15 -> "15R5d" [label = "['+']" style = solid] + "15R5d" [style = filled, shape = diamond, fillcolor = 5, label = "R5"] + 15 -> 9 [style=solid label="'+'"] +]]) + +m4_popdef([AT_TEST]) diff --git a/tests/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/regression.at b/tests/regression.at index 6cf22685..b6bff17c 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -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. ## ## ------------------- ## 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 ]])