2
0
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:
Joel de Guzman
2008-04-13 00:54:10 +00:00
parent f2a31e171d
commit ffd0cc1001
417 changed files with 54702 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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)

View 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

View 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)

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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_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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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)

View 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)

View 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

View 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

View 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

View 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

View 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

Binary file not shown.

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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.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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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 &current_, 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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