mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
The current approach was too adhoc: the symbols were not sufficiently self-contained, in particular wrt memory management. The "new" guideline is the one that should have been followed from the start: let the symbols handle themslves, instead of leaving their users to it. It was justified by the will to avoid gratuitious moves and copies, but the current approach does not seem to be slower, yet it will probably be simpler to adjust to support move semantics from C++11. The documentation says that the %parse-param are available from the %destructor. In retrospect, that was a silly design decision, which we can break for variants, as its a new feature. It should be phased out for non-variants too. * data/variant.hh: A variant never knows if it stores something or not, it is up to its users to store this information. Yet, in parse.assert mode, make sure the empty/filled variants are properly used. (b4_symbol_constructor_define_): Don't call directly the symbol constructor, to save a useless temporary. * data/stack.hh (push): Steal the pushed value instead of duplicating it. This will simplify the callers of push, who handled this "move" approach themselves. * data/c++.m4 (basic_symbol): Let -1, as kind, denote the fact that a symbol is empty. This is needed for instance when shifting the lookahead: yyla is given as argument to "push", and its value is then moved on the stack. But then yyla must be declared "empty" so that its destructor won't be called. (basic_symbol::move): New. Move the responsibility of calling the destructor from yy_destroy to ~basic_symbol in the case of variants. * data/lalr1.cc (stack_symbol_type): Now a derived class from its previous value, so that we can add a constructor from a symbol_type. (by_state): State -1 means empty. (yypush_): Factor, by calling one overload from the other one, and using the new semantics of stack::push. No longer reclaim by hand the memory from rhs symbols, since now that we store objects with proper destructors, they will be reclaimed automatically. Conversely, be sure to delete yylhs. * tests/c++.at (C++ Variant-based Symbols): New "unit" test for symbols.
147 lines
2.8 KiB
C++
147 lines
2.8 KiB
C++
# C++ skeleton for Bison
|
|
|
|
# Copyright (C) 2002-2013 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/>.
|
|
|
|
m4_pushdef([b4_copyright_years],
|
|
[2002-2013])
|
|
|
|
# b4_stack_define
|
|
# ---------------
|
|
m4_define([b4_stack_define],
|
|
[[ template <class T, class S = std::vector<T> >
|
|
class stack
|
|
{
|
|
public:
|
|
// Hide our reversed order.
|
|
typedef typename S::reverse_iterator iterator;
|
|
typedef typename S::const_reverse_iterator const_iterator;
|
|
|
|
stack ()
|
|
: seq_ ()
|
|
{
|
|
}
|
|
|
|
stack (unsigned int n)
|
|
: seq_ (n)
|
|
{
|
|
}
|
|
|
|
inline
|
|
T&
|
|
operator[] (unsigned int i)
|
|
{
|
|
return seq_[seq_.size () - 1 - i];
|
|
}
|
|
|
|
inline
|
|
const T&
|
|
operator[] (unsigned int i) const
|
|
{
|
|
return seq_[seq_.size () - 1 - i];
|
|
}
|
|
|
|
/// Steal the contents of \a t.
|
|
///
|
|
/// Close to move-semantics.
|
|
inline
|
|
void
|
|
push (T& t)
|
|
{
|
|
seq_.push_back (T());
|
|
operator[](0).move (t);
|
|
}
|
|
|
|
inline
|
|
void
|
|
pop (unsigned int n = 1)
|
|
{
|
|
for (; n; --n)
|
|
seq_.pop_back ();
|
|
}
|
|
|
|
inline
|
|
typename S::size_type
|
|
size () const
|
|
{
|
|
return seq_.size ();
|
|
}
|
|
|
|
inline
|
|
const_iterator
|
|
begin () const
|
|
{
|
|
return seq_.rbegin ();
|
|
}
|
|
|
|
inline
|
|
const_iterator
|
|
end () const
|
|
{
|
|
return seq_.rend ();
|
|
}
|
|
|
|
private:
|
|
/// The wrapped container.
|
|
S seq_;
|
|
};
|
|
|
|
/// Present a slice of the top of a stack.
|
|
template <class T, class S = stack<T> >
|
|
class slice
|
|
{
|
|
public:
|
|
slice (const S& stack, unsigned int range)
|
|
: stack_ (stack)
|
|
, range_ (range)
|
|
{
|
|
}
|
|
|
|
inline
|
|
const T&
|
|
operator [] (unsigned int i) const
|
|
{
|
|
return stack_[range_ - i];
|
|
}
|
|
|
|
private:
|
|
const S& stack_;
|
|
unsigned int range_;
|
|
};
|
|
]])
|
|
|
|
b4_defines_if(
|
|
[b4_output_begin([b4_dir_prefix[]stack.hh])
|
|
b4_copyright([Stack handling for Bison parsers in C++])[
|
|
|
|
/**
|
|
** \file ]b4_dir_prefix[stack.hh
|
|
** Define the ]b4_namespace_ref[::stack class.
|
|
*/
|
|
|
|
]b4_cpp_guard_open([b4_dir_prefix[]stack.hh])[
|
|
|
|
# include <vector>
|
|
|
|
]b4_namespace_open[
|
|
]b4_stack_define[
|
|
]b4_namespace_close[
|
|
|
|
]b4_cpp_guard_close([b4_dir_prefix[]stack.hh])
|
|
b4_output_end()
|
|
])
|
|
|
|
m4_popdef([b4_copyright_years])
|