mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
adding spirit2
[SVN r44358]
This commit is contained in:
10
include/boost/spirit/home/classic.hpp
Normal file
10
include/boost/spirit/home/classic.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2008 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_CLASSIC_APRIL_11_2008_0849AM)
|
||||
#define BOOST_SPIRIT_CLASSIC_APRIL_11_2008_0849AM
|
||||
|
||||
#endif
|
||||
24
include/boost/spirit/home/karma.hpp
Normal file
24
include/boost/spirit/home/karma.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// 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(SPIRIT_KARMA_CORE_MARCH_06_2007_0833PM)
|
||||
#define SPIRIT_KARMA_CORE_MARCH_06_2007_0833PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/char.hpp>
|
||||
#include <boost/spirit/home/karma/string.hpp>
|
||||
#include <boost/spirit/home/karma/numeric.hpp>
|
||||
#include <boost/spirit/home/karma/operator.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal.hpp>
|
||||
#include <boost/spirit/home/karma/action.hpp>
|
||||
#include <boost/spirit/home/karma/directive.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary.hpp>
|
||||
#include <boost/spirit/home/karma/generate.hpp>
|
||||
#include <boost/spirit/home/karma/what.hpp>
|
||||
|
||||
#endif
|
||||
16
include/boost/spirit/home/karma/action.hpp
Normal file
16
include/boost/spirit/home/karma/action.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_KARMA_ACTION_MAR_04_2007_0912AM)
|
||||
#define BOOST_SPIRIT_KARMA_ACTION_MAR_04_2007_0912AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/action/action.hpp>
|
||||
#include <boost/spirit/home/karma/action/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
83
include/boost/spirit/home/karma/action/action.hpp
Normal file
83
include/boost/spirit/home/karma/action/action.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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_KARMA_ACTION_MAR_07_2007_0851AM)
|
||||
#define BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/values.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct action
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::left<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
result_of::left<Component>::type::director
|
||||
director;
|
||||
|
||||
typedef typename
|
||||
attribute<Component, Context, unused_type>::type
|
||||
param_type;
|
||||
|
||||
// create a parameter if one is not supplied
|
||||
// this creates a _copy_ of the parameter because the semantic
|
||||
// action likely will change parts of this
|
||||
typename mpl::if_<
|
||||
is_same<typename remove_const<Parameter>::type, unused_type>,
|
||||
param_type,
|
||||
Parameter
|
||||
>::type p = spirit::detail::make_value<param_type>::call(param);
|
||||
|
||||
// call the function, passing the parameter, the context
|
||||
// and a bool flag that the client can set to false to
|
||||
// fail parsing.
|
||||
bool pass = true;
|
||||
spirit::right(component)(
|
||||
spirit::detail::pass_value<param_type>::call(p), ctx, pass);
|
||||
|
||||
return pass &&
|
||||
director::generate(spirit::left(component), sink, ctx, d, p);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
typedef typename
|
||||
spirit::result_of::left<Component>::type::director
|
||||
director;
|
||||
return director::what(spirit::left(component));
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
70
include/boost/spirit/home/karma/action/meta_grammar.hpp
Normal file
70
include/boost/spirit/home/karma/action/meta_grammar.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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_KARMA_META_GRAMMAR_MAR_04_2007_0907AM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_MAR_04_2007_0907AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct action;
|
||||
|
||||
struct main_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// action meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct action_meta_grammar :
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, action,
|
||||
main_meta_grammar, proto::when<proto::_, proto::_arg>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, action_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, action_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<action_meta_grammar>
|
||||
{
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
16
include/boost/spirit/home/karma/auxiliary.hpp
Normal file
16
include/boost/spirit/home/karma/auxiliary.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_KARMA_AUXILIARY_MAR_26_2007_1225PM)
|
||||
#define BOOST_SPIRIT_KARMA_AUXILIARY_MAR_26_2007_1225PM
|
||||
|
||||
#include <boost/spirit/home/karma/auxiliary/none.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary/eps.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary/functor.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary/functor_director.hpp>
|
||||
#include <boost/spirit/home/karma/auxiliary/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
68
include/boost/spirit/home/karma/auxiliary/eps.hpp
Normal file
68
include/boost/spirit/home/karma/auxiliary/eps.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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_KARMA_EPS_APRIL_21_2007_0246PM)
|
||||
#define BOOST_SPIRIT_KARMA_EPS_APRIL_21_2007_0246PM
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct eps_generator
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
karma::delimit(sink, d);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "eps";
|
||||
}
|
||||
};
|
||||
|
||||
struct semantic_predicate
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
karma::delimit(sink, d);
|
||||
return fusion::at_c<0>(component.elements)(unused, ctx);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "semantic-predicate";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
213
include/boost/spirit/home/karma/auxiliary/functor.hpp
Normal file
213
include/boost/spirit/home/karma/auxiliary/functor.hpp
Normal file
@@ -0,0 +1,213 @@
|
||||
// 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_KARMA_FUNCTOR_APR_01_2007_1038AM)
|
||||
#define BOOST_SPIRIT_KARMA_FUNCTOR_APR_01_2007_1038AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/auxiliary/functor_holder.hpp>
|
||||
#include <boost/spirit/home/support/auxiliary/meta_function_holder.hpp>
|
||||
#include <boost/spirit/home/support/detail/values.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/lambda.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
namespace karma
|
||||
{
|
||||
template <typename Functor, typename ParameterMF = Functor>
|
||||
class functor_generator;
|
||||
}
|
||||
|
||||
namespace result_of
|
||||
{
|
||||
template <typename Functor>
|
||||
struct as_generator
|
||||
{
|
||||
typedef karma::functor_generator<Functor> type;
|
||||
};
|
||||
|
||||
template <typename Functor, typename ParameterMF>
|
||||
struct as_generator_mf
|
||||
{
|
||||
typedef karma::functor_generator<Functor, ParameterMF> type;
|
||||
};
|
||||
}
|
||||
|
||||
}} // boost::spirit
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This struct may be used as a base class for a user defined functor
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct functor_base
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The return value of a karma functor is always bool
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Parameter, typename OutputIterator>
|
||||
struct result
|
||||
{
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
// FIXME: It will be possible to specify the return value as a typedef, but for
|
||||
// that Phoenix will have to be fixed.
|
||||
// typedef bool result_type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The expected parameter type of a functor has to be defined using a
|
||||
// embedded apply metafunction. Normally this will be overloaded by
|
||||
// the derived class, but the default is unused type.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Context>
|
||||
struct apply
|
||||
{
|
||||
typedef spirit::unused_type type;
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The functor generator template may be used to create new generators
|
||||
// without having to dig into the implementation details of Karma
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor, typename ParameterMF>
|
||||
class functor_generator
|
||||
: public proto::extends<
|
||||
typename make_functor_holder<
|
||||
functor_generator<Functor, ParameterMF> const*,
|
||||
functor_generator<Functor, ParameterMF>
|
||||
>::type,
|
||||
functor_generator<Functor, ParameterMF>
|
||||
>
|
||||
{
|
||||
private:
|
||||
typedef functor_generator<Functor, ParameterMF> self_type;
|
||||
typedef typename
|
||||
make_functor_holder<self_type const*, self_type>::type
|
||||
functor_tag;
|
||||
typedef proto::extends<functor_tag, self_type> base_type;
|
||||
|
||||
public:
|
||||
template <typename Context>
|
||||
struct result
|
||||
: mpl::apply<ParameterMF, Context>
|
||||
{};
|
||||
|
||||
private:
|
||||
// generate function just delegates to the functor supplied function
|
||||
template <typename OutputIterator, typename Context, typename Parameter>
|
||||
bool
|
||||
generate (OutputIterator& sink, Context& ctx, Parameter const& p) const
|
||||
{
|
||||
// create an attribute if none is supplied
|
||||
typedef typename result<Context>::type parameter_type;
|
||||
typename mpl::if_<
|
||||
is_same<typename remove_const<Parameter>::type, unused_type>,
|
||||
parameter_type,
|
||||
Parameter const&
|
||||
>::type
|
||||
param = spirit::detail::make_value<parameter_type>::call(p);
|
||||
|
||||
return functor(param, ctx, sink);
|
||||
}
|
||||
|
||||
friend struct functor_director;
|
||||
|
||||
public:
|
||||
explicit functor_generator()
|
||||
: base_type(make_tag())
|
||||
{
|
||||
}
|
||||
|
||||
functor_generator(Functor const& functor_)
|
||||
: base_type(make_tag()), functor(functor_)
|
||||
{
|
||||
}
|
||||
|
||||
functor_generator(Functor const& functor_, ParameterMF const& mf)
|
||||
: base_type(make_tag()), functor(functor_), mf_(mf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
functor_tag make_tag() const
|
||||
{
|
||||
functor_tag xpr = {{ this }};
|
||||
return xpr;
|
||||
}
|
||||
|
||||
Functor functor;
|
||||
meta_function_holder<Functor, ParameterMF> mf_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The as_generator generator function may be used to create a functor
|
||||
// generator from a function object (some callable item).
|
||||
// The supplied functor needs to expose
|
||||
//
|
||||
// - an embedded result meta function:
|
||||
//
|
||||
// template <typename Parameter, typename OutputIterator>
|
||||
// struct result
|
||||
// {
|
||||
// typedef bool type;
|
||||
// };
|
||||
//
|
||||
// which declares 'bool' as the result type of the defined function
|
||||
// operator and
|
||||
//
|
||||
// - an embedded apply meta function:
|
||||
//
|
||||
// template <typename Context>
|
||||
// struct apply
|
||||
// {
|
||||
// typedef unspecified type;
|
||||
// };
|
||||
//
|
||||
// which declares the given type as the expected parameter type for
|
||||
// the generator to create.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
inline typename result_of::as_generator<Functor>::type
|
||||
as_generator(Functor const& func)
|
||||
{
|
||||
return functor_generator<Functor>(func);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The as_generator_mf generator function is equivalent to the function
|
||||
// as_generator above except that the user has explicitly to specify a
|
||||
// type exposing an embedded apply meta function declaring the expected
|
||||
// parameter type for the generator to create.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename ParameterMF, typename Functor>
|
||||
inline typename result_of::as_generator_mf<Functor, ParameterMF>::type
|
||||
as_generator_mf(Functor const& func, ParameterMF const& mf)
|
||||
{
|
||||
return functor_generator<Functor, ParameterMF>(func, mf);
|
||||
}
|
||||
|
||||
template <typename ParameterMF, typename Functor>
|
||||
inline typename result_of::as_generator_mf<Functor, ParameterMF>::type
|
||||
as_generator_mf(Functor const& func)
|
||||
{
|
||||
return functor_generator<Functor, ParameterMF>(func, ParameterMF());
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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_KARMA_FUNCTOR_DIRECTOR_APR_01_2007_1041AM)
|
||||
#define BOOST_SPIRIT_KARMA_FUNCTOR_DIRECTOR_APR_01_2007_1041AM
|
||||
|
||||
#include <boost/spirit/home/support/auxiliary/functor_holder.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
// this is the director for all functor generators
|
||||
struct functor_director
|
||||
{
|
||||
// expected value type of the generator
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type::functor_holder
|
||||
functor_holder;
|
||||
typedef typename functor_holder::functor_type functor_type;
|
||||
|
||||
typedef typename
|
||||
functor_type::template result<Context>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// generate functionality, delegates back to the corresponding functor
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
bool result = subject(component).held->generate(sink, ctx, param);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "functor";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
89
include/boost/spirit/home/karma/auxiliary/lazy.hpp
Normal file
89
include/boost/spirit/home/karma/auxiliary/lazy.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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_KARMA_LAZY_MARCH_27_2007_1231PM)
|
||||
#define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct lazy_generator
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type
|
||||
subject_type;
|
||||
|
||||
typedef typename
|
||||
remove_reference<
|
||||
typename boost::result_of<
|
||||
subject_type(unused_type, Context)
|
||||
>::type
|
||||
>::type
|
||||
expr_type;
|
||||
|
||||
typedef typename
|
||||
result_of::as_component<karma::domain, expr_type>::type
|
||||
component_type;
|
||||
|
||||
typedef typename
|
||||
traits::attribute_of<
|
||||
karma::domain, component_type, Context>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type
|
||||
subject_type;
|
||||
|
||||
typedef typename
|
||||
remove_reference<
|
||||
typename boost::result_of<
|
||||
subject_type(unused_type, Context)
|
||||
>::type
|
||||
>::type
|
||||
expr_type;
|
||||
|
||||
typedef typename
|
||||
result_of::as_component<karma::domain, expr_type>::type
|
||||
component_type;
|
||||
|
||||
component_type subject
|
||||
= spirit::as_component(
|
||||
karma::domain(),
|
||||
fusion::at_c<0>(component.elements)(unused, ctx));
|
||||
|
||||
return component_type::director::
|
||||
generate(subject, sink, ctx, d, param);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
std::string result = "lazy[";
|
||||
// FIXME: need to get at the what of the embedded component
|
||||
result += "...";
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
89
include/boost/spirit/home/karma/auxiliary/meta_grammar.hpp
Normal file
89
include/boost/spirit/home/karma/auxiliary/meta_grammar.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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_KARMA_META_GRAMMAR_MARCH_26_2007_1230PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_MARCH_26_2007_1230PM
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
template <typename T, typename Functor>
|
||||
struct functor_holder;
|
||||
}}
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct none;
|
||||
struct eps_generator;
|
||||
struct semantic_predicate;
|
||||
struct lazy_generator;
|
||||
struct functor_director;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// auxiliary generators meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// none, and lazy
|
||||
struct auxiliary_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::empty_terminal_rule<
|
||||
karma::domain, tag::none, none>,
|
||||
meta_grammar::empty_terminal_rule<
|
||||
karma::domain, tag::eps, eps_generator>,
|
||||
meta_grammar::function1_rule<
|
||||
karma::domain, tag::eps, semantic_predicate>,
|
||||
meta_grammar::function1_rule<
|
||||
karma::domain, tag::lazy, lazy_generator>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain,
|
||||
functor_holder<proto::_, proto::_>,
|
||||
functor_director
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, auxiliary_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, auxiliary_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<auxiliary_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
42
include/boost/spirit/home/karma/auxiliary/none.hpp
Normal file
42
include/boost/spirit/home/karma/auxiliary/none.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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_KARMA_NONE_MARCH_26_2007_1227PM)
|
||||
#define BOOST_SPIRIT_KARMA_NONE_MARCH_26_2007_1227PM
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct none
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "none";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
16
include/boost/spirit/home/karma/binary.hpp
Normal file
16
include/boost/spirit/home/karma/binary.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_KARMA_BINARY_MAY_04_2007_0859AM)
|
||||
#define BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0859AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/binary/binary.hpp>
|
||||
#include <boost/spirit/home/karma/binary/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
185
include/boost/spirit/home/karma/binary/binary.hpp
Normal file
185
include/boost/spirit/home/karma/binary/binary.hpp
Normal file
@@ -0,0 +1,185 @@
|
||||
// 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_KARMA_BINARY_MAY_04_2007_0904AM)
|
||||
#define BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0904AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/integer/endian.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/detail/generate_to.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <int bits>
|
||||
struct integer
|
||||
{
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
bits == 8 || bits == 16 || bits == 32 || bits == 64,
|
||||
not_supported_binary_size, ());
|
||||
#else
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
bits == 8 || bits == 16 || bits == 32,
|
||||
not_supported_binary_size, ());
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
struct integer<8>
|
||||
{
|
||||
typedef uint_least8_t type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct integer<16>
|
||||
{
|
||||
typedef uint_least16_t type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct integer<32>
|
||||
{
|
||||
typedef uint_least32_t type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <>
|
||||
struct integer<64>
|
||||
{
|
||||
typedef uint_least64_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <boost::integer::endianness bits>
|
||||
struct what;
|
||||
|
||||
template <>
|
||||
struct what<boost::integer::native>
|
||||
{
|
||||
static std::string is()
|
||||
{
|
||||
return "native-endian binary";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct what<boost::integer::little>
|
||||
{
|
||||
static char const* is()
|
||||
{
|
||||
return "little-endian binary";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct what<boost::integer::big>
|
||||
{
|
||||
static char const* is()
|
||||
{
|
||||
return "big-endian binary";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <integer::endianness endian, int bits>
|
||||
struct any_binary_director
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef boost::integer::endian<
|
||||
endian, typename karma::detail::integer<bits>::type, bits
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typename traits::attribute_of<
|
||||
karma::domain, Component, Context>::type p (param);
|
||||
unsigned char const* bytes =
|
||||
reinterpret_cast<unsigned char const*>(&p);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(p); ++i)
|
||||
detail::generate_to(sink, *bytes++);
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
// this any_byte_director has no parameter attached, it needs to have
|
||||
// been initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false,
|
||||
binary_generator_not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return karma::detail::what<endian>::is();
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <integer::endianness endian, int bits>
|
||||
struct binary_lit_director
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
boost::integer::endian<
|
||||
endian, typename karma::detail::integer<bits>::type, bits
|
||||
> p (fusion::at_c<0>(component.elements));
|
||||
|
||||
unsigned char const* bytes =
|
||||
reinterpret_cast<unsigned char const*>(&p);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(p); ++i)
|
||||
detail::generate_to(sink, *bytes++);
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return karma::detail::what<endian>::is();
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
259
include/boost/spirit/home/karma/binary/meta_grammar.hpp
Normal file
259
include/boost/spirit/home/karma/binary/meta_grammar.hpp
Normal file
@@ -0,0 +1,259 @@
|
||||
// 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_KARMA_META_GRAMMAR_MAY_04_2007_0853AM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_MAY_04_2007_0853AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/support/detail/integer/endian.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <integer::endianness endian, int bits>
|
||||
struct any_binary_director;
|
||||
|
||||
template <integer::endianness endian, int bits>
|
||||
struct binary_lit_director;
|
||||
|
||||
struct main_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of an integer based binary literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct extract_literal_bin_director
|
||||
{
|
||||
typedef binary_lit_director<
|
||||
boost::integer::native, sizeof(T)*CHAR_BIT
|
||||
> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a binary tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag>
|
||||
struct extract_binary_director;
|
||||
|
||||
// native endian binaries
|
||||
template <>
|
||||
struct extract_binary_director<tag::byte>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::native, 8> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::word>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::native, 16> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::dword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::native, 32> type;
|
||||
};
|
||||
|
||||
// big endian binaries
|
||||
template <>
|
||||
struct extract_binary_director<tag::big_word>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::big, 16> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::big_dword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::big, 32> type;
|
||||
};
|
||||
|
||||
// little endian binaries
|
||||
template <>
|
||||
struct extract_binary_director<tag::little_word>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::little, 16> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::little_dword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::little, 32> type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <>
|
||||
struct extract_binary_director<tag::qword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::native, 64> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::big_qword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::big, 64> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_binary_director<tag::little_qword>
|
||||
{
|
||||
typedef any_binary_director<boost::integer::little, 64> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a binary literal tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename T>
|
||||
struct extract_binary_lit_director;
|
||||
|
||||
// native endian binaries
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::byte, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::native, 8> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::word, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::native, 16> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::dword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::native, 32> type;
|
||||
};
|
||||
|
||||
// big endian binaries
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::big_word, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::big, 16> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::big_dword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::big, 32> type;
|
||||
};
|
||||
|
||||
// little endian binaries
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::little_word, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::little, 16> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::little_dword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::little, 32> type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::qword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::native, 64> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::big_qword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::big, 64> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_binary_lit_director<tag::little_qword, T>
|
||||
{
|
||||
typedef binary_lit_director<boost::integer::little, 64> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// binary meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// literals: 10, 10L, 10LL
|
||||
struct int_binary_meta_grammar
|
||||
: meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_int_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_literal_bin_director<mpl::_> >
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct binary_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_binary_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_binary_director<mpl::_> >
|
||||
>,
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_binary_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
int_binary_meta_grammar
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_binary_lit_director<mpl::_, mpl::_> >
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, binary_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, binary_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<binary_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
17
include/boost/spirit/home/karma/char.hpp
Normal file
17
include/boost/spirit/home/karma/char.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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_KARMA_CHAR_FEB_21_2007_0547PM)
|
||||
#define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0547PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/char/char.hpp>
|
||||
#include <boost/spirit/home/karma/char/space.hpp>
|
||||
#include <boost/spirit/home/karma/char/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
323
include/boost/spirit/home/karma/char/char.hpp
Normal file
323
include/boost/spirit/home/karma/char/char.hpp
Normal file
@@ -0,0 +1,323 @@
|
||||
// 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_KARMA_CHAR_FEB_21_2007_0543PM)
|
||||
#define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/detail/generate_to.hpp>
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/support/detail/to_narrow.hpp>
|
||||
#include <boost/spirit/home/support/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/ascii.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// any_char
|
||||
// generates a single character from the associated parameter
|
||||
//
|
||||
// Note: this generator has to have an associated parameter
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct any_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef Char type;
|
||||
};
|
||||
|
||||
// any_char has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
detail::generate_to(sink, param);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
// this any_char has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, char__not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "any-char";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// literal_char
|
||||
// generates a single character given by a literal it was initialized
|
||||
// from
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct literal_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// any_char has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
detail::generate_to(sink, fusion::at_c<0>(component.elements));
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return std::string("'")
|
||||
+ spirit::detail::to_narrow_char(
|
||||
fusion::at_c<0>(component.elements))
|
||||
+ '\'';
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lazy_char
|
||||
// generates a single character given by a functor it was initialized
|
||||
// from
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct lazy_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// any_char has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
detail::generate_to(sink,
|
||||
fusion::at_c<0>(component.elements)(unused, ctx));
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "char";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lower and upper case variants of any_char with an associated parameter
|
||||
// note: this generator has to have a parameter associated
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char, typename Tag>
|
||||
struct case_any_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef Char type;
|
||||
};
|
||||
|
||||
typedef typename Tag::char_set char_set;
|
||||
typedef typename Tag::char_class char_class_;
|
||||
|
||||
// case_any_char has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
using spirit::char_class::convert;
|
||||
Char p = convert<char_set>::to(char_class_(), param);
|
||||
detail::generate_to(sink, p);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
// this case_any_char has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, char__not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
std::string result;
|
||||
result = std::string("any-") +
|
||||
spirit::char_class::what<char_set>::is(char_class_()) +
|
||||
"case-char";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case and upper_case any_char and literal_char generators
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::literal_char<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
char_type;
|
||||
typedef fusion::vector<char_type> vector_type;
|
||||
|
||||
typedef component<
|
||||
karma::domain, karma::literal_char<Char>, vector_type>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
|
||||
char_type ch = fusion::at_c<0>(elements);
|
||||
vector_type v(char_set::tolower(ch));
|
||||
return type(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::literal_char<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
char_type;
|
||||
typedef fusion::vector<char_type> vector_type;
|
||||
|
||||
typedef
|
||||
component<karma::domain, karma::literal_char<Char>, vector_type>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
|
||||
char_type ch = fusion::at_c<0>(elements);
|
||||
vector_type v(char_set::toupper(ch));
|
||||
return type(v);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case and upper case_any_char conversions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::any_char<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef component<
|
||||
karma::domain, karma::case_any_char<Char, key_tag>, fusion::nil>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::any_char<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef component<
|
||||
karma::domain, karma::case_any_char<Char, key_tag>, fusion::nil>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
#endif // !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
|
||||
230
include/boost/spirit/home/karma/char/meta_grammar.hpp
Normal file
230
include/boost/spirit/home/karma/char/meta_grammar.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_META_GRAMMAR_FEB_21_2007_0742AM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_21_2007_0742AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a character literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename CharSet>
|
||||
struct is_char_tag<
|
||||
spirit::char_class::key<CharSet, char_class::tag::space>,
|
||||
karma::domain
|
||||
>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forward declarations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct any_char;
|
||||
|
||||
template <typename Char>
|
||||
struct literal_char;
|
||||
|
||||
struct lazy_char;
|
||||
|
||||
template <typename Tag, typename Char>
|
||||
struct any_space_char;
|
||||
|
||||
template <typename Tag, typename Char>
|
||||
struct literal_space_char;
|
||||
|
||||
struct char_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a character literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename T>
|
||||
struct extract_literal_char_director;
|
||||
|
||||
template <typename T>
|
||||
struct extract_literal_char_director<tag::char_, T>
|
||||
{
|
||||
typedef literal_char<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_literal_char_director<tag::wchar, T>
|
||||
{
|
||||
typedef literal_char<wchar_t> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_literal_char_director<tag::lit, T>
|
||||
{
|
||||
typedef literal_char<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_literal_char_director<tag::wlit, T>
|
||||
{
|
||||
typedef literal_char<wchar_t> type;
|
||||
};
|
||||
|
||||
template <typename CharSet, typename T>
|
||||
struct extract_literal_char_director<
|
||||
spirit::char_class::key<CharSet, char_class::tag::space>, T
|
||||
>
|
||||
{
|
||||
typedef
|
||||
spirit::char_class::key<CharSet, char_class::tag::space>
|
||||
key_type;
|
||||
typedef literal_space_char<key_type, T> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a plain character type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag>
|
||||
struct extract_any_char_director;
|
||||
|
||||
template <>
|
||||
struct extract_any_char_director<tag::char_>
|
||||
{
|
||||
typedef any_char<char> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_any_char_director<tag::wchar>
|
||||
{
|
||||
typedef any_char<wchar_t> type;
|
||||
};
|
||||
|
||||
template <typename CharSet>
|
||||
struct extract_any_char_director<
|
||||
spirit::char_class::key<CharSet, char_class::tag::space>
|
||||
>
|
||||
{
|
||||
typedef typename CharSet::char_type char_type;
|
||||
typedef
|
||||
spirit::char_class::key<CharSet, char_class::tag::space>
|
||||
key_type;
|
||||
typedef any_space_char<key_type, char_type> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// char generator meta-grammars
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// literals: 'x', L'x'
|
||||
struct char_literal_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, char, literal_char<char>
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, wchar_t, literal_char<wchar_t>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// literals: 'x', L'x'
|
||||
struct basic_char_literal_meta_grammar
|
||||
: proto::or_<
|
||||
proto::terminal<char>,
|
||||
proto::terminal<wchar_t>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// char_, wchar, space
|
||||
// char_('x'), char_(L'x'), wchar('x'), wchar(L'x'), space(' ')
|
||||
struct char_meta_grammar1
|
||||
: proto::or_<
|
||||
// char_, wchar, space
|
||||
meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_char_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_any_char_director<mpl::_> >
|
||||
>,
|
||||
// char_('x'), wchar(L'x'), space(' ')
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_char_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
basic_char_literal_meta_grammar
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_literal_char_director<mpl::_, mpl::_> >
|
||||
>,
|
||||
// lit('x'), wlit('x')
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
basic_char_literal_meta_grammar
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_literal_char_director<mpl::_, mpl::_> >
|
||||
>,
|
||||
// char_(val('y'))
|
||||
meta_grammar::function1_rule<
|
||||
karma::domain, tag::char_, lazy_char
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// main char_meta_grammar
|
||||
struct char_meta_grammar
|
||||
: proto::or_<
|
||||
char_literal_meta_grammar,
|
||||
char_meta_grammar1
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hook into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<Expr,
|
||||
typename enable_if<proto::matches<Expr, char_meta_grammar> >::type>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<Expr,
|
||||
typename enable_if<proto::matches<Expr, char_meta_grammar> >::type>
|
||||
: mpl::identity<char_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
116
include/boost/spirit/home/karma/char/space.hpp
Normal file
116
include/boost/spirit/home/karma/char/space.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// 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_KARMA_SPACE_MAR_06_2007_0934PM)
|
||||
#define BOOST_SPIRIT_KARMA_SPACE_MAR_06_2007_0934PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/detail/generate_to.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/support/detail/to_narrow.hpp>
|
||||
#include <boost/spirit/home/support/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/ascii.hpp>
|
||||
#include <boost/spirit/home/support/standard.hpp>
|
||||
#include <boost/spirit/home/support/standard_wide.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// space
|
||||
// generates a single character from the associated parameter
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename Char>
|
||||
struct any_space_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef Char type;
|
||||
};
|
||||
|
||||
typedef typename Tag::char_set char_set;
|
||||
typedef typename Tag::char_class char_class_;
|
||||
|
||||
// space has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& ch)
|
||||
{
|
||||
using spirit::char_class::classify;
|
||||
BOOST_ASSERT(classify<char_set>::is(char_class_(), ch));
|
||||
detail::generate_to(sink, ch);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
// this space has no parameter attached, just generate a single ' '
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator& sink, Context&,
|
||||
Delimiter const& d, unused_type)
|
||||
{
|
||||
detail::generate_to(sink, ' '); // generate a single space
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "any-space";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// space(...)
|
||||
// generates a single space character given by a literal it was
|
||||
// initialized from
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename Char>
|
||||
struct literal_space_char
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// any_char has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
detail::generate_to(sink, fusion::at_c<0>(component.elements));
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return std::string("space('")
|
||||
+ spirit::detail::to_narrow_char(
|
||||
fusion::at_c<0>(component.elements))
|
||||
+ "')";
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif // !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
|
||||
35
include/boost/spirit/home/karma/delimit.hpp
Normal file
35
include/boost/spirit/home/karma/delimit.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_KARMA_DELIMIT_FEB_20_2007_1208PM)
|
||||
#define BOOST_SPIRIT_KARMA_DELIMIT_FEB_20_2007_1208PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Do delimiting. This is equivalent to p << d. The function is a
|
||||
// no-op if spirit::unused is passed as the delimiter-generator.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Delimiter>
|
||||
inline void delimit(OutputIterator& sink, Delimiter const& d)
|
||||
{
|
||||
Delimiter::director::generate(d, sink, unused, unused, unused);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
inline void delimit(OutputIterator&, unused_type)
|
||||
{
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
58
include/boost/spirit/home/karma/detail/generate_to.hpp
Normal file
58
include/boost/spirit/home/karma/detail/generate_to.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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_KARMA_DETAIL_EXTRACT_FROM_FEB_20_2007_0417PM)
|
||||
#define BOOST_SPIRIT_KARMA_DETAIL_EXTRACT_FROM_FEB_20_2007_0417PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These utility functions insert the given parameter into the supplied
|
||||
// output iterator.
|
||||
// If the parameter is spirit's unused_type, this is a no_op.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Parameter, typename Tag>
|
||||
inline bool
|
||||
generate_to(OutputIterator& sink, Parameter const& p, Tag)
|
||||
{
|
||||
typedef typename Tag::char_set char_set;
|
||||
typedef typename Tag::char_class char_class;
|
||||
|
||||
*sink = spirit::char_class::convert<char_set>::to(char_class(), p);
|
||||
++sink;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Parameter>
|
||||
inline bool
|
||||
generate_to(OutputIterator& sink, Parameter const& p, unused_type = unused)
|
||||
{
|
||||
*sink = p;
|
||||
++sink;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Tag>
|
||||
inline bool generate_to(OutputIterator& sink, unused_type, Tag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
inline bool generate_to(OutputIterator& sink, unused_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}} // namespace boost::spirit::karma::detail
|
||||
|
||||
#endif // KARMA_CORE_DETAIL_INSERT_TO_HPP
|
||||
57
include/boost/spirit/home/karma/detail/ostream_iterator.hpp
Normal file
57
include/boost/spirit/home/karma/detail/ostream_iterator.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// 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_KARMA_OSTREAM_ITERATOR_MAY_26_2007_1016PM)
|
||||
#define BOOST_SPIRIT_KARMA_OSTREAM_ITERATOR_MAY_26_2007_1016PM
|
||||
|
||||
#include <iterator>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// We need our own implementation of an ostream_iterator just to be able
|
||||
// to access the wrapped ostream, which is necessary for the
|
||||
// stream_director, where we must generate the output using the original
|
||||
// ostream to retain possibly registered facets.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename T, typename Elem = char,
|
||||
typename Traits = std::char_traits<Elem>
|
||||
>
|
||||
class ostream_iterator
|
||||
: public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
public:
|
||||
typedef Elem char_type;
|
||||
typedef Traits traits_type;
|
||||
typedef std::basic_ostream<Elem, Traits> ostream_type;
|
||||
typedef ostream_iterator<T, Elem, Traits> self_type;
|
||||
|
||||
ostream_iterator(ostream_type& os_, Elem const* delim_ = 0)
|
||||
: os(&os_), delim(delim_) {}
|
||||
|
||||
self_type& operator= (T const& val)
|
||||
{
|
||||
*os << val;
|
||||
if (0 != delim)
|
||||
*os << delim;
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_type& operator*() { return *this; }
|
||||
self_type& operator++() { return *this; }
|
||||
self_type operator++(int) { return *this; }
|
||||
|
||||
ostream_type& get_ostream() { return *os; }
|
||||
|
||||
protected:
|
||||
ostream_type *os;
|
||||
Elem const* delim;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
340
include/boost/spirit/home/karma/detail/output_iterator.hpp
Normal file
340
include/boost/spirit/home/karma/detail/output_iterator.hpp
Normal file
@@ -0,0 +1,340 @@
|
||||
// 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_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM)
|
||||
#define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/spirit/home/karma/detail/ostream_iterator.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This class is used to count the umber of characters streamed into the
|
||||
// output.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class counting_sink
|
||||
{
|
||||
public:
|
||||
counting_sink() : count(0) {}
|
||||
|
||||
void init(std::size_t count_) { count = count_; }
|
||||
void tidy() { count = 0; }
|
||||
|
||||
void output() { ++count; }
|
||||
std::size_t get_count() const { return count; }
|
||||
|
||||
private:
|
||||
std::size_t count;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The following classes are used to intercept the output into a buffer
|
||||
// allowing to do things like alignment, character escaping etc.
|
||||
//
|
||||
// We need to use virtual functions because output_iterators do not have
|
||||
// an associated value_type. The type of the buffer elements is available
|
||||
// at insertion time only (and not at buffer creation time).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
struct abstract_container
|
||||
{
|
||||
virtual ~abstract_container() {}
|
||||
virtual void output(void const *item) = 0;
|
||||
virtual void copy(OutputIterator& sink) = 0;
|
||||
virtual std::size_t buffer_size() = 0;
|
||||
};
|
||||
|
||||
template <typename OutputIterator, typename T>
|
||||
class concrete_container : public abstract_container<OutputIterator>
|
||||
{
|
||||
public:
|
||||
concrete_container(std::size_t size)
|
||||
{
|
||||
buffer.reserve(size);
|
||||
}
|
||||
~concrete_container() {}
|
||||
|
||||
void output(void const *item)
|
||||
{
|
||||
buffer.push_back(*static_cast<T const*>(item));
|
||||
}
|
||||
void copy(OutputIterator& sink)
|
||||
{
|
||||
std::copy(buffer.begin(), buffer.end(), sink);
|
||||
}
|
||||
std::size_t buffer_size()
|
||||
{
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> buffer;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
class buffer_sink
|
||||
{
|
||||
public:
|
||||
buffer_sink()
|
||||
: width(0), buffer(0)
|
||||
{}
|
||||
|
||||
~buffer_sink()
|
||||
{
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void init(std::size_t width_) { width = width_; }
|
||||
void tidy() { delete buffer; buffer = 0; width = 0; }
|
||||
|
||||
template <typename T>
|
||||
void output(T const& value)
|
||||
{
|
||||
if (0 == buffer)
|
||||
{
|
||||
typedef concrete_container<OutputIterator, T> container;
|
||||
buffer = new container(width);
|
||||
}
|
||||
buffer->output(&value);
|
||||
}
|
||||
|
||||
void copy(OutputIterator& sink) const
|
||||
{
|
||||
if (buffer)
|
||||
buffer->copy(sink);
|
||||
}
|
||||
|
||||
std::size_t buffer_size() const
|
||||
{
|
||||
return buffer ? buffer->buffer_size() : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t width;
|
||||
abstract_container<OutputIterator> *buffer;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forward declaration only
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator> struct enable_counting;
|
||||
template <typename OutputIterator> struct enable_buffering;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Karma uses a output iterator wrapper for all output operations. This
|
||||
// is necessary to avoid the dreaded 'scanner business' problem, i.e. the
|
||||
// dependency of rules and grammars on the used output iterator.
|
||||
//
|
||||
// By default the user supplied output iterator is wrapped inside an
|
||||
// instance of this internal output_iterator class.
|
||||
//
|
||||
// This output_iterator class normally just forwards to the embedded user
|
||||
// supplied iterator. But it is possible to enable additional functionality
|
||||
// on demand, such as counting, buffering, and position tracking.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Enable = void>
|
||||
class output_iterator
|
||||
{
|
||||
private:
|
||||
enum output_mode
|
||||
{
|
||||
output_characters = 0, // just hand through character
|
||||
count_characters = 1, // additionally count characters
|
||||
buffer_characters = 2 // buffer all characters, no output
|
||||
};
|
||||
|
||||
struct output_proxy
|
||||
{
|
||||
output_proxy(output_iterator& parent)
|
||||
: parent(parent)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
output_proxy& operator=(T const& value)
|
||||
{
|
||||
parent.output(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
output_iterator& parent;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
private:
|
||||
friend struct enable_counting<output_iterator>;
|
||||
friend struct enable_buffering<output_iterator>;
|
||||
#else
|
||||
public:
|
||||
#endif
|
||||
// functions related to counting
|
||||
void enable_counting(std::size_t count = 0)
|
||||
{
|
||||
count_data.init(count);
|
||||
mode = output_mode(mode | count_characters);
|
||||
}
|
||||
void disable_counting()
|
||||
{
|
||||
mode = output_mode(mode & ~count_characters);
|
||||
}
|
||||
void reset_counting()
|
||||
{
|
||||
count_data.tidy();
|
||||
}
|
||||
|
||||
// functions related to buffering
|
||||
void enable_buffering(std::size_t width = 0)
|
||||
{
|
||||
buffer_data.init(width);
|
||||
mode = output_mode(mode | buffer_characters);
|
||||
}
|
||||
void disable_buffering()
|
||||
{
|
||||
mode = output_mode(mode & ~buffer_characters);
|
||||
}
|
||||
void reset_buffering()
|
||||
{
|
||||
buffer_data.tidy();
|
||||
}
|
||||
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
output_iterator(OutputIterator& sink_)
|
||||
: sink(sink_), mode(output_characters)
|
||||
{}
|
||||
|
||||
output_proxy operator*() { return output_proxy(*this); }
|
||||
output_iterator& operator++() { ++sink; return *this; }
|
||||
output_iterator& operator++(int) { sink++; return *this; }
|
||||
|
||||
template <typename T>
|
||||
void output(T const& value)
|
||||
{
|
||||
if (mode & count_characters) // count characters, if appropriate
|
||||
count_data.output();
|
||||
|
||||
if (mode & buffer_characters) // buffer output, if appropriate
|
||||
buffer_data.output(value);
|
||||
else
|
||||
*sink = value;
|
||||
}
|
||||
|
||||
// functions related to counting
|
||||
std::size_t count() const
|
||||
{
|
||||
return count_data.get_count();
|
||||
}
|
||||
|
||||
// functions related to buffering
|
||||
std::size_t buffer_size() const
|
||||
{
|
||||
return buffer_data.buffer_size();
|
||||
}
|
||||
void buffer_copy()
|
||||
{
|
||||
buffer_data.copy(sink);
|
||||
}
|
||||
|
||||
protected:
|
||||
// this is the wrapped user supplied output iterator
|
||||
OutputIterator& sink;
|
||||
|
||||
private:
|
||||
// these are the hooks providing optional functionality
|
||||
counting_sink count_data; // for counting
|
||||
buffer_sink<OutputIterator> buffer_data; // for buffering
|
||||
output_mode mode;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Elem, typename Traits>
|
||||
class output_iterator<ostream_iterator<T, Elem, Traits> >
|
||||
: public output_iterator<ostream_iterator<T, Elem, Traits>, int>
|
||||
{
|
||||
private:
|
||||
typedef
|
||||
output_iterator<ostream_iterator<T, Elem, Traits>, int>
|
||||
base_type;
|
||||
typedef ostream_iterator<T, Elem, Traits> base_iterator_type;
|
||||
typedef std::basic_ostream<Elem, Traits> ostream_type;
|
||||
|
||||
public:
|
||||
output_iterator(base_iterator_type& sink)
|
||||
: base_type(sink)
|
||||
{}
|
||||
|
||||
ostream_type& get_ostream() { return this->sink.get_ostream(); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Helper class for exception safe enabling of character counting in the
|
||||
// output iterator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
struct enable_counting
|
||||
{
|
||||
enable_counting(OutputIterator& sink_, std::size_t count = 0)
|
||||
: sink(sink_)
|
||||
{
|
||||
sink.enable_counting(count);
|
||||
}
|
||||
~enable_counting()
|
||||
{
|
||||
sink.disable_counting();
|
||||
sink.reset_counting();
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
sink.disable_counting();
|
||||
}
|
||||
|
||||
OutputIterator& sink;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Helper class for exception safe enabling of character buffering in the
|
||||
// output iterator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
struct enable_buffering
|
||||
{
|
||||
enable_buffering(OutputIterator& sink_, std::size_t width = 0)
|
||||
: sink(sink_)
|
||||
{
|
||||
sink.enable_buffering(width);
|
||||
}
|
||||
~enable_buffering()
|
||||
{
|
||||
sink.disable_buffering();
|
||||
sink.reset_buffering();
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
sink.disable_buffering();
|
||||
}
|
||||
|
||||
OutputIterator& sink;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
85
include/boost/spirit/home/karma/detail/string_generate.hpp
Normal file
85
include/boost/spirit/home/karma/detail/string_generate.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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_KARMA_STRING_GENERATE_FEB_23_2007_1232PM)
|
||||
#define BOOST_SPIRIT_KARMA_STRING_GENERATE_FEB_23_2007_1232PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <boost/spirit/home/karma/detail/generate_to.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate a string given by a pointer
|
||||
template <typename OutputIterator, typename Char>
|
||||
inline bool
|
||||
string_generate(OutputIterator& sink, Char const* str, unused_type = unused)
|
||||
{
|
||||
Char ch;
|
||||
for (/**/; !!(ch = *str); ++str)
|
||||
detail::generate_to(sink, ch);
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate a string given by a std::string
|
||||
template <typename OutputIterator, typename Char>
|
||||
inline bool
|
||||
string_generate(OutputIterator& sink, std::basic_string<Char> const& str,
|
||||
unused_type = unused)
|
||||
{
|
||||
typedef std::basic_string<Char> string_type;
|
||||
|
||||
typename string_type::const_iterator end = str.end();
|
||||
for (typename string_type::const_iterator it = str.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
detail::generate_to(sink, *it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate a string given by a pointer, converting according using a
|
||||
// given character class tag
|
||||
template <typename OutputIterator, typename Char, typename Tag>
|
||||
inline bool
|
||||
string_generate(OutputIterator& sink, Char const* str, Tag tag)
|
||||
{
|
||||
Char ch;
|
||||
for (/**/; !!(ch = *str); ++str)
|
||||
{
|
||||
detail::generate_to(sink, ch, tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate a string given by a std::string, converting according using a
|
||||
// given character class tag
|
||||
template <typename OutputIterator, typename Char, typename Tag>
|
||||
inline bool
|
||||
string_generate(OutputIterator& sink, std::basic_string<Char> const& str,
|
||||
Tag tag)
|
||||
{
|
||||
typedef std::basic_string<Char> string_type;
|
||||
|
||||
typename string_type::const_iterator end = str.end();
|
||||
for (typename string_type::const_iterator it = str.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
detail::generate_to(sink, *it, tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
36
include/boost/spirit/home/karma/directive.hpp
Normal file
36
include/boost/spirit/home/karma/directive.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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_KARMA_DIRECTIVE_FEB_21_2007_0833PM)
|
||||
#define BOOST_SPIRIT_KARMA_DIRECTIVE_FEB_21_2007_0833PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// directives related to alignment
|
||||
// left_align[...], right_align[...], center[...]
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/spirit/home/karma/directive/left_alignment.hpp>
|
||||
#include <boost/spirit/home/karma/directive/right_alignment.hpp>
|
||||
#include <boost/spirit/home/karma/directive/center_alignment.hpp>
|
||||
#include <boost/spirit/home/karma/directive/alignment_meta_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// directives related to character case
|
||||
// lower[...] and upper[...]
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/spirit/home/karma/directive/case_meta_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// directives related to delimiting generators
|
||||
// delimit[...] and verbatim[...]
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/spirit/home/karma/directive/verbatim.hpp>
|
||||
#include <boost/spirit/home/karma/directive/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/directive/delimiter_meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
// 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_KARMA_ALIGNMENT_META_GRAMMAR_FEB_21_2007_0826PM)
|
||||
#define BOOST_SPIRIT_KARMA_ALIGNMENT_META_GRAMMAR_FEB_21_2007_0826PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct main_meta_grammar;
|
||||
|
||||
struct simple_left_aligment;
|
||||
struct simple_right_aligment;
|
||||
struct simple_center_aligment;
|
||||
|
||||
struct width_left_aligment;
|
||||
struct width_right_aligment;
|
||||
struct width_center_aligment;
|
||||
|
||||
struct padding_left_aligment;
|
||||
struct padding_right_aligment;
|
||||
struct padding_center_aligment;
|
||||
|
||||
struct full_left_aligment;
|
||||
struct full_right_aligment;
|
||||
struct full_center_aligment;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// left, right and center directive meta-grammars
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct simple_align_directive_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, simple_left_aligment,
|
||||
proto::terminal<tag::left_align>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, simple_right_aligment,
|
||||
proto::terminal<tag::right_align>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, simple_center_aligment,
|
||||
proto::terminal<tag::center>, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// matches alignment directives defining the width only:
|
||||
// left_align(width)[...], right_align(width)[...], center(width)[...]
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct width_align_directive_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::left_align, width_left_aligment,
|
||||
proto::terminal<int>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::right_align, width_right_aligment,
|
||||
proto::terminal<int>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::center, width_center_aligment,
|
||||
proto::terminal<int>, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// matches alignment directives defining the padding generator only:
|
||||
// left_align(padding)[...], right_align(padding)[...], center(padding)[...]
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct padding_align_directive_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::left_align, padding_left_aligment,
|
||||
main_meta_grammar, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::right_align, padding_right_aligment,
|
||||
main_meta_grammar, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::center, padding_center_aligment,
|
||||
main_meta_grammar, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// matches full alignment directives: left_align(width, padding)[...],
|
||||
// right_align(width, padding)[...], center(width, padding)[...]
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct full_align_directive_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::subscript_function2_rule<
|
||||
karma::domain, tag::left_align, full_left_aligment,
|
||||
proto::terminal<int>, main_meta_grammar, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function2_rule<
|
||||
karma::domain, tag::right_align, full_right_aligment,
|
||||
proto::terminal<int>, main_meta_grammar, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function2_rule<
|
||||
karma::domain, tag::center, full_center_aligment,
|
||||
proto::terminal<int>, main_meta_grammar, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
// main alignment_directive_meta_grammar
|
||||
struct alignment_directive_meta_grammar
|
||||
: proto::or_<
|
||||
simple_align_directive_meta_grammar,
|
||||
width_align_directive_meta_grammar,
|
||||
padding_align_directive_meta_grammar,
|
||||
full_align_directive_meta_grammar
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, alignment_directive_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, alignment_directive_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<alignment_directive_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
133
include/boost/spirit/home/karma/directive/case_meta_grammar.hpp
Normal file
133
include/boost/spirit/home/karma/directive/case_meta_grammar.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// 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_KARMA_CASE_META_GRAMMAR_FEB_21_2007_0826PM)
|
||||
#define BOOST_SPIRIT_KARMA_CASE_META_GRAMMAR_FEB_21_2007_0826PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/ascii.hpp>
|
||||
#include <boost/spirit/home/support/standard.hpp>
|
||||
#include <boost/spirit/home/support/standard_wide.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct main_meta_grammar;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower and upper directive meta-grammars
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct lower_case_directive_meta_grammar
|
||||
: meta_grammar::deep_directive_meta_grammar<
|
||||
spirit::char_class::lower_case_tag<proto::_>,
|
||||
main_meta_grammar
|
||||
>
|
||||
{};
|
||||
|
||||
struct upper_case_directive_meta_grammar
|
||||
: meta_grammar::deep_directive_meta_grammar<
|
||||
spirit::char_class::upper_case_tag<proto::_>,
|
||||
main_meta_grammar
|
||||
>
|
||||
{};
|
||||
|
||||
// main directive_meta_grammar
|
||||
struct directive_meta_grammar
|
||||
: proto::or_<
|
||||
lower_case_directive_meta_grammar,
|
||||
upper_case_directive_meta_grammar
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<Expr,
|
||||
typename enable_if<proto::matches<Expr, directive_meta_grammar> >::type>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<Expr,
|
||||
typename enable_if<proto::matches<Expr, directive_meta_grammar> >::type>
|
||||
: mpl::identity<directive_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The following specializations for the add_modifier template are added
|
||||
// to allow for special handling of the lower[] and upper[] directives
|
||||
// which are mutually exclusive. Since the first of these directives
|
||||
// added to the modifier corresponds to the outermost one in the generator
|
||||
// expression, we just ignore the request to add a tag if one of the two
|
||||
// has been already added.
|
||||
template <typename Modifier, typename Tag>
|
||||
struct add_modifier<Modifier, spirit::char_class::lower_case_tag<Tag> >
|
||||
{
|
||||
// add the new tag to the modifier (if it isn't already)
|
||||
typedef spirit::char_class::upper_case_tag<Tag> reciprocal_tag;
|
||||
typedef spirit::char_class::lower_case_tag<Tag> tag;
|
||||
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
mpl::or_<
|
||||
is_member_of_modifier<Modifier, reciprocal_tag>,
|
||||
is_member_of_modifier<Modifier, tag>
|
||||
>,
|
||||
Modifier,
|
||||
modifier<Modifier, tag>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Modifier, typename Tag>
|
||||
struct add_modifier<Modifier, spirit::char_class::upper_case_tag<Tag> >
|
||||
{
|
||||
// add the new tag to the modifier (if it isn't already)
|
||||
typedef spirit::char_class::lower_case_tag<Tag> reciprocal_tag;
|
||||
typedef spirit::char_class::upper_case_tag<Tag> tag;
|
||||
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
mpl::or_<
|
||||
is_member_of_modifier<Modifier, reciprocal_tag>,
|
||||
is_member_of_modifier<Modifier, tag>
|
||||
>,
|
||||
Modifier,
|
||||
modifier<Modifier, tag>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
231
include/boost/spirit/home/karma/directive/center_alignment.hpp
Normal file
231
include/boost/spirit/home/karma/directive/center_alignment.hpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// 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_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/directive/detail/center_alignment_generate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The BOOST_KARMA_DEFAULT_FIELD_LENGTH specifies the default field length
|
||||
// to be used for padding.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(BOOST_KARMA_DEFAULT_FIELD_LENGTH)
|
||||
#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 10
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The simple center alignment directive is used for center[...]
|
||||
// generators. It uses default values for the generated width (defined via
|
||||
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct simple_center_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::argument1<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::center_generate(sink, ctx, d, param,
|
||||
argument1(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH,
|
||||
spirit::as_component(karma::domain(), ' '));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "center[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::argument1(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The center alignment with width directive, is used for generators
|
||||
// like center(width)[...]. It uses a default value for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct width_center_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::center_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)), ' ');
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "center(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The center alignment directive with padding, is used for generators like
|
||||
// center(padding)[...], where padding is a arbitrary generator
|
||||
// expression. It uses a default value for the generated width (defined
|
||||
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct padding_center_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::center_generate(sink, ctx, d, param,
|
||||
subject(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH,
|
||||
argument1(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "center(";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument1(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The full center alignment directive, is used for generators like
|
||||
// center(width, padding)[...], where width is a integer value to be
|
||||
// used as the field width and padding is a arbitrary generator
|
||||
// expression.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct full_center_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::center_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)),
|
||||
argument2(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "center(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ", ";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument2<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument2(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
126
include/boost/spirit/home/karma/directive/delimit.hpp
Normal file
126
include/boost/spirit/home/karma/directive/delimit.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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_KARMA_DELIMIT_MAR_02_2007_0217PM)
|
||||
#define BOOST_SPIRIT_KARMA_DELIMIT_MAR_02_2007_0217PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The delimit_space generator is used for delimit[...] directives.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct delimit_space
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::right<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& /*d*/, Parameter const& param)
|
||||
{
|
||||
// the delimit_space generator simply dispatches to the embedded
|
||||
// generator while supplying a single space as the new delimiter
|
||||
// to use
|
||||
typedef typename
|
||||
result_of::right<Component>::type::director
|
||||
director;
|
||||
|
||||
return director::generate(spirit::right(component),
|
||||
sink, ctx, spirit::as_component(karma::domain(), ' '), param);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "delimit[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::right<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::right(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The delimit_ generator is used for delimit(d)[...] directives.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct delimit_
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& /*d*/, Parameter const& param)
|
||||
{
|
||||
// the delimit generator simply dispatches to the embedded
|
||||
// generator while supplying it's argument as the new delimiter
|
||||
// to use
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
return director::generate(spirit::subject(component), sink, ctx,
|
||||
spirit::as_component(
|
||||
karma::domain(), spirit::argument1(component)),
|
||||
param);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "delimit(";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
delimiter;
|
||||
|
||||
result += delimiter::what(spirit::argument1(component));
|
||||
result +=")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#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_KARMA_DELIMITER_META_GRAMMAR_FEB_21_2007_0826PM)
|
||||
#define BOOST_SPIRIT_KARMA_DELIMITER_META_GRAMMAR_FEB_21_2007_0826PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct main_meta_grammar;
|
||||
|
||||
struct delimit_;
|
||||
struct delimit_space;
|
||||
struct verbatim;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// delimit and verbatim directive meta-grammars
|
||||
// delimit[...], delimit(delimiter)[...] and verbatim[...]
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct delimiter_directive_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, verbatim,
|
||||
proto::terminal<tag::verbatim>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::subscript, delimit_space,
|
||||
proto::terminal<tag::delimit>, main_meta_grammar
|
||||
>,
|
||||
meta_grammar::subscript_function1_rule<
|
||||
karma::domain, tag::delimit, delimit_,
|
||||
main_meta_grammar, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hook into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, delimiter_directive_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, delimiter_directive_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<delimiter_directive_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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_KARMA_CENTER_ALIGNMENT_GENERATE_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_GENERATE_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The center_generate template function is used for all the different
|
||||
// flavors of the center[] directive.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Context, typename Delimiter,
|
||||
typename Parameter, typename Embedded, typename Padding>
|
||||
inline static bool
|
||||
center_generate(OutputIterator& sink, Context& ctx,
|
||||
Delimiter const& d, Parameter const& param, Embedded const& e,
|
||||
unsigned int const width, Padding const& p)
|
||||
{
|
||||
// make sure all generator parameters are valid
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Embedded>::value),
|
||||
embedded_is_not_convertible_to_a_generator, (Context, Embedded));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Padding>::value),
|
||||
padding_is_not_convertible_to_a_generator, (Context, Padding));
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Embedded>::type
|
||||
embedded;
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Padding>::type
|
||||
padding;
|
||||
|
||||
// wrap the given output iterator to allow left padding
|
||||
detail::enable_buffering<OutputIterator> buffering(sink, width);
|
||||
|
||||
// first generate the embedded output
|
||||
embedded ec = spirit::as_component(karma::domain(), e);
|
||||
typedef typename embedded::director director;
|
||||
bool r = director::generate(ec, sink, ctx, d, param);
|
||||
|
||||
buffering.disable(); // do not perform buffering any more
|
||||
|
||||
// generate the left padding
|
||||
detail::enable_counting<OutputIterator>
|
||||
counting(sink, (sink.buffer_size() + width) / 2);
|
||||
|
||||
padding pc = spirit::as_component(karma::domain(), p);
|
||||
typedef typename padding::director padding_director;
|
||||
while (r && sink.count() < width)
|
||||
r = padding_director::generate(pc, sink, ctx, unused, unused);
|
||||
|
||||
if (r) {
|
||||
// copy the embedded output to the target output iterator
|
||||
sink.buffer_copy();
|
||||
|
||||
// generate the right padding
|
||||
std::size_t const max_count = width + (width - sink.buffer_size()) / 2;
|
||||
while (r && sink.count() < max_count)
|
||||
r = padding_director::generate(pc, sink, ctx, unused, unused);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}}}} // namespace boost::spirit::karma::detail
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// 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_KARMA_LEFT_ALIGNMENT_GENERATE_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_LEFT_ALIGNMENT_GENERATE_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The left_align_generate template function is used for all the different
|
||||
// flavors of the left_align[] directive.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Context, typename Delimiter,
|
||||
typename Parameter, typename Embedded, typename Padding>
|
||||
inline static bool
|
||||
left_align_generate(OutputIterator& sink, Context& ctx,
|
||||
Delimiter const& d, Parameter const& param, Embedded const& e,
|
||||
unsigned int const width, Padding const& p)
|
||||
{
|
||||
// make sure all generator parameters are valid
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Embedded>::value),
|
||||
embedded_is_not_convertible_to_a_generator, (Context, Embedded));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Padding>::value),
|
||||
padding_is_not_convertible_to_a_generator, (Context, Padding));
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Embedded>::type
|
||||
embedded;
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Padding>::type
|
||||
padding;
|
||||
|
||||
// wrap the given output iterator to allow counting
|
||||
detail::enable_counting<OutputIterator> counting(sink);
|
||||
|
||||
// first generate the underlying output
|
||||
embedded ec = spirit::as_component(karma::domain(), e);
|
||||
typedef typename embedded::director director;
|
||||
bool r = director::generate(ec, sink, ctx, d, param);
|
||||
|
||||
// pad the output until the max width is reached
|
||||
padding pc = spirit::as_component(karma::domain(), p);
|
||||
while(r && sink.count() < width) {
|
||||
typedef typename padding::director padding_director;
|
||||
r = padding_director::generate(pc, sink, ctx, unused, unused);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}}}} // namespace boost::spirit::karma::detail
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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_KARMA_RIGHT_ALIGNMENT_GENERATE_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_RIGHT_ALIGNMENT_GENERATE_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The right_align_generate template function is used for all the
|
||||
// different flavors of the right_align[] directive.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Context, typename Delimiter,
|
||||
typename Parameter, typename Embedded, typename Padding>
|
||||
inline static bool
|
||||
right_align_generate(OutputIterator& sink, Context& ctx,
|
||||
Delimiter const& d, Parameter const& param, Embedded const& e,
|
||||
unsigned int const width, Padding const& p)
|
||||
{
|
||||
// make sure all generator parameters are valid
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Embedded>::value),
|
||||
embedded_is_not_convertible_to_a_generator, (Context, Embedded));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(spirit::traits::is_component<karma::domain, Padding>::value),
|
||||
padding_is_not_convertible_to_a_generator, (Context, Padding));
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Embedded>::type
|
||||
embedded;
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Padding>::type
|
||||
padding;
|
||||
|
||||
// wrap the given output iterator to allow left padding
|
||||
detail::enable_buffering<OutputIterator> buffering(sink, width);
|
||||
|
||||
// first generate the embedded output
|
||||
embedded ec = spirit::as_component(karma::domain(), e);
|
||||
typedef typename embedded::director director;
|
||||
bool r = director::generate(ec, sink, ctx, d, param);
|
||||
|
||||
buffering.disable(); // do not perform buffering any more
|
||||
|
||||
// generate the left padding
|
||||
detail::enable_counting<OutputIterator> counting(sink, sink.buffer_size());
|
||||
|
||||
padding pc = spirit::as_component(karma::domain(), p);
|
||||
while(r && sink.count() < width) {
|
||||
typedef typename padding::director padding_director;
|
||||
r = padding_director::generate(pc, sink, ctx, unused, unused);
|
||||
}
|
||||
|
||||
// copy the embedded output to the target output iterator
|
||||
if (r)
|
||||
sink.buffer_copy();
|
||||
return r;
|
||||
}
|
||||
|
||||
}}}} // namespace boost::spirit::karma::detail
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
230
include/boost/spirit/home/karma/directive/left_alignment.hpp
Normal file
230
include/boost/spirit/home/karma/directive/left_alignment.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
// 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_KARMA_LEFT_ALIGNMENT_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_LEFT_ALIGNMENT_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/directive/detail/left_alignment_generate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The BOOST_KARMA_DEFAULT_FIELD_LENGTH specifies the default field length
|
||||
// to be used for padding.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(BOOST_KARMA_DEFAULT_FIELD_LENGTH)
|
||||
#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 10
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The simple left alignment directive is used for left_align[...]
|
||||
// generators. It uses default values for the generated width (defined via
|
||||
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct simple_left_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::argument1<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::left_align_generate(sink, ctx, d, param,
|
||||
argument1(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH, ' ');
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "left_align[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::argument1(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The left alignment with width directive, is used for generators
|
||||
// like left_align(width)[...]. It uses a default value for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct width_left_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::left_align_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)), ' ');
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "left_align(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The left alignment directive with padding, is used for generators like
|
||||
// left_align(padding)[...], where padding is a arbitrary generator
|
||||
// expression. It uses a default value for the generated width (defined
|
||||
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct padding_left_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::left_align_generate(sink, ctx, d, param,
|
||||
subject(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH,
|
||||
argument1(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "left_align(";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument1(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The full left alignment directive, is used for generators like
|
||||
// left_align(width, padding)[...], where width is a integer value to be
|
||||
// used as the field width and padding is a arbitrary generator
|
||||
// expression.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct full_left_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::left_align_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)),
|
||||
argument2(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "left_align(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ", ";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument2<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument2(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
231
include/boost/spirit/home/karma/directive/right_alignment.hpp
Normal file
231
include/boost/spirit/home/karma/directive/right_alignment.hpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// 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_KARMA_RIGHT_ALIGNMENT_FEB_27_2007_1216PM)
|
||||
#define BOOST_SPIRIT_KARMA_RIGHT_ALIGNMENT_FEB_27_2007_1216PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/directive/detail/right_alignment_generate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The BOOST_KARMA_DEFAULT_FIELD_LENGTH specifies the default field length
|
||||
// to be used for padding.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(BOOST_KARMA_DEFAULT_FIELD_LENGTH)
|
||||
#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 10
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The simple right alignment directive is used for right_align[...]
|
||||
// generators. It uses default values for the generated width (defined via
|
||||
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct simple_right_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::argument1<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::right_align_generate(sink, ctx, d, param,
|
||||
argument1(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH,
|
||||
spirit::as_component(karma::domain(), ' '));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "right_align[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::argument1(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The right alignment with width directive, is used for generators
|
||||
// like right_align(width)[...]. It uses a default value for the padding
|
||||
// generator (always spaces).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct width_right_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::right_align_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)), ' ');
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "right_align(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The right alignment directive with padding, is used for generators like
|
||||
// right_align(padding)[...], where padding is a arbitrary generator
|
||||
// expression. It uses a default value for the generated width (defined
|
||||
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct padding_right_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::right_align_generate(sink, ctx, d, param,
|
||||
subject(component), BOOST_KARMA_DEFAULT_FIELD_LENGTH,
|
||||
argument1(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "right_align(";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument1<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument1(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The full right alignment directive, is used for generators like
|
||||
// right_align(width, padding)[...], where width is a integer value to be
|
||||
// used as the field width and padding is a arbitrary generator
|
||||
// expression.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct full_right_aligment
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::subject<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
return detail::right_align_generate(sink, ctx, d, param,
|
||||
subject(component), proto::arg_c<0>(argument1(component)),
|
||||
argument2(component));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "right_align(";
|
||||
|
||||
result += boost::lexical_cast<std::string>(
|
||||
proto::arg_c<0>(argument1(component)));
|
||||
result += ", ";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::argument2<Component>::type::director
|
||||
padding;
|
||||
|
||||
result += padding::what(spirit::argument2(component));
|
||||
result += ")[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
75
include/boost/spirit/home/karma/directive/verbatim.hpp
Normal file
75
include/boost/spirit/home/karma/directive/verbatim.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// 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_KARMA_VERBATIM_MAR_02_2007_0303PM)
|
||||
#define BOOST_SPIRIT_KARMA_VERBATIM_MAR_02_2007_0303PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The verbatim generator is used for verbatim[...] directives.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct verbatim
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
: traits::attribute_of<
|
||||
karma::domain,
|
||||
typename result_of::right<Component>::type,
|
||||
Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
// the verbatim generator simply dispatches to the embedded
|
||||
// generator while supplying unused as the new delimiter
|
||||
// to avoid delimiting down the generator stream
|
||||
typedef typename
|
||||
spirit::result_of::right<Component>::type::director
|
||||
director;
|
||||
|
||||
if (director::generate(spirit::right(component), sink, ctx,
|
||||
unused, param))
|
||||
{
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "verbatim[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::right<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::right(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
21
include/boost/spirit/home/karma/domain.hpp
Normal file
21
include/boost/spirit/home/karma/domain.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_DOMAIN_FEB_20_2007_0943AM)
|
||||
#define BOOST_SPIRIT_KARMA_DOMAIN_FEB_20_2007_0943AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct domain
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
182
include/boost/spirit/home/karma/generate.hpp
Normal file
182
include/boost/spirit/home/karma/generate.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
// 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_KARMA_GENERATE_FEB_20_2007_0959AM)
|
||||
#define BOOST_SPIRIT_KARMA_GENERATE_FEB_20_2007_0959AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
// normally any skipper can be used with any generator
|
||||
template <typename Generator, typename Delimiter>
|
||||
struct delimiter_is_compatible : mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
// If the parser is a rule or a grammar, then the delimiter must be
|
||||
// convertible to the delimiter used with this rule or grammar. The
|
||||
// corresponding specializations are defined in the files grammar.hpp and
|
||||
// rule.hpp.
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Expr>
|
||||
inline bool
|
||||
generate(OutputIterator target_sink, Expr const& xpr)
|
||||
{
|
||||
typedef spirit::traits::is_component<karma::domain, Expr> is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr));
|
||||
|
||||
// wrap user supplied iterator into our own output iterator
|
||||
detail::output_iterator<OutputIterator> sink(target_sink);
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
|
||||
component c = spirit::as_component(karma::domain(), xpr);
|
||||
return director::generate(c, sink, unused, unused, unused);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Expr, typename Parameter>
|
||||
inline bool
|
||||
generate(OutputIterator target_sink, Expr const& xpr, Parameter const& param)
|
||||
{
|
||||
typedef spirit::traits::is_component<karma::domain, Expr> is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr, Parameter));
|
||||
|
||||
// wrap user supplied iterator into our own output iterator
|
||||
detail::output_iterator<OutputIterator> sink(target_sink);
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
|
||||
component c = spirit::as_component(karma::domain(), xpr);
|
||||
return director::generate(c, sink, unused, unused, param);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Expr, typename Delimiter>
|
||||
inline bool
|
||||
generate_delimited(OutputIterator target_sink, Expr const& xpr,
|
||||
Delimiter const& delimiter)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
expr_is_component;
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Delimiter>
|
||||
delimiter_is_component;
|
||||
|
||||
// report invalid expression errors as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(expr_is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr, Delimiter));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(delimiter_is_component::value,
|
||||
delimiter_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr, Delimiter));
|
||||
|
||||
typedef spirit::traits::delimiter_is_compatible<Expr, Delimiter>
|
||||
delimiter_is_compatible;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
delimiter_is_compatible::value,
|
||||
delimiter_is_not_compatible_with_generator,
|
||||
(OutputIterator, Expr, Delimiter));
|
||||
|
||||
// wrap user supplied iterator into our own output iterator
|
||||
detail::output_iterator<OutputIterator> sink(target_sink);
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Delimiter>::type
|
||||
delim_component;
|
||||
|
||||
component c = spirit::as_component(karma::domain(), xpr);
|
||||
delim_component d = spirit::as_component(karma::domain(), delimiter);
|
||||
return director::generate(c, sink, unused, d, unused);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Expr, typename Parameter,
|
||||
typename Delimiter>
|
||||
inline bool
|
||||
generate_delimited(OutputIterator target_sink, Expr const& xpr,
|
||||
Parameter const& param, Delimiter const& delimiter)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
expr_is_component;
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Delimiter>
|
||||
delimiter_is_component;
|
||||
|
||||
// report invalid expression errors as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(expr_is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr, Parameter, Delimiter));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(delimiter_is_component::value,
|
||||
delimiter_is_not_convertible_to_a_generator,
|
||||
(OutputIterator, Expr, Parameter, Delimiter));
|
||||
|
||||
typedef spirit::traits::delimiter_is_compatible<Expr, Delimiter>
|
||||
delimiter_is_compatible;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
delimiter_is_compatible::value,
|
||||
delimiter_is_not_compatible_with_generator,
|
||||
(OutputIterator, Expr, Parameter, Delimiter));
|
||||
|
||||
// wrap user supplied iterator into our own output iterator
|
||||
detail::output_iterator<OutputIterator> sink(target_sink);
|
||||
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
typedef
|
||||
typename result_of::as_component<karma::domain, Delimiter>::type
|
||||
delim_component;
|
||||
|
||||
component c = spirit::as_component(karma::domain(), xpr);
|
||||
delim_component d = spirit::as_component(karma::domain(), delimiter);
|
||||
return director::generate(c, sink, unused, d, param);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
53
include/boost/spirit/home/karma/meta_grammar.hpp
Normal file
53
include/boost/spirit/home/karma/meta_grammar.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_META_GRAMMAR_FEB_20_2007_0939AM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_20_2007_0939AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar/basic_transforms.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
// Check if Expr is a valid Karma expression
|
||||
template <typename Expr, typename Enable = void>
|
||||
struct is_valid_expr : mpl::false_ {};
|
||||
|
||||
// Return a suitable transform for the given Expr
|
||||
template <typename Expr, typename Enable = void>
|
||||
struct expr_transform;
|
||||
|
||||
struct main_meta_grammar
|
||||
: meta_grammar::if_transform<
|
||||
is_valid_expr<proto::_>(),
|
||||
expr_transform<proto::_>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace meta_grammar
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The spirit karma domain meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct grammar<karma::domain>
|
||||
{
|
||||
typedef karma::main_meta_grammar type;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
17
include/boost/spirit/home/karma/nonterminal.hpp
Normal file
17
include/boost/spirit/home/karma/nonterminal.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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_KARMA_NONTERMINAL_MAR_05_2007_0539PM)
|
||||
#define BOOST_SPIRIT_KARMA_NONTERMINAL_MAR_05_2007_0539PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/nonterminal/rule.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/grammar.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
273
include/boost/spirit/home/karma/nonterminal/detail/rule.hpp
Normal file
273
include/boost/spirit/home/karma/nonterminal/detail/rule.hpp
Normal file
@@ -0,0 +1,273 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_RULE_MAR_05_2007_0519PM)
|
||||
#define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0519PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/function_types/is_function.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/fusion/include/pop_front.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
template <typename OutputIterator, typename Context, typename Delimiter>
|
||||
struct virtual_component_base
|
||||
{
|
||||
struct no_delimiter {};
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<Delimiter, unused_type>,
|
||||
mpl::identity<no_delimiter>,
|
||||
result_of::as_component<karma::domain, Delimiter>
|
||||
>::type
|
||||
delimiter_type;
|
||||
|
||||
virtual_component_base()
|
||||
: use_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~virtual_component_base()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool
|
||||
generate(OutputIterator& sink, Context& context,
|
||||
delimiter_type const& delim) = 0;
|
||||
|
||||
virtual bool
|
||||
generate(OutputIterator& sink, Context& context, unused_type) = 0;
|
||||
|
||||
boost::detail::atomic_count use_count;
|
||||
};
|
||||
|
||||
template <typename OutputIterator, typename Context, typename Delimiter>
|
||||
inline void
|
||||
intrusive_ptr_add_ref(
|
||||
virtual_component_base<OutputIterator, Context, Delimiter>* p)
|
||||
{
|
||||
++p->use_count;
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Context, typename Delimiter>
|
||||
inline void
|
||||
intrusive_ptr_release(
|
||||
virtual_component_base<OutputIterator, Context, Delimiter>* p)
|
||||
{
|
||||
if (--p->use_count == 0)
|
||||
delete p;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context>
|
||||
struct needs_single_attribute
|
||||
: mpl::not_<
|
||||
typename fusion::traits::is_sequence<
|
||||
typename traits::attribute_of<
|
||||
karma::domain, Component, Context>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename MustDeref, typename Parameter>
|
||||
struct deref_if
|
||||
{
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
MustDeref,
|
||||
fusion::result_of::at_c<Parameter, 1>,
|
||||
fusion::result_of::pop_front<Parameter>
|
||||
>::type
|
||||
type;
|
||||
|
||||
template <typename Param>
|
||||
static type
|
||||
call(Param const& param, mpl::true_)
|
||||
{
|
||||
return fusion::at_c<1>(param);
|
||||
}
|
||||
|
||||
template <typename Param>
|
||||
static type
|
||||
call(Param const& param, mpl::false_)
|
||||
{
|
||||
return fusion::pop_front(param);
|
||||
}
|
||||
|
||||
template <typename Param>
|
||||
static type
|
||||
call(Param const& param)
|
||||
{
|
||||
return call(param, MustDeref());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context>
|
||||
struct propagate_param
|
||||
{
|
||||
// If first element of the context (that's the parameter type) contains
|
||||
// one element only, then the parameter type to propagate is unused,
|
||||
// otherwise we consider to use everything except the first element of
|
||||
// this sequence.
|
||||
//
|
||||
// If the resulting sequence type is a fusion sequence containing
|
||||
// exactly one element and the right hand side expects a singular
|
||||
// (non-sequence) parameter we pass on the first (and only) element of
|
||||
// this sequence, otherwise we pass the parameter sequence itself.
|
||||
typedef typename
|
||||
boost::add_const<
|
||||
typename boost::remove_reference<
|
||||
typename fusion::result_of::at_c<Context, 0>::type
|
||||
>::type
|
||||
>::type
|
||||
parameter_type;
|
||||
|
||||
// this evaluates to mpl::true_ if the rules parameter type is unused
|
||||
typedef typename
|
||||
mpl::equal_to<mpl::size<parameter_type>, mpl::long_<1> >::type
|
||||
no_parameter;
|
||||
|
||||
// this evaluates to mpl::true_ if the rules parameter type contains
|
||||
// one element and the right hand side generator expects a single
|
||||
// (non-sequence) parameter type
|
||||
typedef typename
|
||||
mpl::and_<
|
||||
mpl::equal_to<mpl::size<parameter_type>, mpl::long_<2> >,
|
||||
needs_single_attribute<Component, Context>
|
||||
>::type
|
||||
must_dereference;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
no_parameter,
|
||||
mpl::identity<unused_type const>,
|
||||
deref_if<must_dereference, parameter_type>
|
||||
>::type
|
||||
propagated_type;
|
||||
|
||||
template <typename Ctx>
|
||||
static unused_type const
|
||||
call(Ctx& context, mpl::true_)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
|
||||
template <typename Ctx>
|
||||
static propagated_type
|
||||
call(Ctx& context, mpl::false_)
|
||||
{
|
||||
return deref_if<must_dereference, parameter_type>::
|
||||
call(fusion::at_c<0>(context));
|
||||
}
|
||||
|
||||
template <typename Ctx>
|
||||
static propagated_type
|
||||
call(Ctx& context)
|
||||
{
|
||||
return call(context, no_parameter());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Component, typename Context,
|
||||
typename Delimiter, typename Auto>
|
||||
struct virtual_component
|
||||
: virtual_component_base<OutputIterator, Context, Delimiter>
|
||||
{
|
||||
typedef
|
||||
virtual_component_base<OutputIterator, Context, Delimiter>
|
||||
base_type;
|
||||
typedef typename base_type::delimiter_type delimiter_type;
|
||||
typedef typename base_type::no_delimiter no_delimiter;
|
||||
|
||||
virtual_component(Component const& component)
|
||||
: component(component)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~virtual_component()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Delimiter_>
|
||||
bool generate_main(OutputIterator& sink, Context& context,
|
||||
Delimiter_ const& delim, mpl::false_)
|
||||
{
|
||||
// If Auto is false, the component's parameter is unused.
|
||||
typedef typename Component::director director;
|
||||
return director::generate(component, sink, context, delim, unused);
|
||||
}
|
||||
|
||||
template <typename Delimiter_>
|
||||
bool generate_main(OutputIterator& sink, Context& context,
|
||||
Delimiter_ const& delim, mpl::true_)
|
||||
{
|
||||
// If Auto is true, we pass the rule's parameters on to the
|
||||
// component.
|
||||
typedef typename Component::director director;
|
||||
return director::generate(component, sink, context, delim,
|
||||
detail::propagate_param<Component, Context>::call(context));
|
||||
}
|
||||
|
||||
bool
|
||||
generate_main(OutputIterator& /*sink*/, Context& /*context*/, no_delimiter,
|
||||
mpl::false_)
|
||||
{
|
||||
BOOST_ASSERT(false); // this should never be called
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
generate_main(OutputIterator& /*sink*/, Context& /*context*/, no_delimiter,
|
||||
mpl::true_)
|
||||
{
|
||||
BOOST_ASSERT(false); // this should never be called
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
generate(OutputIterator& sink, Context& context,
|
||||
delimiter_type const& delim)
|
||||
{
|
||||
return generate_main(sink, context, delim, Auto());
|
||||
}
|
||||
|
||||
virtual bool
|
||||
generate(OutputIterator& sink, Context& context, unused_type)
|
||||
{
|
||||
return generate_main(sink, context, unused, Auto());
|
||||
}
|
||||
|
||||
Component component;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
136
include/boost/spirit/home/karma/nonterminal/grammar.hpp
Normal file
136
include/boost/spirit/home/karma/nonterminal/grammar.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_GRAMMAR_MAR_05_2007_0542PM)
|
||||
#define BOOST_SPIRIT_KARMA_GRAMMAR_MAR_05_2007_0542PM
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/rule.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/nonterminal_director.hpp>
|
||||
#include <boost/function_types/is_function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename Definition>
|
||||
struct grammar
|
||||
: nonterminal<
|
||||
grammar<Definition>,
|
||||
typename Definition::sig_type,
|
||||
typename Definition::locals_type
|
||||
>
|
||||
{
|
||||
typedef typename Definition::sig_type sig_type;
|
||||
typedef typename Definition::locals_type locals_type;
|
||||
typedef typename Definition::delimiter_type delimiter_type;
|
||||
typedef typename Definition::start_type start_type;
|
||||
typedef typename Definition::iterator_type iterator_type;
|
||||
|
||||
explicit grammar(Definition const& definition_)
|
||||
: definition(definition_), start(definition_.start)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Definition_, typename Start>
|
||||
grammar(Definition_ const& definition_, Start const& start_)
|
||||
: definition(definition_), start(start_)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename OutputIterator, typename Context, typename Delimiter>
|
||||
bool generate(OutputIterator& sink, Context& context,
|
||||
Delimiter const& delim) const
|
||||
{
|
||||
return start.generate(sink, context, delim);
|
||||
}
|
||||
|
||||
std::string what() const
|
||||
{
|
||||
if (definition.name().empty())
|
||||
{
|
||||
return start.what();
|
||||
}
|
||||
else
|
||||
{
|
||||
return definition.name();
|
||||
}
|
||||
}
|
||||
|
||||
friend struct nonterminal_director;
|
||||
Definition const& definition;
|
||||
start_type const& start;
|
||||
};
|
||||
|
||||
template <typename OutputIterator, typename T0 = unused_type,
|
||||
typename T1 = unused_type, typename T2 = unused_type>
|
||||
struct grammar_def : noncopyable
|
||||
{
|
||||
typedef karma::rule<OutputIterator, T0, T1, T2> start_type;
|
||||
typedef typename start_type::iterator_type iterator_type;
|
||||
typedef typename start_type::sig_type sig_type;
|
||||
typedef typename start_type::locals_type locals_type;
|
||||
typedef typename start_type::delimiter_type delimiter_type;
|
||||
|
||||
grammar_def(std::string const& name_ = std::string())
|
||||
: name_(name_) {}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void name(std::string const& name__)
|
||||
{
|
||||
name_ = name__;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator functions helping to construct a proper grammar object
|
||||
// instance
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Definition>
|
||||
inline grammar<Definition>
|
||||
make_generator(Definition const& def)
|
||||
{
|
||||
return grammar<Definition>(def);
|
||||
}
|
||||
|
||||
template <typename Definition, typename Start>
|
||||
inline grammar<Definition>
|
||||
make_generator(Definition const& def, Start const& start)
|
||||
{
|
||||
return grammar<Definition>(def, start);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
// forward declaration only (the default specialization is defined in the
|
||||
// file generate.hpp)
|
||||
template <typename Generator, typename Delimiter>
|
||||
struct delimiter_is_compatible;
|
||||
|
||||
// If the parser is a grammar, then the delimiter must be convertible to
|
||||
// the delimiter used with this grammar.
|
||||
template <typename Definition, typename Delimiter>
|
||||
struct delimiter_is_compatible<karma::grammar<Definition>, Delimiter>
|
||||
: is_convertible<
|
||||
Delimiter, typename karma::grammar<Definition>::delimiter_type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
72
include/boost/spirit/home/karma/nonterminal/meta_grammar.hpp
Normal file
72
include/boost/spirit/home/karma/nonterminal/meta_grammar.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_META_GRAMMAR_MAR_05_2007_0436PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_MAR_05_2007_0436PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct nonterminal_director;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// nonterminal meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct nonterminal_meta_grammar
|
||||
: meta_grammar::terminal_rule<
|
||||
karma::domain,
|
||||
nonterminal_holder<proto::_, proto::_>,
|
||||
nonterminal_director
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hook into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, nonterminal_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, nonterminal_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<nonterminal_meta_grammar>
|
||||
{
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
164
include/boost/spirit/home/karma/nonterminal/nonterminal.hpp
Normal file
164
include/boost/spirit/home/karma/nonterminal/nonterminal.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_NONTERMINAL_MAR_06_2007_0750AM)
|
||||
#define BOOST_SPIRIT_KARMA_NONTERMINAL_MAR_06_2007_0750AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/locals.hpp>
|
||||
#include <boost/spirit/home/support/argument.hpp>
|
||||
|
||||
#include <boost/xpressive/proto/proto.hpp>
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/function_types/is_function.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>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/copy_if.hpp>
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/mpl/find_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/preprocessor/enum_params.hpp>
|
||||
#include <boost/preprocessor/enum_params_with_a_default.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Derived, typename Sig, typename Locals>
|
||||
struct nonterminal
|
||||
: proto::extends<
|
||||
typename make_nonterminal_holder<
|
||||
Derived const*, Derived
|
||||
>::type,
|
||||
Derived
|
||||
>
|
||||
{
|
||||
typedef Sig sig_type;
|
||||
typedef typename
|
||||
function_types::result_type<sig_type>::type
|
||||
result_type_;
|
||||
|
||||
// This is the nonterminal return type
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<result_type_, void>, unused_type, result_type_
|
||||
>::type
|
||||
result_type;
|
||||
|
||||
// param_types is a sequence of types passed as parameters to the
|
||||
// nonterminal
|
||||
typedef typename
|
||||
function_types::parameter_types<sig_type>::type
|
||||
param_types_;
|
||||
|
||||
// if no parameters have been specified, we generate a single
|
||||
// unused_type parameter, which is needed to allow grammar parameter
|
||||
// propagation to function correctly
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<typename mpl::size<param_types_>::type, mpl::long_<0> >,
|
||||
fusion::single_view<unused_type>,
|
||||
param_types_
|
||||
>::type
|
||||
param_types;
|
||||
|
||||
// locals_type is a sequence of types to be used as local variables
|
||||
typedef typename
|
||||
fusion::result_of::as_vector<Locals>::type
|
||||
locals_type;
|
||||
|
||||
// The overall context_type consist of a tuple with:
|
||||
// 1) a tuple of the return value and parameters
|
||||
// 2) the locals
|
||||
typedef fusion::vector<
|
||||
typename fusion::result_of::as_vector<
|
||||
fusion::joint_view<
|
||||
fusion::single_view<result_type const>,
|
||||
param_types
|
||||
>
|
||||
>::type,
|
||||
typename fusion::result_of::as_vector<locals_type>::type
|
||||
>
|
||||
context_type;
|
||||
|
||||
typedef nonterminal<Derived, Sig, Locals> self_type;
|
||||
typedef nonterminal_holder<Derived const*, Derived> nonterminal_holder_;
|
||||
typedef typename proto::terminal<nonterminal_holder_>::type nonterminal_tag;
|
||||
typedef proto::extends<nonterminal_tag, Derived> base_type;
|
||||
|
||||
explicit nonterminal()
|
||||
: base_type(make_tag())
|
||||
{
|
||||
}
|
||||
|
||||
// bring in the operator() overloads
|
||||
#include <boost/spirit/home/support/nonterminal/detail/nonterminal_fcall.hpp>
|
||||
|
||||
private:
|
||||
|
||||
nonterminal_tag make_tag() const
|
||||
{
|
||||
nonterminal_tag xpr = {{static_cast<Derived const*>(this)}};
|
||||
return xpr;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Derived, typename T0, typename T1, typename T2>
|
||||
struct make_nonterminal
|
||||
{
|
||||
typedef mpl::vector<T0, T1, T2> types;
|
||||
typedef function_types::is_function<mpl::_> is_function;
|
||||
typedef spirit::detail::is_locals<mpl::_> is_locals;
|
||||
typedef spirit::traits::is_component<karma::domain, mpl::_> is_delimiter;
|
||||
|
||||
typedef typename mpl::find_if<types, is_function>::type sig_;
|
||||
typedef typename mpl::find_if<types, is_locals>::type locals_;
|
||||
typedef typename mpl::find_if<types, is_delimiter>::type delimiter_;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<sig_, typename mpl::end<types>::type>,
|
||||
mpl::identity<unused_type()>,
|
||||
mpl::deref<sig_>
|
||||
>::type
|
||||
sig_type;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<locals_, typename mpl::end<types>::type>,
|
||||
mpl::identity<locals<> >,
|
||||
mpl::deref<locals_>
|
||||
>::type
|
||||
locals_type;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<delimiter_, typename mpl::end<types>::type>,
|
||||
mpl::identity<unused_type>,
|
||||
mpl::deref<delimiter_>
|
||||
>::type
|
||||
delimiter_type;
|
||||
|
||||
typedef nonterminal<Derived, sig_type, locals_type> type;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM)
|
||||
#define BOOST_SPIRIT_KARMA_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/detail/expand_arg.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/values.hpp>
|
||||
#include <boost/fusion/include/transform.hpp>
|
||||
#include <boost/fusion/include/join.hpp>
|
||||
#include <boost/fusion/include/single_view.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct nonterminal_director
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef typename result_of::subject<Component>::type nonterminal_holder;
|
||||
typedef typename nonterminal_holder::nonterminal_type::param_types type;
|
||||
};
|
||||
|
||||
template <
|
||||
typename NonterminalContext, typename Nonterminal,
|
||||
typename OutputIterator, typename Context,
|
||||
typename Delimiter, typename Parameter>
|
||||
static bool generate_nonterminal(
|
||||
nonterminal_object<Nonterminal> const& x,
|
||||
OutputIterator& sink, Context& context_,
|
||||
Delimiter const& delim, Parameter const& param)
|
||||
{
|
||||
// the nonterminal_holder holds an actual nonterminal_object
|
||||
typedef typename Nonterminal::locals_type locals_type;
|
||||
NonterminalContext context(param, locals_type());
|
||||
return x.obj.generate(sink, context, delim);
|
||||
}
|
||||
|
||||
template <
|
||||
typename NonterminalContext, typename Nonterminal,
|
||||
typename OutputIterator, typename Context,
|
||||
typename Delimiter, typename Parameter>
|
||||
static bool generate_nonterminal(
|
||||
Nonterminal const* ptr,
|
||||
OutputIterator& sink, Context& /*context_*/,
|
||||
Delimiter const& delim, Parameter const& param)
|
||||
{
|
||||
// the nonterminal_holder holds a pointer to a nonterminal
|
||||
typedef typename Nonterminal::locals_type locals_type;
|
||||
NonterminalContext context(param, locals_type());
|
||||
return ptr->generate(sink, context, delim);
|
||||
}
|
||||
|
||||
template <
|
||||
typename NonterminalContext, typename Nonterminal,
|
||||
typename FSequence, typename OutputIterator,
|
||||
typename Context, typename Delimiter,
|
||||
typename Parameter>
|
||||
static bool generate_nonterminal(
|
||||
parameterized_nonterminal<Nonterminal, FSequence> const& x,
|
||||
OutputIterator& sink, Context& context_,
|
||||
Delimiter const& delim, Parameter const& /*param*/)
|
||||
{
|
||||
// the nonterminal_holder holds a parameterized_nonterminal
|
||||
typedef typename Nonterminal::locals_type locals_type;
|
||||
fusion::single_view<unused_type const> front(unused);
|
||||
NonterminalContext context(
|
||||
fusion::join(
|
||||
front,
|
||||
fusion::transform(
|
||||
x.fseq,
|
||||
spirit::detail::expand_arg<Context>(context_)
|
||||
)
|
||||
),
|
||||
locals_type()
|
||||
);
|
||||
return x.ptr->generate(sink, context, delim);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// main entry point
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Component,
|
||||
typename OutputIterator, typename Context,
|
||||
typename Delimiter, typename Parameter>
|
||||
static bool generate(
|
||||
Component const& component, OutputIterator& sink,
|
||||
Context& context, Delimiter const& delim, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type
|
||||
nonterminal_holder;
|
||||
|
||||
// The overall context_type consists of a tuple with:
|
||||
// 1) a tuple of the return value and parameters
|
||||
// 2) the locals
|
||||
// if no signature is specified the first tuple contains
|
||||
// an unused_type element at position zero only.
|
||||
|
||||
typedef typename
|
||||
nonterminal_holder::nonterminal_type::context_type
|
||||
context_type;
|
||||
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<typename remove_const<Parameter>::type, unused_type>,
|
||||
context_type,
|
||||
Parameter
|
||||
>::type
|
||||
parameter_type;
|
||||
|
||||
// create an parameter if one is not supplied
|
||||
parameter_type p (spirit::detail::make_value<parameter_type>::call(param));
|
||||
|
||||
return generate_nonterminal<context_type>(
|
||||
subject(component).held, sink, context, delim, p
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Nonterminal>
|
||||
static std::string what_nonterminal(nonterminal_object<Nonterminal> const& x)
|
||||
{
|
||||
// the nonterminal_holder holds an actual nonterminal_object
|
||||
return x.obj.what();
|
||||
}
|
||||
|
||||
template <typename Nonterminal>
|
||||
static std::string what_nonterminal(Nonterminal const* ptr)
|
||||
{
|
||||
// the nonterminal_holder holds a pointer to a nonterminal
|
||||
return ptr->what();
|
||||
}
|
||||
|
||||
template <typename Nonterminal, typename FSequence>
|
||||
static std::string what_nonterminal(
|
||||
parameterized_nonterminal<Nonterminal, FSequence> const& x)
|
||||
{
|
||||
// the nonterminal_holder holds a parameterized_nonterminal
|
||||
return x.ptr->what();
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return what_nonterminal(subject(component).held);
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
220
include/boost/spirit/home/karma/nonterminal/rule.hpp
Normal file
220
include/boost/spirit/home/karma/nonterminal/rule.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_RULE_MAR_05_2007_0455PM)
|
||||
#define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/nonterminal.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/detail/rule.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename Definition>
|
||||
struct grammar; // forward declaration
|
||||
|
||||
template <typename OutputIterator, typename T0 = unused_type,
|
||||
typename T1 = unused_type, typename T2 = unused_type>
|
||||
struct rule
|
||||
: make_nonterminal<rule<OutputIterator, T0, T1, T2>, T0, T1, T2>::type
|
||||
{
|
||||
typedef
|
||||
make_nonterminal<rule<OutputIterator, T0, T1, T2>, T0, T1, T2>
|
||||
make_nonterminal_;
|
||||
|
||||
typedef typename make_nonterminal_::delimiter_type delimiter_type;
|
||||
typedef typename make_nonterminal_::type base_type;
|
||||
typedef detail::output_iterator<OutputIterator> iterator_type;
|
||||
typedef rule<OutputIterator, T0, T1, T2> self_type;
|
||||
|
||||
typedef
|
||||
detail::virtual_component_base<
|
||||
iterator_type,
|
||||
typename base_type::context_type,
|
||||
delimiter_type
|
||||
>
|
||||
virtual_component;
|
||||
|
||||
typedef intrusive_ptr<virtual_component> pointer_type;
|
||||
|
||||
rule() {}
|
||||
~rule() {}
|
||||
|
||||
rule(rule const& rhs)
|
||||
: ptr(rhs.ptr)
|
||||
{
|
||||
}
|
||||
|
||||
rule& operator=(rule const& rhs)
|
||||
{
|
||||
ptr = rhs.ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Expr>
|
||||
rule& operator=(Expr const& xpr)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, ());
|
||||
|
||||
define(xpr, mpl::false_());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Expr>
|
||||
friend rule& operator%=(rule& r, Expr const& xpr)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, ());
|
||||
|
||||
r.define(xpr, mpl::true_());
|
||||
return r;
|
||||
}
|
||||
|
||||
self_type alias() const
|
||||
{
|
||||
self_type result;
|
||||
result.define(*this, mpl::false_());
|
||||
return result;
|
||||
}
|
||||
|
||||
typename
|
||||
make_nonterminal_holder<
|
||||
nonterminal_object<self_type>
|
||||
, self_type
|
||||
>::type
|
||||
copy() const
|
||||
{
|
||||
typename
|
||||
make_nonterminal_holder<
|
||||
nonterminal_object<self_type>
|
||||
, self_type
|
||||
>::type
|
||||
result = {{*this}};
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void name(std::string const& str)
|
||||
{
|
||||
name_ = str;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename Definition>
|
||||
friend struct grammar;
|
||||
|
||||
template <typename Expr, typename Auto>
|
||||
void define(Expr const& xpr, Auto)
|
||||
{
|
||||
typedef typename
|
||||
result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef
|
||||
detail::virtual_component<
|
||||
iterator_type,
|
||||
component,
|
||||
typename base_type::context_type,
|
||||
delimiter_type,
|
||||
Auto
|
||||
>
|
||||
virtual_component;
|
||||
ptr = new virtual_component(spirit::as_component(karma::domain(), xpr));
|
||||
}
|
||||
|
||||
template <typename OutputIterator_, typename Context, typename Delimiter>
|
||||
bool generate(
|
||||
OutputIterator_& sink, Context& context, Delimiter const& delim) const
|
||||
{
|
||||
return ptr->generate(sink, context, delim);
|
||||
}
|
||||
|
||||
std::string what() const
|
||||
{
|
||||
if (name_.empty())
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
return "unnamed-rule";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "empty-rule";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
}
|
||||
|
||||
friend struct nonterminal_director;
|
||||
pointer_type ptr;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
// forward declaration only (the default specialization is defined in the
|
||||
// file generate.hpp)
|
||||
template <typename Generator, typename Delimiter>
|
||||
struct delimiter_is_compatible;
|
||||
|
||||
// If the parser is a rule, then the delimiter must be convertible to
|
||||
// the delimiter used with this rule.
|
||||
template <
|
||||
typename OutputIterator, typename T0, typename T1, typename T2,
|
||||
typename Delimiter
|
||||
>
|
||||
struct delimiter_is_compatible<
|
||||
karma::rule<OutputIterator, T0, T1, T2>, Delimiter>
|
||||
: is_convertible<
|
||||
Delimiter,
|
||||
typename karma::rule<OutputIterator, T0, T1, T2>::delimiter_type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
19
include/boost/spirit/home/karma/numeric.hpp
Normal file
19
include/boost/spirit/home/karma/numeric.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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_KARMA_NUMERIC_FEB_23_2007_0507PM)
|
||||
#define BOOST_SPIRIT_KARMA_NUMERIC_FEB_23_2007_0507PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/numeric/numeric_fwd.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/int.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/uint.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/real.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
625
include/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
Normal file
625
include/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
Normal file
@@ -0,0 +1,625 @@
|
||||
// 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_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
|
||||
#define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/support/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/ascii.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/karma/detail/generate_to.hpp>
|
||||
#include <boost/spirit/home/karma/detail/string_generate.hpp>
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#include <boost/spirit/home/support/detail/math/signbit.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
|
||||
// integer string generation loop (see below).
|
||||
//
|
||||
// Set the value to some integer in between 0 (no unrolling) and the
|
||||
// largest expected generated integer string length (complete unrolling).
|
||||
// If not specified, this value defaults to 6.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
|
||||
#define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
|
||||
#endif
|
||||
|
||||
#if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
|
||||
#error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a positive value!"
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// return the absolute value from a given number, avoiding over- and
|
||||
// underflow
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
inline unsigned short absolute_value (short n)
|
||||
{
|
||||
return (n >= 0) ? n : (unsigned short)(-n);
|
||||
}
|
||||
|
||||
inline unsigned int absolute_value (int n)
|
||||
{
|
||||
return (n >= 0) ? n : (unsigned int)(-n);
|
||||
}
|
||||
|
||||
inline unsigned long absolute_value (long n)
|
||||
{
|
||||
return (n >= 0) ? n : (unsigned long)(-n);
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
inline boost::ulong_long_type absolute_value (boost::long_long_type n)
|
||||
{
|
||||
return (n >= 0) ? n : (boost::ulong_long_type)(-n);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline float absolute_value (float n)
|
||||
{
|
||||
return boost::math::signbit(n) ? boost::math::changesign(n) : n;
|
||||
}
|
||||
|
||||
inline double absolute_value (double n)
|
||||
{
|
||||
return boost::math::signbit(n) ? boost::math::changesign(n) : n;
|
||||
}
|
||||
|
||||
inline long double absolute_value (long double n)
|
||||
{
|
||||
return boost::math::signbit(n) ? boost::math::changesign(n) : n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T absolute_value (T n)
|
||||
{
|
||||
using namespace std;
|
||||
return fabs(n);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
inline bool is_negative(float n)
|
||||
{
|
||||
return boost::math::signbit(n);
|
||||
}
|
||||
|
||||
inline bool is_negative(double n)
|
||||
{
|
||||
return boost::math::signbit(n);
|
||||
}
|
||||
|
||||
inline bool is_negative(long double n)
|
||||
{
|
||||
return boost::math::signbit(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool is_negative(T n)
|
||||
{
|
||||
return (n < 0) ? true : false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
inline bool is_zero(float n)
|
||||
{
|
||||
return boost::math::fpclassify(n) == FP_ZERO;
|
||||
}
|
||||
|
||||
inline bool is_zero(double n)
|
||||
{
|
||||
return boost::math::fpclassify(n) == FP_ZERO;
|
||||
}
|
||||
|
||||
inline bool is_zero(long double n)
|
||||
{
|
||||
return boost::math::fpclassify(n) == FP_ZERO;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool is_zero(T n)
|
||||
{
|
||||
return (n == 0) ? true : false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct cast_to_long
|
||||
{
|
||||
static long call(float n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n));
|
||||
}
|
||||
|
||||
static long call(double n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n));
|
||||
}
|
||||
|
||||
static long call(long double n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n, mpl::false_)
|
||||
{
|
||||
// allow for ADL to find the correct overload for floor and
|
||||
// lround
|
||||
using namespace std;
|
||||
return lround(floor(n));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n, mpl::true_)
|
||||
{
|
||||
return static_cast<long>(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n)
|
||||
{
|
||||
return call(n, mpl::bool_<is_integral<T>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct round_to_long
|
||||
{
|
||||
static long call(float n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n + 0.5f));
|
||||
}
|
||||
|
||||
static long call(double n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n + 0.5));
|
||||
}
|
||||
|
||||
static long call(long double n, mpl::false_)
|
||||
{
|
||||
return static_cast<long>(std::floor(n + 0.5l));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n, mpl::false_)
|
||||
{
|
||||
using namespace std;
|
||||
return lround(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n, mpl::true_)
|
||||
{
|
||||
return static_cast<long>(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n)
|
||||
{
|
||||
return call(n, mpl::bool_<is_integral<T>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Traits class for radix specific number conversion
|
||||
//
|
||||
// Convert a digit from binary representation to character
|
||||
// representation:
|
||||
//
|
||||
// static int digit(unsigned n);
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template<unsigned Radix, typename Tag>
|
||||
struct radix_traits;
|
||||
|
||||
// Binary
|
||||
template<typename Tag>
|
||||
struct radix_traits<2, Tag>
|
||||
{
|
||||
static int digit(unsigned n)
|
||||
{
|
||||
return n + '0';
|
||||
}
|
||||
};
|
||||
|
||||
// Octal
|
||||
template<typename Tag>
|
||||
struct radix_traits<8, Tag>
|
||||
{
|
||||
static int digit(unsigned n)
|
||||
{
|
||||
return n + '0';
|
||||
}
|
||||
};
|
||||
|
||||
// Decimal
|
||||
template<typename Tag>
|
||||
struct radix_traits<10, Tag>
|
||||
{
|
||||
static int digit(unsigned n)
|
||||
{
|
||||
return n + '0';
|
||||
}
|
||||
};
|
||||
|
||||
// Hexadecimal, lower case
|
||||
template<>
|
||||
struct radix_traits<16, unused_type>
|
||||
{
|
||||
static int digit(unsigned n)
|
||||
{
|
||||
if (n <= 9)
|
||||
return n + '0';
|
||||
return n - 10 + 'a';
|
||||
}
|
||||
};
|
||||
|
||||
// Hexadecimal, upper case
|
||||
template<typename Tag>
|
||||
struct radix_traits<16, Tag>
|
||||
{
|
||||
typedef typename Tag::char_set char_set;
|
||||
typedef typename Tag::char_class char_class_;
|
||||
|
||||
static int digit(unsigned n)
|
||||
{
|
||||
if (n <= 9)
|
||||
return n + '0';
|
||||
|
||||
using spirit::char_class::convert;
|
||||
return convert<char_set>::to(char_class_(), n - 10 + 'a');
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <unsigned Radix>
|
||||
struct divide
|
||||
{
|
||||
template <typename T>
|
||||
static T call(T& n, mpl::true_)
|
||||
{
|
||||
return n / Radix;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T call(T& n, mpl::false_)
|
||||
{
|
||||
// Allow ADL to find the correct overload for floor
|
||||
using namespace std;
|
||||
return floor(n / Radix);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T call(T& n)
|
||||
{
|
||||
return call(n, mpl::bool_<is_integral<T>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <unsigned Radix>
|
||||
struct remainder
|
||||
{
|
||||
template <typename T>
|
||||
static long call(T n, mpl::true_)
|
||||
{
|
||||
// this cast is safe since we know the result is not larger
|
||||
// than Radix
|
||||
return static_cast<long>(n % Radix);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n, mpl::false_)
|
||||
{
|
||||
// Allow ADL to find the correct overload for fmod
|
||||
using namespace std;
|
||||
return cast_to_long::call(fmod(n, Radix));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static long call(T n)
|
||||
{
|
||||
return call(n, mpl::bool_<is_integral<T>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The int_inserter template takes care of the integer to string
|
||||
// conversion. If specified, the loop is unrolled for better performance.
|
||||
//
|
||||
// Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
|
||||
// between 0 (no unrolling) and the largest expected generated integer
|
||||
// string length (complete unrolling).
|
||||
// If not specified, this value defaults to 6.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data) \
|
||||
if (!detail::is_zero(n)) { \
|
||||
int ch = radix_type::digit(remainder_type::call(n)); \
|
||||
n = divide_type::call(n); \
|
||||
/**/
|
||||
|
||||
#define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data) \
|
||||
*sink = ch; \
|
||||
++sink; \
|
||||
} \
|
||||
/**/
|
||||
|
||||
template <unsigned Radix, typename Tag = unused_type>
|
||||
struct int_inserter
|
||||
{
|
||||
typedef detail::radix_traits<Radix, Tag> radix_type;
|
||||
typedef detail::divide<Radix> divide_type;
|
||||
typedef detail::remainder<Radix> remainder_type;
|
||||
|
||||
// Common code for integer string representations
|
||||
template <typename OutputIterator, typename T>
|
||||
static bool
|
||||
call(OutputIterator& sink, T n)
|
||||
{
|
||||
// remainder_type::call returns n % Radix
|
||||
int ch = radix_type::digit(remainder_type::call(n));
|
||||
n = divide_type::call(n);
|
||||
|
||||
BOOST_PP_REPEAT(
|
||||
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
|
||||
BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
|
||||
|
||||
if (!detail::is_zero(n))
|
||||
call(sink, n);
|
||||
|
||||
BOOST_PP_REPEAT(
|
||||
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
|
||||
BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _);
|
||||
|
||||
*sink = ch;
|
||||
++sink;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
|
||||
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The sign_inserter template generates a sign for a given numeric value.
|
||||
//
|
||||
// The parameter ForceSign allows to generate a sign even for positive
|
||||
// numbers.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <bool ForceSign>
|
||||
struct sign_inserter
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
call(OutputIterator& sink, bool /*is_zero*/, bool is_negative)
|
||||
{
|
||||
// generate a sign for negative numbers only
|
||||
if (is_negative) {
|
||||
*sink = '-';
|
||||
++sink;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sign_inserter<true>
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
call(OutputIterator& sink, bool is_zero, bool is_negative)
|
||||
{
|
||||
// generate a sign for all numbers except zero
|
||||
if (!is_zero)
|
||||
*sink = is_negative ? '-' : '+';
|
||||
else
|
||||
*sink = ' ';
|
||||
|
||||
++sink;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These are helper functions for the real policies allowing to generate
|
||||
// a single character and a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag = unused_type>
|
||||
struct char_inserter
|
||||
{
|
||||
template <typename OutputIterator, typename Char>
|
||||
static bool
|
||||
call(OutputIterator& sink, Char c)
|
||||
{
|
||||
return detail::generate_to(sink, c, Tag());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tag = unused_type>
|
||||
struct string_inserter
|
||||
{
|
||||
template <typename OutputIterator, typename String>
|
||||
static bool
|
||||
call(OutputIterator& sink, String str)
|
||||
{
|
||||
return detail::string_generate(sink, str, Tag());
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The real_inserter template takes care of the floating point number to
|
||||
// string conversion. The RealPolicies template parameter is used to allow
|
||||
// customization of the formatting process
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename RealPolicies, typename Tag = unused_type>
|
||||
struct real_inserter
|
||||
{
|
||||
enum { force_sign = RealPolicies::force_sign };
|
||||
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
call (OutputIterator& sink, float n, RealPolicies const& p)
|
||||
{
|
||||
int fpclass = boost::math::fpclassify(n);
|
||||
if (FP_NAN == fpclass)
|
||||
return RealPolicies::template nan<force_sign, Tag>(sink, n);
|
||||
else if (FP_INFINITE == fpclass)
|
||||
return RealPolicies::template inf<force_sign, Tag>(sink, n);
|
||||
return call_n(sink, n, p);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
call (OutputIterator& sink, double n, RealPolicies const& p)
|
||||
{
|
||||
int fpclass = boost::math::fpclassify(n);
|
||||
if (FP_NAN == fpclass)
|
||||
return RealPolicies::template nan<force_sign, Tag>(sink, n);
|
||||
else if (FP_INFINITE == fpclass)
|
||||
return RealPolicies::template inf<force_sign, Tag>(sink, n);
|
||||
return call_n(sink, n, p);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
call (OutputIterator& sink, long double n, RealPolicies const& p)
|
||||
{
|
||||
int fpclass = boost::math::fpclassify(n);
|
||||
if (FP_NAN == fpclass)
|
||||
return RealPolicies::template nan<force_sign, Tag>(sink, n);
|
||||
else if (FP_INFINITE == fpclass)
|
||||
return RealPolicies::template inf<force_sign, Tag>(sink, n);
|
||||
return call_n(sink, n, p);
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename U>
|
||||
static bool
|
||||
call (OutputIterator& sink, U n, RealPolicies const& p)
|
||||
{
|
||||
// we have no means of testing whether the number is normalized if
|
||||
// the type is not float, double or long double
|
||||
return call_n(sink, T(n), p);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// This is the workhorse behind the real generator
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename T>
|
||||
static bool
|
||||
call_n (OutputIterator& sink, T n, RealPolicies const& p)
|
||||
{
|
||||
// prepare sign and get output format
|
||||
bool sign_val = false;
|
||||
int flags = p.floatfield(n);
|
||||
if (detail::is_negative(n))
|
||||
{
|
||||
n = -n;
|
||||
sign_val = true;
|
||||
}
|
||||
|
||||
// The scientific representation requires the normalization of the
|
||||
// value to convert.
|
||||
|
||||
// allow for ADL to find the correct overloads for log10 et.al.
|
||||
using namespace std;
|
||||
|
||||
T dim = 0;
|
||||
if (0 == (p.fixed & flags) && !detail::is_zero(n))
|
||||
{
|
||||
dim = log10(n);
|
||||
if (dim > 0)
|
||||
n /= pow(T(10.0), (int)detail::round_to_long::call(dim));
|
||||
else if (n < 1.)
|
||||
n *= pow(T(10.0), (int)detail::round_to_long::call(-dim));
|
||||
}
|
||||
|
||||
// prepare numbers (sign, integer and fraction part)
|
||||
unsigned precision = p.precision(n);
|
||||
T integer_part;
|
||||
T precexp = std::pow(10.0, (int)precision);
|
||||
T fractional_part = modf(n, &integer_part);
|
||||
|
||||
fractional_part = floor(fractional_part * precexp + 0.5);
|
||||
if (fractional_part >= precexp)
|
||||
{
|
||||
fractional_part -= precexp;
|
||||
integer_part += 1; // handle rounding overflow
|
||||
}
|
||||
|
||||
// if trailing zeros are to be omitted, normalize the precision and
|
||||
// fractional part
|
||||
T long_int_part = floor(integer_part);
|
||||
T long_frac_part = floor(fractional_part);
|
||||
if (!p.trailing_zeros)
|
||||
{
|
||||
if (0 != long_frac_part) {
|
||||
// remove the trailing zeros
|
||||
while (0 != precision &&
|
||||
0 == detail::remainder<10>::call(long_frac_part))
|
||||
{
|
||||
long_frac_part = detail::divide<10>::call(long_frac_part);
|
||||
--precision;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the fractional part is zero, we don't need to output
|
||||
// any additional digits
|
||||
precision = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// call the actual generating functions to output the different parts
|
||||
if (sign_val && detail::is_zero(long_int_part) &&
|
||||
detail::is_zero(long_frac_part))
|
||||
{
|
||||
sign_val = false; // result is zero, no sign please
|
||||
}
|
||||
|
||||
// generate integer part
|
||||
bool r = p.template integer_part<force_sign>(
|
||||
sink, long_int_part, sign_val);
|
||||
|
||||
// generate decimal point
|
||||
r = r && p.dot(sink, long_frac_part);
|
||||
|
||||
// generate fractional part with the desired precision
|
||||
r = r && p.fraction_part(sink, long_frac_part, precision);
|
||||
|
||||
if (r && 0 == (p.fixed & flags)) {
|
||||
return p.template exponent<Tag>(sink,
|
||||
detail::round_to_long::call(dim));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
240
include/boost/spirit/home/karma/numeric/int.hpp
Normal file
240
include/boost/spirit/home/karma/numeric/int.hpp
Normal file
@@ -0,0 +1,240 @@
|
||||
// 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_KARMA_INT_FEB_23_2007_0840PM)
|
||||
#define BOOST_SPIRIT_KARMA_INT_FEB_23_2007_0840PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/numeric_fwd.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization is used for int generators not having a direct
|
||||
// initializer: int_, long_ etc. These generators must be used in
|
||||
// conjunction with a parameter.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct int_generator<false, T, Radix, ForceSign, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// check template parameter 'Radix' for validity
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
|
||||
not_supported_radix, ());
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(std::numeric_limits<T>::is_signed,
|
||||
signed_unsigned_mismatch, ());
|
||||
|
||||
// int has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
sign_inserter<ForceSign>::call(sink, detail::is_zero(param),
|
||||
detail::is_negative(param));
|
||||
bool result = int_inserter<Radix, Tag>::call(sink,
|
||||
detail::absolute_value(param));
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
// this int has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, int__not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "integer";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization is used for int generators having a direct
|
||||
// initializer: int_(10), long_(20) etc.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct int_generator<true, T, Radix, ForceSign, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// check template parameter 'Radix' for validity
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
|
||||
not_supported_radix, ());
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(std::numeric_limits<T>::is_signed,
|
||||
signed_unsigned_mismatch, ());
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
T n = fusion::at_c<0>(component.elements);
|
||||
sign_inserter<ForceSign>::call(sink, detail::is_zero(n),
|
||||
detail::is_negative(n));
|
||||
bool result = int_inserter<Radix, Tag>::call(sink,
|
||||
detail::absolute_value(n));
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "integer";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case int_generator generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::int_generator<false, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef karma::int_generator<false, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, fusion::nil> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::int_generator<true, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
int_data_type;
|
||||
typedef fusion::vector<int_data_type> vector_type;
|
||||
|
||||
typedef karma::int_generator<true, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// upper_case int_generator generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::int_generator<false, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef karma::int_generator<false, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, fusion::nil> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::int_generator<true, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
int_data_type;
|
||||
typedef fusion::vector<int_data_type> vector_type;
|
||||
|
||||
typedef karma::int_generator<true, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
#endif
|
||||
452
include/boost/spirit/home/karma/numeric/meta_grammar.hpp
Normal file
452
include/boost/spirit/home/karma/numeric/meta_grammar.hpp
Normal file
@@ -0,0 +1,452 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_META_GRAMMAR_FEB_23_2007_0505PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_23_2007_0505PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/numeric_fwd.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// numeric tags
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct int_tag
|
||||
{};
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct uint_tag
|
||||
{};
|
||||
|
||||
template <typename T, typename RealPolicies>
|
||||
struct real_tag
|
||||
{
|
||||
RealPolicies policies;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// numeric specs
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct int_spec
|
||||
: proto::terminal<int_tag<T, Radix, ForceSign> >::type
|
||||
{};
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct uint_spec
|
||||
: proto::terminal<uint_tag<T, Radix, ForceSign> >::type
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename RealPolicies>
|
||||
struct real_spec
|
||||
: proto::terminal<real_tag<T, RealPolicies> >::type
|
||||
{
|
||||
private:
|
||||
typedef typename
|
||||
proto::terminal<real_tag<T, RealPolicies> >::type
|
||||
base_type;
|
||||
|
||||
base_type make_tag(RealPolicies const& p) const
|
||||
{
|
||||
base_type xpr = {{p}};
|
||||
return xpr;
|
||||
}
|
||||
|
||||
public:
|
||||
real_spec(RealPolicies const& p = RealPolicies())
|
||||
: base_type(make_tag(p))
|
||||
{}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
template <typename RealPolicies>
|
||||
struct real_policy
|
||||
{
|
||||
template <typename Tag>
|
||||
static RealPolicies get(Tag) { return RealPolicies(); }
|
||||
|
||||
template <typename T>
|
||||
static RealPolicies const& get(real_tag<T, RealPolicies> const& p)
|
||||
{ return p.policies; }
|
||||
};
|
||||
}
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is an int tag (the basic specializations are defined in
|
||||
// the file support/placeholders.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct is_int_tag<karma::int_tag<T, Radix, ForceSign>, karma::domain> :
|
||||
mpl::true_ {};
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign>
|
||||
struct is_int_tag<karma::uint_tag<T, Radix, ForceSign>, karma::domain> :
|
||||
mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// test if a tag is a real tag (the basic specializations are defined in
|
||||
// the file support/placeholders.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename RealPolicies>
|
||||
struct is_real_tag<karma::real_tag<T, RealPolicies>, karma::domain> :
|
||||
mpl::true_ {};
|
||||
|
||||
}} // namespace boost::spirit
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of an int tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, bool IsLiteral>
|
||||
struct extract_int_director;
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::bin, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned, 2, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::oct, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned, 8, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::hex, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned, 16, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::ushort, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned short, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::ulong, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned long, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::uint, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, unsigned int, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::short_, IsLiteral>
|
||||
{
|
||||
typedef int_generator<IsLiteral, short, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::long_, IsLiteral>
|
||||
{
|
||||
typedef int_generator<IsLiteral, long, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::int_, IsLiteral>
|
||||
{
|
||||
typedef int_generator<IsLiteral, int, 10, false> type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::ulong_long, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, boost::ulong_long_type, 10, false> type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_int_director<tag::long_long, IsLiteral>
|
||||
{
|
||||
typedef int_generator<IsLiteral, boost::long_long_type, 10, false> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign, bool IsLiteral>
|
||||
struct extract_int_director<int_tag<T, Radix, ForceSign>, IsLiteral>
|
||||
{
|
||||
typedef int_generator<IsLiteral, T, Radix, ForceSign> type;
|
||||
};
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign, bool IsLiteral>
|
||||
struct extract_int_director<uint_tag<T, Radix, ForceSign>, IsLiteral>
|
||||
{
|
||||
typedef uint_generator<IsLiteral, T, Radix, ForceSign> type;
|
||||
};
|
||||
|
||||
template <typename T, typename Unused>
|
||||
struct extract_int_director_lit
|
||||
: extract_int_director<T, true> {};
|
||||
|
||||
template <typename T>
|
||||
struct extract_int_director_plain
|
||||
: extract_int_director<T, false> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a floating point literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag>
|
||||
struct extract_literal_real_director;
|
||||
|
||||
template <>
|
||||
struct extract_literal_real_director<float>
|
||||
{
|
||||
typedef
|
||||
real_generator<true, float, real_generator_policies<float> >
|
||||
type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_real_director<double>
|
||||
{
|
||||
typedef
|
||||
real_generator<true, double, real_generator_policies<double> >
|
||||
type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_real_director<long double>
|
||||
{
|
||||
typedef
|
||||
real_generator<
|
||||
true, long double, real_generator_policies<long double>
|
||||
>
|
||||
type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a floating point tag
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, bool IsLiteral>
|
||||
struct extract_real_director;
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_real_director<tag::float_, IsLiteral>
|
||||
{
|
||||
typedef
|
||||
real_generator<IsLiteral, float, real_generator_policies<float> >
|
||||
type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_real_director<tag::double_, IsLiteral>
|
||||
{
|
||||
typedef
|
||||
real_generator<IsLiteral, double, real_generator_policies<double> >
|
||||
type;
|
||||
};
|
||||
|
||||
template <bool IsLiteral>
|
||||
struct extract_real_director<tag::long_double, IsLiteral>
|
||||
{
|
||||
typedef
|
||||
real_generator<
|
||||
IsLiteral, long double, real_generator_policies<long double>
|
||||
>
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename T, typename RealPolicies, bool IsLiteral>
|
||||
struct extract_real_director<real_tag<T, RealPolicies>, IsLiteral>
|
||||
{
|
||||
typedef real_generator<IsLiteral, T, RealPolicies> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename Unused>
|
||||
struct extract_real_director_lit
|
||||
: extract_real_director<Tag, true> {};
|
||||
|
||||
template <typename Tag>
|
||||
struct extract_real_director_plain
|
||||
: extract_real_director<Tag, false> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of an integer literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct extract_literal_int_director;
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<short>
|
||||
{
|
||||
typedef int_generator<true, short, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<unsigned short>
|
||||
{
|
||||
typedef uint_generator<true, unsigned short, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<int>
|
||||
{
|
||||
typedef int_generator<true, int, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<unsigned int>
|
||||
{
|
||||
typedef uint_generator<true, unsigned int, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<long>
|
||||
{
|
||||
typedef int_generator<true, long, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<unsigned long>
|
||||
{
|
||||
typedef uint_generator<true, unsigned long, 10, false> type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <>
|
||||
struct extract_literal_int_director<boost::ulong_long_type>
|
||||
{
|
||||
typedef int_generator<true, boost::ulong_long_type, 10, false> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_literal_int_director<boost::long_long_type>
|
||||
{
|
||||
typedef uint_generator<true, boost::long_long_type, 10, false> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// numeric parser meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// literals: 10, 10L, 10LL
|
||||
struct int_literal_meta_grammar
|
||||
: meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_int_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_literal_int_director<mpl::_> >
|
||||
>
|
||||
{};
|
||||
|
||||
// all the different integer's as int_, uint, bin, oct, dec, hex, etc.
|
||||
// and the corresponding int_(10), uint(10), etc.
|
||||
struct int_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_int_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_int_director_plain<mpl::_> >
|
||||
>,
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_int_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
int_literal_meta_grammar
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_int_director_lit<mpl::_, mpl::_> >
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
// floating point literals: 1.0, 1.0f, 10.1e2 etc.
|
||||
struct real_literal_meta_grammar
|
||||
: meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_real_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_literal_real_director<mpl::_> >
|
||||
>
|
||||
{};
|
||||
|
||||
struct real_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::compose_single<
|
||||
proto::if_<
|
||||
is_real_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_real_director_plain<mpl::_> >
|
||||
>,
|
||||
meta_grammar::compose_function1_full<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_real_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
real_literal_meta_grammar
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_real_director_lit<mpl::_, mpl::_> >
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct numeric_meta_grammar
|
||||
: proto::or_<
|
||||
int_meta_grammar,
|
||||
real_meta_grammar
|
||||
>
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the RD meta-grammar.
|
||||
// (see qi/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<Expr
|
||||
, typename enable_if<proto::matches<Expr, numeric_meta_grammar> >::type>
|
||||
: mpl::true_
|
||||
{};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<Expr
|
||||
, typename enable_if<proto::matches<Expr, numeric_meta_grammar> >::type>
|
||||
: mpl::identity<numeric_meta_grammar>
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
51
include/boost/spirit/home/karma/numeric/numeric_fwd.hpp
Normal file
51
include/boost/spirit/home/karma/numeric/numeric_fwd.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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_KARMA_NUMERIC_FWD_FEB_27_2007_1338PM)
|
||||
#define BOOST_SPIRIT_KARMA_NUMERIC_FWD_FEB_27_2007_1338PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <bool IsLiteral, typename T, unsigned Radix, bool ForceSign,
|
||||
typename Tag = unused_type>
|
||||
struct int_generator;
|
||||
|
||||
template <bool IsLiteral, typename T, unsigned Radix, bool ForceSign,
|
||||
typename Tag = unused_type>
|
||||
struct uint_generator;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T = int, unsigned Radix = 10, bool ForceSign = false>
|
||||
struct int_spec;
|
||||
|
||||
template <typename T = unsigned int, unsigned Radix = 10,
|
||||
bool ForceSign = false>
|
||||
struct uint_spec;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <bool IsLiteral, typename T, typename RealPolicies,
|
||||
typename Tag = unused_type>
|
||||
struct real_generator;
|
||||
|
||||
template <typename T>
|
||||
struct real_generator_policies;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T = double,
|
||||
typename RealPolicies = real_generator_policies<T> >
|
||||
struct real_spec;
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
246
include/boost/spirit/home/karma/numeric/real.hpp
Normal file
246
include/boost/spirit/home/karma/numeric/real.hpp
Normal file
@@ -0,0 +1,246 @@
|
||||
// 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_KARMA_REAL_FEB_26_2007_0512PM)
|
||||
#define BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/real_policies.hpp>
|
||||
#include <boost/spirit/home/karma/char.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/int.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename RealPolicies>
|
||||
struct real_policy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization is used for real generators not having a direct
|
||||
// initializer: float_, double_ etc. These generators must be used in
|
||||
// conjunction with a parameter.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename RealPolicies, typename Tag>
|
||||
struct real_generator<false, T, RealPolicies, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// double_/float_/etc. has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
RealPolicies const& p = detail::real_policy<RealPolicies>::get(
|
||||
fusion::at_c<0>(component.elements));
|
||||
bool result = real_inserter<T, RealPolicies, Tag>::
|
||||
call(sink, param, p);
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
// this double_/float_/etc. has no parameter attached, it needs to have
|
||||
// been initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, real_not_usable_without_parameter,
|
||||
(Component, Context));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "real number";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization is used for real generators having a direct
|
||||
// initializer: float_(10.), double_(20.) etc.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename RealPolicies, typename Tag>
|
||||
struct real_generator<true, T, RealPolicies, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
RealPolicies const& p = detail::real_policy<RealPolicies>::get(
|
||||
fusion::at_c<0>(component.elements));
|
||||
T n = fusion::at_c<1>(component.elements);
|
||||
bool result = real_inserter<T, RealPolicies, Tag>::call(sink, n, p);
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "real number";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case real generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, typename RealPolicies, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::real_generator<false, T, RealPolicies, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
real_policy_type;
|
||||
typedef fusion::vector<real_policy_type> vector_type;
|
||||
|
||||
typedef karma::real_generator<false, T, RealPolicies, key_tag> real_type;
|
||||
typedef component<karma::domain, real_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, typename RealPolicies, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::real_generator<true, T, RealPolicies, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
real_policy_type;
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 1>::type
|
||||
real_data_type;
|
||||
typedef fusion::vector<real_policy_type, real_data_type> vector_type;
|
||||
|
||||
typedef karma::real_generator<true, T, RealPolicies, key_tag> real_type;
|
||||
typedef component<karma::domain, real_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case real generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, typename RealPolicies, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::real_generator<false, T, RealPolicies, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
real_policy_type;
|
||||
typedef fusion::vector<real_policy_type> vector_type;
|
||||
|
||||
typedef karma::real_generator<false, T, RealPolicies, key_tag> real_type;
|
||||
typedef component<karma::domain, real_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, typename RealPolicies, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::real_generator<true, T, RealPolicies, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
real_policy_type;
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 1>::type
|
||||
real_data_type;
|
||||
typedef fusion::vector<real_policy_type, real_data_type> vector_type;
|
||||
|
||||
typedef karma::real_generator<true, T, RealPolicies, key_tag> real_type;
|
||||
typedef component<karma::domain, real_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
#endif // defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
|
||||
282
include/boost/spirit/home/karma/numeric/real_policies.hpp
Normal file
282
include/boost/spirit/home/karma/numeric/real_policies.hpp
Normal file
@@ -0,0 +1,282 @@
|
||||
// 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_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
|
||||
#define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/karma/generate.hpp>
|
||||
#include <boost/spirit/home/karma/char.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/int.hpp>
|
||||
#include <cmath>
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// real_generator_policies, if you need special handling of your floating
|
||||
// point numbers, just overload this policy class and use it as a template
|
||||
// parameter to the karma::real_spec floating point specifier:
|
||||
//
|
||||
// template <typename T>
|
||||
// struct scientific_policy : karma::real_generator_policies<T>
|
||||
// {
|
||||
// // we want the numbers always to be in scientific format
|
||||
// static int floatfield(T n) { return scientific; }
|
||||
// };
|
||||
//
|
||||
// typedef
|
||||
// karma::real_spec<double, scientific_policy<double> >
|
||||
// science_type;
|
||||
//
|
||||
// karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct real_generator_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Specifies, which representation type to use during output
|
||||
// generation.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
enum fmtflags
|
||||
{
|
||||
scientific = 0, // Generate floating-point values in scientific
|
||||
// format (with an exponent field).
|
||||
fixed = 1 // Generate floating-point values in fixed-point
|
||||
// format (with no exponent field).
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The default behavior is to not to require generating a sign. If
|
||||
// 'force_sign' is specified as true, then all generated numbers will
|
||||
// have a sign ('+' or '-', zeros will have a space instead of a sign)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static bool const force_sign = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The 'trailing_zeros' flag instructs the floating point generator to
|
||||
// emit trailing zeros up to the required precision digits.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static bool const trailing_zeros = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Decide, which representation type to use in the generated output.
|
||||
//
|
||||
// By default all numbers having an absolute value of zero or in
|
||||
// between 0.001 and 100000 will be generated using the fixed format,
|
||||
// all others will be generated using the scientific representation.
|
||||
//
|
||||
// The trailing_zeros flag can be used to force the output of trailing
|
||||
// zeros in the fractional part up to the number of digits returned by
|
||||
// the precision() member function. The default is not to generate
|
||||
// the trailing zeros.
|
||||
//
|
||||
// n The floating point number to output. This can be used to
|
||||
// adjust the formatting flags depending on the value of
|
||||
// this number.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static int
|
||||
floatfield(T n)
|
||||
{
|
||||
if (detail::is_zero(n))
|
||||
return fixed;
|
||||
|
||||
T abs_n = detail::absolute_value(n);
|
||||
return (abs_n >= 1e5 || abs_n < 1e-3) ? scientific : fixed;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The 'fractional_precision' constant specifies the default number of
|
||||
// digits to generate for the fractional part of a floating point
|
||||
// number. This is used by this (default) policies implementation
|
||||
// only. If you need another fractional precision you'll have to
|
||||
// overload the precision function below.
|
||||
//
|
||||
// Note: The actual number of digits for a floating point number is
|
||||
// determined by the precision() function below. This allows to
|
||||
// have different precisions depending on the value of the
|
||||
// floating point number.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static unsigned int const fractional_precision = 3;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Return the maximum number of decimal digits to generate in the
|
||||
// fractional part of the output.
|
||||
//
|
||||
// n The floating point number to output. This can be used to
|
||||
// adjust the required precision depending on the value of
|
||||
// this number. If the trailing zeros flag is specified the
|
||||
// fractional part of the output will be 'filled' with
|
||||
// zeros, if appropriate
|
||||
//
|
||||
// Note: If the trailing_zeros flag is not in effect additional
|
||||
// comments apply. See the comment for the fraction_part()
|
||||
// function below.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static unsigned int
|
||||
precision(T)
|
||||
{
|
||||
// generate max. 'fractional_precision' fractional digits
|
||||
return fractional_precision;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Generate the integer part of the number.
|
||||
//
|
||||
// sink The output iterator to use for generation
|
||||
// n The absolute value of the integer part of the floating
|
||||
// point number to convert (always non-negative).
|
||||
// sign The sign of the overall floating point number to convert.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <bool ForceSign, typename OutputIterator>
|
||||
static bool
|
||||
integer_part (OutputIterator& sink, T n, bool sign)
|
||||
{
|
||||
return sign_inserter<ForceSign>::call(
|
||||
sink, detail::is_zero(n), sign) &&
|
||||
int_inserter<10>::call(sink, n);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Generate the decimal point.
|
||||
//
|
||||
// sink The output iterator to use for generation
|
||||
// n The fractional part of the floating point number to
|
||||
// convert. Note that this number is scaled such, that
|
||||
// it represents the number of units which correspond
|
||||
// to the value returned from the precision() function
|
||||
// earlier. I.e. a fractional part of 0.01234 is
|
||||
// represented as 1234 when the 'Precision' is 5.
|
||||
//
|
||||
// This is given to allow to decide, whether a decimal point
|
||||
// has to be generated at all.
|
||||
//
|
||||
// Note: If the trailing_zeros flag is not in effect additional
|
||||
// comments apply. See the comment for the fraction_part()
|
||||
// function below.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
dot (OutputIterator& sink, T)
|
||||
{
|
||||
return char_inserter<>::call(sink, '.'); // generate the dot by default
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Generate the fractional part of the number.
|
||||
//
|
||||
// sink The output iterator to use for generation
|
||||
// n The fractional part of the floating point number to
|
||||
// convert. This number is scaled such, that it represents
|
||||
// the number of units which correspond to the 'Precision'.
|
||||
// I.e. a fractional part of 0.01234 is represented as 1234
|
||||
// when the 'precision_' parameter is 5.
|
||||
//
|
||||
// Note: If the trailing_zeros flag is not returned from the
|
||||
// floatfield() function, the 'precision_' parameter will have
|
||||
// been corrected from the value the precision() function
|
||||
// returned earlier (defining the maximal number of fractional
|
||||
// digits) in the sense, that it takes into account trailing
|
||||
// zeros. I.e. a floating point number 0.0123 and a value of 5
|
||||
// returned from precision() will result in:
|
||||
//
|
||||
// trailing_zeros is not specified:
|
||||
// n 123
|
||||
// precision_ 4
|
||||
//
|
||||
// trailing_zeros is specified:
|
||||
// n 1230
|
||||
// precision_ 5
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator>
|
||||
static bool
|
||||
fraction_part (OutputIterator& sink, T n, unsigned precision_)
|
||||
{
|
||||
// allow for ADL to find the correct overload for floor and log10
|
||||
using namespace std;
|
||||
|
||||
// The following is equivalent to:
|
||||
// generate(sink, right_align(precision, '0')[ulong], n);
|
||||
// but it's spelled out to avoid inter-modular dependencies.
|
||||
|
||||
T digits = (detail::is_zero(n) ? 0 : floor(log10(n))) + 1;
|
||||
bool r = true;
|
||||
for (/**/; r && digits < precision_; digits = digits + 1)
|
||||
r = char_inserter<>::call(sink, '0');
|
||||
return r && int_inserter<10>::call(sink, n);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Generate the exponential part of the number (this is called only
|
||||
// if the floatfield() function returned the 'scientific' flag).
|
||||
//
|
||||
// sink The output iterator to use for generation
|
||||
// n The (signed) exponential part of the floating point
|
||||
// number to convert.
|
||||
//
|
||||
// The Tag template parameter is either of the type unused_type or
|
||||
// describes the character class and conversion to be applied to any
|
||||
// output possibly influenced by either the lower[...] or upper[...]
|
||||
// directives.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename OutputIterator>
|
||||
static bool
|
||||
exponent (OutputIterator& sink, T n)
|
||||
{
|
||||
T abs_n = detail::absolute_value(n);
|
||||
bool r = char_inserter<Tag>::call(sink, 'e') &&
|
||||
sign_inserter<false>::call(
|
||||
sink, detail::is_zero(n), detail::is_negative(n));
|
||||
|
||||
// the C99 Standard requires at least two digits in the exponent
|
||||
if (r && abs_n < 10)
|
||||
r = char_inserter<Tag>::call(sink, '0');
|
||||
return r && int_inserter<10>::call(sink, abs_n);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Print the textual representations for non-normal floats (NaN and
|
||||
// Inf)
|
||||
//
|
||||
// sink The output iterator to use for generation
|
||||
// n The (signed) floating point number to convert.
|
||||
//
|
||||
// The Tag template parameter is either of the type unused_type or
|
||||
// describes the character class and conversion to be applied to any
|
||||
// output possibly influenced by either the lower[...] or upper[...]
|
||||
// directives.
|
||||
//
|
||||
// Note: These functions get called only if fpclassify() returned
|
||||
// FP_INFINITY or FP_NAN.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <bool ForceSign, typename Tag, typename OutputIterator>
|
||||
static bool
|
||||
nan (OutputIterator& sink, T n)
|
||||
{
|
||||
return sign_inserter<ForceSign>::call(
|
||||
sink, false, detail::is_negative(n)) &&
|
||||
string_inserter<Tag>::call(sink, "nan");
|
||||
}
|
||||
|
||||
template <bool ForceSign, typename Tag, typename OutputIterator>
|
||||
static bool
|
||||
inf (OutputIterator& sink, T n)
|
||||
{
|
||||
return sign_inserter<ForceSign>::call(
|
||||
sink, false, detail::is_negative(n)) &&
|
||||
string_inserter<Tag>::call(sink, "inf");
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
|
||||
224
include/boost/spirit/home/karma/numeric/uint.hpp
Normal file
224
include/boost/spirit/home/karma/numeric/uint.hpp
Normal file
@@ -0,0 +1,224 @@
|
||||
// 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_KARMA_UINT_FEB_23_2007_0840PM)
|
||||
#define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/numeric_fwd.hpp>
|
||||
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct uint_generator<false, T, Radix, ForceSign, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// check template parameter 'Radix' for validity
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
|
||||
not_supported_radix, ());
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(!std::numeric_limits<T>::is_signed,
|
||||
signed_unsigned_mismatch, ());
|
||||
|
||||
// uint has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
bool result = int_inserter<Radix, Tag>::call(sink, param);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
// this uint has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, uint_not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "unsigned integer";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct uint_generator<true, T, Radix, ForceSign, Tag>
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// check template parameter 'Radix' for validity
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
|
||||
not_supported_radix, ());
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(!std::numeric_limits<T>::is_signed,
|
||||
signed_unsigned_mismatch, ());
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
T n = fusion::at_c<0>(component.elements);
|
||||
bool result = int_inserter<Radix, Tag>::call(sink, n);
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "unsigned integer";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case int_ generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::uint_generator<false, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef karma::uint_generator<false, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, fusion::nil> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::uint_generator<true, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
int_data_type;
|
||||
typedef fusion::vector<int_data_type> vector_type;
|
||||
|
||||
typedef karma::uint_generator<true, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// upper_case int_ generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::uint_generator<false, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef karma::uint_generator<false, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, fusion::nil> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename T, unsigned Radix, bool ForceSign, typename Tag>
|
||||
struct make_modified_component<
|
||||
Domain, karma::uint_generator<true, T, Radix, ForceSign, Tag>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<Elements, 0>::type
|
||||
int_data_type;
|
||||
typedef fusion::vector<int_data_type> vector_type;
|
||||
|
||||
typedef karma::uint_generator<true, T, Radix, ForceSign, key_tag> int_type;
|
||||
typedef component<karma::domain, int_type, vector_type> type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
return type(elements);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
#endif
|
||||
21
include/boost/spirit/home/karma/operator.hpp
Normal file
21
include/boost/spirit/home/karma/operator.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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_KARMA_OPERATOR_FEB_28_2007_0351PM)
|
||||
#define BOOST_SPIRIT_KARMA_OPERATOR_FEB_28_2007_0351PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/operator/sequence.hpp>
|
||||
#include <boost/spirit/home/karma/operator/alternative.hpp>
|
||||
#include <boost/spirit/home/karma/operator/kleene.hpp>
|
||||
#include <boost/spirit/home/karma/operator/plus.hpp>
|
||||
#include <boost/spirit/home/karma/operator/optional.hpp>
|
||||
#include <boost/spirit/home/karma/operator/list.hpp>
|
||||
#include <boost/spirit/home/karma/operator/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
90
include/boost/spirit/home/karma/operator/alternative.hpp
Normal file
90
include/boost/spirit/home/karma/operator/alternative.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_ALTERNATIVE_MAR_01_2007_1117AM)
|
||||
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/operator/detail/alternative.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
#include <boost/spirit/home/support/as_variant.hpp>
|
||||
#include <boost/spirit/home/support/detail/what_function.hpp>
|
||||
#include <boost/spirit/home/support/algorithm/any.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct alternative
|
||||
{
|
||||
template <typename T>
|
||||
struct transform_child : mpl::identity<T> {};
|
||||
|
||||
template <typename All, typename Filtered>
|
||||
struct build_container
|
||||
{
|
||||
// Ok, now make a variant over the attribute_sequence. It's
|
||||
// a pity that make_variant_over does not support forward MPL
|
||||
// sequences. We use our own conversion metaprogram (as_variant).
|
||||
typedef typename
|
||||
as_variant<Filtered>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_fusion_sequence<alternative, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef detail::alternative_generate_functor<
|
||||
Component, OutputIterator, Context, Delimiter, Parameter>
|
||||
functor;
|
||||
|
||||
functor f(component, sink, ctx, d, param);
|
||||
return boost::apply_visitor(f, param);
|
||||
}
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, unused_type)
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 0>::type
|
||||
child_component_type;
|
||||
|
||||
typedef typename child_component_type::director director;
|
||||
return director::generate(
|
||||
fusion::at_c<0>(component.elements),
|
||||
sink, ctx, d, unused);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "alternatives[";
|
||||
fusion::for_each(component.elements,
|
||||
spirit::detail::what_function(result));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
118
include/boost/spirit/home/karma/operator/detail/alternative.hpp
Normal file
118
include/boost/spirit/home/karma/operator/detail/alternative.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
|
||||
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
struct alternative_generate_functor
|
||||
{
|
||||
typedef bool result_type; // to satisfy boost::variant visition
|
||||
|
||||
template <typename Attribute, typename Got>
|
||||
struct compute_is_compatible
|
||||
{
|
||||
typedef typename
|
||||
Attribute::types
|
||||
types; // mpl sequence of types in the variant
|
||||
|
||||
typedef typename
|
||||
mpl::begin<types>::type
|
||||
begin; // iterator to the first element
|
||||
|
||||
typedef typename
|
||||
mpl::end<types>::type
|
||||
end; // iterator to the last element
|
||||
|
||||
typedef typename
|
||||
mpl::find_if<
|
||||
types,
|
||||
is_same<mpl::_1, Got> // $$$ fix this
|
||||
>::type
|
||||
iter;
|
||||
|
||||
typedef typename mpl::distance<begin, iter>::type index;
|
||||
typedef typename mpl::not_<is_same<iter, end> >::type type;
|
||||
enum { value = type::value };
|
||||
};
|
||||
|
||||
template <typename Got>
|
||||
struct compute_is_compatible<unused_type, Got> : mpl::false_ {};
|
||||
|
||||
template <typename Attribute, typename Component_, typename Context_>
|
||||
struct is_compatible :
|
||||
compute_is_compatible<
|
||||
typename traits::attribute_of<
|
||||
karma::domain, Component_, Context_>::type,
|
||||
Attribute>
|
||||
{
|
||||
};
|
||||
|
||||
alternative_generate_functor(Component const& component_,
|
||||
OutputIterator& sink_, Context& ctx_,
|
||||
Delimiter const& d, Parameter const& p)
|
||||
: component(component_), sink(sink_), ctx(ctx_), delim(d), param(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool call(Attribute const& actual_attribute, mpl::true_) const
|
||||
{
|
||||
typedef is_compatible<Attribute, Component, Context> is_compatible;
|
||||
typedef typename is_compatible::index index;
|
||||
typedef typename Component::elements_type elements;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at<elements, index>::type
|
||||
child_component_type;
|
||||
|
||||
typedef typename child_component_type::director director;
|
||||
return director::generate(
|
||||
fusion::at<index>(component.elements),
|
||||
sink, ctx, delim, actual_attribute);
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool call(Attribute const&, mpl::false_) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool operator()(Attribute const& actual_attribute) const
|
||||
{
|
||||
typedef mpl::bool_<
|
||||
is_compatible<Attribute, Component, Context>::value>
|
||||
is_compatible;
|
||||
|
||||
return call(actual_attribute, is_compatible());
|
||||
}
|
||||
|
||||
Component const& component;
|
||||
OutputIterator& sink;
|
||||
Context& ctx;
|
||||
Delimiter const& delim;
|
||||
Parameter const& param;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
50
include/boost/spirit/home/karma/operator/detail/sequence.hpp
Normal file
50
include/boost/spirit/home/karma/operator/detail/sequence.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_SEQUENCE_FEB_28_2007_0249PM)
|
||||
#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0249PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
template <typename OutputIterator, typename Context, typename Delimiter>
|
||||
struct sequence_generate
|
||||
{
|
||||
sequence_generate(OutputIterator& sink_, Context& context_,
|
||||
Delimiter const& delim_)
|
||||
: sink(sink_), ctx(context_), delim(delim_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Component, typename Parameter>
|
||||
bool operator()(Component const& component, Parameter& p)
|
||||
{
|
||||
// return true if any of the generators fail
|
||||
typedef typename Component::director director;
|
||||
return !director::generate(component, sink, ctx, delim, p);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
bool operator()(Component const& component)
|
||||
{
|
||||
// return true if any of the generators fail
|
||||
typedef typename Component::director director;
|
||||
return !director::generate(component, sink, ctx, delim, unused);
|
||||
}
|
||||
|
||||
OutputIterator& sink;
|
||||
Context& ctx;
|
||||
Delimiter const& delim;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::spirit::karma::detail
|
||||
|
||||
#endif
|
||||
BIN
include/boost/spirit/home/karma/operator/karma-alt.zip
Normal file
BIN
include/boost/spirit/home/karma/operator/karma-alt.zip
Normal file
Binary file not shown.
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2001-2007 Hartmut Kaiser
|
||||
// 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_KARMA_ALTERNATIVE_MAR_01_2007_1117AM)
|
||||
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/operator/detail/alternative.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
#include <boost/spirit/home/support/as_variant.hpp>
|
||||
#include <boost/spirit/home/support/detail/what_function.hpp>
|
||||
#include <boost/spirit/home/support/algorithm/any.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct alternative
|
||||
{
|
||||
template <typename T>
|
||||
struct transform_child : mpl::identity<T> {};
|
||||
|
||||
template <typename All, typename Filtered>
|
||||
struct build_container
|
||||
{
|
||||
// Ok, now make a variant over the attribute_sequence. It's
|
||||
// a pity that make_variant_over does not support forward MPL
|
||||
// sequences. We use our own conversion metaprogram (as_variant).
|
||||
typedef typename
|
||||
as_variant<Filtered>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_fusion_sequence<alternative, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef detail::alternative_generate_functor<
|
||||
Component, OutputIterator, Context, Delimiter, Parameter>
|
||||
functor;
|
||||
|
||||
functor f(component, sink, ctx, d, param);
|
||||
return boost::apply_visitor(f, param);
|
||||
}
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, unused_type)
|
||||
{
|
||||
typedef typename
|
||||
fusion::result_of::value_at_c<
|
||||
typename Component::elements_type, 0>::type
|
||||
child_component_type;
|
||||
|
||||
typedef typename child_component_type::director director;
|
||||
return director::generate(
|
||||
fusion::at_c<0>(component.elements),
|
||||
sink, ctx, d, unused);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "alternatives[";
|
||||
fusion::for_each(component.elements,
|
||||
spirit::detail::what_function(result));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2001-2007 Hartmut Kaiser
|
||||
// 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_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
|
||||
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/attribute_of.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
struct alternative_generate_functor
|
||||
{
|
||||
typedef bool result_type; // to satisfy boost::variant visition
|
||||
|
||||
template <typename Attribute, typename Got>
|
||||
struct compute_is_compatible
|
||||
{
|
||||
typedef typename
|
||||
Attribute::types
|
||||
types; // mpl sequence of types in the variant
|
||||
|
||||
typedef typename
|
||||
mpl::begin<types>::type
|
||||
begin; // iterator to the first element
|
||||
|
||||
typedef typename
|
||||
mpl::end<types>::type
|
||||
end; // iterator to the last element
|
||||
|
||||
typedef typename
|
||||
mpl::find_if<
|
||||
types,
|
||||
is_same<mpl::_1, Got> // $$$ fix this
|
||||
>::type
|
||||
iter;
|
||||
|
||||
typedef typename mpl::distance<begin, iter>::type index;
|
||||
typedef typename mpl::not_<is_same<iter, end> >::type type;
|
||||
enum { value = type::value };
|
||||
};
|
||||
|
||||
template <typename Got>
|
||||
struct compute_is_compatible<unused_type, Got> : mpl::false_ {};
|
||||
|
||||
template <typename Attribute, typename Component_, typename Context_>
|
||||
struct is_compatible :
|
||||
compute_is_compatible<
|
||||
typename traits::attribute_of<
|
||||
karma::domain, Component_, Context_>::type,
|
||||
Attribute>
|
||||
{
|
||||
};
|
||||
|
||||
alternative_generate_functor(Component const& component_,
|
||||
OutputIterator& sink_, Context& ctx_,
|
||||
Delimiter const& d, Parameter const& p)
|
||||
: component(component_), sink(sink_), ctx(ctx_), delim(d), param(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool call(Attribute const& actual_attribute, mpl::true_) const
|
||||
{
|
||||
typedef is_compatible<Attribute, Component, Context> is_compatible;
|
||||
typedef typename is_compatible::index index;
|
||||
typedef typename Component::elements_type elements;
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::value_at<elements, index>::type
|
||||
child_component_type;
|
||||
|
||||
typedef typename child_component_type::director director;
|
||||
return director::generate(
|
||||
fusion::at<index>(component.elements),
|
||||
sink, ctx, delim, actual_attribute);
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool call(Attribute const& actual_attribute, mpl::false_) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
bool operator()(Attribute const& actual_attribute) const
|
||||
{
|
||||
typedef mpl::bool_<
|
||||
is_compatible<Attribute, Component, Context>::value>
|
||||
is_compatible;
|
||||
|
||||
return call(actual_attribute, is_compatible());
|
||||
}
|
||||
|
||||
Component const& component;
|
||||
OutputIterator& sink;
|
||||
Context& ctx;
|
||||
Delimiter const& delim;
|
||||
Parameter const& param;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
92
include/boost/spirit/home/karma/operator/kleene.hpp
Normal file
92
include/boost/spirit/home/karma/operator/kleene.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_KLEENE_MAR_03_2007_0337AM)
|
||||
#define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/container.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct kleene
|
||||
{
|
||||
template <typename T>
|
||||
struct build_attribute_container
|
||||
{
|
||||
typedef std::vector<T> type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_container<kleene, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type::director
|
||||
director;
|
||||
typedef typename
|
||||
container::result_of::iterator<Parameter const>::type
|
||||
iterator_type;
|
||||
|
||||
iterator_type it = container::begin(param);
|
||||
iterator_type end = container::end(param);
|
||||
|
||||
// kleene fails only if the embedded parser fails
|
||||
bool result = true;
|
||||
for (/**/; result && !container::compare(it, end);
|
||||
container::next(it))
|
||||
{
|
||||
result = director::generate(subject(component), sink, ctx, d,
|
||||
container::deref(it));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// this kleene has no parameter attached
|
||||
// template <typename Component, typename OutputIterator,
|
||||
// typename Context, typename Delimiter>
|
||||
// static bool
|
||||
// generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
// unused_type)
|
||||
// {
|
||||
// BOOST_MPL_ASSERT_MSG(false, kleene_not_usable_without_parameter, ());
|
||||
// return false;
|
||||
// }
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "kleene[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
96
include/boost/spirit/home/karma/operator/list.hpp
Normal file
96
include/boost/spirit/home/karma/operator/list.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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(SPIRIT_KARMA_LIST_MAY_01_2007_0229PM)
|
||||
#define SPIRIT_KARMA_LIST_MAY_01_2007_0229PM
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/container.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct list
|
||||
{
|
||||
template <typename T>
|
||||
struct build_attribute_container
|
||||
{
|
||||
typedef std::vector<T> type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_container<list, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
spirit::result_of::left<Component>::type::director
|
||||
ldirector;
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::right<Component>::type::director
|
||||
rdirector;
|
||||
|
||||
typedef typename
|
||||
container::result_of::iterator<Parameter const>::type
|
||||
iterator_type;
|
||||
|
||||
iterator_type it = container::begin(param);
|
||||
iterator_type end = container::end(param);
|
||||
|
||||
bool result = !container::compare(it, end);
|
||||
if (result && ldirector::generate(
|
||||
spirit::left(component), sink, ctx, d, container::deref(it)))
|
||||
{
|
||||
for (container::next(it); result && !container::compare(it, end);
|
||||
container::next(it))
|
||||
{
|
||||
result =
|
||||
rdirector::generate(
|
||||
spirit::right(component), sink, ctx, d, unused) &&
|
||||
ldirector::generate(
|
||||
spirit::left(component), sink, ctx, d, container::deref(it));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "list[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::left<Component>::type::director
|
||||
ldirector;
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::right<Component>::type::director
|
||||
rdirector;
|
||||
|
||||
result += ldirector::what(spirit::left(component));
|
||||
result += ", ";
|
||||
result += rdirector::what(spirit::right(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
113
include/boost/spirit/home/karma/operator/meta_grammar.hpp
Normal file
113
include/boost/spirit/home/karma/operator/meta_grammar.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// 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_KARMA_META_GRAMMAR_FEB_28_2007_0346PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_28_2007_0346PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct sequence;
|
||||
struct alternative;
|
||||
struct kleene;
|
||||
struct plus;
|
||||
struct optional;
|
||||
struct list;
|
||||
|
||||
struct main_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// operator meta-grammars
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct sequence_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::binary_rule_flat<
|
||||
karma::domain, proto::tag::shift_left, sequence,
|
||||
main_meta_grammar
|
||||
>,
|
||||
meta_grammar::binary_rule_flat<
|
||||
karma::domain, proto::tag::plus, sequence,
|
||||
main_meta_grammar
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct alternative_meta_grammar
|
||||
: meta_grammar::binary_rule_flat<
|
||||
karma::domain, proto::tag::bitwise_or, alternative,
|
||||
main_meta_grammar
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct repeat_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::unary_rule<
|
||||
karma::domain, proto::tag::dereference, kleene,
|
||||
main_meta_grammar
|
||||
>,
|
||||
meta_grammar::unary_rule<
|
||||
karma::domain, proto::tag::negate, optional,
|
||||
main_meta_grammar
|
||||
>,
|
||||
meta_grammar::unary_rule<
|
||||
karma::domain, proto::tag::posit, plus,
|
||||
main_meta_grammar
|
||||
>,
|
||||
meta_grammar::binary_rule<
|
||||
karma::domain, proto::tag::modulus, list,
|
||||
main_meta_grammar, main_meta_grammar
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct operator_meta_grammar
|
||||
: proto::or_<
|
||||
sequence_meta_grammar,
|
||||
alternative_meta_grammar,
|
||||
repeat_meta_grammar
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<Expr
|
||||
, typename enable_if<proto::matches<Expr, operator_meta_grammar> >::type>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<Expr
|
||||
, typename enable_if<proto::matches<Expr, operator_meta_grammar> >::type>
|
||||
: mpl::identity<operator_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
99
include/boost/spirit/home/karma/operator/optional.hpp
Normal file
99
include/boost/spirit/home/karma/operator/optional.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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(SPIRIT_KARMA_OPTIONAL_MARCH_31_2007_0852AM)
|
||||
#define SPIRIT_KARMA_OPTIONAL_MARCH_31_2007_0852AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Parameter>
|
||||
inline bool
|
||||
optional_is_valid(boost::optional<Parameter> const& opt)
|
||||
{
|
||||
return opt;
|
||||
}
|
||||
|
||||
inline bool
|
||||
optional_is_valid(unused_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Parameter>
|
||||
inline Parameter const&
|
||||
optional_get(boost::optional<Parameter> const& opt)
|
||||
{
|
||||
return get(opt) ;
|
||||
}
|
||||
|
||||
inline unused_type
|
||||
optional_get(unused_type)
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
}
|
||||
|
||||
struct optional
|
||||
{
|
||||
template <typename T>
|
||||
struct build_attribute_container
|
||||
{
|
||||
typedef boost::optional<T> type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_container<optional, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
if (detail::optional_is_valid(param))
|
||||
{
|
||||
director::generate(subject(component), sink, ctx, d,
|
||||
detail::optional_get(param));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "optional[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
95
include/boost/spirit/home/karma/operator/plus.hpp
Normal file
95
include/boost/spirit/home/karma/operator/plus.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_KARMA_POSITIVE_MAR_03_2007_0945PM)
|
||||
#define BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
#include <boost/spirit/home/support/detail/container.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct plus
|
||||
{
|
||||
template <typename T>
|
||||
struct build_attribute_container
|
||||
{
|
||||
typedef std::vector<T> type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_container<plus, Component, Iterator, Context>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
typedef typename
|
||||
container::result_of::iterator<Parameter const>::type
|
||||
iterator_type;
|
||||
|
||||
iterator_type it = container::begin(param);
|
||||
iterator_type end = container::end(param);
|
||||
|
||||
// plus fails if the parameter is empty
|
||||
if (it == end)
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
for (/**/; result && !container::compare(it, end);
|
||||
container::next(it))
|
||||
{
|
||||
result = director::generate(spirit::subject(component), sink,
|
||||
ctx, d, container::deref(it));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// this kleene has no parameter attached
|
||||
// template <typename Component, typename OutputIterator,
|
||||
// typename Context, typename Delimiter>
|
||||
// static bool
|
||||
// generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
// unused_type)
|
||||
// {
|
||||
// BOOST_MPL_ASSERT_MSG(false, plus_not_usable_without_parameter, ());
|
||||
// return false;
|
||||
// }
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "plus[";
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::subject<Component>::type::director
|
||||
director;
|
||||
|
||||
result += director::what(spirit::subject(component));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
89
include/boost/spirit/home/karma/operator/sequence.hpp
Normal file
89
include/boost/spirit/home/karma/operator/sequence.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_KARMA_SEQUENCE_FEB_28_2007_0247PM)
|
||||
#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0247PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/operator/detail/sequence.hpp>
|
||||
#include <boost/spirit/home/support/attribute_transform.hpp>
|
||||
#include <boost/spirit/home/support/detail/what_function.hpp>
|
||||
#include <boost/spirit/home/support/algorithm/any_if.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/transform.hpp>
|
||||
#include <boost/fusion/include/filter_if.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
struct sequence
|
||||
{
|
||||
template <typename T>
|
||||
struct transform_child : mpl::identity<T> {};
|
||||
|
||||
template <typename All, typename Filtered>
|
||||
struct build_container
|
||||
{
|
||||
typedef
|
||||
typename fusion::result_of::as_vector<Filtered>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute :
|
||||
build_fusion_sequence<
|
||||
sequence, Component, Iterator, Context
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
struct attribute_not_unused
|
||||
{
|
||||
template <typename Component>
|
||||
struct apply
|
||||
: spirit::traits::is_not_unused<typename
|
||||
traits::attribute_of<karma::domain, Component, Context>::type>
|
||||
{};
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
detail::sequence_generate<OutputIterator, Context, Delimiter>
|
||||
f (sink, ctx, d);
|
||||
|
||||
typedef attribute_not_unused<Context> predicate;
|
||||
|
||||
// f returns true if *any* of the generators fail
|
||||
return !spirit::any_if(component.elements, param, f, predicate());
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
std::string result = "sequence[";
|
||||
fusion::for_each(component.elements,
|
||||
spirit::detail::what_function(result));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
#endif
|
||||
17
include/boost/spirit/home/karma/stream.hpp
Normal file
17
include/boost/spirit/home/karma/stream.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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_KARMA_STREAM_MAY_01_2007_1254AM)
|
||||
#define BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_1254AM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/stream/format_manip.hpp>
|
||||
#include <boost/spirit/home/karma/stream/stream.hpp>
|
||||
#include <boost/spirit/home/karma/stream/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM)
|
||||
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <boost/spirit/home/karma/detail/ostream_iterator.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Expr,
|
||||
typename Parameter = unused_type,
|
||||
typename Delimiter = unused_type
|
||||
>
|
||||
struct format_manip
|
||||
{
|
||||
format_manip(Expr const& xpr, Parameter const& p, Delimiter const& d)
|
||||
: expr(xpr), param(p), delim(d)
|
||||
{}
|
||||
|
||||
Expr const& expr;
|
||||
Parameter const& param;
|
||||
Delimiter const& delim;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename Char, typename Traits, typename Expr>
|
||||
inline std::basic_ostream<Char, Traits> &
|
||||
operator<< (std::basic_ostream<Char, Traits> &os,
|
||||
format_manip<Expr> const& fm)
|
||||
{
|
||||
ostream_iterator<Char, Char, Traits> sink(os);
|
||||
if (!karma::generate (sink, fm.expr))
|
||||
{
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename Char, typename Traits, typename Expr, typename Parameter>
|
||||
inline std::basic_ostream<Char, Traits> &
|
||||
operator<< (std::basic_ostream<Char, Traits> &os,
|
||||
format_manip<Expr, Parameter> const& fm)
|
||||
{
|
||||
ostream_iterator<Char, Char, Traits> sink(os);
|
||||
if (!karma::generate(sink, fm.expr, fm.param))
|
||||
{
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename Char, typename Traits, typename Expr, typename Delimiter>
|
||||
inline std::basic_ostream<Char, Traits> &
|
||||
operator<< (std::basic_ostream<Char, Traits> &os,
|
||||
format_manip<Expr, unused_type, Delimiter> const& fm)
|
||||
{
|
||||
ostream_iterator<Char, Char, Traits> sink(os);
|
||||
if (!karma::generate_delimited(sink, fm.expr, fm.delim))
|
||||
{
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<
|
||||
typename Char, typename Traits,
|
||||
typename Expr, typename Parameter, typename Delimiter
|
||||
>
|
||||
inline std::basic_ostream<Char, Traits> &
|
||||
operator<< (
|
||||
std::basic_ostream<Char, Traits> &os,
|
||||
format_manip<Expr, Parameter, Delimiter> const& fm)
|
||||
{
|
||||
ostream_iterator<Char, Char, Traits> sink(os);
|
||||
if (!karma::generate_delimited(sink, fm.expr, fm.param, fm.delim))
|
||||
{
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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.boist.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_ITERATOR_OSTREAM_MAY_27_2007_0133PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_OSTREAM_MAY_27_2007_0133PM
|
||||
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Char>
|
||||
struct iterator_sink
|
||||
{
|
||||
typedef boost::iostreams::sink_tag category;
|
||||
typedef Char char_type;
|
||||
|
||||
iterator_sink (OutputIterator& sink_)
|
||||
: sink(sink_)
|
||||
{}
|
||||
|
||||
// Write up to n characters from the buffer s to the output sequence,
|
||||
// returning the number of characters written
|
||||
std::streamsize write (Char const* s, std::streamsize n)
|
||||
{
|
||||
std::streamsize bytes_written = 0;
|
||||
while (n--) {
|
||||
*sink = *s;
|
||||
++sink; ++s; ++bytes_written;
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
OutputIterator& sink;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
113
include/boost/spirit/home/karma/stream/format_manip.hpp
Normal file
113
include/boost/spirit/home/karma/stream/format_manip.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// 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_KARMA_FORMAT_MANIP_MAY_01_2007_1211PM)
|
||||
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_01_2007_1211PM
|
||||
|
||||
#include <boost/spirit/home/karma/generate.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/karma/stream/detail/format_manip.hpp>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
inline detail::format_manip<Expr>
|
||||
format(Expr const& xpr)
|
||||
{
|
||||
typedef spirit::traits::is_component<karma::domain, Expr> is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, (Expr));
|
||||
|
||||
return karma::detail::format_manip<Expr>(xpr, unused, unused);
|
||||
}
|
||||
|
||||
template <typename Expr, typename Parameter>
|
||||
inline detail::format_manip<Expr, Parameter>
|
||||
format(Expr const& xpr, Parameter const& p)
|
||||
{
|
||||
typedef spirit::traits::is_component<karma::domain, Expr> is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, (Expr, Parameter));
|
||||
|
||||
return karma::detail::format_manip<Expr, Parameter>(xpr, p, unused);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr, typename Delimiter>
|
||||
inline detail::format_manip<Expr, unused_type, Delimiter>
|
||||
format_delimited(Expr const& xpr, Delimiter const& d)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
expr_is_component;
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Delimiter>
|
||||
delimiter_is_component;
|
||||
|
||||
// report invalid expression errors as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(expr_is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, (Expr, Delimiter));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(delimiter_is_component::value,
|
||||
delimiter_is_not_convertible_to_a_generator, (Expr, Delimiter));
|
||||
|
||||
return karma::detail::format_manip<Expr, unused_type, Delimiter>(
|
||||
xpr, unused, d);
|
||||
}
|
||||
|
||||
template <typename Expr, typename Parameter, typename Delimiter>
|
||||
inline detail::format_manip<Expr, Parameter, Delimiter>
|
||||
format_delimited(Expr const& xpr, Parameter const& p, Delimiter const& d)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Expr>
|
||||
expr_is_component;
|
||||
typedef
|
||||
spirit::traits::is_component<karma::domain, Delimiter>
|
||||
delimiter_is_component;
|
||||
|
||||
// report invalid expression errors as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(expr_is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator,
|
||||
(Expr, Parameter, Delimiter));
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(delimiter_is_component::value,
|
||||
delimiter_is_not_convertible_to_a_generator,
|
||||
(Expr, Parameter, Delimiter));
|
||||
|
||||
return karma::detail::format_manip<Expr, Parameter, Delimiter>(
|
||||
xpr, p, d);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename Char, typename Traits, typename Expr>
|
||||
inline typename
|
||||
enable_if<
|
||||
spirit::traits::is_component<karma::domain, Expr>,
|
||||
std::basic_ostream<Char, Traits> &
|
||||
>::type
|
||||
operator<< (std::basic_ostream<Char, Traits> &os, Expr const& xpr)
|
||||
{
|
||||
karma::detail::ostream_iterator<Char, Char, Traits> sink(os);
|
||||
if (!karma::generate (sink, xpr))
|
||||
{
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
126
include/boost/spirit/home/karma/stream/meta_grammar.hpp
Normal file
126
include/boost/spirit/home/karma/stream/meta_grammar.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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_KARMA_META_GRAMMAR_MAY_01_2007_0313PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_MAY_01_2007_0313PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct any_stream;
|
||||
|
||||
template <typename Char>
|
||||
struct stream_director;
|
||||
|
||||
struct main_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director for a stream
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag>
|
||||
struct extract_any_stream_director;
|
||||
|
||||
template <>
|
||||
struct extract_any_stream_director<tag::stream>
|
||||
{
|
||||
typedef any_stream<char> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_any_stream_director<tag::wstream>
|
||||
{
|
||||
typedef any_stream<wchar_t> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename T>
|
||||
struct extract_stream_director;
|
||||
|
||||
template <typename T>
|
||||
struct extract_stream_director<tag::stream, T>
|
||||
{
|
||||
typedef stream_director<char> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_stream_director<tag::wstream, T>
|
||||
{
|
||||
typedef stream_director<wchar_t> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// utility meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct utility_meta_grammar
|
||||
: proto::or_<
|
||||
// stream, wstream
|
||||
meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_stream_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_any_stream_director<mpl::_> >
|
||||
>,
|
||||
// stream(T), wstream(T)
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_stream_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
proto::_
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_stream_director<mpl::_, mpl::_> >
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hook into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, utility_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, utility_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<utility_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
190
include/boost/spirit/home/karma/stream/stream.hpp
Normal file
190
include/boost/spirit/home/karma/stream/stream.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
// 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_KARMA_STREAM_MAY_01_2007_0310PM)
|
||||
#define BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_0310PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/stream/detail/format_manip.hpp>
|
||||
#include <boost/spirit/home/karma/stream/detail/iterator_ostream.hpp>
|
||||
#include <boost/spirit/home/support/detail/hold_any.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// overload the streaming operators for the unused_type
|
||||
template <typename Char, typename Traits>
|
||||
inline std::basic_ostream<Char, Traits>&
|
||||
operator<< (std::basic_ostream<Char, Traits>& os, unused_type)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename Char>
|
||||
struct any_stream
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef spirit::hold_any type;
|
||||
};
|
||||
|
||||
// any_stream has a parameter attached
|
||||
|
||||
// this overload will be used in the normal case (not called from
|
||||
// format_manip).
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef
|
||||
karma::detail::iterator_sink<OutputIterator, Char>
|
||||
sink_device;
|
||||
|
||||
iostreams::stream<sink_device> ostr(sink);
|
||||
ostr << param << std::flush; // use existing operator<<()
|
||||
|
||||
if (ostr.good()) {
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is a special overload to detect if the output iterator has been
|
||||
// generated by a format_manip object.
|
||||
template <
|
||||
typename Component, typename T, typename Traits,
|
||||
typename Context, typename Delimiter, typename Parameter
|
||||
>
|
||||
static bool
|
||||
generate(Component const& component,
|
||||
karma::detail::output_iterator<
|
||||
karma::detail::ostream_iterator<T, Char, Traits>
|
||||
>& sink, Context&, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
typedef karma::detail::output_iterator<
|
||||
karma::detail::ostream_iterator<T, Char, Traits>
|
||||
> output_iterator;
|
||||
typedef
|
||||
karma::detail::iterator_sink<output_iterator, Char>
|
||||
sink_device;
|
||||
|
||||
iostreams::stream<sink_device> ostr(sink);
|
||||
ostr.imbue(sink.get_ostream().getloc());
|
||||
ostr << param << std::flush; // use existing operator<<()
|
||||
|
||||
if (ostr.good()) {
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this any_stream has no parameter attached, it needs to have been
|
||||
// initialized from a value/variable
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const&, OutputIterator&, Context&, Delimiter const&,
|
||||
unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, stream__not_usable_without_parameter,
|
||||
(Component, OutputIterator, Delimiter));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return "any-stream";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct stream_director
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
// stream_director has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const&)
|
||||
{
|
||||
typedef
|
||||
karma::detail::iterator_sink<OutputIterator, Char>
|
||||
sink_device;
|
||||
|
||||
// use existing operator<<()
|
||||
iostreams::stream<sink_device> ostr(sink);
|
||||
ostr << fusion::at_c<0>(component.elements) << std::flush;
|
||||
|
||||
if (ostr.good()) {
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is a special overload to detect if the output iterator has been
|
||||
// generated by a format_manip object.
|
||||
template <
|
||||
typename Component, typename T, typename Traits,
|
||||
typename Context, typename Delimiter, typename Parameter
|
||||
>
|
||||
static bool
|
||||
generate(Component const& component,
|
||||
karma::detail::output_iterator<
|
||||
karma::detail::ostream_iterator<T, Char, Traits>
|
||||
>& sink, Context&, Delimiter const& d, Parameter const&)
|
||||
{
|
||||
typedef karma::detail::output_iterator<
|
||||
karma::detail::ostream_iterator<T, Char, Traits>
|
||||
> output_iterator;
|
||||
typedef
|
||||
karma::detail::iterator_sink<output_iterator, Char>
|
||||
sink_device;
|
||||
|
||||
// use existing operator<<()
|
||||
iostreams::stream<sink_device> ostr(sink);
|
||||
ostr.imbue(sink.get_ostream().getloc());
|
||||
ostr << fusion::at_c<0>(component.elements) << std::flush;
|
||||
|
||||
if (ostr.good()) {
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return "stream";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
16
include/boost/spirit/home/karma/string.hpp
Normal file
16
include/boost/spirit/home/karma/string.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_KARMA_STRING_FEB_23_2007_0156PM)
|
||||
#define BOOST_SPIRIT_KARMA_STRING_FEB_23_2007_0156PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/string/lit.hpp>
|
||||
#include <boost/spirit/home/karma/string/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
310
include/boost/spirit/home/karma/string/lit.hpp
Normal file
310
include/boost/spirit/home/karma/string/lit.hpp
Normal file
@@ -0,0 +1,310 @@
|
||||
// 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_KARMA_LIT_FEB_22_2007_0534PM)
|
||||
#define BOOST_SPIRIT_KARMA_LIT_FEB_22_2007_0534PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/delimit.hpp>
|
||||
#include <boost/spirit/home/karma/detail/string_generate.hpp>
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
#include <boost/spirit/home/support/modifier.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate literal strings from a given parameter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct any_string
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef std::basic_string<Char> type;
|
||||
};
|
||||
|
||||
// lit has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
bool result = detail::string_generate(sink, param);
|
||||
if (result)
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
// this lit has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, lit_not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "any-string";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate literal strings
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct literal_string
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
bool result = detail::string_generate(sink,
|
||||
fusion::at_c<0>(component.elements));
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return std::string("\"")
|
||||
+ spirit::detail::to_narrow_string(
|
||||
fusion::at_c<0>(component.elements))
|
||||
+ std::string("\"")
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lazy string generation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct lazy_string
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& ctx, Delimiter const& d, Parameter const& /*param*/)
|
||||
{
|
||||
bool result = detail::string_generate(sink,
|
||||
fusion::at_c<0>(component.elements)(unused, ctx));
|
||||
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// generate literal strings from a given parameter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char, typename Tag>
|
||||
struct case_any_string
|
||||
{
|
||||
template <typename Component, typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef std::basic_string<Char> type;
|
||||
};
|
||||
|
||||
// case_any_string has a parameter attached
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter, typename Parameter>
|
||||
static bool
|
||||
generate(Component const& /*component*/, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, Parameter const& param)
|
||||
{
|
||||
bool result = detail::string_generate(sink, param, Tag());
|
||||
karma::delimit(sink, d); // always do post-delimiting
|
||||
return result;
|
||||
}
|
||||
|
||||
// this case_any_string has no parameter attached, it needs to have been
|
||||
// initialized from a direct literal
|
||||
template <typename Component, typename OutputIterator,
|
||||
typename Context, typename Delimiter>
|
||||
static bool
|
||||
generate(Component const& component, OutputIterator& sink,
|
||||
Context& /*ctx*/, Delimiter const& d, unused_type)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, lit_not_usable_without_parameter, ());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const&)
|
||||
{
|
||||
typedef typename Tag::char_set char_set;
|
||||
typedef typename Tag::char_class char_class_;
|
||||
return std::string("any-") +
|
||||
spirit::char_class::what<char_set>::is(char_class_())
|
||||
+ "case-string";
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower_case and upper_case literal_string generator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::literal_string<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef std::basic_string<Char> string_type;
|
||||
typedef fusion::vector<string_type> vector_type;
|
||||
|
||||
typedef
|
||||
component<karma::domain, karma::literal_string<Char>, vector_type>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
|
||||
string_type val(fusion::at_c<0>(elements));
|
||||
typename string_type::iterator end = val.end();
|
||||
for (typename string_type::iterator it = val.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
*it = char_set::tolower(*it);
|
||||
}
|
||||
|
||||
return type(vector_type(val));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::literal_string<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef std::basic_string<Char> string_type;
|
||||
typedef fusion::vector<string_type> vector_type;
|
||||
|
||||
typedef
|
||||
component<karma::domain, karma::literal_string<Char>, vector_type>
|
||||
type;
|
||||
|
||||
static type
|
||||
call(Elements const& elements)
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
|
||||
string_type val(fusion::at_c<0>(elements));
|
||||
typename string_type::iterator end = val.end();
|
||||
for (typename string_type::iterator it = val.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
*it = char_set::toupper(*it);
|
||||
}
|
||||
|
||||
return type(vector_type(val));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lower and upper case_any_string conversions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::any_string<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::lower_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::lower char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef component<
|
||||
karma::domain, karma::case_any_string<Char, key_tag>, fusion::nil
|
||||
> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Domain, typename Elements, typename Modifier,
|
||||
typename Char>
|
||||
struct make_modified_component<
|
||||
Domain, karma::any_string<Char>, Elements, Modifier,
|
||||
typename enable_if<
|
||||
is_member_of_modifier<Modifier, spirit::char_class::upper_case_base_tag>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef typename Modifier::char_set char_set;
|
||||
typedef spirit::char_class::tag::upper char_class_;
|
||||
typedef spirit::char_class::key<char_set, char_class_> key_tag;
|
||||
|
||||
typedef component<
|
||||
karma::domain, karma::case_any_string<Char, key_tag>, fusion::nil
|
||||
> type;
|
||||
|
||||
static type
|
||||
call(Elements const&)
|
||||
{
|
||||
return type(fusion::nil());
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
236
include/boost/spirit/home/karma/string/meta_grammar.hpp
Normal file
236
include/boost/spirit/home/karma/string/meta_grammar.hpp
Normal file
@@ -0,0 +1,236 @@
|
||||
// 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_KARMA_META_GRAMMAR_FEB_22_2007_0532PM)
|
||||
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_22_2007_0532PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forwards
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct any_string;
|
||||
|
||||
template <typename Char>
|
||||
struct literal_string;
|
||||
|
||||
struct lazy_string;
|
||||
|
||||
struct string_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct extract_char;
|
||||
|
||||
template <typename Char, typename Traits, typename Alloc>
|
||||
struct extract_char<std::basic_string<Char, Traits, Alloc> >
|
||||
{
|
||||
typedef Char type;
|
||||
};
|
||||
|
||||
template <typename Char, int N>
|
||||
struct extract_char<Char[N]>
|
||||
{
|
||||
typedef typename remove_const<Char>::type type;
|
||||
};
|
||||
|
||||
template <typename Char, int N>
|
||||
struct extract_char<Char(&)[N]>
|
||||
{
|
||||
typedef typename remove_const<Char>::type type;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
struct extract_char<Char*>
|
||||
{
|
||||
typedef typename remove_const<Char>::type type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the director of a string literal type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag, typename T>
|
||||
struct extract_lit_director_lit;
|
||||
|
||||
template <typename T>
|
||||
struct extract_lit_director_lit<tag::lit, T>
|
||||
{
|
||||
typedef typename extract_char<T>::type char_type;
|
||||
typedef literal_string<char_type> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_lit_director_lit<tag::wlit, T>
|
||||
{
|
||||
typedef typename extract_char<T>::type char_type;
|
||||
typedef literal_string<char_type> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tag>
|
||||
struct extract_lit_director_plain;
|
||||
|
||||
template <>
|
||||
struct extract_lit_director_plain<tag::lit>
|
||||
{
|
||||
typedef any_string<char> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct extract_lit_director_plain<tag::wlit>
|
||||
{
|
||||
typedef any_string<wchar_t> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// string generator meta-grammar
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// literal strings: "hello"
|
||||
struct string_literal_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, char const*, literal_string<char>
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, wchar_t const*, literal_string<wchar_t>
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, char*, literal_string<char>
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain, wchar_t*, literal_string<wchar_t>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// literal strings: "hello"
|
||||
struct basic_string_literal_meta_grammar
|
||||
: proto::or_<
|
||||
proto::terminal<char const*>,
|
||||
proto::terminal<wchar_t const*>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// std::string(s)
|
||||
struct std_string_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain,
|
||||
std::basic_string<char, proto::_, proto::_>,
|
||||
literal_string<char>
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
karma::domain,
|
||||
std::basic_string<wchar_t, proto::_, proto::_>,
|
||||
literal_string<wchar_t>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// std::string(s)
|
||||
struct basic_std_string_meta_grammar
|
||||
: proto::or_<
|
||||
proto::terminal<std::basic_string<char, proto::_, proto::_> >,
|
||||
proto::terminal<std::basic_string<wchar_t, proto::_, proto::_> >
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// we use this test to detect if the argument to lit is a callable
|
||||
// function or not. Only types convertible to int or function/
|
||||
// function objects are allowed. Therefore, if T is not convertible
|
||||
// to an int, then we have a function/function object.
|
||||
template <typename T>
|
||||
struct is_not_convertible_to_int
|
||||
: mpl::not_<is_convertible<T, int> >
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
// this is the string literal meta grammar
|
||||
// literal strings: lit, lit("hello")
|
||||
struct string_meta_grammar
|
||||
: proto::or_<
|
||||
string_literal_meta_grammar,
|
||||
std_string_meta_grammar,
|
||||
meta_grammar::compose_empty<
|
||||
proto::if_<
|
||||
is_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_lit_director_plain<mpl::_> >
|
||||
>,
|
||||
meta_grammar::compose_function1_eval<
|
||||
proto::function<
|
||||
proto::if_<
|
||||
is_lit_tag<proto::_arg, karma::domain>()
|
||||
>,
|
||||
proto::or_<
|
||||
basic_string_literal_meta_grammar,
|
||||
basic_std_string_meta_grammar
|
||||
>
|
||||
>,
|
||||
karma::domain,
|
||||
mpl::identity<extract_lit_director_lit<mpl::_, mpl::_> >
|
||||
>,
|
||||
meta_grammar::function1_rule<
|
||||
karma::domain, tag::lit, lazy_string,
|
||||
proto::if_<
|
||||
detail::is_not_convertible_to_int<proto::_arg>()
|
||||
>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hooks into the Karma meta-grammar.
|
||||
// (see karma/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<Expr,
|
||||
typename enable_if<proto::matches<Expr, string_meta_grammar> >::type>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<Expr,
|
||||
typename enable_if<proto::matches<Expr, string_meta_grammar> >::type>
|
||||
: mpl::identity<string_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
36
include/boost/spirit/home/karma/what.hpp
Normal file
36
include/boost/spirit/home/karma/what.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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_WHAT_MAY_04_2007_0116PM)
|
||||
#define BOOST_SPIRIT_WHAT_MAY_04_2007_0116PM
|
||||
|
||||
#include <boost/spirit/home/karma/meta_grammar.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
template <typename Expr>
|
||||
inline std::string what(Expr const& xpr)
|
||||
{
|
||||
typedef spirit::traits::is_component<karma::domain, Expr> is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_generator, ());
|
||||
|
||||
typedef typename
|
||||
spirit::result_of::as_component<karma::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
|
||||
component c = spirit::as_component(karma::domain(), xpr);
|
||||
return director::what(c);
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
18
include/boost/spirit/home/lex.hpp
Normal file
18
include/boost/spirit/home/lex.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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_LEXER_MARCH_22_2007_0929PM)
|
||||
#define BOOST_SPIRIT_LEXER_MARCH_22_2007_0929PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/lexer.hpp>
|
||||
#include <boost/spirit/home/lex/domain.hpp>
|
||||
#include <boost/spirit/home/lex/meta_grammar.hpp>
|
||||
#include <boost/spirit/home/lex/tokenize_and_parse.hpp>
|
||||
|
||||
#endif
|
||||
21
include/boost/spirit/home/lex/domain.hpp
Normal file
21
include/boost/spirit/home/lex/domain.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_LEX_DOMAIN_MAR_13_2007_0140PM)
|
||||
#define BOOST_SPIRIT_LEX_DOMAIN_MAR_13_2007_0140PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
struct domain
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
29
include/boost/spirit/home/lex/lexer.hpp
Normal file
29
include/boost/spirit/home/lex/lexer.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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_LEXER_MAR_22_2007_1008PM)
|
||||
#define BOOST_SPIRIT_LEXER_MAR_22_2007_1008PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/terminal_director.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/token_def.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/token_set.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/char_token_def.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/string_token_def.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/sequence.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/action.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexer.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/meta_grammar.hpp>
|
||||
|
||||
#include <boost/spirit/home/lex/qi/state/state_switcher.hpp>
|
||||
#include <boost/spirit/home/lex/qi/state/in_state.hpp>
|
||||
#include <boost/spirit/home/lex/qi/utility/plain_token.hpp>
|
||||
#include <boost/spirit/home/lex/qi/meta_grammar.hpp>
|
||||
|
||||
#endif
|
||||
95
include/boost/spirit/home/lex/lexer/action.hpp
Normal file
95
include/boost/spirit/home/lex/lexer/action.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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(SPIRIT_LEX_ACTION_NOV_18_2007_0743PM)
|
||||
#define SPIRIT_LEX_ACTION_NOV_18_2007_0743PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/set_state.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
struct set_state_functor
|
||||
{
|
||||
set_state_functor (Char const* new_state_)
|
||||
: new_state(new_state_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Range, typename LexerContext>
|
||||
void operator()(Range const&, std::size_t, LexerContext& ctx,
|
||||
bool&) const
|
||||
{
|
||||
ctx.set_state_name(new_state);
|
||||
}
|
||||
|
||||
Char const* new_state;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
set_state_functor<Char>
|
||||
make_set_state(Char const* new_state)
|
||||
{
|
||||
return set_state_functor<Char>(new_state);
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits, typename Alloc>
|
||||
set_state_functor<Char>
|
||||
make_set_state(std::basic_string<Char, Traits, Alloc> const& new_state)
|
||||
{
|
||||
return set_state_functor<Char>(new_state.c_str());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename LexerDef, typename F>
|
||||
inline void add_action_helper(LexerDef& lexdef, std::size_t id, F act)
|
||||
{
|
||||
lexdef.add_action(id, act);
|
||||
}
|
||||
|
||||
template <typename LexerDef, typename String>
|
||||
inline void add_action_helper(LexerDef& lexdef, std::size_t id,
|
||||
spirit::tag::set_state_tag<String> t)
|
||||
{
|
||||
lexdef.add_action(id, make_set_state(t.name));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct action
|
||||
{
|
||||
template <typename Component, typename LexerDef, typename String>
|
||||
static void
|
||||
collect(Component const& component, LexerDef& lexdef,
|
||||
String const& state)
|
||||
{
|
||||
typedef typename
|
||||
result_of::left<Component>::type::director
|
||||
director;
|
||||
|
||||
// first collect the token definition information for the token_def
|
||||
// this action is attached to
|
||||
director::collect(spirit::left(component), lexdef, state);
|
||||
|
||||
// retrieve the id of the associated token_def and register the
|
||||
// given semantic action with the lexer instance
|
||||
std::size_t id = director::id(spirit::left(component));
|
||||
detail::add_action_helper(lexdef, id, spirit::right(component));
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::lex
|
||||
|
||||
#endif
|
||||
40
include/boost/spirit/home/lex/lexer/char_token_def.hpp
Normal file
40
include/boost/spirit/home/lex/lexer/char_token_def.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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_LEX_CHAR_TOKEN_DEF_MAR_28_2007_0626PM)
|
||||
#define BOOST_SPIRIT_LEX_CHAR_TOKEN_DEF_MAR_28_2007_0626PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// char_token_def
|
||||
// represents a single character token definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct char_token_def
|
||||
{
|
||||
template <typename Component, typename LexerDef, typename String>
|
||||
static void
|
||||
collect(Component const& component, LexerDef& lexdef,
|
||||
String const& state)
|
||||
{
|
||||
typedef typename result_of::subject<Component>::type char_type;
|
||||
|
||||
char_type c = subject(component);
|
||||
lexdef.add_token (state.c_str(), lex::detail::escape(c),
|
||||
static_cast<std::size_t>(c));
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::lex
|
||||
|
||||
#endif
|
||||
38
include/boost/spirit/home/lex/lexer/detail/sequence.hpp
Normal file
38
include/boost/spirit/home/lex/lexer/detail/sequence.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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_LEX_SEQUENCE_FEB_28_2007_0249PM)
|
||||
#define BOOST_SPIRIT_LEX_SEQUENCE_FEB_28_2007_0249PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex { namespace detail
|
||||
{
|
||||
template <typename LexerDef, typename String>
|
||||
struct sequence_collect
|
||||
{
|
||||
sequence_collect(LexerDef& def_, String const& state_)
|
||||
: def(def_), state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
bool operator()(Component const& component)
|
||||
{
|
||||
Component::director::collect(component, def, state);
|
||||
return false; // execute for all sequence elements
|
||||
}
|
||||
|
||||
LexerDef& def;
|
||||
String const& state;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::spirit::lex::detail
|
||||
|
||||
#endif
|
||||
367
include/boost/spirit/home/lex/lexer/lexer.hpp
Normal file
367
include/boost/spirit/home/lex/lexer/lexer.hpp
Normal file
@@ -0,0 +1,367 @@
|
||||
// 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_LEX_LEXER_MAR_13_2007_0145PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/safe_bool.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/token_def.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <string>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename LexerDef>
|
||||
struct lexer_def_
|
||||
: public proto::extends<
|
||||
typename make_terminal_holder<
|
||||
lexer_def_<LexerDef> const*, lexer_def_<LexerDef>
|
||||
>::type,
|
||||
lexer_def_<LexerDef>
|
||||
>
|
||||
{
|
||||
private:
|
||||
// avoid warnings about using 'this' in constructor
|
||||
lexer_def_& this_() { return *this; }
|
||||
|
||||
// initialize proto base class
|
||||
typedef
|
||||
terminal_holder<lexer_def_ const*, lexer_def_>
|
||||
terminal_holder;
|
||||
typedef typename proto::terminal<terminal_holder>::type tag;
|
||||
typedef proto::extends<tag, lexer_def_> base_type;
|
||||
|
||||
tag make_tag() const
|
||||
{
|
||||
tag xpr = {{ this }};
|
||||
return xpr;
|
||||
}
|
||||
|
||||
typedef typename LexerDef::char_type char_type;
|
||||
typedef typename LexerDef::string_type string_type;
|
||||
|
||||
public:
|
||||
// Qi interface: metafunction calculating parser return type
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
// the return value of a token set contains the matched token
|
||||
// id, and the corresponding pair of iterators
|
||||
typedef typename Iterator::base_iterator_type iterator_type;
|
||||
typedef
|
||||
fusion::vector<std::size_t, iterator_range<iterator_type> >
|
||||
type;
|
||||
};
|
||||
|
||||
private:
|
||||
// Qi interface: parse functionality
|
||||
template <typename Iterator, typename Context, typename Skipper,
|
||||
typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last,
|
||||
Context& context, Skipper const& skipper, Attribute& attr) const
|
||||
{
|
||||
qi::skip(first, last, skipper); // always do a pre-skip
|
||||
|
||||
if (first != last) {
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
token_type;
|
||||
|
||||
token_type &t = *first;
|
||||
if (0 != t.id()) {
|
||||
// any of the token definitions matched
|
||||
qi::detail::assign_to(t, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
friend struct terminal_director;
|
||||
|
||||
static std::string what()
|
||||
{
|
||||
return "lexer";
|
||||
}
|
||||
|
||||
// allow to use the lexer.self.add("regex1", id1)("regex2", id2);
|
||||
// syntax
|
||||
struct adder
|
||||
{
|
||||
adder(lexer_def_& def_)
|
||||
: def(def_)
|
||||
{}
|
||||
|
||||
adder const&
|
||||
operator()(char_type c, std::size_t token_id = 0) const
|
||||
{
|
||||
if (0 == token_id)
|
||||
token_id = static_cast<std::size_t>(c);
|
||||
def.def.add_token (def.state.c_str(), lex::detail::escape(c),
|
||||
token_id);
|
||||
return *this;
|
||||
}
|
||||
adder const&
|
||||
operator()(string_type const& s, std::size_t token_id = 0) const
|
||||
{
|
||||
if (0 == token_id)
|
||||
token_id = next_id();
|
||||
def.def.add_token (def.state.c_str(), s, token_id);
|
||||
return *this;
|
||||
}
|
||||
template <typename Attribute>
|
||||
adder const&
|
||||
operator()(token_def<Attribute, char_type>& tokdef,
|
||||
std::size_t token_id = 0) const
|
||||
{
|
||||
// make sure we have a token id
|
||||
if (0 == token_id) {
|
||||
if (0 == tokdef.id()) {
|
||||
token_id = next_id();
|
||||
tokdef.id(token_id);
|
||||
}
|
||||
else {
|
||||
token_id = tokdef.id();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the following assertion makes sure, that the token_def
|
||||
// instance has not been assigned a different id earlier
|
||||
BOOST_ASSERT(0 == tokdef.id() || token_id == tokdef.id());
|
||||
tokdef.id(token_id);
|
||||
}
|
||||
|
||||
def.define(tokdef);
|
||||
return *this;
|
||||
}
|
||||
template <typename TokenSet>
|
||||
adder const&
|
||||
operator()(token_set<TokenSet>& tokset) const
|
||||
{
|
||||
def.define(tokset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
lexer_def_& def;
|
||||
};
|
||||
friend struct adder;
|
||||
|
||||
// allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
|
||||
// syntax
|
||||
struct pattern_adder
|
||||
{
|
||||
pattern_adder(lexer_def_& def_)
|
||||
: def(def_)
|
||||
{}
|
||||
|
||||
pattern_adder const&
|
||||
operator()(string_type const& p, string_type const& s) const
|
||||
{
|
||||
def.def.add_pattern (def.state.c_str(), p, s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
lexer_def_& def;
|
||||
};
|
||||
friend struct pattern_adder;
|
||||
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
void define(Expr const& xpr)
|
||||
{
|
||||
typedef typename
|
||||
result_of::as_component<lex::domain, Expr>::type
|
||||
component;
|
||||
typedef typename component::director director;
|
||||
|
||||
component c = spirit::as_component(lex::domain(), xpr);
|
||||
director::collect(c, def, state);
|
||||
}
|
||||
|
||||
lexer_def_(LexerDef& def_, string_type const& state_)
|
||||
: base_type(make_tag()), add(this_()), add_pattern(this_()),
|
||||
def(def_), state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
// allow to switch states
|
||||
lexer_def_ operator()(char_type const* state) const
|
||||
{
|
||||
return lexer_def_(def, state);
|
||||
}
|
||||
lexer_def_ operator()(string_type const& state) const
|
||||
{
|
||||
return lexer_def_(def, state);
|
||||
}
|
||||
|
||||
// allow to assign a token definition expression
|
||||
template <typename Expr>
|
||||
lexer_def_& operator= (Expr const& xpr)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<lex::domain, Expr>
|
||||
is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_token_definition, ());
|
||||
|
||||
def.clear(state.c_str());
|
||||
define(xpr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
adder add;
|
||||
pattern_adder add_pattern;
|
||||
|
||||
private:
|
||||
LexerDef& def;
|
||||
string_type state;
|
||||
};
|
||||
|
||||
// allow to assign a token definition expression
|
||||
template <typename LexerDef, typename Expr>
|
||||
inline lexer_def_<LexerDef>&
|
||||
operator+= (lexer_def_<LexerDef>& lexdef, Expr& xpr)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<lex::domain, Expr>
|
||||
is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_token_definition, ());
|
||||
|
||||
lexdef.define(xpr);
|
||||
return lexdef;
|
||||
}
|
||||
|
||||
template <typename LexerDef, typename Expr>
|
||||
inline lexer_def_<LexerDef>&
|
||||
operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
|
||||
{
|
||||
typedef
|
||||
spirit::traits::is_component<lex::domain, Expr>
|
||||
is_component;
|
||||
|
||||
// report invalid expression error as early as possible
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
is_component::value,
|
||||
xpr_is_not_convertible_to_a_token_definition, ());
|
||||
|
||||
lexdef.define(xpr);
|
||||
return lexdef;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This represents a lexer definition (helper for token and token set
|
||||
// definitions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Lexer>
|
||||
class lexer_def : noncopyable, public Lexer
|
||||
{
|
||||
private:
|
||||
typedef lexer_def<Lexer> self_type;
|
||||
|
||||
// avoid warnings about using 'this' in constructor
|
||||
lexer_def& this_() { return *this; }
|
||||
|
||||
public:
|
||||
typedef Lexer lexer_type;
|
||||
typedef detail::lexer_def_<self_type> token_set;
|
||||
typedef typename Lexer::char_type char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
lexer_def()
|
||||
: self(this_(), Lexer::initial_state())
|
||||
{
|
||||
}
|
||||
|
||||
token_set self; // allow for easy token definition
|
||||
|
||||
// this is just a dummy implementation to allow to use lexer_def
|
||||
// directly, without having to derive a separate class
|
||||
void def(token_set& /*self*/) {}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This represents a lexer object
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Definition>
|
||||
class lexer : public safe_bool<lexer<Definition> >
|
||||
{
|
||||
public:
|
||||
// operator_bool() is needed for the safe_bool base class
|
||||
bool operator_bool() const { return token_def; }
|
||||
|
||||
typedef typename Definition::lexer_type lexer_type;
|
||||
typedef typename Definition::char_type char_type;
|
||||
typedef typename Definition::iterator_type iterator_type;
|
||||
|
||||
lexer(Definition& token_def_)
|
||||
: token_def(token_def_)
|
||||
{
|
||||
// call initialization routine supplied by the target lexer
|
||||
token_def.def(token_def.self);
|
||||
}
|
||||
|
||||
// access iterator interface
|
||||
template <typename Iterator>
|
||||
iterator_type begin(Iterator& first, Iterator const& last) const
|
||||
{ return token_def.begin(first, last); }
|
||||
iterator_type end() const { return token_def.end(); }
|
||||
|
||||
std::size_t map_state(char_type const* state)
|
||||
{ return token_def.add_state(state); }
|
||||
|
||||
Definition& get_definition() { return token_def; }
|
||||
Definition const& get_definition() const { return token_def; }
|
||||
|
||||
private:
|
||||
Definition& token_def;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Metafunction returning the iterator type of the lexer given the token
|
||||
// definition type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Definition>
|
||||
struct lexer_iterator
|
||||
{
|
||||
typedef typename lexer<Definition>::iterator_type type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator function helping to construct a proper lexer object
|
||||
// instance
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Definition>
|
||||
inline lexer<Definition>
|
||||
make_lexer(Definition& def)
|
||||
{
|
||||
return lexer<Definition>(def);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
47
include/boost/spirit/home/lex/lexer/lexer_actions.hpp
Normal file
47
include/boost/spirit/home/lex/lexer/lexer_actions.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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_LEX_LEXER_ACTIONS_FEB_13_2008_1232PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_ACTIONS_FEB_13_2008_1232PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char, typename Traits>
|
||||
struct echo_input_functor
|
||||
{
|
||||
echo_input_functor (std::basic_ostream<Char, Traits>& os_)
|
||||
: os(os_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Range, typename LexerContext>
|
||||
void operator()(Range const& r, std::size_t, LexerContext&, bool&) const
|
||||
{
|
||||
os << r;
|
||||
}
|
||||
|
||||
std::basic_ostream<Char, Traits>& os;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Char, typename Traits>
|
||||
inline echo_input_functor<Char, Traits>
|
||||
echo_input(std::basic_ostream<Char, Traits>& os)
|
||||
{
|
||||
return echo_input_functor<Char, Traits>(os);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}}}
|
||||
|
||||
#endif
|
||||
44
include/boost/spirit/home/lex/lexer/lexer_fwd.hpp
Normal file
44
include/boost/spirit/home/lex/lexer/lexer_fwd.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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_LEX_LEXER_FWD_MAR_22_2007_1137PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_FWD_MAR_22_2007_1137PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This component represents a token definition
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename Attribute = unused_type, typename Char = char>
|
||||
class token_def;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// token_set
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename TokenSet>
|
||||
class token_set;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This represents a lexer definition (helper for token and token set
|
||||
// definitions)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Lexer>
|
||||
class lexer_def;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This represents a lexer object
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Definition>
|
||||
class lexer;
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,257 @@
|
||||
// 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_LEXERTL_ITERATOR_TOKENISER_MARCH_22_2007_0859AM)
|
||||
#define BOOST_SPIRIT_LEXERTL_ITERATOR_TOKENISER_MARCH_22_2007_0859AM
|
||||
|
||||
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/size_t.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
template<typename Iterator>
|
||||
class basic_iterator_tokeniser
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::size_t> size_t_vector;
|
||||
|
||||
// static std::size_t next (const std::size_t * const lookup_,
|
||||
// std::size_t const dfa_alphabet_, const std::size_t * const dfa_,
|
||||
// Iterator const& start_, Iterator &start_token_,
|
||||
// Iterator const& end_)
|
||||
// {
|
||||
// if (start_token_ == end_) return 0;
|
||||
//
|
||||
// const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
|
||||
// Iterator curr_ = start_token_;
|
||||
// bool end_state_ = *ptr_ != 0;
|
||||
// std::size_t id_ = *(ptr_ + lexer::id_index);
|
||||
// Iterator end_token_ = start_token_;
|
||||
//
|
||||
// while (curr_ != end_)
|
||||
// {
|
||||
// std::size_t const BOL_state_ = ptr_[lexer::bol_index];
|
||||
// std::size_t const EOL_state_ = ptr_[lexer::eol_index];
|
||||
//
|
||||
// if (BOL_state_ && (start_token_ == start_ ||
|
||||
// *(start_token_ - 1) == '\n'))
|
||||
// {
|
||||
// ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
// }
|
||||
// else if (EOL_state_ && *curr_ == '\n')
|
||||
// {
|
||||
// ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// std::size_t const state_ = ptr_[lookup_[*curr_++]];
|
||||
//
|
||||
// if (state_ == 0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
// }
|
||||
//
|
||||
// if (*ptr_)
|
||||
// {
|
||||
// end_state_ = true;
|
||||
// id_ = *(ptr_ + lexer::id_index);
|
||||
// end_token_ = curr_;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const std::size_t EOL_state_ = ptr_[lexer::eol_index];
|
||||
//
|
||||
// if (EOL_state_ && curr_ == end_)
|
||||
// {
|
||||
// ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
//
|
||||
// if (*ptr_)
|
||||
// {
|
||||
// end_state_ = true;
|
||||
// id_ = *(ptr_ + lexer::id_index);
|
||||
// end_token_ = curr_;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (end_state_) {
|
||||
// // return longest match
|
||||
// start_token_ = end_token_;
|
||||
// }
|
||||
// else {
|
||||
// id_ = lexer::npos;
|
||||
// }
|
||||
//
|
||||
// return id_;
|
||||
// }
|
||||
|
||||
static std::size_t next (boost::lexer::state_machine const& state_machine_,
|
||||
std::size_t &dfa_state_, Iterator const& start_,
|
||||
Iterator &start_token_, Iterator const& end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
again:
|
||||
std::size_t const* lookup_ = &state_machine_._lookup[dfa_state_]->
|
||||
front ();
|
||||
std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[dfa_state_];
|
||||
std::size_t const* dfa_ = &state_machine_._dfa[dfa_state_]->front ();
|
||||
std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
|
||||
Iterator curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + boost::lexer::id_index);
|
||||
Iterator end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
std::size_t const BOL_state_ = ptr_[boost::lexer::bol_index];
|
||||
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
|
||||
|
||||
if (BOL_state_ && (start_token_ == start_ ||
|
||||
*(start_token_ - 1) == '\n'))
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t const state_ = ptr_[lookup_[*curr_++]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + boost::lexer::id_index);
|
||||
dfa_state_ = *(ptr_ + boost::lexer::state_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + boost::lexer::id_index);
|
||||
dfa_state_ = *(ptr_ + boost::lexer::state_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_) {
|
||||
// return longest match
|
||||
start_token_ = end_token_;
|
||||
|
||||
if (id_ == 0)
|
||||
goto again;
|
||||
}
|
||||
else {
|
||||
id_ = boost::lexer::npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static
|
||||
std::size_t next (boost::lexer::state_machine const& state_machine_,
|
||||
Iterator const& start_, Iterator &start_token_, Iterator const& end_)
|
||||
{
|
||||
if (start_token_ == end_) return 0;
|
||||
|
||||
std::size_t const* lookup_ = &state_machine_._lookup[0]->front();
|
||||
std::size_t dfa_alphabet_ = state_machine_._dfa_alphabet[0];
|
||||
std::size_t const* dfa_ = &state_machine_._dfa[0]->front ();
|
||||
std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
|
||||
Iterator curr_ = start_token_;
|
||||
bool end_state_ = *ptr_ != 0;
|
||||
std::size_t id_ = *(ptr_ + boost::lexer::id_index);
|
||||
Iterator end_token_ = start_token_;
|
||||
|
||||
while (curr_ != end_)
|
||||
{
|
||||
std::size_t const BOL_state_ = ptr_[boost::lexer::bol_index];
|
||||
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
|
||||
|
||||
if (BOL_state_ && (start_token_ == start_ ||
|
||||
*(start_token_ - 1) == '\n'))
|
||||
{
|
||||
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else if (EOL_state_ && *curr_ == '\n')
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t const state_ = ptr_[lookup_[*curr_++]];
|
||||
|
||||
if (state_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr_ = &dfa_[state_ * dfa_alphabet_];
|
||||
}
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + boost::lexer::id_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
|
||||
|
||||
if (EOL_state_ && curr_ == end_)
|
||||
{
|
||||
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
|
||||
|
||||
if (*ptr_)
|
||||
{
|
||||
end_state_ = true;
|
||||
id_ = *(ptr_ + boost::lexer::id_index);
|
||||
end_token_ = curr_;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_state_) {
|
||||
// return longest match
|
||||
start_token_ = end_token_;
|
||||
}
|
||||
else {
|
||||
id_ = boost::lexer::npos;
|
||||
}
|
||||
|
||||
return id_;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
typedef basic_iterator_tokeniser<char const *> tokeniser;
|
||||
typedef basic_iterator_tokeniser<wchar_t const *> wtokeniser;
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
357
include/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp
Normal file
357
include/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp
Normal file
@@ -0,0 +1,357 @@
|
||||
// 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_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <map>
|
||||
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
|
||||
|
||||
#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
||||
#define BOOST_SPIRIT_EOF_PREFIX static
|
||||
#else
|
||||
#define BOOST_SPIRIT_EOF_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename HasActors, typename HasState>
|
||||
struct Data; // no default specialization
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// doesn't support no state and no actors
|
||||
template <typename Iterator>
|
||||
struct Data<Iterator, mpl::false_, mpl::false_>
|
||||
{
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
typedef unused_type semantic_actions_type;
|
||||
|
||||
// initialize the shared data
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: state_machine(data_.state_machine_),
|
||||
rules(data_.rules_),
|
||||
first(first_), last(last_)
|
||||
{}
|
||||
|
||||
std::size_t next(Iterator& end)
|
||||
{
|
||||
typedef basic_iterator_tokeniser<Iterator> tokenizer;
|
||||
return tokenizer::next(state_machine, first, end, last);
|
||||
}
|
||||
|
||||
// nothing to invoke, so this is empty
|
||||
bool invoke_actions(std::size_t, Iterator const&)
|
||||
{
|
||||
return true; // always accept
|
||||
}
|
||||
|
||||
std::size_t get_state() const { return 0; }
|
||||
void set_state_name (char_type const* state) {}
|
||||
|
||||
boost::lexer::state_machine const& state_machine;
|
||||
boost::lexer::basic_rules<char_type> const& rules;
|
||||
Iterator& first;
|
||||
Iterator last;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// doesn't support actors
|
||||
template <typename Iterator>
|
||||
struct Data<Iterator, mpl::false_, mpl::true_>
|
||||
: Data<Iterator, mpl::false_, mpl::false_>
|
||||
{
|
||||
typedef Data<Iterator, mpl::false_, mpl::false_> base_type;
|
||||
|
||||
// initialize the shared data
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: base_type(data_, first_, last_), state(0)
|
||||
{}
|
||||
|
||||
std::size_t next(Iterator& end)
|
||||
{
|
||||
typedef basic_iterator_tokeniser<Iterator> tokenizer;
|
||||
return tokenizer::next(this->state_machine, state,
|
||||
this->first, end, this->last);
|
||||
}
|
||||
|
||||
std::size_t& get_state() { return state; }
|
||||
void set_state_name (char_type const* new_state)
|
||||
{
|
||||
std::size_t state_id = this->rules.state(new_state);
|
||||
|
||||
// if the following assertion fires you've probably been using
|
||||
// a lexer state name which was not defined in your token
|
||||
// definition
|
||||
BOOST_ASSERT(state_id != boost::lexer::npos);
|
||||
|
||||
if (state_id != boost::lexer::npos)
|
||||
state = state_id;
|
||||
}
|
||||
|
||||
std::size_t state;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// does support actors, but may have no state
|
||||
template <typename Iterator, typename HasState>
|
||||
struct Data<Iterator, mpl::true_, HasState>
|
||||
: Data<Iterator, mpl::false_, HasState>
|
||||
{
|
||||
typedef Data<Iterator, mpl::false_, HasState> base_type;
|
||||
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
typedef void functor_type(iterpair_type, std::size_t, Data&, bool&);
|
||||
typedef boost::function<functor_type> functor_wrapper_type;
|
||||
typedef std::multimap<std::size_t, functor_wrapper_type>
|
||||
semantic_actions_type;
|
||||
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: base_type(data_, first_, last_),
|
||||
actions(data_.actions_)
|
||||
{}
|
||||
|
||||
// invoke attached semantic actions, if defined
|
||||
bool invoke_actions(std::size_t id, Iterator const& end)
|
||||
{
|
||||
if (actions.empty())
|
||||
return true; // nothing to invoke, continue with 'match'
|
||||
|
||||
iterpair_type itp(this->first, end);
|
||||
bool match = true;
|
||||
|
||||
typedef typename
|
||||
semantic_actions_type::const_iterator
|
||||
iterator_type;
|
||||
|
||||
std::pair<iterator_type, iterator_type> p = actions.equal_range(id);
|
||||
while (p.first != p.second)
|
||||
{
|
||||
((*p.first).second)(itp, id, *this, match);
|
||||
if (!match)
|
||||
return false; // return a 'no-match'
|
||||
++p.first;
|
||||
}
|
||||
return true; // normal execution
|
||||
}
|
||||
|
||||
semantic_actions_type const& actions;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lexertl_functor is a template usable as the functor object for the
|
||||
// multi_pass iterator allowing to wrap a lexertl based dfa into a
|
||||
// iterator based interface.
|
||||
//
|
||||
// Iterator: the type of the underlying iterator
|
||||
// Token: the type of the tokens produced by this functor
|
||||
// this needs to expose a constructor with the following
|
||||
// prototype:
|
||||
//
|
||||
// Token(std::size_t id, std::size_t state,
|
||||
// Iterator start, Iterator end)
|
||||
//
|
||||
// where 'id' is the token id, state is the lexer state,
|
||||
// this token has been matched in, and 'first' and 'end'
|
||||
// mark the start and the end of the token with respect
|
||||
// to the underlying character stream.
|
||||
// SupportsActors:
|
||||
// this is expected to be a mpl::bool_, if mpl::true_ the
|
||||
// lexertl_functor invokes functors which (optionally) have
|
||||
// been attached to the token definitions.
|
||||
// SupportState:
|
||||
// this is expected to be a mpl::bool_, if mpl::true_ the
|
||||
// lexertl_functor supports different lexer states,
|
||||
// otherwise no lexer state is supported.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename SupportsActors = mpl::false_,
|
||||
typename SupportsState = typename Token::has_state>
|
||||
class lexertl_functor
|
||||
{
|
||||
public:
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
private:
|
||||
// Needed by compilers not implementing the resolution to DR45. For
|
||||
// reference, see
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
|
||||
template <typename Iterator_, typename HasActors, typename HasState>
|
||||
friend struct detail::Data;
|
||||
|
||||
// Helper template allowing to assign a value on exit
|
||||
template <typename T>
|
||||
struct assign_on_exit
|
||||
{
|
||||
assign_on_exit(T& dst_, T const& src_)
|
||||
: dst(dst_), src(src_)
|
||||
{}
|
||||
~assign_on_exit()
|
||||
{
|
||||
dst = src;
|
||||
}
|
||||
|
||||
T& dst;
|
||||
T const& src;
|
||||
};
|
||||
|
||||
public:
|
||||
lexertl_functor()
|
||||
#if 0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900 || defined(__PGI)
|
||||
, eof()
|
||||
#endif // 0 != __DECCXX_VER
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// interface to the multi_pass_policies::split_functor_input policy
|
||||
typedef Token result_type;
|
||||
typedef lexertl_functor unique;
|
||||
typedef detail::Data<Iterator, SupportsActors, SupportsState> shared;
|
||||
|
||||
BOOST_SPIRIT_EOF_PREFIX result_type const eof;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
typedef Iterator iterator_type;
|
||||
typedef typename shared::semantic_actions_type semantic_actions_type;
|
||||
|
||||
template <typename MultiPass>
|
||||
static result_type& get_next(MultiPass& mp, result_type& result)
|
||||
{
|
||||
shared& data = mp.shared->ftor;
|
||||
if (data.first == data.last)
|
||||
return result = eof;
|
||||
|
||||
Iterator end = data.first;
|
||||
std::size_t id = data.next(end);
|
||||
|
||||
if (boost::lexer::npos == id) { // no match
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
std::string next;
|
||||
Iterator it = data.first;
|
||||
for (std::size_t i = 0; i < 10 && it != data.last; ++it, ++i)
|
||||
next += *it;
|
||||
|
||||
std::cerr << "Not matched, in state: " << data.state
|
||||
<< ", lookahead: >" << next << "<" << std::endl;
|
||||
#endif
|
||||
result = result_type(0);
|
||||
}
|
||||
else if (0 == id) { // EOF reached
|
||||
result = eof;
|
||||
}
|
||||
else {
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
{
|
||||
std::string next;
|
||||
Iterator it = data.first;
|
||||
for (std::size_t i = 0; i < 10 && it != data.last; ++it, ++i)
|
||||
next += *it;
|
||||
|
||||
std::cerr << "Matched: " << id << ", in state: "
|
||||
<< data.state << ", string: >"
|
||||
<< std::basic_string<char_type>(data.first, end) << "<"
|
||||
<< ", lookahead: >" << next << "<" << std::endl;
|
||||
}
|
||||
#endif
|
||||
// invoke_actions might change state
|
||||
std::size_t state = data.get_state();
|
||||
|
||||
// invoke attached semantic actions, if defined
|
||||
if (!data.invoke_actions(id, end))
|
||||
{
|
||||
// one of the semantic actions signaled no-match
|
||||
result = result_type(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return matched token, advancing 'data.first' past the
|
||||
// matched sequence
|
||||
assign_on_exit<Iterator> on_exit(data.first, end);
|
||||
result = result_type(id, state, data.first, end);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// set_state are propagated up to the iterator interface, allowing to
|
||||
// manipulate the current lexer state through any of the exposed
|
||||
// iterators.
|
||||
template <typename MultiPass>
|
||||
static std::size_t set_state(MultiPass& mp, std::size_t state_)
|
||||
{
|
||||
std::size_t oldstate = mp.shared->ftor.state;
|
||||
mp.shared->ftor.state = state_;
|
||||
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
std::cerr << "Switching state from: " << oldstate
|
||||
<< " to: " << state_
|
||||
<< std::endl;
|
||||
#endif
|
||||
return oldstate;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static std::size_t
|
||||
map_state(MultiPass const& mp, char_type const* statename)
|
||||
{
|
||||
return mp.shared->ftor.rules.state(statename);
|
||||
}
|
||||
|
||||
// we don't need this
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass const& mp)
|
||||
{}
|
||||
};
|
||||
|
||||
#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// eof token
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token, typename Iterator, typename SupportsActors,
|
||||
typename SupportsState>
|
||||
typename lexertl_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::result_type const
|
||||
lexertl_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::eof =
|
||||
typename lexertl_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::result_type();
|
||||
#endif // 0 != __COMO_VERSION__
|
||||
|
||||
}}}
|
||||
|
||||
#undef BOOST_SPIRIT_EOF_PREFIX
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,559 @@
|
||||
// Copyright (c) 2008 Ben Hanson
|
||||
// Copyright (c) 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_LEX_LEXERTL_GENERATE_CPP_FEB_10_2008_0855PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXERTL_GENERATE_CPP_FEB_10_2008_0855PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/size_t.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace lex { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generate a table of the names of the used lexer states, which is a bit
|
||||
// tricky, because the table stored with the rules is sorted based on the
|
||||
// names, but we need it sorted using the state ids.
|
||||
template <typename Char>
|
||||
inline bool
|
||||
generate_cpp_state_names (boost::lexer::basic_rules<Char> const& rules_,
|
||||
std::ostream &os_, char const* name_suffix = "")
|
||||
{
|
||||
// we need to re-sort the state names in ascending order if the state
|
||||
// ids, filling possible gaps in between later
|
||||
typedef typename
|
||||
boost::lexer::basic_rules<Char>::string_size_t_map::const_iterator
|
||||
state_iterator;
|
||||
typedef std::map<std::size_t, char const*> reverse_state_map_type;
|
||||
|
||||
reverse_state_map_type reverse_state_map;
|
||||
state_iterator send = rules_.statemap().end();
|
||||
for (state_iterator sit = rules_.statemap().begin(); sit != send; ++sit)
|
||||
{
|
||||
typedef typename reverse_state_map_type::value_type value_type;
|
||||
reverse_state_map.insert(value_type((*sit).second, (*sit).first.c_str()));
|
||||
}
|
||||
|
||||
os_ << "// this table defines the names of the lexer states\n";
|
||||
os_ << "char const* const lexer_state_names" << name_suffix
|
||||
<< "[" << rules_.statemap().size() << "] = \n{\n";
|
||||
|
||||
typedef typename reverse_state_map_type::iterator iterator;
|
||||
iterator rend = reverse_state_map.end();
|
||||
std::size_t last_id = 0;
|
||||
for (iterator rit = reverse_state_map.begin(); rit != rend; ++rit)
|
||||
{
|
||||
for (/**/; last_id < (*rit).first; ++last_id)
|
||||
{
|
||||
os_ << " 0, // \"<undefined state>\"\n";
|
||||
}
|
||||
os_ << " \"" << (*rit).second << "\",\n";
|
||||
}
|
||||
os_ << "};\n\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generate a tokenizer for the given state machine.
|
||||
template <typename Char>
|
||||
inline bool
|
||||
generate_cpp (boost::lexer::state_machine const& sm_,
|
||||
boost::lexer::basic_rules<Char> const& rules_,
|
||||
std::ostream &os_, char const* name_suffix = "",
|
||||
bool skip_on_nomatch = true, bool optimize_parameters = true)
|
||||
{
|
||||
if (sm_._lookup->empty())
|
||||
return false;
|
||||
|
||||
std::size_t const dfas_ = sm_._dfa->size();
|
||||
std::size_t const lookups_ = sm_._lookup->front()->size();
|
||||
|
||||
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";
|
||||
|
||||
std::string guard(__DATE__ "_" __TIME__);
|
||||
std::string::size_type p = guard.find_first_of(": ");
|
||||
while (std::string::npos != p)
|
||||
{
|
||||
guard.replace(p, 1, "_");
|
||||
p = guard.find_first_of(": ", p);
|
||||
}
|
||||
|
||||
os_ << "#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_" << guard << ")\n";
|
||||
os_ << "#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_" << guard << "\n\n";
|
||||
|
||||
os_ << "#include <boost/detail/iterator.hpp>\n";
|
||||
os_ << "#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>\n\n";
|
||||
|
||||
os_ << "// the generated table of state names and the tokenizer have to be\n"
|
||||
"// defined in the boost::spirit::lex::static namespace\n";
|
||||
os_ << "namespace boost { namespace spirit { namespace lex { "
|
||||
"namespace static_ {\n\n";
|
||||
|
||||
// generate the table containing state names
|
||||
if (!generate_cpp_state_names(rules_, os_, name_suffix))
|
||||
return false;
|
||||
|
||||
os_ << "template<typename Iterator>\n";
|
||||
os_ << "std::size_t next_token" << name_suffix << " (";
|
||||
|
||||
if (dfas_ > 1 || !optimize_parameters)
|
||||
{
|
||||
os_ << "std::size_t &start_state_, ";
|
||||
}
|
||||
|
||||
if (sm_._seen_BOL_assertion || !optimize_parameters)
|
||||
{
|
||||
os_ << "Iterator const& start_, ";
|
||||
}
|
||||
|
||||
if (dfas_ > 1 || sm_._seen_BOL_assertion || !optimize_parameters)
|
||||
{
|
||||
os_ << "\n ";
|
||||
}
|
||||
|
||||
os_ << "Iterator &start_token_, Iterator const& 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)
|
||||
{
|
||||
for (std::size_t state_ = 0; state_ < dfas_; ++state_)
|
||||
{
|
||||
std::size_t i_ = 0;
|
||||
std::size_t j_ = 1;
|
||||
std::size_t count_ = lookups_ / 8;
|
||||
std::size_t const* lookup_ = &sm_._lookup[state_]->front ();
|
||||
std::size_t const* 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 << " ";
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t const 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
|
||||
{
|
||||
std::size_t const* lookup_ = &sm_._lookup[0]->front();
|
||||
std::size_t const* 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_ << " std::size_t const BOL_state_ = ptr_[bol_index];\n";
|
||||
}
|
||||
|
||||
if (sm_._seen_EOL_assertion)
|
||||
{
|
||||
os_ << " std::size_t const 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_ << " std::size_t const state_ =\n";
|
||||
|
||||
if (lookups_ == 256)
|
||||
{
|
||||
os_ << " ptr_[lookup_[<typename Traits::index_type>"
|
||||
"(*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_ << " std::size_t const 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_ << " std::size_t const 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_ << " std::size_t const 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_on_nomatch)
|
||||
{
|
||||
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\n";
|
||||
|
||||
os_ << "}}}} // namespace boost::spirit::lex::static_\n\n";
|
||||
|
||||
os_ << "#endif\n";
|
||||
|
||||
return os_.good();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}}}} // namespace boost::spirit::lex::detail
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Lexer>
|
||||
inline bool
|
||||
generate_static(Lexer const& lexer, std::ostream& os,
|
||||
char const* name_suffix = "")
|
||||
{
|
||||
if (!lexer.get_definition().init_dfa())
|
||||
return false;
|
||||
return detail::generate_cpp(lexer.get_definition().state_machine,
|
||||
lexer.get_definition().rules, os, name_suffix, false, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}}}
|
||||
|
||||
#endif
|
||||
117
include/boost/spirit/home/lex/lexer/lexertl/lexertl_iterator.hpp
Normal file
117
include/boost/spirit/home/lex/lexer/lexertl/lexertl_iterator.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// 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_LEX_LEXER_ITERATOR_MAR_16_2007_0353PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_ITERATOR_MAR_16_2007_0353PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
#include <boost/spirit/home/support/iterators/detail/buf_id_check_policy.hpp>
|
||||
#else
|
||||
#include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
|
||||
#endif
|
||||
#include <boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/ref_counted_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/split_std_deque_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Divide the given functor type into its components (unique and shared)
|
||||
// and build a std::pair from these parts
|
||||
template <typename Functor>
|
||||
struct make_functor
|
||||
{
|
||||
typedef
|
||||
std::pair<typename Functor::unique, typename Functor::shared>
|
||||
type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Divide the given functor type into its components (unique and shared)
|
||||
// and build a std::pair from these parts
|
||||
template <typename FunctorData>
|
||||
struct make_multi_pass
|
||||
{
|
||||
typedef
|
||||
std::pair<typename FunctorData::unique, typename FunctorData::shared>
|
||||
functor_data_type;
|
||||
typedef typename FunctorData::result_type result_type;
|
||||
|
||||
typedef multi_pass_policies::split_functor_input input_policy;
|
||||
typedef multi_pass_policies::ref_counted ownership_policy;
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
typedef multi_pass_policies::buf_id_check check_policy;
|
||||
#else
|
||||
typedef multi_pass_policies::no_check check_policy;
|
||||
#endif
|
||||
typedef multi_pass_policies::split_std_deque storage_policy;
|
||||
|
||||
typedef multi_pass_policies::default_policy<
|
||||
input_policy, ownership_policy, check_policy, storage_policy>
|
||||
policy_type;
|
||||
typedef spirit::multi_pass<functor_data_type, policy_type> type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lexer_iterator exposes an iterator for a lexertl based dfa (lexer)
|
||||
// The template parameters have the same semantics as described for the
|
||||
// lexertl_functor above.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
class lexertl_iterator
|
||||
: public make_multi_pass<Functor>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Functor::unique unique_functor_type;
|
||||
typedef typename Functor::shared shared_functor_type;
|
||||
|
||||
typedef typename Functor::iterator_type base_iterator_type;
|
||||
typedef typename Functor::result_type token_type;
|
||||
|
||||
private:
|
||||
typedef
|
||||
typename make_multi_pass<Functor>::functor_data_type
|
||||
functor_type;
|
||||
typedef typename make_multi_pass<Functor>::type base_type;
|
||||
typedef typename Functor::char_type char_type;
|
||||
|
||||
public:
|
||||
// create a new iterator encapsulating the lexer object to be used
|
||||
// for tokenization
|
||||
template <typename IteratorData>
|
||||
lexertl_iterator(IteratorData const& iterdata_,
|
||||
base_iterator_type& first, base_iterator_type const& last)
|
||||
: base_type(functor_type(unique_functor_type(),
|
||||
shared_functor_type(iterdata_, first, last))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
// create an end iterator usable for end of range checking
|
||||
lexertl_iterator()
|
||||
{}
|
||||
|
||||
// set the new required state for the underlying lexer object
|
||||
std::size_t set_state(std::size_t state)
|
||||
{
|
||||
return unique_functor_type::set_state(*this, state);
|
||||
}
|
||||
|
||||
// map the given state name to a corresponding state id as understood
|
||||
// by the underlying lexer object
|
||||
std::size_t map_state(char_type const* statename)
|
||||
{
|
||||
return unique_functor_type::map_state(*this, statename);
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
356
include/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp
Normal file
356
include/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp
Normal file
@@ -0,0 +1,356 @@
|
||||
// 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_LEX_LEXERTL_LEXER_MAR_17_2007_0139PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXERTL_LEXER_MAR_17_2007_0139PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include <boost/spirit/home/support/safe_bool.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_token.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_iterator.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
#include <boost/spirit/home/support/detail/lexer/debug.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The must_escape function checks if the given character value needs
|
||||
// to be preceded by a backslash character to disable its special
|
||||
// meaning in the context of a regular expression
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
inline bool must_escape(Char c)
|
||||
{
|
||||
// FIXME: more needed?
|
||||
switch (c) {
|
||||
case '+': case '/': case '*': case '?':
|
||||
case '|':
|
||||
case '(': case ')':
|
||||
case '[': case ']':
|
||||
case '{': case '}':
|
||||
case '.':
|
||||
case '^': case '$':
|
||||
case '\\':
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The escape function returns the string representation of the given
|
||||
// character value, possibly escaped with a backslash character, to
|
||||
// allow it being safely used in a regular expression definition.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
inline std::basic_string<Char> escape(Char ch)
|
||||
{
|
||||
std::basic_string<Char> result(1, ch);
|
||||
if (detail::must_escape(ch))
|
||||
result.insert(0, 1, '\\');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lexertl_token_set
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token, typename Iterator = typename Token::iterator_type>
|
||||
class lexertl_token_set
|
||||
{
|
||||
protected:
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
public:
|
||||
// interface for token definition management
|
||||
void add_token (char_type const* state, string_type const& tokendef,
|
||||
std::size_t token_id)
|
||||
{
|
||||
rules.add(state, tokendef, token_id, state);
|
||||
}
|
||||
|
||||
// interface for pattern definition management
|
||||
void add_pattern (char_type const* state, string_type const& name,
|
||||
string_type const& patterndef)
|
||||
{
|
||||
add_state(state);
|
||||
rules.add_macro(name.c_str(), patterndef);
|
||||
}
|
||||
|
||||
boost::lexer::rules const& get_rules() const { return rules; }
|
||||
|
||||
void clear() { rules.clear(); }
|
||||
|
||||
std::size_t add_state(char_type const* state)
|
||||
{
|
||||
rules.add_state(state);
|
||||
return rules.state(state);
|
||||
}
|
||||
string_type initial_state() const
|
||||
{
|
||||
return string_type(rules.initial());
|
||||
}
|
||||
|
||||
private:
|
||||
boost::lexer::basic_rules<char_type> rules;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Lexer>
|
||||
bool generate_static(Lexer const& lex, std::ostream& os, char const* name);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Every lexer type to be used as a lexer for Spirit has to conform to
|
||||
// the following public interface:
|
||||
//
|
||||
// typedefs:
|
||||
// iterator_type The type of the iterator exposed by this lexer.
|
||||
// token_type The type of the tokens returned from the exposed
|
||||
// iterators.
|
||||
// token_set The type of the token set representing a lexer
|
||||
// state.
|
||||
//
|
||||
// functions:
|
||||
// default constructor
|
||||
// Since lexers are instantiated as base classes
|
||||
// only it might be a good idea to make this
|
||||
// constructor protected.
|
||||
// begin, end Return a pair of iterators, when dereferenced
|
||||
// returning the sequence of tokens recognized in
|
||||
// the input stream given as the parameters to the
|
||||
// begin() function.
|
||||
// add_token Should add the definition of a token to be
|
||||
// recognized by this lexer.
|
||||
// clear Should delete all current token definitions
|
||||
// associated with the given state of this lexer
|
||||
// object.
|
||||
//
|
||||
// template parameters:
|
||||
// Iterator The type of the iterator used to access the
|
||||
// underlying character stream.
|
||||
// Token The type of the tokens to be returned from the
|
||||
// exposed token iterator.
|
||||
// Functor The type of the InputPolicy to use to instantiate
|
||||
// the multi_pass iterator type to be used as the
|
||||
// token iterator (returned from begin()/end()).
|
||||
// TokenSet The type of the token set to use in conjunction
|
||||
// with this lexer type. This is used for the
|
||||
// token_set typedef described above only.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lexertl_lexer class is a implementation of a Spirit.Lex lexer on
|
||||
// top of Ben Hanson's lexertl library as outlined above (For more
|
||||
// information about lexertl go here: http://www.benhanson.net/lexertl.html).
|
||||
//
|
||||
// This class is supposed to be used as the first and only template
|
||||
// parameter while instantiating instances of a lex::lexer_def class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Token = lexertl_token<>,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename Functor = lexertl_functor<Token, Iterator, mpl::false_>,
|
||||
typename TokenSet = token_set<lexertl_token_set<Token, Iterator> >
|
||||
>
|
||||
class lexertl_lexer
|
||||
: public safe_bool<lexertl_lexer<Token, Iterator, Functor, TokenSet> >
|
||||
{
|
||||
public:
|
||||
// operator_bool() is needed for the safe_bool base class
|
||||
bool operator_bool() const { return initialized_dfa; }
|
||||
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
// Every lexer type to be used as a lexer for Spirit has to conform to
|
||||
// a public interface .
|
||||
typedef Token token_type;
|
||||
typedef TokenSet token_set;
|
||||
typedef lexertl_iterator<Functor> iterator_type;
|
||||
|
||||
// Return the start iterator usable for iterating over the generated
|
||||
// tokens.
|
||||
iterator_type begin(Iterator& first, Iterator const& last) const
|
||||
{
|
||||
struct iterator_data_type {
|
||||
boost::lexer::state_machine const& state_machine_;
|
||||
boost::lexer::basic_rules<char_type> const& rules_;
|
||||
typename Functor::semantic_actions_type const& actions_;
|
||||
};
|
||||
|
||||
iterator_data_type iterator_data = { state_machine, rules, actions };
|
||||
return init_dfa() ? iterator_type(iterator_data, first, last)
|
||||
: iterator_type();
|
||||
}
|
||||
|
||||
// Return the end iterator usable to stop iterating over the generated
|
||||
// tokens.
|
||||
iterator_type end() const
|
||||
{
|
||||
return iterator_type();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Lexer instances can be created by means of a derived class only.
|
||||
lexertl_lexer()
|
||||
: initialized_dfa(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
// interface for token definition management
|
||||
void add_token (char_type const* state, string_type const& tokendef,
|
||||
std::size_t token_id)
|
||||
{
|
||||
add_state(state);
|
||||
rules.add(state, tokendef, token_id, state);
|
||||
initialized_dfa = false;
|
||||
}
|
||||
void add_token(char_type const* state, token_set& tokset)
|
||||
{
|
||||
add_state(state);
|
||||
rules.add(state, tokset.get_rules());
|
||||
initialized_dfa = false;
|
||||
}
|
||||
|
||||
// interface for pattern definition management
|
||||
void add_pattern (char_type const* state, string_type const& name,
|
||||
string_type const& patterndef)
|
||||
{
|
||||
add_state(state);
|
||||
rules.add_macro(name.c_str(), patterndef);
|
||||
initialized_dfa = false;
|
||||
}
|
||||
|
||||
void clear(char_type const* state)
|
||||
{
|
||||
std::size_t s = rules.state(state);
|
||||
if (boost::lexer::npos != s)
|
||||
rules.clear(state);
|
||||
initialized_dfa = false;
|
||||
}
|
||||
std::size_t add_state(char_type const* state)
|
||||
{
|
||||
std::size_t stateid = rules.state(state);
|
||||
if (boost::lexer::npos == stateid) {
|
||||
rules.add_state(state);
|
||||
stateid = rules.state(state);
|
||||
initialized_dfa = false;
|
||||
}
|
||||
return stateid;
|
||||
}
|
||||
string_type initial_state() const
|
||||
{
|
||||
return string_type(rules.initial());
|
||||
}
|
||||
|
||||
// Register a semantic action with the given id
|
||||
template <typename F>
|
||||
void add_action(std::size_t id, F act)
|
||||
{
|
||||
// If you get compilation errors below stating value_type not being
|
||||
// a member of boost::fusion::unused_type, then you are probably
|
||||
// using semantic actions in your token definition without
|
||||
// the lexertl_actor_lexer being specified as the base class
|
||||
// (instead of the lexertl_lexer class).
|
||||
typedef
|
||||
typename Functor::semantic_actions_type::value_type
|
||||
value_type;
|
||||
|
||||
actions.insert(value_type(id, act));
|
||||
}
|
||||
|
||||
bool init_dfa() const
|
||||
{
|
||||
if (!initialized_dfa) {
|
||||
state_machine.clear();
|
||||
try {
|
||||
typedef boost::lexer::basic_generator<char_type> generator;
|
||||
generator::build (rules, state_machine);
|
||||
generator::minimise (state_machine);
|
||||
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
boost::lexer::debug::dump(state_machine, std::cerr);
|
||||
#endif
|
||||
}
|
||||
catch (std::runtime_error const&) {
|
||||
return false;
|
||||
}
|
||||
initialized_dfa = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable boost::lexer::state_machine state_machine;
|
||||
boost::lexer::basic_rules<char_type> rules;
|
||||
typename Functor::semantic_actions_type actions;
|
||||
mutable bool initialized_dfa;
|
||||
|
||||
template <typename Lexer>
|
||||
friend bool generate_static(Lexer const&, std::ostream&, char const*);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lexertl_actor_lexer class is another implementation of a Spirit.Lex
|
||||
// lexer on top of Ben Hanson's lexertl library as outlined above (For
|
||||
// more information about lexertl go here:
|
||||
// http://www.benhanson.net/lexertl.html).
|
||||
//
|
||||
// The only difference to the lexertl_lexer class above is that token_def
|
||||
// definitions may have semantic (lexer) actions attached while being
|
||||
// defined:
|
||||
//
|
||||
// int w;
|
||||
// token_def word = "[^ \t\n]+";
|
||||
// self = word[++ref(w)]; // see example: word_count_lexer
|
||||
//
|
||||
// This class is supposed to be used as the first and only template
|
||||
// parameter while instantiating instances of a lex::lexer_def class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Token = lexertl_token<>,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename Functor = lexertl_functor<Token, Iterator, mpl::true_>,
|
||||
typename TokenSet = token_set<lexertl_token_set<Token, Iterator> >
|
||||
>
|
||||
class lexertl_actor_lexer
|
||||
: public lexertl_lexer<Token, Iterator, Functor, TokenSet>
|
||||
{
|
||||
protected:
|
||||
// Lexer instances can be created by means of a derived class only.
|
||||
lexertl_actor_lexer() {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,343 @@
|
||||
// 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_LEX_LEXER_STATIC_FUNCTOR_FEB_10_2008_0755PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_STATIC_FUNCTOR_FEB_10_2008_0755PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <map>
|
||||
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
|
||||
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
|
||||
|
||||
#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
||||
#define BOOST_SPIRIT_EOF_PREFIX static
|
||||
#else
|
||||
#define BOOST_SPIRIT_EOF_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename HasActors, typename HasState>
|
||||
struct Data; // no default specialization
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// doesn't support no state and no actors
|
||||
template <typename Iterator>
|
||||
struct Data<Iterator, mpl::false_, mpl::false_>
|
||||
{
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
typedef std::size_t (*next_token_functor)(std::size_t&,
|
||||
Iterator const&, Iterator&, Iterator const&);
|
||||
|
||||
typedef unused_type semantic_actions_type;
|
||||
|
||||
// initialize the shared data
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: next_token(data_.next_), first(first_), last(last_)
|
||||
{}
|
||||
|
||||
std::size_t next(Iterator& end)
|
||||
{
|
||||
typedef basic_iterator_tokeniser<Iterator> tokenizer;
|
||||
std::size_t state;
|
||||
return next_token(state, first, end, last);
|
||||
}
|
||||
|
||||
// nothing to invoke, so this is empty
|
||||
bool invoke_actions(std::size_t, Iterator const&)
|
||||
{
|
||||
return true; // always accept
|
||||
}
|
||||
|
||||
std::size_t get_state() const { return 0; }
|
||||
void set_state_name (char const*) {}
|
||||
|
||||
next_token_functor next_token;
|
||||
Iterator& first;
|
||||
Iterator last;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// doesn't support no actors
|
||||
template <typename Iterator>
|
||||
struct Data<Iterator, mpl::false_, mpl::true_>
|
||||
: Data<Iterator, mpl::false_, mpl::false_>
|
||||
{
|
||||
typedef Data<Iterator, mpl::false_, mpl::false_> base_type;
|
||||
|
||||
// initialize the shared data
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: base_type(data_, first_, last_), state(0)
|
||||
{}
|
||||
|
||||
std::size_t next(Iterator& end)
|
||||
{
|
||||
typedef basic_iterator_tokeniser<Iterator> tokenizer;
|
||||
return this->next_token(state, this->first, end, this->last);
|
||||
}
|
||||
|
||||
std::size_t& get_state() { return state; }
|
||||
void set_state_name (char_type const* new_state)
|
||||
{
|
||||
std::size_t state_id = this->rules.state(new_state);
|
||||
BOOST_ASSERT(state_id != boost::lexer::npos);
|
||||
if (state_id != boost::lexer::npos)
|
||||
state = state_id;
|
||||
}
|
||||
|
||||
std::size_t state;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// does support actors, but may have no state
|
||||
template <typename Iterator, typename HasState>
|
||||
struct Data<Iterator, mpl::true_, HasState>
|
||||
: Data<Iterator, mpl::false_, HasState>
|
||||
{
|
||||
typedef Data<Iterator, mpl::false_, HasState> base_type;
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
typedef void functor_type(iterpair_type, std::size_t, Data&, bool&);
|
||||
typedef boost::function<functor_type> functor_wrapper_type;
|
||||
typedef std::multimap<std::size_t, functor_wrapper_type>
|
||||
semantic_actions_type;
|
||||
|
||||
template <typename IterData>
|
||||
Data (IterData const& data_, Iterator& first_, Iterator const& last_)
|
||||
: base_type(data_, first_, last_),
|
||||
actions(data_.actions_)
|
||||
{}
|
||||
|
||||
// invoke attached semantic actions, if defined
|
||||
bool invoke_actions(std::size_t id, Iterator const& end)
|
||||
{
|
||||
if (actions.empty())
|
||||
return true; // nothing to invoke, continue with 'match'
|
||||
|
||||
iterpair_type itp(this->first, end);
|
||||
bool match = true;
|
||||
|
||||
typedef typename
|
||||
semantic_actions_type::const_iterator
|
||||
iterator_type;
|
||||
|
||||
std::pair<iterator_type, iterator_type> p = actions.equal_range(id);
|
||||
while (p.first != p.second)
|
||||
{
|
||||
((*p.first).second)(itp, id, *this, match);
|
||||
if (!match)
|
||||
return false; // return a 'no-match'
|
||||
++p.first;
|
||||
}
|
||||
return true; // normal execution
|
||||
}
|
||||
|
||||
semantic_actions_type const& actions;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lexertl_static_functor is a template usable as the functor object for
|
||||
// the multi_pass iterator allowing to wrap a lexertl based dfa into a
|
||||
// iterator based interface.
|
||||
//
|
||||
// Iterator: the type of the underlying iterator
|
||||
// Token: the type of the tokens produced by this functor
|
||||
// this needs to expose a constructor with the following
|
||||
// prototype:
|
||||
//
|
||||
// Token(std::size_t id, std::size_t state,
|
||||
// Iterator start, Iterator end)
|
||||
//
|
||||
// where 'id' is the token id, state is the lexer state,
|
||||
// this token has been matched in, and 'first' and 'end'
|
||||
// mark the start and the end of the token with respect
|
||||
// to the underlying character stream.
|
||||
// SupportsActors:
|
||||
// this is expected to be a mpl::bool_, if mpl::true_ the
|
||||
// lexertl_static_functor invokes functors which
|
||||
// (optionally) have been attached to the token definitions.
|
||||
// SupportState:
|
||||
// this is expected to be a mpl::bool_, if mpl::true_ the
|
||||
// lexertl_functor supports different lexer states,
|
||||
// otherwise no lexer state is supported.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename SupportsActors = mpl::false_,
|
||||
typename SupportsState = typename Token::has_state>
|
||||
class lexertl_static_functor
|
||||
{
|
||||
public:
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
|
||||
private:
|
||||
// Needed by compilers not implementing the resolution to DR45. For
|
||||
// reference, see
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
|
||||
template <typename Iterator_, typename HasActors, typename HasState>
|
||||
friend struct detail::Data;
|
||||
|
||||
// Helper template allowing to assign a value on exit
|
||||
template <typename T>
|
||||
struct assign_on_exit
|
||||
{
|
||||
assign_on_exit(T& dst_, T const& src_)
|
||||
: dst(dst_), src(src_)
|
||||
{}
|
||||
~assign_on_exit()
|
||||
{
|
||||
dst = src;
|
||||
}
|
||||
|
||||
T& dst;
|
||||
T const& src;
|
||||
};
|
||||
|
||||
public:
|
||||
lexertl_static_functor()
|
||||
#if 0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900
|
||||
, eof()
|
||||
#endif // 0 != __DECCXX_VER
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// interface to the multi_pass_policies::split_functor_input policy
|
||||
typedef Token result_type;
|
||||
typedef lexertl_static_functor unique;
|
||||
typedef detail::Data<Iterator, SupportsActors, SupportsState> shared;
|
||||
|
||||
BOOST_SPIRIT_EOF_PREFIX result_type const eof;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
typedef Iterator iterator_type;
|
||||
typedef typename shared::semantic_actions_type semantic_actions_type;
|
||||
typedef typename shared::next_token_functor next_token_functor;
|
||||
|
||||
template <typename MultiPass>
|
||||
result_type& operator()(MultiPass& mp, result_type& result)
|
||||
{
|
||||
shared& data = mp.shared->ftor;
|
||||
if (data.first == data.last)
|
||||
return result = eof;
|
||||
|
||||
Iterator end = data.first;
|
||||
std::size_t id = data.next(end);
|
||||
|
||||
if (boost::lexer::npos == id) { // no match
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
std::string next;
|
||||
Iterator it = data.first;
|
||||
for (std::size_t i = 0; i < 10 && it != data.last; ++it, ++i)
|
||||
next += *it;
|
||||
|
||||
std::cerr << "Not matched, in state: " << data.state
|
||||
<< ", lookahead: >" << next << "<" << std::endl;
|
||||
#endif
|
||||
return result = result_type(0);
|
||||
}
|
||||
else if (0 == id) { // EOF reached
|
||||
return result = eof;
|
||||
}
|
||||
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
{
|
||||
std::string next;
|
||||
Iterator it = data.first;
|
||||
for (std::size_t i = 0; i < 10 && it != data.last; ++it, ++i)
|
||||
next += *it;
|
||||
|
||||
std::cerr << "Matched: " << id << ", in state: "
|
||||
<< data.state << ", string: >"
|
||||
<< std::basic_string<char_type>(data.first, end) << "<"
|
||||
<< ", lookahead: >" << next << "<" << std::endl;
|
||||
}
|
||||
#endif
|
||||
// invoke_actions might change state
|
||||
std::size_t state = data.get_state();
|
||||
|
||||
// invoke attached semantic actions, if there are any defined
|
||||
if (!data.invoke_actions(id, end))
|
||||
{
|
||||
// one of the semantic actions signaled no-match
|
||||
return result = result_type(0);
|
||||
}
|
||||
|
||||
// return matched token, advancing 'data.first' past the matched
|
||||
// sequence
|
||||
assign_on_exit<Iterator> on_exit(data.first, end);
|
||||
return result = result_type(id, state, data.first, end);
|
||||
}
|
||||
|
||||
// set_state is propagated up to the iterator interface, allowing to
|
||||
// manipulate the current lexer state through any of the exposed
|
||||
// iterators.
|
||||
template <typename MultiPass>
|
||||
static std::size_t set_state(MultiPass& mp, std::size_t state_)
|
||||
{
|
||||
std::size_t oldstate = mp.shared->ftor.state;
|
||||
mp.shared->ftor.state = state_;
|
||||
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
std::cerr << "Switching state from: " << oldstate
|
||||
<< " to: " << state_
|
||||
<< std::endl;
|
||||
#endif
|
||||
return oldstate;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static std::size_t
|
||||
map_state(MultiPass const& mp, char_type const* statename)
|
||||
{
|
||||
return mp.shared->ftor.rules.state(statename);
|
||||
}
|
||||
};
|
||||
|
||||
#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// eof token
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token, typename Iterator, typename SupportsActors,
|
||||
typename SupportsState>
|
||||
typename lexertl_static_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::result_type const
|
||||
lexertl_static_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::eof =
|
||||
typename lexertl_static_functor<
|
||||
Token, Iterator, SupportsActors, SupportsState>::result_type();
|
||||
#endif // 0 != __COMO_VERSION__
|
||||
|
||||
}}}
|
||||
|
||||
#undef BOOST_SPIRIT_EOF_PREFIX
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,299 @@
|
||||
// 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_LEX_LEXERTL_STATIC_LEXER_FEB_10_2008_0753PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXERTL_STATIC_LEXER_FEB_10_2008_0753PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/safe_bool.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_token.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_static_functor.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/lexertl/lexertl_iterator.hpp>
|
||||
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
|
||||
#include <boost/spirit/home/support/detail/lexer/debug.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The escape function returns the string representation of the given
|
||||
// character value, possibly escaped with a backslash character, to
|
||||
// allow it being safely used in a regular expression definition.
|
||||
//
|
||||
// In the case of the static lexer this function does nothing.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Char>
|
||||
inline std::basic_string<Char> escape(Char ch)
|
||||
{
|
||||
return std::basic_string<Char>(1, ch);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forward declaration only
|
||||
namespace static_
|
||||
{
|
||||
// Both items, the table of names and the function to return the next
|
||||
// token have to be generated using the function generate_static().
|
||||
//
|
||||
// This is a forward declaration for the generated static table of
|
||||
// valid state names
|
||||
extern char const* const lexer_state_names[];
|
||||
|
||||
// This is the forward declaration of the generated function to be
|
||||
// called to get the next token.
|
||||
template <typename Iterator>
|
||||
std::size_t next_token (std::size_t& state_, Iterator const& start_,
|
||||
Iterator ¤t_, Iterator const& end_);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// lexertl_static_token_set
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Token, typename Iterator = typename Token::iterator_type>
|
||||
class lexertl_static_token_set
|
||||
{
|
||||
protected:
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
public:
|
||||
// interface for token definition management
|
||||
void add_token (char_type const* state, string_type const& tokendef,
|
||||
std::size_t token_id)
|
||||
{}
|
||||
|
||||
// interface for pattern definition management
|
||||
void add_pattern (char_type const* state, string_type const& name,
|
||||
string_type const& patterndef)
|
||||
{}
|
||||
|
||||
void clear() {}
|
||||
|
||||
std::size_t add_state(char_type const* state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
string_type initial_state() const
|
||||
{
|
||||
return lex::static_::lexer_state_names[0];
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Every lexer type to be used as a lexer for Spirit has to conform to
|
||||
// the following public interface:
|
||||
//
|
||||
// typedefs:
|
||||
// iterator_type The type of the iterator exposed by this lexer.
|
||||
// token_type The type of the tokens returned from the exposed
|
||||
// iterators.
|
||||
// token_set The type of the token set representing a lexer
|
||||
// state.
|
||||
//
|
||||
// functions:
|
||||
// default constructor
|
||||
// Since lexers are instantiated as base classes
|
||||
// only it might be a good idea to make this
|
||||
// constructor protected.
|
||||
// begin, end Return a pair of iterators, when dereferenced
|
||||
// returning the sequence of tokens recognized in
|
||||
// the input stream given as the parameters to the
|
||||
// begin() function.
|
||||
// add_token Should add the definition of a token to be
|
||||
// recognized by this lexer.
|
||||
// clear Should delete all current token definitions
|
||||
// associated with the given state of this lexer
|
||||
// object.
|
||||
//
|
||||
// template parameters:
|
||||
// Token The type of the tokens to be returned from the
|
||||
// exposed token iterator.
|
||||
// Iterator The type of the iterator used to access the
|
||||
// underlying character stream.
|
||||
// Functor The type of the InputPolicy to use to instantiate
|
||||
// the multi_pass iterator type to be used as the
|
||||
// token iterator (returned from begin()/end()).
|
||||
// TokenSet The type of the token set to use in conjunction
|
||||
// with this lexer type. This is used for the
|
||||
// token_set typedef described above only.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lexertl_static_lexer class is a implementation of a Spirit.Lex
|
||||
// lexer on top of Ben Hanson's lexertl library (For more information
|
||||
// about lexertl go here: http://www.benhanson.net/lexertl.html).
|
||||
//
|
||||
// This class is designed to be used in conjunction with a generated,
|
||||
// static lexer. For more information see the documentation (The Static
|
||||
// Lexer Model).
|
||||
//
|
||||
// This class is supposed to be used as the first and only template
|
||||
// parameter while instantiating instances of a lex::lexer_def class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Token = lexertl_token<>,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename Functor = lexertl_static_functor<Token, Iterator, mpl::false_>,
|
||||
typename TokenSet = token_set<lexertl_static_token_set<Token, Iterator> >
|
||||
>
|
||||
class lexertl_static_lexer
|
||||
: public safe_bool<lexertl_static_lexer<Token, Iterator, Functor, TokenSet> >
|
||||
{
|
||||
public:
|
||||
// operator_bool() is needed for the safe_bool base class
|
||||
bool operator_bool() const { return true; }
|
||||
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
// Every lexer type to be used as a lexer for Spirit has to conform to
|
||||
// a public interface
|
||||
typedef Token token_type;
|
||||
typedef TokenSet token_set;
|
||||
typedef lexertl_iterator<Functor> iterator_type;
|
||||
|
||||
// Return the start iterator usable for iterating over the generated
|
||||
// tokens, the Functor F is called to match the next token from the
|
||||
// input.
|
||||
template <typename F>
|
||||
iterator_type begin(Iterator& first, Iterator const& last, F next) const
|
||||
{
|
||||
struct iterator_data_type {
|
||||
typename Functor::next_token_functor next_;
|
||||
typename Functor::semantic_actions_type const& actions_;
|
||||
};
|
||||
|
||||
iterator_data_type iterator_data = { next, actions };
|
||||
return iterator_type(iterator_data, first, last);
|
||||
}
|
||||
|
||||
// Return the start iterator usable for iterating over the generated
|
||||
// tokens, the generated function next_token(...) is called to match
|
||||
// the next token from the input.
|
||||
template <typename Iterator_>
|
||||
iterator_type begin(Iterator_& first, Iterator_ const& last) const
|
||||
{
|
||||
struct iterator_data_type {
|
||||
typename Functor::next_token_functor next_;
|
||||
typename Functor::semantic_actions_type const& actions_;
|
||||
};
|
||||
|
||||
iterator_data_type iterator_data =
|
||||
{ &lex::static_::next_token<Iterator_>, actions };
|
||||
return iterator_type(iterator_data, first, last);
|
||||
}
|
||||
|
||||
// Return the end iterator usable to stop iterating over the generated
|
||||
// tokens.
|
||||
iterator_type end() const
|
||||
{
|
||||
return iterator_type();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Lexer instances can be created by means of a derived class only.
|
||||
lexertl_static_lexer() {}
|
||||
|
||||
public:
|
||||
// interface for token definition management
|
||||
void add_token (char_type const* state, string_type const& tokendef,
|
||||
std::size_t token_id)
|
||||
{}
|
||||
void add_token(char_type const* state, token_set& tokset)
|
||||
{}
|
||||
|
||||
// interface for pattern definition management
|
||||
void add_pattern (char_type const* state, string_type const& name,
|
||||
string_type const& patterndef)
|
||||
{}
|
||||
|
||||
void clear(char_type const* state) {}
|
||||
|
||||
std::size_t add_state(char_type const* state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
string_type initial_state() const
|
||||
{
|
||||
return lex::static_::lexer_state_names[0];
|
||||
}
|
||||
|
||||
// register a semantic action with the given id
|
||||
template <typename F>
|
||||
void add_action(std::size_t id, F act)
|
||||
{
|
||||
// If you get compilation errors below stating value_type not being
|
||||
// a member of boost::fusion::unused_type, then you are probably
|
||||
// using semantic actions in your token definition without
|
||||
// the lexertl_static_actor_lexer being specified as the base class
|
||||
// (instead of the lexertl_static_lexer class).
|
||||
typedef
|
||||
typename Functor::semantic_actions_type::value_type
|
||||
value_type;
|
||||
|
||||
actions.insert(value_type(id, act));
|
||||
}
|
||||
|
||||
bool init_dfa() const { return true; }
|
||||
|
||||
private:
|
||||
typename Functor::semantic_actions_type actions;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lexertl_static_actor_lexer class is another implementation of a
|
||||
// Spirit.Lex lexer on top of Ben Hanson's lexertl library as outlined
|
||||
// above (For more information about lexertl go here:
|
||||
// http://www.benhanson.net/lexertl.html).
|
||||
//
|
||||
// Just as the lexertl_static_lexer class it is meant to be used with
|
||||
// a statically generated lexer as outlined above.
|
||||
//
|
||||
// The only difference to the lexertl_static_lexer class above is that
|
||||
// token_def definitions may have semantic (lexer) actions attached while
|
||||
// being defined:
|
||||
//
|
||||
// int w;
|
||||
// token_def<> word = "[^ \t\n]+";
|
||||
// self = word[++ref(w)]; // see example: word_count_lexer
|
||||
//
|
||||
// This class is supposed to be used as the first and only template
|
||||
// parameter while instantiating instances of a lex::lexer_def class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Token = lexertl_token<>,
|
||||
typename Iterator = typename Token::iterator_type,
|
||||
typename Functor = lexertl_static_functor<Token, Iterator, mpl::true_>,
|
||||
typename TokenSet = token_set<lexertl_static_token_set<Token, Iterator> >
|
||||
>
|
||||
class lexertl_static_actor_lexer
|
||||
: public lexertl_static_lexer<Token, Iterator, Functor, TokenSet>
|
||||
{
|
||||
protected:
|
||||
// Lexer instances can be created by means of a derived class only.
|
||||
lexertl_static_actor_lexer() {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
424
include/boost/spirit/home/lex/lexer/lexertl/lexertl_token.hpp
Normal file
424
include/boost/spirit/home/lex/lexer/lexertl/lexertl_token.hpp
Normal file
@@ -0,0 +1,424 @@
|
||||
// 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_LEX_LEXERTL_TOKEN_FEB_10_2008_0751PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXERTL_TOKEN_FEB_10_2008_0751PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/detail/assign_to.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/begin.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lexertl_token is the type of the objects returned by default by the
|
||||
// lexertl_iterator.
|
||||
//
|
||||
// template parameters:
|
||||
// Iterator The type of the iterator used to access the
|
||||
// underlying character stream.
|
||||
// AttributeTypes A mpl sequence containing the types of all
|
||||
// required different token values to be supported
|
||||
// by this token type.
|
||||
// HasState A mpl::bool_ indicating, whether this token type
|
||||
// should support lexer states.
|
||||
//
|
||||
// It is possible to use other token types with the spirit::lex
|
||||
// framework as well. If you plan to use a different type as your token
|
||||
// type, you'll need to expose the following things from your token type
|
||||
// to make it compatible with spirit::lex:
|
||||
//
|
||||
// typedefs
|
||||
// iterator_type The type of the iterator used to access the
|
||||
// underlying character stream.
|
||||
//
|
||||
// methods
|
||||
// default constructor
|
||||
// This should initialize the token as an end of
|
||||
// input token.
|
||||
// constructors The prototype of the other required
|
||||
// constructors should be:
|
||||
//
|
||||
// token(int)
|
||||
// This constructor should initialize the token as
|
||||
// an invalid token (not carrying any specific
|
||||
// values)
|
||||
//
|
||||
// where: the int is used as a tag only and its value is
|
||||
// ignored
|
||||
//
|
||||
// and:
|
||||
//
|
||||
// token(std::size_t id, std::size_t state,
|
||||
// iterator_type first, iterator_type last);
|
||||
//
|
||||
// where: id: token id
|
||||
// state: lexer state this token was matched in
|
||||
// first, last: pair of iterators marking the matched
|
||||
// range in the underlying input stream
|
||||
//
|
||||
// accessors
|
||||
// id() return the token id of the matched input sequence
|
||||
//
|
||||
// state() return the lexer state this token was matched in
|
||||
//
|
||||
// value() return the token value
|
||||
//
|
||||
// Additionally, you will have to implement a couple of helper functions
|
||||
// in the same namespace as the token type: a comparison operator==() to
|
||||
// compare your token instances, a token_is_valid() function and different
|
||||
// construct() function overloads as described below.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Iterator = char const*,
|
||||
typename AttributeTypes = mpl::vector0<>,
|
||||
typename HasState = mpl::true_
|
||||
>
|
||||
struct lexertl_token;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization of the toke type doesn't contain any item data and
|
||||
// doesn't support working with lexer states.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct lexertl_token<Iterator, omitted, mpl::false_>
|
||||
{
|
||||
typedef Iterator iterator_type;
|
||||
typedef mpl::false_ has_state;
|
||||
|
||||
// default constructed tokens correspond to EOI tokens
|
||||
lexertl_token()
|
||||
: id_(boost::lexer::npos)
|
||||
{}
|
||||
|
||||
// construct an invalid token
|
||||
lexertl_token(int)
|
||||
: id_(0)
|
||||
{}
|
||||
|
||||
lexertl_token(std::size_t id, std::size_t)
|
||||
: id_(id)
|
||||
{}
|
||||
|
||||
lexertl_token(std::size_t id, std::size_t,
|
||||
Iterator const&, Iterator const&)
|
||||
: id_(id)
|
||||
{}
|
||||
|
||||
// this default conversion operator is needed to allow the direct
|
||||
// usage of tokens in conjunction with the primitive parsers defined
|
||||
// in Qi
|
||||
operator std::size_t() const { return id_; }
|
||||
|
||||
std::size_t id() const { return id_; }
|
||||
std::size_t state() const { return 0; } // always '0' (INITIAL state)
|
||||
|
||||
protected:
|
||||
std::size_t id_; // token id, 0 if nothing has been matched
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This specialization of the toke type doesn't contain any item data but
|
||||
// supports working with lexer states.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct lexertl_token<Iterator, omitted, mpl::true_>
|
||||
: lexertl_token<Iterator, omitted, mpl::false_>
|
||||
{
|
||||
private:
|
||||
typedef lexertl_token<Iterator, omitted, mpl::false_> base_type;
|
||||
|
||||
public:
|
||||
typedef Iterator iterator_type;
|
||||
typedef mpl::true_ has_state;
|
||||
|
||||
// default constructed tokens correspond to EOI tokens
|
||||
lexertl_token()
|
||||
: state_(boost::lexer::npos)
|
||||
{}
|
||||
|
||||
// construct an invalid token
|
||||
lexertl_token(int)
|
||||
: base_type(0), state_(boost::lexer::npos)
|
||||
{}
|
||||
|
||||
lexertl_token(std::size_t id, std::size_t state)
|
||||
: base_type(id, boost::lexer::npos), state_(state)
|
||||
{}
|
||||
|
||||
lexertl_token(std::size_t id, std::size_t state,
|
||||
Iterator const&, Iterator const&)
|
||||
: base_type(id, boost::lexer::npos), state_(state)
|
||||
{}
|
||||
|
||||
std::size_t state() const { return state_; }
|
||||
|
||||
protected:
|
||||
std::size_t state_; // lexer state this token was matched in
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The generic version of the lexertl_token type derives from the
|
||||
// specialization above and adds a single data member holding the item
|
||||
// data carried by the token instance.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Metafunction to calculate the type of the variant data item to be
|
||||
// stored with each token instance.
|
||||
//
|
||||
// Note: The iterator pair needs to be the first type in the list of
|
||||
// types supported by the generated variant type (this is being
|
||||
// used to identify whether the stored data item in a particular
|
||||
// token instance needs to be converted from the pair of
|
||||
// iterators (see the first of the construct() functions below).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename IteratorPair, typename AttributeTypes>
|
||||
struct token_value_typesequence
|
||||
{
|
||||
typedef typename
|
||||
mpl::insert<
|
||||
AttributeTypes,
|
||||
typename mpl::begin<AttributeTypes>::type,
|
||||
IteratorPair
|
||||
>::type
|
||||
sequence_type;
|
||||
typedef typename make_variant_over<sequence_type>::type type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The type of the data item stored with a token instance is defined
|
||||
// by the template parameter 'AttributeTypes' and may be:
|
||||
//
|
||||
// omitted: no data item is stored with the token
|
||||
// instance (this is handled by the
|
||||
// specializations of the lexertl_token class
|
||||
// below)
|
||||
// mpl::vector0<>: each token instance stores a pair of
|
||||
// iterators pointing to the matched input
|
||||
// sequence
|
||||
// mpl::vector<...>: each token instance stores a variant being
|
||||
// able to store the pair of iterators pointing
|
||||
// to the matched input sequence, or any of the
|
||||
// types a specified in the mpl::vector<>
|
||||
//
|
||||
// All this is done to ensure the token type is as small (in terms
|
||||
// of its byte-size) as possible.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename IteratorPair, typename AttributeTypes>
|
||||
struct token_value_type
|
||||
{
|
||||
typedef
|
||||
typename mpl::eval_if<
|
||||
is_same<AttributeTypes, mpl::vector0<> >,
|
||||
mpl::identity<IteratorPair>,
|
||||
token_value_typesequence<IteratorPair, AttributeTypes>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState>
|
||||
struct lexertl_token : lexertl_token<Iterator, omitted, HasState>
|
||||
{
|
||||
private: // precondition assertions
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
|
||||
is_same<AttributeTypes, omitted>::value));
|
||||
#endif
|
||||
typedef lexertl_token<Iterator, omitted, HasState> base_type;
|
||||
|
||||
protected:
|
||||
// If no additional token value types are given, the the token will
|
||||
// hold the plain pair of iterators pointing to the matched range
|
||||
// in the underlying input sequence. Otherwise the token value is
|
||||
// stored as a variant and will again hold the pair of iterators but
|
||||
// is able to hold any of the given data types as well. The conversion
|
||||
// from the iterator pair to the required data type is done when it is
|
||||
// accessed for the first time.
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef
|
||||
typename detail::token_value_type<iterpair_type, AttributeTypes>::type
|
||||
token_value_type;
|
||||
|
||||
public:
|
||||
typedef Iterator iterator_type;
|
||||
|
||||
// default constructed tokens correspond to EOI tokens
|
||||
lexertl_token()
|
||||
: value_(iterpair_type(iterator_type(), iterator_type()))
|
||||
{}
|
||||
|
||||
// construct an invalid token
|
||||
lexertl_token(int)
|
||||
: base_type(0), value_(iterpair_type(iterator_type(), iterator_type()))
|
||||
{}
|
||||
|
||||
lexertl_token(std::size_t id, std::size_t state,
|
||||
Iterator first, Iterator last)
|
||||
: base_type(id, state), value_(iterpair_type(first, last))
|
||||
{}
|
||||
|
||||
token_value_type& value() { return value_; }
|
||||
token_value_type const& value() const { return value_; }
|
||||
|
||||
protected:
|
||||
token_value_type value_; // token value, by default a pair of iterators
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// tokens are considered equal, if their id's match (these are unique)
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState>
|
||||
inline bool
|
||||
operator== (lexertl_token<Iterator, AttributeTypes, HasState> const& lhs,
|
||||
lexertl_token<Iterator, AttributeTypes, HasState> const& rhs)
|
||||
{
|
||||
return lhs.id() == rhs.id();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This overload is needed by the multi_pass/functor_input_policy to
|
||||
// validate a token instance. It has to be defined in the same namespace
|
||||
// as the token class itself to allow ADL to find it.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState>
|
||||
inline bool
|
||||
token_is_valid(lexertl_token<Iterator, AttributeTypes, HasState> const& t)
|
||||
{
|
||||
return 0 != t.id() && std::size_t(boost::lexer::npos) != t.id();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// We have to provide overloads for the construct() function allowing
|
||||
// to extract the needed value from the token. These overloads have to be
|
||||
// defined in the same namespace as the token class itself to allow ADL to
|
||||
// find them.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is called from the parse function of token_def if the token_def
|
||||
// has been defined to carry a special attribute type
|
||||
template <typename Attribute, typename Iterator, typename AttributeTypes,
|
||||
typename HasState>
|
||||
inline void construct(Attribute& attr,
|
||||
lexertl_token<Iterator, AttributeTypes, HasState>& t)
|
||||
{
|
||||
// The goal of this function is to avoid the conversion of the pair of
|
||||
// iterators (to the matched character sequence) into the token value
|
||||
// of the required type being done more than once. For this purpose it
|
||||
// checks whether the stored value type is still the default one (pair
|
||||
// of iterators) and if yes, replaces the pair of iterators with the
|
||||
// converted value to be returned from subsequent calls.
|
||||
|
||||
if (0 == t.value().which()) {
|
||||
// first access to the token value
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
iterpair_type const& ip = get<iterpair_type>(t.value());
|
||||
|
||||
// Interestingly enough we use the assign_to() framework defined in
|
||||
// Spirit.Qi allowing to convert the pair of iterators to almost any
|
||||
// required type (assign_to(), if available, uses the standard Spirit
|
||||
// parsers to do the conversion, and falls back to boost::lexical_cast
|
||||
// otherwise).
|
||||
qi::detail::assign_to(ip.begin(), ip.end(), attr);
|
||||
|
||||
// If you get an error during the compilation of the following
|
||||
// assignment expression, you probably forgot to list one or more
|
||||
// types used as token value types (in your token_def<...>
|
||||
// definitions) in your definition of the token class. I.e. any token
|
||||
// value type used for a token_def<...> definition has to be listed
|
||||
// during the declaration of the token type to use. For instance let's
|
||||
// assume we have two token_def's:
|
||||
//
|
||||
// token_def<int> number; number = "...";
|
||||
// token_def<std::string> identifier; identifier = "...";
|
||||
//
|
||||
// Then you'll have to use the following token type definition
|
||||
// (assuming you are using the lexertl_token class):
|
||||
//
|
||||
// typedef mpl::vector<int, std::string> token_values;
|
||||
// typedef lexertl_token<base_iter_type, token_values> token_type;
|
||||
//
|
||||
// where: base_iter_type is the iterator type used to expose the
|
||||
// underlying input stream.
|
||||
//
|
||||
// This token_type has to be used as the second template parameter
|
||||
// to the lexer class:
|
||||
//
|
||||
// typedef lexertl_lexer<base_iter_type, token_type> lexer_type;
|
||||
//
|
||||
// again, assuming you're using the lexertl_lexer<> template for your
|
||||
// tokenization.
|
||||
|
||||
t.value() = attr; // re-assign value
|
||||
}
|
||||
else {
|
||||
// reuse the already assigned value
|
||||
qi::detail::assign_to(get<Attribute>(t.value()), attr);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called from the parse function of token_def if the token type
|
||||
// has no special attribute type assigned
|
||||
template <typename Attribute, typename Iterator, typename HasState>
|
||||
inline void construct(Attribute& attr,
|
||||
lexertl_token<Iterator, mpl::vector0<>, HasState>& t)
|
||||
{
|
||||
// The default type returned by the token_def parser component (if it
|
||||
// has no token value type assigned) is the pair of iterators to the
|
||||
// matched character sequence.
|
||||
|
||||
qi::detail::assign_to(t.value().begin(), t.value().end(), attr);
|
||||
}
|
||||
|
||||
// This is called from the parse function of token_def if the token type
|
||||
// has been explicitly omitted (i.e. no attribute value is used), which
|
||||
// essentially means that every attribute gets initialized using default
|
||||
// constructed values.
|
||||
template <typename Attribute, typename Iterator, typename HasState>
|
||||
inline void
|
||||
construct(Attribute& attr, lexertl_token<Iterator, omitted, HasState>& t)
|
||||
{
|
||||
}
|
||||
|
||||
// This is called from the parse function of token_set or lexer_def_
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState>
|
||||
inline void
|
||||
construct(fusion::vector<std::size_t, iterator_range<Iterator> >& attr,
|
||||
lexertl_token<Iterator, AttributeTypes, HasState> const& t)
|
||||
{
|
||||
// The type returned by the token_set and lexer_def_ parser components
|
||||
// is a fusion::vector containing the token id of the matched token
|
||||
// and the pair of iterators to the matched character sequence.
|
||||
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef
|
||||
fusion::vector<std::size_t, iterator_range<Iterator> >
|
||||
attribute_type;
|
||||
|
||||
iterpair_type const& ip = get<iterpair_type>(t.value());
|
||||
attr = attribute_type(t.id(), get<iterpair_type>(t.value()));
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
156
include/boost/spirit/home/lex/lexer/meta_grammar.hpp
Normal file
156
include/boost/spirit/home/lex/lexer/meta_grammar.hpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) 2001-2007 Joel de Guzman
|
||||
// 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_LEX_LEXER_META_GRAMMAR_MAR_22_2007_0548PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_META_GRAMMAR_MAR_22_2007_0548PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/domain.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
||||
#include <boost/spirit/home/support/placeholders.hpp>
|
||||
#include <boost/spirit/home/support/meta_grammar.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// forward declarations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct terminal_director;
|
||||
struct sequence;
|
||||
struct action;
|
||||
struct string_token_def;
|
||||
struct char_token_def;
|
||||
|
||||
template<typename Attribute, typename Char>
|
||||
class token_def;
|
||||
|
||||
template <typename TokenSet>
|
||||
class token_set;
|
||||
|
||||
struct lexer_meta_grammar;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct is_valid_expr;
|
||||
|
||||
template <typename Expr, typename Enable>
|
||||
struct expr_transform;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// main lexer_meta_grammar in the lex namespace
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct token_def_meta_grammar
|
||||
: proto::or_<
|
||||
// token_def<>
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain,
|
||||
terminal_holder<proto::_, lex::token_def<proto::_, proto::_> >,
|
||||
terminal_director
|
||||
>,
|
||||
// token_set
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain,
|
||||
terminal_holder<proto::_, lex::token_set<proto::_> >,
|
||||
terminal_director
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// 'x', L'x', "x", L"x", std::string, std::wstring
|
||||
struct literal_token_def_meta_grammar
|
||||
: proto::or_<
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain, char, char_token_def
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain, wchar_t, char_token_def
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain, char const*, string_token_def
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain, wchar_t const*, string_token_def
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain,
|
||||
std::basic_string<char, proto::_, proto::_>,
|
||||
string_token_def
|
||||
>,
|
||||
meta_grammar::terminal_rule<
|
||||
lex::domain,
|
||||
std::basic_string<wchar_t, proto::_, proto::_>,
|
||||
string_token_def
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct action_lexer_meta_grammar
|
||||
: proto::or_<
|
||||
// semantic actions for tokens
|
||||
meta_grammar::binary_rule<
|
||||
lex::domain, proto::tag::subscript, action,
|
||||
token_def_meta_grammar, proto::when<proto::_, proto::_arg>
|
||||
>,
|
||||
meta_grammar::binary_rule<
|
||||
lex::domain, proto::tag::subscript, action,
|
||||
action_lexer_meta_grammar, proto::when<proto::_, proto::_arg>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
struct lexer_meta_grammar
|
||||
: proto::or_<
|
||||
// token_def<>, ' ', L' ', "...", L"...", std::string, std::wstring
|
||||
token_def_meta_grammar,
|
||||
literal_token_def_meta_grammar,
|
||||
// token_def[...]
|
||||
action_lexer_meta_grammar,
|
||||
// sequence delimited by '|'
|
||||
meta_grammar::binary_rule_flat<
|
||||
lex::domain, proto::tag::bitwise_or, sequence,
|
||||
lexer_meta_grammar
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// These specializations non-intrusively hook into the Lex meta-grammar.
|
||||
// (see lex/meta_grammar.hpp)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
struct is_valid_expr<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, lexer_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct expr_transform<
|
||||
Expr,
|
||||
typename enable_if<
|
||||
proto::matches<Expr, lexer_meta_grammar>
|
||||
>::type
|
||||
>
|
||||
: mpl::identity<lexer_meta_grammar>
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
32
include/boost/spirit/home/lex/lexer/sequence.hpp
Normal file
32
include/boost/spirit/home/lex/lexer/sequence.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(SPIRIT_LEX_SEQUENCE_MAR_28_2007_0610PM)
|
||||
#define SPIRIT_LEX_SEQUENCE_MAR_28_2007_0610PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/lexer/detail/sequence.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
struct sequence
|
||||
{
|
||||
template <typename Component, typename LexerDef, typename String>
|
||||
static void
|
||||
collect(Component const& component, LexerDef& lexdef,
|
||||
String const& state)
|
||||
{
|
||||
detail::sequence_collect<LexerDef, String> f (lexdef, state);
|
||||
fusion::any(component.elements, f);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::lex
|
||||
|
||||
#endif
|
||||
36
include/boost/spirit/home/lex/lexer/string_token_def.hpp
Normal file
36
include/boost/spirit/home/lex/lexer/string_token_def.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM)
|
||||
#define BOOST_SPIRIT_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// string_token_def
|
||||
// represents a string based token definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct string_token_def
|
||||
{
|
||||
template <typename Component, typename LexerDef, typename String>
|
||||
static void
|
||||
collect(Component const& component, LexerDef& lexdef,
|
||||
String const& state)
|
||||
{
|
||||
lexdef.add_token (state.c_str(), subject(component), next_id());
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::spirit::lex
|
||||
|
||||
#endif
|
||||
73
include/boost/spirit/home/lex/lexer/terminal_director.hpp
Normal file
73
include/boost/spirit/home/lex/lexer/terminal_director.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_LEX_TERMINAL_DIRECTOR_MAR_22_2007_0846PM)
|
||||
#define BOOST_SPIRIT_LEX_TERMINAL_DIRECTOR_MAR_22_2007_0846PM
|
||||
|
||||
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
||||
#include <boost/spirit/home/lex/domain.hpp>
|
||||
#include <boost/spirit/home/support/component.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
// this is the director for all lexer related proto terminals
|
||||
struct terminal_director
|
||||
{
|
||||
// Qi interface: return value of the parser
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef typename
|
||||
result_of::subject<Component>::type
|
||||
terminal_holder;
|
||||
typedef typename terminal_holder::terminal_type terminal_type;
|
||||
|
||||
typedef typename
|
||||
terminal_type::template attribute<
|
||||
terminal_holder, Context, Iterator
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// Qi interface: parse functionality, delegates back to the
|
||||
// corresponding lexer terminal
|
||||
template <typename Component, typename Iterator, typename Context,
|
||||
typename Skipper, typename Attribute>
|
||||
static bool parse(Component const& component,
|
||||
Iterator& first, Iterator const& last, Context& context,
|
||||
Skipper const& skipper, Attribute& attr)
|
||||
{
|
||||
// main entry point, just forward to the lexer terminal
|
||||
return subject(component).held->parse(
|
||||
first, last, context, skipper, attr);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
static std::string what(Component const& component)
|
||||
{
|
||||
return subject(component).held->what();
|
||||
}
|
||||
|
||||
// Lex interface: collect functionality, delegates back to the
|
||||
// corresponding lexer terminal
|
||||
template <typename Component, typename LexerDef, typename String>
|
||||
static void collect (Component const& component, LexerDef& lexdef,
|
||||
String const& state)
|
||||
{
|
||||
subject(component).held->collect(lexdef, state);
|
||||
}
|
||||
|
||||
// Lex interface: return the token id of the associated token_def
|
||||
template <typename Component>
|
||||
static std::size_t id(Component const& component)
|
||||
{
|
||||
return subject(component).held->id();
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
29
include/boost/spirit/home/lex/lexer/terminal_holder.hpp
Normal file
29
include/boost/spirit/home/lex/lexer/terminal_holder.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2001-2008 Hartmut Kaiser
|
||||
// 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_LEX_TERMINAL_HOLDER_MAR_22_2007_0217PM)
|
||||
#define BOOST_SPIRIT_LEX_TERMINAL_HOLDER_MAR_22_2007_0217PM
|
||||
|
||||
#include <boost/xpressive/proto/proto.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
template <typename T, typename Terminal>
|
||||
struct terminal_holder
|
||||
{
|
||||
typedef Terminal terminal_type;
|
||||
T held;
|
||||
};
|
||||
|
||||
template <typename T, typename Terminal>
|
||||
struct make_terminal_holder
|
||||
: proto::terminal<terminal_holder<T, Terminal> >
|
||||
{
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
183
include/boost/spirit/home/lex/lexer/token_def.hpp
Normal file
183
include/boost/spirit/home/lex/lexer/token_def.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// 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_LEX_TOKEN_DEF_MAR_13_2007_0145PM)
|
||||
#define BOOST_SPIRIT_LEX_TOKEN_DEF_MAR_13_2007_0145PM
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once // MS compatible compilers support #pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/spirit/home/qi/skip.hpp>
|
||||
#include <boost/spirit/home/qi/detail/construct.hpp>
|
||||
#include <boost/spirit/home/qi/detail/assign_to.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// create a unique token id, note this is not thread safe
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
enum tokenids {
|
||||
// this is the first token id automatically assigned by the library
|
||||
// if needed
|
||||
min_token_id = 0x10000
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
inline std::size_t next_id()
|
||||
{
|
||||
static std::size_t next_token_id = min_token_id;
|
||||
return next_token_id++;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This component represents a token definition
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename Attribute, typename Char>
|
||||
class token_def
|
||||
: public proto::extends<
|
||||
typename make_terminal_holder<
|
||||
token_def<Attribute, Char>*, token_def<Attribute, Char>
|
||||
>::type,
|
||||
token_def<Attribute, Char>
|
||||
>
|
||||
{
|
||||
private:
|
||||
// initialize proto base class
|
||||
typedef terminal_holder<token_def*, token_def> terminal_holder;
|
||||
typedef typename proto::terminal<terminal_holder>::type tag;
|
||||
typedef proto::extends<tag, token_def> base_type;
|
||||
|
||||
tag make_tag()
|
||||
{
|
||||
tag xpr = {{ this }};
|
||||
return xpr;
|
||||
}
|
||||
|
||||
public:
|
||||
// Qi interface: metafunction calculating parser return type
|
||||
template <typename Component, typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
// The return value of the token_def is either the specified
|
||||
// attribute type, or the pair of iterators from the match of the
|
||||
// corresponding token (if no attribute type has been specified),
|
||||
// or unused_type (if omitted has been specified).
|
||||
typedef typename Iterator::base_iterator_type iterator_type;
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<Attribute, unused_type>,
|
||||
iterator_range<iterator_type>,
|
||||
typename mpl::if_<
|
||||
is_same<Attribute, omitted>,
|
||||
unused_type,
|
||||
Attribute
|
||||
>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
private:
|
||||
// Qi interface: parse functionality
|
||||
template <typename Iterator, typename Context, typename Skipper,
|
||||
typename Attribute1>
|
||||
bool parse(Iterator& first, Iterator const& last,
|
||||
Context& /*context*/, Skipper const& skipper, Attribute1& attr) const
|
||||
{
|
||||
qi::skip(first, last, skipper); // always do a pre-skip
|
||||
|
||||
if (first != last) {
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<Iterator>::value_type
|
||||
token_type;
|
||||
|
||||
// If the following assertion fires you probably forgot to
|
||||
// associate this token definition with a lexer instance.
|
||||
BOOST_ASSERT((std::size_t)(~0) != token_state);
|
||||
|
||||
token_type &t = *first;
|
||||
if (token_id == t.id() && token_state == t.state()) {
|
||||
qi::detail::assign_to(t, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
friend struct terminal_director;
|
||||
|
||||
std::string what() const
|
||||
{
|
||||
std::string result = "token_def(\"";
|
||||
result += def;
|
||||
result += "\")";
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Lex interface: collect token definitions and put it into the
|
||||
// provided lexer def
|
||||
template <typename LexerDef, typename String>
|
||||
void collect(LexerDef& lexdef, String const& state)
|
||||
{
|
||||
token_state = lexdef.add_state(state.c_str());
|
||||
if (0 == token_id)
|
||||
token_id = next_id();
|
||||
lexdef.add_token (state.c_str(), def, token_id);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Char char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
// Lex interface: constructing token definitions
|
||||
token_def()
|
||||
: base_type(make_tag()), token_id(0), token_state(~0)
|
||||
{}
|
||||
explicit token_def(char_type def_, std::size_t id_ = 0)
|
||||
: base_type(make_tag()), def(lex::detail::escape(def_)),
|
||||
token_id(0 == id_ ? def_ : id_), token_state(~0)
|
||||
{}
|
||||
explicit token_def(string_type def_, std::size_t id_ = 0)
|
||||
: base_type(make_tag()), def(def_), token_id(id_), token_state(~0)
|
||||
{}
|
||||
|
||||
template <typename String>
|
||||
token_def& operator= (String const& definition)
|
||||
{
|
||||
def = definition;
|
||||
token_id = 0;
|
||||
return *this;
|
||||
}
|
||||
token_def& operator= (token_def const& rhs)
|
||||
{
|
||||
def = rhs.def;
|
||||
token_id = rhs.token_id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// general accessors
|
||||
std::size_t id() const { return token_id; }
|
||||
void id(std::size_t id) { token_id = id; }
|
||||
string_type const& definition() const { return def; }
|
||||
std::size_t state() const { return token_state; }
|
||||
|
||||
private:
|
||||
string_type def;
|
||||
std::size_t token_id;
|
||||
std::size_t token_state;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user