From: Akim Demaille Date: Fri, 27 Jul 2012 14:22:45 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/maint' X-Git-Tag: v2.7.90~378 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/4323e0dac386d777d070c68564f1c0041b06935d Merge remote-tracking branch 'origin/maint' * origin/maint: (29 commits) regen synclines: remove spurious empty line also support $$ in the %initial-action skeletons: b4_dollar_pushdef and popdef to simpify complex definitions regen printer/destructor: translate only once factor the handling of m4 escaping news: schedule the removal of the ";" hack style changes in the scanners regen support $$ in printers and destructors scan-code: factor the handling of the type in $$ muscles: fix another occurrence of unescaped type name glr.cc: fix the handling of yydebug gnulib: update formatting changes tests: fix an assertion tests: adjust to GCC 4.8, which displays caret errors be sure to properly escape type names obstack_quote: escape and quote for M4 muscles: shuffle responsabilities muscles: make private functions static muscles: rename private functions/macros obstack_escape: escape M4 characters remove dead macro maint: style changes doc: avoid problems with case insensitive file systems configure: fix botched quoting news: fix typo. Conflicts: NEWS data/c.m4 data/glr.cc data/lalr1.cc examples/rpcalc/local.mk src/muscle-tab.h src/output.c src/parse-gram.c src/parse-gram.h src/parse-gram.y src/scan-code.l src/symlist.c src/symlist.h src/symtab.h tests/calc.at --- 4323e0dac386d777d070c68564f1c0041b06935d diff --cc NEWS index fe23b556,b99290c9..150068ee --- a/NEWS +++ b/NEWS @@@ -1,134 -1,42 +1,169 @@@ GNU Bison NEWS +* Noteworthy changes in release ?.? (????-??-??) [?] + +** Incompatible changes + +*** Obsolete features + + Support for YYFAIL is removed, as announced since Bison 2.4.2. + Support for yystype and yyltype (instead of YYSTYPE and YYLTYPE) + is removed, as announced in Bison 1.875. + +** Warnings + +*** Warning categories are now displayed in warnings + + For instance: + + foo.y:4.6: warning: type clash on default action: != [-Wother] + +*** Useless semantic types + + Bison now warns about useless (uninhabited) semantic types. Since + semantic types are not declared to Bison (they are defined in the opaque + %union structure), it is %printer/%destructor directives about useless + types that trigger the warning: + + %token term + %type nterm + %printer {} + %destructor {} + %% + nterm: term { $$ = $1; }; + + 3.28-34: warning: type is used, but is not associated to any symbol + 4.28-34: warning: type is used, but is not associated to any symbol + +*** Undeclared symbols + + Bison used to raise an error for %printer and %destructor directives for + undefined symbols. + + %printer {} symbol1 + %destructor {} symbol2 + %% + exp: "a"; + + This is now only a warning. + +*** Useless destructors or printers + + Bison now warns about useless destructors or printers. In the following + example, the printer for , and the destructor for are + useless: all symbols of (token1) already have a printer, and all + symbols of type (token2) already have a destructor. + + %token token1 + token2 + token3 + token4 + %printer {} token1 + %destructor {} token2 + +** Additional yylex/yyparse arguments + + The new directive %param declares additional arguments to both yylex and + yyparse. The %lex-param, %parse-param, and %param directives support one + or more arguments. Instead of + + %lex-param {arg1_type *arg1} + %lex-param {arg2_type *arg2} + %parse-param {arg1_type *arg1} + %parse-param {arg2_type *arg2} + + one may now declare + + %param {arg1_type *arg1} {arg2_type *arg2} + +** Java skeleton improvements + + The constants for token names were moved to the Lexer interface. + Also, it is possible to add code to the parser's constructors using + "%code init" and "%define init_throws". + +** C++ skeleton improvements + + The C++ parser features a syntax_error exception, which can be + thrown from the scanner or from user rules to raise syntax errors. + This facilitates reporting errors caught in sub-functions (e.g., + rejecting too large integral literals from a conversion function + used by the scanner, or rejecting invalid combinations from a + factory invoked by the user actions). + +** Variable api.tokens.prefix + + The variable api.tokens.prefix changes the way tokens are identified in + the generated files. This is especially useful to avoid collisions + with identifiers in the target language. For instance + + %token FILE for ERROR + %define api.tokens.prefix "TOK_" + %% + start: FILE for ERROR; + + will generate the definition of the symbols TOK_FILE, TOK_for, and + TOK_ERROR in the generated sources. In particular, the scanner must + use these prefixed token names, although the grammar itself still + uses the short names (as in the sample rule given above). + +** Variable api.namespace + + The "namespace" variable is renamed "api.namespace". Backward + compatibility is ensured, but upgrading is recommended. + +** Variable parse.error + + The variable error controls the verbosity of error messages. The + use of the %error-verbose directive is deprecated in favor of + %define parse.error "verbose". + +** Semantic predicates + + The new, experimental, semantic-predicate feature allows actions of + the form %?{ BOOLEAN-EXPRESSION }, which cause syntax errors (as for + YYERROR) if the expression evaluates to 0, and are evaluated immediately + in GLR parsers, rather than being deferred. The result is that they + allow the programmer to prune possible parses based on the values of + run-time expressions. + * Noteworthy changes in release ?.? (????-??-??) [?] + Bison no longer executes user-specified M4 code when processing a grammar. + + ** Future Changes + + In addition to the removal of the features announced in Bison 2.6, the + next major release will remove the "Temporary hack for adding a semicolon + to the user action", as announced in the release 2.5. Instead of: + + exp: exp "+" exp { $$ = $1 + $3 }; + + write: + + exp: exp "+" exp { $$ = $1 + $3; }; + + ** Bug fixes + + *** Type names are now properly escaped. + + *** glr.cc: set_debug_level and debug_level work as expected. + + *** Stray @ or $ in actions + + While Bison used to warn about stray $ or @ in action rules, it did not + for other actions such as printers, destructors, or initial actions. It + now does. + + ** Type names in actions + + For consistency with rule actions, it is now possible to qualify $$ by a + type-name in destructors, printers, and initial actions. For instance: + + %printer { fprintf (yyo, "(%d, %f)", $$, $$); } <*> <>; + + will display two values for each typed and untyped symbol (provided + that YYSTYPE has both "ival" and "fval" fields). * Noteworthy changes in release 2.6 (2012-07-19) [stable] diff --cc TODO index dfd6cfe3,4f628a20..64577425 --- a/TODO +++ b/TODO @@@ -1,4 -1,4 +1,8 @@@ * Short term ++** scan-code.l ++Avoid variables for format strings, as then GCC cannot check them. ++show_sub_messages should call show_sub_message. ++ ** Variable names. What should we name `variant' and `lex_symbol'? diff --cc data/bison.m4 index 1db75a8e,fac86f2a..f2126ef4 --- a/data/bison.m4 +++ b/data/bison.m4 @@@ -321,161 -239,8 +321,159 @@@ b4_define_flag_if([nondeterministic] b4_define_flag_if([token_table]) # Whether yytoken_table is demanded. b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated. -# yytoken_table is needed to support verbose errors. -b4_error_verbose_if([m4_define([b4_token_table_flag], [1])]) + +## --------- ## +## Symbols. ## +## --------- ## + +# In order to unify the handling of the various aspects of symbols +# (tag, type_name, whether terminal, etc.), bison.exe defines one +# macro per (token, field), where field can has_id, id, etc.: see +# src/output.c:prepare_symbols_definitions(). +# +# The following macros provide access to these values. + +# b4_symbol_(NUM, FIELD) +# ---------------------- +# Recover a FIELD about symbol #NUM. Thanks to m4_indir, fails if +# undefined. +m4_define([b4_symbol_], +[m4_indir([b4_symbol($1, $2)])]) + + +# b4_symbol(NUM, FIELD) +# --------------------- +# Recover a FIELD about symbol #NUM. Thanks to m4_indir, fails if +# undefined. If FIELD = id, prepend the prefix. +m4_define([b4_symbol], +[m4_case([$2], + [id], [m4_do([b4_percent_define_get([api.tokens.prefix])], + [b4_symbol_([$1], [id])])], + [b4_symbol_($@)])]) + + +# b4_symbol_if(NUM, FIELD, IF-TRUE, IF-FALSE) +# ------------------------------------------- +# If FIELD about symbol #NUM is 1 expand IF-TRUE, if is 0, expand IF-FALSE. +# Otherwise an error. +m4_define([b4_symbol_if], +[m4_case(b4_symbol([$1], [$2]), + [1], [$3], + [0], [$4], + [m4_fatal([$0: field $2 of $1 is not a Boolean:] b4_symbol([$1], [$2]))])]) + + +# b4_symbol_action_location(SYMBOL-NUM, KIND) +# ------------------------------------------- +# Report the location of the KIND action as FILE:LINE. +m4_define([b4_symbol_action_location], +[b4_symbol([$1], [$2_file]):b4_syncline([b4_symbol([$1], [$2_line])])]) + + +# b4_symbol_action(SYMBOL-NUM, KIND) +# ---------------------------------- +# Run the action KIND (destructor or printer) for SYMBOL-NUM. +# Same as in C, but using references instead of pointers. +m4_define([b4_symbol_action], +[b4_symbol_if([$1], [has_$2], - [m4_pushdef([b4_dollar_dollar], - [b4_symbol_value([(*yyvaluep)], - b4_symbol_if([$1], [has_type], - [b4_symbol([$1], [type])]))])dnl - m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl ++[b4_dollar_pushdef([(*yyvaluep)], ++ b4_symbol_if([$1], [has_type], ++ [m4_dquote(b4_symbol([$1], [type]))]), ++ [(*yylocationp)])dnl + b4_symbol_case_([$1])[]dnl +b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"]) + b4_symbol([$1], [$2]) +b4_syncline([@oline@], [@ofile@]) + break; + - m4_popdef([b4_at_dollar])dnl - m4_popdef([b4_dollar_dollar])dnl ++b4_dollar_popdef[]dnl +])]) + + +# b4_symbol_destructor(SYMBOL-NUM) +# b4_symbol_printer(SYMBOL-NUM) +# -------------------------------- +m4_define([b4_symbol_destructor], [b4_symbol_action([$1], [destructor])]) +m4_define([b4_symbol_printer], [b4_symbol_action([$1], [printer])]) + + +# b4_symbol_case_(SYMBOL-NUM) +# --------------------------- +# Issue a "case NUM" for SYMBOL-NUM. +m4_define([b4_symbol_case_], +[ case b4_symbol([$1], [number]): // b4_symbol([$1], [tag]) +]) + + +# b4_symbol_foreach(MACRO) +# ------------------------ +# Invoke MACRO(SYMBOL-NUM) for each SYMBOL-NUM. +m4_define([b4_symbol_foreach], + [m4_map([$1], m4_defn([b4_symbol_numbers]))]) + +# b4_symbol_map(MACRO) +# -------------------- +# Return a list (possibly empty elements) of MACRO invoked for each +# SYMBOL-NUM. +m4_define([b4_symbol_map], +[m4_map_args_sep([$1(], [)], [,], b4_symbol_numbers)]) + + +# b4_token_visible_if(NUM, IF-TRUE, IF-FALSE) +# ------------------------------------------- +# Whether NUM denotes a token that has an exported definition (i.e., +# shows in enum yytokentype). +m4_define([b4_token_visible_if], +[b4_symbol_if([$1], [is_token], + [b4_symbol_if([$1], [has_id], [$2], [$3])], + [$3])]) + +# b4_token_has_definition(NUM) +# ---------------------------- +# 1 if NUM is visible, nothing otherwise. +m4_define([b4_token_has_definition], +[b4_token_visible_if([$1], [1])]) + +# b4_any_token_visible_if([IF-TRUE], [IF-FALSE]) +# ---------------------------------------------- +# Whether there is a token that needs to be defined. +m4_define([b4_any_token_visible_if], +[m4_ifval(b4_symbol_foreach([b4_token_has_definition]), + [$1], [$2])]) + + +# b4_token_format(FORMAT, NUM) +# ---------------------------- +m4_define([b4_token_format], +[b4_token_visible_if([$2], +[m4_quote(m4_format([$1], + [b4_symbol([$2], [id])], + [b4_symbol([$2], [user_number])]))])]) + + +## ------- ## +## Types. ## +## ------- ## + +# b4_type_action_(NUMS) +# --------------------- +# Run actions for the symbol NUMS that all have the same type-name. +# Skip NUMS that have no type-name. +m4_define([b4_type_action_], +[b4_symbol_if([$1], [has_type], +[m4_map([b4_symbol_case_], [$@])[]dnl + b4_dollar_dollar([b4_symbol([$1], [number])], + [b4_symbol([$1], [tag])], + [b4_symbol([$1], [type])]); + break; + +])]) + +# b4_type_foreach(MACRO) +# ---------------------- +# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set. +m4_define([b4_type_foreach], + [m4_map([$1], m4_defn([b4_type_names]))]) diff --cc data/c-like.m4 index 00000000,c2abce7e..732d18d4 mode 000000,100644..100644 --- a/data/c-like.m4 +++ b/data/c-like.m4 @@@ -1,0 -1,44 +1,43 @@@ + -*- Autoconf -*- + + # Common code for C-like languages (C, C++, Java, etc.) + + # Copyright (C) 2012 Free Software Foundation, Inc. + + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + + # b4_dollar_dollar_(VALUE, FIELD, DEFAULT-FIELD) + # ---------------------------------------------- + # If FIELD (or DEFAULT-FIELD) is non-null, return "VALUE.FIELD", + # otherwise just VALUE. Be sure to pass "(VALUE)" is VALUE is a + # pointer. + m4_define([b4_dollar_dollar_], -[m4_if([$2], [[]], - [m4_ifval([$3], [($1.$3)], - [$1])], - [($1.$2)])]) ++[b4_symbol_value([$1], ++ m4_if([$2], [[]], ++ [[$3]], [[$2]]))]) + + # b4_dollar_pushdef(VALUE-POINTER, DEFAULT-FIELD, LOCATION) + # b4_dollar_popdef + # --------------------------------------------------------- + # Define b4_dollar_dollar for VALUE and DEFAULT-FIELD, + # and b4_at_dollar for LOCATION. + m4_define([b4_dollar_pushdef], + [m4_pushdef([b4_dollar_dollar], + [b4_dollar_dollar_([$1], m4_dquote($][1), [$2])])dnl + m4_pushdef([b4_at_dollar], [$3])dnl + ]) + m4_define([b4_dollar_popdef], + [m4_popdef([b4_at_dollar])dnl + m4_popdef([b4_dollar_dollar])dnl + ]) diff --cc data/glr.c index d3926229,08f6cd8d..935ee96a --- a/data/glr.c +++ b/data/glr.c @@@ -2294,12 -2302,10 +2294,10 @@@ yyrecoverSyntaxError (yyGLRStack* yysta #endif ]) m4_ifdef([b4_initial_action], [ - m4_pushdef([b4_at_dollar], [yylloc])dnl - m4_pushdef([b4_dollar_dollar], [yylval])dnl + b4_dollar_pushdef([yylval], [], [yylloc])dnl -/* User initialization code. */ -b4_user_initial_action + /* User initialization code. */ + b4_user_initial_action - m4_popdef([b4_dollar_dollar])dnl - m4_popdef([b4_at_dollar])])dnl + b4_dollar_popdef])[]dnl [ if (! yyinitGLRStack (yystackp, YYINITDEPTH)) goto yyexhaustedlab; diff --cc data/lalr1.cc index 96936bbe,c1639033..313dba27 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@@ -17,106 -17,6 +17,106 @@@ m4_include(b4_pkgdatadir/[c++.m4]) + +# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT) +# -------------------------------------------------------------- +# Declare "parser::yy_" which contents is CONTENT. +m4_define([b4_integral_parser_table_declare], +[m4_ifval([$3], [b4_c_comment([$3], [ ]) +])dnl + static const b4_int_type_for([$2]) yy$1_[[]];dnl +]) + +# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT) +# ------------------------------------------------------------- +# Define "parser::yy_" which contents is CONTENT. +m4_define([b4_integral_parser_table_define], +[ const b4_int_type_for([$2]) + b4_parser_class_name::yy$1_[[]] = + { + $2 + };dnl +]) + + +# b4_symbol_value_template(VAL, [TYPE]) +# ------------------------------------- +# Same as b4_symbol_value, but used in a template method. It makes +# a difference when using variants. +m4_copy([b4_symbol_value], [b4_symbol_value_template]) + + +# b4_lhs_value([TYPE]) +# -------------------- +# Expansion of $$. +m4_define([b4_lhs_value], + [b4_symbol_value([yylhs.value], [$1])]) + + +# b4_lhs_location() +# ----------------- +# Expansion of @$. +m4_define([b4_lhs_location], + [yylhs.location]) + + +# b4_rhs_data(RULE-LENGTH, NUM) +# ----------------------------- +# Return the data corresponding to the symbol #NUM, where the current +# rule has RULE-LENGTH symbols on RHS. +m4_define([b4_rhs_data], + [yystack_@{b4_subtract($@)@}]) + + +# b4_rhs_state(RULE-LENGTH, NUM) +# ------------------------------ +# The state corresponding to the symbol #NUM, where the current +# rule has RULE-LENGTH symbols on RHS. +m4_define([b4_rhs_state], + [b4_rhs_data([$1], [$2]).state]) + + +# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) +# -------------------------------------- +# Expansion of $NUM, where the current rule has RULE-LENGTH +# symbols on RHS. +m4_define([b4_rhs_value], + [b4_symbol_value([b4_rhs_data([$1], [$2]).value], [$3])]) + + +# b4_rhs_location(RULE-LENGTH, NUM) +# --------------------------------- +# Expansion of @NUM, where the current rule has RULE-LENGTH symbols +# on RHS. +m4_define([b4_rhs_location], + [b4_rhs_data([$1], [$2]).location]) + + +# b4_symbol_action(SYMBOL-NUM, KIND) +# ---------------------------------- +# Run the action KIND (destructor or printer) for SYMBOL-NUM. +# Same as in C, but using references instead of pointers. +m4_define([b4_symbol_action], +[b4_symbol_if([$1], [has_$2], - [m4_pushdef([b4_dollar_dollar], - [b4_symbol_value_template([yysym.value], - b4_symbol_if([$1], [has_type], - [b4_symbol([$1], [type])]))])dnl - m4_pushdef([b4_at_dollar], [yysym.location])dnl ++[m4_pushdef([b4_symbol_value], m4_defn([b4_symbol_value_template]))[]dnl ++b4_dollar_pushdef([yysym.value], ++ b4_symbol_if([$1], [has_type], ++ [m4_dquote(b4_symbol([$1], [type]))]), ++ [yysym.location])dnl + b4_symbol_case_([$1]) +b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"]) + b4_symbol([$1], [$2]) +b4_syncline([@oline@], [@ofile@]) + break; + - m4_popdef([b4_at_dollar])dnl - m4_popdef([b4_dollar_dollar])dnl ++m4_popdef([b4_symbol_value])[]dnl ++b4_dollar_popdef[]dnl +])]) + + +m4_pushdef([b4_copyright_years], + [2002-2012]) + m4_define([b4_parser_class_name], [b4_percent_define_get([[parser_class_name]])]) @@@ -670,14 -536,12 +670,12 @@@ m4_if(b4_prefix, [yy], [] YYCDEBUG << "Starting parse" << std::endl; ]m4_ifdef([b4_initial_action], [ - m4_pushdef([b4_at_dollar], [yyla.location])dnl - m4_pushdef([b4_dollar_dollar], [yyla.value])dnl -b4_dollar_pushdef([yylval], [], [yylloc])dnl -/* User initialization code. */ -b4_user_initial_action ++b4_dollar_pushdef([yyla.value], [], [yyla.location])dnl + /* User initialization code. */ + b4_user_initial_action - m4_popdef([b4_dollar_dollar])dnl - m4_popdef([b4_at_dollar])])dnl + b4_dollar_popdef])[]dnl - [ /* Initialize the stacks. The initial state will be pushed in + [ /* Initialize the stack. The initial state will be set in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ diff --cc data/lalr1.java index d3729c6e,d1410a10..1cfaef38 --- a/data/lalr1.java +++ b/data/lalr1.java @@@ -502,12 -458,10 +502,10 @@@ b4_lexer_if([ yyerrstatus_ = 0; ]m4_ifdef([b4_initial_action], [ - m4_pushdef([b4_at_dollar], [yylloc])dnl - m4_pushdef([b4_dollar_dollar], [yylval])dnl + b4_dollar_pushdef([yylval], [], [yylloc])dnl -/* User initialization code. */ -b4_user_initial_action + /* User initialization code. */ + b4_user_initial_action - m4_popdef([b4_dollar_dollar])dnl - m4_popdef([b4_at_dollar])])dnl + b4_dollar_popdef])[]dnl [ /* Initialize the stack. */ yystack.push (yystate, yylval]b4_locations_if([, yylloc])[); diff --cc data/local.mk index 6337f769,00000000..b8db2d64 mode 100644,000000..100644 --- a/data/local.mk +++ b/data/local.mk @@@ -1,44 -1,0 +1,45 @@@ +## Copyright (C) 2002, 2005-2012 Free Software Foundation, Inc. + +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . + +dist_pkgdata_DATA = \ + data/README \ + data/bison.m4 \ + data/c++-skel.m4 \ + data/c++.m4 \ ++ data/c-like.m4 \ + data/c-skel.m4 \ + data/c.m4 \ + data/glr.c \ + data/glr.cc \ + data/java-skel.m4 \ + data/java.m4 \ + data/lalr1.cc \ + data/lalr1.java \ + data/location.cc \ + data/stack.hh \ + data/variant.hh \ + data/yacc.c + +m4sugardir = $(pkgdatadir)/m4sugar +dist_m4sugar_DATA = \ + data/m4sugar/foreach.m4 \ + data/m4sugar/m4sugar.m4 + +xsltdir = $(pkgdatadir)/xslt +dist_xslt_DATA = \ + data/xslt/bison.xsl \ + data/xslt/xml2dot.xsl \ + data/xslt/xml2text.xsl \ + data/xslt/xml2xhtml.xsl diff --cc src/muscle-tab.c index 47d9fb65,5c624982..1168a9c3 --- a/src/muscle-tab.c +++ b/src/muscle-tab.c @@@ -202,14 -202,14 +202,14 @@@ muscle_code_grow (const char *key, cons void muscle_pair_list_grow (const char *muscle, - const char *a1, const char *a2) + const char *a1, const char *a2) { char *pair; - obstack_sgrow (&muscle_obstack, "[[["); - MUSCLE_OBSTACK_SGROW (&muscle_obstack, a1); - obstack_sgrow (&muscle_obstack, "]], [["); - MUSCLE_OBSTACK_SGROW (&muscle_obstack, a2); - obstack_sgrow (&muscle_obstack, "]]]"); + obstack_sgrow (&muscle_obstack, "["); + obstack_quote (&muscle_obstack, a1); + obstack_sgrow (&muscle_obstack, ", "); + obstack_quote (&muscle_obstack, a2); + obstack_sgrow (&muscle_obstack, "]"); obstack_1grow (&muscle_obstack, 0); pair = obstack_finish (&muscle_obstack); muscle_grow (muscle, pair, ",\n"); @@@ -263,12 -266,14 +266,14 @@@ static voi muscle_boundary_grow (char const *key, boundary bound) { char *extension; - MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file); + obstack_sgrow (&muscle_obstack, "[["); + obstack_escape (&muscle_obstack, bound.file); - obstack_1grow (&muscle_obstack, ':'); + obstack_1grow (&muscle_obstack, ':'); obstack_fgrow1 (&muscle_obstack, "%d", bound.line); - obstack_1grow (&muscle_obstack, '.'); + obstack_1grow (&muscle_obstack, '.'); obstack_fgrow1 (&muscle_obstack, "%d", bound.column); + obstack_sgrow (&muscle_obstack, "]]"); - obstack_1grow (&muscle_obstack, '\0'); + obstack_1grow (&muscle_obstack, '\0'); extension = obstack_finish (&muscle_obstack); muscle_grow (key, extension, ""); obstack_free (&muscle_obstack, extension); @@@ -503,9 -475,9 +511,9 @@@ muscle_percent_define_get_loc (char con char const *loc_name; loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); if (!muscle_find_const (loc_name)) - fatal(_("%s: undefined %%define variable %s"), + complain (fatal, _("%s: undefined %%define variable %s"), "muscle_percent_define_get_loc", quote (variable)); - return muscle_location_decode (loc_name); + return location_decode (loc_name); } char const * diff --cc src/muscle-tab.h index 5f701ae4,ddbad408..1f33f8c1 --- a/src/muscle-tab.h +++ b/src/muscle-tab.h @@@ -35,63 -36,46 +35,48 @@@ void muscle_free (void) extern struct obstack muscle_obstack; #define MUSCLE_INSERT_BOOL(Key, Value) \ - do { \ - int v__ = Value; \ - MUSCLE_INSERT_INT (Key, v__); \ - } while(0) + do { \ - int v = Value; \ - MUSCLE_INSERT_INT (Key, v); \ ++ int v__ = Value; \ ++ MUSCLE_INSERT_INT (Key, v__); \ + } while (0) #define MUSCLE_INSERT_INT(Key, Value) \ - do { \ - obstack_fgrow1 (&muscle_obstack, "%d", Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ - } while(0) + do { \ + obstack_fgrow1 (&muscle_obstack, "%d", Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + } while (0) #define MUSCLE_INSERT_LONG_INT(Key, Value) \ - do { \ - obstack_fgrow1 (&muscle_obstack, "%ld", Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ - } while(0) + do { \ + obstack_fgrow1 (&muscle_obstack, "%ld", Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + } while (0) +/* Key -> Value, but don't apply escaping to Value. */ #define MUSCLE_INSERT_STRING_RAW(Key, Value) \ - do { \ - obstack_sgrow (&muscle_obstack, Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ - } while(0) + do { \ + obstack_sgrow (&muscle_obstack, Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + } while (0) +/* Key -> Value, applying M4 escaping to Value. */ #define MUSCLE_INSERT_STRING(Key, Value) \ - do { \ - MUSCLE_OBSTACK_SGROW (&muscle_obstack, Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ - } while(0) - - #define MUSCLE_OBSTACK_SGROW(Obstack, Value) \ - do { \ - char const *p__; \ - for (p__ = Value; *p__; p__++) \ - switch (*p__) \ - { \ - case '$': obstack_sgrow (Obstack, "$]["); break; \ - case '@': obstack_sgrow (Obstack, "@@" ); break; \ - case '[': obstack_sgrow (Obstack, "@{" ); break; \ - case ']': obstack_sgrow (Obstack, "@}" ); break; \ - default: obstack_1grow (Obstack, *p__); break; \ - } \ - } while(0) + do { \ + obstack_escape (&muscle_obstack, Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + } while (0) #define MUSCLE_INSERT_C_STRING(Key, Value) \ - do { \ - MUSCLE_OBSTACK_SGROW (&muscle_obstack, \ - quotearg_style (c_quoting_style, \ - Value)); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ - } while(0) + do { \ + obstack_escape (&muscle_obstack, \ + quotearg_style (c_quoting_style, Value)); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + } while (0) /* Append VALUE to the current value of KEY. If KEY did not already exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously diff --cc src/output.c index 26a6e7fe,d52a7113..c227be22 --- a/src/output.c +++ b/src/output.c @@@ -161,23 -172,23 +171,23 @@@ prepare_symbols (void set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS); for (i = 0; i < nsyms; i++) { - char *cp = quotearg_alloc (symbols[i]->tag, -1, qo); - /* Width of the next token, including the two quotes, the - comma and the space. */ - int width = strlen (cp) + 2; - - if (j + width > 75) - { - obstack_sgrow (&format_obstack, "\n "); - j = 1; - } - - if (i) - obstack_1grow (&format_obstack, ' '); - obstack_escape (&format_obstack, cp); + char *cp = quotearg_alloc (symbols[i]->tag, -1, qo); + /* Width of the next token, including the two quotes, the + comma and the space. */ + int width = strlen (cp) + 2; + + if (j + width > 75) + { + obstack_sgrow (&format_obstack, "\n "); + j = 1; + } + + if (i) + obstack_1grow (&format_obstack, ' '); - MUSCLE_OBSTACK_SGROW (&format_obstack, cp); ++ obstack_escape (&format_obstack, cp); free (cp); - obstack_1grow (&format_obstack, ','); - j += width; + obstack_1grow (&format_obstack, ','); + j += width; } free (qo); obstack_sgrow (&format_obstack, " ]b4_null["); @@@ -352,11 -307,10 +362,11 @@@ user_actions_output (FILE *out for (r = 0; r < nrules; ++r) if (rules[r].action) { - fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1, - rules[r].action_location.start.line); - string_output (out, rules[r].action_location.start.file); - fprintf (out, ")\n[ %s]])\n\n", rules[r].action); + fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ", + rules[r].is_predicate ? "predicate_" : "", + r + 1, rules[r].action_location.start.line); - escaped_output (out, rules[r].action_location.start.file); ++ string_output (out, rules[r].action_location.start.file); + fprintf (out, ")\n[ %s]])\n\n", rules[r].action); } fputs ("])\n\n", out); } diff --cc src/parse-gram.y index 9d9d1a42,e6a27c50..51896994 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@@ -387,12 -345,29 +387,17 @@@ grammar_declaration { grammar_start_symbol_set ($2, @2); } -| "%destructor" "{...}" generic_symlist - { - code_props code; - code_props_symbol_action_init (&code, $2, @2); - code_props_translate_code (&code); - { - symbol_list *list; - for (list = $3; list; list = list->next) - symbol_list_destructor_set (list, &code); - symbol_list_free ($3); - } - } -| "%printer" "{...}" generic_symlist +| code_props_type "{...}" generic_symlist { - symbol_list *list; - for (list = $3; list; list = list->next) - symbol_list_code_props_set (list, $1, @2, $2); - symbol_list_free ($3); + code_props code; + code_props_symbol_action_init (&code, $2, @2); + code_props_translate_code (&code); + { + symbol_list *list; + for (list = $3; list; list = list->next) - symbol_list_printer_set (list, &code); ++ symbol_list_code_props_set (list, $1, &code); + symbol_list_free ($3); + } } | "%default-prec" { diff --cc src/scan-code.l index f6efeffd,31befe91..2fe880ed --- a/src/scan-code.l +++ b/src/scan-code.l @@@ -47,8 -46,11 +47,11 @@@ YY_DECL #define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng); + static char *fetch_type_name (char *cp, char const **type_name, + location dollar_loc); + static void handle_action_dollar (symbol_list *rule, char *cp, - location dollar_loc); + location dollar_loc); static void handle_action_at (symbol_list *rule, char *cp, location at_loc); /* A string to be pushed to obstack after dollar/at has been handled. */ @@@ -177,6 -184,15 +185,15 @@@ ref -?[0-9]+|{id}|"["{id}"]"|"$ STRING_GROW; BEGIN SC_LINE_COMMENT; } + [$@] { - warn_at (*loc, _("stray '%s'"), yytext); ++ complain_at (*loc, Wother, _("stray '%s'"), yytext); + obstack_escape (&obstack_for_string, yytext); + need_semicolon = true; + } + [\[\]] { + obstack_escape (&obstack_for_string, yytext); + need_semicolon = true; + } } @@@ -264,29 -275,17 +265,17 @@@ } - /*-----------------------------------------. - | Escape M4 quoting characters in C code. | - `-----------------------------------------*/ - <*> { - \$ obstack_sgrow (&obstack_for_string, "$]["); - \@ obstack_sgrow (&obstack_for_string, "@@"); - \[ obstack_sgrow (&obstack_for_string, "@{"); - \] obstack_sgrow (&obstack_for_string, "@}"); - } - - /*-----------------------------------------------------. - | By default, grow the string obstack with the input. | - `-----------------------------------------------------*/ + /* Escape M4 quoting characters in C code. */ + [$@\[\]] obstack_escape (&obstack_for_string, yytext); - <*>.|\n STRING_GROW; + /* By default, grow the string obstack with the input. */ + .|\n STRING_GROW; - /* End of processing. */ + /* End of processing. */ - <*><> { - STRING_FINISH; - return last_string; - } + <> STRING_FINISH; return last_string; + } %% @@@ -681,6 -677,31 +670,32 @@@ parse_ref (char *cp, symbol_list *rule int max_left_semantic_context = 0; + /* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its + beginning (i.e., after the opening "<", and return the pointer + immediately after it. */ + + static + char * + fetch_type_name (char *cp, char const **type_name, + location dollar_loc) + { + if (*cp == '<') + { + *type_name = ++cp; + while (*cp != '>') - ++cp; ++ ++cp; + + /* The '>' symbol will be later replaced by '\0'. Original - 'text' is needed for error messages. */ ++ 'text' is needed for error messages. */ + ++cp; + if (untyped_var_seen) - complain_at (dollar_loc, _("explicit type given in untyped grammar")); ++ complain_at (dollar_loc, complaint, ++ _("explicit type given in untyped grammar")); + tag_seen = true; + } + return cp; + } + /*------------------------------------------------------------------. | TEXT is pointing to a wannabee semantic value (i.e., a '$'). | | | @@@ -711,27 -731,14 +725,14 @@@ handle_action_dollar (symbol_list *rule } /* Get the type name if explicit. */ - if (*cp == '<') - { - type_name = ++cp; - while (*cp != '>') - ++cp; - - /* The '>' symbol will be later replaced by '\0'. Original - 'text' is needed for error messages. */ - gt_ptr = cp; - ++cp; - if (untyped_var_seen) - complain_at (dollar_loc, complaint, - _("explicit type given in untyped grammar")); - tag_seen = true; - } + cp = fetch_type_name (cp, &type_name, dollar_loc); n = parse_ref (cp, effective_rule, effective_rule_length, - rule->midrule_parent_rhs_index, text, dollar_loc, '$'); + rule->midrule_parent_rhs_index, text, dollar_loc, '$'); - if (gt_ptr) - *gt_ptr = '\0'; + /* End type_name. */ + if (type_name) + cp[-1] = '\0'; switch (n) { @@@ -776,20 -782,19 +777,20 @@@ if (!type_name) { if (union_seen | tag_seen) - complain_at (dollar_loc, _("$%s of %s has no declared type"), - cp, quote (effective_rule->content.sym->tag)); + complain_at (dollar_loc, complaint, + _("$%s of %s has no declared type"), cp, + quote (effective_rule->content.sym->tag)); else untyped_var_seen = true; - type_name = ""; } - obstack_fgrow3 (&obstack_for_string, - "]b4_rhs_value(%d, %d, [%s])[", - effective_rule_length, n, type_name); + obstack_fgrow2 (&obstack_for_string, - "]b4_rhs_value(%d, %d, ", effective_rule_length, n); ++ "]b4_rhs_value(%d, %d, ", effective_rule_length, n); + obstack_quote (&obstack_for_string, type_name); + obstack_sgrow (&obstack_for_string, ")["); if (n > 0) - symbol_list_n_get (effective_rule, n)->action_props.is_value_used = - true; + symbol_list_n_get (effective_rule, n)->action_props.is_value_used = + true; break; } } diff --cc src/scan-skel.l index 17382a73,862b34fd..b79e5832 --- a/src/scan-skel.l +++ b/src/scan-skel.l @@@ -87,11 -87,11 +87,11 @@@ static void fail_for_invalid_at (char c } /* This pattern must not match more than the previous @ patterns. */ -@[^@{}`(\n]* fail_for_invalid_at (yytext); -\n out_lineno++; ECHO; -[^@\n]+ ECHO; +@[^@{}`(\n]* fail_for_invalid_at (yytext); +\n out_lineno++; ECHO; +[^@\n]+ ECHO; - <> { + <> { if (outname) { free (outname); @@@ -131,18 -131,19 +131,20 @@@ } } - @.? { fail_for_invalid_at (yytext); } + @.? fail_for_invalid_at (yytext); } - { - [ \t\r\n] + + { + [ \t\r\n] continue; - . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; } + . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; } } - { + + { <> { - fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]); + complain (fatal, _("unclosed %s directive in skeleton"), + at_directive_argv[0]); } } diff --cc src/symlist.c index bd9f3c23,69ac8a1b..2bbedb58 --- a/src/symlist.c +++ b/src/symlist.c @@@ -190,26 -223,43 +190,23 @@@ symbol_list_null (symbol_list *node } void -symbol_list_destructor_set (symbol_list *node, code_props const *destructor) -{ - switch (node->content_type) - { - case SYMLIST_SYMBOL: - symbol_destructor_set (node->content.sym, destructor); - break; - case SYMLIST_TYPE: - semantic_type_destructor_set ( - semantic_type_get (node->content.type_name), destructor); - break; - case SYMLIST_DEFAULT_TAGGED: - default_tagged_destructor_set (destructor); - break; - case SYMLIST_DEFAULT_TAGLESS: - default_tagless_destructor_set (destructor); - break; - } -} - -void -symbol_list_printer_set (symbol_list *node, code_props const *printer) +symbol_list_code_props_set (symbol_list *node, code_props_type kind, - location loc, char const *code) ++ code_props const *cprops) { - code_props cprops; - code_props_symbol_action_init (&cprops, code, loc); - code_props_translate_code (&cprops); switch (node->content_type) { case SYMLIST_SYMBOL: - symbol_code_props_set (node->content.sym, kind, &cprops); - symbol_printer_set (node->content.sym, printer); ++ symbol_code_props_set (node->content.sym, kind, cprops); + if (node->content.sym->status == undeclared) + node->content.sym->status = used; break; case SYMLIST_TYPE: - semantic_type_printer_set ( - semantic_type_get (node->content.type_name), printer); - break; - case SYMLIST_DEFAULT_TAGGED: - default_tagged_printer_set (printer); - break; - case SYMLIST_DEFAULT_TAGLESS: - default_tagless_printer_set (printer); + semantic_type_code_props_set + (semantic_type_get (node->content.sem_type->tag, + &node->content.sem_type->location), - kind, &cprops); ++ kind, cprops); + if (node->content.sem_type->status == undeclared) + node->content.sem_type->status = used; break; } } diff --cc src/symlist.h index dd634083,63577f79..03ffebef --- a/src/symlist.h +++ b/src/symlist.h @@@ -113,9 -118,12 +113,8 @@@ uniqstr symbol_list_n_type_name_get (sy /* Check whether the node is a border element of a rule. */ bool symbol_list_null (symbol_list *node); - /** Set the \c \%destructor or \c \%printer for \c node as \c code at - \c loc. */ -/** Set the \c \%destructor for \c node as \c code at \c loc. */ -void symbol_list_destructor_set (symbol_list *node, - code_props const *destructor); - -/** Set the \c \%printer for \c node as \c code at \c loc. */ -void symbol_list_printer_set (symbol_list *node, - code_props const *printer); ++/** Set the \c \%destructor or \c \%printer for \c node as \c cprops. */ +void symbol_list_code_props_set (symbol_list *node, code_props_type kind, - location loc, char const *code); ++ code_props const *cprops); #endif /* !SYMLIST_H_ */ diff --cc src/symtab.h index 93778008,7d8cf982..49eebd4c --- a/src/symtab.h +++ b/src/symtab.h @@@ -97,14 -71,20 +103,14 @@@ struct symbo /** Its \c \%type's location. */ location type_location; - /** Any \c \%destructor declared specifically for this symbol. - - Access this field only through symbol's interface - functions. For example, if symbol::destructor = NULL, a - default \c \%destructor or a per-type \c \%destructor might be - appropriate, and \c symbol_destructor_get will compute the - correct one. */ - code_props destructor; - - /** Any \c \%printer declared specifically for this symbol. + /** Any \c \%destructor (resp. \%printer) declared specificially for this + symbol. - Access this field only through symbol's interface functions. - \sa symbol::destructor */ - code_props printer; + Access this field only through symbol's interface functions. For - Example, if symbol::destructor = NULL (resp. symbol::printer ++ example, if symbol::destructor = NULL (resp. symbol::printer + = NULL), a default \c \%destructor (resp. \%printer) or a per-type - \c symbol_destructor_printer_get will compute the corect one. */ ++ \c symbol_destructor_printer_get will compute the correct one. */ + code_props props[CODE_PROPS_SIZE]; symbol_number number; location prec_location; diff --cc src/system.h index 5613a92f,06fd0f0a..1d0af8fa --- a/src/system.h +++ b/src/system.h @@@ -169,40 -156,83 +169,83 @@@ typedef size_t uintptr_t | Obstacks. | `-----------*/ -# define obstack_chunk_alloc xmalloc -# define obstack_chunk_free free -# include +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free +#include -# define obstack_sgrow(Obs, Str) \ +#define obstack_sgrow(Obs, Str) \ obstack_grow (Obs, Str, strlen (Str)) -# define obstack_fgrow1(Obs, Format, Arg1) \ +#define obstack_fgrow1(Obs, Format, Arg1) \ - do { \ - char buf[4096]; \ - sprintf (buf, Format, Arg1); \ - obstack_grow (Obs, buf, strlen (buf)); \ - } while (0) + do { \ + char buf[4096]; \ + sprintf (buf, Format, Arg1); \ + obstack_grow (Obs, buf, strlen (buf)); \ + } while (0) -# define obstack_fgrow2(Obs, Format, Arg1, Arg2) \ - do { \ - char buf[4096]; \ - sprintf (buf, Format, Arg1, Arg2); \ - obstack_grow (Obs, buf, strlen (buf)); \ +#define obstack_fgrow2(Obs, Format, Arg1, Arg2) \ - do { \ - char buf[4096]; \ - sprintf (buf, Format, Arg1, Arg2); \ - obstack_grow (Obs, buf, strlen (buf)); \ - } while (0) ++ do { \ ++ char buf[4096]; \ ++ sprintf (buf, Format, Arg1, Arg2); \ ++ obstack_grow (Obs, buf, strlen (buf)); \ + } while (0) -# define obstack_fgrow3(Obs, Format, Arg1, Arg2, Arg3) \ +#define obstack_fgrow3(Obs, Format, Arg1, Arg2, Arg3) \ - do { \ - char buf[4096]; \ - sprintf (buf, Format, Arg1, Arg2, Arg3); \ - obstack_grow (Obs, buf, strlen (buf)); \ - } while (0) + do { \ + char buf[4096]; \ + sprintf (buf, Format, Arg1, Arg2, Arg3); \ + obstack_grow (Obs, buf, strlen (buf)); \ + } while (0) -# define obstack_fgrow4(Obs, Format, Arg1, Arg2, Arg3, Arg4) \ +#define obstack_fgrow4(Obs, Format, Arg1, Arg2, Arg3, Arg4) \ - do { \ - char buf[4096]; \ - sprintf (buf, Format, Arg1, Arg2, Arg3, Arg4); \ - obstack_grow (Obs, buf, strlen (buf)); \ - } while (0) + do { \ + char buf[4096]; \ + sprintf (buf, Format, Arg1, Arg2, Arg3, Arg4); \ + obstack_grow (Obs, buf, strlen (buf)); \ + } while (0) + + + /* Output Str escaped for our postprocessing (i.e., escape M4 special + characters). + + For instance "[foo]" -> "@{foo@}", "$$" -> "$][$][". */ + + # define obstack_escape(Obs, Str) \ + do { \ - char const *p; \ - for (p = Str; *p; p++) \ - switch (*p) \ ++ char const *p__; \ ++ for (p__ = Str; *p__; p__++) \ ++ switch (*p__) \ + { \ + case '$': obstack_sgrow (Obs, "$]["); break; \ + case '@': obstack_sgrow (Obs, "@@" ); break; \ + case '[': obstack_sgrow (Obs, "@{" ); break; \ + case ']': obstack_sgrow (Obs, "@}" ); break; \ - default: obstack_1grow (Obs, *p ); break; \ ++ default: obstack_1grow (Obs, *p__ ); break; \ + } \ + } while (0) + + + /* Output Str both quoted for M4 (i.e., embed in [[...]]), and escaped + for our postprocessing (i.e., escape M4 special characters). If + Str is empty (or NULL), output "[]" instead of "[[]]" as it make M4 + programming easier (m4_ifval can be used). + + For instance "[foo]" -> "[[@{foo@}]]", "$$" -> "[[$][$][]]". */ + + # define obstack_quote(Obs, Str) \ + do { \ + char const* obstack_quote_p = Str; \ + if (obstack_quote_p && obstack_quote_p[0]) \ + { \ + obstack_sgrow (Obs, "[["); \ + obstack_escape (Obs, obstack_quote_p); \ + obstack_sgrow (Obs, "]]"); \ + } \ + else \ + obstack_sgrow (Obs, "[]"); \ + } while (0) + + @@@ -210,18 -240,14 +253,14 @@@ | Extensions to use for the output files. | `-----------------------------------------*/ -# ifndef OUTPUT_EXT -# define OUTPUT_EXT ".output" -# endif +#ifndef OUTPUT_EXT +# define OUTPUT_EXT ".output" +#endif -# ifndef TAB_EXT -# define TAB_EXT ".tab" -# endif +#ifndef TAB_EXT +# define TAB_EXT ".tab" +#endif - #ifndef DEFAULT_TMPDIR - # define DEFAULT_TMPDIR "/tmp" - #endif - /*---------------------. diff --cc tests/input.at index 71505cf8,ff1d3924..d6f2084a --- a/tests/input.at +++ b/tests/input.at @@@ -1491,3 -1369,100 +1491,102 @@@ AT_TEST([%define api.prefix foo], [-p b m4_popdef([AT_TEST]) AT_CLEANUP + + + ## -------------- ## + ## Stray $ or @. ## + ## -------------- ## + + AT_SETUP([[Stray $ or @]]) + + # Give %printer and %destructor "<*> exp TOK" instead of "<*>" to + # check that the warnings are reported once, not three times. + + AT_DATA_GRAMMAR([[input.y]], -[[%token TOK ++[[%type exp ++%token TOK TOK2 + %destructor { $%; @%; } <*> exp TOK; + %initial-action { $%; @%; }; + %printer { $%; @%; } <*> exp TOK; + %% + exp: TOK { $%; @%; $$ = $1; }; + ]]) + + AT_BISON_CHECK([[input.y]], 0, [], -[[input.y:10.19: warning: stray '$' -input.y:10.23: warning: stray '@' -input.y:11.19: warning: stray '$' -input.y:11.23: warning: stray '@' -input.y:12.19: warning: stray '$' -input.y:12.23: warning: stray '@' -input.y:14.19: warning: stray '$' -input.y:14.23: warning: stray '@' ++[[input.y:11.19: warning: stray '$' [-Wother] ++input.y:11.23: warning: stray '@' [-Wother] ++input.y:12.19: warning: stray '$' [-Wother] ++input.y:12.23: warning: stray '@' [-Wother] ++input.y:13.19: warning: stray '$' [-Wother] ++input.y:13.23: warning: stray '@' [-Wother] ++input.y:15.19: warning: stray '$' [-Wother] ++input.y:15.23: warning: stray '@' [-Wother] + ]]) + + AT_CLEANUP + + + + ## ---------------- ## + ## Code injection. ## + ## ---------------- ## + + + AT_SETUP([[Code injection]]) + + m4_pattern_allow([^m4_errprintn$]) + + # AT_TEST([MACRO]) + # ---------------- + # Try to have MACRO be run by bison. + m4_pushdef([AT_TEST], + [AT_DATA([[input.y]], + [[%type <$1(DEAD %type)> exp + %token <$1(DEAD %token)> a ++%token b + %initial-action + { + $$; + $<$1(DEAD %initial-action)>$ + }; + %printer + { + $$ + $<$1(DEAD %printer)>$ + } <> <*>; + %lex-param + { + $1(DEAD %lex-param) + }; + %parse-param + { + $1(DEAD %parse-param) + }; + %% + exp: - a a[last] ++ a a[name] b + { + $$; + $][1; + $<$1(DEAD action 1)>$ + $<$1(DEAD action 2)>1 - $<$1(DEAD action 3)>last ++ $<$1(DEAD action 3)>name + $<$1(DEAD action 4)>0 + ; + }; + ]]) + + # FIXME: Provide a means to iterate over all the skeletons. + AT_BISON_CHECK([[-d input.y]]) + AT_BISON_CHECK([[-d -S glr.c input.y]]) + AT_BISON_CHECK([[-d -S lalr1.cc input.y]]) + AT_BISON_CHECK([[-d -S glr.cc input.y]]) + AT_BISON_CHECK([[ -S lalr1.java input.y]]) + ]) + + AT_TEST([m4_errprintn]) + AT_TEST([@:>@m4_errprintn]) + + m4_popdef([AT_TEST]) + + AT_CLEANUP