Imported existing code
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ANY_APR_22_2006_1147AM)
|
||||
#define BOOST_SPIRIT_ANY_APR_22_2006_1147AM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/fusion/include/equal_to.hpp>
|
||||
#include <boost/fusion/include/next.hpp>
|
||||
#include <boost/fusion/include/deref.hpp>
|
||||
#include <boost/fusion/include/begin.hpp>
|
||||
#include <boost/fusion/include/end.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// This is the binary version of fusion::any. This might
|
||||
// be a good candidate for inclusion in fusion algorithm
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename First1, typename Last, typename First2, typename F>
|
||||
inline bool
|
||||
any(First1 const&, First2 const&, Last const&, F const&, mpl::true_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename First1, typename Last, typename First2, typename F>
|
||||
inline bool
|
||||
any(First1 const& first1, First2 const& first2, Last const& last, F& f, mpl::false_)
|
||||
{
|
||||
return f(*first1, *first2) ||
|
||||
detail::any(
|
||||
fusion::next(first1)
|
||||
, fusion::next(first2)
|
||||
, last
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::next<First1>::type, Last>());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Sequence1, typename Sequence2, typename F>
|
||||
inline bool
|
||||
any(Sequence1 const& seq1, Sequence2& seq2, F f)
|
||||
{
|
||||
return detail::any(
|
||||
fusion::begin(seq1)
|
||||
, fusion::begin(seq2)
|
||||
, fusion::end(seq1)
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::begin<Sequence1>::type
|
||||
, typename fusion::result_of::end<Sequence1>::type>());
|
||||
}
|
||||
|
||||
template <typename Sequence, typename F>
|
||||
inline bool
|
||||
any(Sequence const& seq, unused_type, F f)
|
||||
{
|
||||
return fusion::any(seq, f);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
221
libraries/include/boost/spirit/home/support/algorithm/any_if.hpp
Normal file
221
libraries/include/boost/spirit/home/support/algorithm/any_if.hpp
Normal file
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ANY_IF_MAR_30_2007_1220PM)
|
||||
#define BOOST_SPIRIT_ANY_IF_MAR_30_2007_1220PM
|
||||
|
||||
#include <boost/fusion/include/equal_to.hpp>
|
||||
#include <boost/fusion/include/next.hpp>
|
||||
#include <boost/fusion/include/deref.hpp>
|
||||
#include <boost/fusion/include/value_of.hpp>
|
||||
#include <boost/fusion/include/begin.hpp>
|
||||
#include <boost/fusion/include/end.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
#include <boost/fusion/include/make_cons.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/print.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This is a special version for a binary fusion::any. The predicate is
|
||||
// used to decide, whether to advance the second iterator or not.
|
||||
// This is needed for sequences containing components with unused
|
||||
// attributes.
|
||||
// The second iterator is advanced only if the attribute of the
|
||||
// corresponding component iterator is not unused.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Pred>
|
||||
struct apply_predicate
|
||||
{
|
||||
typedef typename
|
||||
mpl::apply1<
|
||||
Pred,
|
||||
typename fusion::result_of::value_of<Iterator>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// if the predicate is true, attribute_next returns next(Iterator2),
|
||||
// otherwise Iterator2
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Iterator1, typename Iterator2, typename Pred>
|
||||
struct attribute_next
|
||||
{
|
||||
typedef typename apply_predicate<Iterator1, Pred>::type pred;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
pred,
|
||||
fusion::result_of::next<Iterator2>,
|
||||
mpl::identity<Iterator2>
|
||||
>::type
|
||||
type;
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const& i, mpl::true_)
|
||||
{
|
||||
return fusion::next(i);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const& i, mpl::false_)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const& i)
|
||||
{
|
||||
return call(i, pred());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Pred, typename Iterator1, typename Iterator2>
|
||||
inline typename
|
||||
result_of::attribute_next<Iterator1, Iterator2, Pred
|
||||
>::type const
|
||||
attribute_next(Iterator2 const& i)
|
||||
{
|
||||
return result_of::attribute_next<Iterator1, Iterator2, Pred>::call(i);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// if the predicate is true, attribute_value returns deref(Iterator2),
|
||||
// otherwise unused
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Iterator1, typename Iterator2, typename Pred>
|
||||
struct attribute_value
|
||||
{
|
||||
typedef typename apply_predicate<Iterator1, Pred>::type pred;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
pred,
|
||||
fusion::result_of::deref<Iterator2>,
|
||||
mpl::identity<unused_type const>
|
||||
>::type
|
||||
type;
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const& i, mpl::true_)
|
||||
{
|
||||
return fusion::deref(i);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const&, mpl::false_)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static type
|
||||
call(Iterator const& i)
|
||||
{
|
||||
return call(i, pred());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Pred, typename Iterator1, typename Iterator2>
|
||||
inline typename
|
||||
result_of::attribute_value<Iterator1, Iterator2, Pred
|
||||
>::type
|
||||
attribute_value(Iterator2 const& i)
|
||||
{
|
||||
return result_of::attribute_value<Iterator1, Iterator2, Pred>::call(i);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Pred, typename First1, typename Last, typename First2,
|
||||
typename F
|
||||
>
|
||||
inline bool
|
||||
any_if (First1 const&, First2 const&, Last const&, F const&, mpl::true_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <
|
||||
typename Pred, typename First1, typename Last, typename First2,
|
||||
typename F
|
||||
>
|
||||
inline bool
|
||||
any_if (First1 const& first1, First2 const& first2, Last const& last,
|
||||
F& f, mpl::false_)
|
||||
{
|
||||
return f(*first1, attribute_value<Pred, First1>(first2)) ||
|
||||
detail::any_if<Pred>(
|
||||
fusion::next(first1)
|
||||
, attribute_next<Pred, First1>(first2)
|
||||
, last
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::next<First1>::type, Last>());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Pred, typename Sequence1, typename Sequence2, typename F>
|
||||
inline typename enable_if<fusion::traits::is_sequence<Sequence2>, bool>::type
|
||||
any_if(Sequence1 const& seq1, Sequence2& seq2, F f, Pred)
|
||||
{
|
||||
return detail::any_if<Pred>(
|
||||
fusion::begin(seq1)
|
||||
, fusion::begin(seq2)
|
||||
, fusion::end(seq1)
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::begin<Sequence1>::type
|
||||
, typename fusion::result_of::end<Sequence1>::type>());
|
||||
}
|
||||
|
||||
template <typename Pred, typename Sequence1, typename Attribute, typename F>
|
||||
inline typename disable_if<fusion::traits::is_sequence<Attribute>, bool>::type
|
||||
any_if(Sequence1 const& seq1, Attribute& attr, F f, Pred /*p*/)
|
||||
{
|
||||
typename
|
||||
fusion::result_of::make_cons<Attribute&>::type
|
||||
seq2(attr); // wrap attribute in a single element tuple
|
||||
|
||||
return detail::any_if<Pred>(
|
||||
fusion::begin(seq1)
|
||||
, fusion::begin(seq2)
|
||||
, fusion::end(seq1)
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::begin<Sequence1>::type
|
||||
, typename fusion::result_of::end<Sequence1>::type>());
|
||||
}
|
||||
|
||||
template <typename Pred, typename Sequence, typename F>
|
||||
inline bool
|
||||
any_if(Sequence const& seq, unused_type const, F f, Pred)
|
||||
{
|
||||
return fusion::any(seq, f);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ANY_NS_MARCH_13_2007_0827AM)
|
||||
#define BOOST_SPIRIT_ANY_NS_MARCH_13_2007_0827AM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/fusion/include/equal_to.hpp>
|
||||
#include <boost/fusion/include/next.hpp>
|
||||
#include <boost/fusion/include/deref.hpp>
|
||||
#include <boost/fusion/include/begin.hpp>
|
||||
#include <boost/fusion/include/end.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// A non-short circuiting (ns) version of the all algorithm (uses
|
||||
// | instead of ||.
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename First1, typename Last, typename First2, typename F>
|
||||
inline bool
|
||||
any_ns(First1 const&, First2 const&, Last const&, F const&, mpl::true_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename First1, typename Last, typename First2, typename F>
|
||||
inline bool
|
||||
any_ns(First1 const& first1, First2 const& first2, Last const& last, F& f, mpl::false_)
|
||||
{
|
||||
return (0 != (f(*first1, *first2) |
|
||||
detail::any_ns(
|
||||
fusion::next(first1)
|
||||
, fusion::next(first2)
|
||||
, last
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::next<First1>::type, Last>())));
|
||||
}
|
||||
|
||||
template <typename First, typename Last, typename F>
|
||||
inline bool
|
||||
any_ns(First const&, Last const&, F const&, mpl::true_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename First, typename Last, typename F>
|
||||
inline bool
|
||||
any_ns(First const& first, Last const& last, F& f, mpl::false_)
|
||||
{
|
||||
return (0 != (f(*first) |
|
||||
detail::any_ns(
|
||||
fusion::next(first)
|
||||
, last
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::next<First>::type, Last>())));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Sequence1, typename Sequence2, typename F>
|
||||
inline bool
|
||||
any_ns(Sequence1 const& seq1, Sequence2& seq2, F f)
|
||||
{
|
||||
return detail::any_ns(
|
||||
fusion::begin(seq1)
|
||||
, fusion::begin(seq2)
|
||||
, fusion::end(seq1)
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::begin<Sequence1>::type
|
||||
, typename fusion::result_of::end<Sequence1>::type>());
|
||||
}
|
||||
|
||||
template <typename Sequence, typename F>
|
||||
inline bool
|
||||
any_ns(Sequence const& seq, unused_type, F f)
|
||||
{
|
||||
return detail::any_ns(
|
||||
fusion::begin(seq)
|
||||
, fusion::end(seq)
|
||||
, f
|
||||
, fusion::result_of::equal_to<
|
||||
typename fusion::result_of::begin<Sequence>::type
|
||||
, typename fusion::result_of::end<Sequence>::type>());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
238
libraries/include/boost/spirit/home/support/argument.hpp
Normal file
238
libraries/include/boost/spirit/home/support/argument.hpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ARGUMENT_FEB_17_2007_0339PM)
|
||||
#define BOOST_SPIRIT_ARGUMENT_FEB_17_2007_0339PM
|
||||
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/spirit/home/phoenix/core/actor.hpp>
|
||||
#include <boost/spirit/home/phoenix/core/argument.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
|
||||
#if !defined(SPIRIT_ARG_LIMIT)
|
||||
# define SPIRIT_ARG_LIMIT PHOENIX_LIMIT
|
||||
#endif
|
||||
|
||||
#define SPIRIT_DECLARE_ARG(z, n, data) \
|
||||
phoenix::actor<argument<n> > const \
|
||||
BOOST_PP_CAT(_, BOOST_PP_INC(n)) = argument<n>(); \
|
||||
phoenix::actor<attribute<n> > const \
|
||||
BOOST_PP_CAT(_r, n) = attribute<n>();
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Sequence, int N>
|
||||
struct get_arg
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::size<Sequence>::type
|
||||
sequence_size;
|
||||
|
||||
// report invalid argument not found (N is out of bounds)
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(N < sequence_size::value),
|
||||
index_is_out_of_bounds, ());
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::at_c<Sequence, N>::type
|
||||
type;
|
||||
|
||||
static type call(Sequence& seq)
|
||||
{
|
||||
return fusion::at_c<N>(seq);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Sequence, int N>
|
||||
struct get_arg<Sequence&, N> : get_arg<Sequence, N>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <int N, typename T>
|
||||
typename result_of::get_arg<T, N>::type
|
||||
get_arg(T& val)
|
||||
{
|
||||
return result_of::get_arg<T, N>::call(val);
|
||||
}
|
||||
|
||||
struct attribute_context
|
||||
{
|
||||
typedef mpl::true_ no_nullary;
|
||||
|
||||
template <typename Env>
|
||||
struct result
|
||||
{
|
||||
// FIXME: is this remove_const really necessary?
|
||||
typedef typename
|
||||
remove_const<
|
||||
typename mpl::at_c<typename Env::args_type, 0>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Env>
|
||||
typename result<Env>::type
|
||||
eval(Env const& env) const
|
||||
{
|
||||
return fusion::at_c<0>(env.args());
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct argument
|
||||
{
|
||||
typedef mpl::true_ no_nullary;
|
||||
|
||||
template <typename Env>
|
||||
struct result
|
||||
{
|
||||
typedef typename
|
||||
mpl::at_c<typename Env::args_type, 0>::type
|
||||
arg_type;
|
||||
|
||||
typedef typename result_of::get_arg<arg_type, N>::type type;
|
||||
};
|
||||
|
||||
template <typename Env>
|
||||
typename result<Env>::type
|
||||
eval(Env const& env) const
|
||||
{
|
||||
return get_arg<N>(fusion::at_c<0>(env.args()));
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct attribute
|
||||
{
|
||||
typedef mpl::true_ no_nullary;
|
||||
|
||||
template <typename Env>
|
||||
struct result
|
||||
{
|
||||
typedef typename
|
||||
mpl::at_c<typename Env::args_type, 1>::type
|
||||
arg_type;
|
||||
|
||||
typedef typename
|
||||
result_of::get_arg<
|
||||
typename result_of::get_arg<arg_type, 0>::type
|
||||
, N
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Env>
|
||||
typename result<Env>::type
|
||||
eval(Env const& env) const
|
||||
{
|
||||
return get_arg<N>(get_arg<0>(fusion::at_c<1>(env.args())));
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct local_var
|
||||
{
|
||||
typedef mpl::true_ no_nullary;
|
||||
|
||||
template <typename Env>
|
||||
struct result
|
||||
{
|
||||
typedef typename
|
||||
mpl::at_c<typename Env::args_type, 1>::type
|
||||
arg_type;
|
||||
|
||||
typedef typename
|
||||
result_of::get_arg<
|
||||
typename result_of::get_arg<arg_type, 1>::type
|
||||
, N
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Env>
|
||||
typename result<Env>::type
|
||||
eval(Env const& env) const
|
||||
{
|
||||
return get_arg<N>(get_arg<1>(fusion::at_c<1>(env.args())));
|
||||
}
|
||||
};
|
||||
|
||||
struct lexer_state
|
||||
{
|
||||
typedef mpl::true_ no_nullary;
|
||||
|
||||
template <typename Env>
|
||||
struct result
|
||||
{
|
||||
typedef typename
|
||||
mpl::at_c<typename Env::args_type, 3>::type::state_type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Env>
|
||||
typename result<Env>::type
|
||||
eval(Env const& env) const
|
||||
{
|
||||
return fusion::at_c<3>(env.args()).state;
|
||||
}
|
||||
};
|
||||
|
||||
namespace arg_names
|
||||
{
|
||||
// _0 refers to the whole attribute as generated by the lhs parser
|
||||
phoenix::actor<attribute_context> const _0 = attribute_context();
|
||||
|
||||
// _1, _2, ... refer to the attributes of the single components the lhs
|
||||
// parser is composed of
|
||||
phoenix::actor<argument<0> > const _1 = argument<0>();
|
||||
phoenix::actor<argument<1> > const _2 = argument<1>();
|
||||
phoenix::actor<argument<2> > const _3 = argument<2>();
|
||||
|
||||
// 'pass' may be used to make a match fail in retrospective
|
||||
phoenix::actor<phoenix::argument<2> > const pass = phoenix::argument<2>();
|
||||
|
||||
// 'id' may be used in a lexer semantic action to refer to the token id
|
||||
// of a matched token
|
||||
phoenix::actor<phoenix::argument<1> > const id = phoenix::argument<1>();
|
||||
|
||||
// 'state' may be used in a lexer semantic action to refer to the
|
||||
// current lexer state
|
||||
phoenix::actor<lexer_state> const state = lexer_state();
|
||||
|
||||
// _val refers to the 'return' value of a rule
|
||||
// _r0, _r1, ... refer to the rule arguments
|
||||
phoenix::actor<attribute<0> > const _val = attribute<0>();
|
||||
phoenix::actor<attribute<0> > const _r0 = attribute<0>();
|
||||
phoenix::actor<attribute<1> > const _r1 = attribute<1>();
|
||||
phoenix::actor<attribute<2> > const _r2 = attribute<2>();
|
||||
|
||||
// Bring in the rest of the arguments and attributes (_4 .. _N+1), using PP
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
3, SPIRIT_ARG_LIMIT, SPIRIT_DECLARE_ARG, _)
|
||||
|
||||
// _a, _b, ... refer to the local variables of a rule
|
||||
phoenix::actor<local_var<0> > const _a = local_var<0>();
|
||||
phoenix::actor<local_var<1> > const _b = local_var<1>();
|
||||
phoenix::actor<local_var<2> > const _c = local_var<2>();
|
||||
phoenix::actor<local_var<3> > const _d = local_var<3>();
|
||||
phoenix::actor<local_var<4> > const _e = local_var<4>();
|
||||
phoenix::actor<local_var<5> > const _f = local_var<5>();
|
||||
phoenix::actor<local_var<6> > const _g = local_var<6>();
|
||||
phoenix::actor<local_var<7> > const _h = local_var<7>();
|
||||
phoenix::actor<local_var<8> > const _i = local_var<8>();
|
||||
phoenix::actor<local_var<9> > const _j = local_var<9>();
|
||||
}
|
||||
}}
|
||||
|
||||
#undef SPIRIT_DECLARE_ARG
|
||||
#endif
|
||||
128
libraries/include/boost/spirit/home/support/as_variant.hpp
Normal file
128
libraries/include/boost/spirit/home/support/as_variant.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#if !defined(BOOST_SPIRIT_AS_VARIANT_NOV_16_2007_0420PM)
|
||||
#define BOOST_SPIRIT_AS_VARIANT_NOV_16_2007_0420PM
|
||||
|
||||
#include <boost/preprocessor/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/push_back.hpp>
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
template <int size>
|
||||
struct as_variant;
|
||||
|
||||
template <>
|
||||
struct as_variant<0>
|
||||
{
|
||||
template <typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
typedef variant<> type;
|
||||
};
|
||||
};
|
||||
|
||||
#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \
|
||||
typedef typename fusion::result_of::next<BOOST_PP_CAT(I, n)>::type \
|
||||
BOOST_PP_CAT(I, BOOST_PP_INC(n));
|
||||
|
||||
#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \
|
||||
typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \
|
||||
BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n));
|
||||
|
||||
#define BOOST_FUSION_VALUE_OF_ITERATOR(z, n, data) \
|
||||
typedef typename fusion::result_of::value_of<BOOST_PP_CAT(I, n)>::type \
|
||||
BOOST_PP_CAT(T, n);
|
||||
|
||||
#define BOOST_PP_FILENAME_1 <boost/spirit/home/support/as_variant.hpp>
|
||||
#define BOOST_PP_ITERATION_LIMITS (1, BOOST_VARIANT_LIMIT_TYPES)
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#undef BOOST_FUSION_NEXT_ITERATOR
|
||||
#undef BOOST_FUSION_NEXT_CALL_ITERATOR
|
||||
#undef BOOST_FUSION_VALUE_OF_ITERATOR
|
||||
|
||||
template <typename Sequence>
|
||||
struct generate_variant
|
||||
{
|
||||
// build a variant generator being able to generate a variant holding
|
||||
// all of the types as given in the typelist
|
||||
typedef typename
|
||||
detail::as_variant<fusion::result_of::size<Sequence>::value>
|
||||
gen;
|
||||
|
||||
// use this generator to create the actual variant
|
||||
typedef typename gen::template apply<
|
||||
typename fusion::result_of::begin<Sequence>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
template <typename Sequence>
|
||||
struct as_variant
|
||||
{
|
||||
// make sure each of the types occurs only once in the type list
|
||||
typedef typename
|
||||
mpl::fold<
|
||||
Sequence, mpl::vector<>,
|
||||
mpl::if_<
|
||||
mpl::contains<mpl::_1, mpl::_2>,
|
||||
mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
|
||||
>
|
||||
>::type
|
||||
new_sequence;
|
||||
|
||||
// if there is only one type in the list of types we strip off the
|
||||
// variant all together
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
mpl::equal_to<mpl::size<new_sequence>, mpl::int_<1> >,
|
||||
mpl::deref<mpl::front<Sequence> >,
|
||||
detail::generate_variant<new_sequence>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
#else // defined(BOOST_PP_IS_ITERATING)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Preprocessor vertical repetition code
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
template <>
|
||||
struct as_variant<N>
|
||||
{
|
||||
template <typename I0>
|
||||
struct apply
|
||||
{
|
||||
BOOST_PP_REPEAT(N, BOOST_FUSION_NEXT_ITERATOR, _)
|
||||
BOOST_PP_REPEAT(N, BOOST_FUSION_VALUE_OF_ITERATOR, _)
|
||||
typedef variant<BOOST_PP_ENUM_PARAMS(N, T)> type;
|
||||
};
|
||||
};
|
||||
|
||||
#undef N
|
||||
#endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
70
libraries/include/boost/spirit/home/support/ascii.hpp
Normal file
70
libraries/include/boost/spirit/home/support/ascii.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(SPIRIT_ASCII_JAN_31_2006_0529PM)
|
||||
#define SPIRIT_ASCII_JAN_31_2006_0529PM
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace ascii
|
||||
{
|
||||
typedef spirit::char_class::ascii char_set;
|
||||
namespace tag = spirit::char_class::tag;
|
||||
|
||||
template <typename Class>
|
||||
struct make_tag
|
||||
: proto::terminal<spirit::char_class::key<char_set, Class> > {};
|
||||
|
||||
typedef make_tag<tag::alnum>::type alnum_type;
|
||||
typedef make_tag<tag::alpha>::type alpha_type;
|
||||
typedef make_tag<tag::blank>::type blank_type;
|
||||
typedef make_tag<tag::cntrl>::type cntrl_type;
|
||||
typedef make_tag<tag::digit>::type digit_type;
|
||||
typedef make_tag<tag::graph>::type graph_type;
|
||||
typedef make_tag<tag::print>::type print_type;
|
||||
typedef make_tag<tag::punct>::type punct_type;
|
||||
typedef make_tag<tag::space>::type space_type;
|
||||
typedef make_tag<tag::xdigit>::type xdigit_type;
|
||||
|
||||
alnum_type const alnum = {{}};
|
||||
alpha_type const alpha = {{}};
|
||||
blank_type const blank = {{}};
|
||||
cntrl_type const cntrl = {{}};
|
||||
digit_type const digit = {{}};
|
||||
graph_type const graph = {{}};
|
||||
print_type const print = {{}};
|
||||
punct_type const punct = {{}};
|
||||
space_type const space = {{}};
|
||||
xdigit_type const xdigit = {{}};
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::no_case_tag<char_set> >::type
|
||||
no_case_type;
|
||||
|
||||
no_case_type const no_case = no_case_type();
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::lower_case_tag<char_set> >::type
|
||||
lower_type;
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::upper_case_tag<char_set> >::type
|
||||
upper_type;
|
||||
|
||||
lower_type const lower = lower_type();
|
||||
upper_type const upper = upper_type();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
inline void silence_unused_warnings__ascii()
|
||||
{
|
||||
(void) alnum; (void) alpha; (void) blank; (void) cntrl; (void) digit;
|
||||
(void) graph; (void) print; (void) punct; (void) space; (void) xdigit;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
49
libraries/include/boost/spirit/home/support/attribute_of.hpp
Normal file
49
libraries/include/boost/spirit/home/support/attribute_of.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ATTRIBUTE_OF_JAN_29_2007_0954AM)
|
||||
#define BOOST_SPIRIT_ATTRIBUTE_OF_JAN_29_2007_0954AM
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <
|
||||
typename Domain, typename T
|
||||
, typename Context, typename Iterator = unused_type>
|
||||
struct attribute_of :
|
||||
attribute_of<
|
||||
Domain
|
||||
, typename result_of::as_component<Domain, T>::type
|
||||
, Context
|
||||
, Iterator
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <
|
||||
typename Domain, typename Director, typename Elements
|
||||
, typename Context, typename Iterator>
|
||||
struct attribute_of<
|
||||
Domain
|
||||
, component<Domain, Director, Elements>
|
||||
, Context
|
||||
, Iterator
|
||||
>
|
||||
{
|
||||
typedef
|
||||
component<Domain, Director, Elements>
|
||||
component_type;
|
||||
|
||||
typedef typename Director::template
|
||||
attribute<component_type, Context, Iterator>::type
|
||||
type;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,195 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ATTRIBUTE_TRANSFORM_DEC_17_2007_0718AM)
|
||||
#define BOOST_SPIRIT_ATTRIBUTE_TRANSFORM_DEC_17_2007_0718AM
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/support/detail/values.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
#include <boost/fusion/include/transform.hpp>
|
||||
#include <boost/fusion/include/filter_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// Generalized attribute transformation utilities for Qi parsers
|
||||
|
||||
namespace traits
|
||||
{
|
||||
using boost::spirit::detail::not_is_variant;
|
||||
|
||||
// Here, we provide policies for stripping single element fusion
|
||||
// sequences. Add more specializations as needed.
|
||||
template <typename T, typename IsSequence, typename Enable = void>
|
||||
struct strip_single_element_sequence
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct strip_single_element_sequence<
|
||||
fusion::vector<T>, mpl::false_,
|
||||
typename boost::enable_if<not_is_variant<T> >::type
|
||||
>
|
||||
{
|
||||
// Strips single element fusion vectors into its 'naked'
|
||||
// form: vector<T> --> T
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct strip_single_element_sequence<
|
||||
fusion::vector<T>, mpl::true_,
|
||||
typename boost::enable_if<not_is_variant<T> >::type
|
||||
>
|
||||
{
|
||||
// Strips single element fusion vectors into its 'naked'
|
||||
// form: vector<T> --> T, but does so only if T is not a fusion
|
||||
// sequence itself
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::vector<T>,
|
||||
T
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename IsSequence>
|
||||
struct strip_single_element_sequence<
|
||||
fusion::vector<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
, IsSequence
|
||||
>
|
||||
{
|
||||
// Exception: Single element variants are not stripped!
|
||||
typedef fusion::vector<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > type;
|
||||
};
|
||||
}
|
||||
|
||||
// Use this when building heterogeneous fusion sequences
|
||||
// Note:
|
||||
//
|
||||
// Director should have these nested metafunctions
|
||||
//
|
||||
// 1: build_container<All, Filtered>
|
||||
//
|
||||
// All: all child attributes
|
||||
// Filtered: all child attributes except unused
|
||||
//
|
||||
// 2: transform_child<T>
|
||||
//
|
||||
// T: child attribute
|
||||
//
|
||||
template <
|
||||
typename Director, typename Component
|
||||
, typename Iterator, typename Context
|
||||
, typename IsSequence = mpl::false_>
|
||||
struct build_fusion_sequence
|
||||
{
|
||||
template <
|
||||
typename Domain, typename Director_
|
||||
, typename Iterator_, typename Context_>
|
||||
struct child_attribute
|
||||
{
|
||||
template <typename T>
|
||||
struct result;
|
||||
|
||||
template <typename F, typename ChildComponent>
|
||||
struct result<F(ChildComponent)>
|
||||
{
|
||||
typedef typename
|
||||
Director_::template transform_child<
|
||||
typename traits::attribute_of<
|
||||
Domain, ChildComponent, Context_, Iterator_>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
};
|
||||
|
||||
// Compute the list of attributes of all sub-parsers
|
||||
typedef
|
||||
typename fusion::result_of::transform<
|
||||
typename Component::elements_type
|
||||
, child_attribute<
|
||||
typename Component::domain, Director, Iterator, Context>
|
||||
>::type
|
||||
all;
|
||||
|
||||
// Compute the list of all *used* attributes of sub-parsers
|
||||
// (filter all unused parsers from the list)
|
||||
typedef
|
||||
typename fusion::result_of::filter_if<
|
||||
all
|
||||
, spirit::traits::is_not_unused<mpl::_>
|
||||
>::type
|
||||
filtered;
|
||||
|
||||
// Ask the director to build the actual fusion sequence.
|
||||
// But *only if* the filtered sequence is not empty. i.e.
|
||||
// if the sequence has all unused elements, our result
|
||||
// will also be unused.
|
||||
typedef
|
||||
typename mpl::eval_if<
|
||||
fusion::result_of::empty<filtered>
|
||||
, mpl::identity<unused_type>
|
||||
, typename Director::template build_container<all, filtered>
|
||||
>::type
|
||||
attribute_sequence;
|
||||
|
||||
// Finally, strip single element sequences into its
|
||||
// naked form (e.g. vector<T> --> T)
|
||||
typedef typename
|
||||
traits::strip_single_element_sequence<attribute_sequence, IsSequence>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// Use this when building homogeneous containers. Component
|
||||
// is assumed to be a unary. Note:
|
||||
//
|
||||
// Director should have this nested metafunction
|
||||
//
|
||||
// 1: build_attribute_container<T>
|
||||
//
|
||||
// T: the data-type for the container
|
||||
//
|
||||
template <
|
||||
typename Director, typename Component
|
||||
, typename Iterator, typename Context>
|
||||
struct build_container
|
||||
{
|
||||
// Get the component's subject.
|
||||
typedef typename
|
||||
result_of::subject<Component>::type
|
||||
subject_type;
|
||||
|
||||
// Get the subject's attribute
|
||||
typedef typename
|
||||
traits::attribute_of<
|
||||
typename Component::domain, subject_type, Context, Iterator>::type
|
||||
attr_type;
|
||||
|
||||
// If attribute is unused_type, return it as it is.
|
||||
// If not, then ask the director to build the actual
|
||||
// container for the attribute type.
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<unused_type, attr_type>
|
||||
, unused_type
|
||||
, typename Director::template
|
||||
build_attribute_container<attr_type>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_SUPPORT_CONFIX_AUG_19_2008_1103AM)
|
||||
#define BOOST_SPIRIT_SUPPORT_CONFIX_AUG_19_2008_1103AM
|
||||
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace tag
|
||||
{
|
||||
// This is the tag returned by the confix() function
|
||||
template <typename Prefix, typename Suffix>
|
||||
struct confix_tag
|
||||
{
|
||||
Prefix prefix;
|
||||
Suffix suffix;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Prefix, typename Suffix = Prefix>
|
||||
struct confix_spec
|
||||
: proto::terminal<tag::confix_tag<Prefix, Suffix> >::type
|
||||
{
|
||||
private:
|
||||
typedef typename
|
||||
proto::terminal<tag::confix_tag<Prefix, Suffix> >::type
|
||||
base_type;
|
||||
|
||||
base_type make_tag(Prefix const& prefix, Suffix const& suffix) const
|
||||
{
|
||||
base_type xpr = {{prefix, suffix}};
|
||||
return xpr;
|
||||
}
|
||||
|
||||
public:
|
||||
confix_spec(Prefix const& prefix, Suffix const& suffix)
|
||||
: base_type(make_tag(prefix, suffix))
|
||||
{}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct confix_extractor
|
||||
{
|
||||
template <typename Prefix, typename Suffix>
|
||||
static Prefix const& prefix(tag::confix_tag<Prefix, Suffix> const& c)
|
||||
{ return c.prefix; }
|
||||
|
||||
template <typename Prefix, typename Suffix>
|
||||
static Suffix const& suffix(tag::confix_tag<Prefix, Suffix> const& c)
|
||||
{ return c.suffix; }
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// construct a confix component
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
inline confix_spec<char const*>
|
||||
confix(char const* prefix, char const* suffix)
|
||||
{
|
||||
return confix_spec<char const*>(prefix, suffix);
|
||||
}
|
||||
|
||||
inline confix_spec<wchar_t const*>
|
||||
confix(wchar_t const* prefix, wchar_t const* suffix)
|
||||
{
|
||||
return confix_spec<wchar_t const*>(prefix, suffix);
|
||||
}
|
||||
|
||||
template <typename Prefix, typename Suffix>
|
||||
inline confix_spec<Prefix, Suffix>
|
||||
confix(Prefix const& prefix, Suffix const& suffix)
|
||||
{
|
||||
return confix_spec<Prefix, Suffix>(prefix, suffix);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_FUNCTOR_HOLDER_APR_01_2007_0917AM)
|
||||
#define BOOST_SPIRIT_FUNCTOR_HOLDER_APR_01_2007_0917AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/proto/core.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Functor>
|
||||
struct functor_holder
|
||||
{
|
||||
typedef Functor functor_type;
|
||||
T held;
|
||||
};
|
||||
|
||||
template <typename T, typename Functor>
|
||||
struct make_functor_holder
|
||||
: proto::terminal<functor_holder<T, Functor> >
|
||||
{
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_SUPPORT_META_FUNCTION_HOLDER_SEP_03_2007_0302PM)
|
||||
#define BOOST_SPIRIT_SUPPORT_META_FUNCTION_HOLDER_SEP_03_2007_0302PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Functor, typename ParameterMF>
|
||||
struct make_function_holder_base
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_same<Functor, ParameterMF>, unused_type, ParameterMF
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Functor, typename ParameterMF>
|
||||
struct meta_function_holder
|
||||
: spirit::detail::make_function_holder_base<Functor, ParameterMF>::type
|
||||
{
|
||||
private:
|
||||
typedef typename
|
||||
spirit::detail::make_function_holder_base<Functor, ParameterMF>::type
|
||||
base_type;
|
||||
|
||||
public:
|
||||
meta_function_holder()
|
||||
{}
|
||||
|
||||
meta_function_holder(ParameterMF const& mf)
|
||||
: base_type(mf)
|
||||
{}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
261
libraries/include/boost/spirit/home/support/char_class.hpp
Normal file
261
libraries/include/boost/spirit/home/support/char_class.hpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_CHAR_CLASS_NOV_10_2006_0907AM)
|
||||
#define BOOST_SPIRIT_CHAR_CLASS_NOV_10_2006_0907AM
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/spirit/home/support/char_class/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_class/standard_wide.hpp>
|
||||
#include <boost/spirit/home/support/char_class/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_class/iso8859_1.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' warning
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace char_class
|
||||
{
|
||||
namespace tag
|
||||
{
|
||||
// classification
|
||||
struct alnum {};
|
||||
struct alpha {};
|
||||
struct digit {};
|
||||
struct xdigit {};
|
||||
struct cntrl {};
|
||||
struct graph {};
|
||||
struct lower {};
|
||||
struct print {};
|
||||
struct punct {};
|
||||
struct space {};
|
||||
struct blank {};
|
||||
struct upper {};
|
||||
}
|
||||
|
||||
// This composite tag type encodes both the character
|
||||
// set and the specific char classification.
|
||||
template <typename CharSet, typename CharClass>
|
||||
struct key
|
||||
{
|
||||
typedef CharSet char_set;
|
||||
typedef CharClass char_class;
|
||||
};
|
||||
|
||||
// This identity tag types encode the character set.
|
||||
struct no_case_base_tag {};
|
||||
struct lower_case_base_tag {};
|
||||
struct upper_case_base_tag {};
|
||||
|
||||
template <typename CharSet>
|
||||
struct no_case_tag : no_case_base_tag
|
||||
{
|
||||
typedef CharSet char_set;
|
||||
};
|
||||
|
||||
template <typename CharSet>
|
||||
struct lower_case_tag : lower_case_base_tag
|
||||
{
|
||||
typedef CharSet char_set;
|
||||
typedef tag::lower char_class;
|
||||
};
|
||||
|
||||
template <typename CharSet>
|
||||
struct upper_case_tag : upper_case_base_tag
|
||||
{
|
||||
typedef CharSet char_set;
|
||||
typedef tag::upper char_class;
|
||||
};
|
||||
|
||||
// Test characters for classification
|
||||
template <typename CharSet>
|
||||
struct classify
|
||||
{
|
||||
typedef typename CharSet::char_type char_type;
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::alnum, Char ch)
|
||||
{
|
||||
return CharSet::isalnum(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::alpha, Char ch)
|
||||
{
|
||||
return CharSet::isalpha(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::digit, Char ch)
|
||||
{
|
||||
return CharSet::isdigit(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::xdigit, Char ch)
|
||||
{
|
||||
return CharSet::isxdigit(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::cntrl, Char ch)
|
||||
{
|
||||
return CharSet::iscntrl(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::graph, Char ch)
|
||||
{
|
||||
return CharSet::isgraph(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::lower, Char ch)
|
||||
{
|
||||
return CharSet::islower(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::print, Char ch)
|
||||
{
|
||||
return CharSet::isprint(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::punct, Char ch)
|
||||
{
|
||||
return CharSet::ispunct(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::space, Char ch)
|
||||
{
|
||||
return CharSet::isspace(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::blank, Char ch)
|
||||
{
|
||||
return CharSet::isblank BOOST_PREVENT_MACRO_SUBSTITUTION (char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static bool
|
||||
is(tag::upper, Char ch)
|
||||
{
|
||||
return CharSet::isupper(char_type(ch));
|
||||
}
|
||||
};
|
||||
|
||||
// Convert characters
|
||||
template <typename CharSet>
|
||||
struct convert
|
||||
{
|
||||
typedef typename CharSet::char_type char_type;
|
||||
|
||||
template <typename Char>
|
||||
static Char
|
||||
to(tag::lower, Char ch)
|
||||
{
|
||||
return CharSet::tolower(char_type(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static Char
|
||||
to(tag::upper, Char ch)
|
||||
{
|
||||
return CharSet::toupper(char_type(ch));
|
||||
}
|
||||
};
|
||||
|
||||
// Info on character classification
|
||||
template <typename CharSet>
|
||||
struct what
|
||||
{
|
||||
static char const* is(tag::alnum)
|
||||
{
|
||||
return "alnum";
|
||||
}
|
||||
|
||||
static char const* is(tag::alpha)
|
||||
{
|
||||
return "alpha";
|
||||
}
|
||||
|
||||
static char const* is(tag::digit)
|
||||
{
|
||||
return "digit";
|
||||
}
|
||||
|
||||
static char const* is(tag::xdigit)
|
||||
{
|
||||
return "xdigit";
|
||||
}
|
||||
|
||||
static char const* is(tag::cntrl)
|
||||
{
|
||||
return "cntrl";
|
||||
}
|
||||
|
||||
static char const* is(tag::graph)
|
||||
{
|
||||
return "graph";
|
||||
}
|
||||
|
||||
static char const* is(tag::lower)
|
||||
{
|
||||
return "lower";
|
||||
}
|
||||
|
||||
static char const* is(tag::print)
|
||||
{
|
||||
return "print";
|
||||
}
|
||||
|
||||
static char const* is(tag::punct)
|
||||
{
|
||||
return "punct";
|
||||
}
|
||||
|
||||
static char const* is(tag::space)
|
||||
{
|
||||
return "space";
|
||||
}
|
||||
|
||||
static char const* is(tag::blank)
|
||||
{
|
||||
return "blank";
|
||||
}
|
||||
|
||||
static char const* is(tag::upper)
|
||||
{
|
||||
return "upper";
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
295
libraries/include/boost/spirit/home/support/char_class/ascii.hpp
Normal file
295
libraries/include/boost/spirit/home/support/char_class/ascii.hpp
Normal file
@@ -0,0 +1,295 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ASCII_APR_26_2006_1106PM)
|
||||
#define BOOST_SPIRIT_ASCII_APR_26_2006_1106PM
|
||||
|
||||
#include <climits>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constants used to classify the single characters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_CC_DIGIT 0x0001
|
||||
#define BOOST_CC_XDIGIT 0x0002
|
||||
#define BOOST_CC_ALPHA 0x0004
|
||||
#define BOOST_CC_CTRL 0x0008
|
||||
#define BOOST_CC_LOWER 0x0010
|
||||
#define BOOST_CC_UPPER 0x0020
|
||||
#define BOOST_CC_SPACE 0x0040
|
||||
#define BOOST_CC_PUNCT 0x0080
|
||||
|
||||
namespace boost { namespace spirit { namespace char_class
|
||||
{
|
||||
// The detection of isgraph(), isprint() and isblank() is done programmatically
|
||||
// to keep the character type table small. Additionally, these functions are
|
||||
// rather seldom used and the programmatic detection is very simple.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ASCII character classification table
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
const unsigned char ascii_char_types[] =
|
||||
{
|
||||
/* NUL 0 0 */ BOOST_CC_CTRL,
|
||||
/* SOH 1 1 */ BOOST_CC_CTRL,
|
||||
/* STX 2 2 */ BOOST_CC_CTRL,
|
||||
/* ETX 3 3 */ BOOST_CC_CTRL,
|
||||
/* EOT 4 4 */ BOOST_CC_CTRL,
|
||||
/* ENQ 5 5 */ BOOST_CC_CTRL,
|
||||
/* ACK 6 6 */ BOOST_CC_CTRL,
|
||||
/* BEL 7 7 */ BOOST_CC_CTRL,
|
||||
/* BS 8 8 */ BOOST_CC_CTRL,
|
||||
/* HT 9 9 */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* NL 10 a */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* VT 11 b */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* NP 12 c */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* CR 13 d */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* SO 14 e */ BOOST_CC_CTRL,
|
||||
/* SI 15 f */ BOOST_CC_CTRL,
|
||||
/* DLE 16 10 */ BOOST_CC_CTRL,
|
||||
/* DC1 17 11 */ BOOST_CC_CTRL,
|
||||
/* DC2 18 12 */ BOOST_CC_CTRL,
|
||||
/* DC3 19 13 */ BOOST_CC_CTRL,
|
||||
/* DC4 20 14 */ BOOST_CC_CTRL,
|
||||
/* NAK 21 15 */ BOOST_CC_CTRL,
|
||||
/* SYN 22 16 */ BOOST_CC_CTRL,
|
||||
/* ETB 23 17 */ BOOST_CC_CTRL,
|
||||
/* CAN 24 18 */ BOOST_CC_CTRL,
|
||||
/* EM 25 19 */ BOOST_CC_CTRL,
|
||||
/* SUB 26 1a */ BOOST_CC_CTRL,
|
||||
/* ESC 27 1b */ BOOST_CC_CTRL,
|
||||
/* FS 28 1c */ BOOST_CC_CTRL,
|
||||
/* GS 29 1d */ BOOST_CC_CTRL,
|
||||
/* RS 30 1e */ BOOST_CC_CTRL,
|
||||
/* US 31 1f */ BOOST_CC_CTRL,
|
||||
/* SP 32 20 */ BOOST_CC_SPACE,
|
||||
/* ! 33 21 */ BOOST_CC_PUNCT,
|
||||
/* " 34 22 */ BOOST_CC_PUNCT,
|
||||
/* # 35 23 */ BOOST_CC_PUNCT,
|
||||
/* $ 36 24 */ BOOST_CC_PUNCT,
|
||||
/* % 37 25 */ BOOST_CC_PUNCT,
|
||||
/* & 38 26 */ BOOST_CC_PUNCT,
|
||||
/* ' 39 27 */ BOOST_CC_PUNCT,
|
||||
/* ( 40 28 */ BOOST_CC_PUNCT,
|
||||
/* ) 41 29 */ BOOST_CC_PUNCT,
|
||||
/* * 42 2a */ BOOST_CC_PUNCT,
|
||||
/* + 43 2b */ BOOST_CC_PUNCT,
|
||||
/* , 44 2c */ BOOST_CC_PUNCT,
|
||||
/* - 45 2d */ BOOST_CC_PUNCT,
|
||||
/* . 46 2e */ BOOST_CC_PUNCT,
|
||||
/* / 47 2f */ BOOST_CC_PUNCT,
|
||||
/* 0 48 30 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 1 49 31 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 2 50 32 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 3 51 33 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 4 52 34 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 5 53 35 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 6 54 36 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 7 55 37 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 8 56 38 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 9 57 39 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* : 58 3a */ BOOST_CC_PUNCT,
|
||||
/* ; 59 3b */ BOOST_CC_PUNCT,
|
||||
/* < 60 3c */ BOOST_CC_PUNCT,
|
||||
/* = 61 3d */ BOOST_CC_PUNCT,
|
||||
/* > 62 3e */ BOOST_CC_PUNCT,
|
||||
/* ? 63 3f */ BOOST_CC_PUNCT,
|
||||
/* @ 64 40 */ BOOST_CC_PUNCT,
|
||||
/* A 65 41 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* B 66 42 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* C 67 43 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* D 68 44 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* E 69 45 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* F 70 46 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* G 71 47 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* H 72 48 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* I 73 49 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* J 74 4a */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* K 75 4b */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* L 76 4c */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* M 77 4d */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* N 78 4e */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* O 79 4f */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* P 80 50 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Q 81 51 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* R 82 52 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* S 83 53 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* T 84 54 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* U 85 55 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* V 86 56 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* W 87 57 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* X 88 58 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Y 89 59 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Z 90 5a */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* [ 91 5b */ BOOST_CC_PUNCT,
|
||||
/* \ 92 5c */ BOOST_CC_PUNCT,
|
||||
/* ] 93 5d */ BOOST_CC_PUNCT,
|
||||
/* ^ 94 5e */ BOOST_CC_PUNCT,
|
||||
/* _ 95 5f */ BOOST_CC_PUNCT,
|
||||
/* ` 96 60 */ BOOST_CC_PUNCT,
|
||||
/* a 97 61 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* b 98 62 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* c 99 63 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* d 100 64 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* e 101 65 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* f 102 66 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* g 103 67 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* h 104 68 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* i 105 69 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* j 106 6a */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* k 107 6b */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* l 108 6c */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* m 109 6d */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* n 110 6e */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* o 111 6f */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* p 112 70 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* q 113 71 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* r 114 72 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* s 115 73 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* t 116 74 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* u 117 75 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* v 118 76 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* w 119 77 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* x 120 78 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* y 121 79 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* z 122 7a */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* { 123 7b */ BOOST_CC_PUNCT,
|
||||
/* | 124 7c */ BOOST_CC_PUNCT,
|
||||
/* } 125 7d */ BOOST_CC_PUNCT,
|
||||
/* ~ 126 7e */ BOOST_CC_PUNCT,
|
||||
/* DEL 127 7f */ BOOST_CC_CTRL,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test characters for specified conditions (using ASCII)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct ascii
|
||||
{
|
||||
typedef char char_type;
|
||||
|
||||
static bool
|
||||
is_ascii(int ch)
|
||||
{
|
||||
return (0 == (ch & ~0x7f)) ? true : false;
|
||||
}
|
||||
|
||||
static int
|
||||
isalnum(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_ALPHA)
|
||||
|| (ascii_char_types[ch] & BOOST_CC_DIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
isalpha(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_ALPHA);
|
||||
}
|
||||
|
||||
static int
|
||||
isdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_DIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
isxdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_XDIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
iscntrl(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_CTRL);
|
||||
}
|
||||
|
||||
static int
|
||||
isgraph(int ch)
|
||||
{
|
||||
return ('\x21' <= ch && ch <= '\x7e');
|
||||
}
|
||||
|
||||
static int
|
||||
islower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_LOWER);
|
||||
}
|
||||
|
||||
static int
|
||||
isprint(int ch)
|
||||
{
|
||||
return ('\x20' <= ch && ch <= '\x7e');
|
||||
}
|
||||
|
||||
static int
|
||||
ispunct(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_PUNCT);
|
||||
}
|
||||
|
||||
static int
|
||||
isspace(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_SPACE);
|
||||
}
|
||||
|
||||
static int
|
||||
isblank BOOST_PREVENT_MACRO_SUBSTITUTION (int ch)
|
||||
{
|
||||
return ('\x09' == ch || '\x20' == ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return (ascii_char_types[ch] & BOOST_CC_UPPER);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Simple character conversions
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int
|
||||
tolower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return isupper(ch) ? (ch - 'A' + 'a') : ch;
|
||||
}
|
||||
|
||||
static int
|
||||
toupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(is_ascii(ch));
|
||||
return islower(ch) ? (ch - 'a' + 'A') : ch;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// undefine macros
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#undef BOOST_CC_DIGIT
|
||||
#undef BOOST_CC_XDIGIT
|
||||
#undef BOOST_CC_ALPHA
|
||||
#undef BOOST_CC_CTRL
|
||||
#undef BOOST_CC_LOWER
|
||||
#undef BOOST_CC_UPPER
|
||||
#undef BOOST_CC_PUNCT
|
||||
#undef BOOST_CC_SPACE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,689 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ISO8859_1_APR_26_2006_1106PM)
|
||||
#define BOOST_SPIRIT_ISO8859_1_APR_26_2006_1106PM
|
||||
|
||||
#include <climits>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constants used to classify the single characters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_CC_DIGIT 0x0001
|
||||
#define BOOST_CC_XDIGIT 0x0002
|
||||
#define BOOST_CC_ALPHA 0x0004
|
||||
#define BOOST_CC_CTRL 0x0008
|
||||
#define BOOST_CC_LOWER 0x0010
|
||||
#define BOOST_CC_UPPER 0x0020
|
||||
#define BOOST_CC_SPACE 0x0040
|
||||
#define BOOST_CC_PUNCT 0x0080
|
||||
|
||||
namespace boost { namespace spirit { namespace char_class
|
||||
{
|
||||
// The detection of isgraph(), isprint() and isblank() is done programmatically
|
||||
// to keep the character type table small. Additionally, these functions are
|
||||
// rather seldom used and the programmatic detection is very simple.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ISO 8859-1 character classification table
|
||||
//
|
||||
// the comments intentionally contain non-ascii characters
|
||||
// boostinspect:noascii
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
const unsigned char iso8859_1_char_types[] =
|
||||
{
|
||||
/* NUL 0 0 */ BOOST_CC_CTRL,
|
||||
/* SOH 1 1 */ BOOST_CC_CTRL,
|
||||
/* STX 2 2 */ BOOST_CC_CTRL,
|
||||
/* ETX 3 3 */ BOOST_CC_CTRL,
|
||||
/* EOT 4 4 */ BOOST_CC_CTRL,
|
||||
/* ENQ 5 5 */ BOOST_CC_CTRL,
|
||||
/* ACK 6 6 */ BOOST_CC_CTRL,
|
||||
/* BEL 7 7 */ BOOST_CC_CTRL,
|
||||
/* BS 8 8 */ BOOST_CC_CTRL,
|
||||
/* HT 9 9 */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* NL 10 a */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* VT 11 b */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* NP 12 c */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* CR 13 d */ BOOST_CC_CTRL|BOOST_CC_SPACE,
|
||||
/* SO 14 e */ BOOST_CC_CTRL,
|
||||
/* SI 15 f */ BOOST_CC_CTRL,
|
||||
/* DLE 16 10 */ BOOST_CC_CTRL,
|
||||
/* DC1 17 11 */ BOOST_CC_CTRL,
|
||||
/* DC2 18 12 */ BOOST_CC_CTRL,
|
||||
/* DC3 19 13 */ BOOST_CC_CTRL,
|
||||
/* DC4 20 14 */ BOOST_CC_CTRL,
|
||||
/* NAK 21 15 */ BOOST_CC_CTRL,
|
||||
/* SYN 22 16 */ BOOST_CC_CTRL,
|
||||
/* ETB 23 17 */ BOOST_CC_CTRL,
|
||||
/* CAN 24 18 */ BOOST_CC_CTRL,
|
||||
/* EM 25 19 */ BOOST_CC_CTRL,
|
||||
/* SUB 26 1a */ BOOST_CC_CTRL,
|
||||
/* ESC 27 1b */ BOOST_CC_CTRL,
|
||||
/* FS 28 1c */ BOOST_CC_CTRL,
|
||||
/* GS 29 1d */ BOOST_CC_CTRL,
|
||||
/* RS 30 1e */ BOOST_CC_CTRL,
|
||||
/* US 31 1f */ BOOST_CC_CTRL,
|
||||
/* SP 32 20 */ BOOST_CC_SPACE,
|
||||
/* ! 33 21 */ BOOST_CC_PUNCT,
|
||||
/* " 34 22 */ BOOST_CC_PUNCT,
|
||||
/* # 35 23 */ BOOST_CC_PUNCT,
|
||||
/* $ 36 24 */ BOOST_CC_PUNCT,
|
||||
/* % 37 25 */ BOOST_CC_PUNCT,
|
||||
/* & 38 26 */ BOOST_CC_PUNCT,
|
||||
/* ' 39 27 */ BOOST_CC_PUNCT,
|
||||
/* ( 40 28 */ BOOST_CC_PUNCT,
|
||||
/* ) 41 29 */ BOOST_CC_PUNCT,
|
||||
/* * 42 2a */ BOOST_CC_PUNCT,
|
||||
/* + 43 2b */ BOOST_CC_PUNCT,
|
||||
/* , 44 2c */ BOOST_CC_PUNCT,
|
||||
/* - 45 2d */ BOOST_CC_PUNCT,
|
||||
/* . 46 2e */ BOOST_CC_PUNCT,
|
||||
/* / 47 2f */ BOOST_CC_PUNCT,
|
||||
/* 0 48 30 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 1 49 31 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 2 50 32 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 3 51 33 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 4 52 34 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 5 53 35 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 6 54 36 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 7 55 37 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 8 56 38 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* 9 57 39 */ BOOST_CC_DIGIT|BOOST_CC_XDIGIT,
|
||||
/* : 58 3a */ BOOST_CC_PUNCT,
|
||||
/* ; 59 3b */ BOOST_CC_PUNCT,
|
||||
/* < 60 3c */ BOOST_CC_PUNCT,
|
||||
/* = 61 3d */ BOOST_CC_PUNCT,
|
||||
/* > 62 3e */ BOOST_CC_PUNCT,
|
||||
/* ? 63 3f */ BOOST_CC_PUNCT,
|
||||
/* @ 64 40 */ BOOST_CC_PUNCT,
|
||||
/* A 65 41 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* B 66 42 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* C 67 43 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* D 68 44 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* E 69 45 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* F 70 46 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_UPPER,
|
||||
/* G 71 47 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* H 72 48 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* I 73 49 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* J 74 4a */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* K 75 4b */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* L 76 4c */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* M 77 4d */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* N 78 4e */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* O 79 4f */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* P 80 50 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Q 81 51 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* R 82 52 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* S 83 53 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* T 84 54 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* U 85 55 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* V 86 56 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* W 87 57 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* X 88 58 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Y 89 59 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* Z 90 5a */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* [ 91 5b */ BOOST_CC_PUNCT,
|
||||
/* \ 92 5c */ BOOST_CC_PUNCT,
|
||||
/* ] 93 5d */ BOOST_CC_PUNCT,
|
||||
/* ^ 94 5e */ BOOST_CC_PUNCT,
|
||||
/* _ 95 5f */ BOOST_CC_PUNCT,
|
||||
/* ` 96 60 */ BOOST_CC_PUNCT,
|
||||
/* a 97 61 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* b 98 62 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* c 99 63 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* d 100 64 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* e 101 65 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* f 102 66 */ BOOST_CC_ALPHA|BOOST_CC_XDIGIT|BOOST_CC_LOWER,
|
||||
/* g 103 67 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* h 104 68 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* i 105 69 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* j 106 6a */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* k 107 6b */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* l 108 6c */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* m 109 6d */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* n 110 6e */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* o 111 6f */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* p 112 70 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* q 113 71 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* r 114 72 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* s 115 73 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* t 116 74 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* u 117 75 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* v 118 76 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* w 119 77 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* x 120 78 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* y 121 79 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* z 122 7a */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* { 123 7b */ BOOST_CC_PUNCT,
|
||||
/* | 124 7c */ BOOST_CC_PUNCT,
|
||||
/* } 125 7d */ BOOST_CC_PUNCT,
|
||||
/* ~ 126 7e */ BOOST_CC_PUNCT,
|
||||
/* DEL 127 7f */ BOOST_CC_CTRL,
|
||||
/* -- 128 80 */ BOOST_CC_CTRL,
|
||||
/* -- 129 81 */ BOOST_CC_CTRL,
|
||||
/* -- 130 82 */ BOOST_CC_CTRL,
|
||||
/* -- 131 83 */ BOOST_CC_CTRL,
|
||||
/* -- 132 84 */ BOOST_CC_CTRL,
|
||||
/* -- 133 85 */ BOOST_CC_CTRL,
|
||||
/* -- 134 86 */ BOOST_CC_CTRL,
|
||||
/* -- 135 87 */ BOOST_CC_CTRL,
|
||||
/* -- 136 88 */ BOOST_CC_CTRL,
|
||||
/* -- 137 89 */ BOOST_CC_CTRL,
|
||||
/* -- 138 8a */ BOOST_CC_CTRL,
|
||||
/* -- 139 8b */ BOOST_CC_CTRL,
|
||||
/* -- 140 8c */ BOOST_CC_CTRL,
|
||||
/* -- 141 8d */ BOOST_CC_CTRL,
|
||||
/* -- 142 8e */ BOOST_CC_CTRL,
|
||||
/* -- 143 8f */ BOOST_CC_CTRL,
|
||||
/* -- 144 90 */ BOOST_CC_CTRL,
|
||||
/* -- 145 91 */ BOOST_CC_CTRL,
|
||||
/* -- 146 92 */ BOOST_CC_CTRL,
|
||||
/* -- 147 93 */ BOOST_CC_CTRL,
|
||||
/* -- 148 94 */ BOOST_CC_CTRL,
|
||||
/* -- 149 95 */ BOOST_CC_CTRL,
|
||||
/* -- 150 96 */ BOOST_CC_CTRL,
|
||||
/* -- 151 97 */ BOOST_CC_CTRL,
|
||||
/* -- 152 98 */ BOOST_CC_CTRL,
|
||||
/* -- 153 99 */ BOOST_CC_CTRL,
|
||||
/* -- 154 9a */ BOOST_CC_CTRL,
|
||||
/* -- 155 9b */ BOOST_CC_CTRL,
|
||||
/* -- 156 9c */ BOOST_CC_CTRL,
|
||||
/* -- 157 9d */ BOOST_CC_CTRL,
|
||||
/* -- 158 9e */ BOOST_CC_CTRL,
|
||||
/* -- 159 9f */ BOOST_CC_CTRL,
|
||||
/* 160 a0 */ BOOST_CC_SPACE,
|
||||
/* <20> 161 a1 */ BOOST_CC_PUNCT,
|
||||
/* <20> 162 a2 */ BOOST_CC_PUNCT,
|
||||
/* <20> 163 a3 */ BOOST_CC_PUNCT,
|
||||
/* <20> 164 a4 */ BOOST_CC_PUNCT,
|
||||
/* <20> 165 a5 */ BOOST_CC_PUNCT,
|
||||
/* <20> 166 a6 */ BOOST_CC_PUNCT,
|
||||
/* <20> 167 a7 */ BOOST_CC_PUNCT,
|
||||
/* <20> 168 a8 */ BOOST_CC_PUNCT,
|
||||
/* <20> 169 a9 */ BOOST_CC_PUNCT,
|
||||
/* <20> 170 aa */ BOOST_CC_PUNCT,
|
||||
/* <20> 171 ab */ BOOST_CC_PUNCT,
|
||||
/* <20> 172 ac */ BOOST_CC_PUNCT,
|
||||
/* <20> 173 ad */ BOOST_CC_PUNCT,
|
||||
/* <20> 174 ae */ BOOST_CC_PUNCT,
|
||||
/* <20> 175 af */ BOOST_CC_PUNCT,
|
||||
/* <20> 176 b0 */ BOOST_CC_PUNCT,
|
||||
/* <20> 177 b1 */ BOOST_CC_PUNCT,
|
||||
/* <20> 178 b2 */ BOOST_CC_DIGIT|BOOST_CC_PUNCT,
|
||||
/* <20> 179 b3 */ BOOST_CC_DIGIT|BOOST_CC_PUNCT,
|
||||
/* <20> 180 b4 */ BOOST_CC_PUNCT,
|
||||
/* <20> 181 b5 */ BOOST_CC_PUNCT,
|
||||
/* <20> 182 b6 */ BOOST_CC_PUNCT,
|
||||
/* <20> 183 b7 */ BOOST_CC_PUNCT,
|
||||
/* <20> 184 b8 */ BOOST_CC_PUNCT,
|
||||
/* <20> 185 b9 */ BOOST_CC_DIGIT|BOOST_CC_PUNCT,
|
||||
/* <20> 186 ba */ BOOST_CC_PUNCT,
|
||||
/* <20> 187 bb */ BOOST_CC_PUNCT,
|
||||
/* <20> 188 bc */ BOOST_CC_PUNCT,
|
||||
/* <20> 189 bd */ BOOST_CC_PUNCT,
|
||||
/* <20> 190 be */ BOOST_CC_PUNCT,
|
||||
/* <20> 191 bf */ BOOST_CC_PUNCT,
|
||||
/* <20> 192 c0 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 193 c1 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 194 c2 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 195 c3 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 196 c4 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 197 c5 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 198 c6 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 199 c7 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 200 c8 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 201 c9 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 202 ca */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 203 cb */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 204 cc */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 205 cd */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 206 ce */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 207 cf */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 208 d0 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 209 d1 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 210 d2 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 211 d3 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 212 d4 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 213 d5 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 214 d6 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 215 d7 */ BOOST_CC_PUNCT,
|
||||
/* <20> 216 d8 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 217 d9 */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 218 da */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 219 db */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 220 dc */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 221 dd */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 222 de */ BOOST_CC_ALPHA|BOOST_CC_UPPER,
|
||||
/* <20> 223 df */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 224 e0 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 225 e1 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 226 e2 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 227 e3 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 228 e4 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 229 e5 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 230 e6 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 231 e7 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 232 e8 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 233 e9 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 234 ea */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 235 eb */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 236 ec */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 237 ed */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 238 ee */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 239 ef */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 240 f0 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 241 f1 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 242 f2 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 243 f3 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 244 f4 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 245 f5 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 246 f6 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 247 f7 */ BOOST_CC_PUNCT,
|
||||
/* <20> 248 f8 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 249 f9 */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 250 fa */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 251 fb */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 252 fc */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 253 fd */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 254 fe */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
/* <20> 255 ff */ BOOST_CC_ALPHA|BOOST_CC_LOWER,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ISO 8859-1 character conversion table
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
const unsigned char iso8859_1_char_conversion[] =
|
||||
{
|
||||
/* NUL 0 0 */ '\0',
|
||||
/* SOH 1 1 */ '\0',
|
||||
/* STX 2 2 */ '\0',
|
||||
/* ETX 3 3 */ '\0',
|
||||
/* EOT 4 4 */ '\0',
|
||||
/* ENQ 5 5 */ '\0',
|
||||
/* ACK 6 6 */ '\0',
|
||||
/* BEL 7 7 */ '\0',
|
||||
/* BS 8 8 */ '\0',
|
||||
/* HT 9 9 */ '\0',
|
||||
/* NL 10 a */ '\0',
|
||||
/* VT 11 b */ '\0',
|
||||
/* NP 12 c */ '\0',
|
||||
/* CR 13 d */ '\0',
|
||||
/* SO 14 e */ '\0',
|
||||
/* SI 15 f */ '\0',
|
||||
/* DLE 16 10 */ '\0',
|
||||
/* DC1 17 11 */ '\0',
|
||||
/* DC2 18 12 */ '\0',
|
||||
/* DC3 19 13 */ '\0',
|
||||
/* DC4 20 14 */ '\0',
|
||||
/* NAK 21 15 */ '\0',
|
||||
/* SYN 22 16 */ '\0',
|
||||
/* ETB 23 17 */ '\0',
|
||||
/* CAN 24 18 */ '\0',
|
||||
/* EM 25 19 */ '\0',
|
||||
/* SUB 26 1a */ '\0',
|
||||
/* ESC 27 1b */ '\0',
|
||||
/* FS 28 1c */ '\0',
|
||||
/* GS 29 1d */ '\0',
|
||||
/* RS 30 1e */ '\0',
|
||||
/* US 31 1f */ '\0',
|
||||
/* SP 32 20 */ '\0',
|
||||
/* ! 33 21 */ '\0',
|
||||
/* " 34 22 */ '\0',
|
||||
/* # 35 23 */ '\0',
|
||||
/* $ 36 24 */ '\0',
|
||||
/* % 37 25 */ '\0',
|
||||
/* & 38 26 */ '\0',
|
||||
/* ' 39 27 */ '\0',
|
||||
/* ( 40 28 */ '\0',
|
||||
/* ) 41 29 */ '\0',
|
||||
/* * 42 2a */ '\0',
|
||||
/* + 43 2b */ '\0',
|
||||
/* , 44 2c */ '\0',
|
||||
/* - 45 2d */ '\0',
|
||||
/* . 46 2e */ '\0',
|
||||
/* / 47 2f */ '\0',
|
||||
/* 0 48 30 */ '\0',
|
||||
/* 1 49 31 */ '\0',
|
||||
/* 2 50 32 */ '\0',
|
||||
/* 3 51 33 */ '\0',
|
||||
/* 4 52 34 */ '\0',
|
||||
/* 5 53 35 */ '\0',
|
||||
/* 6 54 36 */ '\0',
|
||||
/* 7 55 37 */ '\0',
|
||||
/* 8 56 38 */ '\0',
|
||||
/* 9 57 39 */ '\0',
|
||||
/* : 58 3a */ '\0',
|
||||
/* ; 59 3b */ '\0',
|
||||
/* < 60 3c */ '\0',
|
||||
/* = 61 3d */ '\0',
|
||||
/* > 62 3e */ '\0',
|
||||
/* ? 63 3f */ '\0',
|
||||
/* @ 64 40 */ '\0',
|
||||
/* A 65 41 */ 'a',
|
||||
/* B 66 42 */ 'b',
|
||||
/* C 67 43 */ 'c',
|
||||
/* D 68 44 */ 'd',
|
||||
/* E 69 45 */ 'e',
|
||||
/* F 70 46 */ 'f',
|
||||
/* G 71 47 */ 'g',
|
||||
/* H 72 48 */ 'h',
|
||||
/* I 73 49 */ 'i',
|
||||
/* J 74 4a */ 'j',
|
||||
/* K 75 4b */ 'k',
|
||||
/* L 76 4c */ 'l',
|
||||
/* M 77 4d */ 'm',
|
||||
/* N 78 4e */ 'n',
|
||||
/* O 79 4f */ 'o',
|
||||
/* P 80 50 */ 'p',
|
||||
/* Q 81 51 */ 'q',
|
||||
/* R 82 52 */ 'r',
|
||||
/* S 83 53 */ 's',
|
||||
/* T 84 54 */ 't',
|
||||
/* U 85 55 */ 'u',
|
||||
/* V 86 56 */ 'v',
|
||||
/* W 87 57 */ 'w',
|
||||
/* X 88 58 */ 'x',
|
||||
/* Y 89 59 */ 'y',
|
||||
/* Z 90 5a */ 'z',
|
||||
/* [ 91 5b */ '\0',
|
||||
/* \ 92 5c */ '\0',
|
||||
/* ] 93 5d */ '\0',
|
||||
/* ^ 94 5e */ '\0',
|
||||
/* _ 95 5f */ '\0',
|
||||
/* ` 96 60 */ '\0',
|
||||
/* a 97 61 */ 'A',
|
||||
/* b 98 62 */ 'B',
|
||||
/* c 99 63 */ 'C',
|
||||
/* d 100 64 */ 'D',
|
||||
/* e 101 65 */ 'E',
|
||||
/* f 102 66 */ 'F',
|
||||
/* g 103 67 */ 'G',
|
||||
/* h 104 68 */ 'H',
|
||||
/* i 105 69 */ 'I',
|
||||
/* j 106 6a */ 'J',
|
||||
/* k 107 6b */ 'K',
|
||||
/* l 108 6c */ 'L',
|
||||
/* m 109 6d */ 'M',
|
||||
/* n 110 6e */ 'N',
|
||||
/* o 111 6f */ 'O',
|
||||
/* p 112 70 */ 'P',
|
||||
/* q 113 71 */ 'Q',
|
||||
/* r 114 72 */ 'R',
|
||||
/* s 115 73 */ 'S',
|
||||
/* t 116 74 */ 'T',
|
||||
/* u 117 75 */ 'U',
|
||||
/* v 118 76 */ 'V',
|
||||
/* w 119 77 */ 'W',
|
||||
/* x 120 78 */ 'X',
|
||||
/* y 121 79 */ 'Y',
|
||||
/* z 122 7a */ 'Z',
|
||||
/* { 123 7b */ '\0',
|
||||
/* | 124 7c */ '\0',
|
||||
/* } 125 7d */ '\0',
|
||||
/* ~ 126 7e */ '\0',
|
||||
/* DEL 127 7f */ '\0',
|
||||
/* -- 128 80 */ '\0',
|
||||
/* -- 129 81 */ '\0',
|
||||
/* -- 130 82 */ '\0',
|
||||
/* -- 131 83 */ '\0',
|
||||
/* -- 132 84 */ '\0',
|
||||
/* -- 133 85 */ '\0',
|
||||
/* -- 134 86 */ '\0',
|
||||
/* -- 135 87 */ '\0',
|
||||
/* -- 136 88 */ '\0',
|
||||
/* -- 137 89 */ '\0',
|
||||
/* -- 138 8a */ '\0',
|
||||
/* -- 139 8b */ '\0',
|
||||
/* -- 140 8c */ '\0',
|
||||
/* -- 141 8d */ '\0',
|
||||
/* -- 142 8e */ '\0',
|
||||
/* -- 143 8f */ '\0',
|
||||
/* -- 144 90 */ '\0',
|
||||
/* -- 145 91 */ '\0',
|
||||
/* -- 146 92 */ '\0',
|
||||
/* -- 147 93 */ '\0',
|
||||
/* -- 148 94 */ '\0',
|
||||
/* -- 149 95 */ '\0',
|
||||
/* -- 150 96 */ '\0',
|
||||
/* -- 151 97 */ '\0',
|
||||
/* -- 152 98 */ '\0',
|
||||
/* -- 153 99 */ '\0',
|
||||
/* -- 154 9a */ '\0',
|
||||
/* -- 155 9b */ '\0',
|
||||
/* -- 156 9c */ '\0',
|
||||
/* -- 157 9d */ '\0',
|
||||
/* -- 158 9e */ '\0',
|
||||
/* -- 159 9f */ '\0',
|
||||
/* 160 a0 */ '\0',
|
||||
/* <20> 161 a1 */ '\0',
|
||||
/* <20> 162 a2 */ '\0',
|
||||
/* <20> 163 a3 */ '\0',
|
||||
/* <20> 164 a4 */ '\0',
|
||||
/* <20> 165 a5 */ '\0',
|
||||
/* <20> 166 a6 */ '\0',
|
||||
/* <20> 167 a7 */ '\0',
|
||||
/* <20> 168 a8 */ '\0',
|
||||
/* <20> 169 a9 */ '\0',
|
||||
/* <20> 170 aa */ '\0',
|
||||
/* <20> 171 ab */ '\0',
|
||||
/* <20> 172 ac */ '\0',
|
||||
/* <20> 173 ad */ '\0',
|
||||
/* <20> 174 ae */ '\0',
|
||||
/* <20> 175 af */ '\0',
|
||||
/* <20> 176 b0 */ '\0',
|
||||
/* <20> 177 b1 */ '\0',
|
||||
/* <20> 178 b2 */ '\0',
|
||||
/* <20> 179 b3 */ '\0',
|
||||
/* <20> 180 b4 */ '\0',
|
||||
/* <20> 181 b5 */ '\0',
|
||||
/* <20> 182 b6 */ '\0',
|
||||
/* <20> 183 b7 */ '\0',
|
||||
/* <20> 184 b8 */ '\0',
|
||||
/* <20> 185 b9 */ '\0',
|
||||
/* <20> 186 ba */ '\0',
|
||||
/* <20> 187 bb */ '\0',
|
||||
/* <20> 188 bc */ '\0',
|
||||
/* <20> 189 bd */ '\0',
|
||||
/* <20> 190 be */ '\0',
|
||||
/* <20> 191 bf */ '\0',
|
||||
/* <20> 192 c0 */ 0xe0,
|
||||
/* <20> 193 c1 */ 0xe1,
|
||||
/* <20> 194 c2 */ 0xe2,
|
||||
/* <20> 195 c3 */ 0xe3,
|
||||
/* <20> 196 c4 */ 0xe4,
|
||||
/* <20> 197 c5 */ 0xe5,
|
||||
/* <20> 198 c6 */ 0xe6,
|
||||
/* <20> 199 c7 */ 0xe7,
|
||||
/* <20> 200 c8 */ 0xe8,
|
||||
/* <20> 201 c9 */ 0xe9,
|
||||
/* <20> 202 ca */ 0xea,
|
||||
/* <20> 203 cb */ 0xeb,
|
||||
/* <20> 204 cc */ 0xec,
|
||||
/* <20> 205 cd */ 0xed,
|
||||
/* <20> 206 ce */ 0xee,
|
||||
/* <20> 207 cf */ 0xef,
|
||||
/* <20> 208 d0 */ 0xf0,
|
||||
/* <20> 209 d1 */ 0xf1,
|
||||
/* <20> 210 d2 */ 0xf2,
|
||||
/* <20> 211 d3 */ 0xf3,
|
||||
/* <20> 212 d4 */ 0xf4,
|
||||
/* <20> 213 d5 */ 0xf5,
|
||||
/* <20> 214 d6 */ 0xf6,
|
||||
/* <20> 215 d7 */ '\0',
|
||||
/* <20> 216 d8 */ 0xf8,
|
||||
/* <20> 217 d9 */ 0xf9,
|
||||
/* <20> 218 da */ 0xfa,
|
||||
/* <20> 219 db */ 0xfb,
|
||||
/* <20> 220 dc */ 0xfc,
|
||||
/* <20> 221 dd */ 0xfd,
|
||||
/* <20> 222 de */ 0xfe,
|
||||
/* <20> 223 df */ '\0',
|
||||
/* <20> 224 e0 */ 0xc0,
|
||||
/* <20> 225 e1 */ 0xc1,
|
||||
/* <20> 226 e2 */ 0xc2,
|
||||
/* <20> 227 e3 */ 0xc3,
|
||||
/* <20> 228 e4 */ 0xc4,
|
||||
/* <20> 229 e5 */ 0xc5,
|
||||
/* <20> 230 e6 */ 0xc6,
|
||||
/* <20> 231 e7 */ 0xc7,
|
||||
/* <20> 232 e8 */ 0xc8,
|
||||
/* <20> 233 e9 */ 0xc9,
|
||||
/* <20> 234 ea */ 0xca,
|
||||
/* <20> 235 eb */ 0xcb,
|
||||
/* <20> 236 ec */ 0xcc,
|
||||
/* <20> 237 ed */ 0xcd,
|
||||
/* <20> 238 ee */ 0xce,
|
||||
/* <20> 239 ef */ 0xcf,
|
||||
/* <20> 240 f0 */ 0xd0,
|
||||
/* <20> 241 f1 */ 0xd1,
|
||||
/* <20> 242 f2 */ 0xd2,
|
||||
/* <20> 243 f3 */ 0xd3,
|
||||
/* <20> 244 f4 */ 0xd4,
|
||||
/* <20> 245 f5 */ 0xd5,
|
||||
/* <20> 246 f6 */ 0xd6,
|
||||
/* <20> 247 f7 */ '\0',
|
||||
/* <20> 248 f8 */ 0xd8,
|
||||
/* <20> 249 f9 */ 0xd9,
|
||||
/* <20> 250 fa */ 0xda,
|
||||
/* <20> 251 fb */ 0xdb,
|
||||
/* <20> 252 fc */ 0xdc,
|
||||
/* <20> 253 fd */ 0xdd,
|
||||
/* <20> 254 fe */ 0xde,
|
||||
/* <20> 255 ff */ '\0',
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test characters for specified conditions (using iso8859-1)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct iso8859_1
|
||||
{
|
||||
typedef unsigned char char_type;
|
||||
|
||||
static bool
|
||||
is_ascii(int ch)
|
||||
{
|
||||
return (0 == (ch & ~0x7f)) ? true : false;
|
||||
}
|
||||
|
||||
static int
|
||||
isalnum(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_ALPHA)
|
||||
|| (iso8859_1_char_types[ch] & BOOST_CC_DIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
isalpha(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_ALPHA);
|
||||
}
|
||||
|
||||
static int
|
||||
isdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_DIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
isxdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_XDIGIT);
|
||||
}
|
||||
|
||||
static int
|
||||
iscntrl(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_CTRL);
|
||||
}
|
||||
|
||||
static int
|
||||
isgraph(int ch)
|
||||
{
|
||||
return ('\x21' <= ch && ch <= '\x7e') || ('\xa1' <= ch && ch <= '\xff');
|
||||
}
|
||||
|
||||
static int
|
||||
islower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_LOWER);
|
||||
}
|
||||
|
||||
static int
|
||||
isprint(int ch)
|
||||
{
|
||||
return ('\x20' <= ch && ch <= '\x7e') || ('\xa0' <= ch && ch <= '\xff');
|
||||
}
|
||||
|
||||
static int
|
||||
ispunct(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_PUNCT);
|
||||
}
|
||||
|
||||
static int
|
||||
isspace(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_SPACE);
|
||||
}
|
||||
|
||||
static int
|
||||
isblank BOOST_PREVENT_MACRO_SUBSTITUTION (int ch)
|
||||
{
|
||||
return ('\x09' == ch || '\x20' == ch || '\xa0' == ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(0 == (ch & ~UCHAR_MAX));
|
||||
return (iso8859_1_char_types[ch] & BOOST_CC_UPPER);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Simple character conversions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int
|
||||
tolower(int ch)
|
||||
{
|
||||
return isupper(ch) && '\0' != iso8859_1_char_conversion[ch] ?
|
||||
iso8859_1_char_conversion[ch] : ch;
|
||||
}
|
||||
|
||||
static int
|
||||
toupper(int ch)
|
||||
{
|
||||
return islower(ch) && '\0' != iso8859_1_char_conversion[ch] ?
|
||||
iso8859_1_char_conversion[ch] : ch;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// undefine macros
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#undef BOOST_CC_DIGIT
|
||||
#undef BOOST_CC_XDIGIT
|
||||
#undef BOOST_CC_ALPHA
|
||||
#undef BOOST_CC_CTRL
|
||||
#undef BOOST_CC_LOWER
|
||||
#undef BOOST_CC_UPPER
|
||||
#undef BOOST_CC_PUNCT
|
||||
#undef BOOST_CC_SPACE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_STANDARD_APR_26_2006_1106PM)
|
||||
#define BOOST_SPIRIT_STANDARD_APR_26_2006_1106PM
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace boost { namespace spirit { namespace char_class
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test characters for specified conditions (using std functions)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct standard
|
||||
{
|
||||
typedef char char_type;
|
||||
|
||||
static bool
|
||||
is_ascii(int ch)
|
||||
{
|
||||
return (0 == (ch & ~0x7f)) ? true : false;
|
||||
}
|
||||
|
||||
static int
|
||||
isalnum(int ch)
|
||||
{
|
||||
return std::isalnum(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isalpha(int ch)
|
||||
{
|
||||
return std::isalpha(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isdigit(int ch)
|
||||
{
|
||||
return std::isdigit(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isxdigit(int ch)
|
||||
{
|
||||
return std::isxdigit(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
iscntrl(int ch)
|
||||
{
|
||||
return std::iscntrl(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isgraph(int ch)
|
||||
{
|
||||
return std::isgraph(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
islower(int ch)
|
||||
{
|
||||
return std::islower(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isprint(int ch)
|
||||
{
|
||||
return std::isprint(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
ispunct(int ch)
|
||||
{
|
||||
return std::ispunct(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isspace(int ch)
|
||||
{
|
||||
return std::isspace(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
isblank BOOST_PREVENT_MACRO_SUBSTITUTION (int ch)
|
||||
{
|
||||
return (ch == ' ' || ch == '\t');
|
||||
}
|
||||
|
||||
static int
|
||||
isupper(int ch)
|
||||
{
|
||||
return std::isupper(ch);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Simple character conversions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static int
|
||||
tolower(int ch)
|
||||
{
|
||||
return std::tolower(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
toupper(int ch)
|
||||
{
|
||||
return std::toupper(ch);
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_STANDARD_WIDE_NOV_10_2006_0913AM)
|
||||
#define BOOST_SPIRIT_STANDARD_WIDE_NOV_10_2006_0913AM
|
||||
|
||||
#include <cwctype>
|
||||
|
||||
namespace boost { namespace spirit { namespace char_class
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test characters for specified conditions (using std wchar_t functions)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct standard_wide
|
||||
{
|
||||
typedef wchar_t char_type;
|
||||
|
||||
template <typename Char>
|
||||
static typename std::char_traits<Char>::int_type
|
||||
to_int_type(Char ch)
|
||||
{
|
||||
return std::char_traits<Char>::to_int_type(ch);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
static Char
|
||||
to_char_type(typename std::char_traits<Char>::int_type ch)
|
||||
{
|
||||
return std::char_traits<Char>::to_char_type(ch);
|
||||
}
|
||||
|
||||
static bool
|
||||
isalnum(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswalnum(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isalpha(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswalpha(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
iscntrl(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswcntrl(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isdigit(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswdigit(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isgraph(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswgraph(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
islower(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswlower(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isprint(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswprint(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ispunct(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswpunct(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isspace(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswspace(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isupper(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswupper(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isxdigit(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return iswxdigit(to_int_type(ch)) ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
isblank BOOST_PREVENT_MACRO_SUBSTITUTION (wchar_t ch)
|
||||
{
|
||||
return (ch == L' ' || ch == L'\t');
|
||||
}
|
||||
|
||||
static wchar_t
|
||||
tolower(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return isupper(ch) ?
|
||||
to_char_type<wchar_t>(towlower(to_int_type(ch))) : ch;
|
||||
}
|
||||
|
||||
static wchar_t
|
||||
toupper(wchar_t ch)
|
||||
{
|
||||
using namespace std;
|
||||
return islower(ch) ?
|
||||
to_char_type<wchar_t>(towupper(to_int_type(ch))) : ch;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
291
libraries/include/boost/spirit/home/support/component.hpp
Normal file
291
libraries/include/boost/spirit/home/support/component.hpp
Normal file
@@ -0,0 +1,291 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_COMPONENT_JAN_14_2007_1102AM)
|
||||
#define BOOST_SPIRIT_COMPONENT_JAN_14_2007_1102AM
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// component generalizes a spirit component. A component can be a parser,
|
||||
// a primitive-parser, a composite-parser, a generator, etc.
|
||||
// A component has:
|
||||
//
|
||||
// 1) Domain: The world it operates on (purely a type e.g. qi::domain).
|
||||
// 2) Director: Its Director (purely a type e.g. qi::sequence)
|
||||
// 3) Elements: For composites, a tuple of components
|
||||
// For primitives, a tuple of arbitrary information
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Director, typename Elements>
|
||||
struct component
|
||||
{
|
||||
typedef Domain domain;
|
||||
typedef Director director;
|
||||
typedef Elements elements_type;
|
||||
|
||||
component()
|
||||
{
|
||||
}
|
||||
|
||||
component(Elements const& elements)
|
||||
: elements(elements)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Elements2>
|
||||
component(component<Domain, Director, Elements2> const& other)
|
||||
: elements(other.elements)
|
||||
{
|
||||
// allow copy from components with compatible elements
|
||||
}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Utils for extracting child components
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Component>
|
||||
struct subject
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 0>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component>
|
||||
struct left
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 0>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component>
|
||||
struct right
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 1>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component>
|
||||
struct argument1
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 1>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component>
|
||||
struct argument2
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 2>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template<typename Component, int N>
|
||||
struct arg_c
|
||||
: fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, N>
|
||||
{};
|
||||
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, 0>::type
|
||||
inline subject(Component const& c)
|
||||
{
|
||||
return fusion::at_c<0>(c.elements);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, 0>::type
|
||||
inline left(Component const& c)
|
||||
{
|
||||
return fusion::at_c<0>(c.elements);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, 1>::type
|
||||
inline right(Component const& c)
|
||||
{
|
||||
return fusion::at_c<1>(c.elements);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, 1>::type
|
||||
inline argument1(Component const& c)
|
||||
{
|
||||
return fusion::at_c<1>(c.elements);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, 2>::type
|
||||
inline argument2(Component const& c)
|
||||
{
|
||||
return fusion::at_c<2>(c.elements);
|
||||
}
|
||||
|
||||
template <int N, typename Component>
|
||||
typename fusion::result_of::at_c<
|
||||
typename Component::elements_type const, N>::type
|
||||
inline arg_c(Component const& c)
|
||||
{
|
||||
return fusion::at_c<N>(c.elements);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test if Expr conforms to the grammar of Domain. If Expr is already
|
||||
// a component, return mpl::true_.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace traits
|
||||
{
|
||||
template <typename Domain, typename Expr>
|
||||
struct is_component
|
||||
: proto::matches<
|
||||
typename proto::result_of::as_expr<Expr>::type
|
||||
, typename meta_grammar::grammar<Domain>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Domain, typename Director, typename Elements>
|
||||
struct is_component<Domain, component<Domain, Director, Elements> > :
|
||||
mpl::true_
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Convert an arbitrary expression to a spirit component. There's
|
||||
// a metafunction in namespace result_of and a function in main
|
||||
// spirit namespace. If Expr is already a component, return it as-is.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace result_of
|
||||
{
|
||||
template <
|
||||
typename Domain, typename Expr, typename State = unused_type,
|
||||
typename Visitor = unused_type
|
||||
>
|
||||
struct as_component
|
||||
{
|
||||
typedef typename meta_grammar::grammar<Domain>::type grammar;
|
||||
typedef typename proto::result_of::as_expr<Expr>::type proto_xpr;
|
||||
typedef typename grammar::template impl<proto_xpr, State, Visitor> callable;
|
||||
typedef typename callable::result_type type;
|
||||
};
|
||||
|
||||
// special case for arrays
|
||||
template <
|
||||
typename Domain, typename T, int N,
|
||||
typename State, typename Visitor>
|
||||
struct as_component<Domain, T[N], State, Visitor>
|
||||
{
|
||||
typedef typename meta_grammar::grammar<Domain>::type grammar;
|
||||
typedef typename proto::result_of::as_expr<T const*>::type proto_xpr;
|
||||
typedef typename grammar::template impl<proto_xpr, State, Visitor> callable;
|
||||
typedef typename callable::result_type type;
|
||||
};
|
||||
|
||||
// special case for components
|
||||
template <typename Domain, typename Director, typename Elements>
|
||||
struct as_component<Domain, component<Domain, Director, Elements> > :
|
||||
mpl::identity<component<Domain, Director, Elements> >
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
T &decay(T &t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T, int N>
|
||||
T *decay(T (&t)[N])
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Domain, typename Expr>
|
||||
inline typename result_of::as_component<Domain, Expr>::type
|
||||
as_component(Domain, Expr const& xpr)
|
||||
{
|
||||
typedef typename result_of::as_component<Domain, Expr>::callable callable;
|
||||
return callable()(proto::as_expr(detail::decay(xpr)), unused_type(), unused_type());
|
||||
}
|
||||
|
||||
template <typename Domain, typename Expr, typename State, typename Visitor>
|
||||
inline typename result_of::as_component<Domain, Expr>::type
|
||||
as_component(Domain, Expr const& xpr, State const& state, Visitor& visitor)
|
||||
{
|
||||
typedef typename result_of::as_component<Domain, Expr, State, Visitor>::callable callable;
|
||||
return callable()(proto::as_expr(detail::decay(xpr)), state, visitor);
|
||||
}
|
||||
|
||||
template <typename Domain, typename Director, typename Elements>
|
||||
inline component<Domain, Director, Elements> const&
|
||||
as_component(Domain, component<Domain, Director, Elements> const& component)
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Create a component. This is a customization point. Components are
|
||||
// not created directly; they are created through make_component.
|
||||
// Clients may customize this to direct the creation of a component.
|
||||
//
|
||||
// The extra Modifier template parameter may be used to direct the
|
||||
// creation of the component. This is the Visitor parameter in Proto
|
||||
// transforms.
|
||||
//
|
||||
// (see also: modifier.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace traits
|
||||
{
|
||||
template <
|
||||
typename Domain, typename Director
|
||||
, typename Elements, typename Modifier, typename Enable = void>
|
||||
struct make_component
|
||||
: mpl::identity<component<Domain, Director, Elements> >
|
||||
{
|
||||
static component<Domain, Director, Elements>
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return component<Domain, Director, Elements>(elements);
|
||||
}
|
||||
};
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2008 Joel de Guzman
|
||||
Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ACTION_DISPATCH_APR_18_2008_0720AM)
|
||||
#define BOOST_SPIRIT_ACTION_DISPATCH_APR_18_2008_0720AM
|
||||
|
||||
#include <boost/spirit/home/support/detail/values.hpp>
|
||||
#include <boost/spirit/home/phoenix/core/actor.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
// general handler for everything not explicitly specialized below
|
||||
template <typename F, typename Attribute, typename Context, bool IsSequence>
|
||||
bool action_dispatch(F const& f, Attribute& attr, Context& context
|
||||
, mpl::bool_<IsSequence>)
|
||||
{
|
||||
bool pass = true;
|
||||
f(attr, context, pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
// handler for phoenix actors
|
||||
|
||||
// If the component this action has to be invoked for is a sequence, we
|
||||
// wrap any non-fusion sequence into a fusion sequence (done by pass_value)
|
||||
// and pass through any fusion sequence.
|
||||
template <typename Eval, typename Attribute, typename Context>
|
||||
bool action_dispatch(phoenix::actor<Eval> const& f
|
||||
, Attribute& attr, Context& context, mpl::true_)
|
||||
{
|
||||
bool pass = true;
|
||||
f (pass_value<Attribute>::call(attr), context, pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
// If this action has to be invoked for anything but a sequence, we always
|
||||
// need to wrap the attribute into a fusion sequence, because the attribute
|
||||
// has to be treated as being a single value in any case (even if it
|
||||
// actually already is a fusion sequence on its own).
|
||||
template <typename Eval, typename Attribute, typename Context>
|
||||
bool action_dispatch(phoenix::actor<Eval> const& f
|
||||
, Attribute& attr, Context& context, mpl::false_)
|
||||
{
|
||||
bool pass = true;
|
||||
fusion::vector<Attribute&> wrapped_attr(attr);
|
||||
f (wrapped_attr, context, pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
// specializations for plain function pointers taking a different number of
|
||||
// arguments
|
||||
template <typename RT, typename A0, typename A1, typename A2
|
||||
, typename Attribute, typename Context, bool IsSequence>
|
||||
bool action_dispatch(RT(*f)(A0, A1, A2)
|
||||
, Attribute& attr, Context& context, mpl::bool_<IsSequence>)
|
||||
{
|
||||
bool pass = true;
|
||||
f(attr, context, pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
template <typename RT, typename A0, typename A1
|
||||
, typename Attribute, typename Context, bool IsSequence>
|
||||
bool action_dispatch(RT(*f)(A0, A1)
|
||||
, Attribute& attr, Context& context, mpl::bool_<IsSequence>)
|
||||
{
|
||||
f(attr, context);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename RT, typename A0
|
||||
, typename Attribute, typename Context, bool IsSequence>
|
||||
bool action_dispatch(RT(*f)(A0)
|
||||
, Attribute& attr, Context&, mpl::bool_<IsSequence>)
|
||||
{
|
||||
f(attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename RT
|
||||
, typename Attribute, typename Context, bool IsSequence>
|
||||
bool action_dispatch(RT(*f)()
|
||||
, Attribute&, Context&, mpl::bool_<IsSequence>)
|
||||
{
|
||||
f();
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
186
libraries/include/boost/spirit/home/support/detail/container.hpp
Normal file
186
libraries/include/boost/spirit/home/support/detail/container.hpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_CONTAINER_FEB_06_2007_1001AM)
|
||||
#define BOOST_SPIRIT_CONTAINER_FEB_06_2007_1001AM
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
|
||||
|
||||
namespace boost { namespace spirit { namespace container
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This file contains some container utils for stl containers. The
|
||||
// utilities provided also accept spirit's unused_type; all no-ops.
|
||||
// Compiler optimization will easily strip these away.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Container>
|
||||
struct value
|
||||
{
|
||||
typedef typename Container::value_type type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct value<unused_type>
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct value<unused_type const>
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
struct iterator
|
||||
{
|
||||
typedef typename Container::iterator type;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
struct iterator<Container const>
|
||||
{
|
||||
typedef typename Container::const_iterator type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator<unused_type>
|
||||
{
|
||||
typedef unused_type const* type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator<unused_type const>
|
||||
{
|
||||
typedef unused_type const* type;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename T>
|
||||
inline void push_back(Container& c, T const& val)
|
||||
{
|
||||
c.push_back(val);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline void push_back(Container&, unused_type)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void push_back(unused_type, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
inline void push_back(unused_type, unused_type)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container>
|
||||
inline typename result_of::iterator<Container>::type
|
||||
begin(Container& c)
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline typename result_of::iterator<Container const>::type
|
||||
begin(Container const& c)
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
inline unused_type const*
|
||||
begin(unused_type)
|
||||
{
|
||||
return &unused;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline typename result_of::iterator<Container>::type
|
||||
end(Container& c)
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline typename result_of::iterator<Container const>::type
|
||||
end(Container const& c)
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
inline unused_type const*
|
||||
end(unused_type)
|
||||
{
|
||||
return &unused;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
inline typename boost::detail::iterator_traits<Iterator>::value_type
|
||||
deref(Iterator& it)
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
|
||||
inline unused_type
|
||||
deref(unused_type*)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
|
||||
inline unused_type
|
||||
deref(unused_type const*)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
inline Iterator
|
||||
next(Iterator& it)
|
||||
{
|
||||
return ++it;
|
||||
}
|
||||
|
||||
inline unused_type
|
||||
next(unused_type*)
|
||||
{
|
||||
return &unused;
|
||||
}
|
||||
|
||||
inline unused_type
|
||||
next(unused_type const*)
|
||||
{
|
||||
return &unused;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
inline bool
|
||||
compare(Iterator const& it1, Iterator const& it2)
|
||||
{
|
||||
return it1 == it2;
|
||||
}
|
||||
|
||||
inline bool
|
||||
compare(unused_type*, unused_type*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
425
libraries/include/boost/spirit/home/support/detail/hold_any.hpp
Normal file
425
libraries/include/boost/spirit/home/support/detail/hold_any.hpp
Normal file
@@ -0,0 +1,425 @@
|
||||
// Copyright (c) 2008-2009 Hartmut Kaiser
|
||||
// Copyright (c) Christopher Diggins 2005
|
||||
// Copyright (c) Pablo Aguilar 2005
|
||||
// Copyright (c) Kevlin Henney 2001
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// The class boost::spirit::hold_any is built based on the any class
|
||||
// published here: http://www.codeproject.com/cpp/dynamic_typing.asp. It adds
|
||||
// support for std streaming operator<<() and operator>>().
|
||||
|
||||
#if !defined(BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM)
|
||||
#define BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <algorithm>
|
||||
#include <iosfwd>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4100) // 'x': unreferenced formal parameter
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
struct bad_any_cast
|
||||
: std::bad_cast
|
||||
{
|
||||
bad_any_cast(std::type_info const& src, std::type_info const& dest)
|
||||
: from(src.name()), to(dest.name())
|
||||
{}
|
||||
|
||||
virtual const char* what() const throw() { return "bad any cast"; }
|
||||
|
||||
const char* from;
|
||||
const char* to;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// function pointer table
|
||||
struct fxn_ptr_table
|
||||
{
|
||||
std::type_info const& (*get_type)();
|
||||
void (*static_delete)(void**);
|
||||
void (*destruct)(void**);
|
||||
void (*clone)(void* const*, void**);
|
||||
void (*move)(void* const*, void**);
|
||||
std::istream& (*stream_in)(std::istream&, void**);
|
||||
std::ostream& (*stream_out)(std::ostream&, void* const*);
|
||||
};
|
||||
|
||||
// static functions for small value-types
|
||||
template<typename Small>
|
||||
struct fxns;
|
||||
|
||||
template<>
|
||||
struct fxns<mpl::true_>
|
||||
{
|
||||
template<typename T>
|
||||
struct type
|
||||
{
|
||||
static std::type_info const& get_type()
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
static void static_delete(void** x)
|
||||
{
|
||||
reinterpret_cast<T*>(x)->~T();
|
||||
}
|
||||
static void destruct(void** x)
|
||||
{
|
||||
reinterpret_cast<T*>(x)->~T();
|
||||
}
|
||||
static void clone(void* const* src, void** dest)
|
||||
{
|
||||
new (dest) T(*reinterpret_cast<T const*>(src));
|
||||
}
|
||||
static void move(void* const* src, void** dest)
|
||||
{
|
||||
reinterpret_cast<T*>(dest)->~T();
|
||||
*reinterpret_cast<T*>(dest) =
|
||||
*reinterpret_cast<T const*>(src);
|
||||
}
|
||||
static std::istream& stream_in (std::istream& i, void** obj)
|
||||
{
|
||||
i >> *reinterpret_cast<T*>(obj);
|
||||
return i;
|
||||
}
|
||||
static std::ostream& stream_out(std::ostream& o, void* const* obj)
|
||||
{
|
||||
o << *reinterpret_cast<T const*>(obj);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// static functions for big value-types (bigger than a void*)
|
||||
template<>
|
||||
struct fxns<mpl::false_>
|
||||
{
|
||||
template<typename T>
|
||||
struct type
|
||||
{
|
||||
static std::type_info const& get_type()
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
static void static_delete(void** x)
|
||||
{
|
||||
// destruct and free memory
|
||||
delete (*reinterpret_cast<T**>(x));
|
||||
}
|
||||
static void destruct(void** x)
|
||||
{
|
||||
// destruct only, we'll reuse memory
|
||||
(*reinterpret_cast<T**>(x))->~T();
|
||||
}
|
||||
static void clone(void* const* src, void** dest)
|
||||
{
|
||||
*dest = new T(**reinterpret_cast<T* const*>(src));
|
||||
}
|
||||
static void move(void* const* src, void** dest)
|
||||
{
|
||||
(*reinterpret_cast<T**>(dest))->~T();
|
||||
**reinterpret_cast<T**>(dest) =
|
||||
**reinterpret_cast<T* const*>(src);
|
||||
}
|
||||
static std::istream& stream_in(std::istream& i, void** obj)
|
||||
{
|
||||
i >> **reinterpret_cast<T**>(obj);
|
||||
return i;
|
||||
}
|
||||
static std::ostream& stream_out(std::ostream& o, void* const* obj)
|
||||
{
|
||||
o << **reinterpret_cast<T* const*>(obj);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct get_table
|
||||
{
|
||||
typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
|
||||
|
||||
static fxn_ptr_table* get()
|
||||
{
|
||||
static fxn_ptr_table static_table =
|
||||
{
|
||||
fxns<is_small>::template type<T>::get_type,
|
||||
fxns<is_small>::template type<T>::static_delete,
|
||||
fxns<is_small>::template type<T>::destruct,
|
||||
fxns<is_small>::template type<T>::clone,
|
||||
fxns<is_small>::template type<T>::move,
|
||||
fxns<is_small>::template type<T>::stream_in,
|
||||
fxns<is_small>::template type<T>::stream_out
|
||||
};
|
||||
return &static_table;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct empty {};
|
||||
|
||||
inline std::istream&
|
||||
operator>> (std::istream& i, empty&)
|
||||
{
|
||||
// If this assertion fires you tried to insert from a std istream
|
||||
// into an empty hold_any instance. This simply can't work, because
|
||||
// there is no way to figure out what type to extract from the
|
||||
// stream.
|
||||
// The only way to make this work is to assign an arbitrary
|
||||
// value of the required type to the hold_any instance you want to
|
||||
// stream to. This assignment has to be executed before the actual
|
||||
// call to the operator>>().
|
||||
BOOST_ASSERT(false);
|
||||
return i;
|
||||
}
|
||||
|
||||
inline std::ostream&
|
||||
operator<< (std::ostream& o, empty const&)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class hold_any
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
template <typename T>
|
||||
hold_any(T const& x)
|
||||
: table(spirit::detail::get_table<T>::get()), object(0)
|
||||
{
|
||||
if (spirit::detail::get_table<T>::is_small::value)
|
||||
new (&object) T(x);
|
||||
else
|
||||
object = new T(x);
|
||||
}
|
||||
|
||||
hold_any()
|
||||
: table(spirit::detail::get_table<spirit::detail::empty>::get()),
|
||||
object(0)
|
||||
{
|
||||
}
|
||||
|
||||
hold_any(hold_any const& x)
|
||||
: table(spirit::detail::get_table<spirit::detail::empty>::get()),
|
||||
object(0)
|
||||
{
|
||||
assign(x);
|
||||
}
|
||||
|
||||
~hold_any()
|
||||
{
|
||||
table->static_delete(&object);
|
||||
}
|
||||
|
||||
// assignment
|
||||
hold_any& assign(hold_any const& x)
|
||||
{
|
||||
if (&x != this) {
|
||||
// are we copying between the same type?
|
||||
if (table == x.table) {
|
||||
// if so, we can avoid reallocation
|
||||
table->move(&x.object, &object);
|
||||
}
|
||||
else {
|
||||
reset();
|
||||
x.table->clone(&x.object, &object);
|
||||
table = x.table;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
hold_any& assign(T const& x)
|
||||
{
|
||||
// are we copying between the same type?
|
||||
spirit::detail::fxn_ptr_table* x_table =
|
||||
spirit::detail::get_table<T>::get();
|
||||
if (table == x_table) {
|
||||
// if so, we can avoid deallocating and re-use memory
|
||||
table->destruct(&object); // first destruct the old content
|
||||
if (spirit::detail::get_table<T>::is_small::value) {
|
||||
// create copy on-top of object pointer itself
|
||||
new (&object) T(x);
|
||||
}
|
||||
else {
|
||||
// create copy on-top of old version
|
||||
new (object) T(x);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (spirit::detail::get_table<T>::is_small::value) {
|
||||
// create copy on-top of object pointer itself
|
||||
table->destruct(&object); // first destruct the old content
|
||||
new (&object) T(x);
|
||||
}
|
||||
else {
|
||||
reset(); // first delete the old content
|
||||
object = new T(x);
|
||||
}
|
||||
table = x_table; // update table pointer
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// assignment operator
|
||||
template <typename T>
|
||||
hold_any& operator=(T const& x)
|
||||
{
|
||||
return assign(x);
|
||||
}
|
||||
|
||||
// utility functions
|
||||
hold_any& swap(hold_any& x)
|
||||
{
|
||||
std::swap(table, x.table);
|
||||
std::swap(object, x.object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::type_info const& type() const
|
||||
{
|
||||
return table->get_type();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T const& cast() const
|
||||
{
|
||||
if (type() != typeid(T))
|
||||
throw bad_any_cast(type(), typeid(T));
|
||||
|
||||
return spirit::detail::get_table<T>::is_small::value ?
|
||||
*reinterpret_cast<T const*>(&object) :
|
||||
*reinterpret_cast<T const*>(object);
|
||||
}
|
||||
|
||||
// implicit casting is disabled by default for compatibility with boost::any
|
||||
#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
|
||||
// automatic casting operator
|
||||
template <typename T>
|
||||
operator T const& () const { return cast<T>(); }
|
||||
#endif // implicit casting
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return table == spirit::detail::get_table<spirit::detail::empty>::get();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
table->static_delete(&object);
|
||||
table = spirit::detail::get_table<spirit::detail::empty>::get();
|
||||
object = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// these functions have been added in the assumption that the embedded
|
||||
// type has a corresponding operator defined, which is completely safe
|
||||
// because spirit::hold_any is used only in contexts where these operators
|
||||
// do exist
|
||||
friend std::istream& operator>> (std::istream& i, hold_any& obj)
|
||||
{
|
||||
return obj.table->stream_in(i, &obj.object);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<< (std::ostream& o, hold_any const& obj)
|
||||
{
|
||||
return obj.table->stream_out(o, &obj.object);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
private: // types
|
||||
template<typename T>
|
||||
friend T* any_cast(hold_any *);
|
||||
#else
|
||||
public: // types (public so any_cast can be non-friend)
|
||||
#endif
|
||||
// fields
|
||||
spirit::detail::fxn_ptr_table* table;
|
||||
void* object;
|
||||
};
|
||||
|
||||
// boost::any-like casting
|
||||
template <typename T>
|
||||
inline T* any_cast (hold_any* operand)
|
||||
{
|
||||
if (operand && operand->type() == typeid(T)) {
|
||||
return spirit::detail::get_table<T>::is_small::value ?
|
||||
reinterpret_cast<T*>(&operand->object) :
|
||||
reinterpret_cast<T*>(operand->object);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T const* any_cast(hold_any const* operand)
|
||||
{
|
||||
return any_cast<T>(const_cast<hold_any*>(operand));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T any_cast(hold_any& operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// If 'nonref' is still reference type, it means the user has not
|
||||
// specialized 'remove_reference'.
|
||||
|
||||
// Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
|
||||
// to generate specialization of remove_reference for your class
|
||||
// See type traits library documentation for details
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
nonref* result = any_cast<nonref>(&operand);
|
||||
if(!result)
|
||||
boost::throw_exception(bad_any_cast(operand.type(), typeid(T)));
|
||||
return *result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T const& any_cast(hold_any const& operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// The comment in the above version of 'any_cast' explains when this
|
||||
// assert is fired and what to do.
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
return any_cast<nonref const&>(const_cast<hold_any &>(operand));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}} // namespace boost::spirit
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
// boost/integer/cover_operators.hpp ----------------------------------------//
|
||||
|
||||
// (C) Copyright Darin Adler 2000
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_INTEGER_COVER_OPERATORS_HPP
|
||||
#define BOOST_INTEGER_COVER_OPERATORS_HPP
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace integer
|
||||
{
|
||||
|
||||
// A class that adds integer operators to an integer cover class
|
||||
|
||||
template <typename T, typename IntegerType>
|
||||
class cover_operators : boost::operators<T>
|
||||
{
|
||||
// The other operations take advantage of the type conversion that's
|
||||
// built into unary +.
|
||||
|
||||
// Unary operations.
|
||||
friend IntegerType operator+(const T& x) { return x; }
|
||||
friend IntegerType operator-(const T& x) { return -+x; }
|
||||
friend IntegerType operator~(const T& x) { return ~+x; }
|
||||
friend IntegerType operator!(const T& x) { return !+x; }
|
||||
|
||||
// The basic ordering operations.
|
||||
friend bool operator==(const T& x, IntegerType y) { return +x == y; }
|
||||
friend bool operator<(const T& x, IntegerType y) { return +x < y; }
|
||||
|
||||
// The basic arithmetic operations.
|
||||
friend T& operator+=(T& x, IntegerType y) { return x = +x + y; }
|
||||
friend T& operator-=(T& x, IntegerType y) { return x = +x - y; }
|
||||
friend T& operator*=(T& x, IntegerType y) { return x = +x * y; }
|
||||
friend T& operator/=(T& x, IntegerType y) { return x = +x / y; }
|
||||
friend T& operator%=(T& x, IntegerType y) { return x = +x % y; }
|
||||
friend T& operator&=(T& x, IntegerType y) { return x = +x & y; }
|
||||
friend T& operator|=(T& x, IntegerType y) { return x = +x | y; }
|
||||
friend T& operator^=(T& x, IntegerType y) { return x = +x ^ y; }
|
||||
friend T& operator<<=(T& x, IntegerType y) { return x = +x << y; }
|
||||
friend T& operator>>=(T& x, IntegerType y) { return x = +x >> y; }
|
||||
|
||||
// A few binary arithmetic operations not covered by operators base class.
|
||||
friend IntegerType operator<<(const T& x, IntegerType y) { return +x << y; }
|
||||
friend IntegerType operator>>(const T& x, IntegerType y) { return +x >> y; }
|
||||
|
||||
// Auto-increment and auto-decrement can be defined in terms of the
|
||||
// arithmetic operations.
|
||||
friend T& operator++(T& x) { return x += 1; }
|
||||
friend T& operator--(T& x) { return x -= 1; }
|
||||
|
||||
/// TODO: stream I/O needs to be templatized on the stream type, so will
|
||||
/// work with wide streams, etc.
|
||||
|
||||
// Stream input and output.
|
||||
friend std::ostream& operator<<(std::ostream& s, const T& x)
|
||||
{ return s << +x; }
|
||||
friend std::istream& operator>>(std::istream& s, T& x)
|
||||
{
|
||||
IntegerType i;
|
||||
if (s >> i)
|
||||
x = i;
|
||||
return s;
|
||||
}
|
||||
};
|
||||
} // namespace integer
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_INTEGER_COVER_OPERATORS_HPP
|
||||
@@ -0,0 +1,338 @@
|
||||
// Boost endian.hpp header file (proposed) ----------------------------------//
|
||||
|
||||
// (C) Copyright Darin Adler 2000
|
||||
// (C) Copyright Beman Dawes 2006
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See library home page at http://www.boost.org/libs/endian
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// Original design developed by Darin Adler based on classes developed by Mark
|
||||
// Borgerding. Four original class templates combined into a single endian
|
||||
// class template by Beman Dawes, who also added the unrolled_byte_loops sign
|
||||
// partial specialization to correctly extend the sign when cover integer size
|
||||
// differs from endian representation size.
|
||||
|
||||
#ifndef BOOST_ENDIAN_HPP
|
||||
#define BOOST_ENDIAN_HPP
|
||||
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/spirit/home/support/detail/integer/cover_operators.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <iosfwd>
|
||||
#include <climits>
|
||||
|
||||
# if CHAR_BIT != 8
|
||||
# error Platforms with CHAR_BIT != 8 are not supported
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Unrolled loops for loading and storing streams of bytes.
|
||||
|
||||
template <typename T, std::size_t n_bytes,
|
||||
bool sign=boost::is_signed<T>::value >
|
||||
struct unrolled_byte_loops
|
||||
{
|
||||
typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
|
||||
|
||||
static T load_big(const unsigned char* bytes)
|
||||
{ return *(bytes - 1) | (next::load_big(bytes - 1) << 8); }
|
||||
static T load_little(const unsigned char* bytes)
|
||||
{ return *bytes | (next::load_little(bytes + 1) << 8); }
|
||||
|
||||
static void store_big(char* bytes, T value)
|
||||
{
|
||||
*(bytes - 1) = static_cast<char>(value);
|
||||
next::store_big(bytes - 1, value >> 8);
|
||||
}
|
||||
static void store_little(char* bytes, T value)
|
||||
{
|
||||
*bytes = static_cast<char>(value);
|
||||
next::store_little(bytes + 1, value >> 8);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct unrolled_byte_loops<T, 1, false>
|
||||
{
|
||||
static T load_big(const unsigned char* bytes)
|
||||
{ return *(bytes - 1); }
|
||||
static T load_little(const unsigned char* bytes)
|
||||
{ return *bytes; }
|
||||
static void store_big(char* bytes, T value)
|
||||
{ *(bytes - 1) = static_cast<char>(value); }
|
||||
static void store_little(char* bytes, T value)
|
||||
{ *bytes = static_cast<char>(value); }
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct unrolled_byte_loops<T, 1, true>
|
||||
{
|
||||
static T load_big(const unsigned char* bytes)
|
||||
{ return *reinterpret_cast<const signed char*>(bytes - 1); }
|
||||
static T load_little(const unsigned char* bytes)
|
||||
{ return *reinterpret_cast<const signed char*>(bytes); }
|
||||
static void store_big(char* bytes, T value)
|
||||
{ *(bytes - 1) = static_cast<char>(value); }
|
||||
static void store_little(char* bytes, T value)
|
||||
{ *bytes = static_cast<char>(value); }
|
||||
};
|
||||
|
||||
template <typename T, std::size_t n_bytes>
|
||||
inline
|
||||
T load_big_endian(const void* bytes)
|
||||
{
|
||||
return unrolled_byte_loops<T, n_bytes>::load_big
|
||||
(static_cast<const unsigned char*>(bytes) + n_bytes);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t n_bytes>
|
||||
inline
|
||||
T load_little_endian(const void* bytes)
|
||||
{
|
||||
return unrolled_byte_loops<T, n_bytes>::load_little
|
||||
(static_cast<const unsigned char*>(bytes));
|
||||
}
|
||||
|
||||
template <typename T, std::size_t n_bytes>
|
||||
inline
|
||||
void store_big_endian(void* bytes, T value)
|
||||
{
|
||||
unrolled_byte_loops<T, n_bytes>::store_big
|
||||
(static_cast<char*>(bytes) + n_bytes, value);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t n_bytes>
|
||||
inline
|
||||
void store_little_endian(void* bytes, T value)
|
||||
{
|
||||
unrolled_byte_loops<T, n_bytes>::store_little
|
||||
(static_cast<char*>(bytes), value);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace integer
|
||||
{
|
||||
|
||||
// endian class template and specializations -----------------------------//
|
||||
|
||||
enum endianness { big, little, native };
|
||||
|
||||
enum alignment { unaligned, aligned };
|
||||
|
||||
template <endianness E, typename T, std::size_t n_bits,
|
||||
alignment A = unaligned>
|
||||
class endian;
|
||||
|
||||
// Specializations that represent unaligned bytes.
|
||||
// Taking an integer type as a parameter provides a nice way to pass both
|
||||
// the size and signedness of the desired integer and get the appropriate
|
||||
// corresponding integer type for the interface.
|
||||
|
||||
template <typename T, std::size_t n_bits>
|
||||
class endian< big, T, n_bits, unaligned >
|
||||
: cover_operators< endian< big, T, n_bits >, T >
|
||||
{
|
||||
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
|
||||
public:
|
||||
typedef T value_type;
|
||||
endian() {}
|
||||
endian(T i) { detail::store_big_endian<T, n_bits/8>(bytes, i); }
|
||||
operator T() const
|
||||
{ return detail::load_big_endian<T, n_bits/8>(bytes); }
|
||||
private:
|
||||
char bytes[n_bits/8];
|
||||
};
|
||||
|
||||
template <typename T, std::size_t n_bits>
|
||||
class endian< little, T, n_bits, unaligned >
|
||||
: cover_operators< endian< little, T, n_bits >, T >
|
||||
{
|
||||
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
|
||||
public:
|
||||
typedef T value_type;
|
||||
endian() {}
|
||||
endian(T i) { detail::store_little_endian<T, n_bits/8>(bytes, i); }
|
||||
operator T() const
|
||||
{ return detail::load_little_endian<T, n_bits/8>(bytes); }
|
||||
private:
|
||||
char bytes[n_bits/8];
|
||||
};
|
||||
|
||||
template <typename T, std::size_t n_bits>
|
||||
class endian< native, T, n_bits, unaligned >
|
||||
: cover_operators< endian< native, T, n_bits >, T >
|
||||
{
|
||||
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
|
||||
public:
|
||||
typedef T value_type;
|
||||
endian() {}
|
||||
# ifdef BOOST_BIG_ENDIAN
|
||||
endian(T i) { detail::store_big_endian<T, n_bits/8>(bytes, i); }
|
||||
operator T() const
|
||||
{ return detail::load_big_endian<T, n_bits/8>(bytes); }
|
||||
# else
|
||||
endian(T i) { detail::store_little_endian<T, n_bits/8>(bytes, i); }
|
||||
operator T() const
|
||||
{ return detail::load_little_endian<T, n_bits/8>(bytes); }
|
||||
# endif
|
||||
private:
|
||||
char bytes[n_bits/8];
|
||||
};
|
||||
|
||||
// Specializations that mimic built-in integer types.
|
||||
// These typically have the same alignment as the underlying types.
|
||||
|
||||
template <typename T, std::size_t n_bits>
|
||||
class endian< big, T, n_bits, aligned >
|
||||
: cover_operators< endian< big, T, n_bits, aligned >, T >
|
||||
{
|
||||
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
|
||||
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
|
||||
public:
|
||||
typedef T value_type;
|
||||
endian() {}
|
||||
#ifdef BOOST_BIG_ENDIAN
|
||||
endian(T i) : integer(i) { }
|
||||
operator T() const { return integer; }
|
||||
#else
|
||||
endian(T i) { detail::store_big_endian<T, sizeof(T)>(&integer, i); }
|
||||
operator T() const
|
||||
{ return detail::load_big_endian<T, sizeof(T)>(&integer); }
|
||||
#endif
|
||||
private:
|
||||
T integer;
|
||||
};
|
||||
|
||||
template <typename T, std::size_t n_bits>
|
||||
class endian< little, T, n_bits, aligned >
|
||||
: cover_operators< endian< little, T, n_bits, aligned >, T >
|
||||
{
|
||||
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
|
||||
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
|
||||
public:
|
||||
typedef T value_type;
|
||||
endian() {}
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
endian(T i) : integer(i) { }
|
||||
operator T() const { return integer; }
|
||||
#else
|
||||
endian(T i)
|
||||
{ detail::store_little_endian<T, sizeof(T)>(&integer, i); }
|
||||
operator T() const
|
||||
{ return detail::load_little_endian<T, sizeof(T)>(&integer); }
|
||||
#endif
|
||||
private:
|
||||
T integer;
|
||||
};
|
||||
|
||||
// naming convention typedefs --------------------------------------------//
|
||||
|
||||
// unaligned big endian signed integer types
|
||||
typedef endian< big, int_least8_t, 8 > big8_t;
|
||||
typedef endian< big, int_least16_t, 16 > big16_t;
|
||||
typedef endian< big, int_least32_t, 24 > big24_t;
|
||||
typedef endian< big, int_least32_t, 32 > big32_t;
|
||||
typedef endian< big, int_least64_t, 40 > big40_t;
|
||||
typedef endian< big, int_least64_t, 48 > big48_t;
|
||||
typedef endian< big, int_least64_t, 56 > big56_t;
|
||||
typedef endian< big, int_least64_t, 64 > big64_t;
|
||||
|
||||
// unaligned big endian unsigned integer types
|
||||
typedef endian< big, uint_least8_t, 8 > ubig8_t;
|
||||
typedef endian< big, uint_least16_t, 16 > ubig16_t;
|
||||
typedef endian< big, uint_least32_t, 24 > ubig24_t;
|
||||
typedef endian< big, uint_least32_t, 32 > ubig32_t;
|
||||
typedef endian< big, uint_least64_t, 40 > ubig40_t;
|
||||
typedef endian< big, uint_least64_t, 48 > ubig48_t;
|
||||
typedef endian< big, uint_least64_t, 56 > ubig56_t;
|
||||
typedef endian< big, uint_least64_t, 64 > ubig64_t;
|
||||
|
||||
// unaligned little endian signed integer types
|
||||
typedef endian< little, int_least8_t, 8 > little8_t;
|
||||
typedef endian< little, int_least16_t, 16 > little16_t;
|
||||
typedef endian< little, int_least32_t, 24 > little24_t;
|
||||
typedef endian< little, int_least32_t, 32 > little32_t;
|
||||
typedef endian< little, int_least64_t, 40 > little40_t;
|
||||
typedef endian< little, int_least64_t, 48 > little48_t;
|
||||
typedef endian< little, int_least64_t, 56 > little56_t;
|
||||
typedef endian< little, int_least64_t, 64 > little64_t;
|
||||
|
||||
// unaligned little endian unsigned integer types
|
||||
typedef endian< little, uint_least8_t, 8 > ulittle8_t;
|
||||
typedef endian< little, uint_least16_t, 16 > ulittle16_t;
|
||||
typedef endian< little, uint_least32_t, 24 > ulittle24_t;
|
||||
typedef endian< little, uint_least32_t, 32 > ulittle32_t;
|
||||
typedef endian< little, uint_least64_t, 40 > ulittle40_t;
|
||||
typedef endian< little, uint_least64_t, 48 > ulittle48_t;
|
||||
typedef endian< little, uint_least64_t, 56 > ulittle56_t;
|
||||
typedef endian< little, uint_least64_t, 64 > ulittle64_t;
|
||||
|
||||
// unaligned native endian signed integer types
|
||||
typedef endian< native, int_least8_t, 8 > native8_t;
|
||||
typedef endian< native, int_least16_t, 16 > native16_t;
|
||||
typedef endian< native, int_least32_t, 24 > native24_t;
|
||||
typedef endian< native, int_least32_t, 32 > native32_t;
|
||||
typedef endian< native, int_least64_t, 40 > native40_t;
|
||||
typedef endian< native, int_least64_t, 48 > native48_t;
|
||||
typedef endian< native, int_least64_t, 56 > native56_t;
|
||||
typedef endian< native, int_least64_t, 64 > native64_t;
|
||||
|
||||
// unaligned native endian unsigned integer types
|
||||
typedef endian< native, uint_least8_t, 8 > unative8_t;
|
||||
typedef endian< native, uint_least16_t, 16 > unative16_t;
|
||||
typedef endian< native, uint_least32_t, 24 > unative24_t;
|
||||
typedef endian< native, uint_least32_t, 32 > unative32_t;
|
||||
typedef endian< native, uint_least64_t, 40 > unative40_t;
|
||||
typedef endian< native, uint_least64_t, 48 > unative48_t;
|
||||
typedef endian< native, uint_least64_t, 56 > unative56_t;
|
||||
typedef endian< native, uint_least64_t, 64 > unative64_t;
|
||||
|
||||
#define BOOST_HAS_INT16_T
|
||||
#define BOOST_HAS_INT32_T
|
||||
#define BOOST_HAS_INT64_T
|
||||
|
||||
// These types only present if platform has exact size integers:
|
||||
// aligned big endian signed integer types
|
||||
// aligned big endian unsigned integer types
|
||||
// aligned little endian signed integer types
|
||||
// aligned little endian unsigned integer types
|
||||
|
||||
// aligned native endian typedefs are not provided because
|
||||
// <cstdint> types are superior for this use case
|
||||
|
||||
# if defined(BOOST_HAS_INT16_T)
|
||||
typedef endian< big, int16_t, 16, aligned > aligned_big16_t;
|
||||
typedef endian< big, uint16_t, 16, aligned > aligned_ubig16_t;
|
||||
typedef endian< little, int16_t, 16, aligned > aligned_little16_t;
|
||||
typedef endian< little, uint16_t, 16, aligned > aligned_ulittle16_t;
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_HAS_INT32_T)
|
||||
typedef endian< big, int32_t, 32, aligned > aligned_big32_t;
|
||||
typedef endian< big, uint32_t, 32, aligned > aligned_ubig32_t;
|
||||
typedef endian< little, int32_t, 32, aligned > aligned_little32_t;
|
||||
typedef endian< little, uint32_t, 32, aligned > aligned_ulittle32_t;
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_HAS_INT64_T)
|
||||
typedef endian< big, int64_t, 64, aligned > aligned_big64_t;
|
||||
typedef endian< big, uint64_t, 64, aligned > aligned_ubig64_t;
|
||||
typedef endian< little, int64_t, 64, aligned > aligned_little64_t;
|
||||
typedef endian< little, uint64_t, 64, aligned > aligned_ulittle64_t;
|
||||
# endif
|
||||
|
||||
} // namespace integer
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ENDIAN_HPP
|
||||
@@ -0,0 +1,54 @@
|
||||
// char_traits.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_CHAR_TRAITS_H
|
||||
#define BOOST_LEXER_CHAR_TRAITS_H
|
||||
|
||||
// Make sure wchar_t is defined
|
||||
#include <string>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT>
|
||||
struct char_traits
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef CharT index_type;
|
||||
|
||||
static index_type call (CharT ch)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_traits<char>
|
||||
{
|
||||
typedef char char_type;
|
||||
typedef unsigned char index_type;
|
||||
|
||||
static index_type call (char ch)
|
||||
{
|
||||
return static_cast<index_type>(ch);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_traits<wchar_t>
|
||||
{
|
||||
typedef wchar_t char_type;
|
||||
typedef wchar_t index_type;
|
||||
|
||||
static index_type call (wchar_t ch)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
// consts.h
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_CONSTS_H
|
||||
#define BOOST_LEXER_CONSTS_H
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
#include "size_t.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
enum regex_flags {none = 0, icase = 1, dot_not_newline = 2};
|
||||
// 0 = end state, 1 = id, 2 = lex state, 3 = bol, 4 = eol,
|
||||
// 5 = dead_state_index
|
||||
enum {end_state_index, id_index, state_index, bol_index, eol_index,
|
||||
dead_state_index, dfa_offset};
|
||||
|
||||
const std::size_t max_macro_len = 20;
|
||||
const std::size_t num_chars = 256;
|
||||
const std::size_t num_wchar_ts =
|
||||
(boost::integer_traits<wchar_t>::const_max < 0x110000) ?
|
||||
boost::integer_traits<wchar_t>::const_max : 0x110000;
|
||||
const std::size_t null_token = static_cast<std::size_t> (~0);
|
||||
const std::size_t bol_token = static_cast<std::size_t> (~1);
|
||||
const std::size_t eol_token = static_cast<std::size_t> (~2);
|
||||
const std::size_t end_state = 1;
|
||||
const std::size_t npos = static_cast<std::size_t> (~0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
// ptr_list.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_PTR_LIST_HPP
|
||||
#define BOOST_LEXER_PTR_LIST_HPP
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Type>
|
||||
class ptr_list
|
||||
{
|
||||
public:
|
||||
typedef std::list<Type *> list;
|
||||
|
||||
ptr_list ()
|
||||
{
|
||||
}
|
||||
|
||||
~ptr_list ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
list *operator -> ()
|
||||
{
|
||||
return &_list;
|
||||
}
|
||||
|
||||
const list *operator -> () const
|
||||
{
|
||||
return &_list;
|
||||
}
|
||||
|
||||
list &operator * ()
|
||||
{
|
||||
return _list;
|
||||
}
|
||||
|
||||
const list &operator * () const
|
||||
{
|
||||
return _list;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
while (!_list.empty ())
|
||||
{
|
||||
delete _list.front ();
|
||||
_list.pop_front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
list _list;
|
||||
|
||||
ptr_list (ptr_list const &); // No copy construction.
|
||||
ptr_list &operator = (ptr_list const &); // No assignment.
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
// ptr_vector.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_PTR_VECTOR_HPP
|
||||
#define BOOST_LEXER_PTR_VECTOR_HPP
|
||||
|
||||
#include "../size_t.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Type>
|
||||
class ptr_vector
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Type *> vector;
|
||||
|
||||
ptr_vector ()
|
||||
{
|
||||
}
|
||||
|
||||
~ptr_vector ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
vector *operator -> ()
|
||||
{
|
||||
return &_vector;
|
||||
}
|
||||
|
||||
const vector *operator -> () const
|
||||
{
|
||||
return &_vector;
|
||||
}
|
||||
|
||||
vector &operator * ()
|
||||
{
|
||||
return _vector;
|
||||
}
|
||||
|
||||
const vector &operator * () const
|
||||
{
|
||||
return _vector;
|
||||
}
|
||||
|
||||
Type * &operator [] (const std::size_t index_)
|
||||
{
|
||||
return _vector[index_];
|
||||
}
|
||||
|
||||
Type * const &operator [] (const std::size_t index_) const
|
||||
{
|
||||
return _vector[index_];
|
||||
}
|
||||
|
||||
bool operator == (const ptr_vector &rhs_) const
|
||||
{
|
||||
bool equal_ = _vector.size () == rhs_._vector.size ();
|
||||
|
||||
if (equal_)
|
||||
{
|
||||
typename vector::const_iterator lhs_iter_ = _vector.begin ();
|
||||
typename vector::const_iterator end_ = _vector.end ();
|
||||
typename vector::const_iterator rhs_iter_ = rhs_._vector.begin ();
|
||||
|
||||
for (; equal_ && lhs_iter_ != end_; ++lhs_iter_, ++rhs_iter_)
|
||||
{
|
||||
equal_ = **lhs_iter_ == **rhs_iter_;
|
||||
}
|
||||
}
|
||||
|
||||
return equal_;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
if (!_vector.empty ())
|
||||
{
|
||||
Type **iter_ = &_vector.front ();
|
||||
Type **end_ = iter_ + _vector.size ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
delete *iter_;
|
||||
}
|
||||
}
|
||||
|
||||
_vector.clear ();
|
||||
}
|
||||
|
||||
private:
|
||||
vector _vector;
|
||||
|
||||
ptr_vector (ptr_vector const &); // No copy construction.
|
||||
ptr_vector &operator = (ptr_vector const &); // No assignment.
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
// char_state_machine.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_CHAR_STATE_MACHINE_HPP
|
||||
#define BOOST_LEXER_CHAR_STATE_MACHINE_HPP
|
||||
|
||||
#include "../consts.hpp"
|
||||
#include <map>
|
||||
#include "../size_t.hpp"
|
||||
#include "../string_token.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
struct basic_char_state_machine
|
||||
{
|
||||
struct state
|
||||
{
|
||||
typedef basic_string_token<CharT> string_token;
|
||||
typedef std::map<std::size_t, string_token> size_t_string_token_map;
|
||||
typedef std::pair<std::size_t, string_token> size_t_string_token_pair;
|
||||
|
||||
bool _end_state;
|
||||
std::size_t _id;
|
||||
std::size_t _state;
|
||||
std::size_t _bol_index;
|
||||
std::size_t _eol_index;
|
||||
size_t_string_token_map _transitions;
|
||||
|
||||
state () :
|
||||
_end_state (false),
|
||||
_id (0),
|
||||
_state (0),
|
||||
_bol_index (npos),
|
||||
_eol_index (npos)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<state> state_vector;
|
||||
typedef std::vector<state_vector> state_vector_vector;
|
||||
|
||||
state_vector_vector _sm_vector;
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return _sm_vector.empty ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
_sm_vector.clear ();
|
||||
}
|
||||
|
||||
void swap (basic_char_state_machine &csm_)
|
||||
{
|
||||
_sm_vector.swap (csm_._sm_vector);
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_char_state_machine<char> char_state_machine;
|
||||
typedef basic_char_state_machine<wchar_t> wchar_state_machine;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,302 @@
|
||||
// debug.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_DEBUG_HPP
|
||||
#define BOOST_LEXER_DEBUG_HPP
|
||||
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include "size_t.hpp"
|
||||
#include "state_machine.hpp"
|
||||
#include "string_token.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT>
|
||||
class basic_debug
|
||||
{
|
||||
public:
|
||||
typedef std::basic_ostream<CharT> ostream;
|
||||
typedef std::basic_string<CharT> string;
|
||||
typedef std::vector<std::size_t> size_t_vector;
|
||||
|
||||
static void escape_control_chars (const string &in_, string &out_)
|
||||
{
|
||||
const CharT *ptr_ = in_.c_str ();
|
||||
std::size_t size_ = in_.size ();
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
out_.erase ();
|
||||
#else
|
||||
out_.clear ();
|
||||
#endif
|
||||
|
||||
while (size_)
|
||||
{
|
||||
switch (*ptr_)
|
||||
{
|
||||
case '\0':
|
||||
out_ += '\\';
|
||||
out_ += '0';
|
||||
break;
|
||||
case '\a':
|
||||
out_ += '\\';
|
||||
out_ += 'a';
|
||||
break;
|
||||
case '\b':
|
||||
out_ += '\\';
|
||||
out_ += 'b';
|
||||
break;
|
||||
case 27:
|
||||
out_ += '\\';
|
||||
out_ += 'x';
|
||||
out_ += '1';
|
||||
out_ += 'b';
|
||||
break;
|
||||
case '\f':
|
||||
out_ += '\\';
|
||||
out_ += 'f';
|
||||
break;
|
||||
case '\n':
|
||||
out_ += '\\';
|
||||
out_ += 'n';
|
||||
break;
|
||||
case '\r':
|
||||
out_ += '\\';
|
||||
out_ += 'r';
|
||||
break;
|
||||
case '\t':
|
||||
out_ += '\\';
|
||||
out_ += 't';
|
||||
break;
|
||||
case '\v':
|
||||
out_ += '\\';
|
||||
out_ += 'v';
|
||||
break;
|
||||
case '\\':
|
||||
out_ += '\\';
|
||||
out_ += '\\';
|
||||
break;
|
||||
case '"':
|
||||
out_ += '\\';
|
||||
out_ += '"';
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (*ptr_ < 32 && *ptr_ >= 0)
|
||||
{
|
||||
stringstream ss_;
|
||||
|
||||
out_ += '\\';
|
||||
out_ += 'x';
|
||||
ss_ << std::hex <<
|
||||
static_cast<std::size_t> (*ptr_);
|
||||
out_ += ss_.str ();
|
||||
}
|
||||
else
|
||||
{
|
||||
out_ += *ptr_;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++ptr_;
|
||||
--size_;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump (const basic_state_machine<CharT> &state_machine_, ostream &stream_)
|
||||
{
|
||||
typename basic_state_machine<CharT>::iterator iter_ =
|
||||
state_machine_.begin ();
|
||||
typename basic_state_machine<CharT>::iterator end_ =
|
||||
state_machine_.end ();
|
||||
|
||||
for (std::size_t dfa_ = 0, dfas_ = state_machine_.size ();
|
||||
dfa_ < dfas_; ++dfa_)
|
||||
{
|
||||
const std::size_t states_ = iter_->states;
|
||||
|
||||
for (std::size_t i_ = 0; i_ < states_; ++i_)
|
||||
{
|
||||
state (stream_);
|
||||
stream_ << i_ << std::endl;
|
||||
|
||||
if (iter_->end_state)
|
||||
{
|
||||
end_state (stream_);
|
||||
stream_ << iter_->id;
|
||||
dfa (stream_);
|
||||
stream_ << iter_->goto_dfa;
|
||||
stream_ << std::endl;
|
||||
}
|
||||
|
||||
if (iter_->bol_index != npos)
|
||||
{
|
||||
bol (stream_);
|
||||
stream_ << iter_->bol_index << std::endl;
|
||||
}
|
||||
|
||||
if (iter_->eol_index != npos)
|
||||
{
|
||||
eol (stream_);
|
||||
stream_ << iter_->eol_index << std::endl;
|
||||
}
|
||||
|
||||
const std::size_t transitions_ = iter_->transitions;
|
||||
|
||||
if (transitions_ == 0)
|
||||
{
|
||||
++iter_;
|
||||
}
|
||||
|
||||
for (std::size_t t_ = 0; t_ < transitions_; ++t_)
|
||||
{
|
||||
std::size_t goto_state_ = iter_->goto_state;
|
||||
|
||||
if (iter_->token.any ())
|
||||
{
|
||||
any (stream_);
|
||||
}
|
||||
else
|
||||
{
|
||||
open_bracket (stream_);
|
||||
|
||||
if (iter_->token._negated)
|
||||
{
|
||||
negated (stream_);
|
||||
}
|
||||
|
||||
string charset_;
|
||||
CharT c_ = 0;
|
||||
|
||||
escape_control_chars (iter_->token._charset,
|
||||
charset_);
|
||||
c_ = *charset_.c_str ();
|
||||
|
||||
if (!iter_->token._negated &&
|
||||
(c_ == '^' || c_ == ']'))
|
||||
{
|
||||
stream_ << '\\';
|
||||
}
|
||||
|
||||
stream_ << charset_;
|
||||
close_bracket (stream_);
|
||||
}
|
||||
|
||||
stream_ << goto_state_ << std::endl;
|
||||
++iter_;
|
||||
}
|
||||
|
||||
stream_ << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef std::basic_stringstream<CharT> stringstream;
|
||||
|
||||
static void state (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << "State: ";
|
||||
}
|
||||
|
||||
static void state (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L"State: ";
|
||||
}
|
||||
|
||||
static void bol (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << " BOL -> ";
|
||||
}
|
||||
|
||||
static void bol (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L" BOL -> ";
|
||||
}
|
||||
|
||||
static void eol (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << " EOL -> ";
|
||||
}
|
||||
|
||||
static void eol (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L" EOL -> ";
|
||||
}
|
||||
|
||||
static void end_state (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << " END STATE, Id = ";
|
||||
}
|
||||
|
||||
static void end_state (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L" END STATE, Id = ";
|
||||
}
|
||||
|
||||
static void any (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << " . -> ";
|
||||
}
|
||||
|
||||
static void any (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L" . -> ";
|
||||
}
|
||||
|
||||
static void open_bracket (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << " [";
|
||||
}
|
||||
|
||||
static void open_bracket (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L" [";
|
||||
}
|
||||
|
||||
static void negated (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << "^";
|
||||
}
|
||||
|
||||
static void negated (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L"^";
|
||||
}
|
||||
|
||||
static void close_bracket (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << "] -> ";
|
||||
}
|
||||
|
||||
static void close_bracket (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L"] -> ";
|
||||
}
|
||||
|
||||
static void dfa (std::basic_ostream<char> &stream_)
|
||||
{
|
||||
stream_ << ", dfa = ";
|
||||
}
|
||||
|
||||
static void dfa (std::basic_ostream<wchar_t> &stream_)
|
||||
{
|
||||
stream_ << L", dfa = ";
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_debug<char> debug;
|
||||
typedef basic_debug<wchar_t> wdebug;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,456 @@
|
||||
// file_input.hpp
|
||||
// Copyright (c) 2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_FILE_INPUT
|
||||
#define BOOST_LEXER_FILE_INPUT
|
||||
|
||||
#include "char_traits.hpp"
|
||||
#include <fstream>
|
||||
#include "size_t.hpp"
|
||||
#include "state_machine.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT, typename Traits = char_traits<CharT> >
|
||||
class basic_file_input
|
||||
{
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend basic_file_input;
|
||||
#else
|
||||
friend class basic_file_input;
|
||||
#endif
|
||||
|
||||
struct data
|
||||
{
|
||||
std::size_t id;
|
||||
const CharT *start;
|
||||
const CharT *end;
|
||||
std::size_t state;
|
||||
|
||||
// Construct in end() state.
|
||||
data () :
|
||||
id (0),
|
||||
state (npos)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const data &rhs_) const
|
||||
{
|
||||
return id == rhs_.id && start == rhs_.start &&
|
||||
end == rhs_.end && state == rhs_.state;
|
||||
}
|
||||
};
|
||||
|
||||
iterator () :
|
||||
_input (0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const iterator &rhs_) const
|
||||
{
|
||||
return _data == rhs_._data;
|
||||
}
|
||||
|
||||
bool operator != (const iterator &rhs_) const
|
||||
{
|
||||
return !(*this == rhs_);
|
||||
}
|
||||
|
||||
data &operator * ()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
data *operator -> ()
|
||||
{
|
||||
return &_data;
|
||||
}
|
||||
|
||||
// Let compiler generate operator = ().
|
||||
|
||||
// prefix version
|
||||
iterator &operator ++ ()
|
||||
{
|
||||
next_token ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// postfix version
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator iter_ = *this;
|
||||
|
||||
next_token ();
|
||||
return iter_;
|
||||
}
|
||||
|
||||
void next_token ()
|
||||
{
|
||||
_data.start = _data.end;
|
||||
|
||||
if (_input->_state_machine->_dfa->size () == 1)
|
||||
{
|
||||
_data.id = _input->next (&_input->_state_machine->_lookup->
|
||||
front ()->front (), _input->_state_machine->_dfa_alphabet.
|
||||
front (), &_input->_state_machine->_dfa->front ()->
|
||||
front (), _data.start, _data.end);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.id = _input->next (*_input->_state_machine, _data.state,
|
||||
_data.start, _data.end);
|
||||
}
|
||||
|
||||
if (_data.id == 0)
|
||||
{
|
||||
_data.start = 0;
|
||||
_data.end = 0;
|
||||
// Ensure current state matches that returned by end().
|
||||
_data.state = npos;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Not owner (obviously!)
|
||||
basic_file_input *_input;
|
||||
data _data;
|
||||
};
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend iterator;
|
||||
#else
|
||||
friend class iterator;
|
||||
#endif
|
||||
|
||||
// Make it explict that we are NOT taking a copy of state_machine_!
|
||||
basic_file_input (const basic_state_machine<CharT> *state_machine_,
|
||||
std::basic_ifstream<CharT> *is_,
|
||||
const std::streamsize buffer_size_ = 4096,
|
||||
const std::streamsize buffer_increment_ = 1024) :
|
||||
_state_machine (state_machine_),
|
||||
_stream (is_),
|
||||
_buffer_size (buffer_size_),
|
||||
_buffer_increment (buffer_increment_),
|
||||
_buffer (_buffer_size, '!')
|
||||
{
|
||||
_start_buffer = &_buffer.front ();
|
||||
_end_buffer = _start_buffer + _buffer.size ();
|
||||
_start_token = _end_buffer;
|
||||
_end_token = _end_buffer;
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._input = this;
|
||||
iter_._data.id = npos;
|
||||
iter_._data.start = 0;
|
||||
iter_._data.end = 0;
|
||||
iter_._data.state = 0;
|
||||
++iter_;
|
||||
return iter_;
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._input = this;
|
||||
iter_._data.start = 0;
|
||||
iter_._data.end = 0;
|
||||
return iter_;
|
||||
}
|
||||
|
||||
void flush ()
|
||||
{
|
||||
// This temporary is mandatory, otherwise the
|
||||
// pointer calculations won't work!
|
||||
const CharT *temp_ = _end_buffer;
|
||||
|
||||
_start_token = _end_token = _end_buffer;
|
||||
reload_buffer (temp_, true, _end_token);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::basic_istream<CharT> istream;
|
||||
typedef std::vector<CharT> buffer;
|
||||
|
||||
const basic_state_machine<CharT> *_state_machine;
|
||||
const std::streamsize _buffer_size;
|
||||
const std::streamsize _buffer_increment;
|
||||
|
||||
buffer _buffer;
|
||||
CharT *_start_buffer;
|
||||
istream *_stream;
|
||||
const CharT *_start_token;
|
||||
const CharT *_end_token;
|
||||
CharT *_end_buffer;
|
||||
|
||||
std::size_t next (const basic_state_machine<CharT> &state_machine_,
|
||||
std::size_t &start_state_, const CharT * &start_, const CharT * &end_)
|
||||
{
|
||||
_start_token = _end_token;
|
||||
|
||||
again:
|
||||
const std::size_t * lookup_ = &state_machine_._lookup[start_state_]->
|
||||
front ();
|
||||
std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[start_state_];
|
||||
const std::size_t *dfa_ = &state_machine_._dfa[start_state_]->front ();
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
const CharT *curr_ = _start_token;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + id_index);
|
||||
const CharT *end_token_ = curr_;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (curr_ >= _end_buffer)
|
||||
{
|
||||
if (!reload_buffer (curr_, end_state_, end_token_))
|
||||
{
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t BOL_state_ = ptr_[bol_index];
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (BOL_state_ && (_start_token == _start_buffer ||
|
||||
*(_start_token - 1) == '\n'))
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::size_t state_ =
|
||||
ptr_[lookup_[static_cast<typename Traits::index_type> (*curr_++)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
start_state_ = *(ptr_ + state_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (_start_token >= _end_buffer)
|
||||
{
|
||||
// No more tokens...
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
start_state_ = *(ptr_ + state_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
_end_token = end_token_;
|
||||
|
||||
if (id_ == 0) goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
_end_token = _start_token + 1;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
start_ = _start_token;
|
||||
end_ = _end_token;
|
||||
return id_;
|
||||
}
|
||||
|
||||
std::size_t next (const std::size_t * const lookup_,
|
||||
const std::size_t dfa_alphabet_, const std::size_t * const dfa_,
|
||||
const CharT * &start_, const CharT * &end_)
|
||||
{
|
||||
_start_token = _end_token;
|
||||
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
const CharT *curr_ = _start_token;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = id_ = *(ptr_ + id_index);
|
||||
const CharT *end_token_ = curr_;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (curr_ >= _end_buffer)
|
||||
{
|
||||
if (!reload_buffer (curr_, end_state_, end_token_))
|
||||
{
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t BOL_state_ = ptr_[bol_index];
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (BOL_state_ && (_start_token == _start_buffer ||
|
||||
*(_start_token - 1) == '\n'))
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::size_t state_ =
|
||||
ptr_[lookup_[static_cast<typename Traits::index_type> (*curr_++)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (_start_token >= _end_buffer)
|
||||
{
|
||||
// No more tokens...
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
_end_token = end_token_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
_end_token = _start_token + 1;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
start_ = _start_token;
|
||||
end_ = _end_token;
|
||||
return id_;
|
||||
}
|
||||
|
||||
bool reload_buffer (const CharT * &curr_, const bool end_state_,
|
||||
const CharT * &end_token_)
|
||||
{
|
||||
bool success_ = !_stream->eof ();
|
||||
|
||||
if (success_)
|
||||
{
|
||||
const CharT *old_start_token_ = _start_token;
|
||||
std::size_t old_size_ = _buffer.size ();
|
||||
std::size_t count_ = 0;
|
||||
|
||||
if (_start_token - 1 == _start_buffer)
|
||||
{
|
||||
// Run out of buffer space, so increase.
|
||||
_buffer.resize (old_size_ + _buffer_increment, '!');
|
||||
_start_buffer = &_buffer.front ();
|
||||
_start_token = _start_buffer + 1;
|
||||
_stream->read (_start_buffer + old_size_,
|
||||
_buffer_increment);
|
||||
count_ = _stream->gcount ();
|
||||
_end_buffer = _start_buffer + old_size_ + count_;
|
||||
}
|
||||
else if (_start_token < _end_buffer)
|
||||
{
|
||||
const std::size_t len_ = _end_buffer - _start_token;
|
||||
|
||||
::memcpy (_start_buffer, _start_token - 1, (len_ + 1) * sizeof (CharT));
|
||||
_stream->read (_start_buffer + len_ + 1,
|
||||
static_cast<std::streamsize> (_buffer.size () - len_ - 1));
|
||||
count_ = _stream->gcount ();
|
||||
_start_token = _start_buffer + 1;
|
||||
_end_buffer = _start_buffer + len_ + 1 + count_;
|
||||
}
|
||||
else
|
||||
{
|
||||
_stream->read (_start_buffer, static_cast<std::streamsize>
|
||||
(_buffer.size ()));
|
||||
count_ = _stream->gcount ();
|
||||
_start_token = _start_buffer;
|
||||
_end_buffer = _start_buffer + count_;
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
end_token_ = _start_token +
|
||||
(end_token_ - old_start_token_);
|
||||
}
|
||||
|
||||
curr_ = _start_token + (curr_ - old_start_token_);
|
||||
}
|
||||
|
||||
return success_;
|
||||
}
|
||||
|
||||
// Disallow copying of buffer
|
||||
basic_file_input (const basic_file_input &);
|
||||
const basic_file_input &operator = (const basic_file_input &);
|
||||
};
|
||||
|
||||
typedef basic_file_input<char> file_input;
|
||||
typedef basic_file_input<wchar_t> wfile_input;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,537 @@
|
||||
// generate_cpp_code.hpp
|
||||
// Copyright (c) 2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_GENERATE_CPP_CODE_HPP
|
||||
#define BOOST_LEXER_GENERATE_CPP_CODE_HPP
|
||||
|
||||
#include "char_traits.hpp"
|
||||
#include "consts.hpp"
|
||||
#include <iostream>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include "runtime_error.hpp"
|
||||
#include "size_t.hpp"
|
||||
#include "state_machine.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT>
|
||||
void generate_cpp (const basic_state_machine<CharT> &sm_, std::ostream &os_,
|
||||
const bool use_pointers_ = false, const bool skip_unknown_ = true,
|
||||
const bool optimise_parameters_ = true, const char *name_ = "next_token")
|
||||
{
|
||||
if (sm_._lookup->size () == 0)
|
||||
{
|
||||
throw runtime_error ("Cannot generate code from an empty state machine");
|
||||
}
|
||||
|
||||
std::string upper_name_ (__DATE__);
|
||||
const std::size_t lookups_ = sm_._lookup->front ()->size ();
|
||||
const std::size_t dfas_ = sm_._dfa->size ();
|
||||
std::string::size_type pos_ = upper_name_.find (' ');
|
||||
const char *iterator_ = 0;
|
||||
|
||||
if (use_pointers_)
|
||||
{
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
iterator_ = "const char *";
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator_ = "const wchar_t *";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator_ = "Iterator &";
|
||||
}
|
||||
|
||||
while (pos_ != std::string::npos)
|
||||
{
|
||||
upper_name_.replace (pos_, 1, "_");
|
||||
pos_ = upper_name_.find (' ', pos_);
|
||||
}
|
||||
|
||||
upper_name_ += '_';
|
||||
upper_name_ += __TIME__;
|
||||
|
||||
pos_ = upper_name_.find (':');
|
||||
|
||||
while (pos_ != std::string::npos)
|
||||
{
|
||||
upper_name_.erase (pos_, 1);
|
||||
pos_ = upper_name_.find (':', pos_);
|
||||
}
|
||||
|
||||
upper_name_ = '_' + upper_name_;
|
||||
upper_name_ = name_ + upper_name_;
|
||||
std::transform (upper_name_.begin (), upper_name_.end (),
|
||||
upper_name_.begin (), ::toupper);
|
||||
os_ << "#ifndef " << upper_name_ + '\n';
|
||||
os_ << "#define " << upper_name_ + '\n';
|
||||
os_ << "// Copyright (c) 2008 Ben Hanson\n";
|
||||
os_ << "//\n";
|
||||
os_ << "// Distributed under the Boost Software License, "
|
||||
"Version 1.0. (See accompanying\n";
|
||||
os_ << "// file licence_1_0.txt or copy at "
|
||||
"http://www.boost.org/LICENSE_1_0.txt)\n\n";
|
||||
os_ << "// Auto-generated by boost::lexer\n";
|
||||
os_ << "template<typename Iterator>\n";
|
||||
os_ << "std::size_t " << name_ << " (";
|
||||
|
||||
if (dfas_ > 1 || !optimise_parameters_)
|
||||
{
|
||||
os_ << "std::size_t &start_state_, ";
|
||||
}
|
||||
|
||||
if (sm_._seen_BOL_assertion || !optimise_parameters_)
|
||||
{
|
||||
if (use_pointers_)
|
||||
{
|
||||
os_ << iterator_ << " const ";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << "const " << iterator_;
|
||||
}
|
||||
|
||||
os_ << "start_, ";
|
||||
}
|
||||
|
||||
if (dfas_ > 1 || sm_._seen_BOL_assertion || !optimise_parameters_)
|
||||
{
|
||||
os_ << "\n ";
|
||||
}
|
||||
|
||||
if (use_pointers_)
|
||||
{
|
||||
os_ << iterator_ << " &";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << iterator_;
|
||||
}
|
||||
|
||||
os_ << "start_token_, ";
|
||||
|
||||
if (use_pointers_)
|
||||
{
|
||||
os_ << iterator_ << " const ";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << "const " << iterator_;
|
||||
}
|
||||
|
||||
os_ << "end_)\n";
|
||||
os_ << "{\n";
|
||||
os_ << " enum {end_state_index, id_index, state_index, bol_index, "
|
||||
"eol_index,\n";
|
||||
os_ << " dead_state_index, dfa_offset};\n";
|
||||
os_ << " static const std::size_t npos = static_cast"
|
||||
"<std::size_t>(~0);\n";
|
||||
|
||||
if (dfas_ > 1)
|
||||
{
|
||||
std::size_t state_ = 0;
|
||||
|
||||
for (; state_ < dfas_; ++state_)
|
||||
{
|
||||
std::size_t i_ = 0;
|
||||
std::size_t j_ = 1;
|
||||
std::size_t count_ = lookups_ / 8;
|
||||
const std::size_t *lookup_ = &sm_._lookup[state_]->front ();
|
||||
const std::size_t *dfa_ = &sm_._dfa[state_]->front ();
|
||||
|
||||
os_ << " static const std::size_t lookup" << state_ << "_[" <<
|
||||
lookups_ << "] = {";
|
||||
|
||||
for (; i_ < count_; ++i_)
|
||||
{
|
||||
const std::size_t index_ = i_ * 8;
|
||||
|
||||
os_ << lookup_[index_];
|
||||
|
||||
for (; j_ < 8; ++j_)
|
||||
{
|
||||
os_ << ", " << lookup_[index_ + j_];
|
||||
}
|
||||
|
||||
if (i_ < count_ - 1)
|
||||
{
|
||||
os_ << "," << std::endl << " ";
|
||||
}
|
||||
|
||||
j_ = 1;
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
count_ = sm_._dfa[state_]->size ();
|
||||
os_ << " static const std::size_t dfa" << state_ << "_[" <<
|
||||
count_ << "] = {";
|
||||
count_ /= 8;
|
||||
|
||||
for (i_ = 0; i_ < count_; ++i_)
|
||||
{
|
||||
const std::size_t index_ = i_ * 8;
|
||||
|
||||
os_ << dfa_[index_];
|
||||
|
||||
for (j_ = 1; j_ < 8; ++j_)
|
||||
{
|
||||
os_ << ", " << dfa_[index_ + j_];
|
||||
}
|
||||
|
||||
if (i_ < count_ - 1)
|
||||
{
|
||||
os_ << "," << std::endl << " ";
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t mod_ = sm_._dfa[state_]->size () % 8;
|
||||
|
||||
if (mod_)
|
||||
{
|
||||
const std::size_t index_ = count_ * 8;
|
||||
|
||||
if (count_)
|
||||
{
|
||||
os_ << ",\n ";
|
||||
}
|
||||
|
||||
os_ << dfa_[index_];
|
||||
|
||||
for (j_ = 1; j_ < mod_; ++j_)
|
||||
{
|
||||
os_ << ", " << dfa_[index_ + j_];
|
||||
}
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
}
|
||||
|
||||
std::size_t count_ = sm_._dfa_alphabet.size ();
|
||||
std::size_t i_ = 1;
|
||||
|
||||
os_ << " static const std::size_t *lookup_arr_[" << count_ <<
|
||||
"] = {";
|
||||
os_ << "lookup0_";
|
||||
|
||||
for (i_ = 1; i_ < count_; ++i_)
|
||||
{
|
||||
os_ << ", " << "lookup" << i_ << "_";
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
os_ << " static const std::size_t dfa_alphabet_arr_[" << count_ <<
|
||||
"] = {";
|
||||
os_ << sm_._dfa_alphabet.front ();
|
||||
|
||||
for (i_ = 1; i_ < count_; ++i_)
|
||||
{
|
||||
os_ << ", " << sm_._dfa_alphabet[i_];
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
os_ << " static const std::size_t *dfa_arr_[" << count_ <<
|
||||
"] = {";
|
||||
os_ << "dfa0_";
|
||||
|
||||
for (i_ = 1; i_ < count_; ++i_)
|
||||
{
|
||||
os_ << ", " << "dfa" << i_ << "_";
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::size_t *lookup_ = &sm_._lookup[0]->front ();
|
||||
const std::size_t *dfa_ = &sm_._dfa[0]->front ();
|
||||
std::size_t i_ = 0;
|
||||
std::size_t j_ = 1;
|
||||
std::size_t count_ = lookups_ / 8;
|
||||
|
||||
os_ << " static const std::size_t lookup_[";
|
||||
os_ << sm_._lookup[0]->size () << "] = {";
|
||||
|
||||
for (; i_ < count_; ++i_)
|
||||
{
|
||||
const std::size_t index_ = i_ * 8;
|
||||
|
||||
os_ << lookup_[index_];
|
||||
|
||||
for (; j_ < 8; ++j_)
|
||||
{
|
||||
os_ << ", " << lookup_[index_ + j_];
|
||||
}
|
||||
|
||||
if (i_ < count_ - 1)
|
||||
{
|
||||
os_ << "," << std::endl << " ";
|
||||
}
|
||||
|
||||
j_ = 1;
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
os_ << " static const std::size_t dfa_alphabet_ = " <<
|
||||
sm_._dfa_alphabet.front () << ";\n";
|
||||
os_ << " static const std::size_t dfa_[" <<
|
||||
sm_._dfa[0]->size () << "] = {";
|
||||
count_ = sm_._dfa[0]->size () / 8;
|
||||
|
||||
for (i_ = 0; i_ < count_; ++i_)
|
||||
{
|
||||
const std::size_t index_ = i_ * 8;
|
||||
|
||||
os_ << dfa_[index_];
|
||||
|
||||
for (j_ = 1; j_ < 8; ++j_)
|
||||
{
|
||||
os_ << ", " << dfa_[index_ + j_];
|
||||
}
|
||||
|
||||
if (i_ < count_ - 1)
|
||||
{
|
||||
os_ << "," << std::endl << " ";
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t mod_ = sm_._dfa[0]->size () % 8;
|
||||
|
||||
if (mod_)
|
||||
{
|
||||
const std::size_t index_ = count_ * 8;
|
||||
|
||||
if (count_)
|
||||
{
|
||||
os_ << ",\n ";
|
||||
}
|
||||
|
||||
os_ << dfa_[index_];
|
||||
|
||||
for (j_ = 1; j_ < mod_; ++j_)
|
||||
{
|
||||
os_ << ", " << dfa_[index_ + j_];
|
||||
}
|
||||
}
|
||||
|
||||
os_ << "};\n";
|
||||
}
|
||||
|
||||
os_ << "\n if (start_token_ == end_) return 0;\n\n";
|
||||
|
||||
if (dfas_ > 1)
|
||||
{
|
||||
os_ << "again:\n";
|
||||
os_ << " const std::size_t * lookup_ = lookup_arr_[start_state_];\n";
|
||||
os_ << " std::size_t dfa_alphabet_ = dfa_alphabet_arr_[start_state_];\n";
|
||||
os_ << " const std::size_t *dfa_ = dfa_arr_[start_state_];\n";
|
||||
}
|
||||
|
||||
os_ << " const std::size_t *ptr_ = dfa_ + dfa_alphabet_;\n";
|
||||
os_ << " Iterator curr_ = start_token_;\n";
|
||||
os_ << " bool end_state_ = *ptr_ != 0;\n";
|
||||
os_ << " std::size_t id_ = *(ptr_ + id_index);\n";
|
||||
os_ << " Iterator end_token_ = start_token_;\n";
|
||||
os_ << '\n';
|
||||
os_ << " while (curr_ != end_)\n";
|
||||
os_ << " {\n";
|
||||
|
||||
if (sm_._seen_BOL_assertion)
|
||||
{
|
||||
os_ << " const std::size_t BOL_state_ = ptr_[bol_index];\n";
|
||||
}
|
||||
|
||||
if (sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << " const std::size_t EOL_state_ = ptr_[eol_index];\n";
|
||||
}
|
||||
|
||||
if (sm_._seen_BOL_assertion || sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << '\n';
|
||||
}
|
||||
|
||||
if (sm_._seen_BOL_assertion && sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << " if (BOL_state_ && (start_token_ == start_ ||\n";
|
||||
os_ << " *(start_token_ - 1) == '\\n'))\n";
|
||||
os_ << " {\n";
|
||||
os_ << " ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
os_ << " else if (EOL_state_ && *curr_ == '\\n')\n";
|
||||
os_ << " {\n";
|
||||
os_ << " ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
os_ << " else\n";
|
||||
os_ << " {\n";
|
||||
os_ << " const std::size_t state_ =\n";
|
||||
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
os_ << " ptr_[lookup_[static_cast<unsigned char>\n";
|
||||
os_ << " (*curr_++)]];\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << " ptr_[lookup_[*curr_++]];\n";
|
||||
}
|
||||
|
||||
os_ << '\n';
|
||||
os_ << " if (state_ == 0) break;\n";
|
||||
os_ << '\n';
|
||||
os_ << " ptr_ = &dfa_[state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
}
|
||||
else if (sm_._seen_BOL_assertion)
|
||||
{
|
||||
os_ << " if (BOL_state_ && (start_token_ == start_ ||\n";
|
||||
os_ << " *(start_token_ - 1) == '\\n'))\n";
|
||||
os_ << " {\n";
|
||||
os_ << " ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
os_ << " else\n";
|
||||
os_ << " {\n";
|
||||
os_ << " const std::size_t state_ =\n";
|
||||
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
os_ << " ptr_[lookup_[static_cast<unsigned char>\n";
|
||||
os_ << " (*curr_++)]];\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << " ptr_[lookup_[*curr_++]];\n";
|
||||
}
|
||||
|
||||
os_ << '\n';
|
||||
os_ << " if (state_ == 0) break;\n";
|
||||
os_ << '\n';
|
||||
os_ << " ptr_ = &dfa_[state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
}
|
||||
else if (sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << " if (EOL_state_ && *curr_ == '\\n')\n";
|
||||
os_ << " {\n";
|
||||
os_ << " ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
os_ << " else\n";
|
||||
os_ << " {\n";
|
||||
os_ << " const std::size_t state_ =\n";
|
||||
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
os_ << " ptr_[lookup_[static_cast<unsigned char>\n";
|
||||
os_ << " (*curr_++)]];\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << " ptr_[lookup_[*curr_++]];\n";
|
||||
}
|
||||
|
||||
os_ << '\n';
|
||||
os_ << " if (state_ == 0) break;\n";
|
||||
os_ << '\n';
|
||||
os_ << " ptr_ = &dfa_[state_ * dfa_alphabet_];\n";
|
||||
os_ << " }\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << " const std::size_t state_ =\n";
|
||||
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
os_ << " ptr_[lookup_[static_cast<unsigned char>\n";
|
||||
os_ << " (*curr_++)]];\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os_ << " ptr_[lookup_[*curr_++]];\n";
|
||||
}
|
||||
|
||||
os_ << '\n';
|
||||
os_ << " if (state_ == 0) break;\n";
|
||||
os_ << '\n';
|
||||
os_ << " ptr_ = &dfa_[state_ * dfa_alphabet_];\n";
|
||||
}
|
||||
|
||||
os_ << '\n';
|
||||
os_ << " if (*ptr_)\n";
|
||||
os_ << " {\n";
|
||||
os_ << " end_state_ = true;\n";
|
||||
os_ << " id_ = *(ptr_ + id_index);\n";
|
||||
|
||||
if (dfas_ > 1)
|
||||
{
|
||||
os_ << " start_state_ = *(ptr_ + state_index);\n";
|
||||
}
|
||||
|
||||
os_ << " end_token_ = curr_;\n";
|
||||
os_ << " }\n";
|
||||
os_ << " }\n";
|
||||
os_ << '\n';
|
||||
|
||||
if (sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << " const std::size_t EOL_state_ = ptr_[eol_index];\n";
|
||||
os_ << '\n';
|
||||
os_ << " if (EOL_state_ && curr_ == end_)\n";
|
||||
os_ << " {\n";
|
||||
os_ << " ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];\n";
|
||||
os_ << '\n';
|
||||
os_ << " if (*ptr_)\n";
|
||||
os_ << " {\n";
|
||||
os_ << " end_state_ = true;\n";
|
||||
os_ << " id_ = *(ptr_ + id_index);\n";
|
||||
|
||||
if (dfas_ > 1)
|
||||
{
|
||||
os_ << " start_state_ = *(ptr_ + state_index);\n";
|
||||
}
|
||||
|
||||
os_ << " end_token_ = curr_;\n";
|
||||
os_ << " }\n";
|
||||
os_ << " }\n";
|
||||
os_ << '\n';
|
||||
}
|
||||
|
||||
os_ << " if (end_state_)\n";
|
||||
os_ << " {\n";
|
||||
os_ << " // return longest match\n";
|
||||
os_ << " start_token_ = end_token_;\n";
|
||||
|
||||
if (dfas_ > 1)
|
||||
{
|
||||
os_ << '\n';
|
||||
os_ << " if (id_ == 0) goto again;\n";
|
||||
}
|
||||
|
||||
os_ << " }\n";
|
||||
os_ << " else\n";
|
||||
os_ << " {\n";
|
||||
|
||||
if (skip_unknown_)
|
||||
{
|
||||
os_ << " // No match causes char to be skipped\n";
|
||||
os_ << " ++start_token_;\n";
|
||||
}
|
||||
|
||||
os_ << " id_ = npos;\n";
|
||||
os_ << " }\n";
|
||||
os_ << '\n';
|
||||
os_ << " return id_;\n";
|
||||
os_ << "}\n";
|
||||
os_ << "\n#endif\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,818 @@
|
||||
// generator.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_GENERATOR_HPP
|
||||
#define BOOST_LEXER_GENERATOR_HPP
|
||||
|
||||
#include "char_traits.hpp"
|
||||
// memcmp()
|
||||
#include <cstring>
|
||||
#include "partition/charset.hpp"
|
||||
#include "partition/equivset.hpp"
|
||||
#include <memory>
|
||||
#include "parser/tree/node.hpp"
|
||||
#include "parser/parser.hpp"
|
||||
#include "containers/ptr_list.hpp"
|
||||
#include "rules.hpp"
|
||||
#include "state_machine.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT, typename Traits = char_traits<CharT> >
|
||||
class basic_generator
|
||||
{
|
||||
public:
|
||||
typedef typename basic_state_machine<CharT>::size_t_vector size_t_vector;
|
||||
typedef basic_rules<CharT> rules;
|
||||
|
||||
static void build (const rules &rules_, basic_state_machine<CharT> &state_machine_)
|
||||
{
|
||||
std::size_t index_ = 0;
|
||||
std::size_t size_ = rules_.statemap ().size ();
|
||||
node_ptr_vector node_ptr_vector_;
|
||||
|
||||
state_machine_.clear ();
|
||||
|
||||
for (; index_ < size_; ++index_)
|
||||
{
|
||||
state_machine_._lookup->push_back (0);
|
||||
state_machine_._lookup->back () = new size_t_vector;
|
||||
state_machine_._dfa_alphabet.push_back (0);
|
||||
state_machine_._dfa->push_back (0);
|
||||
state_machine_._dfa->back () = new size_t_vector;
|
||||
}
|
||||
|
||||
for (index_ = 0, size_ = state_machine_._lookup->size ();
|
||||
index_ < size_; ++index_)
|
||||
{
|
||||
state_machine_._lookup[index_]->resize (sizeof (CharT) == 1 ?
|
||||
num_chars : num_wchar_ts, dead_state_index);
|
||||
|
||||
if (!rules_.regexes ()[index_].empty ())
|
||||
{
|
||||
// vector mapping token indexes to partitioned token index sets
|
||||
index_set_vector set_mapping_;
|
||||
// syntax tree
|
||||
detail::node *root_ = build_tree (rules_, index_,
|
||||
node_ptr_vector_, state_machine_._lookup[index_],
|
||||
set_mapping_, state_machine_._dfa_alphabet[index_],
|
||||
state_machine_._seen_BOL_assertion,
|
||||
state_machine_._seen_EOL_assertion);
|
||||
|
||||
build_dfa (root_, set_mapping_,
|
||||
state_machine_._dfa_alphabet[index_],
|
||||
*state_machine_._dfa[index_]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void minimise (basic_state_machine<CharT> &state_machine_)
|
||||
{
|
||||
const std::size_t machines_ = state_machine_._dfa->size ();
|
||||
|
||||
for (std::size_t i_ = 0; i_ < machines_; ++i_)
|
||||
{
|
||||
const std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[i_];
|
||||
size_t_vector *dfa_ = state_machine_._dfa[i_];
|
||||
|
||||
if (dfa_alphabet_ != 0)
|
||||
{
|
||||
std::size_t size_ = 0;
|
||||
|
||||
do
|
||||
{
|
||||
size_ = dfa_->size ();
|
||||
minimise_dfa (dfa_alphabet_, *dfa_, size_);
|
||||
} while (dfa_->size () != size_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef detail::basic_charset<CharT> charset;
|
||||
typedef detail::ptr_list<charset> charset_list;
|
||||
typedef std::auto_ptr<charset> charset_ptr;
|
||||
typedef detail::equivset equivset;
|
||||
typedef detail::ptr_list<equivset> equivset_list;
|
||||
typedef std::auto_ptr<equivset> equivset_ptr;
|
||||
typedef typename charset::index_set index_set;
|
||||
typedef std::vector<index_set> index_set_vector;
|
||||
typedef detail::basic_parser<CharT> parser;
|
||||
typedef typename parser::node_ptr_vector node_ptr_vector;
|
||||
typedef std::set<const detail::node *> node_set;
|
||||
typedef detail::ptr_vector<node_set> node_set_vector;
|
||||
typedef std::vector<const detail::node *> node_vector;
|
||||
typedef detail::ptr_vector<node_vector> node_vector_vector;
|
||||
typedef typename parser::string string;
|
||||
typedef std::pair<string, string> string_pair;
|
||||
typedef typename parser::tokeniser::string_token string_token;
|
||||
typedef std::deque<string_pair> macro_deque;
|
||||
typedef std::pair<string, const detail::node *> macro_pair;
|
||||
typedef typename parser::macro_map::iterator macro_iter;
|
||||
typedef std::pair<macro_iter, bool> macro_iter_pair;
|
||||
typedef typename parser::tokeniser::token_map token_map;
|
||||
|
||||
static detail::node *build_tree (const rules &rules_,
|
||||
const std::size_t state_, node_ptr_vector &node_ptr_vector_,
|
||||
size_t_vector *lookup_, index_set_vector &set_mapping_,
|
||||
std::size_t &dfa_alphabet_, bool &seen_BOL_assertion_,
|
||||
bool &seen_EOL_assertion_)
|
||||
{
|
||||
const typename rules::string_deque_deque ®exes_ =
|
||||
rules_.regexes ();
|
||||
const typename rules::id_vector_deque &ids_ = rules_.ids ();
|
||||
const typename rules::id_vector_deque &states_ = rules_.states ();
|
||||
typename rules::string_deque::const_iterator regex_iter_ =
|
||||
regexes_[state_].begin ();
|
||||
typename rules::string_deque::const_iterator regex_iter_end_ =
|
||||
regexes_[state_].end ();
|
||||
typename rules::id_vector::const_iterator ids_iter_ =
|
||||
ids_[state_].begin ();
|
||||
typename rules::id_vector::const_iterator states_iter_ =
|
||||
states_[state_].begin ();
|
||||
const typename rules::string ®ex_ = *regex_iter_;
|
||||
// map of regex charset tokens (strings) to index
|
||||
token_map token_map_;
|
||||
const typename rules::string_pair_deque ¯odeque_ =
|
||||
rules_.macrodeque ();
|
||||
typename parser::macro_map macromap_;
|
||||
typename detail::node::node_vector tree_vector_;
|
||||
|
||||
build_macros (token_map_, macrodeque_, macromap_,
|
||||
rules_.flags (), rules_.locale (), node_ptr_vector_,
|
||||
seen_BOL_assertion_, seen_EOL_assertion_);
|
||||
|
||||
detail::node *root_ = parser::parse (regex_.c_str (),
|
||||
regex_.c_str () + regex_.size (), *ids_iter_, *states_iter_,
|
||||
rules_.flags (), rules_.locale (), node_ptr_vector_, macromap_,
|
||||
token_map_, seen_BOL_assertion_, seen_EOL_assertion_);
|
||||
|
||||
++regex_iter_;
|
||||
++ids_iter_;
|
||||
++states_iter_;
|
||||
tree_vector_.push_back (root_);
|
||||
|
||||
// build syntax trees
|
||||
while (regex_iter_ != regex_iter_end_)
|
||||
{
|
||||
// re-declare var, otherwise we perform an assignment..!
|
||||
const typename rules::string ®ex_ = *regex_iter_;
|
||||
|
||||
root_ = parser::parse (regex_.c_str (),
|
||||
regex_.c_str () + regex_.size (), *ids_iter_,
|
||||
*states_iter_, rules_.flags (), rules_.locale (),
|
||||
node_ptr_vector_, macromap_, token_map_,
|
||||
seen_BOL_assertion_, seen_EOL_assertion_);
|
||||
tree_vector_.push_back (root_);
|
||||
++regex_iter_;
|
||||
++ids_iter_;
|
||||
++states_iter_;
|
||||
}
|
||||
|
||||
if (seen_BOL_assertion_)
|
||||
{
|
||||
// Fixup BOLs
|
||||
typename detail::node::node_vector::iterator iter_ =
|
||||
tree_vector_.begin ();
|
||||
typename detail::node::node_vector::iterator end_ =
|
||||
tree_vector_.end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
fixup_bol (*iter_, node_ptr_vector_);
|
||||
}
|
||||
}
|
||||
|
||||
// join trees
|
||||
{
|
||||
typename detail::node::node_vector::iterator iter_ =
|
||||
tree_vector_.begin ();
|
||||
typename detail::node::node_vector::iterator end_ =
|
||||
tree_vector_.end ();
|
||||
|
||||
if (iter_ != end_)
|
||||
{
|
||||
root_ = *iter_;
|
||||
++iter_;
|
||||
}
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new detail::selection_node
|
||||
(root_, *iter_);
|
||||
root_ = node_ptr_vector_->back ();
|
||||
}
|
||||
}
|
||||
|
||||
// partitioned token list
|
||||
charset_list token_list_;
|
||||
|
||||
set_mapping_.resize (token_map_.size ());
|
||||
partition_tokens (token_map_, token_list_);
|
||||
|
||||
typename charset_list::list::const_iterator iter_ =
|
||||
token_list_->begin ();
|
||||
typename charset_list::list::const_iterator end_ =
|
||||
token_list_->end ();
|
||||
std::size_t index_ = 0;
|
||||
|
||||
for (; iter_ != end_; ++iter_, ++index_)
|
||||
{
|
||||
const charset *cs_ = *iter_;
|
||||
typename charset::index_set::const_iterator set_iter_ =
|
||||
cs_->_index_set.begin ();
|
||||
typename charset::index_set::const_iterator set_end_ =
|
||||
cs_->_index_set.end ();
|
||||
|
||||
fill_lookup (cs_->_token, lookup_, index_);
|
||||
|
||||
for (; set_iter_ != set_end_; ++set_iter_)
|
||||
{
|
||||
set_mapping_[*set_iter_].insert (index_);
|
||||
}
|
||||
}
|
||||
|
||||
dfa_alphabet_ = token_list_->size () + dfa_offset;
|
||||
return root_;
|
||||
}
|
||||
|
||||
static void build_macros (token_map &token_map_,
|
||||
const macro_deque ¯odeque_,
|
||||
typename parser::macro_map ¯omap_, const regex_flags flags_,
|
||||
const std::locale &locale_, node_ptr_vector &node_ptr_vector_,
|
||||
bool &seen_BOL_assertion_, bool &seen_EOL_assertion_)
|
||||
{
|
||||
for (typename macro_deque::const_iterator iter_ =
|
||||
macrodeque_.begin (), end_ = macrodeque_.end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
const typename rules::string &name_ = iter_->first;
|
||||
const typename rules::string ®ex_ = iter_->second;
|
||||
detail::node *node_ = parser::parse (regex_.c_str (),
|
||||
regex_.c_str () + regex_.size (), 0, 0, flags_,
|
||||
locale_, node_ptr_vector_, macromap_, token_map_,
|
||||
seen_BOL_assertion_, seen_EOL_assertion_);
|
||||
macro_iter_pair map_iter_ = macromap_.
|
||||
insert (macro_pair (name_, 0));
|
||||
|
||||
map_iter_.first->second = node_;
|
||||
}
|
||||
}
|
||||
|
||||
static void build_dfa (detail::node *root_,
|
||||
const index_set_vector &set_mapping_, const std::size_t dfa_alphabet_,
|
||||
size_t_vector &dfa_)
|
||||
{
|
||||
typename detail::node::node_vector *followpos_ =
|
||||
&root_->firstpos ();
|
||||
node_set_vector seen_sets_;
|
||||
node_vector_vector seen_vectors_;
|
||||
size_t_vector hash_vector_;
|
||||
|
||||
// 'jam' state
|
||||
dfa_.resize (dfa_alphabet_, 0);
|
||||
closure (followpos_, seen_sets_, seen_vectors_,
|
||||
hash_vector_, dfa_alphabet_, dfa_);
|
||||
|
||||
std::size_t *ptr_ = 0;
|
||||
|
||||
for (std::size_t index_ = 0; index_ < seen_vectors_->size (); ++index_)
|
||||
{
|
||||
equivset_list equiv_list_;
|
||||
|
||||
build_equiv_list (seen_vectors_[index_], set_mapping_, equiv_list_);
|
||||
|
||||
for (typename equivset_list::list::const_iterator iter_ =
|
||||
equiv_list_->begin (), end_ = equiv_list_->end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
equivset *equivset_ = *iter_;
|
||||
const std::size_t transition_ = closure (&equivset_->_followpos,
|
||||
seen_sets_, seen_vectors_, hash_vector_, dfa_alphabet_, dfa_);
|
||||
|
||||
if (transition_ != npos)
|
||||
{
|
||||
ptr_ = &dfa_.front () + ((index_ + 1) * dfa_alphabet_);
|
||||
|
||||
// Prune abstemious transitions from end states.
|
||||
if (*ptr_ && !equivset_->_greedy) continue;
|
||||
|
||||
for (typename detail::equivset::index_vector::const_iterator
|
||||
equiv_iter_ = equivset_->_index_vector.begin (),
|
||||
equiv_end_ = equivset_->_index_vector.end ();
|
||||
equiv_iter_ != equiv_end_; ++equiv_iter_)
|
||||
{
|
||||
const std::size_t index_ = *equiv_iter_;
|
||||
|
||||
if (index_ == bol_token)
|
||||
{
|
||||
if (ptr_[eol_index] == 0)
|
||||
{
|
||||
ptr_[bol_index] = transition_;
|
||||
}
|
||||
}
|
||||
else if (index_ == eol_token)
|
||||
{
|
||||
if (ptr_[bol_index] == 0)
|
||||
{
|
||||
ptr_[eol_index] = transition_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr_[index_ + dfa_offset] = transition_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::size_t closure (typename detail::node::node_vector *followpos_,
|
||||
node_set_vector &seen_sets_, node_vector_vector &seen_vectors_,
|
||||
size_t_vector &hash_vector_, const std::size_t size_, size_t_vector &dfa_)
|
||||
{
|
||||
bool end_state_ = false;
|
||||
std::size_t id_ = 0;
|
||||
std::size_t state_ = 0;
|
||||
std::size_t hash_ = 0;
|
||||
|
||||
if (followpos_->empty ()) return npos;
|
||||
|
||||
std::size_t index_ = 0;
|
||||
std::auto_ptr<node_set> set_ptr_ (new node_set);
|
||||
std::auto_ptr<node_vector> vector_ptr_ (new node_vector);
|
||||
|
||||
for (typename detail::node::node_vector::const_iterator iter_ =
|
||||
followpos_->begin (), end_ = followpos_->end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
closure_ex (*iter_, end_state_, id_, state_, set_ptr_.get (),
|
||||
vector_ptr_.get (), hash_);
|
||||
}
|
||||
|
||||
bool found_ = false;
|
||||
typename size_t_vector::const_iterator hash_iter_ =
|
||||
hash_vector_.begin ();
|
||||
typename size_t_vector::const_iterator hash_end_ =
|
||||
hash_vector_.end ();
|
||||
typename node_set_vector::vector::const_iterator set_iter_ =
|
||||
seen_sets_->begin ();
|
||||
|
||||
for (; hash_iter_ != hash_end_; ++hash_iter_, ++set_iter_)
|
||||
{
|
||||
found_ = *hash_iter_ == hash_ && *(*set_iter_) == *set_ptr_;
|
||||
++index_;
|
||||
|
||||
if (found_) break;
|
||||
}
|
||||
|
||||
if (!found_)
|
||||
{
|
||||
seen_sets_->push_back (0);
|
||||
seen_sets_->back () = set_ptr_.release ();
|
||||
seen_vectors_->push_back (0);
|
||||
seen_vectors_->back () = vector_ptr_.release ();
|
||||
hash_vector_.push_back (hash_);
|
||||
// State 0 is the jam state...
|
||||
index_ = seen_sets_->size ();
|
||||
|
||||
const std::size_t old_size_ = dfa_.size ();
|
||||
|
||||
dfa_.resize (old_size_ + size_, 0);
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
dfa_[old_size_] |= end_state;
|
||||
dfa_[old_size_ + id_index] = id_;
|
||||
dfa_[old_size_ + state_index] = state_;
|
||||
}
|
||||
}
|
||||
|
||||
return index_;
|
||||
}
|
||||
|
||||
static void closure_ex (detail::node *node_, bool &end_state_,
|
||||
std::size_t &id_, std::size_t &state_, node_set *set_ptr_,
|
||||
node_vector *vector_ptr_, std::size_t &hash_)
|
||||
{
|
||||
const bool temp_end_state_ = node_->end_state ();
|
||||
|
||||
if (temp_end_state_)
|
||||
{
|
||||
if (!end_state_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = node_->id ();
|
||||
state_ = node_->lexer_state ();
|
||||
}
|
||||
}
|
||||
|
||||
if (set_ptr_->insert (node_).second)
|
||||
{
|
||||
vector_ptr_->push_back (node_);
|
||||
hash_ += reinterpret_cast<std::size_t> (node_);
|
||||
}
|
||||
}
|
||||
|
||||
static void partition_tokens (const token_map &map_,
|
||||
charset_list &lhs_)
|
||||
{
|
||||
charset_list rhs_;
|
||||
|
||||
fill_rhs_list (map_, rhs_);
|
||||
|
||||
if (!rhs_->empty ())
|
||||
{
|
||||
typename charset_list::list::iterator iter_;
|
||||
typename charset_list::list::iterator end_;
|
||||
charset_ptr overlap_ (new charset);
|
||||
|
||||
lhs_->push_back (0);
|
||||
lhs_->back () = rhs_->front ();
|
||||
rhs_->pop_front ();
|
||||
|
||||
while (!rhs_->empty ())
|
||||
{
|
||||
charset_ptr r_ (rhs_->front ());
|
||||
|
||||
rhs_->pop_front ();
|
||||
iter_ = lhs_->begin ();
|
||||
end_ = lhs_->end ();
|
||||
|
||||
while (!r_->empty () && iter_ != end_)
|
||||
{
|
||||
typename charset_list::list::iterator l_iter_ = iter_;
|
||||
|
||||
(*l_iter_)->intersect (*r_.get (), *overlap_.get ());
|
||||
|
||||
if (overlap_->empty ())
|
||||
{
|
||||
++iter_;
|
||||
}
|
||||
else if ((*l_iter_)->empty ())
|
||||
{
|
||||
delete *l_iter_;
|
||||
*l_iter_ = overlap_.release ();
|
||||
|
||||
// VC++ 6 Hack:
|
||||
charset_ptr temp_overlap_ (new charset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
++iter_;
|
||||
}
|
||||
else if (r_->empty ())
|
||||
{
|
||||
delete r_.release ();
|
||||
r_ = overlap_;
|
||||
|
||||
// VC++ 6 Hack:
|
||||
charset_ptr temp_overlap_ (new charset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter_ = lhs_->insert (++iter_, 0);
|
||||
*iter_ = overlap_.release ();
|
||||
|
||||
// VC++ 6 Hack:
|
||||
charset_ptr temp_overlap_ (new charset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
++iter_;
|
||||
end_ = lhs_->end ();
|
||||
}
|
||||
}
|
||||
|
||||
if (!r_->empty ())
|
||||
{
|
||||
lhs_->push_back (0);
|
||||
lhs_->back () = r_.release ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_rhs_list (const token_map &map_,
|
||||
charset_list &list_)
|
||||
{
|
||||
typename parser::tokeniser::token_map::const_iterator iter_ =
|
||||
map_.begin ();
|
||||
typename parser::tokeniser::token_map::const_iterator end_ =
|
||||
map_.end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
list_->push_back (0);
|
||||
list_->back () = new charset (iter_->first, iter_->second);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_lookup (const string_token &token_,
|
||||
size_t_vector *lookup_, const std::size_t index_)
|
||||
{
|
||||
const CharT *curr_ = token_._charset.c_str ();
|
||||
const CharT *chars_end_ = curr_ + token_._charset.size ();
|
||||
std::size_t *ptr_ = &lookup_->front ();
|
||||
const std::size_t max_ = sizeof (CharT) == 1 ?
|
||||
num_chars : num_wchar_ts;
|
||||
|
||||
if (token_._negated)
|
||||
{
|
||||
CharT curr_char_ = sizeof (CharT) == 1 ? -128 : 0;
|
||||
std::size_t i_ = 0;
|
||||
|
||||
while (curr_ < chars_end_)
|
||||
{
|
||||
while (*curr_ > curr_char_)
|
||||
{
|
||||
ptr_[static_cast<typename Traits::index_type>
|
||||
(curr_char_)] = index_ + dfa_offset;
|
||||
++curr_char_;
|
||||
++i_;
|
||||
}
|
||||
|
||||
++curr_char_;
|
||||
++curr_;
|
||||
++i_;
|
||||
}
|
||||
|
||||
for (; i_ < max_; ++i_)
|
||||
{
|
||||
ptr_[static_cast<typename Traits::index_type>(curr_char_)] =
|
||||
index_ + dfa_offset;
|
||||
++curr_char_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (curr_ < chars_end_)
|
||||
{
|
||||
ptr_[static_cast<typename Traits::index_type>(*curr_)] =
|
||||
index_ + dfa_offset;
|
||||
++curr_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void build_equiv_list (const node_vector *vector_,
|
||||
const index_set_vector &set_mapping_, equivset_list &lhs_)
|
||||
{
|
||||
equivset_list rhs_;
|
||||
|
||||
fill_rhs_list (vector_, set_mapping_, rhs_);
|
||||
|
||||
if (!rhs_->empty ())
|
||||
{
|
||||
typename equivset_list::list::iterator iter_;
|
||||
typename equivset_list::list::iterator end_;
|
||||
equivset_ptr overlap_ (new equivset);
|
||||
|
||||
lhs_->push_back (0);
|
||||
lhs_->back () = rhs_->front ();
|
||||
rhs_->pop_front ();
|
||||
|
||||
while (!rhs_->empty ())
|
||||
{
|
||||
equivset_ptr r_ (rhs_->front ());
|
||||
|
||||
rhs_->pop_front ();
|
||||
iter_ = lhs_->begin ();
|
||||
end_ = lhs_->end ();
|
||||
|
||||
while (!r_->empty () && iter_ != end_)
|
||||
{
|
||||
typename equivset_list::list::iterator l_iter_ = iter_;
|
||||
|
||||
(*l_iter_)->intersect (*r_.get (), *overlap_.get ());
|
||||
|
||||
if (overlap_->empty ())
|
||||
{
|
||||
++iter_;
|
||||
}
|
||||
else if ((*l_iter_)->empty ())
|
||||
{
|
||||
delete *l_iter_;
|
||||
*l_iter_ = overlap_.release ();
|
||||
|
||||
// VC++ 6 Hack:
|
||||
equivset_ptr temp_overlap_ (new equivset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
++iter_;
|
||||
}
|
||||
else if (r_->empty ())
|
||||
{
|
||||
delete r_.release ();
|
||||
r_ = overlap_;
|
||||
|
||||
// VC++ 6 Hack:
|
||||
equivset_ptr temp_overlap_ (new equivset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter_ = lhs_->insert (++iter_, 0);
|
||||
*iter_ = overlap_.release ();
|
||||
|
||||
// VC++ 6 Hack:
|
||||
equivset_ptr temp_overlap_ (new equivset);
|
||||
|
||||
overlap_ = temp_overlap_;
|
||||
++iter_;
|
||||
end_ = lhs_->end ();
|
||||
}
|
||||
}
|
||||
|
||||
if (!r_->empty ())
|
||||
{
|
||||
lhs_->push_back (0);
|
||||
lhs_->back () = r_.release ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_rhs_list (const node_vector *vector_,
|
||||
const index_set_vector &set_mapping_, equivset_list &list_)
|
||||
{
|
||||
typename node_vector::const_iterator iter_ =
|
||||
vector_->begin ();
|
||||
typename node_vector::const_iterator end_ =
|
||||
vector_->end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
const detail::node *node_ = *iter_;
|
||||
|
||||
if (!node_->end_state ())
|
||||
{
|
||||
const std::size_t token_ = node_->token ();
|
||||
|
||||
if (token_ != null_token)
|
||||
{
|
||||
list_->push_back (0);
|
||||
|
||||
if (token_ == bol_token || token_ == eol_token)
|
||||
{
|
||||
std::set<std::size_t> index_set_;
|
||||
|
||||
index_set_.insert (token_);
|
||||
list_->back () = new equivset (index_set_,
|
||||
node_->greedy (), token_, node_->followpos ());
|
||||
}
|
||||
else
|
||||
{
|
||||
list_->back () = new equivset (set_mapping_[token_],
|
||||
node_->greedy (), token_, node_->followpos ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fixup_bol (detail::node * &root_,
|
||||
node_ptr_vector &node_ptr_vector_)
|
||||
{
|
||||
typename detail::node::node_vector *first_ = &root_->firstpos ();
|
||||
bool found_ = false;
|
||||
typename detail::node::node_vector::const_iterator iter_ =
|
||||
first_->begin ();
|
||||
typename detail::node::node_vector::const_iterator end_ =
|
||||
first_->end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
const detail::node *node_ = *iter_;
|
||||
|
||||
found_ = !node_->end_state () && node_->token () == bol_token;
|
||||
|
||||
if (found_) break;
|
||||
}
|
||||
|
||||
if (!found_)
|
||||
{
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new detail::leaf_node (bol_token, true);
|
||||
|
||||
detail::node *lhs_ = node_ptr_vector_->back ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new detail::leaf_node (null_token, true);
|
||||
|
||||
detail::node *rhs_ = node_ptr_vector_->back ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () =
|
||||
new detail::selection_node (lhs_, rhs_);
|
||||
lhs_ = node_ptr_vector_->back ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () =
|
||||
new detail::sequence_node (lhs_, root_);
|
||||
root_ = node_ptr_vector_->back ();
|
||||
}
|
||||
}
|
||||
|
||||
static void minimise_dfa (const std::size_t dfa_alphabet_,
|
||||
size_t_vector &dfa_, std::size_t size_)
|
||||
{
|
||||
const std::size_t *first_ = &dfa_.front ();
|
||||
const std::size_t *second_ = 0;
|
||||
const std::size_t *end_ = first_ + size_;
|
||||
std::size_t index_ = 1;
|
||||
std::size_t new_index_ = 1;
|
||||
std::size_t curr_index_ = 0;
|
||||
index_set index_set_;
|
||||
size_t_vector lookup_;
|
||||
std::size_t *lookup_ptr_ = 0;
|
||||
|
||||
lookup_.resize (size_ / dfa_alphabet_, null_token);
|
||||
lookup_ptr_ = &lookup_.front ();
|
||||
*lookup_ptr_ = 0;
|
||||
// Only one 'jam' state, so skip it.
|
||||
first_ += dfa_alphabet_;
|
||||
|
||||
for (; first_ < end_; first_ += dfa_alphabet_, ++index_)
|
||||
{
|
||||
for (second_ = first_ + dfa_alphabet_, curr_index_ = index_ + 1;
|
||||
second_ < end_; second_ += dfa_alphabet_, ++curr_index_)
|
||||
{
|
||||
if (index_set_.find (curr_index_) != index_set_.end ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Some systems have memcmp in namespace std.
|
||||
using namespace std;
|
||||
|
||||
if (memcmp (first_, second_, sizeof (std::size_t) *
|
||||
dfa_alphabet_) == 0)
|
||||
{
|
||||
index_set_.insert (curr_index_);
|
||||
lookup_ptr_[curr_index_] = new_index_;
|
||||
}
|
||||
}
|
||||
|
||||
if (lookup_ptr_[index_] == null_token)
|
||||
{
|
||||
lookup_ptr_[index_] = new_index_;
|
||||
++new_index_;
|
||||
}
|
||||
}
|
||||
|
||||
if (!index_set_.empty ())
|
||||
{
|
||||
const std::size_t *front_ = &dfa_.front ();
|
||||
size_t_vector new_dfa_ (front_, front_ + dfa_alphabet_);
|
||||
typename index_set::iterator set_end_ =
|
||||
index_set_.end ();
|
||||
const std::size_t *ptr_ = front_ + dfa_alphabet_;
|
||||
std::size_t *new_ptr_ = 0;
|
||||
|
||||
new_dfa_.resize (size_ - index_set_.size () * dfa_alphabet_, 0);
|
||||
new_ptr_ = &new_dfa_.front () + dfa_alphabet_;
|
||||
size_ /= dfa_alphabet_;
|
||||
|
||||
for (index_ = 1; index_ < size_; ++index_)
|
||||
{
|
||||
if (index_set_.find (index_) != set_end_)
|
||||
{
|
||||
ptr_ += dfa_alphabet_;
|
||||
continue;
|
||||
}
|
||||
|
||||
new_ptr_[end_state_index] = ptr_[end_state_index];
|
||||
new_ptr_[id_index] = ptr_[id_index];
|
||||
new_ptr_[state_index] = ptr_[state_index];
|
||||
new_ptr_[bol_index] = lookup_ptr_[ptr_[bol_index]];
|
||||
new_ptr_[eol_index] = lookup_ptr_[ptr_[eol_index]];
|
||||
new_ptr_ += dfa_offset;
|
||||
ptr_ += dfa_offset;
|
||||
|
||||
for (std::size_t i_ = dfa_offset; i_ < dfa_alphabet_; ++i_)
|
||||
{
|
||||
*new_ptr_++ = lookup_ptr_[*ptr_++];
|
||||
}
|
||||
}
|
||||
|
||||
dfa_.swap (new_dfa_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_generator<char> generator;
|
||||
typedef basic_generator<wchar_t> wgenerator;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,488 @@
|
||||
// input.hpp
|
||||
// Copyright (c) 2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_INPUT
|
||||
#define BOOST_LEXER_INPUT
|
||||
|
||||
#include "char_traits.hpp"
|
||||
#include <iterator>
|
||||
#include "size_t.hpp"
|
||||
#include "state_machine.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename FwdIter, typename Traits =
|
||||
char_traits<typename boost::detail::iterator_traits<FwdIter>::value_type> >
|
||||
class basic_input
|
||||
{
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend basic_input;
|
||||
#else
|
||||
friend class basic_input;
|
||||
#endif
|
||||
|
||||
struct data
|
||||
{
|
||||
std::size_t id;
|
||||
FwdIter start;
|
||||
FwdIter end;
|
||||
bool bol;
|
||||
std::size_t state;
|
||||
|
||||
// Construct in end() state.
|
||||
data () :
|
||||
id (0),
|
||||
bol (false),
|
||||
state (npos)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const data &rhs_) const
|
||||
{
|
||||
return id == rhs_.id && start == rhs_.start &&
|
||||
end == rhs_.end && bol == rhs_.bol && state == rhs_.state;
|
||||
}
|
||||
};
|
||||
|
||||
iterator () :
|
||||
_input (0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const iterator &rhs_) const
|
||||
{
|
||||
return _data == rhs_._data;
|
||||
}
|
||||
|
||||
bool operator != (const iterator &rhs_) const
|
||||
{
|
||||
return !(*this == rhs_);
|
||||
}
|
||||
|
||||
data &operator * ()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
data *operator -> ()
|
||||
{
|
||||
return &_data;
|
||||
}
|
||||
|
||||
// Let compiler generate operator = ().
|
||||
|
||||
// prefix version
|
||||
iterator &operator ++ ()
|
||||
{
|
||||
next_token ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// postfix version
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator iter_ = *this;
|
||||
|
||||
next_token ();
|
||||
return iter_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Not owner (obviously!)
|
||||
const basic_input *_input;
|
||||
data _data;
|
||||
|
||||
void next_token ()
|
||||
{
|
||||
_data.start = _data.end;
|
||||
|
||||
if (_input->_state_machine->_dfa->size () == 1)
|
||||
{
|
||||
if (_input->_state_machine->_seen_BOL_assertion ||
|
||||
_input->_state_machine->_seen_EOL_assertion)
|
||||
{
|
||||
_data.id = next
|
||||
(&_input->_state_machine->_lookup->front ()->front (),
|
||||
_input->_state_machine->_dfa_alphabet.front (),
|
||||
&_input->_state_machine->_dfa->front ()->front (),
|
||||
_data.bol, _data.end, _input->_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.id = next (&_input->_state_machine->_lookup->
|
||||
front ()->front (), _input->_state_machine->
|
||||
_dfa_alphabet.front (), &_input->_state_machine->
|
||||
_dfa->front ()->front (), _data.end, _input->_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_input->_state_machine->_seen_BOL_assertion ||
|
||||
_input->_state_machine->_seen_EOL_assertion)
|
||||
{
|
||||
_data.id = next (*_input->_state_machine, _data.state,
|
||||
_data.bol, _data.end, _input->_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.id = next (*_input->_state_machine, _data.state,
|
||||
_data.end, _input->_end);
|
||||
}
|
||||
}
|
||||
|
||||
if (_data.end == _input->_end && _data.start == _data.end)
|
||||
{
|
||||
// Ensure current state matches that returned by end().
|
||||
_data.state = npos;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t next (const basic_state_machine
|
||||
<typename Traits::char_type> &state_machine_,
|
||||
std::size_t &start_state_, bool bol_,
|
||||
FwdIter &start_token_, const FwdIter &end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
again:
|
||||
const std::size_t * lookup_ = &state_machine_._lookup[start_state_]->
|
||||
front ();
|
||||
std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[start_state_];
|
||||
const std::size_t *dfa_ = &state_machine_._dfa[start_state_]->front ();
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
FwdIter curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + id_index);
|
||||
bool end_bol_ = bol_;
|
||||
FwdIter end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
const std::size_t BOL_state_ = ptr_[bol_index];
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (BOL_state_ && bol_)
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
typename Traits::char_type prev_char_ = *curr_++;
|
||||
|
||||
bol_ = prev_char_ == '\n';
|
||||
|
||||
const std::size_t state_ =
|
||||
ptr_[lookup_[static_cast<typename Traits::index_type>
|
||||
(prev_char_)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
start_state_ = *(ptr_ + state_index);
|
||||
end_bol_ = bol_;
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
start_state_ = *(ptr_ + state_index);
|
||||
end_bol_ = bol_;
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
_data.bol = end_bol_;
|
||||
start_token_ = end_token_;
|
||||
|
||||
if (id_ == 0)
|
||||
{
|
||||
bol_ = _data.bol;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
_data.bol = *start_token_ == '\n';
|
||||
++start_token_;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
|
||||
std::size_t next (const basic_state_machine
|
||||
<typename Traits::char_type> &state_machine_,
|
||||
std::size_t &start_state_, FwdIter &start_token_,
|
||||
FwdIter const &end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
again:
|
||||
const std::size_t * lookup_ = &state_machine_._lookup[start_state_]->
|
||||
front ();
|
||||
std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[start_state_];
|
||||
const std::size_t *dfa_ = &state_machine_._dfa[start_state_]->front ();
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
FwdIter curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + id_index);
|
||||
FwdIter end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
const std::size_t state_ = ptr_[lookup_[static_cast
|
||||
<typename Traits::index_type>(*curr_++)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
start_state_ = *(ptr_ + state_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
start_token_ = end_token_;
|
||||
|
||||
if (id_ == 0) goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
++start_token_;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
|
||||
std::size_t next (const std::size_t * const lookup_,
|
||||
const std::size_t dfa_alphabet_, const std::size_t * const dfa_,
|
||||
bool bol_, FwdIter &start_token_, FwdIter const &end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
FwdIter curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + id_index);
|
||||
bool end_bol_ = bol_;
|
||||
FwdIter end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
const std::size_t BOL_state_ = ptr_[bol_index];
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (BOL_state_ && bol_)
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
typename Traits::char_type prev_char_ = *curr_++;
|
||||
|
||||
bol_ = prev_char_ == '\n';
|
||||
|
||||
const std::size_t state_ =
|
||||
ptr_[lookup_[static_cast<typename Traits::index_type>
|
||||
(prev_char_)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
end_bol_ = bol_;
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t EOL_state_ = ptr_[eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
end_bol_ = bol_;
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
start_token_ = end_token_;
|
||||
_data.bol = end_bol_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
_data.bol = *start_token_ == '\n';
|
||||
++start_token_;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
|
||||
std::size_t next (const std::size_t * const lookup_,
|
||||
const std::size_t dfa_alphabet_, const std::size_t * const dfa_,
|
||||
FwdIter &start_token_, FwdIter const &end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
FwdIter curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + id_index);
|
||||
FwdIter end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
const std::size_t state_ = ptr_[lookup_[static_cast
|
||||
<typename Traits::index_type>(*curr_++)]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + id_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_)
|
||||
{
|
||||
// return longest match
|
||||
start_token_ = end_token_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match causes char to be skipped
|
||||
++start_token_;
|
||||
id_ = npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend iterator;
|
||||
#else
|
||||
friend class iterator;
|
||||
#endif
|
||||
|
||||
// Make it explict that we are NOT taking a copy of state_machine_!
|
||||
basic_input (const basic_state_machine<typename Traits::char_type>
|
||||
*state_machine_, const FwdIter &begin_, const FwdIter &end_) :
|
||||
_state_machine (state_machine_),
|
||||
_begin (begin_),
|
||||
_end (end_)
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin () const
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._input = this;
|
||||
iter_._data.id = npos;
|
||||
iter_._data.start = _begin;
|
||||
iter_._data.end = _begin;
|
||||
iter_._data.bol = _state_machine->_seen_BOL_assertion;
|
||||
iter_._data.state = 0;
|
||||
++iter_;
|
||||
return iter_;
|
||||
}
|
||||
|
||||
iterator end () const
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._input = this;
|
||||
iter_._data.start = _end;
|
||||
iter_._data.end = _end;
|
||||
return iter_;
|
||||
}
|
||||
|
||||
private:
|
||||
const basic_state_machine<typename Traits::char_type> *_state_machine;
|
||||
FwdIter _begin;
|
||||
FwdIter _end;
|
||||
};
|
||||
|
||||
typedef basic_input<std::string::iterator> iter_input;
|
||||
typedef basic_input<std::wstring::iterator> iter_winput;
|
||||
typedef basic_input<const char *> ptr_input;
|
||||
typedef basic_input<const wchar_t *> ptr_winput;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,521 @@
|
||||
// parser.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_PARSER_HPP
|
||||
#define BOOST_LEXER_PARSER_HPP
|
||||
|
||||
#include <assert.h>
|
||||
#include "tree/end_node.hpp"
|
||||
#include "tree/iteration_node.hpp"
|
||||
#include "tree/leaf_node.hpp"
|
||||
#include "../runtime_error.hpp"
|
||||
#include "tree/selection_node.hpp"
|
||||
#include "tree/sequence_node.hpp"
|
||||
#include "../size_t.hpp"
|
||||
#include "tokeniser/re_tokeniser.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
class basic_parser
|
||||
{
|
||||
public:
|
||||
typedef basic_re_tokeniser<CharT> tokeniser;
|
||||
typedef typename tokeniser::string string;
|
||||
typedef std::map<string, const node *> macro_map;
|
||||
typedef node::node_ptr_vector node_ptr_vector;
|
||||
typedef typename tokeniser::num_token token;
|
||||
|
||||
/*
|
||||
General principles of regex parsing:
|
||||
- Every regex is a sequence of sub-regexes.
|
||||
- Regexes consist of operands and operators
|
||||
- All operators decompose to sequence, selection ('|') and iteration ('*')
|
||||
- Regex tokens are stored on the stack.
|
||||
- When a complete sequence of regex tokens is on the stack it is processed.
|
||||
|
||||
Grammar:
|
||||
|
||||
<REGEX> -> <OREXP>
|
||||
<OREXP> -> <SEQUENCE> | <OREXP>'|'<SEQUENCE>
|
||||
<SEQUENCE> -> <SUB>
|
||||
<SUB> -> <EXPRESSION> | <SUB><EXPRESSION>
|
||||
<EXPRESSION> -> <REPEAT>
|
||||
<REPEAT> -> charset | macro | '('<REGEX>')' | <REPEAT><DUPLICATE>
|
||||
<DUPLICATE> -> '?' | '*' | '+' | '{n[,[m]]}'
|
||||
*/
|
||||
static node *parse (const CharT *start_, const CharT * const end_,
|
||||
const std::size_t id_, const std::size_t dfa_state_,
|
||||
const regex_flags flags_, const std::locale &locale_,
|
||||
node_ptr_vector &node_ptr_vector_, const macro_map ¯omap_,
|
||||
typename tokeniser::token_map &map_,
|
||||
bool &seen_BOL_assertion_, bool &seen_EOL_assertion_)
|
||||
{
|
||||
node *root_ = 0;
|
||||
state state_ (start_, end_, flags_, locale_);
|
||||
token lhs_token_;
|
||||
token rhs_token_;
|
||||
token_stack token_stack_;
|
||||
tree_node_stack tree_node_stack_;
|
||||
char action_ = 0;
|
||||
|
||||
token_stack_.push (rhs_token_);
|
||||
tokeniser::next (state_, map_, rhs_token_);
|
||||
|
||||
do
|
||||
{
|
||||
lhs_token_ = token_stack_.top ();
|
||||
action_ = lhs_token_.precedence (rhs_token_._type);
|
||||
|
||||
switch (action_)
|
||||
{
|
||||
case '<':
|
||||
case '=':
|
||||
token_stack_.push (rhs_token_);
|
||||
tokeniser::next (state_, map_, rhs_token_);
|
||||
break;
|
||||
case '>':
|
||||
reduce (token_stack_, macromap_, node_ptr_vector_,
|
||||
tree_node_stack_);
|
||||
break;
|
||||
default:
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "A syntax error occurred: '" <<
|
||||
lhs_token_.precedence_string () <<
|
||||
"' against '" << rhs_token_.precedence_string () <<
|
||||
"' at index " << state_.index () << ".";
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
break;
|
||||
}
|
||||
} while (!token_stack_.empty ());
|
||||
|
||||
if (tree_node_stack_.empty ())
|
||||
{
|
||||
throw runtime_error ("Empty rules are not allowed.");
|
||||
}
|
||||
|
||||
assert (tree_node_stack_.size () == 1);
|
||||
|
||||
node *lhs_node_ = tree_node_stack_.top ();
|
||||
|
||||
tree_node_stack_.pop ();
|
||||
|
||||
if (id_ == 0)
|
||||
{
|
||||
// Macros have no end state...
|
||||
root_ = lhs_node_;
|
||||
}
|
||||
else
|
||||
{
|
||||
node_ptr_vector_->push_back (0);
|
||||
|
||||
node *rhs_node_ = new end_node (id_, dfa_state_);
|
||||
|
||||
node_ptr_vector_->back () = rhs_node_;
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new sequence_node (lhs_node_, rhs_node_);
|
||||
root_ = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
// Done this way as bug in VC++ 6 prevents |= operator working
|
||||
// properly!
|
||||
if (state_._seen_BOL_assertion) seen_BOL_assertion_ = true;
|
||||
|
||||
if (state_._seen_EOL_assertion) seen_EOL_assertion_ = true;
|
||||
|
||||
return root_;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename tokeniser::state state;
|
||||
typedef std::stack<token> token_stack;
|
||||
typedef node::node_stack tree_node_stack;
|
||||
|
||||
static void reduce (token_stack &token_stack_,
|
||||
const macro_map ¯omap_, node_ptr_vector &node_vector_ptr_,
|
||||
tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
typename tokeniser::num_token lhs_;
|
||||
typename tokeniser::num_token rhs_;
|
||||
token_stack handle_;
|
||||
char action_ = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rhs_ = token_stack_.top ();
|
||||
token_stack_.pop ();
|
||||
handle_.push (rhs_);
|
||||
|
||||
if (!token_stack_.empty ())
|
||||
{
|
||||
lhs_ = token_stack_.top ();
|
||||
action_ = lhs_.precedence (rhs_._type);
|
||||
}
|
||||
} while (!token_stack_.empty () && action_ == '=');
|
||||
|
||||
assert (token_stack_.empty () || action_ == '<');
|
||||
|
||||
switch (rhs_._type)
|
||||
{
|
||||
case token::BEGIN:
|
||||
// finished processing so exit
|
||||
break;
|
||||
case token::REGEX:
|
||||
// finished parsing, nothing to do
|
||||
break;
|
||||
case token::OREXP:
|
||||
orexp (handle_, token_stack_, node_vector_ptr_, tree_node_stack_);
|
||||
break;
|
||||
case token::SEQUENCE:
|
||||
token_stack_.push (token::OREXP);
|
||||
break;
|
||||
case token::SUB:
|
||||
sub (handle_, token_stack_, node_vector_ptr_, tree_node_stack_);
|
||||
break;
|
||||
case token::EXPRESSION:
|
||||
token_stack_.push (token::SUB);
|
||||
break;
|
||||
case token::REPEAT:
|
||||
repeat (handle_, token_stack_);
|
||||
break;
|
||||
case token::CHARSET:
|
||||
charset (handle_, token_stack_, node_vector_ptr_,
|
||||
tree_node_stack_);
|
||||
break;
|
||||
case token::MACRO:
|
||||
macro (handle_, token_stack_, macromap_, node_vector_ptr_,
|
||||
tree_node_stack_);
|
||||
break;
|
||||
case token::OPENPAREN:
|
||||
openparen (handle_, token_stack_);
|
||||
break;
|
||||
case token::OPT:
|
||||
case token::AOPT:
|
||||
optional (rhs_._type == token::OPT, node_vector_ptr_,
|
||||
tree_node_stack_);
|
||||
token_stack_.push (token::DUP);
|
||||
break;
|
||||
case token::ZEROORMORE:
|
||||
case token::AZEROORMORE:
|
||||
zero_or_more (rhs_._type == token::ZEROORMORE, node_vector_ptr_,
|
||||
tree_node_stack_);
|
||||
token_stack_.push (token::DUP);
|
||||
break;
|
||||
case token::ONEORMORE:
|
||||
case token::AONEORMORE:
|
||||
one_or_more (rhs_._type == token::ONEORMORE, node_vector_ptr_,
|
||||
tree_node_stack_);
|
||||
token_stack_.push (token::DUP);
|
||||
break;
|
||||
case token::REPEATN:
|
||||
case token::AREPEATN:
|
||||
repeatn (rhs_._type == token::REPEATN, handle_.top (),
|
||||
node_vector_ptr_, tree_node_stack_);
|
||||
token_stack_.push (token::DUP);
|
||||
break;
|
||||
default:
|
||||
throw runtime_error
|
||||
("Internal error regex_parser::reduce");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void orexp (token_stack &handle_, token_stack &token_stack_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
assert (handle_.top ()._type == token::OREXP &&
|
||||
(handle_.size () == 1 || handle_.size () == 3));
|
||||
|
||||
if (handle_.size () == 1)
|
||||
{
|
||||
token_stack_.push (token::REGEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::OR);
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::SEQUENCE);
|
||||
perform_or (node_ptr_vector_, tree_node_stack_);
|
||||
token_stack_.push (token::OREXP);
|
||||
}
|
||||
}
|
||||
|
||||
static void sub (token_stack &handle_, token_stack &token_stack_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
assert (handle_.top ()._type == token::SUB &&
|
||||
handle_.size () == 1 || handle_.size () == 2);
|
||||
|
||||
if (handle_.size () == 1)
|
||||
{
|
||||
token_stack_.push (token::SEQUENCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::EXPRESSION);
|
||||
// perform join
|
||||
sequence (node_ptr_vector_, tree_node_stack_);
|
||||
token_stack_.push (token::SUB);
|
||||
}
|
||||
}
|
||||
|
||||
static void repeat (token_stack &handle_, token_stack &token_stack_)
|
||||
{
|
||||
assert (handle_.top ()._type == token::REPEAT &&
|
||||
handle_.size () >= 1 && handle_.size () <= 3);
|
||||
|
||||
if (handle_.size () == 1)
|
||||
{
|
||||
token_stack_.push (token::EXPRESSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::DUP);
|
||||
token_stack_.push (token::REPEAT);
|
||||
}
|
||||
}
|
||||
|
||||
static void charset (token_stack &handle_, token_stack &token_stack_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
assert (handle_.top ()._type == token::CHARSET &&
|
||||
handle_.size () == 1);
|
||||
// store charset
|
||||
node_ptr_vector_->push_back (0);
|
||||
|
||||
const size_t id_ = handle_.top ()._id;
|
||||
|
||||
node_ptr_vector_->back () = new leaf_node (id_, true);
|
||||
tree_node_stack_.push (node_ptr_vector_->back ());
|
||||
token_stack_.push (token::REPEAT);
|
||||
}
|
||||
|
||||
static void macro (token_stack &handle_, token_stack &token_stack_,
|
||||
const macro_map ¯omap_, node_ptr_vector &node_ptr_vector_,
|
||||
tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
token &top_ = handle_.top ();
|
||||
|
||||
assert (top_._type == token::MACRO && handle_.size () == 1);
|
||||
|
||||
typename macro_map::const_iterator iter_ =
|
||||
macromap_.find (top_._macro);
|
||||
|
||||
if (iter_ == macromap_.end ())
|
||||
{
|
||||
const CharT *name_ = top_._macro;
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Unknown MACRO name '";
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
os_ << ss_.narrow (*name_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
|
||||
tree_node_stack_.push (iter_->second->copy (node_ptr_vector_));
|
||||
token_stack_.push (token::REPEAT);
|
||||
}
|
||||
|
||||
static void openparen (token_stack &handle_, token_stack &token_stack_)
|
||||
{
|
||||
assert (handle_.top ()._type == token::OPENPAREN &&
|
||||
handle_.size () == 3);
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::REGEX);
|
||||
handle_.pop ();
|
||||
assert (handle_.top ()._type == token::CLOSEPAREN);
|
||||
token_stack_.push (token::REPEAT);
|
||||
}
|
||||
|
||||
static void perform_or (node_ptr_vector &node_ptr_vector_,
|
||||
tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
// perform or
|
||||
node *rhs_ = tree_node_stack_.top ();
|
||||
|
||||
tree_node_stack_.pop ();
|
||||
|
||||
node *lhs_ = tree_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new selection_node (lhs_, rhs_);
|
||||
tree_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
static void sequence (node_ptr_vector &node_ptr_vector_,
|
||||
tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
node *rhs_ = tree_node_stack_.top ();
|
||||
|
||||
tree_node_stack_.pop ();
|
||||
|
||||
node *lhs_ = tree_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new sequence_node (lhs_, rhs_);
|
||||
tree_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
static void optional (const bool greedy_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
// perform ?
|
||||
node *lhs_ = tree_node_stack_.top ();
|
||||
// You don't know if lhs_ is a leaf_node, so get firstpos.
|
||||
node::node_vector &firstpos_ = lhs_->firstpos();
|
||||
|
||||
for (node::node_vector::iterator iter_ = firstpos_.begin (),
|
||||
end_ = firstpos_.end (); iter_ != end_; ++iter_)
|
||||
{
|
||||
// These are leaf_nodes!
|
||||
(*iter_)->greedy (greedy_);
|
||||
}
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
|
||||
node *rhs_ = new leaf_node (null_token, greedy_);
|
||||
|
||||
node_ptr_vector_->back () = rhs_;
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new selection_node (lhs_, rhs_);
|
||||
tree_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
static void zero_or_more (const bool greedy_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
// perform *
|
||||
node *ptr_ = tree_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new iteration_node (ptr_, greedy_);
|
||||
tree_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
static void one_or_more (const bool greedy_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
// perform +
|
||||
node *lhs_ = tree_node_stack_.top ();
|
||||
node *copy_ = lhs_->copy (node_ptr_vector_);
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
|
||||
node *rhs_ = new iteration_node (copy_, greedy_);
|
||||
|
||||
node_ptr_vector_->back () = rhs_;
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new sequence_node (lhs_, rhs_);
|
||||
tree_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
|
||||
static void repeatn (const bool greedy_, const token &token_,
|
||||
node_ptr_vector &node_ptr_vector_, tree_node_stack &tree_node_stack_)
|
||||
{
|
||||
// perform {n[,[m]]}
|
||||
// Semantic checks have already been performed.
|
||||
// {0,} = *
|
||||
// {0,1} = ?
|
||||
// {1,} = +
|
||||
// therefore we do not check for these cases.
|
||||
if (!(token_._min == 1 && !token_._comma))
|
||||
{
|
||||
const std::size_t top_ = token_._min > 0 ?
|
||||
token_._min : token_._max;
|
||||
|
||||
if (token_._min == 0)
|
||||
{
|
||||
optional (greedy_, node_ptr_vector_, tree_node_stack_);
|
||||
}
|
||||
|
||||
node *prev_ = tree_node_stack_.top ()->copy (node_ptr_vector_);
|
||||
node *curr_ = 0;
|
||||
|
||||
for (std::size_t i_ = 2; i_ < top_; ++i_)
|
||||
{
|
||||
node *temp_ = prev_->copy (node_ptr_vector_);
|
||||
|
||||
curr_ = temp_;
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
sequence (node_ptr_vector_, tree_node_stack_);
|
||||
prev_ = curr_;
|
||||
}
|
||||
|
||||
if (token_._comma && token_._min > 0)
|
||||
{
|
||||
if (token_._min > 1)
|
||||
{
|
||||
node *temp_ = prev_->copy (node_ptr_vector_);
|
||||
|
||||
curr_ = temp_;
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
sequence (node_ptr_vector_, tree_node_stack_);
|
||||
prev_ = curr_;
|
||||
}
|
||||
|
||||
if (token_._comma && token_._max)
|
||||
{
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
optional (greedy_, node_ptr_vector_, tree_node_stack_);
|
||||
|
||||
node *temp_ = tree_node_stack_.top ();
|
||||
|
||||
tree_node_stack_.pop ();
|
||||
prev_ = temp_;
|
||||
|
||||
const std::size_t count_ = token_._max - token_._min;
|
||||
|
||||
for (std::size_t i_ = 1; i_ < count_; ++i_)
|
||||
{
|
||||
node *temp_ = prev_->copy (node_ptr_vector_);
|
||||
|
||||
curr_ = temp_;
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
sequence (node_ptr_vector_, tree_node_stack_);
|
||||
prev_ = curr_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
zero_or_more (greedy_, node_ptr_vector_, tree_node_stack_);
|
||||
|
||||
node *temp_ = tree_node_stack_.top ();
|
||||
|
||||
prev_ = temp_;
|
||||
tree_node_stack_.pop ();
|
||||
}
|
||||
}
|
||||
|
||||
tree_node_stack_.push (0);
|
||||
tree_node_stack_.top () = prev_;
|
||||
sequence (node_ptr_vector_, tree_node_stack_);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,146 @@
|
||||
// num_token.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_NUM_TOKEN_HPP
|
||||
#define BOOST_LEXER_NUM_TOKEN_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include "../../consts.hpp" // null_token
|
||||
#include "../../size_t.hpp"
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
struct basic_num_token
|
||||
{
|
||||
enum type {BEGIN, REGEX, OREXP, SEQUENCE, SUB, EXPRESSION, REPEAT,
|
||||
DUP, OR, CHARSET, MACRO, OPENPAREN, CLOSEPAREN, OPT, AOPT,
|
||||
ZEROORMORE, AZEROORMORE, ONEORMORE, AONEORMORE, REPEATN, AREPEATN,
|
||||
END};
|
||||
|
||||
type _type;
|
||||
std::size_t _id;
|
||||
std::size_t _min;
|
||||
bool _comma;
|
||||
std::size_t _max;
|
||||
CharT _macro[max_macro_len + 1];
|
||||
static const char _precedence_table[END + 1][END + 1];
|
||||
static const char *_precedence_strings[END + 1];
|
||||
|
||||
basic_num_token (const type type_ = BEGIN,
|
||||
const std::size_t id_ = null_token) :
|
||||
_type (type_),
|
||||
_id (id_),
|
||||
_min (0),
|
||||
_comma (false),
|
||||
_max (0)
|
||||
{
|
||||
*_macro = 0;
|
||||
}
|
||||
|
||||
basic_num_token &operator = (const basic_num_token &rhs_)
|
||||
{
|
||||
_type = rhs_._type;
|
||||
_id = rhs_._id;
|
||||
_min = rhs_._min;
|
||||
_comma = rhs_._comma;
|
||||
_max = rhs_._max;
|
||||
|
||||
if (_type == MACRO)
|
||||
{
|
||||
const CharT *read_ = rhs_._macro;
|
||||
CharT *write_ = _macro;
|
||||
|
||||
while (*read_)
|
||||
{
|
||||
*write_++ = *read_++;
|
||||
}
|
||||
|
||||
*write_ = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set (const type type_)
|
||||
{
|
||||
_type = type_;
|
||||
_id = null_token;
|
||||
}
|
||||
|
||||
void set (const type type_, const std::size_t id_)
|
||||
{
|
||||
_type = type_;
|
||||
_id = id_;
|
||||
}
|
||||
|
||||
void min_max (const std::size_t min_, const bool comma_,
|
||||
const std::size_t max_)
|
||||
{
|
||||
_min = min_;
|
||||
_comma = comma_;
|
||||
_max = max_;
|
||||
}
|
||||
|
||||
char precedence (const type type_) const
|
||||
{
|
||||
return _precedence_table[_type][type_];
|
||||
}
|
||||
|
||||
const char *precedence_string () const
|
||||
{
|
||||
return _precedence_strings[_type];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
const char basic_num_token<CharT>::_precedence_table[END + 1][END + 1] = {
|
||||
// BEG, REG, ORE, SEQ, SUB, EXP, RPT, DUP, | , CHR, MCR, ( , ) , ? , ?? , * , *? , + , +?, {n}?, {n}, END
|
||||
/*BEGIN*/{' ', '<', '<', '<', '<', '<', '<', ' ', ' ', '<', '<', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/*REGEX*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '=', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/*OREXP*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '=', '>', '>', ' ', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* SEQ */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', ' ', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* SUB */{' ', ' ', ' ', ' ', ' ', '=', '<', ' ', '>', '<', '<', '<', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/*EXPRE*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* RPT */{' ', ' ', ' ', ' ', ' ', ' ', ' ', '=', '>', '>', '>', '>', '>', '<', '<', '<', '<', '<', '<', '<', '<', '>'},
|
||||
/*DUPLI*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* | */{' ', ' ', ' ', '=', '<', '<', '<', ' ', ' ', '<', '<', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
||||
/*CHARA*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>'},
|
||||
/*MACRO*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>'},
|
||||
/* ( */{' ', '=', '<', '<', '<', '<', '<', ' ', ' ', '<', '<', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
||||
/* ) */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>', '>'},
|
||||
/* ? */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* ?? */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* * */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* *? */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* + */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* +? */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/*{n,m}*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', '<', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/*{nm}?*/{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>', '>', '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '>'},
|
||||
/* END */{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
const char *basic_num_token<CharT>::_precedence_strings[END + 1] =
|
||||
#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, BOOST_TESTED_AT(910))
|
||||
{{"BEGIN"}, {"REGEX"}, {"OREXP"}, {"SEQUENCE"}, {"SUB"}, {"EXPRESSION"},
|
||||
{"REPEAT"}, {"DUPLICATE"}, {"|"}, {"CHARSET"}, {"MACRO"},
|
||||
{"("}, {")"}, {"?"}, {"??"}, {"*"}, {"*?"}, {"+"}, {"+?"}, {"{n[,[m]]}"},
|
||||
{"{n[,[m]]}?"}, {"END"}};
|
||||
#else
|
||||
{"BEGIN", "REGEX", "OREXP", "SEQUENCE", "SUB", "EXPRESSION", "REPEAT",
|
||||
"DUPLICATE", "|", "CHARSET", "MACRO", "(", ")", "?", "??", "*", "*?",
|
||||
"+", "+?", "{n[,[m]]}", "{n[,[m]]}?", "END"};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,571 @@
|
||||
// tokeniser.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_RE_TOKENISER_HPP
|
||||
#define BOOST_LEXER_RE_TOKENISER_HPP
|
||||
|
||||
// memcpy()
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include "num_token.hpp"
|
||||
#include "../../runtime_error.hpp"
|
||||
#include "../../size_t.hpp"
|
||||
#include <sstream>
|
||||
#include "../../string_token.hpp"
|
||||
#include "re_tokeniser_helper.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
class basic_re_tokeniser
|
||||
{
|
||||
public:
|
||||
typedef basic_num_token<CharT> num_token;
|
||||
typedef basic_re_tokeniser_state<CharT> state;
|
||||
typedef basic_string_token<CharT> string_token;
|
||||
typedef typename string_token::string string;
|
||||
typedef std::map<string_token, std::size_t> token_map;
|
||||
typedef std::pair<string_token, std::size_t> token_pair;
|
||||
|
||||
static void next (state &state_, token_map &map_, num_token &token_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = state_.next (ch_);
|
||||
|
||||
token_.min_max (0, false, 0);
|
||||
|
||||
while (!eos_ && ch_ == '"')
|
||||
{
|
||||
state_._in_string ^= 1;
|
||||
eos_ = state_.next (ch_);
|
||||
}
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
if (state_._in_string)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '\"').");
|
||||
}
|
||||
|
||||
if (state_._paren_count)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing ')').");
|
||||
}
|
||||
|
||||
token_.set (num_token::END, null_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch_ == '\\')
|
||||
{
|
||||
// Even if we are in a string, respect escape sequences...
|
||||
escape (state_, map_, token_);
|
||||
}
|
||||
else if (state_._in_string)
|
||||
{
|
||||
// All other meta characters lose their special meaning
|
||||
// inside a string.
|
||||
create_charset_token (string (1, ch_), false, map_, token_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not an escape sequence and not inside a string, so
|
||||
// check for meta characters.
|
||||
switch (ch_)
|
||||
{
|
||||
case '(':
|
||||
token_.set (num_token::OPENPAREN, null_token);
|
||||
++state_._paren_count;
|
||||
read_options (state_);
|
||||
break;
|
||||
case ')':
|
||||
--state_._paren_count;
|
||||
|
||||
if (state_._paren_count < 0)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Number of open parenthesis < 0 at index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
token_.set (num_token::CLOSEPAREN, null_token);
|
||||
|
||||
if (!state_._flags_stack.empty ())
|
||||
{
|
||||
state_._flags = state_._flags_stack.top ();
|
||||
state_._flags_stack.pop ();
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
if (!state_.eos () && *state_._curr == '?')
|
||||
{
|
||||
token_.set (num_token::AOPT, null_token);
|
||||
state_.increment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
token_.set (num_token::OPT, null_token);
|
||||
}
|
||||
|
||||
break;
|
||||
case '*':
|
||||
if (!state_.eos () && *state_._curr == '?')
|
||||
{
|
||||
token_.set (num_token::AZEROORMORE, null_token);
|
||||
state_.increment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
token_.set (num_token::ZEROORMORE, null_token);
|
||||
}
|
||||
|
||||
break;
|
||||
case '+':
|
||||
if (!state_.eos () && *state_._curr == '?')
|
||||
{
|
||||
token_.set (num_token::AONEORMORE, null_token);
|
||||
state_.increment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
token_.set (num_token::ONEORMORE, null_token);
|
||||
}
|
||||
|
||||
break;
|
||||
case '{':
|
||||
open_curly (state_, token_);
|
||||
break;
|
||||
case '|':
|
||||
token_.set (num_token::OR, null_token);
|
||||
break;
|
||||
case '^':
|
||||
if (state_._curr - 1 == state_._start)
|
||||
{
|
||||
token_.set (num_token::CHARSET, bol_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_charset_token (string (1, ch_), false,
|
||||
map_, token_);
|
||||
}
|
||||
|
||||
state_._seen_BOL_assertion = true;
|
||||
break;
|
||||
case '$':
|
||||
if (state_._curr == state_._end)
|
||||
{
|
||||
token_.set (num_token::CHARSET, eol_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_charset_token (string (1, ch_), false,
|
||||
map_, token_);
|
||||
}
|
||||
|
||||
state_._seen_EOL_assertion = true;
|
||||
break;
|
||||
case '.':
|
||||
{
|
||||
string dot_;
|
||||
|
||||
if (state_._flags & dot_not_newline)
|
||||
{
|
||||
dot_ = '\n';
|
||||
}
|
||||
|
||||
create_charset_token (dot_, true, map_, token_);
|
||||
break;
|
||||
}
|
||||
case '[':
|
||||
{
|
||||
charset (state_, map_, token_);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if ((state_._flags & icase) &&
|
||||
(std::isupper (ch_, state_._locale) ||
|
||||
std::islower (ch_, state_._locale)))
|
||||
{
|
||||
CharT upper_ = std::toupper (ch_, state_._locale);
|
||||
CharT lower_ = std::tolower (ch_, state_._locale);
|
||||
|
||||
string str_ (1, upper_);
|
||||
|
||||
str_ += lower_;
|
||||
create_charset_token (str_, false, map_, token_);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_charset_token (string (1, ch_), false,
|
||||
map_, token_);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef basic_re_tokeniser_helper<CharT> tokeniser_helper;
|
||||
|
||||
static void read_options (state &state_)
|
||||
{
|
||||
if (!state_.eos () && *state_._curr == '?')
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = false;
|
||||
bool negate_ = false;
|
||||
|
||||
state_.increment ();
|
||||
eos_ = state_.next (ch_);
|
||||
state_._flags_stack.push (state_._flags);
|
||||
|
||||
while (!eos_ && ch_ != ':')
|
||||
{
|
||||
switch (ch_)
|
||||
{
|
||||
case '-':
|
||||
negate_ ^= 1;
|
||||
break;
|
||||
case 'i':
|
||||
if (negate_)
|
||||
{
|
||||
state_._flags = static_cast<regex_flags>
|
||||
(state_._flags & ~icase);
|
||||
}
|
||||
else
|
||||
{
|
||||
state_._flags = static_cast<regex_flags>
|
||||
(state_._flags | icase);
|
||||
}
|
||||
|
||||
negate_ = false;
|
||||
break;
|
||||
case 's':
|
||||
if (negate_)
|
||||
{
|
||||
state_._flags = static_cast<regex_flags>
|
||||
(state_._flags | dot_not_newline);
|
||||
}
|
||||
else
|
||||
{
|
||||
state_._flags = static_cast<regex_flags>
|
||||
(state_._flags & ~dot_not_newline);
|
||||
}
|
||||
|
||||
negate_ = false;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Unknown option at " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
}
|
||||
|
||||
eos_ = state_.next (ch_);
|
||||
}
|
||||
|
||||
// End of string handler will handle early termination
|
||||
}
|
||||
else if (!state_._flags_stack.empty ())
|
||||
{
|
||||
state_._flags_stack.push (state_._flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void escape (state &state_, token_map &map_, num_token &token_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
std::size_t str_len_ = 0;
|
||||
const CharT *str_ = tokeniser_helper::escape_sequence (state_,
|
||||
ch_, str_len_);
|
||||
|
||||
if (str_)
|
||||
{
|
||||
state state2_ (str_ + 1, str_ + str_len_, state_._flags,
|
||||
state_._locale);
|
||||
|
||||
charset (state2_, map_, token_);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_charset_token (string (1, ch_), false, map_, token_);
|
||||
}
|
||||
}
|
||||
|
||||
static void charset (state &state_, token_map &map_, num_token &token_)
|
||||
{
|
||||
string chars_;
|
||||
bool negated_ = false;
|
||||
|
||||
tokeniser_helper::charset (state_, chars_, negated_);
|
||||
create_charset_token (chars_, negated_, map_, token_);
|
||||
}
|
||||
|
||||
static void create_charset_token (const string &charset_,
|
||||
const bool negated_, token_map &map_, num_token &token_)
|
||||
{
|
||||
std::size_t id_ = null_token;
|
||||
string_token stok_ (negated_, charset_);
|
||||
|
||||
stok_.remove_duplicates ();
|
||||
stok_.normalise ();
|
||||
|
||||
typename token_map::const_iterator iter_ = map_.find (stok_);
|
||||
|
||||
if (iter_ == map_.end ())
|
||||
{
|
||||
id_ = map_.size ();
|
||||
map_.insert (token_pair (stok_, id_));
|
||||
}
|
||||
else
|
||||
{
|
||||
id_ = iter_->second;
|
||||
}
|
||||
|
||||
token_.set (num_token::CHARSET, id_);
|
||||
}
|
||||
|
||||
static void open_curly (state &state_, num_token &token_)
|
||||
{
|
||||
if (state_.eos ())
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '}').");
|
||||
}
|
||||
else if (*state_._curr >= '0' && *state_._curr <= '9')
|
||||
{
|
||||
repeat_n (state_, token_);
|
||||
|
||||
if (!state_.eos () && *state_._curr == '?')
|
||||
{
|
||||
token_._type = num_token::AREPEATN;
|
||||
state_.increment ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
macro (state_, token_);
|
||||
}
|
||||
}
|
||||
|
||||
// SYNTAX:
|
||||
// {n[,[n]]}
|
||||
// SEMANTIC RULES:
|
||||
// {0} - INVALID (throw exception)
|
||||
// {0,} = *
|
||||
// {0,0} - INVALID (throw exception)
|
||||
// {0,1} = ?
|
||||
// {1,} = +
|
||||
// {min,max} where min == max - {min}
|
||||
// {min,max} where max < min - INVALID (throw exception)
|
||||
static void repeat_n (state &state_, num_token &token_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = state_.next (ch_);
|
||||
|
||||
while (!eos_ && ch_ >= '0' && ch_ <= '9')
|
||||
{
|
||||
token_._min *= 10;
|
||||
token_._min += ch_ - '0';
|
||||
eos_ = state_.next (ch_);
|
||||
}
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '}').");
|
||||
}
|
||||
|
||||
bool min_max_ = false;
|
||||
bool repeatn_ = true;
|
||||
|
||||
token_._comma = ch_ == ',';
|
||||
|
||||
if (token_._comma)
|
||||
{
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '}').");
|
||||
}
|
||||
|
||||
if (ch_ == '}')
|
||||
{
|
||||
// Small optimisation: Check for '*' equivalency.
|
||||
if (token_._min == 0)
|
||||
{
|
||||
token_.set (num_token::ZEROORMORE, null_token);
|
||||
repeatn_ = false;
|
||||
}
|
||||
// Small optimisation: Check for '+' equivalency.
|
||||
else if (token_._min == 1)
|
||||
{
|
||||
token_.set (num_token::ONEORMORE, null_token);
|
||||
repeatn_ = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch_ < '0' || ch_ > '9')
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Missing '}' at index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
min_max_ = true;
|
||||
|
||||
do
|
||||
{
|
||||
token_._max *= 10;
|
||||
token_._max += ch_ - '0';
|
||||
eos_ = state_.next (ch_);
|
||||
} while (!eos_ && ch_ >= '0' && ch_ <= '9');
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '}').");
|
||||
}
|
||||
|
||||
// Small optimisation: Check for '?' equivalency.
|
||||
if (token_._min == 0 && token_._max == 1)
|
||||
{
|
||||
token_.set (num_token::OPT, null_token);
|
||||
repeatn_ = false;
|
||||
}
|
||||
// Small optimisation: if min == max, then min.
|
||||
else if (token_._min == token_._max)
|
||||
{
|
||||
token_._comma = false;
|
||||
min_max_ = false;
|
||||
token_._max = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch_ != '}')
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Missing '}' at index " << state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
if (repeatn_)
|
||||
{
|
||||
// SEMANTIC VALIDATION follows:
|
||||
// NOTE: {0,} has already become *
|
||||
// therefore we don't check for a comma.
|
||||
if (token_._min == 0 && token_._max == 0)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Cannot have exactly zero repeats preceding index " <<
|
||||
state_.index () << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
if (min_max_ && token_._max < token_._min)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Max less than min preceding index " <<
|
||||
state_.index () << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
token_.set (num_token::REPEATN, null_token);
|
||||
}
|
||||
}
|
||||
|
||||
static void macro (state &state_, num_token &token_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = false;
|
||||
const CharT *start_ = state_._curr;
|
||||
|
||||
state_.next (ch_);
|
||||
|
||||
if (ch_ != '_' && !(ch_ >= 'A' && ch_ <= 'Z') &&
|
||||
!(ch_ >= 'a' && ch_ <= 'z'))
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Invalid MACRO name at index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing '}').");
|
||||
}
|
||||
} while (ch_ == '_' || ch_ == '-' || ch_ >= 'A' && ch_ <= 'Z' ||
|
||||
ch_ >= 'a' && ch_ <= 'z' || ch_ >= '0' && ch_ <= '9');
|
||||
|
||||
if (ch_ != '}')
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Missing '}' at index " << state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
std::size_t len_ = state_._curr - 1 - start_;
|
||||
|
||||
if (len_ > max_macro_len)
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "MACRO name '";
|
||||
|
||||
while (len_)
|
||||
{
|
||||
os_ << ss_.narrow (*start_++, ' ');
|
||||
--len_;
|
||||
}
|
||||
|
||||
os_ << "' too long.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
|
||||
token_.set (num_token::MACRO, null_token);
|
||||
|
||||
// Some systems have memcpy in namespace std.
|
||||
using namespace std;
|
||||
|
||||
memcpy (token_._macro, start_, len_ * sizeof (CharT));
|
||||
token_._macro[len_] = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,549 @@
|
||||
// tokeniser_helper.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_RE_TOKENISER_HELPER_H
|
||||
#define BOOST_LEXER_RE_TOKENISER_HELPER_H
|
||||
|
||||
#include "../../char_traits.hpp"
|
||||
// strlen()
|
||||
#include <cstring>
|
||||
#include "../../size_t.hpp"
|
||||
#include "re_tokeniser_state.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT, typename Traits = char_traits<CharT> >
|
||||
class basic_re_tokeniser_helper
|
||||
{
|
||||
public:
|
||||
typedef basic_re_tokeniser_state<CharT> state;
|
||||
typedef std::basic_string<CharT> string;
|
||||
|
||||
static const CharT *escape_sequence (state &state_, CharT &ch_,
|
||||
std::size_t &str_len_)
|
||||
{
|
||||
bool eos_ = state_.eos ();
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"following '\\'.");
|
||||
}
|
||||
|
||||
const CharT *str_ = charset_shortcut (*state_._curr, str_len_);
|
||||
|
||||
if (str_)
|
||||
{
|
||||
state_.increment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
ch_ = chr (state_);
|
||||
}
|
||||
|
||||
return str_;
|
||||
}
|
||||
|
||||
// This function can call itself.
|
||||
static void charset (state &state_, string &chars_, bool &negated_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"following '['.");
|
||||
}
|
||||
|
||||
negated_ = ch_ == '^';
|
||||
|
||||
if (negated_)
|
||||
{
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"following '^'.");
|
||||
}
|
||||
}
|
||||
|
||||
bool chset_ = false;
|
||||
CharT prev_ = 0;
|
||||
|
||||
while (ch_ != ']')
|
||||
{
|
||||
if (ch_ == '\\')
|
||||
{
|
||||
std::size_t str_len_ = 0;
|
||||
const CharT *str_ = escape_sequence (state_, prev_, str_len_);
|
||||
|
||||
chset_ = str_ != 0;
|
||||
|
||||
if (chset_)
|
||||
{
|
||||
state temp_state_ (str_ + 1, str_ + str_len_,
|
||||
state_._flags, state_._locale);
|
||||
string temp_chars_;
|
||||
bool temp_negated_ = false;
|
||||
|
||||
charset (temp_state_, temp_chars_, temp_negated_);
|
||||
|
||||
if (negated_ != temp_negated_)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Mismatch in charset negation preceding "
|
||||
"index " << state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
chars_ += temp_chars_;
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (ch_ == '[' && !state_.eos () && *state_._curr == ':')
|
||||
{
|
||||
// TODO: POSIX charsets
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
chset_ = false;
|
||||
prev_ = ch_;
|
||||
}
|
||||
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
// Covers preceding if, else if and else
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing ']').");
|
||||
}
|
||||
|
||||
if (ch_ == '-')
|
||||
{
|
||||
charset_range (chset_, state_, eos_, ch_, prev_, chars_);
|
||||
}
|
||||
else if (!chset_)
|
||||
{
|
||||
if ((state_._flags & icase) &&
|
||||
(std::isupper (prev_, state_._locale) ||
|
||||
std::islower (prev_, state_._locale)))
|
||||
{
|
||||
CharT upper_ = std::toupper (prev_, state_._locale);
|
||||
CharT lower_ = std::tolower (prev_, state_._locale);
|
||||
|
||||
chars_ += upper_;
|
||||
chars_ += lower_;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars_ += prev_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!negated_ && chars_.empty ())
|
||||
{
|
||||
throw runtime_error ("Empty charsets not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const char *charset_shortcut (const char ch_,
|
||||
std::size_t &str_len_)
|
||||
{
|
||||
const char *str_ = 0;
|
||||
|
||||
switch (ch_)
|
||||
{
|
||||
case 'd':
|
||||
str_ = "[0-9]";
|
||||
break;
|
||||
case 'D':
|
||||
str_ = "[^0-9]";
|
||||
break;
|
||||
case 's':
|
||||
str_ = "[ \t\n\r\f\v]";
|
||||
break;
|
||||
case 'S':
|
||||
str_ = "[^ \t\n\r\f\v]";
|
||||
break;
|
||||
case 'w':
|
||||
str_ = "[_0-9A-Za-z]";
|
||||
break;
|
||||
case 'W':
|
||||
str_ = "[^_0-9A-Za-z]";
|
||||
break;
|
||||
}
|
||||
|
||||
if (str_)
|
||||
{
|
||||
// Some systems have strlen in namespace std.
|
||||
using namespace std;
|
||||
|
||||
str_len_ = strlen (str_);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_len_ = 0;
|
||||
}
|
||||
|
||||
return str_;
|
||||
}
|
||||
|
||||
static const wchar_t *charset_shortcut (const wchar_t ch_,
|
||||
std::size_t &str_len_)
|
||||
{
|
||||
const wchar_t *str_ = 0;
|
||||
|
||||
switch (ch_)
|
||||
{
|
||||
case 'd':
|
||||
str_ = L"[0-9]";
|
||||
break;
|
||||
case 'D':
|
||||
str_ = L"[^0-9]";
|
||||
break;
|
||||
case 's':
|
||||
str_ = L"[ \t\n\r\f\v]";
|
||||
break;
|
||||
case 'S':
|
||||
str_ = L"[^ \t\n\r\f\v]";
|
||||
break;
|
||||
case 'w':
|
||||
str_ = L"[_0-9A-Za-z]";
|
||||
break;
|
||||
case 'W':
|
||||
str_ = L"[^_0-9A-Za-z]";
|
||||
break;
|
||||
}
|
||||
|
||||
if (str_)
|
||||
{
|
||||
// Some systems have wcslen in namespace std.
|
||||
using namespace std;
|
||||
|
||||
str_len_ = wcslen (str_);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_len_ = 0;
|
||||
}
|
||||
|
||||
return str_;
|
||||
}
|
||||
|
||||
static CharT chr (state &state_)
|
||||
{
|
||||
CharT ch_ = 0;
|
||||
|
||||
// eos_ has already been checked for.
|
||||
switch (*state_._curr)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
ch_ = decode_octal (state_);
|
||||
break;
|
||||
case 'a':
|
||||
ch_ = '\a';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'b':
|
||||
ch_ = '\b';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'c':
|
||||
ch_ = decode_control_char (state_);
|
||||
break;
|
||||
case 'e':
|
||||
ch_ = 27; // '\e' not recognised by compiler
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'f':
|
||||
ch_ = '\f';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'n':
|
||||
ch_ = '\n';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'r':
|
||||
ch_ = '\r';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 't':
|
||||
ch_ = '\t';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'v':
|
||||
ch_ = '\v';
|
||||
state_.increment ();
|
||||
break;
|
||||
case 'x':
|
||||
ch_ = decode_hex (state_);
|
||||
break;
|
||||
default:
|
||||
ch_ = *state_._curr;
|
||||
state_.increment ();
|
||||
break;
|
||||
}
|
||||
|
||||
return ch_;
|
||||
}
|
||||
|
||||
static CharT decode_octal (state &state_)
|
||||
{
|
||||
std::size_t accumulator_ = 0;
|
||||
CharT ch_ = *state_._curr;
|
||||
unsigned short count_ = 3;
|
||||
bool eos_ = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
accumulator_ *= 8;
|
||||
accumulator_ += ch_ - '0';
|
||||
--count_;
|
||||
state_.increment ();
|
||||
eos_ = state_.eos ();
|
||||
|
||||
if (!count_ || eos_) break;
|
||||
|
||||
ch_ = *state_._curr;
|
||||
|
||||
// Don't consume invalid chars!
|
||||
if (ch_ < '0' || ch_ > '7')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<CharT> (accumulator_);
|
||||
}
|
||||
|
||||
static CharT decode_control_char (state &state_)
|
||||
{
|
||||
// Skip over 'c'
|
||||
state_.increment ();
|
||||
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex following \\c.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch_ >= 'a' && ch_ <= 'z')
|
||||
{
|
||||
ch_ -= 'a' - 1;
|
||||
}
|
||||
else if (ch_ >= 'A' && ch_ <= 'Z')
|
||||
{
|
||||
ch_ -= 'A' - 1;
|
||||
}
|
||||
else if (ch_ == '@')
|
||||
{
|
||||
// Apparently...
|
||||
ch_ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Invalid control char at index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
}
|
||||
|
||||
return ch_;
|
||||
}
|
||||
|
||||
static CharT decode_hex (state &state_)
|
||||
{
|
||||
// Skip over 'x'
|
||||
state_.increment ();
|
||||
|
||||
CharT ch_ = 0;
|
||||
bool eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex following \\x.");
|
||||
}
|
||||
|
||||
if (!((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'a' && ch_ <= 'f') ||
|
||||
(ch_ >= 'A' && ch_ <= 'F')))
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Illegal char following \\x at index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
std::size_t hex_ = 0;
|
||||
|
||||
do
|
||||
{
|
||||
hex_ *= 16;
|
||||
|
||||
if (ch_ >= '0' && ch_ <= '9')
|
||||
{
|
||||
hex_ += ch_ - '0';
|
||||
}
|
||||
else if (ch_ >= 'a' && ch_ <= 'f')
|
||||
{
|
||||
hex_ += 10 + (ch_ - 'a');
|
||||
}
|
||||
else
|
||||
{
|
||||
hex_ += 10 + (ch_ - 'A');
|
||||
}
|
||||
|
||||
eos_ = state_.eos ();
|
||||
|
||||
if (!eos_)
|
||||
{
|
||||
ch_ = *state_._curr;
|
||||
|
||||
// Don't consume invalid chars!
|
||||
if (((ch_ >= '0' && ch_ <= '9') ||
|
||||
(ch_ >= 'a' && ch_ <= 'f') || (ch_ >= 'A' && ch_ <= 'F')))
|
||||
{
|
||||
state_.increment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
eos_ = true;
|
||||
}
|
||||
}
|
||||
} while (!eos_);
|
||||
|
||||
return static_cast<CharT> (hex_);
|
||||
}
|
||||
|
||||
static void charset_range (const bool chset_, state &state_, bool &eos_,
|
||||
CharT &ch_, const CharT prev_, string &chars_)
|
||||
{
|
||||
if (chset_)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Charset cannot form start of range preceding "
|
||||
"index " << state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"following '-'.");
|
||||
}
|
||||
|
||||
CharT curr_ = 0;
|
||||
|
||||
if (ch_ == '\\')
|
||||
{
|
||||
std::size_t str_len_ = 0;
|
||||
|
||||
if (escape_sequence (state_, curr_, str_len_))
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Charset cannot form end of range preceding index "
|
||||
<< state_.index () << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (ch_ == '[' && !state_.eos () && *state_._curr == ':')
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "POSIX char class cannot form end of range at "
|
||||
"index " << state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
curr_ = ch_;
|
||||
}
|
||||
|
||||
eos_ = state_.next (ch_);
|
||||
|
||||
// Covers preceding if and else
|
||||
if (eos_)
|
||||
{
|
||||
// Pointless returning index if at end of string
|
||||
throw runtime_error ("Unexpected end of regex "
|
||||
"(missing ']').");
|
||||
}
|
||||
|
||||
std::size_t start_ = static_cast<typename Traits::index_type> (prev_);
|
||||
std::size_t end_ = static_cast<typename Traits::index_type> (curr_);
|
||||
|
||||
// Semanic check
|
||||
if (end_ < start_)
|
||||
{
|
||||
std::ostringstream ss_;
|
||||
|
||||
ss_ << "Invalid range in charset preceding index " <<
|
||||
state_.index () - 1 << '.';
|
||||
throw runtime_error (ss_.str ().c_str ());
|
||||
}
|
||||
|
||||
chars_.reserve (chars_.size () + (end_ + 1 - start_));
|
||||
|
||||
for (; start_ <= end_; ++start_)
|
||||
{
|
||||
CharT ch_ = static_cast<CharT> (start_);
|
||||
|
||||
if ((state_._flags & icase) &&
|
||||
(std::isupper (ch_, state_._locale) ||
|
||||
std::islower (ch_, state_._locale)))
|
||||
{
|
||||
CharT upper_ = std::toupper (ch_, state_._locale);
|
||||
CharT lower_ = std::tolower (ch_, state_._locale);
|
||||
|
||||
chars_ += (upper_);
|
||||
chars_ += (lower_);
|
||||
}
|
||||
else
|
||||
{
|
||||
chars_ += (ch_);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
// tokeniser_state.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_RE_TOKENISER_STATE_HPP
|
||||
#define BOOST_LEXER_RE_TOKENISER_STATE_HPP
|
||||
|
||||
#include "../../consts.hpp"
|
||||
#include <locale>
|
||||
#include "../../size_t.hpp"
|
||||
#include <stack>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
struct basic_re_tokeniser_state
|
||||
{
|
||||
const CharT * const _start;
|
||||
const CharT * const _end;
|
||||
const CharT *_curr;
|
||||
regex_flags _flags;
|
||||
std::stack<regex_flags> _flags_stack;
|
||||
std::locale _locale;
|
||||
long _paren_count;
|
||||
bool _in_string;
|
||||
bool _seen_BOL_assertion;
|
||||
bool _seen_EOL_assertion;
|
||||
|
||||
basic_re_tokeniser_state (const CharT *start_, const CharT * const end_,
|
||||
const regex_flags flags_, const std::locale locale_) :
|
||||
_start (start_),
|
||||
_end (end_),
|
||||
_curr (start_),
|
||||
_flags (flags_),
|
||||
_locale (locale_),
|
||||
_paren_count (0),
|
||||
_in_string (false),
|
||||
_seen_BOL_assertion (false),
|
||||
_seen_EOL_assertion (false)
|
||||
{
|
||||
}
|
||||
|
||||
// prevent VC++ 7.1 warning:
|
||||
const basic_re_tokeniser_state &operator = (const basic_re_tokeniser_state &rhs_)
|
||||
{
|
||||
_start = rhs_._start;
|
||||
_end = rhs_._end;
|
||||
_curr = rhs_._curr;
|
||||
_flags = rhs_._flags;
|
||||
_locale = rhs_._locale;
|
||||
_paren_count = rhs_._paren_count;
|
||||
_in_string = rhs_._in_string;
|
||||
_seen_BOL_assertion = rhs_._seen_BOL_assertion;
|
||||
_seen_EOL_assertion = rhs_._seen_EOL_assertion;
|
||||
return this;
|
||||
}
|
||||
|
||||
inline bool next (CharT &ch_)
|
||||
{
|
||||
if (_curr >= _end)
|
||||
{
|
||||
ch_ = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch_ = *_curr;
|
||||
increment ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void increment ()
|
||||
{
|
||||
++_curr;
|
||||
}
|
||||
|
||||
inline std::size_t index ()
|
||||
{
|
||||
return _curr - _start;
|
||||
}
|
||||
|
||||
inline bool eos ()
|
||||
{
|
||||
return _curr >= _end;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
// end_node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_END_NODE_HPP
|
||||
#define BOOST_LEXER_END_NODE_HPP
|
||||
|
||||
#include "node.hpp"
|
||||
#include "../../size_t.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class end_node : public node
|
||||
{
|
||||
public:
|
||||
end_node (const std::size_t id_, const std::size_t lexer_state_) :
|
||||
node (false),
|
||||
_id (id_),
|
||||
_lexer_state (lexer_state_)
|
||||
{
|
||||
node::_firstpos.push_back (this);
|
||||
node::_lastpos.push_back (this);
|
||||
}
|
||||
|
||||
virtual ~end_node ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual type what_type () const
|
||||
{
|
||||
return END;
|
||||
}
|
||||
|
||||
virtual bool traverse (const_node_stack &/*node_stack_*/,
|
||||
bool_stack &/*perform_op_stack_*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual const node_vector &followpos () const
|
||||
{
|
||||
// _followpos is always empty..!
|
||||
return _followpos;
|
||||
}
|
||||
|
||||
virtual bool end_state () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual std::size_t id () const
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
virtual std::size_t lexer_state () const
|
||||
{
|
||||
return _lexer_state;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t _id;
|
||||
std::size_t _lexer_state;
|
||||
node_vector _followpos;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &/*node_ptr_vector_*/,
|
||||
node_stack &/*new_node_stack_*/, bool_stack &/*perform_op_stack_*/,
|
||||
bool &/*down_*/) const
|
||||
{
|
||||
// Nothing to do, as end_nodes are not copied.
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// iteration_node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_ITERATION_NODE_HPP
|
||||
#define BOOST_LEXER_ITERATION_NODE_HPP
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class iteration_node : public node
|
||||
{
|
||||
public:
|
||||
iteration_node (node *next_, const bool greedy_) :
|
||||
node (true),
|
||||
_next (next_),
|
||||
_greedy (greedy_)
|
||||
{
|
||||
node_vector::iterator iter_;
|
||||
node_vector::iterator end_;
|
||||
|
||||
_next->append_firstpos (_firstpos);
|
||||
_next->append_lastpos (_lastpos);
|
||||
|
||||
for (iter_ = _lastpos.begin (), end_ = _lastpos.end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
(*iter_)->append_followpos (_firstpos);
|
||||
}
|
||||
|
||||
for (iter_ = _firstpos.begin (), end_ = _firstpos.end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
(*iter_)->greedy (greedy_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~iteration_node ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual type what_type () const
|
||||
{
|
||||
return ITERATION;
|
||||
}
|
||||
|
||||
virtual bool traverse (const_node_stack &node_stack_,
|
||||
bool_stack &perform_op_stack_) const
|
||||
{
|
||||
perform_op_stack_.push (true);
|
||||
node_stack_.push (_next);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Not owner of this pointer...
|
||||
node *_next;
|
||||
bool _greedy;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &node_ptr_vector_,
|
||||
node_stack &new_node_stack_, bool_stack &perform_op_stack_,
|
||||
bool &down_) const
|
||||
{
|
||||
if (perform_op_stack_.top ())
|
||||
{
|
||||
node *ptr_ = new_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new iteration_node (ptr_, _greedy);
|
||||
new_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
else
|
||||
{
|
||||
down_ = true;
|
||||
}
|
||||
|
||||
perform_op_stack_.pop ();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
// leaf_node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_LEAF_NODE_HPP
|
||||
#define BOOST_LEXER_LEAF_NODE_HPP
|
||||
|
||||
#include "../../consts.hpp" // null_token
|
||||
#include "node.hpp"
|
||||
#include "../../size_t.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class leaf_node : public node
|
||||
{
|
||||
public:
|
||||
leaf_node (const std::size_t token_, const bool greedy_) :
|
||||
node (token_ == null_token),
|
||||
_token (token_),
|
||||
_set_greedy (!greedy_),
|
||||
_greedy (greedy_)
|
||||
{
|
||||
if (!_nullable)
|
||||
{
|
||||
_firstpos.push_back (this);
|
||||
_lastpos.push_back (this);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~leaf_node ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void append_followpos (const node_vector &followpos_)
|
||||
{
|
||||
for (node_vector::const_iterator iter_ = followpos_.begin (),
|
||||
end_ = followpos_.end (); iter_ != end_; ++iter_)
|
||||
{
|
||||
_followpos.push_back (*iter_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual type what_type () const
|
||||
{
|
||||
return LEAF;
|
||||
}
|
||||
|
||||
virtual bool traverse (const_node_stack &/*node_stack_*/,
|
||||
bool_stack &/*perform_op_stack_*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::size_t token () const
|
||||
{
|
||||
return _token;
|
||||
}
|
||||
|
||||
virtual void greedy (const bool greedy_)
|
||||
{
|
||||
if (!_set_greedy)
|
||||
{
|
||||
_greedy = greedy_;
|
||||
_set_greedy = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool greedy () const
|
||||
{
|
||||
return _greedy;
|
||||
}
|
||||
|
||||
virtual const node_vector &followpos () const
|
||||
{
|
||||
return _followpos;
|
||||
}
|
||||
|
||||
virtual node_vector &followpos ()
|
||||
{
|
||||
return _followpos;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t _token;
|
||||
bool _set_greedy;
|
||||
bool _greedy;
|
||||
node_vector _followpos;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &node_ptr_vector_,
|
||||
node_stack &new_node_stack_, bool_stack &/*perform_op_stack_*/,
|
||||
bool &/*down_*/) const
|
||||
{
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new leaf_node (_token, _greedy);
|
||||
new_node_stack_.push (node_ptr_vector_->back ());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
// node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_NODE_HPP
|
||||
#define BOOST_LEXER_NODE_HPP
|
||||
|
||||
#include <assert.h>
|
||||
#include "../../containers/ptr_vector.hpp"
|
||||
#include "../../runtime_error.hpp"
|
||||
#include "../../size_t.hpp"
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class node
|
||||
{
|
||||
public:
|
||||
enum type {LEAF, SEQUENCE, SELECTION, ITERATION, END};
|
||||
|
||||
typedef std::stack<bool> bool_stack;
|
||||
typedef std::stack<node *> node_stack;
|
||||
// stack and vector not owner of node pointers
|
||||
typedef std::stack<const node *> const_node_stack;
|
||||
typedef std::vector<node *> node_vector;
|
||||
typedef ptr_vector<node> node_ptr_vector;
|
||||
|
||||
node () :
|
||||
_nullable (false)
|
||||
{
|
||||
}
|
||||
|
||||
node (const bool nullable_) :
|
||||
_nullable (nullable_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~node ()
|
||||
{
|
||||
}
|
||||
|
||||
bool nullable () const
|
||||
{
|
||||
return _nullable;
|
||||
}
|
||||
|
||||
void append_firstpos (node_vector &firstpos_) const
|
||||
{
|
||||
firstpos_.insert (firstpos_.end (),
|
||||
_firstpos.begin (), _firstpos.end ());
|
||||
}
|
||||
|
||||
void append_lastpos (node_vector &lastpos_) const
|
||||
{
|
||||
lastpos_.insert (lastpos_.end (),
|
||||
_lastpos.begin (), _lastpos.end ());
|
||||
}
|
||||
|
||||
virtual void append_followpos (const node_vector &/*followpos_*/)
|
||||
{
|
||||
throw runtime_error ("Internal error node::append_followpos()");
|
||||
}
|
||||
|
||||
node *copy (node_ptr_vector &node_ptr_vector_) const
|
||||
{
|
||||
node *new_root_ = 0;
|
||||
const_node_stack node_stack_;
|
||||
bool_stack perform_op_stack_;
|
||||
bool down_ = true;
|
||||
node_stack new_node_stack_;
|
||||
|
||||
node_stack_.push (this);
|
||||
|
||||
while (!node_stack_.empty ())
|
||||
{
|
||||
while (down_)
|
||||
{
|
||||
down_ = node_stack_.top ()->traverse (node_stack_,
|
||||
perform_op_stack_);
|
||||
}
|
||||
|
||||
while (!down_ && !node_stack_.empty ())
|
||||
{
|
||||
const node *top_ = node_stack_.top ();
|
||||
|
||||
top_->copy_node (node_ptr_vector_, new_node_stack_, perform_op_stack_, down_);
|
||||
|
||||
if (!down_) node_stack_.pop ();
|
||||
}
|
||||
}
|
||||
|
||||
assert (new_node_stack_.size () == 1);
|
||||
new_root_ = new_node_stack_.top ();
|
||||
new_node_stack_.pop ();
|
||||
return new_root_;
|
||||
}
|
||||
|
||||
virtual type what_type () const = 0;
|
||||
|
||||
virtual bool traverse (const_node_stack &node_stack_,
|
||||
bool_stack &perform_op_stack_) const = 0;
|
||||
|
||||
node_vector &firstpos ()
|
||||
{
|
||||
return _firstpos;
|
||||
}
|
||||
|
||||
const node_vector &firstpos () const
|
||||
{
|
||||
return _firstpos;
|
||||
}
|
||||
|
||||
// _lastpos modified externally, so not const &
|
||||
node_vector &lastpos ()
|
||||
{
|
||||
return _lastpos;
|
||||
}
|
||||
|
||||
virtual bool end_state () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::size_t id () const
|
||||
{
|
||||
throw runtime_error ("Internal error node::id()");
|
||||
}
|
||||
|
||||
virtual std::size_t lexer_state () const
|
||||
{
|
||||
throw runtime_error ("Internal error node::state()");
|
||||
}
|
||||
|
||||
virtual std::size_t token () const
|
||||
{
|
||||
throw runtime_error ("Internal error node::token()");
|
||||
}
|
||||
|
||||
virtual void greedy (const bool /*greedy_*/)
|
||||
{
|
||||
throw runtime_error ("Internal error node::token(bool)");
|
||||
}
|
||||
|
||||
virtual bool greedy () const
|
||||
{
|
||||
throw runtime_error ("Internal error node::token()");
|
||||
}
|
||||
|
||||
virtual const node_vector &followpos () const
|
||||
{
|
||||
throw runtime_error ("Internal error node::followpos()");
|
||||
}
|
||||
|
||||
virtual node_vector &followpos ()
|
||||
{
|
||||
throw runtime_error ("Internal error node::followpos()");
|
||||
}
|
||||
|
||||
protected:
|
||||
const bool _nullable;
|
||||
node_vector _firstpos;
|
||||
node_vector _lastpos;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &node_ptr_vector_,
|
||||
node_stack &new_node_stack_, bool_stack &perform_op_stack_,
|
||||
bool &down_) const = 0;
|
||||
|
||||
private:
|
||||
node (node const &); // No copy construction.
|
||||
node &operator = (node const &); // No assignment.
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
// selection_node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_SELECTION_NODE_HPP
|
||||
#define BOOST_LEXER_SELECTION_NODE_HPP
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class selection_node : public node
|
||||
{
|
||||
public:
|
||||
selection_node (node *left_, node *right_) :
|
||||
node (left_->nullable () || right_->nullable ()),
|
||||
_left (left_),
|
||||
_right (right_)
|
||||
{
|
||||
_left->append_firstpos (_firstpos);
|
||||
_right->append_firstpos (_firstpos);
|
||||
_left->append_lastpos (_lastpos);
|
||||
_right->append_lastpos (_lastpos);
|
||||
}
|
||||
|
||||
virtual ~selection_node ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual type what_type () const
|
||||
{
|
||||
return SELECTION;
|
||||
}
|
||||
|
||||
virtual bool traverse (const_node_stack &node_stack_,
|
||||
bool_stack &perform_op_stack_) const
|
||||
{
|
||||
perform_op_stack_.push (true);
|
||||
|
||||
switch (_right->what_type ())
|
||||
{
|
||||
case SEQUENCE:
|
||||
case SELECTION:
|
||||
case ITERATION:
|
||||
perform_op_stack_.push (false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
node_stack_.push (_right);
|
||||
node_stack_.push (_left);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Not owner of these pointers...
|
||||
node *_left;
|
||||
node *_right;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &node_ptr_vector_,
|
||||
node_stack &new_node_stack_, bool_stack &perform_op_stack_,
|
||||
bool &down_) const
|
||||
{
|
||||
if (perform_op_stack_.top ())
|
||||
{
|
||||
node *rhs_ = new_node_stack_.top ();
|
||||
|
||||
new_node_stack_.pop ();
|
||||
|
||||
node *lhs_ = new_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new selection_node (lhs_, rhs_);
|
||||
new_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
else
|
||||
{
|
||||
down_ = true;
|
||||
}
|
||||
|
||||
perform_op_stack_.pop ();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
// sequence_node.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_SEQUENCE_NODE_HPP
|
||||
#define BOOST_LEXER_SEQUENCE_NODE_HPP
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class sequence_node : public node
|
||||
{
|
||||
public:
|
||||
sequence_node (node *left_, node *right_) :
|
||||
node (left_->nullable () && right_->nullable ()),
|
||||
_left (left_),
|
||||
_right (right_)
|
||||
{
|
||||
_left->append_firstpos (_firstpos);
|
||||
|
||||
if (_left->nullable ())
|
||||
{
|
||||
_right->append_firstpos (_firstpos);
|
||||
}
|
||||
|
||||
if (_right->nullable ())
|
||||
{
|
||||
_left->append_lastpos (_lastpos);
|
||||
}
|
||||
|
||||
_right->append_lastpos (_lastpos);
|
||||
|
||||
node_vector &lastpos_ = _left->lastpos ();
|
||||
const node_vector &firstpos_ = _right->firstpos ();
|
||||
|
||||
for (node_vector::iterator iter_ = lastpos_.begin (),
|
||||
end_ = lastpos_.end (); iter_ != end_; ++iter_)
|
||||
{
|
||||
(*iter_)->append_followpos (firstpos_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~sequence_node ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual type what_type () const
|
||||
{
|
||||
return SEQUENCE;
|
||||
}
|
||||
|
||||
virtual bool traverse (const_node_stack &node_stack_,
|
||||
bool_stack &perform_op_stack_) const
|
||||
{
|
||||
perform_op_stack_.push (true);
|
||||
|
||||
switch (_right->what_type ())
|
||||
{
|
||||
case SEQUENCE:
|
||||
case SELECTION:
|
||||
case ITERATION:
|
||||
perform_op_stack_.push (false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
node_stack_.push (_right);
|
||||
node_stack_.push (_left);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Not owner of these pointers...
|
||||
node *_left;
|
||||
node *_right;
|
||||
|
||||
virtual void copy_node (node_ptr_vector &node_ptr_vector_,
|
||||
node_stack &new_node_stack_, bool_stack &perform_op_stack_,
|
||||
bool &down_) const
|
||||
{
|
||||
if (perform_op_stack_.top ())
|
||||
{
|
||||
node *rhs_ = new_node_stack_.top ();
|
||||
|
||||
new_node_stack_.pop ();
|
||||
|
||||
node *lhs_ = new_node_stack_.top ();
|
||||
|
||||
node_ptr_vector_->push_back (0);
|
||||
node_ptr_vector_->back () = new sequence_node (lhs_, rhs_);
|
||||
new_node_stack_.top () = node_ptr_vector_->back ();
|
||||
}
|
||||
else
|
||||
{
|
||||
down_ = true;
|
||||
}
|
||||
|
||||
perform_op_stack_.pop ();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
// charset.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_CHARSET_HPP
|
||||
#define BOOST_LEXER_CHARSET_HPP
|
||||
|
||||
#include <set>
|
||||
#include "../size_t.hpp"
|
||||
#include "../string_token.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename CharT>
|
||||
struct basic_charset
|
||||
{
|
||||
typedef basic_string_token<CharT> token;
|
||||
typedef std::set<std::size_t> index_set;
|
||||
|
||||
token _token;
|
||||
index_set _index_set;
|
||||
|
||||
basic_charset ()
|
||||
{
|
||||
}
|
||||
|
||||
basic_charset (const token &token_, const std::size_t index_) :
|
||||
_token (token_)
|
||||
{
|
||||
_index_set.insert (index_);
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return _token.empty () && _index_set.empty ();
|
||||
}
|
||||
|
||||
void intersect (basic_charset &rhs_, basic_charset &overlap_)
|
||||
{
|
||||
_token.intersect (rhs_._token, overlap_._token);
|
||||
|
||||
if (!overlap_._token.empty ())
|
||||
{
|
||||
typename index_set::const_iterator iter_ = _index_set.begin ();
|
||||
typename index_set::const_iterator end_ = _index_set.end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
overlap_._index_set.insert (*iter_);
|
||||
}
|
||||
|
||||
iter_ = rhs_._index_set.begin ();
|
||||
end_ = rhs_._index_set.end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
overlap_._index_set.insert (*iter_);
|
||||
}
|
||||
|
||||
if (_token.empty ())
|
||||
{
|
||||
_index_set.clear ();
|
||||
}
|
||||
|
||||
if (rhs_._token.empty ())
|
||||
{
|
||||
rhs_._index_set.clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
// equivset.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_EQUIVSET_HPP
|
||||
#define BOOST_LEXER_EQUIVSET_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include "../parser/tree/node.hpp"
|
||||
#include <set>
|
||||
#include "../size_t.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct equivset
|
||||
{
|
||||
typedef std::set<std::size_t> index_set;
|
||||
typedef std::vector<std::size_t> index_vector;
|
||||
// Not owner of nodes:
|
||||
typedef std::vector<node *> node_vector;
|
||||
|
||||
index_vector _index_vector;
|
||||
bool _greedy;
|
||||
std::size_t _id;
|
||||
node_vector _followpos;
|
||||
|
||||
equivset () :
|
||||
_greedy (true),
|
||||
_id (0)
|
||||
{
|
||||
}
|
||||
|
||||
equivset (const index_set &index_set_, const bool greedy_,
|
||||
const std::size_t id_, const node_vector &followpos_) :
|
||||
_greedy (greedy_),
|
||||
_id (id_),
|
||||
_followpos (followpos_)
|
||||
{
|
||||
index_set::const_iterator iter_ = index_set_.begin ();
|
||||
index_set::const_iterator end_ = index_set_.end ();
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
_index_vector.push_back (*iter_);
|
||||
}
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return _index_vector.empty () && _followpos.empty ();
|
||||
}
|
||||
|
||||
void intersect (equivset &rhs_, equivset &overlap_)
|
||||
{
|
||||
intersect_indexes (rhs_._index_vector, overlap_._index_vector);
|
||||
|
||||
if (!overlap_._index_vector.empty ())
|
||||
{
|
||||
// Note that the LHS takes priority in order to
|
||||
// respect rule ordering priority in the lex spec.
|
||||
overlap_._id = _id;
|
||||
overlap_._greedy = _greedy;
|
||||
overlap_._followpos = _followpos;
|
||||
|
||||
node_vector::const_iterator overlap_begin_ =
|
||||
overlap_._followpos.begin ();
|
||||
node_vector::const_iterator overlap_end_ =
|
||||
overlap_._followpos.end ();
|
||||
node_vector::const_iterator rhs_iter_ =
|
||||
rhs_._followpos.begin ();
|
||||
node_vector::const_iterator rhs_end_ =
|
||||
rhs_._followpos.end ();
|
||||
|
||||
for (; rhs_iter_ != rhs_end_; ++rhs_iter_)
|
||||
{
|
||||
node *node_ = *rhs_iter_;
|
||||
|
||||
if (std::find (overlap_begin_, overlap_end_, node_) ==
|
||||
overlap_end_)
|
||||
{
|
||||
overlap_._followpos.push_back (node_);
|
||||
overlap_begin_ = overlap_._followpos.begin ();
|
||||
overlap_end_ = overlap_._followpos.end ();
|
||||
}
|
||||
}
|
||||
|
||||
if (_index_vector.empty ())
|
||||
{
|
||||
_followpos.clear ();
|
||||
}
|
||||
|
||||
if (rhs_._index_vector.empty ())
|
||||
{
|
||||
rhs_._followpos.clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void intersect_indexes (index_vector &rhs_, index_vector &overlap_)
|
||||
{
|
||||
index_vector::iterator iter_ = _index_vector.begin ();
|
||||
index_vector::iterator end_ = _index_vector.end ();
|
||||
index_vector::iterator rhs_iter_ = rhs_.begin ();
|
||||
index_vector::iterator rhs_end_ = rhs_.end ();
|
||||
|
||||
while (iter_ != end_ && rhs_iter_ != rhs_end_)
|
||||
{
|
||||
const std::size_t index_ = *iter_;
|
||||
const std::size_t rhs_index_ = *rhs_iter_;
|
||||
|
||||
if (index_ < rhs_index_)
|
||||
{
|
||||
++iter_;
|
||||
}
|
||||
else if (index_ > rhs_index_)
|
||||
{
|
||||
++rhs_iter_;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlap_.push_back (index_);
|
||||
iter_ = _index_vector.erase (iter_);
|
||||
end_ = _index_vector.end ();
|
||||
rhs_iter_ = rhs_.erase (rhs_iter_);
|
||||
rhs_end_ = rhs_.end ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,524 @@
|
||||
// rules.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_RULES_HPP
|
||||
#define BOOST_LEXER_RULES_HPP
|
||||
|
||||
#include "consts.hpp"
|
||||
#include <deque>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include "runtime_error.hpp"
|
||||
#include <set>
|
||||
#include "size_t.hpp"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// return name of initial state
|
||||
template <typename CharT>
|
||||
struct initial;
|
||||
|
||||
template <>
|
||||
struct initial<char>
|
||||
{
|
||||
static const char *str ()
|
||||
{
|
||||
return "INITIAL";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct initial<wchar_t>
|
||||
{
|
||||
static const wchar_t *str ()
|
||||
{
|
||||
return L"INITIAL";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
class basic_rules
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::size_t> id_vector;
|
||||
typedef std::deque<id_vector> id_vector_deque;
|
||||
typedef std::basic_string<CharT> string;
|
||||
typedef std::deque<string> string_deque;
|
||||
typedef std::deque<string_deque> string_deque_deque;
|
||||
typedef std::set<string> string_set;
|
||||
typedef std::pair<string, string> string_pair;
|
||||
typedef std::deque<string_pair> string_pair_deque;
|
||||
typedef std::map<string, std::size_t> string_size_t_map;
|
||||
typedef std::pair<string, std::size_t> string_size_t_pair;
|
||||
|
||||
basic_rules (const regex_flags flags_ = dot_not_newline) :
|
||||
_flags (flags_)
|
||||
{
|
||||
add_state (initial ());
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
_statemap.clear ();
|
||||
_macrodeque.clear ();
|
||||
_macroset.clear ();
|
||||
_regexes.clear ();
|
||||
_ids.clear ();
|
||||
_states.clear ();
|
||||
_flags = dot_not_newline;
|
||||
_locale = std::locale ();
|
||||
add_state (initial ());
|
||||
}
|
||||
|
||||
void clear (const CharT *state_name_)
|
||||
{
|
||||
std::size_t state_ = state (state_name_);
|
||||
|
||||
if (state_ != npos)
|
||||
{
|
||||
_regexes[state_].clear ();
|
||||
_ids[state_].clear ();
|
||||
_states[state_].clear ();
|
||||
}
|
||||
}
|
||||
|
||||
void flags (const regex_flags flags_)
|
||||
{
|
||||
_flags = flags_;
|
||||
}
|
||||
|
||||
regex_flags flags () const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
std::locale imbue (std::locale &locale_)
|
||||
{
|
||||
std::locale loc_ = _locale;
|
||||
|
||||
_locale = locale_;
|
||||
return loc_;
|
||||
}
|
||||
|
||||
const std::locale &locale () const
|
||||
{
|
||||
return _locale;
|
||||
}
|
||||
|
||||
std::size_t state (const CharT *name_) const
|
||||
{
|
||||
std::size_t state_ = npos;
|
||||
typename string_size_t_map::const_iterator iter_ =
|
||||
_statemap.find (name_);
|
||||
|
||||
if (iter_ != _statemap.end ())
|
||||
{
|
||||
state_ = iter_->second;
|
||||
}
|
||||
|
||||
return state_;
|
||||
}
|
||||
|
||||
void add_state (const CharT *name_)
|
||||
{
|
||||
validate (name_, true);
|
||||
|
||||
if (_statemap.insert (string_size_t_pair (name_,
|
||||
_statemap.size ())).second)
|
||||
{
|
||||
_regexes.push_back (string_deque ());
|
||||
_ids.push_back (id_vector ());
|
||||
_states.push_back (id_vector ());
|
||||
}
|
||||
}
|
||||
|
||||
void add_macro (const CharT *name_, const CharT *regex_)
|
||||
{
|
||||
add_macro (name_, string (regex_));
|
||||
}
|
||||
|
||||
void add_macro (const CharT *name_, const CharT *regex_start_,
|
||||
const CharT *regex_end_)
|
||||
{
|
||||
add_macro (name_, string (regex_start_, regex_end_));
|
||||
}
|
||||
|
||||
void add_macro (const CharT *name_, const string ®ex_)
|
||||
{
|
||||
validate (name_, false);
|
||||
|
||||
typename string_set::const_iterator iter_ = _macroset.find (name_);
|
||||
|
||||
if (iter_ == _macroset.end ())
|
||||
{
|
||||
_macrodeque.push_back (string_pair (name_, regex_));
|
||||
_macroset.insert (name_);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Attempt to redefine MACRO '";
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
os_ << ss_.narrow (*name_++, static_cast<CharT> (' '));
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
}
|
||||
|
||||
void add (const CharT *regex_, const std::size_t id_)
|
||||
{
|
||||
add (string (regex_), id_);
|
||||
}
|
||||
|
||||
void add (const CharT *regex_start_, const CharT *regex_end_,
|
||||
const std::size_t id_)
|
||||
{
|
||||
add (string (regex_start_, regex_end_), id_);
|
||||
}
|
||||
|
||||
void add (const string ®ex_, const std::size_t id_)
|
||||
{
|
||||
check_for_invalid_id (id_);
|
||||
_regexes[0].push_back (regex_);
|
||||
_ids[0].push_back (id_);
|
||||
_states[0].push_back (0);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const CharT *regex_,
|
||||
const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, string (regex_), new_state_);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const CharT *regex_start_,
|
||||
const CharT *regex_end_, const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, string (regex_start_, regex_end_), new_state_);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const string ®ex_,
|
||||
const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, regex_, 0, new_state_, false);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const CharT *regex_,
|
||||
const std::size_t id_, const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, string (regex_), id_, new_state_);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const CharT *regex_start_,
|
||||
const CharT *regex_end_, const std::size_t id_, const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, string (regex_start_, regex_end_), id_, new_state_);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const string ®ex_,
|
||||
const std::size_t id_, const CharT *new_state_)
|
||||
{
|
||||
add (curr_state_, regex_, id_, new_state_, true);
|
||||
}
|
||||
|
||||
void add (const CharT *curr_state_, const basic_rules &rules_)
|
||||
{
|
||||
const string_deque_deque ®exes_ = rules_.regexes ();
|
||||
const id_vector_deque &ids_ = rules_.ids ();
|
||||
typename string_deque_deque::const_iterator state_regex_iter_ =
|
||||
regexes_.begin ();
|
||||
typename string_deque_deque::const_iterator state_regex_end_ =
|
||||
regexes_.end ();
|
||||
typename id_vector_deque::const_iterator state_id_iter_ =
|
||||
ids_.begin ();
|
||||
typename string_deque::const_iterator regex_iter_;
|
||||
typename string_deque::const_iterator regex_end_;
|
||||
typename id_vector::const_iterator id_iter_;
|
||||
|
||||
for (; state_regex_iter_ != state_regex_end_; ++state_regex_iter_)
|
||||
{
|
||||
regex_iter_ = state_regex_iter_->begin ();
|
||||
regex_end_ = state_regex_iter_->end ();
|
||||
id_iter_ = state_id_iter_->begin ();
|
||||
|
||||
for (; regex_iter_ != regex_end_; ++regex_iter_, ++id_iter_)
|
||||
{
|
||||
add (curr_state_, *regex_iter_, *id_iter_, curr_state_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const string_size_t_map &statemap () const
|
||||
{
|
||||
return _statemap;
|
||||
}
|
||||
|
||||
const string_pair_deque ¯odeque () const
|
||||
{
|
||||
return _macrodeque;
|
||||
}
|
||||
|
||||
const string_deque_deque ®exes () const
|
||||
{
|
||||
return _regexes;
|
||||
}
|
||||
|
||||
const id_vector_deque &ids () const
|
||||
{
|
||||
return _ids;
|
||||
}
|
||||
|
||||
const id_vector_deque &states () const
|
||||
{
|
||||
return _states;
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
typename string_deque_deque::const_iterator iter_ = _regexes.begin ();
|
||||
typename string_deque_deque::const_iterator end_ = _regexes.end ();
|
||||
bool empty_ = true;
|
||||
|
||||
for (; iter_ != end_; ++iter_)
|
||||
{
|
||||
if (!iter_->empty ())
|
||||
{
|
||||
empty_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return empty_;
|
||||
}
|
||||
|
||||
static const CharT *initial ()
|
||||
{
|
||||
return detail::initial<CharT>::str ();
|
||||
}
|
||||
|
||||
private:
|
||||
string_size_t_map _statemap;
|
||||
string_pair_deque _macrodeque;
|
||||
string_set _macroset;
|
||||
string_deque_deque _regexes;
|
||||
id_vector_deque _ids;
|
||||
id_vector_deque _states;
|
||||
regex_flags _flags;
|
||||
std::locale _locale;
|
||||
|
||||
void add (const CharT *curr_state_, const string ®ex_,
|
||||
const std::size_t id_, const CharT *new_state_, const bool check_)
|
||||
{
|
||||
const bool star_ = *curr_state_ == '*' && *(curr_state_ + 1) == 0;
|
||||
const bool dot_ = *new_state_ == '.' && *(new_state_ + 1) == 0;
|
||||
|
||||
if (check_)
|
||||
{
|
||||
check_for_invalid_id (id_);
|
||||
}
|
||||
|
||||
if (!dot_)
|
||||
{
|
||||
validate (new_state_, true);
|
||||
}
|
||||
|
||||
std::size_t new_ = string::npos;
|
||||
typename string_size_t_map::const_iterator iter_;
|
||||
typename string_size_t_map::const_iterator end_ = _statemap.end ();
|
||||
id_vector states_;
|
||||
|
||||
if (!dot_)
|
||||
{
|
||||
iter_ = _statemap.find (new_state_);
|
||||
|
||||
if (iter_ == end_)
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Unknown state name '";
|
||||
|
||||
while (*new_state_)
|
||||
{
|
||||
os_ << ss_.narrow (*new_state_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
|
||||
new_ = iter_->second;
|
||||
}
|
||||
|
||||
if (star_)
|
||||
{
|
||||
const std::size_t size_ = _statemap.size ();
|
||||
|
||||
for (std::size_t i_ = 0; i_ < size_; ++i_)
|
||||
{
|
||||
states_.push_back (i_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const CharT *start_ = curr_state_;
|
||||
string state_;
|
||||
|
||||
while (*curr_state_)
|
||||
{
|
||||
while (*curr_state_ && *curr_state_ != ',')
|
||||
{
|
||||
++curr_state_;
|
||||
}
|
||||
|
||||
state_.assign (start_, curr_state_);
|
||||
|
||||
if (*curr_state_)
|
||||
{
|
||||
++curr_state_;
|
||||
start_ = curr_state_;
|
||||
}
|
||||
|
||||
validate (state_.c_str (), true);
|
||||
iter_ = _statemap.find (state_.c_str ());
|
||||
|
||||
if (iter_ == end_)
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Unknown state name '";
|
||||
|
||||
while (*curr_state_)
|
||||
{
|
||||
os_ << ss_.narrow (*curr_state_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
|
||||
states_.push_back (iter_->second);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i_ = 0, size_ = states_.size (); i_ < size_; ++i_)
|
||||
{
|
||||
const std::size_t curr_ = states_[i_];
|
||||
|
||||
_regexes[curr_].push_back (regex_);
|
||||
_ids[curr_].push_back (id_);
|
||||
_states[curr_].push_back (dot_ ? curr_ : new_);
|
||||
}
|
||||
}
|
||||
|
||||
void validate (const CharT *name_, const bool comma_) const
|
||||
{
|
||||
again:
|
||||
const CharT *start_ = name_;
|
||||
|
||||
if (*name_ != '_' && !(*name_ >= 'A' && *name_ <= 'Z') &&
|
||||
!(*name_ >= 'a' && *name_ <= 'z'))
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Invalid name '";
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
os_ << ss_.narrow (*name_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
else if (*name_)
|
||||
{
|
||||
++name_;
|
||||
}
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
if (*name_ == ',' && comma_)
|
||||
{
|
||||
++name_;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (*name_ != '_' && *name_ != '-' &&
|
||||
!(*name_ >= 'A' && *name_ <= 'Z') &&
|
||||
!(*name_ >= 'a' && *name_ <= 'z') &&
|
||||
!(*name_ >= '0' && *name_ <= '9'))
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Invalid name '";
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
os_ << ss_.narrow (*name_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "'.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
|
||||
++name_;
|
||||
}
|
||||
|
||||
if (name_ - start_ > static_cast<std::ptrdiff_t>(max_macro_len))
|
||||
{
|
||||
std::basic_stringstream<CharT> ss_;
|
||||
std::ostringstream os_;
|
||||
|
||||
os_ << "Name '";
|
||||
|
||||
while (*name_)
|
||||
{
|
||||
os_ << ss_.narrow (*name_++, ' ');
|
||||
}
|
||||
|
||||
os_ << "' too long.";
|
||||
throw runtime_error (os_.str ());
|
||||
}
|
||||
}
|
||||
|
||||
void check_for_invalid_id (const std::size_t id_) const
|
||||
{
|
||||
switch (id_)
|
||||
{
|
||||
case 0:
|
||||
throw runtime_error ("id 0 is reserved for EOF.");
|
||||
case npos:
|
||||
throw runtime_error ("id npos is reserved for the "
|
||||
"UNKNOWN token.");
|
||||
default:
|
||||
// OK
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_rules<char> rules;
|
||||
typedef basic_rules<wchar_t> wrules;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
// runtime_error.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_RUNTIME_ERROR_HPP
|
||||
#define BOOST_LEXER_RUNTIME_ERROR_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
class runtime_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
runtime_error (const std::string &what_arg_) :
|
||||
std::runtime_error (what_arg_)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
// examples/serialise.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_SERIALISE_HPP
|
||||
#define BOOST_LEXER_SERIALISE_HPP
|
||||
|
||||
#include "state_machine.hpp"
|
||||
#include <boost/serialization/vector.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
// IMPORTANT! This won't work if you don't enable RTTI!
|
||||
template<typename CharT, class Archive>
|
||||
void serialise (basic_state_machine<CharT> &sm_, Archive &ar_, unsigned int version_ = 1)
|
||||
{
|
||||
ar_ & version_;
|
||||
ar_ & *sm_._lookup;
|
||||
ar_ & sm_._dfa_alphabet;
|
||||
ar_ & *sm_._dfa;
|
||||
ar_ & sm_._seen_BOL_assertion;
|
||||
ar_ & sm_._seen_EOL_assertion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
// size_t.h
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_SIZE_T_H
|
||||
#define BOOST_LEXER_SIZE_T_H
|
||||
|
||||
#include <stddef.h> // ptrdiff_t
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
namespace std
|
||||
{
|
||||
using ::ptrdiff_t;
|
||||
using ::size_t;
|
||||
}
|
||||
#else
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,448 @@
|
||||
// state_machine.hpp
|
||||
// Copyright (c) 2007 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_STATE_MACHINE_HPP
|
||||
#define BOOST_LEXER_STATE_MACHINE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include "conversion/char_state_machine.hpp"
|
||||
#include "consts.hpp"
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include "containers/ptr_vector.hpp"
|
||||
#include "size_t.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT>
|
||||
class basic_state_machine
|
||||
{
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend basic_state_machine;
|
||||
#else
|
||||
friend class basic_state_machine;
|
||||
#endif
|
||||
|
||||
struct data
|
||||
{
|
||||
// Current iterator info
|
||||
std::size_t dfa;
|
||||
std::size_t states;
|
||||
std::size_t state;
|
||||
std::size_t transitions;
|
||||
std::size_t transition;
|
||||
|
||||
// Current state info
|
||||
bool end_state;
|
||||
std::size_t id;
|
||||
std::size_t goto_dfa;
|
||||
std::size_t bol_index;
|
||||
std::size_t eol_index;
|
||||
|
||||
// Current transition info
|
||||
basic_string_token<CharT> token;
|
||||
std::size_t goto_state;
|
||||
|
||||
data () :
|
||||
dfa (npos),
|
||||
states (0),
|
||||
state (npos),
|
||||
transitions (0),
|
||||
transition (npos),
|
||||
end_state (false),
|
||||
id (npos),
|
||||
goto_dfa (npos),
|
||||
bol_index (npos),
|
||||
eol_index (npos),
|
||||
goto_state (npos)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const data &rhs_) const
|
||||
{
|
||||
return dfa == rhs_.dfa &&
|
||||
states == rhs_.states &&
|
||||
state == rhs_.state &&
|
||||
transitions == rhs_.transitions &&
|
||||
transition == rhs_.transition &&
|
||||
end_state == rhs_.end_state &&
|
||||
id == rhs_.id &&
|
||||
goto_dfa == rhs_.goto_dfa &&
|
||||
bol_index == rhs_.bol_index &&
|
||||
eol_index == rhs_.eol_index &&
|
||||
token == rhs_.token &&
|
||||
transition == rhs_.transition;
|
||||
}
|
||||
};
|
||||
|
||||
iterator () :
|
||||
_sm (0),
|
||||
_dfas (0),
|
||||
_dfa (npos),
|
||||
_states (0),
|
||||
_state (npos),
|
||||
_transitions (0),
|
||||
_transition (npos)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const iterator &rhs_) const
|
||||
{
|
||||
return _dfas == rhs_._dfas && _dfa == rhs_._dfa &&
|
||||
_states == rhs_._states && _state == rhs_._state &&
|
||||
_transitions == rhs_._transitions &&
|
||||
_transition == rhs_._transition;
|
||||
}
|
||||
|
||||
bool operator != (const iterator &rhs_) const
|
||||
{
|
||||
return !(*this == rhs_);
|
||||
}
|
||||
|
||||
data &operator * ()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
data *operator -> ()
|
||||
{
|
||||
return &_data;
|
||||
}
|
||||
|
||||
// Let compiler generate operator = ().
|
||||
|
||||
// prefix version
|
||||
iterator &operator ++ ()
|
||||
{
|
||||
next ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// postfix version
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator iter_ = *this;
|
||||
|
||||
next ();
|
||||
return iter_;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
_dfas = _states = _transitions = 0;
|
||||
_dfa = _state = _transition = npos;
|
||||
}
|
||||
|
||||
private:
|
||||
basic_state_machine *_sm;
|
||||
data _data;
|
||||
std::size_t _dfas;
|
||||
std::size_t _dfa;
|
||||
std::size_t _states;
|
||||
std::size_t _state;
|
||||
std::size_t _transitions;
|
||||
std::size_t _transition;
|
||||
typename detail::basic_char_state_machine<CharT>::state::
|
||||
size_t_string_token_map::const_iterator _token_iter;
|
||||
typename detail::basic_char_state_machine<CharT>::state::
|
||||
size_t_string_token_map::const_iterator _token_end;
|
||||
|
||||
void next ()
|
||||
{
|
||||
bool reset_state_ = false;
|
||||
|
||||
if (_transition >= _transitions)
|
||||
{
|
||||
_transition = _data.transition = 0;
|
||||
_data.state = ++_state;
|
||||
reset_state_ = true;
|
||||
|
||||
if (_state >= _states)
|
||||
{
|
||||
++_dfa;
|
||||
|
||||
if (_dfa >= _dfas)
|
||||
{
|
||||
clear ();
|
||||
reset_state_ = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_states = _sm->_csm._sm_vector[_dfa].size ();
|
||||
_state = _data.state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.transition = _transition;
|
||||
}
|
||||
|
||||
if (reset_state_)
|
||||
{
|
||||
const typename detail::basic_char_state_machine<CharT>::
|
||||
state *ptr_ = &_sm->_csm._sm_vector[_dfa][_state];
|
||||
|
||||
_transitions = _data.transitions = ptr_->_transitions.size ();
|
||||
_data.end_state = ptr_->_end_state;
|
||||
_data.id = ptr_->_id;
|
||||
_data.goto_dfa = ptr_->_state;
|
||||
_data.bol_index = ptr_->_bol_index;
|
||||
_data.eol_index = ptr_->_eol_index;
|
||||
_token_iter = ptr_->_transitions.begin ();
|
||||
_token_end = ptr_->_transitions.end ();
|
||||
}
|
||||
|
||||
if (_token_iter != _token_end)
|
||||
{
|
||||
_data.token = _token_iter->second;
|
||||
_data.goto_state = _token_iter->first;
|
||||
++_token_iter;
|
||||
++_transition;
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.token.clear ();
|
||||
_data.goto_state = npos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
friend iterator;
|
||||
#else
|
||||
friend class iterator;
|
||||
#endif
|
||||
|
||||
basic_state_machine () :
|
||||
_seen_BOL_assertion (false),
|
||||
_seen_EOL_assertion (false)
|
||||
{
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
_lookup.clear ();
|
||||
_dfa_alphabet.clear ();
|
||||
_dfa.clear ();
|
||||
_seen_BOL_assertion = false;
|
||||
_seen_EOL_assertion = false;
|
||||
_csm.clear ();
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
// Don't include _csm in this test, as irrelevant to state.
|
||||
return _lookup->empty () && _dfa_alphabet.empty () &&
|
||||
_dfa->empty ();
|
||||
}
|
||||
|
||||
std::size_t size () const
|
||||
{
|
||||
return _dfa->size ();
|
||||
}
|
||||
|
||||
bool operator == (const basic_state_machine &rhs_) const
|
||||
{
|
||||
// Don't include _csm in this test, as irrelevant to state.
|
||||
return _lookup == rhs_._lookup &&
|
||||
_dfa_alphabet == rhs_._dfa_alphabet &&
|
||||
_dfa == rhs_._dfa &&
|
||||
_seen_BOL_assertion == rhs_._seen_BOL_assertion &&
|
||||
_seen_EOL_assertion == rhs_._seen_EOL_assertion;
|
||||
}
|
||||
|
||||
iterator begin () const
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._sm = const_cast<basic_state_machine *>(this);
|
||||
check_for_csm ();
|
||||
|
||||
if (!_csm.empty())
|
||||
{
|
||||
const typename detail::basic_char_state_machine<CharT>::
|
||||
state_vector *ptr_ = &_csm._sm_vector[0];
|
||||
|
||||
iter_._dfas = _csm._sm_vector.size ();
|
||||
iter_._states = iter_._data.states = ptr_->size ();
|
||||
iter_._transitions = iter_._data.transitions =
|
||||
ptr_->front ()._transitions.size ();
|
||||
iter_._dfa = iter_._data.dfa = 0;
|
||||
iter_._state = iter_._data.state = 0;
|
||||
iter_._transition = 0;
|
||||
iter_._data.end_state = ptr_->front ()._end_state;
|
||||
iter_._data.id = ptr_->front ()._id;
|
||||
iter_._data.goto_dfa = ptr_->front ()._state;
|
||||
iter_._data.bol_index = ptr_->front ()._bol_index;
|
||||
iter_._data.eol_index = ptr_->front ()._eol_index;
|
||||
iter_._token_iter = ptr_->front ()._transitions.begin ();
|
||||
iter_._token_end = ptr_->front ()._transitions.end ();
|
||||
++iter_;
|
||||
}
|
||||
|
||||
return iter_;
|
||||
}
|
||||
|
||||
iterator end () const
|
||||
{
|
||||
iterator iter_;
|
||||
|
||||
iter_._sm = const_cast<basic_state_machine *>(this);
|
||||
return iter_;
|
||||
}
|
||||
|
||||
void swap (basic_state_machine &sm_)
|
||||
{
|
||||
_lookup->swap (*sm_._lookup);
|
||||
_dfa_alphabet.swap (sm_._dfa_alphabet);
|
||||
_dfa->swap (*sm_._dfa);
|
||||
std::swap (_seen_BOL_assertion, sm_._seen_BOL_assertion);
|
||||
std::swap (_seen_EOL_assertion, sm_._seen_EOL_assertion);
|
||||
_csm.swap (sm_._csm);
|
||||
}
|
||||
|
||||
// VC++ 6, 7.1 and 8 can't cope with template friend classes!
|
||||
// #if !(defined _MSC_VER && _MSC_VER < 1500)
|
||||
// private:
|
||||
// #endif
|
||||
typedef std::vector<std::size_t> size_t_vector;
|
||||
typedef detail::ptr_vector<size_t_vector> size_t_vector_vector;
|
||||
|
||||
size_t_vector_vector _lookup;
|
||||
size_t_vector _dfa_alphabet;
|
||||
size_t_vector_vector _dfa;
|
||||
bool _seen_BOL_assertion;
|
||||
bool _seen_EOL_assertion;
|
||||
mutable detail::basic_char_state_machine<CharT> _csm;
|
||||
|
||||
void check_for_csm () const
|
||||
{
|
||||
if (_csm.empty ())
|
||||
{
|
||||
human_readable (_csm);
|
||||
}
|
||||
}
|
||||
|
||||
void human_readable (detail::basic_char_state_machine<CharT> &sm_) const
|
||||
{
|
||||
const std::size_t max_ = sizeof (CharT) == 1 ?
|
||||
num_chars : num_wchar_ts;
|
||||
const std::size_t start_states_ = _dfa->size ();
|
||||
|
||||
sm_.clear ();
|
||||
sm_._sm_vector.resize (start_states_);
|
||||
|
||||
for (std::size_t start_state_index_ = 0;
|
||||
start_state_index_ < start_states_; ++start_state_index_)
|
||||
{
|
||||
const size_t_vector *lu_ = _lookup[start_state_index_];
|
||||
const std::size_t alphabet_ = _dfa_alphabet[start_state_index_] - dfa_offset;
|
||||
std::vector<std::basic_string<CharT> > chars_ (alphabet_);
|
||||
const std::size_t states_ = _dfa[start_state_index_]->size () /
|
||||
(alphabet_ + dfa_offset);
|
||||
const std::size_t *read_ptr_ = &_dfa[start_state_index_]->
|
||||
front () + alphabet_ + dfa_offset;
|
||||
|
||||
sm_._sm_vector[start_state_index_].resize (states_ - 1);
|
||||
|
||||
for (std::size_t alpha_index_ = 0; alpha_index_ < max_;
|
||||
++alpha_index_)
|
||||
{
|
||||
const std::size_t col_ = lu_->at (alpha_index_);
|
||||
|
||||
if (col_ != dead_state_index)
|
||||
{
|
||||
chars_[col_ - dfa_offset] += static_cast<CharT>
|
||||
(alpha_index_);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t state_index_ = 1; state_index_ < states_;
|
||||
++state_index_)
|
||||
{
|
||||
typename detail::basic_char_state_machine<CharT>::state
|
||||
*state_ = &sm_._sm_vector[start_state_index_]
|
||||
[state_index_ - 1];
|
||||
|
||||
state_->_end_state = *read_ptr_ != 0;
|
||||
state_->_id = *(read_ptr_ + id_index);
|
||||
state_->_state = *(read_ptr_ + state_index);
|
||||
state_->_bol_index = *(read_ptr_ + bol_index) - 1;
|
||||
state_->_eol_index = *(read_ptr_ + eol_index) - 1;
|
||||
read_ptr_ += dfa_offset;
|
||||
|
||||
for (std::size_t col_index_ = 0; col_index_ < alphabet_;
|
||||
++col_index_, ++read_ptr_)
|
||||
{
|
||||
const std::size_t transition_ = *read_ptr_;
|
||||
|
||||
if (transition_ != 0)
|
||||
{
|
||||
const std::size_t i_ = transition_ - 1;
|
||||
typename detail::basic_char_state_machine<CharT>::
|
||||
state::size_t_string_token_map::iterator iter_ =
|
||||
state_->_transitions.find (i_);
|
||||
|
||||
if (iter_ == state_->_transitions.end ())
|
||||
{
|
||||
basic_string_token<CharT> token_
|
||||
(false, chars_[col_index_]);
|
||||
typename detail::basic_char_state_machine<CharT>::
|
||||
state::size_t_string_token_pair pair_
|
||||
(i_, token_);
|
||||
|
||||
state_->_transitions.insert (pair_);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter_->second._charset += chars_[col_index_];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (typename detail::basic_char_state_machine<CharT>::state::
|
||||
size_t_string_token_map::iterator iter_ =
|
||||
state_->_transitions.begin (),
|
||||
end_ = state_->_transitions.end ();
|
||||
iter_ != end_; ++iter_)
|
||||
{
|
||||
std::sort (iter_->second._charset.begin (),
|
||||
iter_->second._charset.end ());
|
||||
iter_->second.normalise ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !(defined _MSC_VER && _MSC_VER < 1500)
|
||||
template<typename ChT, typename Traits>
|
||||
friend class basic_file_input;
|
||||
|
||||
template<typename ChT, typename Traits>
|
||||
friend class basic_generator;
|
||||
|
||||
template<typename FwdIter, typename Traits>
|
||||
friend class basic_input;
|
||||
|
||||
template<typename ChT, class Archive>
|
||||
friend void serialise (basic_state_machine &sm_, Archive &ar_,
|
||||
unsigned int version_);
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef basic_state_machine<char> state_machine;
|
||||
typedef basic_state_machine<wchar_t> wstate_machine;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,336 @@
|
||||
// string_token.hpp
|
||||
// Copyright (c) 2007-2008 Ben Hanson (http://www.benhanson.net/)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_LEXER_STRING_TOKEN_HPP
|
||||
#define BOOST_LEXER_STRING_TOKEN_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include "size_t.hpp"
|
||||
#include "consts.hpp" // num_chars, num_wchar_ts
|
||||
#include <string>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace lexer
|
||||
{
|
||||
template<typename CharT>
|
||||
struct basic_string_token
|
||||
{
|
||||
typedef std::basic_string<CharT> string;
|
||||
|
||||
bool _negated;
|
||||
string _charset;
|
||||
|
||||
basic_string_token () :
|
||||
_negated (false)
|
||||
{
|
||||
}
|
||||
|
||||
basic_string_token (const bool negated_, const string &charset_) :
|
||||
_negated (negated_),
|
||||
_charset (charset_)
|
||||
{
|
||||
}
|
||||
|
||||
void remove_duplicates ()
|
||||
{
|
||||
const CharT *start_ = _charset.c_str ();
|
||||
const CharT *end_ = start_ + _charset.size ();
|
||||
|
||||
// Optimisation for very large charsets:
|
||||
// sorting via pointers is much quicker than
|
||||
// via iterators...
|
||||
std::sort (const_cast<CharT *> (start_), const_cast<CharT *> (end_));
|
||||
_charset.erase (std::unique (_charset.begin (), _charset.end ()),
|
||||
_charset.end ());
|
||||
}
|
||||
|
||||
void normalise ()
|
||||
{
|
||||
const std::size_t max_chars_ = sizeof (CharT) == 1 ?
|
||||
num_chars : num_wchar_ts;
|
||||
|
||||
if (_charset.length () == max_chars_)
|
||||
{
|
||||
_negated = !_negated;
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
_charset.erase ();
|
||||
#else
|
||||
_charset.clear ();
|
||||
#endif
|
||||
}
|
||||
else if (_charset.length () > max_chars_ / 2)
|
||||
{
|
||||
negate ();
|
||||
}
|
||||
}
|
||||
|
||||
void negate ()
|
||||
{
|
||||
const std::size_t max_chars_ = sizeof (CharT) == 1 ?
|
||||
num_chars : num_wchar_ts;
|
||||
CharT curr_char_ = sizeof (CharT) == 1 ? -128 : 0;
|
||||
string temp_;
|
||||
const CharT *curr_ = _charset.c_str ();
|
||||
const CharT *chars_end_ = curr_ + _charset.size ();
|
||||
|
||||
_negated = !_negated;
|
||||
temp_.resize (max_chars_ - _charset.size ());
|
||||
|
||||
CharT *ptr_ = const_cast<CharT *> (temp_.c_str ());
|
||||
std::size_t i_ = 0;
|
||||
|
||||
while (curr_ < chars_end_)
|
||||
{
|
||||
while (*curr_ > curr_char_)
|
||||
{
|
||||
*ptr_ = curr_char_;
|
||||
++ptr_;
|
||||
++curr_char_;
|
||||
++i_;
|
||||
}
|
||||
|
||||
++curr_char_;
|
||||
++curr_;
|
||||
++i_;
|
||||
}
|
||||
|
||||
for (; i_ < max_chars_; ++i_)
|
||||
{
|
||||
*ptr_ = curr_char_;
|
||||
++ptr_;
|
||||
++curr_char_;
|
||||
}
|
||||
|
||||
_charset = temp_;
|
||||
}
|
||||
|
||||
bool operator < (const basic_string_token &rhs_) const
|
||||
{
|
||||
return _negated < rhs_._negated ||
|
||||
(_negated == rhs_._negated && _charset < rhs_._charset);
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return _charset.empty () && !_negated;
|
||||
}
|
||||
|
||||
bool any () const
|
||||
{
|
||||
return _charset.empty () && _negated;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
_negated = false;
|
||||
#if defined _MSC_VER && _MSC_VER <= 1200
|
||||
_charset.erase ();
|
||||
#else
|
||||
_charset.clear ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void intersect (basic_string_token &rhs_, basic_string_token &overlap_)
|
||||
{
|
||||
if (any () && rhs_.any () || (_negated == rhs_._negated &&
|
||||
!any () && !rhs_.any ()))
|
||||
{
|
||||
intersect_same_types (rhs_, overlap_);
|
||||
}
|
||||
else
|
||||
{
|
||||
intersect_diff_types (rhs_, overlap_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void intersect_same_types (basic_string_token &rhs_, basic_string_token &overlap_)
|
||||
{
|
||||
if (any ())
|
||||
{
|
||||
clear ();
|
||||
overlap_._negated = true;
|
||||
rhs_.clear ();
|
||||
}
|
||||
else
|
||||
{
|
||||
typename string::iterator iter_ = _charset.begin ();
|
||||
typename string::iterator end_ = _charset.end ();
|
||||
typename string::iterator rhs_iter_ = rhs_._charset.begin ();
|
||||
typename string::iterator rhs_end_ = rhs_._charset.end ();
|
||||
|
||||
overlap_._negated = _negated;
|
||||
|
||||
while (iter_ != end_ && rhs_iter_ != rhs_end_)
|
||||
{
|
||||
if (*iter_ < *rhs_iter_)
|
||||
{
|
||||
++iter_;
|
||||
}
|
||||
else if (*iter_ > *rhs_iter_)
|
||||
{
|
||||
++rhs_iter_;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlap_._charset += *iter_;
|
||||
iter_ = _charset.erase (iter_);
|
||||
end_ = _charset.end ();
|
||||
rhs_iter_ = rhs_._charset.erase (rhs_iter_);
|
||||
rhs_end_ = rhs_._charset.end ();
|
||||
}
|
||||
}
|
||||
|
||||
if (_negated)
|
||||
{
|
||||
// duplicates already merged, so safe to merge
|
||||
// using std lib.
|
||||
|
||||
// src, dest
|
||||
merge (_charset, overlap_._charset);
|
||||
// duplicates already merged, so safe to merge
|
||||
// using std lib.
|
||||
|
||||
// src, dest
|
||||
merge (rhs_._charset, overlap_._charset);
|
||||
_negated = false;
|
||||
rhs_._negated = false;
|
||||
std::swap (_charset, rhs_._charset);
|
||||
normalise ();
|
||||
overlap_.normalise ();
|
||||
rhs_.normalise ();
|
||||
}
|
||||
else if (!overlap_._charset.empty ())
|
||||
{
|
||||
normalise ();
|
||||
overlap_.normalise ();
|
||||
rhs_.normalise ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void intersect_diff_types (basic_string_token &rhs_,
|
||||
basic_string_token &overlap_)
|
||||
{
|
||||
if (any ())
|
||||
{
|
||||
intersect_any (rhs_, overlap_);
|
||||
}
|
||||
else if (_negated)
|
||||
{
|
||||
intersect_negated (rhs_, overlap_);
|
||||
}
|
||||
else // _negated == false
|
||||
{
|
||||
intersect_charset (rhs_, overlap_);
|
||||
}
|
||||
}
|
||||
|
||||
void intersect_any (basic_string_token &rhs_, basic_string_token &overlap_)
|
||||
{
|
||||
if (rhs_._negated)
|
||||
{
|
||||
rhs_.intersect_negated (*this, overlap_);
|
||||
}
|
||||
else // rhs._negated == false
|
||||
{
|
||||
rhs_.intersect_charset (*this, overlap_);
|
||||
}
|
||||
}
|
||||
|
||||
void intersect_negated (basic_string_token &rhs_,
|
||||
basic_string_token &overlap_)
|
||||
{
|
||||
if (rhs_.any ())
|
||||
{
|
||||
overlap_._negated = true;
|
||||
overlap_._charset = _charset;
|
||||
rhs_._negated = false;
|
||||
rhs_._charset = _charset;
|
||||
clear ();
|
||||
}
|
||||
else // rhs._negated == false
|
||||
{
|
||||
rhs_.intersect_charset (*this, overlap_);
|
||||
}
|
||||
}
|
||||
|
||||
void intersect_charset (basic_string_token &rhs_,
|
||||
basic_string_token &overlap_)
|
||||
{
|
||||
if (rhs_.any ())
|
||||
{
|
||||
overlap_._charset = _charset;
|
||||
rhs_._negated = true;
|
||||
rhs_._charset = _charset;
|
||||
clear ();
|
||||
}
|
||||
else // rhs_._negated == true
|
||||
{
|
||||
typename string::iterator iter_ = _charset.begin ();
|
||||
typename string::iterator end_ = _charset.end ();
|
||||
typename string::iterator rhs_iter_ = rhs_._charset.begin ();
|
||||
typename string::iterator rhs_end_ = rhs_._charset.end ();
|
||||
|
||||
while (iter_ != end_ && rhs_iter_ != rhs_end_)
|
||||
{
|
||||
if (*iter_ < *rhs_iter_)
|
||||
{
|
||||
overlap_._charset += *iter_;
|
||||
rhs_iter_ = rhs_._charset.insert (rhs_iter_, *iter_);
|
||||
++rhs_iter_;
|
||||
rhs_end_ = rhs_._charset.end ();
|
||||
iter_ = _charset.erase (iter_);
|
||||
end_ = _charset.end ();
|
||||
}
|
||||
else if (*iter_ > *rhs_iter_)
|
||||
{
|
||||
++rhs_iter_;
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter_;
|
||||
++rhs_iter_;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter_ != end_)
|
||||
{
|
||||
// nothing bigger in rhs_ than iter_,
|
||||
// so safe to merge using std lib.
|
||||
string temp_ (iter_, end_);
|
||||
|
||||
// src, dest
|
||||
merge (temp_, overlap_._charset);
|
||||
_charset.erase (iter_, end_);
|
||||
}
|
||||
|
||||
if (!overlap_._charset.empty ())
|
||||
{
|
||||
merge (overlap_._charset, rhs_._charset);
|
||||
// possible duplicates, so check for any and erase.
|
||||
rhs_._charset.erase (std::unique (rhs_._charset.begin (),
|
||||
rhs_._charset.end ()), rhs_._charset.end ());
|
||||
normalise ();
|
||||
overlap_.normalise ();
|
||||
rhs_.normalise ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void merge (string &src_, string &dest_)
|
||||
{
|
||||
string tmp_ (src_.size () + dest_.size (), 0);
|
||||
|
||||
std::merge (src_.begin (), src_.end (), dest_.begin (), dest_.end (),
|
||||
tmp_.begin ());
|
||||
dest_ = tmp_;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,578 @@
|
||||
// fp_traits.hpp
|
||||
|
||||
#ifndef BOOST_SPIRIT_MATH_FP_TRAITS_HPP
|
||||
#define BOOST_SPIRIT_MATH_FP_TRAITS_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT
|
||||
# error The VAX floating point mode on VMS is not supported.
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Most processors support three different floating point precisions:
|
||||
single precision (32 bits), double precision (64 bits)
|
||||
and extended double precision (>64 bits)
|
||||
|
||||
Note that the C++ type long double can be implemented
|
||||
both as double precision and extended double precision.
|
||||
*/
|
||||
|
||||
struct single_precision_tag {};
|
||||
struct double_precision_tag {};
|
||||
struct extended_double_precision_tag {};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
template<class T, class U> struct fp_traits_impl;
|
||||
|
||||
This is traits class that describes the binary structure of floating
|
||||
point numbers of C++ type T and precision U
|
||||
|
||||
Requirements:
|
||||
|
||||
T = float, double or long double
|
||||
U = single_precision_tag, double_precision_tag
|
||||
or extended_double_precision_tag
|
||||
|
||||
Typedef members:
|
||||
|
||||
bits -- the target type when copying the leading bytes of a floating
|
||||
point number. It is a typedef for uint32_t or uint64_t.
|
||||
|
||||
coverage -- tells us whether all bytes are copied or not.
|
||||
It is a typedef for all_bits or not_all_bits.
|
||||
|
||||
Static data members:
|
||||
|
||||
sign, exponent, flag, mantissa -- bit masks that give the meaning of the bits
|
||||
in the leading bytes.
|
||||
|
||||
Static function members:
|
||||
|
||||
init() -- initializes the static data members, if needed.
|
||||
(Is a no-op in the specialized versions of the template.)
|
||||
|
||||
get_bits(), set_bits() -- provide access to the leading bytes.
|
||||
*/
|
||||
|
||||
struct all_bits {};
|
||||
struct not_all_bits {};
|
||||
|
||||
// Generic version -------------------------------------------------------------
|
||||
|
||||
// The generic version uses run time initialization to determine the floating
|
||||
// point format. It is capable of handling most formats,
|
||||
// but not the Motorola 68K extended double precision format.
|
||||
|
||||
// Currently the generic version is used only for extended double precision
|
||||
// on Itanium. In all other cases there are specializations of the template
|
||||
// that use compile time initialization.
|
||||
|
||||
template<class T> struct uint32_t_coverage
|
||||
{
|
||||
typedef not_all_bits type;
|
||||
};
|
||||
|
||||
template<> struct uint32_t_coverage<single_precision_tag>
|
||||
{
|
||||
typedef all_bits type;
|
||||
};
|
||||
|
||||
template<class T, class U> struct fp_traits_impl
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef BOOST_DEDUCED_TYPENAME uint32_t_coverage<U>::type coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
static uint32_t exponent;
|
||||
static uint32_t flag;
|
||||
static uint32_t mantissa;
|
||||
|
||||
static void init()
|
||||
{
|
||||
if(is_init_) return;
|
||||
do_init_();
|
||||
is_init_ = true;
|
||||
}
|
||||
|
||||
static void get_bits(T x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(T& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
static size_t offset_;
|
||||
static bool is_init_;
|
||||
static void do_init_();
|
||||
};
|
||||
|
||||
//..............................................................................
|
||||
|
||||
template<class T, class U> uint32_t fp_traits_impl<T,U>::exponent;
|
||||
template<class T, class U> uint32_t fp_traits_impl<T,U>::flag;
|
||||
template<class T, class U> uint32_t fp_traits_impl<T,U>::mantissa;
|
||||
template<class T, class U> size_t fp_traits_impl<T,U>::offset_;
|
||||
template<class T, class U> bool fp_traits_impl<T,U>::is_init_;
|
||||
|
||||
// In a single-threaded program, do_init will be called exactly once.
|
||||
// In a multi-threaded program, do_init may be called simultaneously
|
||||
// by more then one thread. That should not be a problem.
|
||||
|
||||
//..............................................................................
|
||||
|
||||
template<class T, class U> void fp_traits_impl<T,U>::do_init_()
|
||||
{
|
||||
T x = static_cast<T>(3) / static_cast<T>(4);
|
||||
// sign bit = 0
|
||||
// exponent: first and last bit = 0, all other bits = 1
|
||||
// flag bit (if present) = 1
|
||||
// mantissa: first bit = 1, all other bits = 0
|
||||
|
||||
uint32_t a;
|
||||
|
||||
for(size_t k = 0; k <= sizeof(T) - 4; ++k) {
|
||||
|
||||
memcpy(&a, reinterpret_cast<unsigned char*>(&x) + k, 4);
|
||||
|
||||
switch(a) {
|
||||
|
||||
case 0x3f400000: // IEEE single precision format
|
||||
|
||||
offset_ = k;
|
||||
exponent = 0x7f800000;
|
||||
flag = 0x00000000;
|
||||
mantissa = 0x007fffff;
|
||||
return;
|
||||
|
||||
case 0x3fe80000: // IEEE double precision format
|
||||
// and PowerPC extended double precision format
|
||||
offset_ = k;
|
||||
exponent = 0x7ff00000;
|
||||
flag = 0x00000000;
|
||||
mantissa = 0x000fffff;
|
||||
return;
|
||||
|
||||
case 0x3ffe0000: // Motorola extended double precision format
|
||||
|
||||
// Must not get here. Must be handled by specialization.
|
||||
// To get accurate cutoff between normals and subnormals
|
||||
// we must use the flag bit that is in the 5th byte.
|
||||
// Otherwise this cutoff will be off by a factor 2.
|
||||
// If we do get here, then we have failed to detect the Motorola
|
||||
// processor at compile time.
|
||||
|
||||
BOOST_ASSERT(false);
|
||||
return;
|
||||
|
||||
case 0x3ffe8000: // IEEE extended double precision format
|
||||
// with 15 exponent bits
|
||||
offset_ = k;
|
||||
exponent = 0x7fff0000;
|
||||
flag = 0x00000000;
|
||||
mantissa = 0x0000ffff;
|
||||
return;
|
||||
|
||||
case 0x3ffec000: // Intel extended double precision format
|
||||
|
||||
offset_ = k;
|
||||
exponent = 0x7fff0000;
|
||||
flag = 0x00008000;
|
||||
mantissa = 0x00007fff;
|
||||
return;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(false);
|
||||
|
||||
// Unknown format.
|
||||
}
|
||||
|
||||
|
||||
// float (32 bits) -------------------------------------------------------------
|
||||
|
||||
template<> struct fp_traits_impl<float, single_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x007fffff);
|
||||
|
||||
static void init() {}
|
||||
static void get_bits(float x, uint32_t& a) { memcpy(&a, &x, 4); }
|
||||
static void set_bits(float& x, uint32_t a) { memcpy(&x, &a, 4); }
|
||||
};
|
||||
|
||||
|
||||
// double (64 bits) ------------------------------------------------------------
|
||||
|
||||
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
|
||||
|
||||
template<> struct fp_traits_impl<double, double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
static void get_bits(double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(double& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
//..............................................................................
|
||||
|
||||
#else
|
||||
|
||||
template<> struct fp_traits_impl<double, double_precision_tag>
|
||||
{
|
||||
typedef uint64_t bits;
|
||||
typedef all_bits coverage;
|
||||
|
||||
static const uint64_t sign = (uint64_t)0x80000000 << 32;
|
||||
static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
|
||||
static const uint64_t flag = 0;
|
||||
static const uint64_t mantissa
|
||||
= ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff;
|
||||
|
||||
static void init() {}
|
||||
static void get_bits(double x, uint64_t& a) { memcpy(&a, &x, 8); }
|
||||
static void set_bits(double& x, uint64_t a) { memcpy(&x, &a, 8); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// long double (64 bits) -------------------------------------------------------
|
||||
|
||||
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
|
||||
|
||||
template<> struct fp_traits_impl<long double, double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
//..............................................................................
|
||||
|
||||
#else
|
||||
|
||||
template<> struct fp_traits_impl<long double, double_precision_tag>
|
||||
{
|
||||
typedef uint64_t bits;
|
||||
typedef all_bits coverage;
|
||||
|
||||
static const uint64_t sign = (uint64_t)0x80000000 << 32;
|
||||
static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
|
||||
static const uint64_t flag = 0;
|
||||
static const uint64_t mantissa
|
||||
= ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff;
|
||||
|
||||
static void init() {}
|
||||
static void get_bits(long double x, uint64_t& a) { memcpy(&a, &x, 8); }
|
||||
static void set_bits(long double& x, uint64_t a) { memcpy(&x, &a, 8); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// long double (>64 bits), x86 and x64 -----------------------------------------
|
||||
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|
||||
|| defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \
|
||||
|| defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
|
||||
|
||||
// Intel extended double precision format (80 bits)
|
||||
|
||||
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), Itanium ---------------------------------------------
|
||||
|
||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||
|
||||
// The floating point format is unknown at compile time
|
||||
// No template specialization is provided.
|
||||
// The generic definition is used.
|
||||
|
||||
// The Itanium supports both
|
||||
// the Intel extended double precision format (80 bits) and
|
||||
// the IEEE extended double precision format with 15 exponent bits (128 bits).
|
||||
|
||||
|
||||
// long double (>64 bits), PowerPC ---------------------------------------------
|
||||
|
||||
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \
|
||||
|| defined(__ppc) || defined(__ppc__) || defined(__PPC__)
|
||||
|
||||
// PowerPC extended double precision format (128 bits)
|
||||
|
||||
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), Motorola 68K ----------------------------------------
|
||||
|
||||
#elif defined(__m68k) || defined(__m68k__) \
|
||||
|| defined(__mc68000) || defined(__mc68000__) \
|
||||
|
||||
// Motorola extended double precision format (96 bits)
|
||||
|
||||
// It is the same format as the Intel extended double precision format,
|
||||
// except that 1) it is big-endian, 2) the 3rd and 4th byte are padding, and
|
||||
// 3) the flag bit is not set for infinity
|
||||
|
||||
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
// copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding.
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, &x, 2);
|
||||
memcpy(reinterpret_cast<unsigned char*>(&a) + 2,
|
||||
reinterpret_cast<const unsigned char*>(&x) + 4, 2);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
memcpy(&x, &a, 2);
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + 4,
|
||||
reinterpret_cast<const unsigned char*>(&a) + 2, 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), All other processors --------------------------------
|
||||
|
||||
#else
|
||||
|
||||
// IEEE extended double precision format with 15 exponent bits (128 bits)
|
||||
|
||||
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
|
||||
{
|
||||
typedef uint32_t bits;
|
||||
typedef not_all_bits coverage;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x0000ffff);
|
||||
|
||||
static void init() {}
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// size_to_precision is a type switch for converting a C++ floating point type
|
||||
// to the corresponding precision type.
|
||||
|
||||
template<int n> struct size_to_precision;
|
||||
|
||||
template<> struct size_to_precision<4>
|
||||
{
|
||||
typedef single_precision_tag type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<8>
|
||||
{
|
||||
typedef double_precision_tag type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<10>
|
||||
{
|
||||
typedef extended_double_precision_tag type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<12>
|
||||
{
|
||||
typedef extended_double_precision_tag type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<16>
|
||||
{
|
||||
typedef extended_double_precision_tag type;
|
||||
};
|
||||
|
||||
// fp_traits is a type switch that selects the right fp_traits_impl
|
||||
|
||||
template<class T> struct fp_traits
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_floating_point<T>::value);
|
||||
typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T)>::type precision;
|
||||
typedef fp_traits_impl<T, precision> type;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace spirit
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
// fpclassify.hpp
|
||||
|
||||
#ifndef BOOST_SPIRIT_MATH_FPCLASSIFY_HPP
|
||||
#define BOOST_SPIRIT_MATH_FPCLASSIFY_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
The following algorithm is used:
|
||||
|
||||
If all exponent bits, the flag bit (if there is one),
|
||||
and all mantissa bits are 0, then the number is zero.
|
||||
|
||||
If all exponent bits and the flag bit (if there is one) are 0,
|
||||
and at least one mantissa bit is 1, then the number is subnormal.
|
||||
|
||||
If all exponent bits are 1 and all mantissa bits are 0,
|
||||
then the number is infinity.
|
||||
|
||||
If all exponent bits are 1 and at least one mantissa bit is 1,
|
||||
then the number is a not-a-number.
|
||||
|
||||
Otherwise the number is normal.
|
||||
|
||||
(Note that the binary representation of infinity
|
||||
has flag bit 0 for Motorola 68K extended double precision,
|
||||
and flag bit 1 for Intel extended double precision.)
|
||||
|
||||
To get the bits, the four or eight most significant bytes are copied
|
||||
into an uint32_t or uint64_t and bit masks are applied.
|
||||
This covers all the exponent bits and the flag bit (if there is one),
|
||||
but not always all the mantissa bits.
|
||||
Some of the functions below have two implementations,
|
||||
depending on whether all the mantissa bits are copied or not.
|
||||
*/
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
#ifndef FP_INFINITE
|
||||
# define FP_INFINITE 0
|
||||
# define FP_NAN 1
|
||||
# define FP_NORMAL 2
|
||||
# define FP_SUBNORMAL 3
|
||||
# define FP_ZERO 4
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace math {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> bool (isfinite)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent;
|
||||
return a != traits::exponent;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> bool (isnormal)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::flag;
|
||||
return (a != 0) && (a < traits::exponent);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T> bool isinf_impl(T x, all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::mantissa;
|
||||
return a == traits::exponent;
|
||||
}
|
||||
|
||||
template<class T> bool isinf_impl(T x, not_all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::mantissa;
|
||||
if(a != traits::exponent)
|
||||
return false;
|
||||
|
||||
traits::set_bits(x,0);
|
||||
return x == 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T> bool (isinf)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
return detail::isinf_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T> bool isnan_impl(T x, all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::mantissa;
|
||||
return a > traits::exponent;
|
||||
}
|
||||
|
||||
template<class T> bool isnan_impl(T x, not_all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
|
||||
a &= traits::exponent | traits::mantissa;
|
||||
if(a < traits::exponent)
|
||||
return false;
|
||||
|
||||
a &= traits::mantissa;
|
||||
traits::set_bits(x,a);
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T> bool (isnan)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
return detail::isnan_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T> int fpclassify_impl(T x, all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::flag | traits::mantissa;
|
||||
|
||||
if(a <= traits::mantissa) {
|
||||
if(a == 0)
|
||||
return FP_ZERO;
|
||||
else
|
||||
return FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
if(a < traits::exponent)
|
||||
return FP_NORMAL;
|
||||
|
||||
a &= traits::mantissa;
|
||||
if(a == 0)
|
||||
return FP_INFINITE;
|
||||
|
||||
return FP_NAN;
|
||||
}
|
||||
|
||||
template<class T> int fpclassify_impl(T x, not_all_bits)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::flag | traits::mantissa;
|
||||
|
||||
if(a <= traits::mantissa) {
|
||||
if(x == 0)
|
||||
return FP_ZERO;
|
||||
else
|
||||
return FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
if(a < traits::exponent)
|
||||
return FP_NORMAL;
|
||||
|
||||
a &= traits::mantissa;
|
||||
traits::set_bits(x,a);
|
||||
if(x == 0)
|
||||
return FP_INFINITE;
|
||||
|
||||
return FP_NAN;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T> int (fpclassify)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
return detail::fpclassify_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace math
|
||||
} // namespace spirit
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,477 @@
|
||||
#ifndef BOOST_SPIRIT_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
#define BOOST_SPIRIT_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <cstring>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#include <boost/spirit/home/support/detail/math/signbit.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4127 4511 4512 4706)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace math {
|
||||
|
||||
|
||||
// flags -----------------------------------------------------------------------
|
||||
|
||||
const int legacy = 0x1;
|
||||
const int signed_zero = 0x2;
|
||||
const int trap_infinity = 0x4;
|
||||
const int trap_nan = 0x8;
|
||||
|
||||
|
||||
// class nonfinite_num_put -----------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class OutputIterator = std::ostreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_put : public std::num_put<CharType, OutputIterator> {
|
||||
public:
|
||||
explicit nonfinite_num_put(int flags = 0) : flags_(flags) {}
|
||||
|
||||
protected:
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb,
|
||||
CharType fill, double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb,
|
||||
CharType fill, long double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
template<class ValType> void put_and_reset_width(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
put_impl(it, iosb, fill, val);
|
||||
iosb.width(0);
|
||||
}
|
||||
|
||||
template<class ValType> void put_impl(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
switch((boost::math::fpclassify)(val)) {
|
||||
|
||||
case FP_INFINITE:
|
||||
if(flags_ & trap_infinity)
|
||||
throw std::ios_base::failure("Infinity");
|
||||
else if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "inf", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "inf", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "inf", fill);
|
||||
break;
|
||||
|
||||
case FP_NAN:
|
||||
if(flags_ & trap_nan)
|
||||
throw std::ios_base::failure("NaN");
|
||||
else if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "nan", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "nan", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "nan", fill);
|
||||
break;
|
||||
|
||||
case FP_ZERO:
|
||||
if(flags_ & signed_zero) {
|
||||
if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "0", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "0", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "0", fill);
|
||||
}
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "0", fill);
|
||||
break;
|
||||
|
||||
default:
|
||||
it = std::num_put<CharType, OutputIterator>::do_put(
|
||||
it, iosb, fill, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void put_num_and_fill(
|
||||
OutputIterator& it, std::ios_base& iosb, const char* prefix,
|
||||
const char* body, CharType fill) const
|
||||
{
|
||||
int width = (int)strlen(prefix) + (int)strlen(body);
|
||||
std::ios_base::fmtflags adjust
|
||||
= iosb.flags() & std::ios_base::adjustfield;
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
|
||||
while(*prefix)
|
||||
*it = ct.widen(*(prefix++));
|
||||
|
||||
if(adjust == std::ios_base::internal)
|
||||
put_fill(it, iosb, fill, width);
|
||||
|
||||
if(iosb.flags() & std::ios_base::uppercase) {
|
||||
while(*body)
|
||||
*it = ct.toupper(ct.widen(*(body++)));
|
||||
}
|
||||
else {
|
||||
while(*body)
|
||||
*it = ct.widen(*(body++));
|
||||
}
|
||||
|
||||
if(adjust == std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
}
|
||||
|
||||
void put_fill(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, int width) const
|
||||
{
|
||||
for(int i = iosb.width() - width; i > 0; --i)
|
||||
*it = fill;
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
};
|
||||
|
||||
|
||||
// class nonfinite_num_get ------------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class InputIterator = std::istreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_get : public std::num_get<CharType, InputIterator> {
|
||||
public:
|
||||
explicit nonfinite_num_get(int flags = 0) : flags_(flags) {}
|
||||
|
||||
protected:
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, float& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, long double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
//..............................................................................
|
||||
|
||||
private:
|
||||
template<class ValType> static ValType positive_nan()
|
||||
{
|
||||
// on some platforms quiet_NaN() is negative
|
||||
return (boost::math::copysign)(
|
||||
std::numeric_limits<ValType>::quiet_NaN(), 1);
|
||||
}
|
||||
|
||||
template<class ValType> void get_and_check_eof(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
get_signed(it, end, iosb, state, val);
|
||||
if(it == end)
|
||||
state |= std::ios_base::eofbit;
|
||||
}
|
||||
|
||||
template<class ValType> void get_signed(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
char c = peek_char(it, end, ct);
|
||||
|
||||
bool negative = (c == '-');
|
||||
|
||||
if(negative || c == '+') {
|
||||
++it;
|
||||
c = peek_char(it, end, ct);
|
||||
if(c == '-' || c == '+') {
|
||||
// without this check, "++5" etc would be accepted
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
get_unsigned(it, end, iosb, ct, state, val);
|
||||
|
||||
if(negative)
|
||||
val = (boost::math::changesign)(val);
|
||||
}
|
||||
|
||||
template<class ValType> void get_unsigned(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
switch(peek_char(it, end, ct)) {
|
||||
|
||||
case 'i':
|
||||
get_i(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
get_n(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
case 's':
|
||||
get_q(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
it = std::num_get<CharType, InputIterator>::do_get(
|
||||
it, end, iosb, state, val);
|
||||
if((flags_ & legacy) && val == static_cast<ValType>(1)
|
||||
&& peek_char(it, end, ct) == '#')
|
||||
get_one_hash(it, end, ct, state, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//..........................................................................
|
||||
|
||||
template<class ValType> void get_i(
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_infinity
|
||||
|| (flags_ & trap_infinity)) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
|
||||
if(!match_string(it, end, ct, "nf")) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
if(peek_char(it, end, ct) != 'i') {
|
||||
val = std::numeric_limits<ValType>::infinity(); // "inf"
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
|
||||
if(!match_string(it, end, ct, "nity")) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = std::numeric_limits<ValType>::infinity(); // "infinity"
|
||||
}
|
||||
|
||||
template<class ValType> void get_n(
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan)) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
|
||||
if(!match_string(it, end, ct, "an")) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(peek_char(it, end, ct)) {
|
||||
case 'q':
|
||||
case 's':
|
||||
if(flags_ && legacy)
|
||||
++it;
|
||||
break; // "nanq", "nans"
|
||||
|
||||
case '(':
|
||||
{
|
||||
++it;
|
||||
char c;
|
||||
while((c = peek_char(it, end, ct))
|
||||
&& c != ')' && c != ' ' && c != '\n' && c != '\t')
|
||||
++it;
|
||||
if(c != ')') {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
break; // "nan(...)"
|
||||
}
|
||||
|
||||
default:
|
||||
break; // "nan"
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>();
|
||||
}
|
||||
|
||||
template<class ValType> void get_q(
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan) || !(flags_ & legacy)) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
|
||||
if(!match_string(it, end, ct, "nan")) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>(); // qnan, snan
|
||||
}
|
||||
|
||||
template<class ValType> void get_one_hash(
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
++it;
|
||||
|
||||
switch(peek_char(it, end, ct)) {
|
||||
case 'i':
|
||||
get_one_hash_i(it, end, ct, state, val);
|
||||
return;
|
||||
|
||||
case 'q':
|
||||
case 's':
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan)) {
|
||||
++it;
|
||||
if(match_string(it, end, ct, "nan")) {
|
||||
// "1.#QNAN", "1.#SNAN"
|
||||
++it;
|
||||
val = positive_nan<ValType>();
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
}
|
||||
|
||||
template<class ValType> void get_one_hash_i(
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val) const
|
||||
{
|
||||
++it;
|
||||
|
||||
if(peek_char(it, end, ct) == 'n') {
|
||||
++it;
|
||||
switch(peek_char(it, end, ct)) {
|
||||
case 'f': // "1.#INF"
|
||||
if(std::numeric_limits<ValType>::has_infinity
|
||||
&& !(flags_ & trap_infinity)) {
|
||||
++it;
|
||||
val = std::numeric_limits<ValType>::infinity();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': // 1.#IND"
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan)) {
|
||||
++it;
|
||||
val = positive_nan<ValType>();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
}
|
||||
|
||||
//..........................................................................
|
||||
|
||||
char peek_char(
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct) const
|
||||
{
|
||||
if(it == end) return 0;
|
||||
return ct.narrow(ct.tolower(*it), 0);
|
||||
}
|
||||
|
||||
bool match_string(
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct, const char* s) const
|
||||
{
|
||||
while(it != end && *s && *s == ct.narrow(ct.tolower(*it), 0)) {
|
||||
++s;
|
||||
++it;
|
||||
}
|
||||
return !*s;
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace math
|
||||
} // namespace spirit
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
// signbit.hpp
|
||||
|
||||
#ifndef BOOST_SPIRIT_MATH_SIGNBIT_HPP
|
||||
#define BOOST_SPIRIT_MATH_SIGNBIT_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace math {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> bool (signbit)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::sign;
|
||||
return a != 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T> T copysign_impl(T x, T y)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= ~traits::sign;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits b;
|
||||
traits::get_bits(y,b);
|
||||
b &= traits::sign;
|
||||
|
||||
traits::set_bits(x,a|b);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
inline float (copysign)(float x, float y) // magnitude of x and sign of y
|
||||
{
|
||||
return detail::copysign_impl(x,y);
|
||||
}
|
||||
|
||||
inline double (copysign)(double x, double y)
|
||||
{
|
||||
return detail::copysign_impl(x,y);
|
||||
}
|
||||
|
||||
inline long double (copysign)(long double x, long double y)
|
||||
{
|
||||
return detail::copysign_impl(x,y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> T (changesign)(T x)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
traits::init();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a ^= traits::sign;
|
||||
traits::set_bits(x,a);
|
||||
return x;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace math
|
||||
} // namespace spirit
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_TO_NARROW_APRIL_29_2007_1122AM)
|
||||
#define BOOST_SPIRIT_TO_NARROW_APRIL_29_2007_1122AM
|
||||
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
inline char to_narrow_char(Char ch)
|
||||
{
|
||||
typedef std::ctype<Char> ctype_type;
|
||||
return std::use_facet<ctype_type>(std::locale()).narrow(ch, '.');
|
||||
}
|
||||
|
||||
inline char to_narrow_char(char ch)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline std::size_t getlength(Char const* p)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
while (*p)
|
||||
++len, ++p;
|
||||
return len;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline std::string to_narrow_string(Char const* source)
|
||||
{
|
||||
typedef std::ctype<Char> ctype_type;
|
||||
|
||||
std::size_t len = getlength(source);
|
||||
std::auto_ptr<char> buffer(new char [len+1]);
|
||||
std::use_facet<ctype_type>(std::locale())
|
||||
.narrow(source, source + len, '.', buffer.get());
|
||||
|
||||
return std::string(buffer.get(), len);
|
||||
}
|
||||
|
||||
inline std::string to_narrow_string(char const* source)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline std::string to_narrow_string(std::basic_string<Char> const& str)
|
||||
{
|
||||
return to_narrow_string(str.c_str());
|
||||
}
|
||||
|
||||
inline std::string const& to_narrow_string(std::string const& str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
120
libraries/include/boost/spirit/home/support/detail/values.hpp
Normal file
120
libraries/include/boost/spirit/home/support/detail/values.hpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_VALUES_JAN_07_2007_0802PM)
|
||||
#define BOOST_SPIRIT_VALUES_JAN_07_2007_0802PM
|
||||
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
struct not_is_variant
|
||||
: mpl::true_ {};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
: mpl::false_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// All parsers and generators have specific attribute or parameter types.
|
||||
// Spirit parsers are passed an attribute and Spirit generators
|
||||
// are passed a parameter; these are either references to the expected
|
||||
// type, or an unused_type -- to flag that we do not care about the
|
||||
// attribute/parameter. For semantic actions, however, we need to have a
|
||||
// real value to pass to the semantic action. If the client did not
|
||||
// provide one, we will have to synthesize the value. This class
|
||||
// takes care of that.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename ValueType>
|
||||
struct make_value
|
||||
{
|
||||
static ValueType call(unused_type)
|
||||
{
|
||||
return ValueType(); // synthesize the attribute/parameter
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T& call(T& value)
|
||||
{
|
||||
return value; // just pass the one provided
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T const& call(T const& value)
|
||||
{
|
||||
return value; // just pass the one provided
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct make_value<ValueType&> : make_value<ValueType>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct make_value<unused_type>
|
||||
{
|
||||
static unused_type call(unused_type)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// pass_value determines how we pass attributes and parameters to semantic
|
||||
// actions. Basically, all SAs receive the arguments in a tuple. So, if
|
||||
// the argument to be passed is not a tuple, wrap it in one.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename ValueType>
|
||||
struct pass_value
|
||||
{
|
||||
typedef
|
||||
mpl::and_<
|
||||
fusion::traits::is_sequence<ValueType>
|
||||
, detail::not_is_variant<ValueType>
|
||||
>
|
||||
is_sequence;
|
||||
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_sequence
|
||||
, ValueType&
|
||||
, fusion::vector<ValueType&> const
|
||||
>::type
|
||||
type;
|
||||
|
||||
static ValueType&
|
||||
call(ValueType& arg, mpl::true_)
|
||||
{
|
||||
// arg is a fusion sequence (except a variant) return it as-is.
|
||||
return arg;
|
||||
}
|
||||
|
||||
static fusion::vector<ValueType&> const
|
||||
call(ValueType& seq, mpl::false_)
|
||||
{
|
||||
// arg is a not fusion sequence wrap it in a fusion::vector.
|
||||
return fusion::vector<ValueType&>(seq);
|
||||
}
|
||||
|
||||
static type
|
||||
call(ValueType& arg)
|
||||
{
|
||||
return call(arg, is_sequence());
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(SPIRIT_WHAT_FUNCTION_APR_22_2007_0236PM)
|
||||
#define SPIRIT_WHAT_FUNCTION_APR_22_2007_0236PM
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
template <typename Context>
|
||||
struct what_function
|
||||
{
|
||||
what_function(std::string& str, Context const& ctx)
|
||||
: str(str), ctx(ctx), first(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
void operator()(Component const& component) const
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
str += ", ";
|
||||
typedef typename Component::director director;
|
||||
str += director::what(component, ctx);
|
||||
}
|
||||
|
||||
std::string& str;
|
||||
Context const& ctx;
|
||||
mutable bool first;
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
70
libraries/include/boost/spirit/home/support/iso8859_1.hpp
Normal file
70
libraries/include/boost/spirit/home/support/iso8859_1.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(SPIRIT_ISO8859_1_JAN_31_2006_0529PM)
|
||||
#define SPIRIT_ISO8859_1_JAN_31_2006_0529PM
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace iso8859_1
|
||||
{
|
||||
typedef spirit::char_class::iso8859_1 char_set;
|
||||
namespace tag = spirit::char_class::tag;
|
||||
|
||||
template <typename Class>
|
||||
struct make_tag
|
||||
: proto::terminal<spirit::char_class::key<char_set, Class> > {};
|
||||
|
||||
typedef make_tag<tag::alnum>::type alnum_type;
|
||||
typedef make_tag<tag::alpha>::type alpha_type;
|
||||
typedef make_tag<tag::blank>::type blank_type;
|
||||
typedef make_tag<tag::cntrl>::type cntrl_type;
|
||||
typedef make_tag<tag::digit>::type digit_type;
|
||||
typedef make_tag<tag::graph>::type graph_type;
|
||||
typedef make_tag<tag::print>::type print_type;
|
||||
typedef make_tag<tag::punct>::type punct_type;
|
||||
typedef make_tag<tag::space>::type space_type;
|
||||
typedef make_tag<tag::xdigit>::type xdigit_type;
|
||||
|
||||
alnum_type const alnum = {{}};
|
||||
alpha_type const alpha = {{}};
|
||||
blank_type const blank = {{}};
|
||||
cntrl_type const cntrl = {{}};
|
||||
digit_type const digit = {{}};
|
||||
graph_type const graph = {{}};
|
||||
print_type const print = {{}};
|
||||
punct_type const punct = {{}};
|
||||
space_type const space = {{}};
|
||||
xdigit_type const xdigit = {{}};
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::no_case_tag<char_set> >::type
|
||||
no_case_type;
|
||||
|
||||
no_case_type const no_case = no_case_type();
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::lower_case_tag<char_set> >::type
|
||||
lower_type;
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::upper_case_tag<char_set> >::type
|
||||
upper_type;
|
||||
|
||||
lower_type const lower = lower_type();
|
||||
upper_type const upper = upper_type();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
inline void silence_unused_warnings__iso8859_1()
|
||||
{
|
||||
(void) alnum; (void) alpha; (void) blank; (void) cntrl; (void) digit;
|
||||
(void) graph; (void) print; (void) punct; (void) space; (void) xdigit;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <exception> // for std::exception
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class illegal_backtracking
|
||||
// thrown by buf_id_check CheckingPolicy if an instance of an iterator is
|
||||
// used after another one has invalidated the queue
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class illegal_backtracking : public std::exception
|
||||
{
|
||||
public:
|
||||
illegal_backtracking() throw() {}
|
||||
~illegal_backtracking() throw() {}
|
||||
|
||||
char const* what() const throw()
|
||||
{
|
||||
return "boost::spirit::multi_pass::illegal_backtracking";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// class buf_id_check
|
||||
// Implementation of the CheckingPolicy used by multi_pass
|
||||
// This policy is most effective when used together with the std_deque
|
||||
// StoragePolicy.
|
||||
//
|
||||
// If used with the fixed_size_queue StoragePolicy, it will not detect
|
||||
// iterator dereferences that are out of the range of the queue.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct buf_id_check
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique //: detail::default_checking_policy
|
||||
{
|
||||
unique()
|
||||
: buf_id(0)
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: buf_id(x.buf_id)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(buf_id, x.buf_id);
|
||||
}
|
||||
|
||||
// called to verify that everything is ok.
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const& mp)
|
||||
{
|
||||
if (mp.buf_id != mp.shared->shared_buf_id)
|
||||
boost::throw_exception(illegal_backtracking());
|
||||
}
|
||||
|
||||
// called from multi_pass::clear_queue, so we can increment the count
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass& mp)
|
||||
{
|
||||
++mp.shared->shared_buf_id;
|
||||
++mp.buf_id;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
|
||||
protected:
|
||||
unsigned long buf_id;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
shared() : shared_buf_id(0) {}
|
||||
unsigned long shared_buf_id;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,480 @@
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM
|
||||
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The purpose of the multi_pass_unique template is to eliminate
|
||||
// empty policy classes (policies not containing any data items) from the
|
||||
// multiple inheritance chain. This is necessary since a compiler is not
|
||||
// allowed to apply the empty base optimization if multiple inheritance is
|
||||
// involved (or at least most compilers fail to apply it).
|
||||
// Additionally this can be used to combine separate policies into one
|
||||
// single multi_pass_policy as required by the multi_pass template
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
// without partial template specialization there is nothing much to do in
|
||||
// terms of empty base optimization anyways...
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique
|
||||
: Ownership, Checking, Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) : Input(x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Ownership::destroy(mp);
|
||||
Checking::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Ownership::swap(x);
|
||||
this->Checking::swap(x);
|
||||
this->Input::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
};
|
||||
#else
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// select the correct derived classes based on if a policy is empty
|
||||
template <
|
||||
typename T,
|
||||
typename Ownership, typename Checking, typename Input, typename Storage,
|
||||
bool OwnershipIsEmpty = boost::is_empty<Ownership>::value,
|
||||
bool CheckingIsEmpty = boost::is_empty<Checking>::value,
|
||||
bool InputIsEmpty = boost::is_empty<Input>::value>
|
||||
struct multi_pass_unique;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
false, false, false>
|
||||
: Ownership, Checking, Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) : Input(x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Ownership::destroy(mp);
|
||||
Checking::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Ownership::swap(x);
|
||||
this->Checking::swap(x);
|
||||
this->Input::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
false, false, true>
|
||||
: Ownership, Checking, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Ownership::destroy(mp);
|
||||
Checking::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Ownership::swap(x);
|
||||
this->Checking::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::input_is_valid(mp, curtok); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
false, true, false>
|
||||
: Ownership, Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) : Input(x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Ownership::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Ownership::swap(x);
|
||||
this->Input::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(mp); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
false, true, true>
|
||||
: Ownership, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Ownership::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Ownership::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::input_is_valid(mp, curtok); }
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(mp); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
true, false, false>
|
||||
: Checking, Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) : Input(x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Checking::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Checking::swap(x);
|
||||
this->Input::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// ownership policy functions are forwarded to the Ownership type
|
||||
template <typename MultiPass>
|
||||
inline static void clone(MultiPass& mp)
|
||||
{ Ownership::clone(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool release(MultiPass& mp)
|
||||
{ return Ownership::release(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool is_unique(MultiPass const& mp)
|
||||
{ return Ownership::is_unique(mp); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
true, false, true>
|
||||
: Checking, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Checking::destroy(mp);
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Checking::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::input_is_valid(mp, curtok); }
|
||||
|
||||
// ownership policy functions are forwarded to the Ownership type
|
||||
template <typename MultiPass>
|
||||
inline static void clone(MultiPass& mp)
|
||||
{ Ownership::clone(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool release(MultiPass& mp)
|
||||
{ return Ownership::release(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool is_unique(MultiPass const& mp)
|
||||
{ return Ownership::is_unique(mp); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
true, true, false>
|
||||
: Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const& x) : Input(x) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Input::swap(x);
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(mp); }
|
||||
|
||||
// ownership policy functions are forwarded to the Ownership type
|
||||
template <typename MultiPass>
|
||||
inline static void clone(MultiPass& mp)
|
||||
{ Ownership::clone(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool release(MultiPass& mp)
|
||||
{ return Ownership::release(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool is_unique(MultiPass const& mp)
|
||||
{ return Ownership::is_unique(mp); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique<T, Ownership, Checking, Input, Storage,
|
||||
true, true, true>
|
||||
: Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
multi_pass_unique(T const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
Input::destroy(mp);
|
||||
Storage::destroy(mp);
|
||||
}
|
||||
void swap(multi_pass_unique& x)
|
||||
{
|
||||
this->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::input_is_valid(mp, curtok); }
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(mp); }
|
||||
|
||||
// ownership policy functions are forwarded to the Ownership type
|
||||
template <typename MultiPass>
|
||||
inline static void clone(MultiPass& mp)
|
||||
{ Ownership::clone(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool release(MultiPass& mp)
|
||||
{ return Ownership::release(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static bool is_unique(MultiPass const& mp)
|
||||
{ return Ownership::is_unique(mp); }
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// the multi_pass_shared structure is used to combine the shared data items
|
||||
// of all policies into one single structure
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<
|
||||
typename T, typename Ownership, typename Checking, typename Input,
|
||||
typename Storage
|
||||
>
|
||||
struct multi_pass_shared : Ownership, Checking, Input, Storage
|
||||
{
|
||||
explicit multi_pass_shared(T const& input)
|
||||
: Input(input)
|
||||
{}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This is a default implementation of a policy class as required by the
|
||||
// multi_pass template, combining 4 separate policies into one. Any other
|
||||
// multi_pass policy class needs to follow the scheme as shown below.
|
||||
template<
|
||||
typename Ownership, typename Checking, typename Input, typename Storage
|
||||
>
|
||||
struct default_policy
|
||||
{
|
||||
typedef Ownership ownership_policy;
|
||||
typedef Checking checking_policy;
|
||||
typedef Input input_policy;
|
||||
typedef Storage storage_policy;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct unique
|
||||
: multi_pass_unique<
|
||||
T, typename Ownership::unique, typename Checking::unique,
|
||||
typename Input::BOOST_NESTED_TEMPLATE unique<T>,
|
||||
typename Storage::BOOST_NESTED_TEMPLATE unique<
|
||||
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
|
||||
>
|
||||
{
|
||||
typedef typename Ownership::unique ownership_policy;
|
||||
typedef typename Checking::unique checking_policy;
|
||||
typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
|
||||
input_policy;
|
||||
typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
|
||||
typename input_policy::value_type>
|
||||
storage_policy;
|
||||
|
||||
typedef multi_pass_unique<T, ownership_policy, checking_policy,
|
||||
input_policy, storage_policy>
|
||||
unique_base_type;
|
||||
|
||||
unique() {}
|
||||
explicit unique(T const& input) : unique_base_type(input) {}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct shared
|
||||
: multi_pass_shared<T,
|
||||
typename Ownership::shared, typename Checking::shared,
|
||||
typename Input::BOOST_NESTED_TEMPLATE shared<T>,
|
||||
typename Storage::BOOST_NESTED_TEMPLATE shared<
|
||||
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
|
||||
>
|
||||
{
|
||||
typedef typename Ownership::shared ownership_policy;
|
||||
typedef typename Checking::shared checking_policy;
|
||||
typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
|
||||
input_policy;
|
||||
typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
|
||||
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
|
||||
storage_policy;
|
||||
|
||||
typedef multi_pass_shared<T, ownership_policy, checking_policy,
|
||||
input_policy, storage_policy>
|
||||
shared_base_type;
|
||||
|
||||
explicit shared(T const& input) : shared_base_type(input) {}
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_FIRST_OWNER_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIRST_OWNER_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class first_owner
|
||||
// Implementation of an OwnershipPolicy used by multi_pass
|
||||
// This ownership policy dictates that the first iterator created will
|
||||
// determine the lifespan of the shared components. This works well for
|
||||
// spirit, since no dynamic allocation of iterators is done, and all
|
||||
// copies are make on the stack.
|
||||
//
|
||||
// There is a caveat about using this policy together with the std_deque
|
||||
// StoragePolicy. Since first_owner always returns false from unique(),
|
||||
// std_deque will only release the queued data if clear_queue() is called.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct first_owner
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : detail::default_ownership_policy
|
||||
{
|
||||
unique()
|
||||
: first(true)
|
||||
{}
|
||||
|
||||
unique(unique const&)
|
||||
: first(false)
|
||||
{}
|
||||
|
||||
// return true to indicate deletion of resources
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp)
|
||||
{
|
||||
return mp.first;
|
||||
}
|
||||
|
||||
// use swap from default policy
|
||||
// if we're the first, we still remain the first, even if assigned
|
||||
// to, so don't swap first_. swap is only called from operator=
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const&)
|
||||
{
|
||||
return false; // no way to know, so always return false
|
||||
}
|
||||
|
||||
protected:
|
||||
bool first;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
// no shared data
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,388 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_MAR_16_2007_1137AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_MAR_16_2007_1137AM
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp> // for BOOST_ASSERT
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Make sure we're using a decent version of the Boost.IteratorAdaptors lib
|
||||
#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
|
||||
BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
|
||||
#error "Please use at least Boost V1.31.0 while compiling the fixed_size_queue class!"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_SPIRIT_ASSERT_FSQ_SIZE \
|
||||
BOOST_ASSERT(((m_tail + N + 1) - m_head) % (N+1) == m_size % (N+1)) \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Queue, typename T, typename Pointer>
|
||||
class fsq_iterator
|
||||
: public boost::iterator_adaptor<
|
||||
fsq_iterator<Queue, T, Pointer>, Pointer, T,
|
||||
std::random_access_iterator_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::position_type position_type;
|
||||
typedef boost::iterator_adaptor<
|
||||
fsq_iterator<Queue, T, Pointer>, Pointer, T,
|
||||
std::random_access_iterator_tag
|
||||
> base_type;
|
||||
|
||||
fsq_iterator() {}
|
||||
fsq_iterator(position_type const &p_) : p(p_) {}
|
||||
|
||||
position_type const &get_position() const { return p; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
typename base_type::reference dereference() const
|
||||
{
|
||||
return p.self->m_queue[p.pos];
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
++p.pos;
|
||||
if (p.pos == Queue::MAX_SIZE+1)
|
||||
p.pos = 0;
|
||||
}
|
||||
|
||||
void decrement()
|
||||
{
|
||||
if (p.pos == 0)
|
||||
p.pos = Queue::MAX_SIZE;
|
||||
else
|
||||
--p.pos;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherDerived, typename OtherIterator,
|
||||
typename V, typename C, typename R, typename D
|
||||
>
|
||||
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D>
|
||||
const &x) const
|
||||
{
|
||||
position_type const &rhs_pos =
|
||||
static_cast<OtherDerived const &>(x).get_position();
|
||||
return (p.self == rhs_pos.self) && (p.pos == rhs_pos.pos);
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherDerived, typename OtherIterator,
|
||||
typename V, typename C, typename R, typename D
|
||||
>
|
||||
typename base_type::difference_type distance_to(
|
||||
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D>
|
||||
const &x) const
|
||||
{
|
||||
typedef typename base_type::difference_type difference_type;
|
||||
|
||||
position_type const &p2 =
|
||||
static_cast<OtherDerived const &>(x).get_position();
|
||||
std::size_t pos1 = p.pos;
|
||||
std::size_t pos2 = p2.pos;
|
||||
|
||||
// Undefined behavior if the iterators come from different
|
||||
// containers
|
||||
BOOST_ASSERT(p.self == p2.self);
|
||||
|
||||
if (pos1 < p.self->m_head)
|
||||
pos1 += Queue::MAX_SIZE;
|
||||
if (pos2 < p2.self->m_head)
|
||||
pos2 += Queue::MAX_SIZE;
|
||||
|
||||
if (pos2 > pos1)
|
||||
return difference_type(pos2 - pos1);
|
||||
else
|
||||
return -difference_type(pos1 - pos2);
|
||||
}
|
||||
|
||||
void advance(typename base_type::difference_type n)
|
||||
{
|
||||
// Notice that we don't care values of n that can
|
||||
// wrap around more than one time, since it would
|
||||
// be undefined behavior anyway (going outside
|
||||
// the begin/end range). Negative wrapping is a bit
|
||||
// cumbersome because we don't want to case p.pos
|
||||
// to signed.
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
if (p.pos < (std::size_t)n)
|
||||
p.pos = Queue::MAX_SIZE+1 - (n - p.pos);
|
||||
else
|
||||
p.pos -= n;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.pos += n;
|
||||
if (p.pos >= Queue::MAX_SIZE+1)
|
||||
p.pos -= Queue::MAX_SIZE+1;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
position_type p;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, std::size_t N>
|
||||
class fixed_size_queue
|
||||
{
|
||||
private:
|
||||
struct position
|
||||
{
|
||||
fixed_size_queue* self;
|
||||
std::size_t pos;
|
||||
|
||||
position() : self(0), pos(0) {}
|
||||
|
||||
// The const_cast here is just to avoid to have two different
|
||||
// position structures for the const and non-const case.
|
||||
// The const semantic is guaranteed by the iterator itself
|
||||
position(const fixed_size_queue* s, std::size_t p)
|
||||
: self(const_cast<fixed_size_queue*>(s)), pos(p)
|
||||
{}
|
||||
};
|
||||
|
||||
public:
|
||||
// Declare the iterators
|
||||
typedef fsq_iterator<fixed_size_queue<T, N>, T, T*> iterator;
|
||||
typedef
|
||||
fsq_iterator<fixed_size_queue<T, N>, T const, T const*>
|
||||
const_iterator;
|
||||
typedef position position_type;
|
||||
|
||||
friend class fsq_iterator<fixed_size_queue<T, N>, T, T*>;
|
||||
friend class fsq_iterator<fixed_size_queue<T, N>, T const, T const*>;
|
||||
|
||||
fixed_size_queue();
|
||||
fixed_size_queue(const fixed_size_queue& x);
|
||||
fixed_size_queue& operator=(const fixed_size_queue& x);
|
||||
~fixed_size_queue();
|
||||
|
||||
void push_back(const T& e);
|
||||
void push_front(const T& e);
|
||||
void serve(T& e);
|
||||
void pop_front();
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return m_size == N;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(position(this, m_head));
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(position(this, m_head));
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(position(this, m_tail));
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(position(this, m_tail));
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
T& front()
|
||||
{
|
||||
return m_queue[m_head];
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
{
|
||||
return m_queue[m_head];
|
||||
}
|
||||
|
||||
private:
|
||||
// Redefine the template parameters to avoid using partial template
|
||||
// specialization on the iterator policy to extract N.
|
||||
BOOST_STATIC_CONSTANT(std::size_t, MAX_SIZE = N);
|
||||
|
||||
std::size_t m_head;
|
||||
std::size_t m_tail;
|
||||
std::size_t m_size;
|
||||
T m_queue[N+1];
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::fixed_size_queue()
|
||||
: m_head(0)
|
||||
, m_tail(0)
|
||||
, m_size(0)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::fixed_size_queue(const fixed_size_queue& x)
|
||||
: m_head(x.m_head)
|
||||
, m_tail(x.m_tail)
|
||||
, m_size(x.m_size)
|
||||
{
|
||||
copy(x.begin(), x.end(), begin());
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline fixed_size_queue<T, N>&
|
||||
fixed_size_queue<T, N>::operator=(const fixed_size_queue& x)
|
||||
{
|
||||
if (this != &x)
|
||||
{
|
||||
m_head = x.m_head;
|
||||
m_tail = x.m_tail;
|
||||
m_size = x.m_size;
|
||||
copy(x.begin(), x.end(), begin());
|
||||
}
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::~fixed_size_queue()
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::push_back(const T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
BOOST_ASSERT(!full());
|
||||
|
||||
m_queue[m_tail] = e;
|
||||
++m_size;
|
||||
++m_tail;
|
||||
if (m_tail == N+1)
|
||||
m_tail = 0;
|
||||
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::push_front(const T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
BOOST_ASSERT(!full());
|
||||
|
||||
if (m_head == 0)
|
||||
m_head = N;
|
||||
else
|
||||
--m_head;
|
||||
|
||||
m_queue[m_head] = e;
|
||||
++m_size;
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::serve(T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
e = m_queue[m_head];
|
||||
pop_front();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::pop_front()
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
++m_head;
|
||||
if (m_head == N+1)
|
||||
m_head = 0;
|
||||
--m_size;
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#undef BOOST_SPIRIT_ASSERT_FSQ_SIZE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/fixed_size_queue.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class fixed_size_queue
|
||||
// Implementation of the StoragePolicy used by multi_pass
|
||||
// fixed_size_queue keeps a circular buffer (implemented by
|
||||
// boost::spirit::fixed_size_queue class) that is size N+1 and stores N
|
||||
// elements.
|
||||
//
|
||||
// It is up to the user to ensure that there is enough look ahead for
|
||||
// their grammar. Currently there is no way to tell if an iterator is
|
||||
// pointing to forgotten data. The leading iterator will put an item in
|
||||
// the queue and remove one when it is incremented. No dynamic allocation
|
||||
// is done, except on creation of the queue (fixed_size_queue constructor).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <std::size_t N>
|
||||
struct fixed_size_queue
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
class unique : public detail::default_storage_policy
|
||||
{
|
||||
private:
|
||||
typedef detail::fixed_size_queue<Value, N> queue_type;
|
||||
|
||||
protected:
|
||||
unique()
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: queuePosition(x.queuePosition)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(queuePosition, x.queuePosition);
|
||||
}
|
||||
|
||||
// This is called when the iterator is dereferenced. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and access the m_input data member.
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference
|
||||
dereference(MultiPass const& mp)
|
||||
{
|
||||
if (mp.queuePosition == mp.shared->queuedElements.end())
|
||||
{
|
||||
return MultiPass::get_input(mp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *mp.queuePosition;
|
||||
}
|
||||
}
|
||||
|
||||
// This is called when the iterator is incremented. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and access the m_input data member.
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass& mp)
|
||||
{
|
||||
if (mp.queuePosition == mp.shared->queuedElements.end())
|
||||
{
|
||||
// don't let the queue get larger than N
|
||||
if (mp.shared->queuedElements.size() >= N)
|
||||
mp.shared->queuedElements.pop_front();
|
||||
|
||||
mp.shared->queuedElements.push_back(MultiPass::get_input(mp));
|
||||
MultiPass::advance_input(mp);
|
||||
}
|
||||
++mp.queuePosition;
|
||||
}
|
||||
|
||||
// clear_queue is a no-op
|
||||
|
||||
// called to determine whether the iterator is an eof iterator
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp)
|
||||
{
|
||||
return mp.queuePosition == mp.shared->queuedElements.end() &&
|
||||
MultiPass::input_at_eof(mp);
|
||||
}
|
||||
|
||||
// called by operator==
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queuePosition == x.queuePosition;
|
||||
}
|
||||
|
||||
// called by operator<
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queuePosition < x.queuePosition;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable typename queue_type::iterator queuePosition;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
struct shared
|
||||
{
|
||||
typedef detail::fixed_size_queue<Value, N> queue_type;
|
||||
queue_type queuedElements;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_16_2008_0448M)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_16_2008_0448M
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class functor_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
// functor_input gets tokens from a functor
|
||||
//
|
||||
// Note: the functor must have a typedef for result_type
|
||||
// It also must have a static variable of type result_type defined
|
||||
// to represent EOF that is called eof.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct functor_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
private:
|
||||
typedef typename Functor::result_type result_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const& x) : ftor(x) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(ftor, x.ftor);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
public:
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
t = mp.ftor();
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
return t == mp.ftor.eof;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
using namespace is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
Functor& get_functor() const
|
||||
{
|
||||
return ftor;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable Functor ftor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(Functor const& x) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_INPUT_ITERATOR_POLICY_MAR_16_2007_1156AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_INPUT_ITERATOR_POLICY_MAR_16_2007_1156AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace input_iterator_is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class input_iterator
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
//
|
||||
// The input_iterator encapsulates an input iterator of type T
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct input_iterator
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
private:
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::value_type
|
||||
result_type;
|
||||
|
||||
public:
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::difference_type
|
||||
difference_type;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::distance_type
|
||||
distance_type;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::pointer
|
||||
pointer;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::reference
|
||||
reference;
|
||||
typedef result_type value_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(T x) : input(x) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(input, x.input);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
t = *++mp.input;
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const&)
|
||||
{
|
||||
return mp.input == T();
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
using namespace input_iterator_is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
protected:
|
||||
T input;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(T) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_LEX_INPUT_POLICY_MAR_16_2007_1205PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_LEX_INPUT_POLICY_MAR_16_2007_1205PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// class lex_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
//
|
||||
// The lex_input class gets tokens (integers) from yylex()
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct lex_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
public:
|
||||
typedef int value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef int* pointer;
|
||||
typedef int& reference;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(T) {}
|
||||
|
||||
public:
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
{
|
||||
extern int yylex();
|
||||
t = yylex();
|
||||
}
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return 0 == t;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return -1 != t;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(T) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1122AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1122AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline void swap(T& t1, T& t2)
|
||||
{
|
||||
using std::swap;
|
||||
using boost::spirit::swap;
|
||||
swap(t1, t2);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Meta-function to generate a std::iterator<> base class for multi_pass.
|
||||
// This is used mainly to improve conformance of compilers not supporting
|
||||
// PTS and thus relying on inheritance to recognize an iterator.
|
||||
//
|
||||
// We are using boost::iterator<> because it offers an automatic
|
||||
// workaround for broken std::iterator<> implementations.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename InputPolicy>
|
||||
struct iterator_base_creator
|
||||
{
|
||||
typedef typename InputPolicy::BOOST_NESTED_TEMPLATE unique<T> input_type;
|
||||
|
||||
typedef boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
typename input_type::value_type,
|
||||
typename input_type::difference_type,
|
||||
typename input_type::pointer,
|
||||
typename input_type::reference
|
||||
> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default implementations of the different policies to be used with a
|
||||
// multi_pass iterator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct default_input_policy
|
||||
{
|
||||
default_input_policy() {}
|
||||
|
||||
template <typename Functor>
|
||||
default_input_policy(Functor const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_input_policy&) {}
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static TokenType& advance_input(MultiPass& mp, TokenType& curtok);
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static bool input_at_eof(MultiPass const& mp, TokenType& curtok);
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static bool input_is_valid(MultiPass& mp, TokenType& curtok);
|
||||
};
|
||||
|
||||
struct default_ownership_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_ownership_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clone(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const& mp);
|
||||
};
|
||||
|
||||
struct default_storage_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_storage_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference dereference(MultiPass const& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x);
|
||||
};
|
||||
|
||||
struct default_checking_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_checking_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_NO_CHECK_POLICY_MAR_16_2007_1121AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_NO_CHECK_POLICY_MAR_16_2007_1121AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class no_check
|
||||
// Implementation of the CheckingPolicy used by multi_pass
|
||||
// It does not do anything :-)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct no_check
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : public detail::default_checking_policy
|
||||
{
|
||||
void swap(unique&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_REF_COUNTED_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_REF_COUNTED_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class ref_counted
|
||||
// Implementation of an OwnershipPolicy used by multi_pass.
|
||||
//
|
||||
// Implementation modified from RefCounted class from the Loki library by
|
||||
// Andrei Alexandrescu.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct ref_counted
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : detail::default_ownership_policy
|
||||
{
|
||||
void swap(unique&) {}
|
||||
|
||||
// clone is called when a copy of the iterator is made, so
|
||||
// increment the ref-count.
|
||||
template <typename MultiPass>
|
||||
static void clone(MultiPass& mp)
|
||||
{
|
||||
if (0 != mp.shared)
|
||||
++mp.shared->count;
|
||||
}
|
||||
|
||||
// called when a copy is deleted. Decrement the ref-count. Return
|
||||
// value of true indicates that the last copy has been released.
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp)
|
||||
{
|
||||
return 0 != mp.shared && 0 == --mp.shared->count;
|
||||
}
|
||||
|
||||
// returns true if there is only one iterator in existence.
|
||||
// std_deque StoragePolicy will free it's buffered data if this
|
||||
// returns true.
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const& mp)
|
||||
{
|
||||
return 0 == mp.shared || 1 == mp.shared->count;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
shared() : count(1) {}
|
||||
std::size_t count;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace split_functor_input_is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class split_functor_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
// split_functor_input gets tokens from a functor
|
||||
//
|
||||
// This policy should be used when the functor hold two parts of data: a
|
||||
// unique part (unique for each instance of the iterator) and a shared
|
||||
// part (to be shared between the different copies of the same iterator).
|
||||
// Using this policy allows to merge the shared part of the functor with
|
||||
// the shared part of the iterator data, saving one pointer and one
|
||||
// allocation per iterator instance.
|
||||
//
|
||||
// The Functor template parameter of this policy is expected to be a
|
||||
// std::pair<unique, shared>, where 'unique' and 'shared' represent the
|
||||
// respective parts of the functor itself.
|
||||
//
|
||||
// Note: the unique part of the functor must have a typedef for result_type
|
||||
// It also must have a static variable of type result_type defined
|
||||
// to represent EOF that is called eof.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct split_functor_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Functor,
|
||||
bool FunctorIsEmpty = is_empty<typename Functor::first_type>::value
|
||||
>
|
||||
class unique;
|
||||
|
||||
// the unique part of the functor is empty, do not include the functor
|
||||
// at all to avoid unnecessary padding bytes to be included into the
|
||||
// generated structure
|
||||
template <typename Functor>
|
||||
class unique<Functor, true> // : public detail::default_input_policy
|
||||
{
|
||||
protected:
|
||||
typedef typename Functor::first_type functor_type;
|
||||
typedef typename functor_type::result_type result_type;
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const&) {}
|
||||
|
||||
public:
|
||||
void swap(unique&) {}
|
||||
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static value_type& advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// passing the current token instance as a parameter helps
|
||||
// generating better code if compared to assigning the
|
||||
// result of the functor to this instance
|
||||
return functor_type::get_next(mp, t);
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return t == functor_type::eof;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const&, value_type const& t)
|
||||
{
|
||||
using namespace split_functor_input_is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
functor_type::destroy(mp);
|
||||
}
|
||||
};
|
||||
|
||||
// the unique part of the functor is non-empty
|
||||
template <typename Functor>
|
||||
class unique<Functor, false> : public unique<Functor, true>
|
||||
{
|
||||
protected:
|
||||
typedef typename Functor::first_type functor_type;
|
||||
typedef typename functor_type::result_type result_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const& x) : ftor(x.first) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(ftor, x.ftor);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
public:
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static value_type& advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// passing the current token instance as a parameter helps
|
||||
// generating better code if compared to assigning the
|
||||
// result of the functor to this instance
|
||||
return mp.ftor.get_next(mp, t);
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
return t == mp.ftor.eof;
|
||||
}
|
||||
|
||||
typename Functor::first_type& get_functor() const
|
||||
{
|
||||
return ftor;
|
||||
}
|
||||
|
||||
mutable functor_type ftor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(Functor const& x) : ftor(x.second) {}
|
||||
|
||||
mutable typename Functor::second_type ftor;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class split_std_deque
|
||||
//
|
||||
// Implementation of the StoragePolicy used by multi_pass
|
||||
// This stores all data in a std::vector (despite its name), and keeps an
|
||||
// offset to the current position. It stores all the data unless there is
|
||||
// only one iterator using the queue.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct split_std_deque
|
||||
{
|
||||
enum { threshold = 16 };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
class unique //: public detail::default_storage_policy
|
||||
{
|
||||
private:
|
||||
typedef std::vector<Value> queue_type;
|
||||
|
||||
protected:
|
||||
unique()
|
||||
: queued_position(0)
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: queued_position(x.queued_position)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(queued_position, x.queued_position);
|
||||
}
|
||||
|
||||
// This is called when the iterator is dereferenced. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and call advance_input and input_is_valid.
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference
|
||||
dereference(MultiPass const& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
if (0 == mp.queued_position)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
queue.push_back(Value());
|
||||
return MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
return queue[mp.queued_position++];
|
||||
}
|
||||
else if (!MultiPass::input_is_valid(mp, queue[mp.queued_position-1]))
|
||||
{
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position-1]);
|
||||
}
|
||||
return queue[mp.queued_position-1];
|
||||
}
|
||||
|
||||
// This is called when the iterator is incremented. It's a template
|
||||
// method so we can recover the type of the multi_pass iterator
|
||||
// and call is_unique and advance_input.
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
typename queue_type::size_type size = queue.size();
|
||||
BOOST_ASSERT(0 != size && mp.queued_position <= size);
|
||||
if (mp.queued_position == size)
|
||||
{
|
||||
// check if this is the only iterator
|
||||
if (size >= threshold && MultiPass::is_unique(mp))
|
||||
{
|
||||
// free up the memory used by the queue. we avoid
|
||||
// clearing the queue on every increment, though,
|
||||
// because this would be too time consuming
|
||||
|
||||
// erase all but first item in queue
|
||||
queue.erase(queue.begin()+1, queue.end());
|
||||
mp.queued_position = 0;
|
||||
|
||||
// reuse first entry in the queue and initialize
|
||||
// it from the input
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new entry in the queue and initialize
|
||||
// it from the input
|
||||
queue.push_back(Value());
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++mp.queued_position;
|
||||
}
|
||||
}
|
||||
|
||||
// called to forcibly clear the queue
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass& mp)
|
||||
{
|
||||
mp.shared->queued_elements.clear();
|
||||
mp.queued_position = 0;
|
||||
}
|
||||
|
||||
// called to determine whether the iterator is an eof iterator
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
return 0 != mp.queued_position &&
|
||||
mp.queued_position == queue.size() &&
|
||||
MultiPass::input_at_eof(mp, queue[mp.queued_position-1]);
|
||||
}
|
||||
|
||||
// called by operator==
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queued_position == x.queued_position;
|
||||
}
|
||||
|
||||
// called by operator<
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queued_position < x.queued_position;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
|
||||
protected:
|
||||
mutable typename queue_type::size_type queued_position;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
struct shared
|
||||
{
|
||||
shared() { queued_elements.reserve(threshold); }
|
||||
|
||||
typedef std::vector<Value> queue_type;
|
||||
queue_type queued_elements;
|
||||
};
|
||||
|
||||
}; // split_std_deque
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
// http://spirit.sourceforge.net/
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_LOOK_AHEAD_MAR_16_2007_1253PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_LOOK_AHEAD_MAR_16_2007_1253PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/detail/input_iterator_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/first_owner_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/fixed_size_queue_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// this could be a template typedef, since such a thing doesn't
|
||||
// exist in C++, we'll use inheritance to accomplish the same thing.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, std::size_t N>
|
||||
class look_ahead :
|
||||
public multi_pass<
|
||||
T,
|
||||
multi_pass_policies::input_iterator,
|
||||
multi_pass_policies::first_owner,
|
||||
multi_pass_policies::no_check,
|
||||
multi_pass_policies::fixed_size_queue<N>
|
||||
>
|
||||
{
|
||||
private:
|
||||
typedef multi_pass<
|
||||
T,
|
||||
multi_pass_policies::input_iterator,
|
||||
multi_pass_policies::first_owner,
|
||||
multi_pass_policies::no_check,
|
||||
multi_pass_policies::fixed_size_queue<N> >
|
||||
base_type;
|
||||
|
||||
public:
|
||||
look_ahead()
|
||||
: base_type() {}
|
||||
|
||||
explicit look_ahead(T x)
|
||||
: base_type(x) {}
|
||||
|
||||
look_ahead(look_ahead const& x)
|
||||
: base_type(x) {}
|
||||
|
||||
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
look_ahead(int) // workaround for a bug in the library
|
||||
: base_type() {} // shipped with gcc 3.1
|
||||
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
|
||||
// default generated operators destructor and assignment operator are ok.
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
// http://spirit.sourceforge.net/
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/combine_policies.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The default multi_pass instantiation uses a ref-counted std_deque scheme.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename T, typename Policies>
|
||||
class multi_pass
|
||||
: public Policies::BOOST_NESTED_TEMPLATE unique<T>
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
, typename iterator_base_creator<T, typename Policies::input_policy>::type
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
// unique and shared data types
|
||||
typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T>
|
||||
policies_base_type;
|
||||
typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T>
|
||||
shared_data_type;
|
||||
|
||||
// define the types the standard embedded iterator typedefs are taken
|
||||
// from
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename iterator_base_creator<Input, T>::type iterator_type;
|
||||
#else
|
||||
typedef typename policies_base_type::input_policy iterator_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// standard iterator typedefs
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename iterator_type::value_type value_type;
|
||||
typedef typename iterator_type::difference_type difference_type;
|
||||
typedef typename iterator_type::distance_type distance_type;
|
||||
typedef typename iterator_type::reference reference;
|
||||
typedef typename iterator_type::pointer pointer;
|
||||
|
||||
multi_pass()
|
||||
: shared(0)
|
||||
{}
|
||||
|
||||
explicit multi_pass(T input)
|
||||
: shared(new shared_data_type(input)), policies_base_type(input)
|
||||
{}
|
||||
|
||||
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
// The standard library shipped with gcc-3.1 has a bug in
|
||||
// bits/basic_string.tcc. It tries to use iter::iter(0) to
|
||||
// construct an iterator. Ironically, this happens in sanity
|
||||
// checking code that isn't required by the standard.
|
||||
// The workaround is to provide an additional constructor that
|
||||
// ignores its int argument and behaves like the default constructor.
|
||||
multi_pass(int)
|
||||
: shared(0)
|
||||
{}
|
||||
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
|
||||
~multi_pass()
|
||||
{
|
||||
if (policies_base_type::release(*this)) {
|
||||
policies_base_type::destroy(*this);
|
||||
delete shared;
|
||||
}
|
||||
}
|
||||
|
||||
multi_pass(multi_pass const& x)
|
||||
: shared(x.shared), policies_base_type(x)
|
||||
{
|
||||
policies_base_type::clone(*this);
|
||||
}
|
||||
|
||||
multi_pass& operator=(multi_pass const& x)
|
||||
{
|
||||
if (this != &x) {
|
||||
multi_pass temp(x);
|
||||
temp.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(multi_pass& x)
|
||||
{
|
||||
spirit::detail::swap(shared, x.shared);
|
||||
this->policies_base_type::swap(x);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
policies_base_type::check(*this);
|
||||
return policies_base_type::dereference(*this);
|
||||
}
|
||||
pointer operator->() const
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
|
||||
multi_pass& operator++()
|
||||
{
|
||||
policies_base_type::check(*this);
|
||||
policies_base_type::increment(*this);
|
||||
return *this;
|
||||
}
|
||||
multi_pass operator++(int)
|
||||
{
|
||||
multi_pass tmp(*this);
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void clear_queue()
|
||||
{
|
||||
policies_base_type::clear_queue(*this);
|
||||
}
|
||||
|
||||
bool operator==(multi_pass const& y) const
|
||||
{
|
||||
if (is_eof())
|
||||
return y.is_eof();
|
||||
if (y.is_eof())
|
||||
return false;
|
||||
|
||||
return policies_base_type::equal_to(*this, y);
|
||||
}
|
||||
bool operator<(multi_pass const& y) const
|
||||
{
|
||||
return policies_base_type::less_than(*this, y);
|
||||
}
|
||||
|
||||
private: // helper functions
|
||||
bool is_eof() const
|
||||
{
|
||||
return (0 == shared) || policies_base_type::is_eof(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
shared_data_type *shared;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator!=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator>(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator>=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator<=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator function
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Policies, typename T>
|
||||
inline multi_pass<T, Policies>
|
||||
make_multi_pass(T i)
|
||||
{
|
||||
return multi_pass<T, Policies>(i);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline void
|
||||
swap(multi_pass<T, Policies> &x,
|
||||
multi_pass<T, Policies> &y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
}} // namespace boost::spirit
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_FWD_APR_18_2008_1102AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_FWD_APR_18_2008_1102AM
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost { namespace spirit {
|
||||
|
||||
namespace multi_pass_policies
|
||||
{
|
||||
// input policies
|
||||
struct input_iterator;
|
||||
struct lex_input;
|
||||
struct functor_input;
|
||||
struct split_functor_input;
|
||||
|
||||
// ownership policies
|
||||
struct ref_counted;
|
||||
struct first_owner;
|
||||
|
||||
// checking policies
|
||||
class illegal_backtracking;
|
||||
struct buf_id_check;
|
||||
struct no_check;
|
||||
|
||||
// storage policies
|
||||
struct std_deque;
|
||||
template<std::size_t N> struct fixed_size_queue;
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
class multi_pass;
|
||||
|
||||
template <typename T, typename Policies>
|
||||
void swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T> void swap(T& t1, T& t2);
|
||||
}
|
||||
|
||||
}} // namespace boost::spirit
|
||||
|
||||
#endif
|
||||
|
||||
16
libraries/include/boost/spirit/home/support/meta_grammar.hpp
Normal file
16
libraries/include/boost/spirit/home/support/meta_grammar.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_META_GRAMMAR_JAN_29_2007_0933AM)
|
||||
#define BOOST_SPIRIT_META_GRAMMAR_JAN_29_2007_0933AM
|
||||
|
||||
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar/basic_rules.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar/basic_transforms.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_BASIC_RULES_JAN_14_2007_1222PM)
|
||||
#define BOOST_SPIRIT_BASIC_RULES_JAN_14_2007_1222PM
|
||||
|
||||
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar/basic_transforms.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
#include <boost/proto/transform.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace meta_grammar
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Director>
|
||||
struct director_identity
|
||||
{
|
||||
template <typename>
|
||||
struct apply : mpl::identity<Director> {};
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes an empty (the terminal is not saved in
|
||||
// the elements tuple) terminal spirit::component given a domain,
|
||||
// a proto-tag and a director. Example:
|
||||
//
|
||||
// a
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Tag, typename Director>
|
||||
struct empty_terminal_rule
|
||||
: compose_empty<
|
||||
proto::terminal<Tag>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a non-empty (the terminal is saved in
|
||||
// the elements tuple) terminal spirit::component given a domain,
|
||||
// a proto-tag and a director. Example:
|
||||
//
|
||||
// a
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Tag, typename Director>
|
||||
struct terminal_rule
|
||||
: compose_single<
|
||||
proto::terminal<Tag>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 1-element spirit::component given a
|
||||
// domain, a proto-tag and a director. No folding takes place. Example:
|
||||
//
|
||||
// +a
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag, typename Director
|
||||
, typename SubjectGrammar = proto::_
|
||||
>
|
||||
struct unary_rule
|
||||
: compose_single<
|
||||
proto::unary_expr<
|
||||
Tag
|
||||
, SubjectGrammar
|
||||
>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 2-element spirit::component given a
|
||||
// domain, a proto-tag and a director. No folding takes place. Example:
|
||||
//
|
||||
// a - b
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag, typename Director
|
||||
, typename LeftGrammar = proto::_, typename RightGrammar = proto::_
|
||||
>
|
||||
struct binary_rule
|
||||
: compose_double<
|
||||
proto::binary_expr<
|
||||
Tag
|
||||
, LeftGrammar
|
||||
, RightGrammar
|
||||
>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 3-element spirit::component given a
|
||||
// domain, a proto-tag and a director. No folding takes place. Example:
|
||||
//
|
||||
// if_else(cond_expr,true_exp,false_expr)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
typename Domain, typename Tag, typename Director
|
||||
, typename Grammar0 = proto::_, typename Grammar1 = proto::_, typename Grammar2 = proto::_
|
||||
>
|
||||
struct ternary_rule
|
||||
: compose_triple<
|
||||
proto::nary_expr<
|
||||
Tag
|
||||
, Grammar0
|
||||
, Grammar1
|
||||
, Grammar2
|
||||
>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 1-element spirit::component from a
|
||||
// binary expression. Only the RHS is stored.
|
||||
//
|
||||
// a[b]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag, typename Director
|
||||
, typename LeftGrammar = proto::_, typename RightGrammar = proto::_
|
||||
>
|
||||
struct binary_rule_rhs
|
||||
: compose_right<
|
||||
proto::binary_expr<
|
||||
Tag
|
||||
, LeftGrammar
|
||||
, RightGrammar
|
||||
>
|
||||
, Domain
|
||||
, detail::director_identity<Director>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a multi-element spirit::component given a
|
||||
// domain, a proto-tag and a director. All like-operators are folded
|
||||
// into one. Example:
|
||||
//
|
||||
// a | b | c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag, typename Director
|
||||
, typename Grammar = proto::_
|
||||
>
|
||||
struct binary_rule_flat
|
||||
: compose_list<
|
||||
proto::when<
|
||||
proto::binary_expr<Tag, Grammar, Grammar>
|
||||
, proto::reverse_fold_tree<
|
||||
proto::_
|
||||
, fusion::nil()
|
||||
, fusion::cons<Grammar, proto::_state>(Grammar, proto::_state)
|
||||
>
|
||||
>
|
||||
, Domain
|
||||
, Director
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 1-element function spirit::component
|
||||
// given a domain, a proto-tag and a director. Example:
|
||||
//
|
||||
// f(a)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag
|
||||
, typename Director, typename ArgGrammar = proto::_>
|
||||
struct function1_rule
|
||||
: compose_function1<
|
||||
proto::function<proto::terminal<Tag>, ArgGrammar>
|
||||
, Domain
|
||||
, Director
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 2-element function spirit::component
|
||||
// given a domain, a proto-tag and a director. Example:
|
||||
//
|
||||
// f(a, b)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag
|
||||
, typename Director, typename ArgGrammar = proto::_>
|
||||
struct function2_rule
|
||||
: compose_function2<
|
||||
proto::function<
|
||||
proto::terminal<Tag>
|
||||
, ArgGrammar
|
||||
, ArgGrammar
|
||||
>
|
||||
, Domain
|
||||
, Director
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule for directives. The directive (terminal) tag
|
||||
// is pushed into the modifier state (the Visitor). Example:
|
||||
//
|
||||
// directive[a]
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename SubjectGrammar = proto::_>
|
||||
struct deep_directive_meta_grammar
|
||||
: meta_grammar::compose_deep_directive<
|
||||
proto::when<
|
||||
proto::subscript<proto::terminal<Tag>, SubjectGrammar>
|
||||
, proto::call<SubjectGrammar(proto::_right)>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 2-element spirit::component given a
|
||||
// domain, a proto-tag, a director, and an embedded grammar.
|
||||
// Example:
|
||||
//
|
||||
// directive[p]
|
||||
//
|
||||
// The difference to deep_directive_meta_grammar is that it stores both
|
||||
// parts of the expression without modifying the modifier state
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag,
|
||||
typename Director, typename EmbeddedGrammar = proto::_
|
||||
>
|
||||
struct subscript_rule
|
||||
: compose_subscript<
|
||||
proto::binary_expr<
|
||||
proto::tag::subscript,
|
||||
proto::terminal<Tag>,
|
||||
EmbeddedGrammar
|
||||
>,
|
||||
Domain,
|
||||
Director
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 2-element spirit::component given a
|
||||
// domain, a proto-tag, a director, an argument and an embedded grammar.
|
||||
// Example:
|
||||
//
|
||||
// directive(a)[p]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag,
|
||||
typename Director, typename ArgGrammar = proto::_,
|
||||
typename EmbeddedGrammar = proto::_
|
||||
>
|
||||
struct subscript_function1_rule
|
||||
: compose_subscript_function1<
|
||||
proto::binary_expr<
|
||||
proto::tag::subscript,
|
||||
proto::function<proto::terminal<Tag>, ArgGrammar>,
|
||||
EmbeddedGrammar
|
||||
>,
|
||||
Domain,
|
||||
Director
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto rule that composes a 3-element spirit::component given a
|
||||
// domain, a proto-tag, a director, two arguments and an embedded grammar.
|
||||
// Example:
|
||||
//
|
||||
// directive(a, b)[p]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Domain, typename Tag,
|
||||
typename Director, typename Arg1Grammar = proto::_,
|
||||
typename Arg2Grammar = proto::_, typename EmbeddedGrammar = proto::_
|
||||
>
|
||||
struct subscript_function2_rule
|
||||
: compose_subscript_function2<
|
||||
proto::binary_expr<
|
||||
proto::tag::subscript,
|
||||
proto::function<proto::terminal<Tag>, Arg1Grammar, Arg2Grammar>,
|
||||
EmbeddedGrammar
|
||||
>,
|
||||
Domain,
|
||||
Director
|
||||
>
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,751 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_BASIC_TRANSFORMS_JAN_14_2007_1222PM)
|
||||
#define BOOST_SPIRIT_BASIC_TRANSFORMS_JAN_14_2007_1222PM
|
||||
|
||||
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
|
||||
#include <boost/proto/core.hpp>
|
||||
#include <boost/proto/transform.hpp>
|
||||
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/fusion/include/list.hpp>
|
||||
#include <boost/fusion/include/make_cons.hpp>
|
||||
#include <boost/fusion/include/make_list.hpp>
|
||||
|
||||
#include <boost/mpl/apply.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace meta_grammar
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Invoke the specified grammar in the "Proto v2" way, dropping top
|
||||
// level const and reference on the three parameters
|
||||
//template<typename Grammar, typename Expr, typename State, typename Data>
|
||||
//typename Grammar::template impl<Expr, State, Data>::result_type
|
||||
//invoke_grammar(Expr const &expr, State const &state, Data &data)
|
||||
//{
|
||||
// return typename Grammar::template impl<Expr, State, Data>()(expr, state, data);
|
||||
//}
|
||||
|
||||
template<typename Grammar, typename Expr, typename State, typename Data>
|
||||
struct invoke_grammar
|
||||
: Grammar::template impl<Expr, State, Data>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating empty component meta descriptions
|
||||
// (proto expressions) usable for defining meta grammars. Additionally,
|
||||
// this is used to make the corresponding spirit component.
|
||||
//
|
||||
// Grammar: the proto grammar to use as the base for this component
|
||||
// meta description (i.e.: proto::terminal<Tag>)
|
||||
// Domain: the domain this proto transform is defined for
|
||||
// (i.e.: qi::domain)
|
||||
// DirectorF: the director is the real component form the specified
|
||||
// domain (i.e.: any_char)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_empty : proto::transform<compose_empty<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename proto::result_of::child<Expr>::type arg_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply1<DirectorF, arg_type>::type
|
||||
, fusion::nil
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param
|
||||
, typename impl::state_param
|
||||
, typename impl::data_param
|
||||
) const
|
||||
{
|
||||
return make_component::call(fusion::nil());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating single-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
//
|
||||
// Grammar: the proto grammar to use as the base for this component
|
||||
// meta description (i.e.: proto::unary_expr<Tag, ...>)
|
||||
// Domain: the domain this proto transform is defined for
|
||||
// (i.e.: qi::domain)
|
||||
// DirectorF: the director is the real component from the specified
|
||||
// domain (i.e.: negated_char_parser<...>)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_single : proto::transform<compose_single<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename Grammar::template impl<Expr, State, Data>::result_type
|
||||
>::type
|
||||
arg_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply1<DirectorF, arg_type>::type
|
||||
, typename fusion::result_of::make_cons<arg_type>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
return make_component::call(
|
||||
fusion::make_cons(
|
||||
proto::child(invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data))
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating double-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
//
|
||||
// Grammar: the proto grammar to use as the base for this component
|
||||
// meta description (i.e.: proto::binary_expr<Tag, ...>)
|
||||
// Domain: the domain this proto transform is defined for
|
||||
// (for instance: qi::domain)
|
||||
// DirectorF: the director is the real component form the specified
|
||||
// domain (i.e.: difference)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_double : proto::transform<compose_double<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
typedef typename proto::result_of::left<trans>::type left_type;
|
||||
typedef typename proto::result_of::right<trans>::type right_type;
|
||||
typedef typename
|
||||
fusion::result_of::make_list<left_type, right_type>::type
|
||||
list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply1<DirectorF, list_type>::type
|
||||
, list_type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
return make_component::call(
|
||||
fusion::make_list(proto::left(t), proto::right(t))
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating triple-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
//
|
||||
// Grammar: the proto grammar to use as the base for this component
|
||||
// meta description (i.e.: proto::nary_expr<Tag,a,b,c>)
|
||||
// Domain: the domain this proto transform is defined for
|
||||
// (for instance: qi::domain)
|
||||
// DirectorF: the director is the real component form the specified
|
||||
// domain (i.e.: difference)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_triple : proto::transform<compose_triple<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
typedef typename proto::result_of::child_c<trans, 0>::type arg0_type;
|
||||
typedef typename proto::result_of::child_c<trans, 1>::type arg1_type;
|
||||
typedef typename proto::result_of::child_c<trans, 2>::type arg2_type;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::make_list<arg0_type, arg1_type, arg2_type>::type
|
||||
list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply1<DirectorF, list_type>::type
|
||||
, list_type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
return make_component::call(
|
||||
fusion::make_list(proto::child_c<0>(t), proto::child_c<1>(t), proto::child_c<2>(t))
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating single-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars
|
||||
// Only the RHS is stored.
|
||||
//
|
||||
// Grammar: the proto grammar to use as the base for this component
|
||||
// meta description (i.e.: proto::binary_expr<Tag, ...>)
|
||||
// Domain: the domain this proto transform is defined for
|
||||
// (for instance: qi::domain)
|
||||
// DirectorF: the director is the real component form the specified
|
||||
// domain (i.e.: difference)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_right : proto::transform<compose_right<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
typedef typename proto::result_of::right<trans>::type right_type;
|
||||
typedef typename
|
||||
fusion::result_of::make_list<right_type>::type
|
||||
list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply1<DirectorF, list_type>::type
|
||||
, list_type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
return make_component::call(
|
||||
fusion::make_list(proto::right(t))
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform that accepts a proto::if_ predicate and
|
||||
// applies a supplied indirect transform if the predicate is true.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Pred, typename TransformF>
|
||||
struct if_transform
|
||||
: proto::when<proto::if_<Pred>, proto::lazy<TransformF> >
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform that composes components from a fusion::list
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_list : proto::transform<compose_list<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain, Director
|
||||
, typename Grammar::template impl<Expr, State, Data>::result_type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
return make_component::call(invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform that composes a single-element component
|
||||
// from a 1-arity proto function expression (e.g. f(x))
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_function1 : proto::transform<compose_function1<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 1>::type
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain, Director
|
||||
, typename fusion::result_of::make_cons<arg1>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
return make_component::call(fusion::make_cons(proto::child(proto::child_c<1>(expr))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Same as compose_function1, except that DirectorF is a meta-function to
|
||||
// be evaluated to get the director
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_function1_eval : proto::transform<compose_function1_eval<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 0>::type
|
||||
>::type
|
||||
function;
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 1>::type
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply2<DirectorF, function, arg1>::type
|
||||
, typename fusion::result_of::make_cons<arg1>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
return make_component::call(
|
||||
fusion::make_cons(proto::child(proto::child_c<1>(expr))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Same as compose_function1, except that the generated component holds
|
||||
// not only the function argument, but the function tag as well
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_function1_full : proto::transform<compose_function1_full<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 0>::type
|
||||
>::type
|
||||
function;
|
||||
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 1>::type
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply2<DirectorF, function, arg1>::type
|
||||
, typename fusion::result_of::make_list<function, arg1>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param
|
||||
, typename impl::data_param
|
||||
) const
|
||||
{
|
||||
return make_component::call(fusion::make_list(
|
||||
proto::child(proto::child_c<0>(expr)),
|
||||
proto::child(proto::child_c<1>(expr))
|
||||
));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform that composes a 2-element component
|
||||
// from a 2-arity proto function expression (e.g. f(x, y))
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_function2 : proto::transform<compose_function2<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 1>::type
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 2>::type
|
||||
>::type
|
||||
arg2;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain, Director
|
||||
, typename fusion::result_of::make_list<arg1, arg2>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param
|
||||
, typename impl::data_param
|
||||
) const
|
||||
{
|
||||
return make_component::call(fusion::make_list(
|
||||
proto::child(proto::child_c<1>(expr))
|
||||
, proto::child(proto::child_c<2>(expr))
|
||||
));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Same as compose_function2, except that DirectorF is a meta-function to
|
||||
// be evaluated to get the director
|
||||
template <typename Grammar, typename Domain, typename DirectorF>
|
||||
struct compose_function2_eval : proto::transform<compose_function2_eval<Grammar, Domain, DirectorF> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 0>::type
|
||||
>::type
|
||||
function;
|
||||
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 1>::type
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
typedef typename
|
||||
proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 2>::type
|
||||
>::type
|
||||
arg2;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain
|
||||
, typename mpl::apply2<DirectorF, function, arg1>::type
|
||||
, typename fusion::result_of::make_list<arg1, arg2>::type
|
||||
, Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param
|
||||
, typename impl::data_param
|
||||
) const
|
||||
{
|
||||
return make_component::call(fusion::make_list(
|
||||
proto::child(proto::child_c<1>(expr))
|
||||
, proto::child(proto::child_c<2>(expr))
|
||||
));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for directives. The directive (terminal) tag
|
||||
// is pushed into the modifier state (the Data).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar>
|
||||
struct compose_deep_directive : proto::transform<compose_deep_directive<Grammar> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
typedef typename
|
||||
add_modifier<
|
||||
Data
|
||||
, typename proto::result_of::child<
|
||||
typename proto::result_of::child_c<Expr, 0>::type
|
||||
>::type
|
||||
>::type
|
||||
modifier_type;
|
||||
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, modifier_type>::result_type
|
||||
result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param
|
||||
) const
|
||||
{
|
||||
modifier_type modifier;
|
||||
return invoke_grammar<Grammar, Expr, State, modifier_type>()(expr, state, modifier);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating double-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
// This can be used to handle constructs like:
|
||||
//
|
||||
// directive[p]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_subscript : proto::transform<compose_subscript<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
// apply all grammar transformations mandated for the whole
|
||||
// expression
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
// this calculates the type of the directive
|
||||
typedef typename proto::result_of::child_c<trans, 0>::type directive;
|
||||
|
||||
// this calculates the type of the embedded expression
|
||||
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
|
||||
|
||||
// this is the type of the contained data
|
||||
typedef fusion::list<embedded, directive> list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<Domain, Director, list_type, Data>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
return make_component::call(
|
||||
list_type(proto::child_c<1>(t), proto::child_c<0>(t)));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating double-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
// This can be used to handle constructs like:
|
||||
//
|
||||
// directive(a)[p]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_subscript_function1 : proto::transform<compose_subscript_function1<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
// apply all grammar transformations mandated for the whole
|
||||
// expression
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
// this calculates the type of the embedded expression
|
||||
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
|
||||
|
||||
// this calculates the type of the argument of the function
|
||||
typedef typename
|
||||
proto::result_of::child_c<
|
||||
typename proto::result_of::child_c<trans, 0>::type, 1
|
||||
>::type
|
||||
arg1;
|
||||
|
||||
// this is the type of the contained data
|
||||
typedef fusion::list<embedded, arg1> list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain, Director,
|
||||
list_type,
|
||||
Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
|
||||
return make_component::call(list_type(
|
||||
proto::child_c<1>(t),
|
||||
proto::child_c<1>(proto::child_c<0>(t))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// A proto transform for creating triple-element component meta
|
||||
// descriptions (proto expressions) usable for defining meta grammars.
|
||||
// This can be used to handle constructs like:
|
||||
//
|
||||
// directive(a, b)[p]
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Grammar, typename Domain, typename Director>
|
||||
struct compose_subscript_function2 : proto::transform<compose_subscript_function2<Grammar, Domain, Director> >, Grammar
|
||||
{
|
||||
template<typename Expr, typename State, typename Data>
|
||||
struct impl : proto::transform_impl<Expr, State, Data>
|
||||
{
|
||||
// apply all grammar transformations mandated for the whole
|
||||
// expression
|
||||
typedef typename
|
||||
Grammar::template impl<Expr, State, Data>::result_type
|
||||
trans;
|
||||
|
||||
// this calculates the types of the arguments of the function
|
||||
typedef typename proto::result_of::child_c<trans, 0>::type arg0;
|
||||
typedef typename proto::result_of::child_c<arg0, 1>::type arg1;
|
||||
typedef typename proto::result_of::child_c<arg0, 2>::type arg2;
|
||||
|
||||
// this calculates the type of the embedded expression
|
||||
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
|
||||
typedef fusion::list<embedded, arg1, arg2> list_type;
|
||||
|
||||
typedef
|
||||
traits::make_component<
|
||||
Domain, Director,
|
||||
list_type,
|
||||
Data
|
||||
>
|
||||
make_component;
|
||||
|
||||
typedef typename make_component::type result_type;
|
||||
|
||||
result_type operator ()(
|
||||
typename impl::expr_param expr
|
||||
, typename impl::state_param state
|
||||
, typename impl::data_param data
|
||||
) const
|
||||
{
|
||||
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
|
||||
arg0 a0 = proto::child_c<0>(t);
|
||||
|
||||
return make_component::call(list_type(
|
||||
proto::child_c<1>(t), proto::child_c<1>(a0),
|
||||
proto::child_c<2>(a0)));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_GRAMMAR_OF_JAN_28_2007_0419PM)
|
||||
#define BOOST_SPIRIT_GRAMMAR_OF_JAN_28_2007_0419PM
|
||||
|
||||
namespace boost { namespace spirit { namespace meta_grammar
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Each domain has a proto meta-grammar. This is the metafunction
|
||||
// that return the domain's meta-grammar.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain>
|
||||
struct grammar;
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
90
libraries/include/boost/spirit/home/support/modifier.hpp
Normal file
90
libraries/include/boost/spirit/home/support/modifier.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_MODIFIER_FEB_05_2007_0259PM)
|
||||
#define BOOST_SPIRIT_MODIFIER_FEB_05_2007_0259PM
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The modifier is like a set of types. Types can be added (but not
|
||||
// removed). The unique feature of the modifier is that addition of
|
||||
// types is done using inheritance. Thus, checking for membership
|
||||
// involves checking for inheritance. More importantly, because the
|
||||
// modifier inherits from a type, the type's members (typedefs,
|
||||
// nested structs, etc.), are all visible; unless, of course, if the
|
||||
// member is hidden (newer types take priority) or there's ambiguity.
|
||||
//
|
||||
// to add: add_modifier<Modifier, T>
|
||||
// to test for membership: is_member_of_modifier<Modifier, T>
|
||||
//
|
||||
// The modifier is used as the "Visitor" in proto transforms to
|
||||
// modify the behavior of the expression template building.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Set = unused_type, typename New = unused_type>
|
||||
struct modifier : Set, New {};
|
||||
|
||||
template <typename Set>
|
||||
struct modifier<Set, unused_type> : Set {};
|
||||
|
||||
template <typename New>
|
||||
struct modifier<unused_type, New> : New {};
|
||||
|
||||
template <>
|
||||
struct modifier<unused_type, unused_type> {};
|
||||
|
||||
template <typename Modifier, typename New>
|
||||
struct add_modifier
|
||||
{
|
||||
typedef typename // add only if New is not a member
|
||||
mpl::if_<
|
||||
is_base_of<New, Modifier>
|
||||
, Modifier
|
||||
, modifier<Modifier, New>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Modifier, typename T>
|
||||
struct is_member_of_modifier : is_base_of<T, Modifier> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This is the main customization point for hooking into the
|
||||
// make_component mechanism for building /modified/ components.
|
||||
// The make_component specialization detects modifier Visitors
|
||||
// and dispatches to the secondary template make_modified_component
|
||||
// for clients to specialize. By default, the modifier is ignored
|
||||
// and the control goes back to make_component.
|
||||
//
|
||||
// (see also: component.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace traits
|
||||
{
|
||||
template <
|
||||
typename Domain, typename Director, typename Elements
|
||||
, typename Modifier, typename Enable = void>
|
||||
struct make_modified_component :
|
||||
make_component<Domain, Director, Elements, unused_type>
|
||||
{
|
||||
};
|
||||
|
||||
template <
|
||||
typename Domain, typename Director
|
||||
, typename Elements, typename Set, typename New>
|
||||
struct make_component<Domain, Director, Elements, modifier<Set, New> >
|
||||
: make_modified_component<Domain, Director, Elements, modifier<Set, New> >
|
||||
{
|
||||
};
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
32
libraries/include/boost/spirit/home/support/multi_pass.hpp
Normal file
32
libraries/include/boost/spirit/home/support/multi_pass.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_0201AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_0201AM
|
||||
|
||||
// Include everything needed for the default configuration of multi_pass
|
||||
// Ownership policies
|
||||
#include <boost/spirit/home/support/iterators/detail/first_owner_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/ref_counted_policy.hpp>
|
||||
|
||||
// Input policies
|
||||
#include <boost/spirit/home/support/iterators/detail/input_iterator_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/lex_input_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp>
|
||||
|
||||
// Checking policies
|
||||
#include <boost/spirit/home/support/iterators/detail/buf_id_check_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
|
||||
|
||||
// Storage policies
|
||||
#include <boost/spirit/home/support/iterators/detail/fixed_size_queue_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/split_std_deque_policy.hpp>
|
||||
|
||||
// Main multi_pass iterator
|
||||
#include <boost/spirit/home/support/iterators/detail/combine_policies.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/spirit/home/support/iterators/multi_pass.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_EXPAND_ARG_FEB_19_2007_1107AM)
|
||||
#define BOOST_SPIRIT_EXPAND_ARG_FEB_19_2007_1107AM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/type_traits/is_scalar.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Context>
|
||||
struct expand_arg
|
||||
{
|
||||
template <typename T>
|
||||
struct result_type
|
||||
{
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_scalar<T>
|
||||
, mpl::identity<T const &>
|
||||
, boost::result_of<T(unused_type, Context)>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct result;
|
||||
|
||||
template <typename F, typename A0>
|
||||
struct result<F(A0)>
|
||||
: result_type<A0> {};
|
||||
|
||||
template <typename F, typename A0>
|
||||
struct result<F(A0&)>
|
||||
: result_type<A0> {};
|
||||
|
||||
expand_arg(Context& context)
|
||||
: context(context)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename result_type<T>::type
|
||||
call(T const& f, mpl::false_) const
|
||||
{
|
||||
return f(unused, context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename result_type<T>::type
|
||||
call(T const& val, mpl::true_) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename result_type<T>::type
|
||||
operator()(T const& x) const
|
||||
{
|
||||
return call(x, is_scalar<T>());
|
||||
}
|
||||
|
||||
Context& context;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
#include <boost/preprocessor/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
#define BOOST_PP_FILENAME_1 \
|
||||
<boost/spirit/home/support/nonterminal/detail/nonterminal_fcall.hpp>
|
||||
#define BOOST_PP_ITERATION_LIMITS (1, SPIRIT_ARG_LIMIT)
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Preprocessor vertical repetition code
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#else // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
template <BOOST_PP_ENUM_PARAMS(N, typename A)>
|
||||
typename lazy_enable_if_c<
|
||||
(mpl::size<param_types>::value == N)
|
||||
, make_nonterminal_holder<
|
||||
parameterized_nonterminal<
|
||||
Derived
|
||||
, fusion::vector<BOOST_PP_ENUM_PARAMS(N, A)>
|
||||
>
|
||||
, Derived
|
||||
>
|
||||
>::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& f)) const
|
||||
{
|
||||
typename
|
||||
make_nonterminal_holder<
|
||||
parameterized_nonterminal<
|
||||
Derived
|
||||
, fusion::vector<BOOST_PP_ENUM_PARAMS(N, A)>
|
||||
>
|
||||
, Derived
|
||||
>::type
|
||||
result =
|
||||
{{
|
||||
static_cast<Derived const*>(this)
|
||||
, fusion::vector<BOOST_PP_ENUM_PARAMS(N, A)>(
|
||||
BOOST_PP_ENUM_PARAMS(N, f))
|
||||
}};
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef N
|
||||
#endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_LOCALS_APR_03_2007_0506PM)
|
||||
#define BOOST_SPIRIT_LOCALS_APR_03_2007_0506PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#if !defined(BOOST_SPIRIT_MAX_LOCALS_SIZE)
|
||||
# define BOOST_SPIRIT_MAX_LOCALS_SIZE 10
|
||||
#else
|
||||
# if BOOST_SPIRIT_MAX_LOCALS_SIZE < 3
|
||||
# undef BOOST_SPIRIT_MAX_LOCALS_SIZE
|
||||
# define BOOST_SPIRIT_MAX_LOCALS_SIZE 10
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
|
||||
BOOST_SPIRIT_MAX_LOCALS_SIZE, typename T, mpl::na)
|
||||
>
|
||||
struct locals
|
||||
: mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_SPIRIT_MAX_LOCALS_SIZE, T)> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
struct is_locals
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <BOOST_PP_ENUM_PARAMS(BOOST_SPIRIT_MAX_LOCALS_SIZE, typename T)>
|
||||
struct is_locals<locals<BOOST_PP_ENUM_PARAMS(BOOST_SPIRIT_MAX_LOCALS_SIZE, T)> >
|
||||
: mpl::true_
|
||||
{};
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_NONTERMINAL_MAR_06_2007_0236PM)
|
||||
#define BOOST_SPIRIT_NONTERMINAL_MAR_06_2007_0236PM
|
||||
|
||||
#include <boost/proto/core.hpp>
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/joint_view.hpp>
|
||||
#include <boost/fusion/include/single_view.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
template <typename T, typename Nonterminal>
|
||||
struct nonterminal_holder
|
||||
{
|
||||
typedef Nonterminal nonterminal_type;
|
||||
T held;
|
||||
};
|
||||
|
||||
template <typename T, typename Nonterminal>
|
||||
struct make_nonterminal_holder
|
||||
: proto::terminal<nonterminal_holder<T, Nonterminal> >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Nonterminal, typename FSequence>
|
||||
struct parameterized_nonterminal
|
||||
{
|
||||
Nonterminal const* ptr;
|
||||
FSequence fseq;
|
||||
};
|
||||
|
||||
template <typename Nonterminal>
|
||||
struct nonterminal_object
|
||||
{
|
||||
Nonterminal obj;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
412
libraries/include/boost/spirit/home/support/placeholders.hpp
Normal file
412
libraries/include/boost/spirit/home/support/placeholders.hpp
Normal file
@@ -0,0 +1,412 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Hartmut Kaiser
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_PLACEHOLDERS_NOV_18_2006_0326PM)
|
||||
#define BOOST_SPIRIT_PLACEHOLDERS_NOV_18_2006_0326PM
|
||||
|
||||
#include <boost/proto/core.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// This file contains the common placeholders. If you have a placeholder
|
||||
// that can be (re)used in different spirit domains. This is the place
|
||||
// to put them in.
|
||||
|
||||
namespace tag
|
||||
{
|
||||
struct char_ {};
|
||||
struct wchar {};
|
||||
struct lit {};
|
||||
struct wlit {};
|
||||
struct eol {};
|
||||
struct eoi {};
|
||||
|
||||
struct bin {};
|
||||
struct oct {};
|
||||
struct hex {};
|
||||
|
||||
struct byte {};
|
||||
struct word {};
|
||||
struct dword {};
|
||||
struct big_word {};
|
||||
struct big_dword {};
|
||||
struct little_word {};
|
||||
struct little_dword {};
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
struct qword {};
|
||||
struct big_qword {};
|
||||
struct little_qword {};
|
||||
#endif
|
||||
struct pad {};
|
||||
|
||||
struct ushort {};
|
||||
struct ulong {};
|
||||
struct uint {};
|
||||
struct short_ {};
|
||||
struct long_ {};
|
||||
struct int_ {};
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
struct ulong_long {};
|
||||
struct long_long {};
|
||||
#endif
|
||||
struct float_ {};
|
||||
struct double_ {};
|
||||
struct long_double {};
|
||||
|
||||
struct left_align {};
|
||||
struct right_align {};
|
||||
struct center {};
|
||||
|
||||
struct delimit {};
|
||||
struct verbatim {};
|
||||
|
||||
struct none {};
|
||||
struct eps {};
|
||||
struct lexeme {};
|
||||
struct lazy {};
|
||||
struct omit {};
|
||||
struct raw {};
|
||||
|
||||
struct stream {};
|
||||
struct wstream {};
|
||||
|
||||
struct token {};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
typedef proto::terminal<tag::char_>::type char_type;
|
||||
typedef proto::terminal<tag::wchar>::type wchar_type;
|
||||
typedef proto::terminal<tag::lit>::type lit_type;
|
||||
typedef proto::terminal<tag::wlit>::type wlit_type;
|
||||
typedef proto::terminal<tag::eol>::type eol_type;
|
||||
typedef proto::terminal<tag::eoi>::type eoi_type;
|
||||
|
||||
typedef proto::terminal<tag::bin>::type bin_type;
|
||||
typedef proto::terminal<tag::oct>::type oct_type;
|
||||
typedef proto::terminal<tag::hex>::type hex_type;
|
||||
|
||||
typedef proto::terminal<tag::byte>::type byte_type;
|
||||
typedef proto::terminal<tag::word>::type word_type;
|
||||
typedef proto::terminal<tag::dword>::type dword_type;
|
||||
typedef proto::terminal<tag::big_word>::type big_word_type;
|
||||
typedef proto::terminal<tag::big_dword>::type big_dword_type;
|
||||
typedef proto::terminal<tag::little_word>::type little_word_type;
|
||||
typedef proto::terminal<tag::little_dword>::type little_dword_type;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
typedef proto::terminal<tag::qword>::type qword_type;
|
||||
typedef proto::terminal<tag::big_qword>::type big_qword_type;
|
||||
typedef proto::terminal<tag::little_qword>::type little_qword_type;
|
||||
#endif
|
||||
typedef proto::terminal<tag::pad>::type pad_type;
|
||||
|
||||
typedef proto::terminal<tag::ushort>::type ushort_type;
|
||||
typedef proto::terminal<tag::ulong>::type ulong_type;
|
||||
typedef proto::terminal<tag::uint>::type uint_type;
|
||||
typedef proto::terminal<tag::short_>::type short_type;
|
||||
typedef proto::terminal<tag::long_>::type long_type;
|
||||
typedef proto::terminal<tag::int_>::type int_type;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
typedef proto::terminal<tag::ulong_long>::type ulong_long_type;
|
||||
typedef proto::terminal<tag::long_long>::type long_long_type;
|
||||
#endif
|
||||
typedef proto::terminal<tag::float_>::type float_type;
|
||||
typedef proto::terminal<tag::double_>::type double_type;
|
||||
typedef proto::terminal<tag::long_double>::type long_double_type;
|
||||
|
||||
typedef proto::terminal<tag::left_align>::type left_align_type;
|
||||
typedef proto::terminal<tag::right_align>::type right_align_type;
|
||||
typedef proto::terminal<tag::center>::type center_type;
|
||||
|
||||
typedef proto::terminal<tag::delimit>::type delimit_type;
|
||||
typedef proto::terminal<tag::verbatim>::type verbatim_type;
|
||||
|
||||
typedef proto::terminal<tag::none>::type none_type;
|
||||
typedef proto::terminal<tag::eps>::type eps_type;
|
||||
typedef proto::terminal<tag::lexeme>::type lexeme_type;
|
||||
typedef proto::terminal<tag::lazy>::type lazy_type;
|
||||
typedef proto::terminal<tag::omit>::type omitted;
|
||||
typedef proto::terminal<tag::raw>::type raw_type;
|
||||
|
||||
typedef proto::terminal<tag::stream>::type stream_type;
|
||||
typedef proto::terminal<tag::wstream>::type wstream_type;
|
||||
|
||||
typedef proto::terminal<tag::token>::type token_type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
proto::terminal<tag::char_>::type const char_ = {{}};
|
||||
proto::terminal<tag::wchar>::type const wchar = {{}};
|
||||
proto::terminal<tag::lit>::type const lit = {{}};
|
||||
proto::terminal<tag::wlit>::type const wlit = {{}};
|
||||
proto::terminal<tag::eol>::type const eol = {{}};
|
||||
proto::terminal<tag::eoi>::type const eoi = {{}};
|
||||
|
||||
proto::terminal<tag::bin>::type const bin = {{}};
|
||||
proto::terminal<tag::oct>::type const oct = {{}};
|
||||
proto::terminal<tag::hex>::type const hex = {{}};
|
||||
|
||||
proto::terminal<tag::byte>::type const byte = {{}};
|
||||
proto::terminal<tag::word>::type const word = {{}};
|
||||
proto::terminal<tag::dword>::type const dword = {{}};
|
||||
proto::terminal<tag::big_word>::type const big_word = {{}};
|
||||
proto::terminal<tag::big_dword>::type const big_dword = {{}};
|
||||
proto::terminal<tag::little_word>::type const little_word = {{}};
|
||||
proto::terminal<tag::little_dword>::type const little_dword = {{}};
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
proto::terminal<tag::qword>::type const qword = {{}};
|
||||
proto::terminal<tag::big_qword>::type const big_qword = {{}};
|
||||
proto::terminal<tag::little_qword>::type const little_qword = {{}};
|
||||
#endif
|
||||
proto::terminal<tag::pad>::type const pad = {{}};
|
||||
|
||||
proto::terminal<tag::ushort>::type const ushort = {{}};
|
||||
proto::terminal<tag::ulong>::type const ulong = {{}};
|
||||
proto::terminal<tag::uint>::type const uint = {{}};
|
||||
proto::terminal<tag::short_>::type const short_ = {{}};
|
||||
proto::terminal<tag::long_>::type const long_ = {{}};
|
||||
proto::terminal<tag::int_>::type const int_ = {{}};
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
proto::terminal<tag::ulong_long>::type const ulong_long = {{}};
|
||||
proto::terminal<tag::long_long>::type const long_long = {{}};
|
||||
#endif
|
||||
proto::terminal<tag::float_>::type const float_ = {{}};
|
||||
proto::terminal<tag::double_>::type const double_ = {{}};
|
||||
proto::terminal<tag::long_double>::type const long_double = {{}};
|
||||
|
||||
proto::terminal<tag::left_align>::type const left_align = {{}};
|
||||
proto::terminal<tag::right_align>::type const right_align = {{}};
|
||||
proto::terminal<tag::center>::type const center = {{}};
|
||||
|
||||
proto::terminal<tag::delimit>::type const delimit = {{}};
|
||||
proto::terminal<tag::verbatim>::type const verbatim = {{}};
|
||||
|
||||
proto::terminal<tag::none>::type const none = {{}};
|
||||
proto::terminal<tag::eps>::type const eps = {{}};
|
||||
proto::terminal<tag::lexeme>::type const lexeme = {{}};
|
||||
proto::terminal<tag::lazy>::type const lazy = {{}};
|
||||
proto::terminal<tag::omit>::type const omit = {{}};
|
||||
proto::terminal<tag::raw>::type const raw = {{}};
|
||||
|
||||
proto::terminal<tag::stream>::type const stream = {{}};
|
||||
proto::terminal<tag::wstream>::type const wstream = {{}};
|
||||
|
||||
proto::terminal<tag::token>::type const token = {{}};
|
||||
|
||||
// Some platforms/compilers have conflict with these terminals below
|
||||
// we'll provide variations for them with trailing underscores as
|
||||
// substitutes.
|
||||
|
||||
proto::terminal<tag::uint>::type const uint_ = {{}};
|
||||
|
||||
#if defined(__GNUC__)
|
||||
inline void silence_unused_warnings__placeholders()
|
||||
{
|
||||
(void) char_; (void) wchar; (void) lit; (void) wlit;
|
||||
(void) eol; (void) eoi;
|
||||
(void) bin; (void) oct; (void) hex;
|
||||
(void) byte; (void) word; (void) dword;
|
||||
(void) big_word; (void) big_dword;
|
||||
(void) little_word; (void) little_dword;
|
||||
(void) ushort; (void) uint; (void) ulong;
|
||||
(void) short_; (void) int_; (void) long_;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
(void) qword; (void) little_qword; (void) big_qword;
|
||||
(void) ulong_long; (void) long_long;
|
||||
#endif
|
||||
(void) pad;
|
||||
(void) float_; (void) double_; (void) long_double;
|
||||
(void) left_align; (void) right_align; (void) center;
|
||||
(void) delimit; (void) verbatim;
|
||||
(void) none; (void) eps; (void) lazy; (void) lexeme;
|
||||
(void) omit; (void) raw;
|
||||
(void) stream; (void) wstream;
|
||||
|
||||
(void) token;
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is an int tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_int_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::bin, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::oct, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::hex, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::ushort, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::ulong, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::uint, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::short_, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::long_, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::int_, Domain> : mpl::true_ {};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::ulong_long, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_tag<tag::long_long, Domain> : mpl::true_ {};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is an integer type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_int_lit_tag : is_enum<T> {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<short, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<unsigned short, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<int, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<unsigned int, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<long, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<unsigned long, Domain> : mpl::true_ {};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<boost::ulong_long_type, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_int_lit_tag<boost::long_long_type, Domain> : mpl::true_ {};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is an floating point tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_real_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_tag<tag::float_, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_tag<tag::double_, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_tag<tag::long_double, Domain> : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a floating type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_real_lit_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_lit_tag<float, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_lit_tag<double, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_real_lit_tag<long double, Domain> : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a character literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_char_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_char_tag<tag::char_, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_char_tag<tag::wchar, Domain> : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a character literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_lit_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_lit_tag<tag::lit, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_lit_tag<tag::wlit, Domain> : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a binary type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_binary_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::byte, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::word, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::dword, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::big_word, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::big_dword, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::little_word, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::little_dword, Domain> : mpl::true_ {};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::qword, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::big_qword, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_binary_tag<tag::little_qword, Domain> : mpl::true_ {};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a stream terminal
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Domain>
|
||||
struct is_stream_tag : mpl::false_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_stream_tag<tag::stream, Domain> : mpl::true_ {};
|
||||
|
||||
template <typename Domain>
|
||||
struct is_stream_tag<tag::wstream, Domain> : mpl::true_ {};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
57
libraries/include/boost/spirit/home/support/safe_bool.hpp
Normal file
57
libraries/include/boost/spirit/home/support/safe_bool.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2003 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_SAFE_BOOL_HPP)
|
||||
#define BOOST_SPIRIT_SAFE_BOOL_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
struct no_base {};
|
||||
|
||||
template <typename T>
|
||||
struct safe_bool_impl
|
||||
{
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
void stub(T*) {}
|
||||
typedef void (safe_bool_impl::*type)(T*);
|
||||
#else
|
||||
typedef T* TP; // workaround to make parsing easier
|
||||
TP stub;
|
||||
typedef TP safe_bool_impl::*type;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Derived, typename Base = detail::no_base<Derived> >
|
||||
struct safe_bool : Base
|
||||
{
|
||||
private:
|
||||
typedef detail::safe_bool_impl<Derived> impl_type;
|
||||
typedef typename impl_type::type bool_type;
|
||||
|
||||
public:
|
||||
operator bool_type() const
|
||||
{
|
||||
return static_cast<const Derived*>(this)->operator_bool() ?
|
||||
&impl_type::stub : 0;
|
||||
}
|
||||
|
||||
operator bool_type()
|
||||
{
|
||||
return static_cast<Derived*>(this)->operator_bool() ?
|
||||
&impl_type::stub : 0;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
70
libraries/include/boost/spirit/home/support/standard.hpp
Normal file
70
libraries/include/boost/spirit/home/support/standard.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(SPIRIT_STANDARD_JAN_31_2006_0529PM)
|
||||
#define SPIRIT_STANDARD_JAN_31_2006_0529PM
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace standard
|
||||
{
|
||||
typedef spirit::char_class::standard char_set;
|
||||
namespace tag = spirit::char_class::tag;
|
||||
|
||||
template <typename Class>
|
||||
struct make_tag
|
||||
: proto::terminal<spirit::char_class::key<char_set, Class> > {};
|
||||
|
||||
typedef make_tag<tag::alnum>::type alnum_type;
|
||||
typedef make_tag<tag::alpha>::type alpha_type;
|
||||
typedef make_tag<tag::blank>::type blank_type;
|
||||
typedef make_tag<tag::cntrl>::type cntrl_type;
|
||||
typedef make_tag<tag::digit>::type digit_type;
|
||||
typedef make_tag<tag::graph>::type graph_type;
|
||||
typedef make_tag<tag::print>::type print_type;
|
||||
typedef make_tag<tag::punct>::type punct_type;
|
||||
typedef make_tag<tag::space>::type space_type;
|
||||
typedef make_tag<tag::xdigit>::type xdigit_type;
|
||||
|
||||
alnum_type const alnum = {{}};
|
||||
alpha_type const alpha = {{}};
|
||||
blank_type const blank = {{}};
|
||||
cntrl_type const cntrl = {{}};
|
||||
digit_type const digit = {{}};
|
||||
graph_type const graph = {{}};
|
||||
print_type const print = {{}};
|
||||
punct_type const punct = {{}};
|
||||
space_type const space = {{}};
|
||||
xdigit_type const xdigit = {{}};
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::no_case_tag<char_set> >::type
|
||||
no_case_type;
|
||||
|
||||
no_case_type const no_case = no_case_type();
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::lower_case_tag<char_set> >::type
|
||||
lower_type;
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::upper_case_tag<char_set> >::type
|
||||
upper_type;
|
||||
|
||||
lower_type const lower = lower_type();
|
||||
upper_type const upper = upper_type();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
inline void silence_unused_warnings__standard()
|
||||
{
|
||||
(void) alnum; (void) alpha; (void) blank; (void) cntrl; (void) digit;
|
||||
(void) graph; (void) print; (void) punct; (void) space; (void) xdigit;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#if !defined(SPIRIT_STANDARD_WIDE_JAN_31_2006_0529PM)
|
||||
#define SPIRIT_STANDARD_WIDE_JAN_31_2006_0529PM
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/proto/core.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace standard_wide
|
||||
{
|
||||
typedef spirit::char_class::standard_wide char_set;
|
||||
namespace tag = spirit::char_class::tag;
|
||||
|
||||
template <typename Class>
|
||||
struct make_tag
|
||||
: proto::terminal<spirit::char_class::key<char_set, Class> > {};
|
||||
|
||||
typedef make_tag<tag::alnum>::type alnum_type;
|
||||
typedef make_tag<tag::alpha>::type alpha_type;
|
||||
typedef make_tag<tag::blank>::type blank_type;
|
||||
typedef make_tag<tag::cntrl>::type cntrl_type;
|
||||
typedef make_tag<tag::digit>::type digit_type;
|
||||
typedef make_tag<tag::graph>::type graph_type;
|
||||
typedef make_tag<tag::print>::type print_type;
|
||||
typedef make_tag<tag::punct>::type punct_type;
|
||||
typedef make_tag<tag::space>::type space_type;
|
||||
typedef make_tag<tag::xdigit>::type xdigit_type;
|
||||
|
||||
alnum_type const alnum = {{}};
|
||||
alpha_type const alpha = {{}};
|
||||
blank_type const blank = {{}};
|
||||
cntrl_type const cntrl = {{}};
|
||||
digit_type const digit = {{}};
|
||||
graph_type const graph = {{}};
|
||||
print_type const print = {{}};
|
||||
punct_type const punct = {{}};
|
||||
space_type const space = {{}};
|
||||
xdigit_type const xdigit = {{}};
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::no_case_tag<char_set> >::type
|
||||
no_case_type;
|
||||
|
||||
no_case_type const no_case = no_case_type();
|
||||
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::lower_case_tag<char_set> >::type
|
||||
lower_type;
|
||||
typedef proto::terminal<
|
||||
spirit::char_class::upper_case_tag<char_set> >::type
|
||||
upper_type;
|
||||
|
||||
lower_type const lower = lower_type();
|
||||
upper_type const upper = upper_type();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
inline void silence_unused_warnings__standard_wide()
|
||||
{
|
||||
(void) alnum; (void) alpha; (void) blank; (void) cntrl; (void) digit;
|
||||
(void) graph; (void) print; (void) punct; (void) space; (void) xdigit;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
52
libraries/include/boost/spirit/home/support/unused.hpp
Normal file
52
libraries/include/boost/spirit/home/support/unused.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_UNUSED_APR_16_2006_0616PM)
|
||||
#define BOOST_SPIRIT_UNUSED_APR_16_2006_0616PM
|
||||
|
||||
#include <boost/fusion/include/unused.hpp>
|
||||
#include <boost/fusion/include/empty.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// since boost::fusion now supports exactly what we need, unused is simply
|
||||
// imported from the fusion namespace
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
typedef boost::fusion::unused_type unused_type;
|
||||
using boost::fusion::unused;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace traits
|
||||
{
|
||||
// We use this test to detect if the argument is not a unused_type
|
||||
template <typename T>
|
||||
struct is_not_unused
|
||||
: mpl::not_<is_same<T, unused_type> >
|
||||
{};
|
||||
|
||||
// Return unused_type if Target is same as Actual, else
|
||||
// return Attribute (Attribute defaults to Actual).
|
||||
template <typename Target, typename Actual, typename Attribute = Actual>
|
||||
struct unused_if_same
|
||||
: mpl::if_<is_same<Target, Actual>, unused_type, Attribute>
|
||||
{};
|
||||
|
||||
// Return unused_type if Sequence is empty, else return Attribute.
|
||||
// (Attribute defaults to Sequence).
|
||||
template <typename Sequence, typename Attribute = Sequence>
|
||||
struct unused_if_empty
|
||||
: mpl::if_<fusion::result_of::empty<Sequence>, unused_type, Attribute>
|
||||
{};
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user