From 478c4a8f495f4b665e6bcb5b5a669089a7bd614a Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 5 Jan 2015 14:31:44 +0100 Subject: [PATCH 01/14] build: do not clean figure sources in make clean "make clean && make" fails in in-tree builds. * doc/local.mk (CLEANDIRS): Replace with... (CLEANFILES): this safer list of files to clean. --- doc/local.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/local.mk b/doc/local.mk index e92ea715..c340452a 100644 --- a/doc/local.mk +++ b/doc/local.mk @@ -132,7 +132,7 @@ endif ## Graphviz examples generation. ## ## ----------------------------- ## -CLEANDIRS += doc/figs +CLEANFILES += $(FIGS_GV:.gv=.eps) $(FIGS_GV:.gv=.pdf) $(FIGS_GV:.gv=.png) FIGS_GV = \ doc/figs/example.gv \ doc/figs/example-reduce.gv doc/figs/example-shift.gv From 56351d4c7b3be8a81953defa7e34503976d3589b Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 5 Jan 2015 18:20:28 +0100 Subject: [PATCH 02/14] c++: locations: complete the API and fix comments There are no support for += between locations, and some comments are wrong. Reported by Alexandre Duret-Lutz. * data/location.cc: Fix. * doc/bison.texi: Document. * tests/c++.at: Check. --- data/location.cc | 30 ++++++++++++++++++------------ doc/bison.texi | 13 +++++++++---- tests/c++.at | 7 +++++++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/data/location.cc b/data/location.cc index 8e8a2c27..53fddd48 100644 --- a/data/location.cc +++ b/data/location.cc @@ -83,7 +83,7 @@ m4_define([b4_position_define], } }; - /// Add and assign a position. + /// Add \a width columns, in place. inline position& operator+= (position& res, int width) { @@ -91,21 +91,21 @@ m4_define([b4_position_define], return res; } - /// Add two position objects. + /// Add \a width columns. inline position operator+ (position res, int width) { return res += width; } - /// Add and assign a position. + /// Subtract \a width columns, in place. inline position& operator-= (position& res, int width) { return res += -width; } - /// Add two position objects. + /// Subtract \a width columns. inline position operator- (position res, int width) { @@ -216,36 +216,42 @@ m4_define([b4_location_define], position end; }; - /// Join two location objects to create a location. - inline location operator+ (location res, const location& end) + /// Join two locations, in place. + inline location& operator+= (location& res, const location& end) { res.end = end.end; return res; } - /// Change end position in place. + /// Join two locations. + inline location operator+ (location res, const location& end) + { + return res += end; + } + + /// Add \a width columns to the end position, in place. inline location& operator+= (location& res, int width) { res.columns (width); return res; } - /// Change end position. + /// Add \a width columns to the end position. inline location operator+ (location res, int width) { return res += width; } - /// Change end position in place. + /// Subtract \a width columns to the end position, in place. inline location& operator-= (location& res, int width) { return res += -width; } - /// Change end position. - inline location operator- (const location& begin, int width) + /// Subtract \a width columns to the end position. + inline location operator- (location res, int width) { - return begin + -width; + return res -= width; } ]b4_percent_define_flag_if([[define_location_comparison]], [[ /// Compare two location objects. diff --git a/doc/bison.texi b/doc/bison.texi index 11bd2d86..d4022159 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -10686,12 +10686,17 @@ The first, inclusive, position of the range, and the first beyond. Forwarded to the @code{end} position. @end deftypemethod -@deftypemethod {location} {location} operator+ (const location& @var{end}) -@deftypemethodx {location} {location} operator+ (int @var{width}) +@deftypemethod {location} {location} operator+ (int @var{width}) @deftypemethodx {location} {location} operator+= (int @var{width}) -@deftypemethodx {location} {location} operator- (int @var{width}) +@deftypemethodx {location} {location} operator- (int @var{width}) @deftypemethodx {location} {location} operator-= (int @var{width}) -Various forms of syntactic sugar. +Various forms of syntactic sugar for @code{columns}. +@end deftypemethod + +@deftypemethod {location} {location} operator+ (const location& @var{end}) +@deftypemethodx {location} {location} operator+= (const location& @var{end}) +Join two locations: starts at the position of the first one, and ends at the +position of the second. @end deftypemethod @deftypemethod {location} {void} step () diff --git a/tests/c++.at b/tests/c++.at index f1586f55..4dbfb760 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -60,8 +60,10 @@ main (void) { int fail = 0; ]AT_YYLTYPE[ loc; fail += check (loc, "1.1"); + fail += check (loc + 10, "1.1-10"); loc += 10; fail += check (loc, "1.1-10"); loc += -5; fail += check (loc, "1.1-5"); + fail += check (loc - 5, "1.1"); loc -= 5; fail += check (loc, "1.1"); // Check that we don't go below. // http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html @@ -70,6 +72,11 @@ main (void) loc.columns (10); loc.lines (10); fail += check (loc, "1.1-11.0"); loc.lines (-2); fail += check (loc, "1.1-9.0"); loc.lines (-10); fail += check (loc, "1.1"); + + ]AT_YYLTYPE[ loc2 (YY_NULLPTR, 5, 10); + fail += check (loc2, "5.10"); + fail += check (loc + loc2, "1.1-5.9"); + loc += loc2; fail += check (loc, "1.1-5.9"); return !fail; } ]]) From 7cf84b13a079740a638fed6b46634bc888bd2622 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 7 Jan 2015 10:24:53 +0100 Subject: [PATCH 03/14] c++: variants: comparing addresses of typeid.name() is undefined Instead of storing and comparing pointers to names of types, store pointers to the typeids, and compares the typeids. Reported by Thomas Jahns. * data/variant.hh (yytname_): Replace with... (yytypeid_): this. --- THANKS | 1 + data/variant.hh | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/THANKS b/THANKS index 2436f004..908498c7 100644 --- a/THANKS +++ b/THANKS @@ -132,6 +132,7 @@ Steve Murphy murf@parsetree.com Sum Wu sum@geekhouse.org Théophile Ranquet theophile.ranquet@gmail.com Thiru Ramakrishnan thiru.ramakrishnan@gmail.com +Thomas Jahns jahns@dkrz.de Tim Josling tej@melbpc.org.au Tim Landscheidt tim@tim-landscheidt.de Tim Van Holder tim.van.holder@pandora.be diff --git a/data/variant.hh b/data/variant.hh index 78c2f945..f918e34c 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -95,13 +95,13 @@ m4_define([b4_variant_define], /// Empty construction. variant ()]b4_parse_assert_if([ - : yytname_ (YY_NULLPTR)])[ + : yytypeid_ (YY_NULLPTR)])[ {} /// Construct and fill. template variant (const T& t)]b4_parse_assert_if([ - : yytname_ (typeid (T).name ())])[ + : yytypeid_ (&typeid (T))])[ { YYASSERT (sizeof (T) <= S); new (yyas_ ()) T (t); @@ -110,7 +110,7 @@ m4_define([b4_variant_define], /// Destruction, allowed only if empty. ~variant () {]b4_parse_assert_if([ - YYASSERT (!yytname_); + YYASSERT (!yytypeid_); ])[} /// Instantiate an empty \a T in here. @@ -118,9 +118,9 @@ m4_define([b4_variant_define], T& build () {]b4_parse_assert_if([ - YYASSERT (!yytname_); + YYASSERT (!yytypeid_); YYASSERT (sizeof (T) <= S); - yytname_ = typeid (T).name ();])[ + yytypeid_ = & typeid (T);])[ return *new (yyas_ ()) T; } @@ -129,9 +129,9 @@ m4_define([b4_variant_define], T& build (const T& t) {]b4_parse_assert_if([ - YYASSERT (!yytname_); + YYASSERT (!yytypeid_); YYASSERT (sizeof (T) <= S); - yytname_ = typeid (T).name ();])[ + yytypeid_ = & typeid (T);])[ return *new (yyas_ ()) T (t); } @@ -140,7 +140,7 @@ m4_define([b4_variant_define], T& as () {]b4_parse_assert_if([ - YYASSERT (yytname_ == typeid (T).name ()); + YYASSERT (*yytypeid_ == typeid (T)); YYASSERT (sizeof (T) <= S);])[ return *yyas_ (); } @@ -150,7 +150,7 @@ m4_define([b4_variant_define], const T& as () const {]b4_parse_assert_if([ - YYASSERT (yytname_ == typeid (T).name ()); + YYASSERT (*yytypeid_ == typeid (T)); YYASSERT (sizeof (T) <= S);])[ return *yyas_ (); } @@ -167,8 +167,8 @@ m4_define([b4_variant_define], void swap (self_type& other) {]b4_parse_assert_if([ - YYASSERT (yytname_); - YYASSERT (yytname_ == other.yytname_);])[ + YYASSERT (yytypeid_); + YYASSERT (*yytypeid_ == *other.yytypeid_);])[ std::swap (as (), other.as ()); } @@ -198,7 +198,7 @@ m4_define([b4_variant_define], destroy () { as ().~T ();]b4_parse_assert_if([ - yytname_ = YY_NULLPTR;])[ + yytypeid_ = YY_NULLPTR;])[ } private: @@ -233,7 +233,7 @@ m4_define([b4_variant_define], } yybuffer_;]b4_parse_assert_if([ /// Whether the content is built: if defined, the name of the stored type. - const char *yytname_;])[ + const std::type_info *yytypeid_;])[ }; ]]) From 8a4ec3595b706180f53458607cd64cca07af24cb Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 09:15:10 +0100 Subject: [PATCH 04/14] c++: comment and style changes * data/c++.m4, data/lalr1.cc: More documentation. Tidy. * tests/c++.at (string_cast): Rename as... (to_string): this C++11 name. --- data/c++.m4 | 6 ++++-- data/lalr1.cc | 14 ++++++++------ tests/c++.at | 8 ++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/data/c++.m4 b/data/c++.m4 index 7c0fd78e..481ea865 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -209,6 +209,7 @@ m4_define([b4_public_types_declare], const semantic_type& v]b4_locations_if([, const location_type& l])[); + /// Destroy the symbol. ~basic_symbol (); /// Destructive move, \a s is emptied into this. @@ -244,16 +245,17 @@ m4_define([b4_public_types_declare], void move (by_type& that); /// The (internal) type number (corresponding to \a type). - /// -1 when this symbol is empty. + /// \a empty when empty. symbol_number_type type_get () const; /// The token. token_type token () const; + /// The type number used to denote an empty symbol. enum { empty = 0 }; /// The symbol type. - /// -1 when this symbol is empty. + /// \a empty when empty. token_number_type type; }; diff --git a/data/lalr1.cc b/data/lalr1.cc index 1bbec8ae..2c38cdf3 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -292,12 +292,14 @@ b4_location_define])])[ void move (by_state& that); /// The (internal) type number (corresponding to \a state). - /// "empty" when empty. + /// \a empty when empty. symbol_number_type type_get () const; + /// The state number used to denote an empty symbol. enum { empty = 0 }; /// The state. + /// \a empty when empty. state_type state; }; @@ -338,7 +340,7 @@ b4_location_define])])[ /// Pop \a n symbols the three stacks. void yypop_ (unsigned int n = 1); - // Constants. + /// Constants. enum { yyeof_ = 0, @@ -695,9 +697,6 @@ m4_if(b4_prefix, [yy], [], int ]b4_parser_class_name[::parse () { - /// Whether yyla contains a lookahead. - bool yyempty = true; - // State. int yyn; /// Length of the RHS of the rule being reduced. @@ -707,6 +706,9 @@ m4_if(b4_prefix, [yy], [], int yynerrs_ = 0; int yyerrstatus_ = 0; + /// Whether yyla contains a lookahead. + bool yyempty = true; + /// The lookahead symbol. symbol_type yyla;]b4_locations_if([[ @@ -1011,7 +1013,6 @@ b4_dollar_popdef])[]dnl b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], [state_type, symbol_number_type])[) const {]b4_error_verbose_if([[ - std::string yyres; // Number of reported tokens (one for the "unexpected", one per // "expected"). size_t yycount = 0; @@ -1089,6 +1090,7 @@ b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], #undef YYCASE_ } + std::string yyres; // Argument number. size_t yyi = 0; for (char const* yyp = yyformat; *yyp; ++yyp) diff --git a/tests/c++.at b/tests/c++.at index 4dbfb760..1aa730f1 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -232,7 +232,7 @@ typedef std::list strings_type; template inline std::string - string_cast (const T& t) + to_string (const T& t) { std::ostringstream o; o << t; @@ -266,7 +266,7 @@ list: item: TEXT { std::swap ($$,$][1); } -| NUMBER { if ($][1 == 3) YYERROR; else $$ = string_cast ($][1); } +| NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); } ; %% ]AT_TOKEN_CTOR_IF([], @@ -304,8 +304,8 @@ namespace yy } else {]AT_TOKEN_CTOR_IF([[ - return parser::make_TEXT (string_cast (stage)]AT_LOCATION_IF([, location ()])[);]], [[ - yylval->BUILD (std::string, string_cast (stage));]AT_LOCATION_IF([ + return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[ + yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([ *yylloc = location ();])[ return parser::token::TEXT;]])[ } From 5422471cbb68d8b5775046702cc92209b0718f58 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 10:04:53 +0100 Subject: [PATCH 05/14] c++: clean up the handling of empty symbols * data/c++.m4, data/lalr1.cc (yyempty_): Remove, replaced by... (empty_symbol, by_state::empty_state): these. (basic_symbol::empty): New. --- data/c++.m4 | 28 ++++++++++++++++++++-------- data/lalr1.cc | 19 +++++++++---------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/data/c++.m4 b/data/c++.m4 index 481ea865..f9ea7e9d 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -174,9 +174,12 @@ m4_define([b4_public_types_declare], /// (External) token type, as returned by yylex. typedef token::yytokentype token_type; - /// Internal symbol number. + /// Symbol type: an internal symbol number. typedef int symbol_number_type; + /// The symbol type number to denote an empty symbol. + enum { empty_symbol = -2 }; + /// Internal symbol number for tokens (subsumed by symbol_number_type). typedef ]b4_int_type_for([b4_translate])[ token_number_type; @@ -212,6 +215,9 @@ m4_define([b4_public_types_declare], /// Destroy the symbol. ~basic_symbol (); + /// Whether empty. + bool empty () const; + /// Destructive move, \a s is emptied into this. void move (basic_symbol& s); @@ -251,12 +257,10 @@ m4_define([b4_public_types_declare], /// The token. token_type token () const; - /// The type number used to denote an empty symbol. - enum { empty = 0 }; - /// The symbol type. - /// \a empty when empty. - token_number_type type; + /// \a empty_symbol when empty. + /// An int, not token_number_type, to be able to store empty_symbol. + int type; }; /// "External" symbols: returned by the scanner. @@ -339,6 +343,14 @@ m4_define([b4_public_types_define], ]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[ } + template + inline + bool + ]b4_parser_class_name[::basic_symbol::empty () const + { + return Base::type_get () == empty_symbol; + } + template inline void @@ -354,7 +366,7 @@ m4_define([b4_public_types_define], // by_type. inline ]b4_parser_class_name[::by_type::by_type () - : type (empty) + : type (empty_symbol) {} inline @@ -372,7 +384,7 @@ m4_define([b4_public_types_define], ]b4_parser_class_name[::by_type::move (by_type& that) { type = that.type; - that.type = empty; + that.type = empty_symbol; } inline diff --git a/data/lalr1.cc b/data/lalr1.cc index 2c38cdf3..1c3481ff 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -214,7 +214,7 @@ b4_location_define])])[ /// Generate an error message. /// \param yystate the state where the error occurred. - /// \param yytoken the lookahead token type, or yyempty_. + /// \param yytoken the lookahead token type, or empty_symbol. virtual std::string yysyntax_error_ (state_type yystate, symbol_number_type yytoken) const; @@ -292,11 +292,11 @@ b4_location_define])])[ void move (by_state& that); /// The (internal) type number (corresponding to \a state). - /// \a empty when empty. + /// \a empty_symbol when empty. symbol_number_type type_get () const; /// The state number used to denote an empty symbol. - enum { empty = 0 }; + enum { empty_state = -1 }; /// The state. /// \a empty when empty. @@ -346,7 +346,6 @@ b4_location_define])])[ yyeof_ = 0, yylast_ = ]b4_last[, ///< Last index in yytable_. yynnts_ = ]b4_nterms_number[, ///< Number of nonterminal symbols. - yyempty_ = -2, yyfinal_ = ]b4_final_state_number[, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, @@ -535,7 +534,7 @@ m4_if(b4_prefix, [yy], [], // by_state. inline ]b4_parser_class_name[::by_state::by_state () - : state (empty) + : state (empty_state) {} inline @@ -548,7 +547,7 @@ m4_if(b4_prefix, [yy], [], ]b4_parser_class_name[::by_state::move (by_state& that) { state = that.state; - that.state = empty; + that.state = empty_state; } inline @@ -560,7 +559,7 @@ m4_if(b4_prefix, [yy], [], ]b4_parser_class_name[::symbol_number_type ]b4_parser_class_name[::by_state::type_get () const { - return state == empty ? 0 : yystos_[state]; + return state == empty_state ? empty_symbol : yystos_[state]; } inline @@ -576,7 +575,7 @@ m4_if(b4_prefix, [yy], [], [value], [move], [that.value])], [[value = that.value;]])[ // that is emptied. - that.type = empty; + that.type = empty_symbol; } inline @@ -876,7 +875,7 @@ b4_dollar_popdef])[]dnl ++yynerrs_; error (]b4_join(b4_locations_if([yyla.location]), [[yysyntax_error_ (yystack_[0].state, - yyempty ? yyempty_ : yyla.type_get ())]])[); + yyempty ? empty_symbol : yyla.type_get ())]])[); } ]b4_locations_if([[ @@ -1046,7 +1045,7 @@ b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], token that will not be accepted due to an error action in a later state. */ - if (yytoken != yyempty_) + if (yytoken != empty_symbol) { yyarg[yycount++] = yytname_[yytoken]; int yyn = yypact_[yystate]; From ee2f433512c2bfc1f8fe0f518f0e80e5e540bf26 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 10:19:10 +0100 Subject: [PATCH 06/14] c++: provide a means to clear symbols The symbol destructor is currently the only means to clear a symbol. Unfortunately during error recovery we might have to clear the lookahead, which is a local variable (yyla) that has not yet reached its end of scope. Rather that duplicating the code to destroy a symbol, or rather than destroying and recreating yyla, let's provide a means to clear a symbol. Reported by Antonio Silva Correia, with an analysis from Michel d'Hooge. * data/c++.m4, data/lalr1.cc (basis_symbol::clear, by_state::clear) (by_type::clear): New. (basic_symbol::~basic_symbol): Use clear. --- THANKS | 2 ++ data/c++.m4 | 24 +++++++++++++++++++++++- data/lalr1.cc | 12 +++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/THANKS b/THANKS index 908498c7..98ec269d 100644 --- a/THANKS +++ b/THANKS @@ -12,6 +12,7 @@ Andreas Schwab schwab@suse.de Andrew Suffield asuffield@users.sourceforge.net Angelo Borsotti angelo.borsotti@gmail.com Anthony Heading ajrh@ajrh.net +Antonio Silva Correia amsilvacorreia@hotmail.com Arnold Robbins arnold@skeeve.com Art Haas ahaas@neosoft.com Baron Schwartz baron@sequent.org @@ -85,6 +86,7 @@ Matt Rosing rosing@peakfive.com Michael Felt mamfelt@gmail.com Michael Hayes m.hayes@elec.canterbury.ac.nz Michael Raskin 7c6f434c@mail.ru +Michel d'Hooge michel.dhooge@gmail.com Michiel De Wilde mdewilde.agilent@gmail.com Mickael Labau labau_m@epita.fr Mike Castle dalgoda@ix.netcom.com diff --git a/data/c++.m4 b/data/c++.m4 index f9ea7e9d..8494d214 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -215,6 +215,9 @@ m4_define([b4_public_types_declare], /// Destroy the symbol. ~basic_symbol (); + /// Destroy contents, and record that is empty. + void clear (); + /// Whether empty. bool empty () const; @@ -247,6 +250,9 @@ m4_define([b4_public_types_declare], /// Constructor from (external) token numbers. by_type (kind_type t); + /// Record that this symbol is empty. + void clear (); + /// Steal the symbol type from \a that. void move (by_type& that); @@ -329,6 +335,14 @@ m4_define([b4_public_types_define], template inline ]b4_parser_class_name[::basic_symbol::~basic_symbol () + { + clear (); + } + + template + inline + void + ]b4_parser_class_name[::basic_symbol::clear () {]b4_variant_if([[ // User destructor. symbol_number_type yytype = this->type_get (); @@ -341,6 +355,7 @@ m4_define([b4_public_types_define], // Type destructor. ]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[ + Base::clear (); } template @@ -379,12 +394,19 @@ m4_define([b4_public_types_define], : type (yytranslate_ (t)) {} + inline + void + ]b4_parser_class_name[::by_type::clear () + { + type = empty_symbol; + } + inline void ]b4_parser_class_name[::by_type::move (by_type& that) { type = that.type; - that.type = empty_symbol; + that.clear (); } inline diff --git a/data/lalr1.cc b/data/lalr1.cc index 1c3481ff..9ab9421e 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -288,6 +288,9 @@ b4_location_define])])[ /// Copy constructor. by_state (const by_state& other); + /// Record that this symbol is empty. + void clear (); + /// Steal the symbol type from \a that. void move (by_state& that); @@ -542,12 +545,19 @@ m4_if(b4_prefix, [yy], [], : state (other.state) {} + inline + void + ]b4_parser_class_name[::by_state::clear () + { + state = empty_state; + } + inline void ]b4_parser_class_name[::by_state::move (by_state& that) { state = that.state; - that.state = empty_state; + that.clear (); } inline From 00cebd11d48e07065cd012929d96085cfe37d07b Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 11:19:57 +0100 Subject: [PATCH 07/14] c++: variants: don't leak the lookahead in error recovery During error recovery, when discarding the lookeahead, we don't destroy it, which is caught by parse.assert assertions. Reported by Antonio Silva Correia. With an analysis and suggested patch from Michel d'Hooge. * tests/c++.at (Variants): Strengthen the test to try syntax errors with discarded lookahead. --- data/lalr1.cc | 1 + tests/c++.at | 69 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/data/lalr1.cc b/data/lalr1.cc index 9ab9421e..d3ab008b 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -901,6 +901,7 @@ b4_dollar_popdef])[]dnl else if (!yyempty) { yy_destroy_ ("Error: discarding", yyla); + yyla.clear (); yyempty = true; } } diff --git a/tests/c++.at b/tests/c++.at index 1aa730f1..30304019 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -175,6 +175,9 @@ AT_CLEANUP ## Variants. ## ## ---------- ## +# Check that the variants are properly supported, including in error +# recovery. + # AT_TEST([DIRECTIVES]) # --------------------- # Check the support of variants in C++, with the additional DIRECTIVES. @@ -243,6 +246,7 @@ typedef std::list strings_type; %token <::std::string> TEXT; %token NUMBER; %token END_OF_FILE 0; +%token COMMA "," %type <::std::string> item; // Using the template type to exercize its parsing. @@ -259,13 +263,13 @@ result: ; list: - /* nothing */ { /* Generates an empty string list */ } -| list item { std::swap ($$,$][1); $$.push_back ($][2); } -| list error { std::swap ($$,$][1); } + item { $$.push_back ($][1); } +| list "," item { std::swap ($$, $][1); $$.push_back ($][3); } +| list error { std::swap ($$, $][1); } ; item: - TEXT { std::swap ($$,$][1); } + TEXT { std::swap ($$, $][1); } | NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); } ; %% @@ -285,30 +289,43 @@ namespace yy parser::location_type* yylloc])[)]])[ {]AT_LOCATION_IF([ typedef parser::location_type location;])[ - static int stage = -1; - ++stage; - if (stage == STAGE_MAX) - {]AT_TOKEN_CTOR_IF([[ + // The 5 is a syntax error whose recovery requires that we discard + // the lookahead. This tests a regression, see + // . + static char const *input = "0,1,2,3,45,6"; + switch (int stage = *input++) + { + case 0:]AT_TOKEN_CTOR_IF([[ return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]], [AT_LOCATION_IF([ *yylloc = location ();])[ return parser::token::END_OF_FILE;]])[ - } - else if (stage % 2) - {]AT_TOKEN_CTOR_IF([[ - return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]], -[[ - yylval->BUILD (int, stage);]AT_LOCATION_IF([ + + case ',': + ]AT_TOKEN_CTOR_IF([[ + return parser::make_COMMA (]AT_LOCATION_IF([location ()])[);]], [[ +]AT_LOCATION_IF([ *yylloc = location ();])[ - return parser::token::NUMBER;]])[ - } - else - {]AT_TOKEN_CTOR_IF([[ - return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[ - yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([ - *yylloc = location ();])[ - return parser::token::TEXT;]])[ - } + return parser::token::COMMA;]])[ + + default: + stage = stage - '0'; + if (stage % 2) + {]AT_TOKEN_CTOR_IF([[ + return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]], [[ + yylval->BUILD (int, stage);]AT_LOCATION_IF([ + *yylloc = location ();])[ + return parser::token::NUMBER;]])[ + } + else + {]AT_TOKEN_CTOR_IF([[ + return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[ + yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([ + *yylloc = location ();])[ + return parser::token::TEXT;]])[ + } + } + abort (); } } @@ -319,7 +336,7 @@ namespace yy AT_FULL_COMPILE([list]) AT_PARSER_CHECK([./list], 0, -[(0, 1, 2, 4) +[(0, 1, 2, 4, 6) ]) AT_BISON_OPTION_POPDEFS @@ -328,11 +345,11 @@ AT_CLEANUP AT_TEST([[%skeleton "lalr1.cc" ]]) AT_TEST([[%skeleton "lalr1.cc" %define parse.assert]]) -AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert]]) +AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %locations]]) AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]]) AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor]]) AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]]) -AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]]) +AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_} %locations]]) m4_popdef([AT_TEST]) From 821394a3c806eb8154337126bebf0c70b3662a3e Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 13:37:16 +0100 Subject: [PATCH 08/14] c++: symbols can be empty, so use it The previous patches ensure that symbols (symbol_type and stack_symbol_type) can be empty, cleared, and their emptiness can be checked. Therefore, yyempty, which codes whether yyla is empty or not, is now useless. In C skeletons (e.g., yacc.c), the fact that the lookahead is empty is coded by "yychar = YYEMPTY", which is exactly what this patch restores, since yychar/yytoken corresponds to yyla.type. * data/lalr1.cc (yyempty): Remove. Rather, depend on yyla.empty (). --- data/lalr1.cc | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/data/lalr1.cc b/data/lalr1.cc index d3ab008b..0e0e17ae 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -214,9 +214,9 @@ b4_location_define])])[ /// Generate an error message. /// \param yystate the state where the error occurred. - /// \param yytoken the lookahead token type, or empty_symbol. + /// \param yyla the lookahead token. virtual std::string yysyntax_error_ (state_type yystate, - symbol_number_type yytoken) const; + const symbol_type& yyla) const; /// Compute post-reduction state. /// \param yystate the current state @@ -468,7 +468,7 @@ m4_if(b4_prefix, [yy], [], #endif // !]b4_api_PREFIX[DEBUG #define yyerrok (yyerrstatus_ = 0) -#define yyclearin (yyempty = true) +#define yyclearin (yyla.clear ()) #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab @@ -715,9 +715,6 @@ m4_if(b4_prefix, [yy], [], int yynerrs_ = 0; int yyerrstatus_ = 0; - /// Whether yyla contains a lookahead. - bool yyempty = true; - /// The lookahead symbol. symbol_type yyla;]b4_locations_if([[ @@ -765,7 +762,7 @@ b4_dollar_popdef])[]dnl goto yydefault; // Read a lookahead token. - if (yyempty) + if (yyla.empty ()) { YYCDEBUG << "Reading a token: "; try @@ -779,7 +776,6 @@ b4_dollar_popdef])[]dnl error (yyexc); goto yyerrlab1; } - yyempty = false; } YY_SYMBOL_PRINT ("Next token is", yyla); @@ -799,9 +795,6 @@ b4_dollar_popdef])[]dnl goto yyreduce; } - // Discard the token being shifted. - yyempty = true; - // Count tokens shifted since error; after three, turn off error status. if (yyerrstatus_) --yyerrstatus_; @@ -884,8 +877,7 @@ b4_dollar_popdef])[]dnl { ++yynerrs_; error (]b4_join(b4_locations_if([yyla.location]), - [[yysyntax_error_ (yystack_[0].state, - yyempty ? empty_symbol : yyla.type_get ())]])[); + [[yysyntax_error_ (yystack_[0].state, yyla)]])[); } ]b4_locations_if([[ @@ -898,11 +890,10 @@ b4_dollar_popdef])[]dnl // Return failure if at end of input. if (yyla.type_get () == yyeof_) YYABORT; - else if (!yyempty) + else if (!yyla.empty ()) { yy_destroy_ ("Error: discarding", yyla); yyla.clear (); - yyempty = true; } } @@ -978,7 +969,7 @@ b4_dollar_popdef])[]dnl goto yyreturn; yyreturn: - if (!yyempty) + if (!yyla.empty ()) yy_destroy_ ("Cleanup: discarding lookahead", yyla); /* Do not reclaim the symbols of the rule whose action triggered @@ -998,7 +989,7 @@ b4_dollar_popdef])[]dnl << std::endl; // Do not try to display the values of the reclaimed symbols, // as their printer might throw an exception. - if (!yyempty) + if (!yyla.empty ()) yy_destroy_ (YY_NULLPTR, yyla); while (1 < yystack_.size ()) @@ -1020,8 +1011,8 @@ b4_dollar_popdef])[]dnl // Generate an error message. std::string ]b4_parser_class_name[::yysyntax_error_ (]dnl -b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], - [state_type, symbol_number_type])[) const +b4_error_verbose_if([state_type yystate, const symbol_type& yyla], + [state_type, const symbol_type&])[) const {]b4_error_verbose_if([[ // Number of reported tokens (one for the "unexpected", one per // "expected"). @@ -1036,7 +1027,7 @@ b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - - The only way there can be no lookahead present (in yytoken) is + - The only way there can be no lookahead present (in yyla) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to @@ -1056,8 +1047,9 @@ b4_error_verbose_if([state_type yystate, symbol_number_type yytoken], token that will not be accepted due to an error action in a later state. */ - if (yytoken != empty_symbol) + if (!yyla.empty ()) { + int yytoken = yyla.type_get (); yyarg[yycount++] = yytname_[yytoken]; int yyn = yypact_[yystate]; if (!yy_pact_value_is_default_ (yyn)) From e1d06b523570e462923d4e9e80465ae4772754fa Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 8 Jan 2015 14:03:09 +0100 Subject: [PATCH 09/14] style: tests: simplify the handling of some C++ tests * tests/c++.at: here. (Doxygen): Pass %define, so that files such as position.hh etc. are generated, instead of putting everything into input.hh. --- tests/c++.at | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tests/c++.at b/tests/c++.at index 30304019..e6d69831 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -369,6 +369,7 @@ AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"]) AT_DATA([input.yy], [[%skeleton "lalr1.cc" %locations +%defines %debug %% exp: /* empty */; @@ -376,7 +377,7 @@ exp: /* empty */; ]AT_YYERROR_DEFINE[ ]]) -AT_BISON_CHECK([-o input.cc input.yy], 0) +AT_BISON_CHECK([-o input.cc input.yy]) AT_DATA([Doxyfile], [# The PROJECT_NAME tag is a single word (or a sequence of words @@ -447,7 +448,7 @@ AT_CHECK_DOXYGEN([Private]) # so don't check compilation. m4_pushdef([AT_TEST], [AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace {$1}]) -AT_DATA_GRAMMAR([[input.y]], +AT_DATA_GRAMMAR([[input.yy]], [[%language "C++" %define api.namespace {]$1[} %union { int i; } @@ -479,10 +480,10 @@ void ]]) -AT_BISON_CHECK([[-o input.cc input.y]]) +AT_BISON_CHECK([[-o input.cc input.yy]]) m4_if([$#], [1], -[AT_COMPILE_CXX([[input]], [[input.cc]]) +[AT_COMPILE_CXX([[input]]) AT_PARSER_CHECK([[./input]])]) AT_BISON_OPTION_POPDEFS ]) @@ -526,7 +527,7 @@ AT_SETUP([[Syntax error discarding no lookahead]]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"]) -AT_DATA_GRAMMAR([[input.yy]], +AT_DATA_GRAMMAR([[input.y]], [[%skeleton "lalr1.cc" %code { @@ -579,8 +580,7 @@ yy::parser::error (const std::string &m) ]AT_MAIN_DEFINE[ ]]) -AT_BISON_CHECK([[-o input.cc input.yy]]) -AT_COMPILE_CXX([[input]]) +AT_FULL_COMPILE([[input]]) # This used to print "Discarding 'a'." again at the end. AT_PARSER_CHECK([[./input]], [[1]], [[]], [[syntax error @@ -600,7 +600,7 @@ AT_SETUP([[Syntax error as exception]]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"]) -AT_DATA_GRAMMAR([[input.yy]], +AT_DATA_GRAMMAR([[input.y]], [[%skeleton "lalr1.cc" %code @@ -655,8 +655,7 @@ yy::parser::error (const std::string &m) ]AT_MAIN_DEFINE[ ]]) -AT_BISON_CHECK([[-o input.cc input.yy]]) -AT_COMPILE_CXX([[input]]) +AT_FULL_COMPILE([[input]]) AT_PARSER_CHECK([[./input]], [[0]], [[]], [[error: invalid expression @@ -953,9 +952,9 @@ AT_TEST([%define api.value.type variant], [without]) m4_popdef([AT_TEST]) -## ------------------------------------ ## -## C++ GLR parser identifier shadowing ## -## ------------------------------------ ## +## ------------------------------------- ## +## C++ GLR parser identifier shadowing. ## +## ------------------------------------- ## AT_SETUP([[C++ GLR parser identifier shadowing]]) @@ -991,7 +990,7 @@ int yylex (yy::parser::semantic_type *yylval) void yy::parser::error (std::string const&) {} -int main() +int main () {} ]) From ee028dceff390a23da391900b5b7fe651cfe320c Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Fri, 9 Jan 2015 12:01:22 +0100 Subject: [PATCH 10/14] c++: fix the use of destructors when variants are enabled When using variants, destructors generate invalid code. Reported by Michael Catanzaro. * data/c++.m4 (~basic_symbol): b4_symbol_foreach works on yysym: define it. * tests/c++.at (Variants): Check it. --- NEWS | 14 +++++++++----- THANKS | 1 + data/c++.m4 | 1 + tests/c++.at | 35 ++++++++++++++++++++++++++++++----- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 490e89ed..18771946 100644 --- a/NEWS +++ b/NEWS @@ -4,19 +4,23 @@ GNU Bison NEWS ** Bug fixes -*** Named %union support +*** C++ with Variants (lalr1.cc) + + Problems with %destructor and '%define parse.assert' have been fixed. + +*** Named %union support (yacc.c, glr.c) Bison 3.0 introduced a regression on named %union such as %union foo { int ival; }; - The possibility to use a name was introduced ``for Yacc compatibility''. + The possibility to use a name was introduced "for Yacc compatibility". It is however not required by POSIX Yacc, and its usefulness is not clear. -*** %define api.value.type union with %defines +*** %define api.value.type union with %defines (yacc.c, glr.c) - The yacc.c and glr.c parsers were broken when %defines was used - together with "%define api.value.type union". + The C parsers were broken when %defines was used together with "%define + api.value.type union". *** Redeclarations are reported in proper order diff --git a/THANKS b/THANKS index 98ec269d..d5feb16e 100644 --- a/THANKS +++ b/THANKS @@ -83,6 +83,7 @@ Martin Mokrejs mmokrejs@natur.cuni.cz Martin Nylin martin.nylin@linuxmail.org Matt Kraai kraai@alumni.cmu.edu Matt Rosing rosing@peakfive.com +Michael Catanzaro mcatanzaro@gnome.org Michael Felt mamfelt@gmail.com Michael Hayes m.hayes@elec.canterbury.ac.nz Michael Raskin 7c6f434c@mail.ru diff --git a/data/c++.m4 b/data/c++.m4 index 8494d214..4321c305 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -346,6 +346,7 @@ m4_define([b4_public_types_define], {]b4_variant_if([[ // User destructor. symbol_number_type yytype = this->type_get (); + basic_symbol& yysym = *this; switch (yytype) { ]b4_symbol_foreach([b4_symbol_destructor])dnl diff --git a/tests/c++.at b/tests/c++.at index e6d69831..737037d3 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -252,10 +252,12 @@ typedef std::list strings_type; // Using the template type to exercize its parsing. // Starting with :: to ensure we don't output "<::" which starts by the // digraph for the left square bracket. -%type <::std::list> list result; +%type <::std::list> list; %printer { yyo << $$; } <::std::string> <::std::list>; +%destructor { std::cerr << "Destroy: " << $$ << '\n'; } <*>; +%destructor { std::cerr << "Destroy: \"" << $$ << "\"\n"; } <::std::string>; %% result: @@ -336,8 +338,31 @@ namespace yy AT_FULL_COMPILE([list]) AT_PARSER_CHECK([./list], 0, -[(0, 1, 2, 4, 6) -]) +[[(0, 1, 2, 4, 6) +]], +[[Destroy: "" +Destroy: "0" +Destroy: (0) +Destroy: 1 +Destroy: "1" +Destroy: () +Destroy: "" +Destroy: "2" +Destroy: () +Destroy: "" +Destroy: 3 +Destroy: () +Destroy: "" +Destroy: "4" +Destroy: () +Destroy: () +Destroy: 5 +Destroy: () +Destroy: "" +Destroy: "6" +Destroy: () +Destroy: (0, 1, 2, 4, 6) +]]) AT_BISON_OPTION_POPDEFS AT_CLEANUP @@ -826,10 +851,10 @@ list: item: 'a' { $$ = $][1; } -| 'e' { YYUSE ($$); YYUSE($][1); error ("syntax error"); } +| 'e' { YYUSE ($$); YYUSE ($][1); error ("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; } +| 'E' 'a' { YYUSE ($][1); $$ = $][2; } | 'R' { ]AT_VARIANT_IF([], [$$ = YY_NULLPTR; delete $][1]; )[YYERROR; } | 'p' { $$ = $][1; } | 's' { $$ = $][1; throw std::runtime_error ("reduction"); } From 671850a1c3e1aaac93a89fabc6d810be6a4a77fe Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Fri, 9 Jan 2015 14:21:09 +0100 Subject: [PATCH 11/14] bison: avoid warnings from static code analysis A static analysis tool reports that some callers of symbol_list_n_get might get NULL and not handle it properly. This is not the case, yet we can suppress this pattern. Reported by Mike Sullivan. * src/symlist.c (symbol_list_n_get): Actually it is never called to return 0. Enforce this postcondition via aver. (symbol_list_n_type_name_get): Simplify accordingly. In particular, discards a (translated) useless error message. * src/symlist.h: Adjust documentation. * src/scan-code.l: Style change. --- THANKS | 1 + po/POTFILES.in | 1 - src/scan-code.l | 2 +- src/symlist.c | 27 +++++++-------------------- src/symlist.h | 5 ++++- 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/THANKS b/THANKS index d5feb16e..4fc99849 100644 --- a/THANKS +++ b/THANKS @@ -91,6 +91,7 @@ Michel d'Hooge michel.dhooge@gmail.com Michiel De Wilde mdewilde.agilent@gmail.com Mickael Labau labau_m@epita.fr Mike Castle dalgoda@ix.netcom.com +Mike Sullivan Mike.sullivan@Oracle.COM Neil Booth NeilB@earthling.net Nelson H. F. Beebe beebe@math.utah.edu Nick Bowler nbowler@elliptictech.com diff --git a/po/POTFILES.in b/po/POTFILES.in index ee34879a..8086f556 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -15,7 +15,6 @@ src/reduce.c src/scan-code.l src/scan-gram.l src/scan-skel.l -src/symlist.c src/symtab.c djgpp/subpipe.c diff --git a/src/scan-code.l b/src/scan-code.l index f90916c1..308d1d0d 100644 --- a/src/scan-code.l +++ b/src/scan-code.l @@ -711,7 +711,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) "]b4_rhs_value(%d, %d, ", effective_rule_length, n); obstack_quote (&obstack_for_string, type_name); obstack_sgrow (&obstack_for_string, ")["); - if (n > 0) + if (0 < n) symbol_list_n_get (effective_rule, n)->action_props.is_value_used = true; break; diff --git a/src/symlist.c b/src/symlist.c index b58cf5c7..d8514636 100644 --- a/src/symlist.c +++ b/src/symlist.c @@ -21,7 +21,6 @@ #include #include "system.h" -#include "complain.h" #include "symlist.h" /*--------------------------------------. @@ -174,22 +173,17 @@ symbol_list * symbol_list_n_get (symbol_list *l, int n) { int i; - - if (n < 0) - return NULL; - + aver (0 <= n); for (i = 0; i < n; ++i) { l = l->next; - if (l == NULL - || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL)) - return NULL; + aver (l); } - + aver (l->content_type == SYMLIST_SYMBOL); + aver (l->content.sym); return l; } - /*--------------------------------------------------------------. | Get the data type (alternative in the union) of the value for | | symbol N in symbol list L. | @@ -198,21 +192,14 @@ symbol_list_n_get (symbol_list *l, int n) uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n) { - l = symbol_list_n_get (l, n); - if (!l) - { - complain (&loc, complaint, _("invalid $ value: $%d"), n); - return NULL; - } - aver (l->content_type == SYMLIST_SYMBOL); - return l->content.sym->type_name; + return symbol_list_n_get (l, n)->content.sym->type_name; } bool symbol_list_null (symbol_list *node) { - return !node || - (node->content_type == SYMLIST_SYMBOL && !(node->content.sym)); + return (!node + || (node->content_type == SYMLIST_SYMBOL && !node->content.sym)); } void diff --git a/src/symlist.h b/src/symlist.h index 639b593b..aeb46229 100644 --- a/src/symlist.h +++ b/src/symlist.h @@ -116,7 +116,10 @@ void symbol_list_free (symbol_list *list); /** Return the length of \c l. */ int symbol_list_length (symbol_list const *l); -/** Get item \c n in symbol list \c l. */ +/** Get item \c n in symbol list \c l. + ** \pre 0 <= n + ** \post res != NULL + **/ symbol_list *symbol_list_n_get (symbol_list *l, int n); /* Get the data type (alternative in the union) of the value for From 9a91e7f24626da71bb4b5f0bd76159f34ba2b6f6 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 12 Jan 2015 11:34:42 +0100 Subject: [PATCH 12/14] doc: liby's main arms the internationalization Reported by Nicolas Bedon. * doc/bison.texi (Yacc Library): Document the call the setlocale. --- THANKS | 1 + doc/bison.texi | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/THANKS b/THANKS index 4fc99849..b9849103 100644 --- a/THANKS +++ b/THANKS @@ -95,6 +95,7 @@ Mike Sullivan Mike.sullivan@Oracle.COM Neil Booth NeilB@earthling.net Nelson H. F. Beebe beebe@math.utah.edu Nick Bowler nbowler@elliptictech.com +Nicolas Bedon nicolas.bedon@univ-rouen.fr Nicolas Burrus nicolas.burrus@epita.fr Nicolas Tisserand nicolas.tisserand@epita.fr Noah Friedman friedman@gnu.org diff --git a/doc/bison.texi b/doc/bison.texi index d4022159..1a2b169b 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -10382,9 +10382,23 @@ declare @code{yyerror} as follows: int yyerror (char const *); @end example -Bison ignores the @code{int} value returned by this @code{yyerror}. -If you use the Yacc library's @code{main} function, your -@code{yyparse} function should have the following type signature: +@noindent +The @code{int} value returned by this @code{yyerror} is ignored. + +The implementation of Yacc library's @code{main} function is: + +@example +int main (void) +@{ + setlocale (LC_ALL, ""); + return yyparse (); +@} +@end example + +@noindent +so if you use it, the internationalization support is enabled (e.g., error +messages are translated), and your @code{yyparse} function should have the +following type signature: @example int yyparse (void); From d72642d6915dbecd28609d307ef4676d1d5ab448 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 12 Jan 2015 12:11:53 +0100 Subject: [PATCH 13/14] package: a bit of trouble shooting indications * README-hacking: here. --- README-hacking | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README-hacking b/README-hacking index 4b773745..25e4ef34 100644 --- a/README-hacking +++ b/README-hacking @@ -103,15 +103,17 @@ to perform the first checkout of the submodules, run $ git submodule update --init -Git submodule support is weak before versions 1.6 and later, you -should probably upgrade Git if your version is older. +Git submodule support is weak before versions 1.6 and later, upgrade Git if +your version is older. The next step is to get other files needed to build, which are extracted from other source packages: $ ./bootstrap -And there you are! Just +If it fails with missing symbols (e.g., "error: possibly undefined macro: +AC_PROG_GNU_M4"), you are likely to have forgotten the submodule +initialization part. Otherwise, there you are! Just $ ./configure $ make From ca5a716303f9262572764671ce4e51a0a08d4c94 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Tue, 13 Jan 2015 14:15:47 +0100 Subject: [PATCH 14/14] tests: split a large test case into several smaller ones * tests/conflicts.at (AT_CONSISTENT_ERRORS_CHECK): Move AT_SETUP/AT_CLEANUP into it, so that we don't skip non Java tests following a test case in Java. --- tests/conflicts.at | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/conflicts.at b/tests/conflicts.at index 819b992d..03b8fa20 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -393,10 +393,10 @@ AT_CLEANUP ## parse.error=verbose and consistent errors. ## ## ------------------------------------------- ## -AT_SETUP([[parse.error=verbose and consistent errors]]) - m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [ +AT_SETUP([[parse.error=verbose and consistent errors: $1]]) + AT_BISON_OPTION_PUSHDEFS([$1]) m4_pushdef([AT_YYLEX_PROTOTYPE], @@ -483,7 +483,11 @@ m4_popdef([AT_EXPECTING]) m4_popdef([AT_YYLEX_PROTOTYPE]) AT_BISON_OPTION_POPDEFS -]) +AT_CLEANUP +]) dnl AT_CONSISTENT_ERRORS_CHECK + + + m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR], [[%nonassoc 'a'; @@ -653,7 +657,6 @@ m4_popdef([AT_USER_ACTION_INPUT]) m4_popdef([AT_CONSISTENT_ERRORS_CHECK]) -AT_CLEANUP