[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master: merge maint
From: |
Akim Demaille |
Subject: |
master: merge maint |
Date: |
Tue, 13 Jan 2015 15:49:57 +0100 |
This is the merge commit itself:
commit dfd5b89d017bda9801814a5d817f8ab1095e1443
Merge: 13e294e ca5a716
Author: Akim Demaille <address@hidden>
Date: Tue Jan 13 14:43:02 2015 +0100
Merge remote-tracking branch 'origin/maint'
* origin/maint:
tests: split a large test case into several smaller ones
package: a bit of trouble shooting indications
doc: liby's main arms the internationalization
bison: avoid warnings from static code analysis
c++: fix the use of destructors when variants are enabled
style: tests: simplify the handling of some C++ tests
c++: symbols can be empty, so use it
c++: variants: don't leak the lookahead in error recovery
c++: provide a means to clear symbols
c++: clean up the handling of empty symbols
c++: comment and style changes
c++: variants: comparing addresses of typeid.name() is undefined
c++: locations: complete the API and fix comments
build: do not clean figure sources in make clean
diff --cc src/symlist.c
index 38f5fc8,d851463..d70763b
--- a/src/symlist.c
+++ b/src/symlist.c
@@@ -198,14 -192,7 +192,7 @@@ symbol_list_n_get (symbol_list *l, int
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->content->type_name;
- return symbol_list_n_get (l, n)->content.sym->type_name;
++ return symbol_list_n_get (l, n)->content.sym->content->type_name;
}
bool
and this is the diff with the previous state of master:
diff --git a/NEWS b/NEWS
index 490e89e..1877194 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/README-hacking b/README-hacking
index 4b77374..25e4ef3 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
diff --git a/THANKS b/THANKS
index 2436f00..b984910 100644
--- a/THANKS
+++ b/THANKS
@@ -12,6 +12,7 @@ Andreas Schwab address@hidden
Andrew Suffield address@hidden
Angelo Borsotti address@hidden
Anthony Heading address@hidden
+Antonio Silva Correia address@hidden
Arnold Robbins address@hidden
Art Haas address@hidden
Baron Schwartz address@hidden
@@ -82,15 +83,19 @@ Martin Mokrejs address@hidden
Martin Nylin address@hidden
Matt Kraai address@hidden
Matt Rosing address@hidden
+Michael Catanzaro address@hidden
Michael Felt address@hidden
Michael Hayes address@hidden
Michael Raskin address@hidden
+Michel d'Hooge address@hidden
Michiel De Wilde address@hidden
Mickael Labau address@hidden
Mike Castle address@hidden
+Mike Sullivan address@hidden
Neil Booth address@hidden
Nelson H. F. Beebe address@hidden
Nick Bowler address@hidden
+Nicolas Bedon address@hidden
Nicolas Burrus address@hidden
Nicolas Tisserand address@hidden
Noah Friedman address@hidden
@@ -132,6 +137,7 @@ Steve Murphy address@hidden
Sum Wu address@hidden
Théophile Ranquet address@hidden
Thiru Ramakrishnan address@hidden
+Thomas Jahns address@hidden
Tim Josling address@hidden
Tim Landscheidt address@hidden
Tim Van Holder address@hidden
diff --git a/data/c++.m4 b/data/c++.m4
index 7c0fd78..4321c30 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;
@@ -209,8 +212,15 @@ m4_define([b4_public_types_declare],
const semantic_type& v]b4_locations_if([,
const location_type& l])[);
+ /// Destroy the symbol.
~basic_symbol ();
+ /// Destroy contents, and record that is empty.
+ void clear ();
+
+ /// Whether empty.
+ bool empty () const;
+
/// Destructive move, \a s is emptied into this.
void move (basic_symbol& s);
@@ -240,21 +250,23 @@ 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);
/// 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;
- enum { empty = 0 };
-
/// The symbol type.
- /// -1 when this symbol is 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.
@@ -323,9 +335,18 @@ m4_define([b4_public_types_define],
template <typename Base>
inline
]b4_parser_class_name[::basic_symbol<Base>::~basic_symbol ()
+ {
+ clear ();
+ }
+
+ template <typename Base>
+ inline
+ void
+ ]b4_parser_class_name[::basic_symbol<Base>::clear ()
{]b4_variant_if([[
// User destructor.
symbol_number_type yytype = this->type_get ();
+ basic_symbol<Base>& yysym = *this;
switch (yytype)
{
]b4_symbol_foreach([b4_symbol_destructor])dnl
@@ -335,6 +356,15 @@ m4_define([b4_public_types_define],
// Type destructor.
]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[
+ Base::clear ();
+ }
+
+ template <typename Base>
+ inline
+ bool
+ ]b4_parser_class_name[::basic_symbol<Base>::empty () const
+ {
+ return Base::type_get () == empty_symbol;
}
template <typename Base>
@@ -352,7 +382,7 @@ m4_define([b4_public_types_define],
// by_type.
inline
]b4_parser_class_name[::by_type::by_type ()
- : type (empty)
+ : type (empty_symbol)
{}
inline
@@ -367,10 +397,17 @@ m4_define([b4_public_types_define],
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;
+ that.clear ();
}
inline
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 1bbec8a..0e0e17a 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 yyempty_.
+ /// \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
@@ -288,16 +288,21 @@ 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);
/// The (internal) type number (corresponding to \a state).
- /// "empty" when empty.
+ /// \a empty_symbol when empty.
symbol_number_type type_get () const;
- enum { empty = 0 };
+ /// The state number used to denote an empty symbol.
+ enum { empty_state = -1 };
/// The state.
+ /// \a empty when empty.
state_type state;
};
@@ -338,13 +343,12 @@ b4_location_define])])[
/// Pop \a n symbols the three stacks.
void yypop_ (unsigned int n = 1);
- // Constants.
+ /// Constants.
enum
{
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,
@@ -464,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
@@ -533,7 +537,7 @@ m4_if(b4_prefix, [yy], [],
// by_state.
inline
]b4_parser_class_name[::by_state::by_state ()
- : state (empty)
+ : state (empty_state)
{}
inline
@@ -543,10 +547,17 @@ m4_if(b4_prefix, [yy], [],
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;
+ that.clear ();
}
inline
@@ -558,7 +569,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
@@ -574,7 +585,7 @@ m4_if(b4_prefix, [yy], [],
[value], [move], [that.value])],
[[value = that.value;]])[
// that is emptied.
- that.type = empty;
+ that.type = empty_symbol;
}
inline
@@ -695,9 +706,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.
@@ -754,7 +762,7 @@ b4_dollar_popdef])[]dnl
goto yydefault;
// Read a lookahead token.
- if (yyempty)
+ if (yyla.empty ())
{
YYCDEBUG << "Reading a token: ";
try
@@ -768,7 +776,6 @@ b4_dollar_popdef])[]dnl
error (yyexc);
goto yyerrlab1;
}
- yyempty = false;
}
YY_SYMBOL_PRINT ("Next token is", yyla);
@@ -788,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_;
@@ -873,8 +877,7 @@ b4_dollar_popdef])[]dnl
{
++yynerrs_;
error (]b4_join(b4_locations_if([yyla.location]),
- [[yysyntax_error_ (yystack_[0].state,
- yyempty ? yyempty_ : yyla.type_get
())]])[);
+ [[yysyntax_error_ (yystack_[0].state, yyla)]])[);
}
]b4_locations_if([[
@@ -887,10 +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);
- yyempty = true;
+ yyla.clear ();
}
}
@@ -966,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
@@ -986,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 ())
@@ -1008,10 +1011,9 @@ 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([[
- std::string yyres;
// Number of reported tokens (one for the "unexpected", one per
// "expected").
size_t yycount = 0;
@@ -1025,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
@@ -1045,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 != yyempty_)
+ if (!yyla.empty ())
{
+ int yytoken = yyla.type_get ();
yyarg[yycount++] = yytname_[yytoken];
int yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn))
@@ -1089,6 +1092,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/data/location.cc b/data/location.cc
index 8e8a2c2..53fddd4 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/data/variant.hh b/data/variant.hh
index 78c2f94..f918e34 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 <typename T>
variant (const T& t)]b4_parse_assert_if([
- : yytname_ (typeid (T).name ())])[
+ : yytypeid_ (&typeid (T))])[
{
YYASSERT (sizeof (T) <= S);
new (yyas_<T> ()) 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> ()) 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 (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_<T> ();
}
@@ -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_<T> ();
}
@@ -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<T> (), other.as<T> ());
}
@@ -198,7 +198,7 @@ m4_define([b4_variant_define],
destroy ()
{
as<T> ().~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_;])[
};
]])
diff --git a/doc/bison.texi b/doc/bison.texi
index 11bd2d8..1a2b169 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
address@hidden function should have the following type signature:
address@hidden
+The @code{int} value returned by this @code{yyerror} is ignored.
+
+The implementation of Yacc library's @code{main} function is:
+
address@hidden
+int main (void)
address@hidden
+ setlocale (LC_ALL, "");
+ return yyparse ();
address@hidden
address@hidden example
+
address@hidden
+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);
@@ -10686,12 +10700,17 @@ The first, inclusive, position of the range, and the
first beyond.
Forwarded to the @code{end} position.
@end deftypemethod
address@hidden {location} {location} operator+ (const location& @var{end})
address@hidden {location} {location} operator+ (int @var{width})
address@hidden {location} {location} operator+ (int @var{width})
@deftypemethodx {location} {location} operator+= (int @var{width})
address@hidden {location} {location} operator- (int @var{width})
address@hidden {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}.
address@hidden deftypemethod
+
address@hidden {location} {location} operator+ (const location& @var{end})
address@hidden {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/doc/local.mk b/doc/local.mk
index e92ea71..c340452 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
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ee34879..8086f55 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 f90916c..308d1d0 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 38f5fc8..d70763b 100644
--- a/src/symlist.c
+++ b/src/symlist.c
@@ -21,7 +21,6 @@
#include <config.h>
#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->content->type_name;
+ return symbol_list_n_get (l, n)->content.sym->content->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 639b593..aeb4622 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
diff --git a/tests/c++.at b/tests/c++.at
index f1586f5..737037d 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;
}
]])
@@ -168,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.
@@ -225,7 +235,7 @@ typedef std::list<std::string> strings_type;
template <typename T>
inline
std::string
- string_cast (const T& t)
+ to_string (const T& t)
{
std::ostringstream o;
o << t;
@@ -236,15 +246,18 @@ typedef std::list<std::string> strings_type;
%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
+%token COMMA ","
%type <::std::string> item;
// 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<std::string>> list result;
+%type <::std::list<std::string>> list;
%printer { yyo << $$; }
<int> <::std::string> <::std::list<std::string>>;
+%destructor { std::cerr << "Destroy: " << $$ << '\n'; } <*>;
+%destructor { std::cerr << "Destroy: \"" << $$ << "\"\n"; } <::std::string>;
%%
result:
@@ -252,14 +265,14 @@ 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); }
-| NUMBER { if ($][1 == 3) YYERROR; else $$ = string_cast ($][1); }
+ TEXT { std::swap ($$, $][1); }
+| NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); }
;
%%
]AT_TOKEN_CTOR_IF([],
@@ -278,30 +291,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
+ // <http://savannah.gnu.org/support/?108481>.
+ 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([
- *yylloc = location ();])[
- return parser::token::NUMBER;]])[
- }
- 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([
+
+ case ',':
+ ]AT_TOKEN_CTOR_IF([[
+ return parser::make_COMMA (]AT_LOCATION_IF([location ()])[);]], [[
+]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 ();
}
}
@@ -312,8 +338,31 @@ namespace yy
AT_FULL_COMPILE([list])
AT_PARSER_CHECK([./list], 0,
-[(0, 1, 2, 4)
-])
+[[(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
@@ -321,11 +370,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])
@@ -345,6 +394,7 @@ AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
AT_DATA([input.yy],
[[%skeleton "lalr1.cc"
%locations
+%defines
%debug
%%
exp: /* empty */;
@@ -352,7 +402,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
@@ -423,7 +473,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; }
@@ -455,10 +505,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
])
@@ -502,7 +552,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 {
@@ -555,8 +605,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
@@ -576,7 +625,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
@@ -631,8 +680,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
@@ -803,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"); }
@@ -929,9 +977,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]])
@@ -967,7 +1015,7 @@ int yylex (yy::parser::semantic_type *yylval)
void yy::parser::error (std::string const&)
{}
-int main()
+int main ()
{}
])
diff --git a/tests/conflicts.at b/tests/conflicts.at
index 819b992..03b8fa2 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master: merge maint,
Akim Demaille <=