[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RFC: lalr1.cc: support move semantics
From: |
Akim Demaille |
Subject: |
RFC: lalr1.cc: support move semantics |
Date: |
Sun, 9 Sep 2018 14:33:52 +0200 |
Hi,
This is my proposal to add support for move semantics to Bison.
The commit message should be clear enough. I’d be happy to receive
comments/reviews.
Frank’s contribution addressed several other issues. Here, I’m
focusing only on move-semantics.
There’s probably more cleanup to do. For instance, it’s unpleasing
that some of YY* macros are intended for the user if she wants to
them, while other are definitely implementation details (e.g.,
YY_RVREF). We should have a consistent approach to clearly separate
public from private macros.
There’s also probably room for improvement in plenty of places.
I have added an example/variant-11.yy that _requires_ move semantics
for some of its semantics values. Please, check it.
commit e5395adb79d8ca1c88a14d4da4280e2ca612ff5d
Author: Akim Demaille <address@hidden>
Date: Sun Aug 12 18:05:47 2018 +0200
lalr1.cc: support move semantics
Symbols (terminal/non terminal) are handled by several functions that used
to take const-refs, which resulted eventually in a copy pushed on the stack.
With modern C++ (post C++11), move semantics allows to avoid some of these
copies. This requires that std::move be used by callers, and rvalue refs
(foo&&) be used by the callees.
In order to avoid duplicating these functions, let's introduce macros
(YY_MOVE, YY_RVREF, etc.) that rely on copy-semantics for C++98/03, and
move-semantics for modern C++.
That's easy for inner types, when the parser's functions pass arguments to
each other. Funtions facing the user (make_NUMBER, make_STRING, etc.)
should support both rvalue-refs (for instance to support move-only types:
make_INT (std::make_unique<int> (1))), and lvalue-refs (so that we can pass
a variable: make_INT (my_int)). To avoid the multiplication of the
signatures (there is also the location), let's take the argument by copy.
Suggested by Frank Heckenbach.
See http://lists.gnu.org/archive/html/bug-bison/2018-03/msg00002.html,
and https://lists.gnu.org/archive/html/bison-patches/2018-04/msg00002.html.
* data/c++.m4 (b4_cxx_portability): New.
(basic_symbol): In C++11, replace copy-ctors with move-ctors.
In C++11, replace copies with moves.
* data/lalr1.cc (stack_symbol_type, yypush_): Likewise.
Use YY_MOVE to avoid useless copies.
* data/variant.hh (variant): Support move-semantics.
(make_SYMBOL): In C++11, in order to support both read-only lvalues,
and rvalues, take the argument as a copy.
* data/stack.hh (yypush_): Use rvalue-refs in C++11.
* tests/c++.at: Use move semantics.
* tests/headers.at: Adjust to the new macros (YY_MOVE, etc.).
* configure.ac (CXX98_CXXFLAGS, CXX11_CXXFLAGS, CXX14_CXXFLAGS)
(CXX17_CXXFLAGS, ENABLE_CXX11): New.
* tests/atlocal.in: Receive them.
* examples/variant-11.test, examples/variant-11.yy: New.
Check the support of move-only types.
* examples/README, examples/local.mk: Adjust.
diff --git a/configure.ac b/configure.ac
index cf4428d7..ea89dbae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,8 @@ AC_PROG_CC_STDC
AC_PROG_CXX
AC_LANG_PUSH([C++])
gl_WARN_ADD([-fno-exceptions], [NO_EXCEPTIONS_CXXFLAGS])
+gl_WARN_ADD([-std=c++11], [CXX11_CXXFLAGS])
+AM_CONDITIONAL([ENABLE_CXX11], [test x"$CXX11_CXXFLAGS" != x])
AC_LANG_POP([C++])
# Gnulib (early checks).
diff --git a/data/c++.m4 b/data/c++.m4
index 0b23b3e0..32bf8254 100644
--- a/data/c++.m4
+++ b/data/c++.m4
@@ -50,6 +50,25 @@ m4_define([b4_inline],
[m4_fatal([$0: invalid argument: $1])])])
+# b4_cxx_portability
+# ------------------
+m4_define([b4_cxx_portability],
+[// Support move semantics when possible.
+#if defined __cplusplus && 201103L <= __cplusplus
+# define YY_MOVE std::move
+# define YY_MOVE_OR_COPY move
+# define YY_MOVE_REF(Type) Type&&
+# define YY_RVREF(Type) Type&&
+# define YY_COPY(Type) Type
+#else
+# define YY_MOVE
+# define YY_MOVE_OR_COPY copy
+# define YY_MOVE_REF(Type) Type&
+# define YY_RVREF(Type) const Type&
+# define YY_COPY(Type) const Type&
+#endif[]dnl
+])
+
## ---------------- ##
## Default values. ##
@@ -219,19 +238,20 @@ m4_define([b4_symbol_type_declare],
/// Default constructor.
basic_symbol ();
- /// Copy constructor.
- basic_symbol (const basic_symbol& other);
+ /// Move or copy constructor.
+ basic_symbol (YY_RVREF (basic_symbol) other);
+
]b4_variant_if([[
/// Constructor for valueless symbols, and symbols from each type.
]b4_type_foreach([b4_basic_symbol_constructor_declare])], [[
/// Constructor for valueless symbols.
basic_symbol (typename Base::kind_type t]b4_locations_if([,
- const location_type& l])[);
+ YY_MOVE_REF (location_type) l])[);
/// Constructor for symbols with semantic value.
basic_symbol (typename Base::kind_type t,
- const semantic_type& v]b4_locations_if([,
- const location_type& l])[);]])[
+ YY_RVREF (semantic_type) v]b4_locations_if([,
+ YY_RVREF (location_type) l])[);]])[
/// Destroy the symbol.
~basic_symbol ();
@@ -312,13 +332,13 @@ m4_define([b4_public_types_define],
{}
template <typename Base>
- ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (const
basic_symbol& other)
- : Base (other)
- , value (]b4_variant_if([], [other.value])[)]b4_locations_if([
- , location (other.location)])[
+ ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (YY_RVREF
(basic_symbol) other)
+ : Base (YY_MOVE (other))
+ , value (]b4_variant_if([], [YY_MOVE (other.value)]))b4_locations_if([
+ , location (YY_MOVE (other.location))])[
{]b4_variant_if([
- b4_symbol_variant([other.type_get ()], [value], [copy],
- [other.value])])[
+ b4_symbol_variant([other.type_get ()], [value], [YY_MOVE_OR_COPY],
+ [YY_MOVE (other.value)])])[
}
]b4_variant_if([[
@@ -328,7 +348,7 @@ m4_define([b4_public_types_define],
template <typename Base>
]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
[typename Base::kind_type t],
- b4_locations_if([const location_type& l]))[)
+ b4_locations_if([YY_MOVE_REF (location_type) l]))[)
: Base (t)
, value ()]b4_locations_if([
, location (l)])[
@@ -337,14 +357,14 @@ m4_define([b4_public_types_define],
template <typename Base>
]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
[typename Base::kind_type t],
- [const semantic_type& v],
- b4_locations_if([const location_type& l]))[)
+ [YY_RVREF (semantic_type) v],
+ b4_locations_if([YY_RVREF (location_type) l]))[)
: Base (t)
- , value (]b4_variant_if([], [v])[)]b4_locations_if([
- , location (l)])[
+ , value (]b4_variant_if([], [YY_MOVE (v)])[)]b4_locations_if([
+ , location (YY_MOVE (l))])[
{]b4_variant_if([[
(void) v;
- ]b4_symbol_variant([this->type_get ()], [value], [copy], [v])])[}]])[
+ ]b4_symbol_variant([this->type_get ()], [value], [YY_MOVE_OR_COPY],
[YY_MOVE (v)])])[}]])[
template <typename Base>
]b4_parser_class_name[::basic_symbol<Base>::~basic_symbol ()
@@ -385,9 +405,9 @@ m4_define([b4_public_types_define],
{
super_type::move (s);
]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [move],
- [s.value])],
- [value = s.value;])[]b4_locations_if([
- location = s.location;])[
+ [YY_MOVE (s.value)])],
+ [value = YY_MOVE (s.value);])[]b4_locations_if([
+ location = YY_MOVE (s.location);])[
}
// by_type.
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 4679eb42..239c242b 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -153,13 +153,17 @@ m4_define([b4_shared_declarations],
# include <iostream>
# include <stdexcept>
# include <string>
-# include <vector>]b4_defines_if([[
+# include <vector>
+
+]b4_cxx_portability[
+]b4_defines_if([[
# include "stack.hh"
]b4_bison_locations_if([[# include "location.hh"]])])[
]b4_variant_if([b4_variant_includes])[
]b4_attribute_define[
]b4_null_define[
+
]b4_YYDEBUG_define[
]b4_namespace_open[
@@ -318,12 +322,12 @@ b4_location_define])])[
typedef basic_symbol<by_state> super_type;
/// Construct an empty symbol.
stack_symbol_type ();
- /// Copy construct (for efficiency).
- stack_symbol_type (const stack_symbol_type& that);
+ /// Move or copy construction.
+ stack_symbol_type (YY_RVREF (stack_symbol_type) that);
/// Steal the contents from \a sym to build this.
- stack_symbol_type (state_type s, symbol_type& sym);
+ stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) sym);
/// Assignment, needed by push_back.
- stack_symbol_type& operator= (stack_symbol_type& that);
+ stack_symbol_type& operator= (YY_MOVE_REF (stack_symbol_type) that);
};
/// Stack type.
@@ -337,15 +341,15 @@ b4_location_define])])[
/// if null, no trace is output.
/// \param sym the symbol
/// \warning the contents of \a s.value is stolen.
- void yypush_ (const char* m, stack_symbol_type& sym);
+ void yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym);
/// Push a new look ahead token on the state on the stack.
/// \param m a debug message to display
/// if null, no trace is output.
/// \param s the state
/// \param sym the symbol (for its value and location).
- /// \warning the contents of \a s.value is stolen.
- void yypush_ (const char* m, state_type s, symbol_type& sym);
+ /// \warning the contents of \a sym.value is stolen.
+ void yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym);
/// Pop \a n symbols the three stacks.
void yypop_ (unsigned n = 1);
@@ -588,34 +592,33 @@ m4_if(b4_prefix, [yy], [],
]b4_parser_class_name[::stack_symbol_type::stack_symbol_type ()
{}
- ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (const
stack_symbol_type& that)
- : super_type (that.state]b4_variant_if([], [,
that.value])[]b4_locations_if([, that.location])[)
+ ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (YY_RVREF
(stack_symbol_type) that)
+ : super_type (YY_MOVE (that.state)]b4_variant_if([], [, YY_MOVE
(that.value)])b4_locations_if([, YY_MOVE (that.location)])[)
{]b4_variant_if([
b4_symbol_variant([that.type_get ()],
- [value], [copy], [that.value])])[
+ [value], [YY_MOVE_OR_COPY], [YY_MOVE (that.value)])])[
}
- ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (state_type s,
symbol_type& that)
- : super_type (s]b4_variant_if([], [, that.value])[]b4_locations_if([,
that.location])[)
+ ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (state_type s,
YY_MOVE_REF (symbol_type) that)
+ : super_type (s]b4_variant_if([], [, YY_MOVE
(that.value)])[]b4_locations_if([, YY_MOVE (that.location)])[)
{]b4_variant_if([
b4_symbol_variant([that.type_get ()],
- [value], [move], [that.value])])[
+ [value], [move], [YY_MOVE (that.value)])])[
// that is emptied.
that.type = empty_symbol;
}
]b4_parser_class_name[::stack_symbol_type&
- ]b4_parser_class_name[::stack_symbol_type::operator= (stack_symbol_type&
that)
+ ]b4_parser_class_name[::stack_symbol_type::operator= (YY_MOVE_REF
(stack_symbol_type) that)
{
state = that.state;
]b4_variant_if([b4_symbol_variant([that.type_get ()],
- [value], [move], [that.value])],
- [[value = that.value;]])[]b4_locations_if([
- location = that.location;])[
+ [value], [move], [YY_MOVE
(that.value)])],
+ [[value = YY_MOVE (that.value);]])[]b4_locations_if([
+ location = YY_MOVE (that.location);])[
return *this;
}
-
template <typename Base>
void
]b4_parser_class_name[::yy_destroy_ (const char* yymsg, basic_symbol<Base>&
yysym) const
@@ -649,18 +652,22 @@ m4_if(b4_prefix, [yy], [],
#endif
void
- ]b4_parser_class_name[::yypush_ (const char* m, stack_symbol_type& sym)
+ ]b4_parser_class_name[::yypush_ (const char* m, YY_MOVE_REF
(stack_symbol_type) sym)
{
if (m)
YY_SYMBOL_PRINT (m, sym);
- yystack_.push (sym);
+ yystack_.push (YY_MOVE (sym));
}
void
- ]b4_parser_class_name[::yypush_ (const char* m, state_type s, symbol_type&
sym)
+ ]b4_parser_class_name[::yypush_ (const char* m, state_type s, YY_MOVE_REF
(symbol_type) sym)
{
- stack_symbol_type t (s, sym);
- yypush_ (m, t);
+#if defined __cplusplus && 201103L <= __cplusplus
+ yypush_ (m, stack_symbol_type (s, YY_MOVE (sym)));
+#else
+ stack_symbol_type ss(s, sym);
+ yypush_ (m, ss);
+#endif
}
void
@@ -756,7 +763,7 @@ b4_dollar_popdef])[]dnl
location values to have been already stored, initialize these
stacks with a primary value. */
yystack_.clear ();
- yypush_ (YY_NULLPTR, 0, yyla);
+ yypush_ (YY_NULLPTR, 0, YY_MOVE (yyla));
// A new symbol was pushed on the stack.
yynewstate:
@@ -818,7 +825,7 @@ b4_dollar_popdef])[]dnl
--yyerrstatus_;
// Shift the lookahead token.
- yypush_ ("Shifting", yyn, yyla);
+ yypush_ ("Shifting", yyn, YY_MOVE (yyla));
goto yynewstate;
/*-----------------------------------------------------------.
@@ -887,7 +894,7 @@ b4_dollar_popdef])[]dnl
YY_STACK_PRINT ();
// Shift the result of the reduction.
- yypush_ (YY_NULLPTR, yylhs);
+ yypush_ (YY_NULLPTR, YY_MOVE (yylhs));
}
goto yynewstate;
@@ -976,7 +983,7 @@ b4_dollar_popdef])[]dnl
// Shift the error token.
error_token.state = yyn;
- yypush_ ("Shifting", error_token);
+ yypush_ ("Shifting", YY_MOVE (error_token));
}
goto yynewstate;
diff --git a/data/stack.hh b/data/stack.hh
index f3ac21f9..f74cdfd2 100644
--- a/data/stack.hh
+++ b/data/stack.hh
@@ -62,7 +62,7 @@ m4_define([b4_stack_define],
///
/// Close to move-semantics.
void
- push (T& t)
+ push (YY_MOVE_REF (T) t)
{
seq_.push_back (T());
operator[](0).move (t);
@@ -142,6 +142,8 @@ b4_copyright([Stack handling for Bison parsers in C++])[
# include <vector>
+]b4_cxx_portability[
+
]b4_namespace_open[
]b4_stack_define[
]b4_namespace_close[
diff --git a/data/variant.hh b/data/variant.hh
index a10d9447..4ba3f006 100644
--- a/data/variant.hh
+++ b/data/variant.hh
@@ -101,11 +101,11 @@ m4_define([b4_variant_define],
/// Construct and fill.
template <typename T>
- variant (const T& t)]b4_parse_assert_if([
+ variant (YY_RVREF (T) t)]b4_parse_assert_if([
: yytypeid_ (&typeid (T))])[
{
YYASSERT (sizeof (T) <= S);
- new (yyas_<T> ()) T (t);
+ new (yyas_<T> ()) T (YY_MOVE (t));
}
/// Destruction, allowed only if empty.
@@ -183,10 +183,26 @@ m4_define([b4_variant_define],
move (self_type& other)
{
build<T> ();
+# if defined __cplusplus && 201103L <= __cplusplus
+ as<T> () = YY_MOVE (other.as<T> ());
+# else
swap<T> (other);
+# endif
other.destroy<T> ();
}
+# if defined __cplusplus && 201103L <= __cplusplus
+ /// Move the content of \a other to this.
+ template <typename T>
+ void
+ move (self_type&& other)
+ {
+ build<T> ();
+ as<T> () = YY_MOVE (other.as<T> ());
+ other.destroy<T> ();
+ }
+#endif
+
/// Copy the content of \a other to this.
template <typename T>
void
@@ -293,8 +309,8 @@ m4_define([b4_symbol_constructor_declare_],
symbol_type
make_[]b4_symbol_([$1], [id]) (dnl
b4_join(b4_symbol_if([$1], [has_type],
- [const b4_symbol([$1], [type])& v]),
- b4_locations_if([const location_type& l])));
+ [YY_COPY (b4_symbol([$1], [type])) v]),
+ b4_locations_if([YY_COPY (location_type) l])));
])])])
@@ -318,12 +334,12 @@ m4_define([b4_symbol_constructor_define_],
b4_parser_class_name::symbol_type
b4_parser_class_name::make_[]b4_symbol_([$1], [id]) (dnl
b4_join(b4_symbol_if([$1], [has_type],
- [const b4_symbol([$1], [type])& v]),
- b4_locations_if([const location_type& l])))
+ [YY_COPY (b4_symbol([$1], [type])) v]),
+ b4_locations_if([YY_COPY (location_type) l])))
{
return symbol_type (b4_join([token::b4_symbol([$1], [id])],
- b4_symbol_if([$1], [has_type], [v]),
- b4_locations_if([l])));
+ b4_symbol_if([$1], [has_type], [YY_MOVE (v)]),
+ b4_locations_if([YY_MOVE (l)])));
}
])])])
@@ -335,8 +351,8 @@ b4_join(b4_symbol_if([$1], [has_type],
m4_define([b4_basic_symbol_constructor_declare],
[[ basic_symbol (]b4_join(
[typename Base::kind_type t],
- b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[& v]),
- b4_locations_if([const location_type& l]))[);
+ b4_symbol_if([$1], [has_type], [YY_RVREF (b4_symbol([$1], [type]))
v]),
+ b4_locations_if([YY_RVREF (location_type) l]))[);
]])
# b4_basic_symbol_constructor_define
@@ -346,11 +362,11 @@ m4_define([b4_basic_symbol_constructor_define],
[[ template <typename Base>
]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
[typename Base::kind_type t],
- b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[& v]),
- b4_locations_if([const location_type& l]))[)
+ b4_symbol_if([$1], [has_type], [YY_RVREF (b4_symbol([$1], [type]))
v]),
+ b4_locations_if([YY_RVREF (location_type) l]))[)
: Base (t)]b4_symbol_if([$1], [has_type], [
- , value (v)])[]b4_locations_if([
- , location (l)])[
+ , value (YY_MOVE (v))])[]b4_locations_if([
+ , location (YY_MOVE (l))])[
{}
]])
diff --git a/examples/README b/examples/README
index 9780d829..f0670cd0 100644
--- a/examples/README
+++ b/examples/README
@@ -13,6 +13,10 @@ A C++ example that uses variants (they allow to use any C++
type as semantic
value type) and symbol constructors (they ensure consistency between
declared token type and effective semantic value).
+* variant-11.yy
+Another C++ example, closely related to the previous one, but exhibiting
+support for C++11's move semantics.
+
-----
Local Variables:
@@ -22,19 +26,11 @@ End:
Copyright (C) 2018 Free Software Foundation, Inc.
-This file is part of Bison, the GNU Compiler Compiler.
-
-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 <http://www.gnu.org/licenses/>.
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+Texts. A copy of the license is included in the "GNU Free
+Documentation License" file as part of this distribution.
# LocalWords: mfcalc calc parsers yy
diff --git a/examples/local.mk b/examples/local.mk
index 2518da34..a5667f92 100644
--- a/examples/local.mk
+++ b/examples/local.mk
@@ -45,14 +45,24 @@ $(extracted): %D%/extracted.stamp
## Examples. ##
## ---------- ##
+
examplesdir = $(docdir)/examples
-dist_examples_DATA = %D%/README %D%/variant.yy
+dist_examples_DATA = %D%/README %D%/variant.yy %D%/variant-11.yy
check_PROGRAMS += %D%/variant
nodist_%C%_variant_SOURCES = %D%/variant.yy
%C%_variant_CPPFLAGS = -I$(top_builddir)
dist_TESTS += %D%/variant.test
+%D%/variant.cc: $(BISON_IN) $(dist_pkgdata_DATA)
+if ENABLE_CXX11
+ check_PROGRAMS += %D%/variant-11
+ nodist_%C%_variant_11_SOURCES = %D%/variant-11.yy
+ %C%_variant_11_CXXFLAGS = $(CXX11_CXXFLAGS)
+ %C%_variant_11_CPPFLAGS = -I$(top_builddir)
+ dist_TESTS += %D%/variant-11.test
+ %D%/variant-11.cc: $(BISON_IN) $(dist_pkgdata_DATA)
+endif
include %D%/calc++/local.mk
include %D%/mfcalc/local.mk
diff --git a/examples/variant-11.test b/examples/variant-11.test
new file mode 100644
index 00000000..3bc2b397
--- /dev/null
+++ b/examples/variant-11.test
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+# Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
+
+: >input
+run 0 "{I have three numbers for you., 1, 2, 3, And that's all!}"
diff --git a/examples/variant-11.yy b/examples/variant-11.yy
new file mode 100644
index 00000000..d8481121
--- /dev/null
+++ b/examples/variant-11.yy
@@ -0,0 +1,163 @@
+/*
+ Copyright (C) 2008-2015, 2018 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 <http://www.gnu.org/licenses/>.
+*/
+
+%debug
+%language "c++"
+%defines
+%define api.token.constructor
+%define api.value.type variant
+%define parse.assert
+%locations
+
+%code requires // *.hh
+{
+#include <memory> // std::unique_ptr
+#include <string>
+#include <vector>
+
+ using ustring = std::unique_ptr<std::string>;
+ using ustrings = std::vector<ustring>;
+}
+
+%code // *.cc
+{
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+ // Prototype of the yylex function providing subsequent tokens.
+ namespace yy
+ {
+ static parser::symbol_type yylex ();
+ }
+
+ // Printing a vector of strings.
+ // Koening look up will look into std, since that's an std::vector.
+ namespace std
+ {
+ std::ostream&
+ operator<< (std::ostream& o, const ustrings& ss)
+ {
+ o << '{';
+ const char *sep = "";
+ for (const auto& s: ss)
+ {
+ o << sep << *s;
+ sep = ", ";
+ }
+ return o << '}';
+ }
+ }
+
+ template <typename... Args>
+ ustring
+ make_ustring (Args&&... args)
+ {
+ // std::make_unique is C++14.
+ return std::unique_ptr<std::string>(new
std::string(std::forward<Args>(args)...));
+ }
+
+ // Conversion to string.
+ template <typename T>
+ std::string
+ to_string (const T& t)
+ {
+ auto&& o = std::ostringstream{};
+ o << t;
+ return o.str ();
+ }
+}
+
+%token <ustring> TEXT;
+%token <int> NUMBER;
+%printer { yyo << '(' << &$$ << ") " << $$; } <*>;
+%printer { yyo << *$$; } <ustring>;
+%token END_OF_FILE 0;
+
+%type <ustring> item;
+%type <ustrings> list;
+
+%%
+
+result:
+ list { std::cout << $1 << '\n'; }
+;
+
+list:
+ %empty { /* Generates an empty string list */ }
+| list item { $$ = std::move ($1); $$.emplace_back (std::move ($2)); }
+;
+
+item:
+ TEXT { $$ = std::move ($1); }
+| NUMBER { $$ = make_ustring (to_string ($1)); }
+;
+%%
+
+namespace yy
+{
+ // The yylex function providing subsequent tokens:
+ // TEXT "I have three numbers for you."
+ // NUMBER 1
+ // NUMBER 2
+ // NUMBER 3
+ // TEXT "And that's all!"
+ // END_OF_FILE
+
+ static
+ parser::symbol_type
+ yylex ()
+ {
+ static auto count = 0u;
+ auto stage = count;
+ ++count;
+ auto loc = parser::location_type{nullptr, stage + 1, stage + 1};
+ switch (stage)
+ {
+ case 0:
+ return parser::make_TEXT (make_ustring ("I have three numbers for
you."), std::move (loc));
+ case 1:
+ case 2:
+ case 3:
+ return parser::make_NUMBER (stage, std::move (loc));
+ case 4:
+ return parser::make_TEXT (make_ustring ("And that's all!"), std::move
(loc));
+ default:
+ return parser::make_END_OF_FILE (std::move (loc));
+ }
+ }
+
+ // Mandatory error function
+ void
+ parser::error (const parser::location_type& loc, const std::string& msg)
+ {
+ std::cerr << loc << ": " << msg << '\n';
+ }
+}
+
+int
+main ()
+{
+ auto&& p = yy::parser{};
+ p.set_debug_level (!!getenv ("YYDEBUG"));
+ return p.parse ();
+}
+
+// Local Variables:
+// mode: C++
+// End:
diff --git a/tests/atlocal.in b/tests/atlocal.in
index a0a91687..c26ed0b5 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -54,6 +54,9 @@ BISON_CXX_WORKS='@BISON_CXX_WORKS@'
# Compiler flags to disable exception support.
NO_EXCEPTIONS_CXXFLAGS='@NO_EXCEPTIONS_CXXFLAGS@'
+# Requiring a specific C++ standard.
+CXX11_CXXFLAGS='@CXX11_CXXFLAGS@'
+
# Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly.
diff --git a/tests/c++.at b/tests/c++.at
index 5941c0ed..1b80063b 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -151,8 +151,12 @@ int main()
// stack_symbol_type: construction, accessor.
{
+#if defined __cplusplus && 201103L <= __cplusplus
+ auto ss = parser::stack_symbol_type(1, parser::make_INT(123));
+#else
parser::symbol_type s = parser::make_INT(123);
parser::stack_symbol_type ss(1, s);
+#endif
std::cerr << ss.value.as<int>() << '\n';
}
@@ -161,8 +165,12 @@ int main()
parser::stack_type st;
for (int i = 0; i < 100; ++i)
{
+#if defined __cplusplus && 201103L <= __cplusplus
+ auto ss = parser::stack_symbol_type(1, parser::make_INT(123));
+#else
parser::symbol_type s = parser::make_INT(123);
parser::stack_symbol_type ss(1, s);
+#endif
st.push(ss);
}
}
diff --git a/tests/headers.at b/tests/headers.at
index 541610db..e6e747b0 100644
--- a/tests/headers.at
+++ b/tests/headers.at
@@ -311,15 +311,20 @@ AT_TEST([x8], [%define api.pure %define api.push-pull
both])
AT_CHECK([[$PERL -n -0777 -e '
s{/\*.*?\*/}{}gs;
s{//.*}{}g;
- s{\b(YYChar
+ s{\b((defined|if)\ YYDEBUG
+ |YYChar
|YYPUSH_MORE(?:_DEFINED)?
|YYUSE
|YY_ATTRIBUTE(?:_PURE|_UNUSED)?
+ |YY_COPY
|YY_IGNORE_MAYBE_UNINITIALIZED_(?:BEGIN|END)
|YY_INITIAL_VALUE
- |YY_\w+_INCLUDED
+ |YY_MOVE
+ |YY_MOVE_OR_COPY
+ |YY_MOVE_REF
|YY_NULLPTR
- |(defined|if)\ YYDEBUG
+ |YY_RVREF
+ |YY_\w+_INCLUDED
)\b}{}gx;
while (/^(.*YY.*)$/gm)
{
- RFC: lalr1.cc: support move semantics,
Akim Demaille <=
- Re: RFC: lalr1.cc: support move semantics, Frank Heckenbach, 2018/09/11
- Re: RFC: lalr1.cc: support move semantics, Akim Demaille, 2018/09/11
- Re: RFC: lalr1.cc: support move semantics, Frank Heckenbach, 2018/09/11
- Re: RFC: lalr1.cc: support move semantics, Akim Demaille, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Akim Demaille, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Akim Demaille, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Hans Åberg, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Frank Heckenbach, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Hans Åberg, 2018/09/12
- Re: RFC: lalr1.cc: support move semantics, Frank Heckenbach, 2018/09/12