stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_KARMA_APR_28_2009_1259PM)
|
||||
#define SPIRIT_REPOSITORY_KARMA_APR_28_2009_1259PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/karma/directive.hpp>
|
||||
#include <boost/spirit/repository/home/karma/nonterminal.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_KARMA_DIRECTIVE_APR_28_2009_1258PM)
|
||||
#define SPIRIT_REPOSITORY_KARMA_DIRECTIVE_APR_28_2009_1258PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/karma/directive/confix.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_KARMA_CONFIX_AUG_19_2008_1041AM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_KARMA_CONFIX_AUG_19_2008_1041AM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/common_terminals.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/karma/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/meta_compiler.hpp>
|
||||
|
||||
#include <boost/spirit/repository/home/support/confix.hpp>
|
||||
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// enables confix(..., ...)[]
|
||||
template <typename Prefix, typename Suffix>
|
||||
struct use_directive<karma::domain
|
||||
, terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > >
|
||||
: mpl::true_ {};
|
||||
|
||||
// enables *lazy* confix(..., ...)[g]
|
||||
template <>
|
||||
struct use_lazy_directive<karma::domain, repository::tag::confix, 2>
|
||||
: mpl::true_ {};
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace repository { namespace karma
|
||||
{
|
||||
using repository::confix_type;
|
||||
using repository::confix;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename Prefix, typename Suffix>
|
||||
struct confix_generator
|
||||
: spirit::karma::primitive_generator<confix_generator<Subject, Prefix, Suffix> >
|
||||
{
|
||||
typedef Subject subject_type;
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
: traits::attribute_of<subject_type, Context, Iterator>
|
||||
{};
|
||||
|
||||
confix_generator(Subject const& subject, Prefix const& prefix
|
||||
, Suffix const& suffix)
|
||||
: subject(subject), prefix(prefix), suffix(suffix) {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename OutputIterator, typename Context, typename Delimiter
|
||||
, typename Attribute>
|
||||
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
|
||||
, Attribute const& attr) const
|
||||
{
|
||||
// generate the prefix, the embedded item and the suffix
|
||||
return prefix.generate(sink, ctx, d, unused) &&
|
||||
subject.generate(sink, ctx, d, attr) &&
|
||||
suffix.generate(sink, ctx, d, unused);
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context const& ctx) const
|
||||
{
|
||||
return info("confix", subject.what(ctx));
|
||||
}
|
||||
|
||||
Subject subject;
|
||||
Prefix prefix;
|
||||
Suffix suffix;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// creates confix(..., ...)[] directive generator
|
||||
template <typename Prefix, typename Suffix, typename Subject
|
||||
, typename Modifiers>
|
||||
struct make_directive<
|
||||
terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> >
|
||||
, Subject, Modifiers>
|
||||
{
|
||||
typedef typename
|
||||
result_of::compile<karma::domain, Prefix, Modifiers>::type
|
||||
prefix_type;
|
||||
typedef typename
|
||||
result_of::compile<karma::domain, Suffix, Modifiers>::type
|
||||
suffix_type;
|
||||
|
||||
typedef repository::karma::confix_generator<
|
||||
Subject, prefix_type, suffix_type> result_type;
|
||||
|
||||
template <typename Terminal>
|
||||
result_type operator()(Terminal const& term, Subject const& subject
|
||||
, Modifiers const& modifiers) const
|
||||
{
|
||||
return result_type(subject
|
||||
, compile<karma::domain>(fusion::at_c<0>(term.args), modifiers)
|
||||
, compile<karma::domain>(fusion::at_c<1>(term.args), modifiers));
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Prefix, typename Suffix>
|
||||
struct has_semantic_action<
|
||||
repository::karma::confix_generator<Subject, Prefix, Suffix> >
|
||||
: mpl::or_<
|
||||
has_semantic_action<Subject>
|
||||
, has_semantic_action<Prefix>
|
||||
, has_semantic_action<Suffix>
|
||||
> {};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 Joel de Guzman
|
||||
// Copyright (c) 2009 Francois Barel
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_KARMA_NONTERMINAL_AUG_12_2009_0807PM)
|
||||
#define SPIRIT_REPOSITORY_KARMA_NONTERMINAL_AUG_12_2009_0807PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/karma/nonterminal/subrule.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
// Copyright (c) 2009 Francois Barel
|
||||
// Copyright (c) 2001-2011 Joel de Guzman
|
||||
// Copyright (c) 2001-2012 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_REPOSITORY_KARMA_SUBRULE_AUGUST_12_2009_0813PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_KARMA_SUBRULE_AUGUST_12_2009_0813PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/karma/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/karma/generator.hpp>
|
||||
#include <boost/spirit/home/karma/reference.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/detail/generator_binder.hpp>
|
||||
#include <boost/spirit/home/karma/nonterminal/detail/parameterized.hpp>
|
||||
#include <boost/spirit/home/support/argument.hpp>
|
||||
#include <boost/spirit/home/support/assert_msg.hpp>
|
||||
#include <boost/spirit/home/karma/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/extract_param.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/locals.hpp>
|
||||
#include <boost/spirit/repository/home/support/subrule_context.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_map.hpp>
|
||||
#include <boost/fusion/include/at_key.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/has_key.hpp>
|
||||
#include <boost/fusion/include/join.hpp>
|
||||
#include <boost/fusion/include/make_map.hpp>
|
||||
#include <boost/fusion/include/make_vector.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_reference.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 repository { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule_group:
|
||||
// - generator representing a group of subrule definitions (one or more),
|
||||
// invokes first subrule on entry,
|
||||
// - also a Proto terminal, so that a group behaves like any Spirit
|
||||
// expression.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Defs>
|
||||
struct subrule_group
|
||||
: proto::extends<
|
||||
typename proto::terminal<
|
||||
spirit::karma::reference<subrule_group<Defs> const>
|
||||
>::type
|
||||
, subrule_group<Defs>
|
||||
>
|
||||
, spirit::karma::generator<subrule_group<Defs> >
|
||||
{
|
||||
struct properties
|
||||
// Forward to first subrule.
|
||||
: remove_reference<
|
||||
typename fusion::result_of::front<Defs>::type
|
||||
>::type::second_type::subject_type::properties {};
|
||||
|
||||
// Fusion associative sequence, associating each subrule ID in this
|
||||
// group (as an MPL integral constant) with its definition
|
||||
typedef Defs defs_type;
|
||||
|
||||
typedef subrule_group<Defs> this_type;
|
||||
typedef spirit::karma::reference<this_type const> reference_;
|
||||
typedef typename proto::terminal<reference_>::type terminal;
|
||||
typedef proto::extends<terminal, this_type> base_type;
|
||||
|
||||
static size_t const params_size =
|
||||
// Forward to first subrule.
|
||||
remove_reference<
|
||||
typename fusion::result_of::front<Defs>::type
|
||||
>::type::second_type::params_size;
|
||||
|
||||
subrule_group(subrule_group const& rhs)
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, defs(rhs.defs)
|
||||
{
|
||||
}
|
||||
|
||||
explicit subrule_group(Defs const& defs)
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, defs(defs)
|
||||
{
|
||||
}
|
||||
|
||||
// from a subrule ID, get the type of a reference to its definition
|
||||
template <int ID>
|
||||
struct def_type
|
||||
{
|
||||
typedef mpl::int_<ID> id_type;
|
||||
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule which was not defined in this group.
|
||||
BOOST_SPIRIT_ASSERT_MSG(
|
||||
(fusion::result_of::has_key<
|
||||
defs_type const, id_type>::type::value)
|
||||
, subrule_used_without_being_defined, (mpl::int_<ID>));
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::at_key<defs_type const, id_type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// from a subrule ID, get a reference to its definition
|
||||
template <int ID>
|
||||
typename def_type<ID>::type def() const
|
||||
{
|
||||
return fusion::at_key<mpl::int_<ID> >(defs);
|
||||
}
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
// Forward to first subrule.
|
||||
: mpl::identity<
|
||||
typename remove_reference<
|
||||
typename fusion::result_of::front<Defs>::type
|
||||
>::type::second_type::attr_type> {};
|
||||
|
||||
template <typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute>
|
||||
bool generate(OutputIterator& sink, Context& context
|
||||
, Delimiter const& delimiter, Attribute const& attr) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return generate_subrule(fusion::front(defs).second
|
||||
, sink, context, delimiter, attr);
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute
|
||||
, typename Params>
|
||||
bool generate(OutputIterator& sink, Context& context
|
||||
, Delimiter const& delimiter, Attribute const& attr
|
||||
, Params const& params) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return generate_subrule(fusion::front(defs).second
|
||||
, sink, context, delimiter, attr, params);
|
||||
}
|
||||
|
||||
template <int ID, typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute>
|
||||
bool generate_subrule_id(OutputIterator& sink
|
||||
, Context& context, Delimiter const& delimiter
|
||||
, Attribute const& attr) const
|
||||
{
|
||||
return generate_subrule(def<ID>()
|
||||
, sink, context, delimiter, attr);
|
||||
}
|
||||
|
||||
template <int ID, typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute, typename Params>
|
||||
bool generate_subrule_id(OutputIterator& sink
|
||||
, Context& context, Delimiter const& delimiter
|
||||
, Attribute const& attr, Params const& params) const
|
||||
{
|
||||
return generate_subrule(def<ID>()
|
||||
, sink, context, delimiter, attr, params);
|
||||
}
|
||||
|
||||
template <typename Def, typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute>
|
||||
bool generate_subrule(Def const& def, OutputIterator& sink
|
||||
, Context& /*caller_context*/, Delimiter const& delimiter
|
||||
, Attribute const& attr) const
|
||||
{
|
||||
// compute context type for this subrule
|
||||
typedef typename Def::locals_type subrule_locals_type;
|
||||
typedef typename Def::attr_type subrule_attr_type;
|
||||
typedef typename Def::attr_reference_type subrule_attr_reference_type;
|
||||
typedef typename Def::parameter_types subrule_parameter_types;
|
||||
|
||||
typedef
|
||||
subrule_context<
|
||||
this_type
|
||||
, fusion::cons<
|
||||
subrule_attr_reference_type, subrule_parameter_types>
|
||||
, subrule_locals_type
|
||||
>
|
||||
context_type;
|
||||
|
||||
// Create an attribute if none is supplied.
|
||||
typedef traits::make_attribute<subrule_attr_type, Attribute>
|
||||
make_attribute;
|
||||
|
||||
// If you are seeing a compilation error here, you are probably
|
||||
// trying to use a subrule which has inherited attributes,
|
||||
// without passing values for them.
|
||||
context_type context(*this
|
||||
, traits::pre_transform<spirit::karma::domain, subrule_attr_type>(
|
||||
make_attribute::call(attr)));
|
||||
|
||||
return def.binder(sink, context, delimiter);
|
||||
}
|
||||
|
||||
template <typename Def, typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute, typename Params>
|
||||
bool generate_subrule(Def const& def, OutputIterator& sink
|
||||
, Context& caller_context, Delimiter const& delimiter
|
||||
, Attribute const& attr, Params const& params) const
|
||||
{
|
||||
// compute context type for this subrule
|
||||
typedef typename Def::locals_type subrule_locals_type;
|
||||
typedef typename Def::attr_type subrule_attr_type;
|
||||
typedef typename Def::attr_reference_type subrule_attr_reference_type;
|
||||
typedef typename Def::parameter_types subrule_parameter_types;
|
||||
|
||||
typedef
|
||||
subrule_context<
|
||||
this_type
|
||||
, fusion::cons<
|
||||
subrule_attr_reference_type, subrule_parameter_types>
|
||||
, subrule_locals_type
|
||||
>
|
||||
context_type;
|
||||
|
||||
// Create an attribute if none is supplied.
|
||||
typedef traits::make_attribute<subrule_attr_type, Attribute>
|
||||
make_attribute;
|
||||
|
||||
// If you are seeing a compilation error here, you are probably
|
||||
// trying to use a subrule which has inherited attributes,
|
||||
// passing values of incompatible types for them.
|
||||
context_type context(*this
|
||||
, traits::pre_transform<spirit::karma::domain, subrule_attr_type>(
|
||||
make_attribute::call(attr)), params, caller_context);
|
||||
|
||||
return def.binder(sink, context, delimiter);
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& context) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return fusion::front(defs).second.binder.g.what(context);
|
||||
}
|
||||
|
||||
template <typename Defs2>
|
||||
subrule_group<
|
||||
typename fusion::result_of::as_map<
|
||||
typename fusion::result_of::join<
|
||||
Defs const, Defs2 const>::type>::type>
|
||||
operator,(subrule_group<Defs2> const& other) const
|
||||
{
|
||||
typedef subrule_group<
|
||||
typename fusion::result_of::as_map<
|
||||
typename fusion::result_of::join<
|
||||
Defs const, Defs2 const>::type>::type> result_type;
|
||||
return result_type(fusion::as_map(fusion::join(defs, other.defs)));
|
||||
}
|
||||
|
||||
// bring in the operator() overloads
|
||||
this_type const& get_parameterized_subject() const { return *this; }
|
||||
typedef this_type parameterized_subject_type;
|
||||
#include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
|
||||
|
||||
Defs defs;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule_definition: holds one particular definition of a subrule
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
int ID_
|
||||
, typename Locals
|
||||
, typename Attr
|
||||
, typename AttrRef
|
||||
, typename Parameters
|
||||
, size_t ParamsSize
|
||||
, typename Subject
|
||||
, bool Auto_
|
||||
>
|
||||
struct subrule_definition
|
||||
{
|
||||
typedef mpl::int_<ID_> id_type;
|
||||
BOOST_STATIC_CONSTANT(int, ID = ID_);
|
||||
|
||||
typedef Locals locals_type;
|
||||
typedef Attr attr_type;
|
||||
typedef AttrRef attr_reference_type;
|
||||
typedef Parameters parameter_types;
|
||||
static size_t const params_size = ParamsSize;
|
||||
|
||||
typedef Subject subject_type;
|
||||
typedef mpl::bool_<Auto_> auto_type;
|
||||
BOOST_STATIC_CONSTANT(bool, Auto = Auto_);
|
||||
|
||||
typedef spirit::karma::detail::generator_binder<
|
||||
Subject, auto_type> binder_type;
|
||||
|
||||
subrule_definition(Subject const& subject, std::string const& name)
|
||||
: binder(subject), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
binder_type const binder;
|
||||
std::string const name;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule placeholder:
|
||||
// - on subrule definition: helper for creation of subrule_group,
|
||||
// - on subrule invocation: Proto terminal and generator.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
int ID_
|
||||
, typename T1 = unused_type
|
||||
, typename T2 = unused_type
|
||||
>
|
||||
struct subrule
|
||||
: proto::extends<
|
||||
typename proto::terminal<
|
||||
spirit::karma::reference<subrule<ID_, T1, T2> const>
|
||||
>::type
|
||||
, subrule<ID_, T1, T2>
|
||||
>
|
||||
, spirit::karma::generator<subrule<ID_, T1, T2> >
|
||||
{
|
||||
//FIXME should go fetch the real properties of this subrule's definition in the current context, but we don't
|
||||
// have the context here (properties would need to be 'template<typename Context> struct properties' instead)
|
||||
typedef mpl::int_<
|
||||
spirit::karma::generator_properties::all_properties> properties;
|
||||
|
||||
typedef mpl::int_<ID_> id_type;
|
||||
BOOST_STATIC_CONSTANT(int, ID = ID_);
|
||||
|
||||
typedef subrule<ID_, T1, T2> this_type;
|
||||
typedef spirit::karma::reference<this_type const> reference_;
|
||||
typedef typename proto::terminal<reference_>::type terminal;
|
||||
typedef proto::extends<terminal, this_type> base_type;
|
||||
|
||||
typedef mpl::vector<T1, T2> template_params;
|
||||
|
||||
// locals_type is a sequence of types to be used as local variables
|
||||
typedef typename
|
||||
spirit::detail::extract_locals<template_params>::type
|
||||
locals_type;
|
||||
|
||||
typedef typename
|
||||
spirit::detail::extract_sig<template_params>::type
|
||||
sig_type;
|
||||
|
||||
// This is the subrule's attribute type
|
||||
typedef typename
|
||||
spirit::detail::attr_from_sig<sig_type>::type
|
||||
attr_type;
|
||||
typedef typename add_reference<
|
||||
typename add_const<attr_type>::type>::type attr_reference_type;
|
||||
|
||||
// parameter_types is a sequence of types passed as parameters to the subrule
|
||||
typedef typename
|
||||
spirit::detail::params_from_sig<sig_type>::type
|
||||
parameter_types;
|
||||
|
||||
static size_t const params_size =
|
||||
fusion::result_of::size<parameter_types>::type::value;
|
||||
|
||||
explicit subrule(std::string const& name_ = "unnamed-subrule")
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, name_(name_)
|
||||
{
|
||||
}
|
||||
|
||||
// compute type of this subrule's definition for expr type Expr
|
||||
template <typename Expr, bool Auto>
|
||||
struct def_type_helper
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (Expr) is not a valid spirit karma expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(spirit::karma::domain, Expr);
|
||||
|
||||
typedef typename result_of::compile<
|
||||
spirit::karma::domain, Expr>::type subject_type;
|
||||
|
||||
typedef subrule_definition<
|
||||
ID_
|
||||
, locals_type
|
||||
, attr_type
|
||||
, attr_reference_type
|
||||
, parameter_types
|
||||
, params_size
|
||||
, subject_type
|
||||
, Auto
|
||||
> const type;
|
||||
};
|
||||
|
||||
// compute type of subrule group containing only this
|
||||
// subrule's definition for expr type Expr
|
||||
template <typename Expr, bool Auto>
|
||||
struct group_type_helper
|
||||
{
|
||||
typedef typename def_type_helper<Expr, Auto>::type def_type;
|
||||
|
||||
// create Defs map with only one entry: (ID -> def)
|
||||
typedef typename
|
||||
#ifndef BOOST_FUSION_HAS_VARIADIC_MAP
|
||||
fusion::result_of::make_map<id_type, def_type>::type
|
||||
#else
|
||||
fusion::result_of::make_map<id_type>::template apply<def_type>::type
|
||||
#endif
|
||||
defs_type;
|
||||
|
||||
typedef subrule_group<defs_type> type;
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
typename group_type_helper<Expr, false>::type
|
||||
operator=(Expr const& expr) const
|
||||
{
|
||||
typedef group_type_helper<Expr, false> helper;
|
||||
typedef typename helper::def_type def_type;
|
||||
typedef typename helper::type result_type;
|
||||
return result_type(fusion::make_map<id_type>(
|
||||
def_type(compile<spirit::karma::domain>(expr), name_)));
|
||||
}
|
||||
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule const& sr, Expr const& expr)
|
||||
{
|
||||
typedef group_type_helper<Expr, true> helper;
|
||||
typedef typename helper::def_type def_type;
|
||||
typedef typename helper::type result_type;
|
||||
return result_type(fusion::make_map<id_type>(
|
||||
def_type(compile<spirit::karma::domain>(expr), sr.name_)));
|
||||
}
|
||||
|
||||
// non-const versions needed to suppress proto's %= kicking in
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule const& sr, Expr& expr)
|
||||
{
|
||||
return operator%=(
|
||||
sr
|
||||
, static_cast<Expr const&>(expr));
|
||||
}
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule& sr, Expr const& expr)
|
||||
{
|
||||
return operator%=(
|
||||
static_cast<subrule const&>(sr)
|
||||
, expr);
|
||||
}
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule& sr, Expr& expr)
|
||||
{
|
||||
return operator%=(
|
||||
static_cast<subrule const&>(sr)
|
||||
, static_cast<Expr const&>(expr));
|
||||
}
|
||||
|
||||
std::string const& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void name(std::string const& str)
|
||||
{
|
||||
name_ = str;
|
||||
}
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef attr_type type;
|
||||
};
|
||||
|
||||
template <typename OutputIterator, typename Group
|
||||
, typename Attributes, typename Locals
|
||||
, typename Delimiter, typename Attribute>
|
||||
bool generate(OutputIterator& sink
|
||||
, subrule_context<Group, Attributes, Locals>& context
|
||||
, Delimiter const& delimiter, Attribute const& attr) const
|
||||
{
|
||||
return context.group.template generate_subrule_id<ID_>(
|
||||
sink, context, delimiter, attr);
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute>
|
||||
bool generate(OutputIterator& /*sink*/
|
||||
, Context& /*context*/
|
||||
, Delimiter const& /*delimiter*/, Attribute const& /*attr*/) const
|
||||
{
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule as a generator outside of a subrule group.
|
||||
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator
|
||||
, subrule_used_outside_subrule_group, (id_type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Group
|
||||
, typename Attributes, typename Locals
|
||||
, typename Delimiter, typename Attribute
|
||||
, typename Params>
|
||||
bool generate(OutputIterator& sink
|
||||
, subrule_context<Group, Attributes, Locals>& context
|
||||
, Delimiter const& delimiter, Attribute const& attr
|
||||
, Params const& params) const
|
||||
{
|
||||
return context.group.template generate_subrule_id<ID_>(
|
||||
sink, context, delimiter, attr, params);
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute
|
||||
, typename Params>
|
||||
bool generate(OutputIterator& /*sink*/
|
||||
, Context& /*context*/
|
||||
, Delimiter const& /*delimiter*/, Attribute const& /*attr*/
|
||||
, Params const& /*params*/) const
|
||||
{
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule as a generator outside of a subrule group.
|
||||
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator
|
||||
, subrule_used_outside_subrule_group, (id_type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& /*context*/) const
|
||||
{
|
||||
return info(name_);
|
||||
}
|
||||
|
||||
// bring in the operator() overloads
|
||||
this_type const& get_parameterized_subject() const { return *this; }
|
||||
typedef this_type parameterized_subject_type;
|
||||
#include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
}}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_QI_APR_28_2009_1258PM)
|
||||
#define SPIRIT_REPOSITORY_QI_APR_28_2009_1258PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/qi/primitive.hpp>
|
||||
#include <boost/spirit/repository/home/qi/directive.hpp>
|
||||
#include <boost/spirit/repository/home/qi/nonterminal.hpp>
|
||||
#include <boost/spirit/repository/home/qi/operator.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_QI_DIRECTIVE_APR_28_2009_1258PM)
|
||||
#define SPIRIT_REPOSITORY_QI_DIRECTIVE_APR_28_2009_1258PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/qi/directive/distinct.hpp>
|
||||
#include <boost/spirit/repository/home/qi/directive/confix.hpp>
|
||||
#include <boost/spirit/repository/home/qi/directive/kwd.hpp>
|
||||
#include <boost/spirit/repository/home/qi/directive/seek.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2009 Chris Hoeppler
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/domain.hpp>
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/qi/auxiliary/lazy.hpp>
|
||||
#include <boost/spirit/home/support/common_terminals.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/qi/detail/attributes.hpp>
|
||||
|
||||
#include <boost/spirit/repository/home/support/confix.hpp>
|
||||
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// enables confix(..., ...)[]
|
||||
template <typename Prefix, typename Suffix>
|
||||
struct use_directive<qi::domain
|
||||
, terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > >
|
||||
: mpl::true_ {};
|
||||
|
||||
// enables *lazy* confix(..., ...)[]
|
||||
template <>
|
||||
struct use_lazy_directive<qi::domain, repository::tag::confix, 2>
|
||||
: mpl::true_ {};
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
using repository::confix_type;
|
||||
using repository::confix;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// the confix() generated parser
|
||||
template <typename Subject, typename Prefix, typename Suffix>
|
||||
struct confix_parser
|
||||
: spirit::qi::unary_parser<confix_parser<Subject, Prefix, Suffix> >
|
||||
{
|
||||
typedef Subject subject_type;
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
: traits::attribute_of<subject_type, Context, Iterator>
|
||||
{};
|
||||
|
||||
confix_parser(Subject const& subject, Prefix const& prefix
|
||||
, Suffix const& suffix)
|
||||
: subject(subject), prefix(prefix), suffix(suffix) {}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
Iterator iter = first;
|
||||
|
||||
if (!(prefix.parse(iter, last, context, skipper, unused) &&
|
||||
subject.parse(iter, last, context, skipper, attr) &&
|
||||
suffix.parse(iter, last, context, skipper, unused)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
first = iter;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context const& ctx) const
|
||||
{
|
||||
return info("confix", subject.what(ctx));
|
||||
}
|
||||
|
||||
Subject subject;
|
||||
Prefix prefix;
|
||||
Suffix suffix;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// creates confix(..., ...)[] directive
|
||||
template <typename Prefix, typename Suffix, typename Subject
|
||||
, typename Modifiers>
|
||||
struct make_directive<
|
||||
terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> >
|
||||
, Subject, Modifiers>
|
||||
{
|
||||
typedef typename
|
||||
result_of::compile<qi::domain, Prefix, Modifiers>::type
|
||||
prefix_type;
|
||||
typedef typename
|
||||
result_of::compile<qi::domain, Suffix, Modifiers>::type
|
||||
suffix_type;
|
||||
|
||||
typedef repository::qi::confix_parser<
|
||||
Subject, prefix_type, suffix_type> result_type;
|
||||
|
||||
template <typename Terminal>
|
||||
result_type operator()(Terminal const& term, Subject const& subject
|
||||
, Modifiers const& modifiers) const
|
||||
{
|
||||
return result_type(subject
|
||||
, compile<qi::domain>(fusion::at_c<0>(term.args), modifiers)
|
||||
, compile<qi::domain>(fusion::at_c<1>(term.args), modifiers));
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Prefix, typename Suffix>
|
||||
struct has_semantic_action<
|
||||
repository::qi::confix_parser<Subject, Prefix, Suffix> >
|
||||
: mpl::or_<
|
||||
has_semantic_action<Subject>
|
||||
, has_semantic_action<Prefix>
|
||||
, has_semantic_action<Suffix>
|
||||
> {};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 Joel de Guzman
|
||||
// Copyright (c) 2003 Vaclav Vesely
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M)
|
||||
#define SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/skip_over.hpp>
|
||||
#include <boost/spirit/home/qi/domain.hpp>
|
||||
#include <boost/spirit/home/qi/parser.hpp>
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/qi/detail/unused_skipper.hpp>
|
||||
#include <boost/spirit/home/support/common_terminals.hpp>
|
||||
#include <boost/spirit/home/support/make_component.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/qi/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/support/string_traits.hpp>
|
||||
#include <boost/spirit/home/qi/auxiliary/eps.hpp>
|
||||
#include <boost/spirit/home/qi/auxiliary/lazy.hpp>
|
||||
#include <boost/spirit/home/qi/directive/lexeme.hpp>
|
||||
#include <boost/spirit/home/qi/operator/not_predicate.hpp>
|
||||
|
||||
#include <boost/spirit/repository/home/support/distinct.hpp>
|
||||
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// enables distinct(...)[...]
|
||||
template <typename Tail>
|
||||
struct use_directive<qi::domain
|
||||
, terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > >
|
||||
: mpl::true_ {};
|
||||
|
||||
// enables *lazy* distinct(...)[...]
|
||||
template <>
|
||||
struct use_lazy_directive<qi::domain, repository::tag::distinct, 1>
|
||||
: mpl::true_ {};
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace repository {namespace qi
|
||||
{
|
||||
using repository::distinct_type;
|
||||
using repository::distinct;
|
||||
|
||||
template <typename Subject, typename Tail, typename Modifier>
|
||||
struct distinct_parser
|
||||
: spirit::qi::unary_parser<distinct_parser<Subject, Tail, Modifier> >
|
||||
{
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
: traits::attribute_of<Subject, Context, Iterator>
|
||||
{};
|
||||
|
||||
distinct_parser(Subject const& subject, Tail const& tail)
|
||||
: subject(subject), tail(tail) {}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper, Attribute& attr) const
|
||||
{
|
||||
Iterator iter = first;
|
||||
|
||||
spirit::qi::skip_over(iter, last, skipper);
|
||||
if (!subject.parse(iter, last, context
|
||||
, spirit::qi::detail::unused_skipper<Skipper>(skipper), attr))
|
||||
return false;
|
||||
|
||||
Iterator i = iter;
|
||||
if (tail.parse(i, last, context, unused, unused))
|
||||
return false;
|
||||
|
||||
first = iter;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& /*ctx*/) const
|
||||
{
|
||||
return info("distinct");
|
||||
}
|
||||
|
||||
Subject subject;
|
||||
Tail tail;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Tail, typename Subject, typename Modifiers>
|
||||
struct make_directive<
|
||||
terminal_ex<repository::tag::distinct, fusion::vector1<Tail> >
|
||||
, Subject, Modifiers>
|
||||
{
|
||||
typedef typename result_of::compile<qi::domain, Tail, Modifiers>::type
|
||||
tail_type;
|
||||
|
||||
typedef repository::qi::distinct_parser<
|
||||
Subject, tail_type, Modifiers> result_type;
|
||||
|
||||
template <typename Terminal>
|
||||
result_type operator()(Terminal const& term, Subject const& subject
|
||||
, Modifiers const& modifiers) const
|
||||
{
|
||||
return result_type(subject
|
||||
, compile<qi::domain>(fusion::at_c<0>(term.args), modifiers));
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Tail, typename Modifier>
|
||||
struct has_semantic_action<
|
||||
repository::qi::distinct_parser<Subject, Tail, Modifier> >
|
||||
: unary_has_semantic_action<Subject> {};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
+1199
File diff suppressed because it is too large
Load Diff
+134
@@ -0,0 +1,134 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Copyright (c) 2011 Jamboree
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//////////////////////////////////////////////////////////////////////////////*/
|
||||
#ifndef BOOST_SPIRIT_REPOSITORY_QI_SEEK
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_SEEK
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/qi/parser.hpp>
|
||||
#include <boost/spirit/home/qi/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/has_semantic_action.hpp>
|
||||
#include <boost/spirit/home/support/handles_container.hpp>
|
||||
#include <boost/spirit/repository/home/support/seek.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// enables seek[...]
|
||||
template <>
|
||||
struct use_directive<qi::domain, repository::tag::seek>
|
||||
: mpl::true_ {};
|
||||
}} // namespace boost::spirit
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace repository {namespace qi
|
||||
{
|
||||
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
||||
using repository::seek;
|
||||
#endif
|
||||
using repository::seek_type;
|
||||
|
||||
template <typename Subject>
|
||||
struct seek_directive
|
||||
: spirit::qi::unary_parser<seek_directive<Subject> >
|
||||
{
|
||||
typedef Subject subject_type;
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef typename
|
||||
traits::attribute_of<subject_type, Context, Iterator>::type
|
||||
type;
|
||||
};
|
||||
|
||||
seek_directive(Subject const& subject)
|
||||
: subject(subject)
|
||||
{}
|
||||
|
||||
template
|
||||
<
|
||||
typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute
|
||||
>
|
||||
bool parse
|
||||
(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr
|
||||
) const
|
||||
{
|
||||
for (Iterator it(first); ; ++it)
|
||||
{
|
||||
if (subject.parse(it, last, context, skipper, attr))
|
||||
{
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
// fail only after subject fails & no input
|
||||
if (it == last)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& context) const
|
||||
{
|
||||
return info("seek", subject.what(context));
|
||||
}
|
||||
|
||||
Subject subject;
|
||||
};
|
||||
}}}} // namespace boost::spirit::repository::qi
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename Modifiers>
|
||||
struct make_directive<repository::tag::seek, Subject, Modifiers>
|
||||
{
|
||||
typedef repository::qi::seek_directive<Subject> result_type;
|
||||
|
||||
result_type operator()(unused_type, Subject const& subject, unused_type) const
|
||||
{
|
||||
return result_type(subject);
|
||||
}
|
||||
};
|
||||
}}} // namespace boost::spirit::qi
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject>
|
||||
struct has_semantic_action<repository::qi::seek_directive<Subject> >
|
||||
: unary_has_semantic_action<Subject> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename Attribute, typename Context
|
||||
, typename Iterator>
|
||||
struct handles_container<repository::qi::seek_directive<Subject>, Attribute
|
||||
, Context, Iterator>
|
||||
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 Joel de Guzman
|
||||
// Copyright (c) 2009 Francois Barel
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_QI_NONTERMINAL_AUG_12_2009_1140AM)
|
||||
#define SPIRIT_REPOSITORY_QI_NONTERMINAL_AUG_12_2009_1140AM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/qi/nonterminal/subrule.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
+590
@@ -0,0 +1,590 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Francois Barel
|
||||
Copyright (c) 2001-2011 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_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/domain.hpp>
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/qi/parser.hpp>
|
||||
#include <boost/spirit/home/qi/reference.hpp>
|
||||
#include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
|
||||
#include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
|
||||
#include <boost/spirit/home/support/argument.hpp>
|
||||
#include <boost/spirit/home/support/assert_msg.hpp>
|
||||
#include <boost/spirit/home/qi/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/extract_param.hpp>
|
||||
#include <boost/spirit/home/support/nonterminal/locals.hpp>
|
||||
#include <boost/spirit/repository/home/support/subrule_context.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_map.hpp>
|
||||
#include <boost/fusion/include/at_key.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/has_key.hpp>
|
||||
#include <boost/fusion/include/join.hpp>
|
||||
#include <boost/fusion/include/make_map.hpp>
|
||||
#include <boost/fusion/include/make_vector.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_reference.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 repository { namespace qi
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule_group:
|
||||
// - parser representing a group of subrule definitions (one or more),
|
||||
// invokes first subrule on entry,
|
||||
// - also a Proto terminal, so that a group behaves like any Spirit
|
||||
// expression.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Defs>
|
||||
struct subrule_group
|
||||
: proto::extends<
|
||||
typename proto::terminal<
|
||||
spirit::qi::reference<subrule_group<Defs> const>
|
||||
>::type
|
||||
, subrule_group<Defs>
|
||||
>
|
||||
, spirit::qi::parser<subrule_group<Defs> >
|
||||
{
|
||||
// Fusion associative sequence, associating each subrule ID in this
|
||||
// group (as an MPL integral constant) with its definition
|
||||
typedef Defs defs_type;
|
||||
|
||||
typedef subrule_group<Defs> this_type;
|
||||
typedef spirit::qi::reference<this_type const> reference_;
|
||||
typedef typename proto::terminal<reference_>::type terminal;
|
||||
typedef proto::extends<terminal, this_type> base_type;
|
||||
|
||||
static size_t const params_size =
|
||||
// Forward to first subrule.
|
||||
remove_reference<
|
||||
typename fusion::result_of::front<Defs>::type
|
||||
>::type::second_type::params_size;
|
||||
|
||||
subrule_group(subrule_group const& rhs)
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, defs(rhs.defs)
|
||||
{
|
||||
}
|
||||
|
||||
explicit subrule_group(Defs const& defs)
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, defs(defs)
|
||||
{
|
||||
}
|
||||
|
||||
// from a subrule ID, get the type of a reference to its definition
|
||||
template <int ID>
|
||||
struct def_type
|
||||
{
|
||||
typedef mpl::int_<ID> id_type;
|
||||
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule which was not defined in this group.
|
||||
BOOST_SPIRIT_ASSERT_MSG(
|
||||
(fusion::result_of::has_key<
|
||||
defs_type const, id_type>::type::value)
|
||||
, subrule_used_without_being_defined, (mpl::int_<ID>));
|
||||
|
||||
typedef typename
|
||||
fusion::result_of::at_key<defs_type const, id_type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// from a subrule ID, get a reference to its definition
|
||||
template <int ID>
|
||||
typename def_type<ID>::type def() const
|
||||
{
|
||||
return fusion::at_key<mpl::int_<ID> >(defs);
|
||||
}
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
// Forward to first subrule.
|
||||
: mpl::identity<
|
||||
typename remove_reference<
|
||||
typename fusion::result_of::front<Defs>::type
|
||||
>::type::second_type::attr_type> {};
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return parse_subrule(fusion::front(defs).second
|
||||
, first, last, context, skipper, attr);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute, typename Params>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr, Params const& params) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return parse_subrule(fusion::front(defs).second
|
||||
, first, last, context, skipper, attr, params);
|
||||
}
|
||||
|
||||
template <int ID, typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse_subrule_id(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
return parse_subrule(def<ID>()
|
||||
, first, last, context, skipper, attr);
|
||||
}
|
||||
|
||||
template <int ID, typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute, typename Params>
|
||||
bool parse_subrule_id(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr, Params const& params) const
|
||||
{
|
||||
return parse_subrule(def<ID>()
|
||||
, first, last, context, skipper, attr, params);
|
||||
}
|
||||
|
||||
template <typename Def
|
||||
, typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse_subrule(Def const& def
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context& /*caller_context*/, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
// compute context type for this subrule
|
||||
typedef typename Def::locals_type subrule_locals_type;
|
||||
typedef typename Def::attr_type subrule_attr_type;
|
||||
typedef typename Def::attr_reference_type subrule_attr_reference_type;
|
||||
typedef typename Def::parameter_types subrule_parameter_types;
|
||||
|
||||
typedef
|
||||
subrule_context<
|
||||
this_type
|
||||
, fusion::cons<
|
||||
subrule_attr_reference_type, subrule_parameter_types>
|
||||
, subrule_locals_type
|
||||
>
|
||||
context_type;
|
||||
|
||||
// prepare attribute
|
||||
typedef traits::make_attribute<
|
||||
subrule_attr_type, Attribute> make_attribute;
|
||||
|
||||
// do down-stream transformation, provides attribute for
|
||||
// rhs parser
|
||||
typedef traits::transform_attribute<
|
||||
typename make_attribute::type, subrule_attr_type, spirit::qi::domain>
|
||||
transform;
|
||||
|
||||
typename make_attribute::type made_attr = make_attribute::call(attr);
|
||||
typename transform::type attr_ = transform::pre(made_attr);
|
||||
|
||||
// If you are seeing a compilation error here, you are probably
|
||||
// trying to use a subrule which has inherited attributes,
|
||||
// without passing values for them.
|
||||
context_type context(*this, attr_);
|
||||
|
||||
if (def.binder(first, last, context, skipper))
|
||||
{
|
||||
// do up-stream transformation, this integrates the results
|
||||
// back into the original attribute value, if appropriate
|
||||
traits::post_transform(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// inform attribute transformation of failed rhs
|
||||
traits::fail_transform(attr, attr_);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Def
|
||||
, typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute, typename Params>
|
||||
bool parse_subrule(Def const& def
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context& caller_context, Skipper const& skipper
|
||||
, Attribute& attr, Params const& params) const
|
||||
{
|
||||
// compute context type for this subrule
|
||||
typedef typename Def::locals_type subrule_locals_type;
|
||||
typedef typename Def::attr_type subrule_attr_type;
|
||||
typedef typename Def::attr_reference_type subrule_attr_reference_type;
|
||||
typedef typename Def::parameter_types subrule_parameter_types;
|
||||
|
||||
typedef
|
||||
subrule_context<
|
||||
this_type
|
||||
, fusion::cons<
|
||||
subrule_attr_reference_type, subrule_parameter_types>
|
||||
, subrule_locals_type
|
||||
>
|
||||
context_type;
|
||||
|
||||
// prepare attribute
|
||||
typedef traits::make_attribute<
|
||||
subrule_attr_type, Attribute> make_attribute;
|
||||
|
||||
// do down-stream transformation, provides attribute for
|
||||
// rhs parser
|
||||
typedef traits::transform_attribute<
|
||||
typename make_attribute::type, subrule_attr_type, spirit::qi::domain>
|
||||
transform;
|
||||
|
||||
typename make_attribute::type made_attr = make_attribute::call(attr);
|
||||
typename transform::type attr_ = transform::pre(made_attr);
|
||||
|
||||
// If you are seeing a compilation error here, you are probably
|
||||
// trying to use a subrule which has inherited attributes,
|
||||
// passing values of incompatible types for them.
|
||||
context_type context(*this, attr_, params, caller_context);
|
||||
|
||||
if (def.binder(first, last, context, skipper))
|
||||
{
|
||||
// do up-stream transformation, this integrates the results
|
||||
// back into the original attribute value, if appropriate
|
||||
traits::post_transform(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// inform attribute transformation of failed rhs
|
||||
traits::fail_transform(attr, attr_);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& context) const
|
||||
{
|
||||
// Forward to first subrule.
|
||||
return fusion::front(defs).second.binder.p.what(context);
|
||||
}
|
||||
|
||||
template <typename Defs2>
|
||||
subrule_group<
|
||||
typename fusion::result_of::as_map<
|
||||
typename fusion::result_of::join<
|
||||
Defs const, Defs2 const>::type>::type>
|
||||
operator,(subrule_group<Defs2> const& other) const
|
||||
{
|
||||
typedef subrule_group<
|
||||
typename fusion::result_of::as_map<
|
||||
typename fusion::result_of::join<
|
||||
Defs const, Defs2 const>::type>::type> result_type;
|
||||
return result_type(fusion::as_map(fusion::join(defs, other.defs)));
|
||||
}
|
||||
|
||||
// bring in the operator() overloads
|
||||
this_type const& get_parameterized_subject() const { return *this; }
|
||||
typedef this_type parameterized_subject_type;
|
||||
#include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
|
||||
|
||||
Defs defs;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule_definition: holds one particular definition of a subrule
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
int ID_
|
||||
, typename Locals
|
||||
, typename Attr
|
||||
, typename AttrRef
|
||||
, typename Parameters
|
||||
, size_t ParamsSize
|
||||
, typename Subject
|
||||
, bool Auto_
|
||||
>
|
||||
struct subrule_definition
|
||||
{
|
||||
typedef mpl::int_<ID_> id_type;
|
||||
BOOST_STATIC_CONSTANT(int, ID = ID_);
|
||||
|
||||
typedef Locals locals_type;
|
||||
typedef Attr attr_type;
|
||||
typedef AttrRef attr_reference_type;
|
||||
typedef Parameters parameter_types;
|
||||
static size_t const params_size = ParamsSize;
|
||||
|
||||
typedef Subject subject_type;
|
||||
typedef mpl::bool_<Auto_> auto_type;
|
||||
BOOST_STATIC_CONSTANT(bool, Auto = Auto_);
|
||||
|
||||
typedef spirit::qi::detail::parser_binder<
|
||||
Subject, auto_type> binder_type;
|
||||
|
||||
subrule_definition(Subject const& subject, std::string const& name)
|
||||
: binder(subject), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
binder_type const binder;
|
||||
std::string const name;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule placeholder:
|
||||
// - on subrule definition: helper for creation of subrule_group,
|
||||
// - on subrule invocation: Proto terminal and parser.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
int ID_
|
||||
, typename T1 = unused_type
|
||||
, typename T2 = unused_type
|
||||
>
|
||||
struct subrule
|
||||
: proto::extends<
|
||||
typename proto::terminal<
|
||||
spirit::qi::reference<subrule<ID_, T1, T2> const>
|
||||
>::type
|
||||
, subrule<ID_, T1, T2>
|
||||
>
|
||||
, spirit::qi::parser<subrule<ID_, T1, T2> >
|
||||
{
|
||||
typedef mpl::int_<ID_> id_type;
|
||||
BOOST_STATIC_CONSTANT(int, ID = ID_);
|
||||
|
||||
typedef subrule<ID_, T1, T2> this_type;
|
||||
typedef spirit::qi::reference<this_type const> reference_;
|
||||
typedef typename proto::terminal<reference_>::type terminal;
|
||||
typedef proto::extends<terminal, this_type> base_type;
|
||||
|
||||
typedef mpl::vector<T1, T2> template_params;
|
||||
|
||||
// locals_type is a sequence of types to be used as local variables
|
||||
typedef typename
|
||||
spirit::detail::extract_locals<template_params>::type
|
||||
locals_type;
|
||||
|
||||
typedef typename
|
||||
spirit::detail::extract_sig<template_params>::type
|
||||
sig_type;
|
||||
|
||||
// This is the subrule's attribute type
|
||||
typedef typename
|
||||
spirit::detail::attr_from_sig<sig_type>::type
|
||||
attr_type;
|
||||
typedef typename add_reference<attr_type>::type attr_reference_type;
|
||||
|
||||
// parameter_types is a sequence of types passed as parameters to the subrule
|
||||
typedef typename
|
||||
spirit::detail::params_from_sig<sig_type>::type
|
||||
parameter_types;
|
||||
|
||||
static size_t const params_size =
|
||||
fusion::result_of::size<parameter_types>::type::value;
|
||||
|
||||
explicit subrule(std::string const& name_ = "unnamed-subrule")
|
||||
: base_type(terminal::make(reference_(*this)))
|
||||
, name_(name_)
|
||||
{
|
||||
}
|
||||
|
||||
// compute type of this subrule's definition for expr type Expr
|
||||
template <typename Expr, bool Auto>
|
||||
struct def_type_helper
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (Expr) is not a valid spirit qi expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, Expr);
|
||||
|
||||
typedef typename result_of::compile<
|
||||
spirit::qi::domain, Expr>::type subject_type;
|
||||
|
||||
typedef subrule_definition<
|
||||
ID_
|
||||
, locals_type
|
||||
, attr_type
|
||||
, attr_reference_type
|
||||
, parameter_types
|
||||
, params_size
|
||||
, subject_type
|
||||
, Auto
|
||||
> const type;
|
||||
};
|
||||
|
||||
// compute type of subrule group containing only this
|
||||
// subrule's definition for expr type Expr
|
||||
template <typename Expr, bool Auto>
|
||||
struct group_type_helper
|
||||
{
|
||||
typedef typename def_type_helper<Expr, Auto>::type def_type;
|
||||
|
||||
// create Defs map with only one entry: (ID -> def)
|
||||
typedef typename
|
||||
#ifndef BOOST_FUSION_HAS_VARIADIC_MAP
|
||||
fusion::result_of::make_map<id_type, def_type>::type
|
||||
#else
|
||||
fusion::result_of::make_map<id_type>::template apply<def_type>::type
|
||||
#endif
|
||||
defs_type;
|
||||
|
||||
typedef subrule_group<defs_type> type;
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
typename group_type_helper<Expr, false>::type
|
||||
operator=(Expr const& expr) const
|
||||
{
|
||||
typedef group_type_helper<Expr, false> helper;
|
||||
typedef typename helper::def_type def_type;
|
||||
typedef typename helper::type result_type;
|
||||
return result_type(fusion::make_map<id_type>(
|
||||
def_type(compile<spirit::qi::domain>(expr), name_)));
|
||||
}
|
||||
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule const& sr, Expr const& expr)
|
||||
{
|
||||
typedef group_type_helper<Expr, true> helper;
|
||||
typedef typename helper::def_type def_type;
|
||||
typedef typename helper::type result_type;
|
||||
return result_type(fusion::make_map<id_type>(
|
||||
def_type(compile<spirit::qi::domain>(expr), sr.name_)));
|
||||
}
|
||||
|
||||
// non-const versions needed to suppress proto's %= kicking in
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule const& sr, Expr& expr)
|
||||
{
|
||||
return operator%=(
|
||||
sr
|
||||
, static_cast<Expr const&>(expr));
|
||||
}
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule& sr, Expr const& expr)
|
||||
{
|
||||
return operator%=(
|
||||
static_cast<subrule const&>(sr)
|
||||
, expr);
|
||||
}
|
||||
template <typename Expr>
|
||||
friend typename group_type_helper<Expr, true>::type
|
||||
operator%=(subrule& sr, Expr& expr)
|
||||
{
|
||||
return operator%=(
|
||||
static_cast<subrule const&>(sr)
|
||||
, static_cast<Expr const&>(expr));
|
||||
}
|
||||
|
||||
std::string const& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void name(std::string const& str)
|
||||
{
|
||||
name_ = str;
|
||||
}
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef attr_type type;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename Group
|
||||
, typename Attributes, typename Locals
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, subrule_context<Group, Attributes, Locals>& context
|
||||
, Skipper const& skipper, Attribute& attr) const
|
||||
{
|
||||
return context.group.template parse_subrule_id<ID_>(
|
||||
first, last, context, skipper, attr);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& /*first*/, Iterator const& /*last*/
|
||||
, Context& /*context*/
|
||||
, Skipper const& /*skipper*/, Attribute& /*attr*/) const
|
||||
{
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule as a parser outside of a subrule group.
|
||||
BOOST_SPIRIT_ASSERT_FAIL(Iterator
|
||||
, subrule_used_outside_subrule_group, (id_type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Group
|
||||
, typename Attributes, typename Locals
|
||||
, typename Skipper, typename Attribute
|
||||
, typename Params>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, subrule_context<Group, Attributes, Locals>& context
|
||||
, Skipper const& skipper, Attribute& attr
|
||||
, Params const& params) const
|
||||
{
|
||||
return context.group.template parse_subrule_id<ID_>(
|
||||
first, last, context, skipper, attr, params);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute
|
||||
, typename Params>
|
||||
bool parse(Iterator& /*first*/, Iterator const& /*last*/
|
||||
, Context& /*context*/
|
||||
, Skipper const& /*skipper*/, Attribute& /*attr*/
|
||||
, Params const& /*params*/) const
|
||||
{
|
||||
// If you are seeing a compilation error here, you are trying
|
||||
// to use a subrule as a parser outside of a subrule group.
|
||||
BOOST_SPIRIT_ASSERT_FAIL(Iterator
|
||||
, subrule_used_outside_subrule_group, (id_type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& /*context*/) const
|
||||
{
|
||||
return info(name_);
|
||||
}
|
||||
|
||||
// bring in the operator() overloads
|
||||
this_type const& get_parameterized_subject() const { return *this; }
|
||||
typedef this_type parameterized_subject_type;
|
||||
#include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
}}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 Joel de Guzman
|
||||
// Copyright (c) 2011 Thomas Bernard
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_QI_OPERATOR_OCT_20_2010_1258PM)
|
||||
#define SPIRIT_REPOSITORY_QI_OPERATOR_OCT_20_2010_1258PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/qi/operator/keywords.hpp>
|
||||
#endif
|
||||
|
||||
+696
@@ -0,0 +1,696 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2011-2012 Thomas Bernard
|
||||
|
||||
Distributed under the 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
|
||||
#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
#include <boost/fusion/include/nview.hpp>
|
||||
#include <boost/spirit/home/qi/string/lit.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
|
||||
// Variant visitor class which handles dispatching the parsing to the selected parser
|
||||
// This also handles passing the correct attributes and flags/counters to the subject parsers
|
||||
template<typename T>
|
||||
struct is_distinct : T::distinct { };
|
||||
|
||||
template<typename T, typename Action>
|
||||
struct is_distinct< spirit::qi::action<T,Action> > : T::distinct { };
|
||||
|
||||
template<typename T>
|
||||
struct is_distinct< spirit::qi::hold_directive<T> > : T::distinct { };
|
||||
|
||||
|
||||
|
||||
template < typename Elements, typename Iterator ,typename Context ,typename Skipper
|
||||
,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
|
||||
struct parse_dispatcher
|
||||
: public boost::static_visitor<bool>
|
||||
{
|
||||
|
||||
typedef Iterator iterator_type;
|
||||
typedef Context context_type;
|
||||
typedef Skipper skipper_type;
|
||||
typedef Elements elements_type;
|
||||
|
||||
typedef typename add_reference<Attribute>::type attr_reference;
|
||||
public:
|
||||
parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Flags &flags, Counters &counters, attr_reference attr) :
|
||||
elements(elements), first(first), last(last)
|
||||
, context(context), skipper(skipper)
|
||||
, flags(flags),counters(counters), attr(attr)
|
||||
{}
|
||||
|
||||
template<typename T> bool operator()(T& idx) const
|
||||
{
|
||||
return call(idx,typename traits::not_is_unused<Attribute>::type());
|
||||
}
|
||||
|
||||
template <typename Subject,typename Index>
|
||||
bool call_subject_unused(
|
||||
Subject const &subject, Iterator &first, Iterator const &last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Index& idx ) const
|
||||
{
|
||||
Iterator save = first;
|
||||
skipper_keyword_marker<Skipper,NoCasePass>
|
||||
marked_skipper(skipper,flags[Index::value],counters[Index::value]);
|
||||
|
||||
if(subject.parse(first,last,context,marked_skipper,unused))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
save = save;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename Subject,typename Index>
|
||||
bool call_subject(
|
||||
Subject const &subject, Iterator &first, Iterator const &last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Index& idx ) const
|
||||
{
|
||||
|
||||
Iterator save = first;
|
||||
skipper_keyword_marker<Skipper,NoCasePass>
|
||||
marked_skipper(skipper,flags[Index::value],counters[Index::value]);
|
||||
if(subject.parse(first,last,context,marked_skipper,fusion::at_c<Index::value>(attr)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
save = save;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle unused attributes
|
||||
template <typename T> bool call(T &idx, mpl::false_) const{
|
||||
|
||||
typedef typename mpl::at<Elements,T>::type ElementType;
|
||||
if(
|
||||
(!is_distinct<ElementType>::value)
|
||||
|| skipper.parse(first,last,unused,unused,unused)
|
||||
){
|
||||
spirit::qi::skip_over(first, last, skipper);
|
||||
return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Handle normal attributes
|
||||
template <typename T> bool call(T &idx, mpl::true_) const{
|
||||
typedef typename mpl::at<Elements,T>::type ElementType;
|
||||
if(
|
||||
(!is_distinct<ElementType>::value)
|
||||
|| skipper.parse(first,last,unused,unused,unused)
|
||||
){
|
||||
return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Elements &elements;
|
||||
Iterator &first;
|
||||
const Iterator &last;
|
||||
Context & context;
|
||||
const Skipper &skipper;
|
||||
Flags &flags;
|
||||
Counters &counters;
|
||||
attr_reference attr;
|
||||
};
|
||||
// string keyword loop handler
|
||||
template <typename Elements, typename StringKeywords, typename IndexList, typename FlagsType, typename Modifiers>
|
||||
struct string_keywords
|
||||
{
|
||||
// Create a variant type to be able to store parser indexes in the embedded symbols parser
|
||||
typedef typename
|
||||
spirit::detail::as_variant<
|
||||
IndexList >::type parser_index_type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// build_char_type_sequence
|
||||
//
|
||||
// Build a fusion sequence from the kwd directive specified character type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence >
|
||||
struct build_char_type_sequence
|
||||
{
|
||||
struct element_char_type
|
||||
{
|
||||
template <typename T>
|
||||
struct result;
|
||||
|
||||
template <typename F, typename Element>
|
||||
struct result<F(Element)>
|
||||
{
|
||||
typedef typename Element::char_type type;
|
||||
|
||||
};
|
||||
template <typename F, typename Element,typename Action>
|
||||
struct result<F(spirit::qi::action<Element,Action>) >
|
||||
{
|
||||
typedef typename Element::char_type type;
|
||||
};
|
||||
template <typename F, typename Element>
|
||||
struct result<F(spirit::qi::hold_directive<Element>)>
|
||||
{
|
||||
typedef typename Element::char_type type;
|
||||
};
|
||||
|
||||
// never called, but needed for decltype-based result_of (C++0x)
|
||||
template <typename Element>
|
||||
typename result<element_char_type(Element)>::type
|
||||
operator()(Element&) const;
|
||||
};
|
||||
|
||||
// Compute the list of character types of the child kwd directives
|
||||
typedef typename
|
||||
fusion::result_of::transform<Sequence, element_char_type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get_keyword_char_type
|
||||
//
|
||||
// Collapses the character type comming from the subject kwd parsers and
|
||||
// and checks that they are all identical (necessary in order to be able
|
||||
// to build a tst parser to parse the keywords.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence>
|
||||
struct get_keyword_char_type
|
||||
{
|
||||
// Make sure each of the types occur only once in the type list
|
||||
typedef typename
|
||||
mpl::fold<
|
||||
Sequence, mpl::vector<>,
|
||||
mpl::if_<
|
||||
mpl::contains<mpl::_1, mpl::_2>,
|
||||
mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
|
||||
>
|
||||
>::type
|
||||
no_duplicate_char_types;
|
||||
|
||||
// If the compiler traps here this means you mixed
|
||||
// character type for the keywords specified in the
|
||||
// kwd directive sequence.
|
||||
BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
|
||||
|
||||
typedef typename mpl::front<no_duplicate_char_types>::type type;
|
||||
|
||||
};
|
||||
|
||||
// Get the character type for the tst parser
|
||||
typedef typename build_char_type_sequence< StringKeywords >::type char_types;
|
||||
typedef typename get_keyword_char_type<
|
||||
typename mpl::if_<
|
||||
mpl::equal_to<
|
||||
typename mpl::size < char_types >::type
|
||||
, mpl::int_<0>
|
||||
>
|
||||
, mpl::vector< boost::spirit::standard::char_type >
|
||||
, char_types >::type
|
||||
>::type char_type;
|
||||
|
||||
// Our symbols container
|
||||
typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
|
||||
|
||||
// Filter functor used for case insensitive parsing
|
||||
template <typename CharEncoding>
|
||||
struct no_case_filter
|
||||
{
|
||||
char_type operator()(char_type ch) const
|
||||
{
|
||||
return static_cast<char_type>(CharEncoding::tolower(ch));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// build_case_type_sequence
|
||||
//
|
||||
// Build a fusion sequence from the kwd/ikwd directives
|
||||
// in order to determine if case sensitive and case insensitive
|
||||
// keywords have been mixed.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence >
|
||||
struct build_case_type_sequence
|
||||
{
|
||||
struct element_case_type
|
||||
{
|
||||
template <typename T>
|
||||
struct result;
|
||||
|
||||
template <typename F, typename Element>
|
||||
struct result<F(Element)>
|
||||
{
|
||||
typedef typename Element::no_case_keyword type;
|
||||
|
||||
};
|
||||
template <typename F, typename Element,typename Action>
|
||||
struct result<F(spirit::qi::action<Element,Action>) >
|
||||
{
|
||||
typedef typename Element::no_case_keyword type;
|
||||
};
|
||||
template <typename F, typename Element>
|
||||
struct result<F(spirit::qi::hold_directive<Element>)>
|
||||
{
|
||||
typedef typename Element::no_case_keyword type;
|
||||
};
|
||||
|
||||
// never called, but needed for decltype-based result_of (C++0x)
|
||||
template <typename Element>
|
||||
typename result<element_case_type(Element)>::type
|
||||
operator()(Element&) const;
|
||||
};
|
||||
|
||||
// Compute the list of character types of the child kwd directives
|
||||
typedef typename
|
||||
fusion::result_of::transform<Sequence, element_case_type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get_nb_case_types
|
||||
//
|
||||
// Counts the number of entries in the case type sequence matching the
|
||||
// CaseType parameter (mpl::true_ -> case insensitve
|
||||
// , mpl::false_ -> case sensitive
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence,typename CaseType>
|
||||
struct get_nb_case_types
|
||||
{
|
||||
// Make sure each of the types occur only once in the type list
|
||||
typedef typename
|
||||
mpl::count_if<
|
||||
Sequence, mpl::equal_to<mpl::_,CaseType>
|
||||
>::type type;
|
||||
|
||||
|
||||
};
|
||||
// Build the case type sequence
|
||||
typedef typename build_case_type_sequence< StringKeywords >::type case_type_sequence;
|
||||
// Count the number of case sensitive entries and case insensitve entries
|
||||
typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
|
||||
typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
|
||||
// Get the size of the original sequence
|
||||
typedef typename mpl::size<IndexList>::type nb_elements;
|
||||
// Determine if all the kwd directive are case sensitive/insensitive
|
||||
typedef typename mpl::and_<
|
||||
typename mpl::greater< nb_elements, mpl::int_<0> >::type
|
||||
, typename mpl::equal_to< ikwd_count, nb_elements>::type
|
||||
>::type all_ikwd;
|
||||
|
||||
typedef typename mpl::and_<
|
||||
typename mpl::greater< nb_elements, mpl::int_<0> >::type
|
||||
, typename mpl::equal_to< kwd_count, nb_elements>::type
|
||||
>::type all_kwd;
|
||||
|
||||
typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
|
||||
|
||||
// Do we have a no case modifier
|
||||
typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
|
||||
|
||||
// Should the no_case filter always be used ?
|
||||
typedef typename mpl::or_<
|
||||
no_case_modifier,
|
||||
mpl::and_<
|
||||
all_directives_of_same_type
|
||||
,all_ikwd
|
||||
>
|
||||
>::type
|
||||
no_case;
|
||||
|
||||
typedef no_case_filter<
|
||||
typename spirit::detail::get_encoding_with_case<
|
||||
Modifiers
|
||||
, char_encoding::standard
|
||||
, no_case::value>::type>
|
||||
nc_filter;
|
||||
// Determine the standard case filter type
|
||||
typedef typename mpl::if_<
|
||||
no_case
|
||||
, nc_filter
|
||||
, spirit::qi::tst_pass_through >::type
|
||||
first_pass_filter_type;
|
||||
|
||||
typedef typename mpl::or_<
|
||||
all_directives_of_same_type
|
||||
, no_case_modifier
|
||||
>::type requires_one_pass;
|
||||
|
||||
|
||||
// Functor which adds all the keywords/subject parser indexes
|
||||
// collected from the subject kwd directives to the keyword tst parser
|
||||
struct keyword_entry_adder
|
||||
{
|
||||
typedef int result_type;
|
||||
|
||||
keyword_entry_adder(shared_ptr<keywords_type> lookup,FlagsType &flags, Elements &elements) :
|
||||
lookup(lookup)
|
||||
,flags(flags)
|
||||
,elements(elements)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
int operator()(const T &index) const
|
||||
{
|
||||
return call(fusion::at_c<T::value>(elements),index);
|
||||
}
|
||||
|
||||
template <typename T, typename Position, typename Action>
|
||||
int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
|
||||
{
|
||||
|
||||
// Make the keyword/parse index entry in the tst parser
|
||||
lookup->add(
|
||||
traits::get_begin<char_type>(get_string(parser.subject.keyword)),
|
||||
traits::get_end<char_type>(get_string(parser.subject.keyword)),
|
||||
position
|
||||
);
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.subject.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename Position>
|
||||
int call( const T & parser, const Position position) const
|
||||
{
|
||||
// Make the keyword/parse index entry in the tst parser
|
||||
lookup->add(
|
||||
traits::get_begin<char_type>(get_string(parser.keyword)),
|
||||
traits::get_end<char_type>(get_string(parser.keyword)),
|
||||
position
|
||||
);
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename Position>
|
||||
int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
|
||||
{
|
||||
// Make the keyword/parse index entry in the tst parser
|
||||
lookup->add(
|
||||
traits::get_begin<char_type>(get_string(parser.subject.keyword)),
|
||||
traits::get_end<char_type>(get_string(parser.subject.keyword)),
|
||||
position
|
||||
);
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.subject.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename String, bool no_attribute>
|
||||
const String get_string(const boost::spirit::qi::literal_string<String,no_attribute> &parser) const
|
||||
{
|
||||
return parser.str;
|
||||
}
|
||||
|
||||
template <typename String, bool no_attribute>
|
||||
const typename boost::spirit::qi::no_case_literal_string<String,no_attribute>::string_type &
|
||||
get_string(const boost::spirit::qi::no_case_literal_string<String,no_attribute> &parser) const
|
||||
{
|
||||
return parser.str_lo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
shared_ptr<keywords_type> lookup;
|
||||
FlagsType & flags;
|
||||
Elements &elements;
|
||||
};
|
||||
|
||||
string_keywords(Elements &elements,FlagsType &flags_init) : lookup(new keywords_type())
|
||||
{
|
||||
// Loop through all the subject parsers to build the keyword parser symbol parser
|
||||
IndexList indexes;
|
||||
keyword_entry_adder f1(lookup,flags_init,elements);
|
||||
fusion::for_each(indexes,f1);
|
||||
|
||||
}
|
||||
template <typename Iterator,typename ParseVisitor, typename Skipper>
|
||||
bool parse(
|
||||
Iterator &first,
|
||||
const Iterator &last,
|
||||
const ParseVisitor &parse_visitor,
|
||||
const Skipper &skipper) const
|
||||
{
|
||||
if(parser_index_type* val_ptr =
|
||||
lookup->find(first,last,first_pass_filter_type()))
|
||||
{
|
||||
if(!apply_visitor(parse_visitor,*val_ptr)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
|
||||
bool parse(
|
||||
Iterator &first,
|
||||
const Iterator &last,
|
||||
const ParseVisitor &parse_visitor,
|
||||
const NoCaseParseVisitor &no_case_parse_visitor,
|
||||
const Skipper &skipper) const
|
||||
{
|
||||
Iterator saved_first = first;
|
||||
if(parser_index_type* val_ptr =
|
||||
lookup->find(first,last,first_pass_filter_type()))
|
||||
{
|
||||
if(!apply_visitor(parse_visitor,*val_ptr)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Second pass case insensitive
|
||||
else if(parser_index_type* val_ptr
|
||||
= lookup->find(saved_first,last,nc_filter()))
|
||||
{
|
||||
first = saved_first;
|
||||
if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
shared_ptr<keywords_type> lookup;
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct empty_keywords_list
|
||||
{
|
||||
typedef mpl::true_ requires_one_pass;
|
||||
|
||||
empty_keywords_list()
|
||||
{}
|
||||
template<typename Elements>
|
||||
empty_keywords_list(const Elements &)
|
||||
{}
|
||||
|
||||
template<typename Elements, typename FlagsInit>
|
||||
empty_keywords_list(const Elements &, const FlagsInit &)
|
||||
{}
|
||||
|
||||
template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
|
||||
bool parse(
|
||||
Iterator &first,
|
||||
const Iterator &last,
|
||||
const ParseVisitor &parse_visitor,
|
||||
const NoCaseParseVisitor &no_case_parse_visitor,
|
||||
const Skipper &skipper) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator,typename ParseVisitor, typename Skipper>
|
||||
bool parse(
|
||||
Iterator &first,
|
||||
const Iterator &last,
|
||||
const ParseVisitor &parse_visitor,
|
||||
const Skipper &skipper) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ParseFunction>
|
||||
bool parse( ParseFunction &function ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ComplexKeywords>
|
||||
struct complex_keywords
|
||||
{
|
||||
// Functor which performs the flag initialization for the complex keyword parsers
|
||||
template <typename FlagsType, typename Elements>
|
||||
struct flag_init_value_setter
|
||||
{
|
||||
typedef int result_type;
|
||||
|
||||
flag_init_value_setter(Elements &elements,FlagsType &flags)
|
||||
:flags(flags)
|
||||
,elements(elements)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
int operator()(const T &index) const
|
||||
{
|
||||
return call(fusion::at_c<T::value>(elements),index);
|
||||
}
|
||||
|
||||
template <typename T, typename Position, typename Action>
|
||||
int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
|
||||
{
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.subject.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename Position>
|
||||
int call( const T & parser, const Position position) const
|
||||
{
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename Position>
|
||||
int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
|
||||
{
|
||||
// Get the initial state of the flags array and store it in the flags initializer
|
||||
flags[Position::value]=parser.subject.iter.flag_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
FlagsType & flags;
|
||||
Elements &elements;
|
||||
};
|
||||
|
||||
template <typename Elements, typename Flags>
|
||||
complex_keywords(Elements &elements, Flags &flags)
|
||||
{
|
||||
flag_init_value_setter<Flags,Elements> flag_initializer(elements,flags);
|
||||
fusion::for_each(complex_keywords_inst,flag_initializer);
|
||||
}
|
||||
|
||||
template <typename ParseFunction>
|
||||
bool parse( ParseFunction &function ) const
|
||||
{
|
||||
return fusion::any(complex_keywords_inst,function);
|
||||
}
|
||||
|
||||
ComplexKeywords complex_keywords_inst;
|
||||
};
|
||||
// This helper class enables jumping over intermediate directives
|
||||
// down the kwd parser iteration count checking policy
|
||||
struct register_successful_parse
|
||||
{
|
||||
template <typename Subject>
|
||||
static bool call(Subject const &subject,bool &flag, int &counter)
|
||||
{
|
||||
return subject.iter.register_successful_parse(flag,counter);
|
||||
}
|
||||
template <typename Subject, typename Action>
|
||||
static bool call(spirit::qi::action<Subject, Action> const &subject,bool &flag, int &counter)
|
||||
{
|
||||
return subject.subject.iter.register_successful_parse(flag,counter);
|
||||
}
|
||||
template <typename Subject>
|
||||
static bool call(spirit::qi::hold_directive<Subject> const &subject,bool &flag, int &counter)
|
||||
{
|
||||
return subject.subject.iter.register_successful_parse(flag,counter);
|
||||
}
|
||||
};
|
||||
|
||||
// This helper class enables jumping over intermediate directives
|
||||
// down the kwd parser
|
||||
struct extract_keyword
|
||||
{
|
||||
template <typename Subject>
|
||||
static Subject const& call(Subject const &subject)
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
template <typename Subject, typename Action>
|
||||
static Subject const& call(spirit::qi::action<Subject, Action> const &subject)
|
||||
{
|
||||
return subject.subject;
|
||||
}
|
||||
template <typename Subject>
|
||||
static Subject const& call(spirit::qi::hold_directive<Subject> const &subject)
|
||||
{
|
||||
return subject.subject;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ParseDispatcher>
|
||||
struct complex_kwd_function
|
||||
{
|
||||
typedef typename ParseDispatcher::iterator_type Iterator;
|
||||
typedef typename ParseDispatcher::context_type Context;
|
||||
typedef typename ParseDispatcher::skipper_type Skipper;
|
||||
complex_kwd_function(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper, ParseDispatcher &dispatcher)
|
||||
: first(first)
|
||||
, last(last)
|
||||
, context(context)
|
||||
, skipper(skipper)
|
||||
, dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
bool operator()(Component const& component)
|
||||
{
|
||||
Iterator save = first;
|
||||
if(
|
||||
extract_keyword::call(
|
||||
fusion::at_c<
|
||||
Component::value
|
||||
,typename ParseDispatcher::elements_type
|
||||
>(dispatcher.elements)
|
||||
)
|
||||
.keyword.parse(
|
||||
first
|
||||
,last
|
||||
,context
|
||||
,skipper
|
||||
,unused)
|
||||
)
|
||||
{
|
||||
if(!dispatcher(component)){
|
||||
first = save;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator& first;
|
||||
Iterator const& last;
|
||||
Context& context;
|
||||
Skipper const& skipper;
|
||||
ParseDispatcher const& dispatcher;
|
||||
|
||||
private:
|
||||
// silence MSVC warning C4512: assignment operator could not be generated
|
||||
complex_kwd_function& operator= (complex_kwd_function const&);
|
||||
};
|
||||
|
||||
|
||||
}}}}}
|
||||
|
||||
#endif
|
||||
+436
@@ -0,0 +1,436 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2011-2012 Thomas Bernard
|
||||
|
||||
Distributed under the 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
|
||||
#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/qi/domain.hpp>
|
||||
#include <boost/spirit/home/qi/detail/permute_function.hpp>
|
||||
#include <boost/spirit/home/qi/detail/attributes.hpp>
|
||||
#include <boost/spirit/home/support/detail/what_function.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/fusion/include/iter_fold.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/value_at.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/spirit/home/qi/string/symbols.hpp>
|
||||
#include <boost/spirit/home/qi/string/lit.hpp>
|
||||
#include <boost/spirit/home/qi/action/action.hpp>
|
||||
#include <boost/spirit/home/qi/directive/hold.hpp>
|
||||
#include <boost/mpl/count_if.hpp>
|
||||
#include <boost/mpl/range_c.hpp>
|
||||
#include <boost/mpl/copy.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/back_inserter.hpp>
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/fusion/include/zip_view.hpp>
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct use_operator<qi::domain, proto::tag::divides > // enables /
|
||||
: mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
|
||||
: mpl::true_ {};
|
||||
}}
|
||||
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
|
||||
// kwd directive parser type identification
|
||||
namespace detail
|
||||
{
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(complex_kwd_parser_id)
|
||||
|
||||
|
||||
}
|
||||
|
||||
// kwd directive type query
|
||||
template <typename T>
|
||||
struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
|
||||
|
||||
template <typename Subject, typename Action>
|
||||
struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
|
||||
|
||||
template <typename Subject>
|
||||
struct is_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_kwd_parser_id<Subject> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_complex_kwd_parser : detail::has_complex_kwd_parser_id<T> {};
|
||||
|
||||
template <typename Subject, typename Action>
|
||||
struct is_complex_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_complex_kwd_parser_id<Subject> {};
|
||||
|
||||
template <typename Subject>
|
||||
struct is_complex_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_complex_kwd_parser_id<Subject> {};
|
||||
|
||||
|
||||
// Keywords operator
|
||||
template <typename Elements, typename Modifiers>
|
||||
struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
|
||||
{
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
// Put all the element attributes in a tuple
|
||||
typedef typename traits::build_attribute_sequence<
|
||||
Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
|
||||
all_attributes;
|
||||
|
||||
// Now, build a fusion vector over the attributes. Note
|
||||
// that build_fusion_vector 1) removes all unused attributes
|
||||
// and 2) may return unused_type if all elements have
|
||||
// unused_type(s).
|
||||
typedef typename
|
||||
traits::build_fusion_vector<all_attributes>::type
|
||||
type;
|
||||
};
|
||||
|
||||
/// Make sure that all subjects are of the kwd type
|
||||
typedef typename mpl::count_if<
|
||||
Elements,
|
||||
mpl::not_<
|
||||
mpl::or_<
|
||||
is_kwd_parser<
|
||||
mpl::_1
|
||||
> ,
|
||||
is_complex_kwd_parser<
|
||||
mpl::_1
|
||||
>
|
||||
>
|
||||
>
|
||||
> non_kwd_subject_count;
|
||||
|
||||
/// If the assertion fails here then you probably forgot to wrap a
|
||||
/// subject of the / operator in a kwd directive
|
||||
BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// build_parser_tags
|
||||
//
|
||||
// Builds a boost::variant from an mpl::range_c in order to "mark" every
|
||||
// parser of the fusion sequence. The integer constant is used in the parser
|
||||
// dispatcher functor in order to use the parser corresponding to the recognised
|
||||
// keyword.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Sequence>
|
||||
struct build_parser_tags
|
||||
{
|
||||
// Get the sequence size
|
||||
typedef typename mpl::size< Sequence >::type sequence_size;
|
||||
|
||||
// Create an integer_c constant for every parser in the sequence
|
||||
typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
|
||||
|
||||
// Transform the range_c to an mpl vector in order to be able to transform it into a variant
|
||||
typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type type;
|
||||
|
||||
};
|
||||
// Build an index mpl vector
|
||||
typedef typename build_parser_tags< Elements >::type parser_index_vector;
|
||||
|
||||
template <typename idx>
|
||||
struct is_complex_kwd_parser_filter : is_complex_kwd_parser< typename mpl::at<Elements, idx>::type >
|
||||
{};
|
||||
|
||||
template <typename idx>
|
||||
struct is_kwd_parser_filter : is_kwd_parser< typename mpl::at<Elements, idx>::type >
|
||||
{};
|
||||
|
||||
// filter out the string kwd directives
|
||||
typedef typename mpl::filter_view< Elements, is_kwd_parser<mpl::_> >::type string_keywords;
|
||||
|
||||
typedef typename mpl::filter_view< parser_index_vector ,
|
||||
is_kwd_parser_filter< mpl::_ >
|
||||
>::type string_keyword_indexes;
|
||||
// filter out the complex keywords
|
||||
typedef typename mpl::filter_view< parser_index_vector ,
|
||||
is_complex_kwd_parser_filter< mpl::_ >
|
||||
>::type complex_keywords_indexes;
|
||||
|
||||
//typedef typename fusion::filter_view< Elements, is_complex_kwd_parser< mpl::_ > > complex_keywords_view;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
typename mpl::empty<complex_keywords_indexes>::type,
|
||||
detail::empty_keywords_list,
|
||||
detail::complex_keywords< complex_keywords_indexes >
|
||||
>::type complex_keywords_type;
|
||||
|
||||
// build a bool array and an integer array which will be used to
|
||||
// check that the repetition constraints of the kwd parsers are
|
||||
// met and bail out a soon as possible
|
||||
typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
|
||||
typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
typename mpl::empty<string_keyword_indexes>::type,
|
||||
detail::empty_keywords_list,
|
||||
detail::string_keywords<
|
||||
Elements,
|
||||
string_keywords,
|
||||
string_keyword_indexes,
|
||||
flags_type,
|
||||
Modifiers>
|
||||
>::type string_keywords_type;
|
||||
|
||||
keywords(Elements const& elements_) :
|
||||
elements(elements_)
|
||||
, string_keywords_inst(elements,flags_init)
|
||||
, complex_keywords_inst(elements,flags_init)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr_) const
|
||||
{
|
||||
// Select which parse function to call
|
||||
// We need to handle the case where kwd / ikwd directives have been mixed
|
||||
// This is where we decide which function should be called.
|
||||
return parse_impl(first, last, context, skipper, attr_,
|
||||
typename string_keywords_type::requires_one_pass()
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse_impl(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr_,mpl::true_ /* one pass */) const
|
||||
{
|
||||
|
||||
// wrap the attribute in a tuple if it is not a tuple
|
||||
typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
|
||||
|
||||
flags_type flags(flags_init);
|
||||
//flags.assign(false);
|
||||
|
||||
counters_type counters;
|
||||
counters.assign(0);
|
||||
|
||||
typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
|
||||
, flags_type, counters_type
|
||||
, typename traits::wrap_if_not_tuple<Attribute>::type
|
||||
, mpl::false_ > parser_visitor_type;
|
||||
|
||||
parser_visitor_type parse_visitor(elements, first, last
|
||||
, context, skipper, flags
|
||||
, counters, attr);
|
||||
|
||||
typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
|
||||
|
||||
complex_kwd_function_type
|
||||
complex_function(first,last,context,skipper,parse_visitor);
|
||||
|
||||
// We have a bool array 'flags' with one flag for each parser as well as a 'counter'
|
||||
// array.
|
||||
// The kwd directive sets and increments the counter when a successeful parse occurred
|
||||
// as well as the slot of the corresponding parser to true in the flags array as soon
|
||||
// the minimum repetition requirement is met and keeps that value to true as long as
|
||||
// the maximum repetition requirement is met.
|
||||
// The parsing takes place here in two steps:
|
||||
// 1) parse a keyword and fetch the parser index associated with that keyword
|
||||
// 2) call the associated parser and store the parsed value in the matching attribute.
|
||||
|
||||
while(true)
|
||||
{
|
||||
|
||||
spirit::qi::skip_over(first, last, skipper);
|
||||
Iterator save = first;
|
||||
if (string_keywords_inst.parse(first, last,parse_visitor,skipper))
|
||||
{
|
||||
save = first;
|
||||
}
|
||||
else {
|
||||
// restore the position to the last successful keyword parse
|
||||
first = save;
|
||||
if(!complex_keywords_inst.parse(complex_function))
|
||||
{
|
||||
first = save;
|
||||
// Check that we are leaving the keywords parser in a successfull state
|
||||
BOOST_FOREACH(bool &valid,flags)
|
||||
{
|
||||
if(!valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
save = first;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle the mixed kwd and ikwd case
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse_impl(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr_,mpl::false_ /* two passes */) const
|
||||
{
|
||||
|
||||
// wrap the attribute in a tuple if it is not a tuple
|
||||
typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
|
||||
|
||||
flags_type flags(flags_init);
|
||||
//flags.assign(false);
|
||||
|
||||
counters_type counters;
|
||||
counters.assign(0);
|
||||
|
||||
typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
|
||||
, flags_type, counters_type
|
||||
, typename traits::wrap_if_not_tuple<Attribute>::type
|
||||
, mpl::false_> parser_visitor_type;
|
||||
|
||||
typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
|
||||
, flags_type, counters_type
|
||||
, typename traits::wrap_if_not_tuple<Attribute>::type
|
||||
, mpl::true_> no_case_parser_visitor_type;
|
||||
|
||||
|
||||
parser_visitor_type parse_visitor(elements,first,last
|
||||
,context,skipper,flags,counters,attr);
|
||||
no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
|
||||
,context,skipper,flags,counters,attr);
|
||||
|
||||
typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
|
||||
|
||||
complex_kwd_function_type
|
||||
complex_function(first,last,context,skipper,parse_visitor);
|
||||
|
||||
|
||||
// We have a bool array 'flags' with one flag for each parser as well as a 'counter'
|
||||
// array.
|
||||
// The kwd directive sets and increments the counter when a successeful parse occurred
|
||||
// as well as the slot of the corresponding parser to true in the flags array as soon
|
||||
// the minimum repetition requirement is met and keeps that value to true as long as
|
||||
// the maximum repetition requirement is met.
|
||||
// The parsing takes place here in two steps:
|
||||
// 1) parse a keyword and fetch the parser index associated with that keyword
|
||||
// 2) call the associated parser and store the parsed value in the matching attribute.
|
||||
|
||||
while(true)
|
||||
{
|
||||
spirit::qi::skip_over(first, last, skipper);
|
||||
Iterator save = first;
|
||||
// String keywords pass
|
||||
if (string_keywords_inst.parse(first,last,parse_visitor,no_case_parse_visitor,skipper))
|
||||
{
|
||||
save = first;
|
||||
}
|
||||
else {
|
||||
first = save;
|
||||
|
||||
if(!complex_keywords_inst.parse(complex_function))
|
||||
{
|
||||
first = save;
|
||||
// Check that we are leaving the keywords parser in a successfull state
|
||||
BOOST_FOREACH(bool &valid,flags)
|
||||
{
|
||||
if(!valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
save = first;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& context) const
|
||||
{
|
||||
info result("keywords");
|
||||
fusion::for_each(elements,
|
||||
spirit::detail::what_function<Context>(result, context));
|
||||
return result;
|
||||
}
|
||||
flags_type flags_init;
|
||||
Elements elements;
|
||||
string_keywords_type string_keywords_inst;
|
||||
complex_keywords_type complex_keywords_inst;
|
||||
|
||||
};
|
||||
}}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace qi {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Elements, typename Modifiers >
|
||||
struct make_composite<proto::tag::divides, Elements, Modifiers >
|
||||
{
|
||||
typedef repository::qi::keywords<Elements,Modifiers> result_type;
|
||||
result_type operator()(Elements ref, unused_type) const
|
||||
{
|
||||
return result_type(ref);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
// We specialize this for keywords (see support/attributes.hpp).
|
||||
// For keywords, we only wrap the attribute in a tuple IFF
|
||||
// it is not already a fusion tuple.
|
||||
template <typename Elements, typename Modifiers,typename Attribute>
|
||||
struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
|
||||
: wrap_if_not_tuple<Attribute> {};
|
||||
|
||||
template <typename Elements, typename Modifiers>
|
||||
struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
|
||||
: nary_has_semantic_action<Elements> {};
|
||||
|
||||
template <typename Elements, typename Attribute, typename Context
|
||||
, typename Iterator, typename Modifiers>
|
||||
struct handles_container<repository::qi::keywords<Elements,Modifiers>, Attribute
|
||||
, Context, Iterator>
|
||||
: nary_handles_container<Elements, Attribute, Context, Iterator> {};
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_QI_PRIMITIVE_APR_28_2009_1258PM)
|
||||
#define SPIRIT_REPOSITORY_QI_PRIMITIVE_APR_28_2009_1258PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/repository/home/qi/primitive/advance.hpp>
|
||||
#include <boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp>
|
||||
#include <boost/spirit/repository/home/qi/primitive/iter_pos.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2011 Aaron Graham
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM
|
||||
|
||||
#include <boost/spirit/include/qi_parse.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// definition the place holder
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
BOOST_SPIRIT_TERMINAL_EX(advance);
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// implementation the enabler
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
template <typename A0>
|
||||
struct use_terminal<qi::domain
|
||||
, terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > >
|
||||
: mpl::or_<is_integral<A0>, is_enum<A0> >
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// implementation of the parser
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
template <typename Int>
|
||||
struct advance_parser
|
||||
: boost::spirit::qi::primitive_parser< advance_parser<Int> >
|
||||
{
|
||||
// Define the attribute type exposed by this parser component
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef boost::spirit::unused_type type;
|
||||
};
|
||||
|
||||
advance_parser(Int dist)
|
||||
: dist(dist)
|
||||
{}
|
||||
|
||||
// This function is called during the actual parsing process
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context&, Skipper&, Attribute&) const
|
||||
{
|
||||
// This series of checks is designed to fail parsing on negative
|
||||
// values, without generating a "expression always evaluates true"
|
||||
// warning on unsigned types.
|
||||
if (dist == Int(0)) return true;
|
||||
if (dist < Int(1)) return false;
|
||||
|
||||
typedef typename std::iterator_traits<Iterator>::iterator_category
|
||||
iterator_category;
|
||||
return advance(first, last, iterator_category());
|
||||
}
|
||||
|
||||
// This function is called during error handling to create
|
||||
// a human readable string for the error context.
|
||||
template <typename Context>
|
||||
boost::spirit::info what(Context&) const
|
||||
{
|
||||
return boost::spirit::info("advance");
|
||||
}
|
||||
|
||||
private:
|
||||
// this is the general implementation used by most iterator categories
|
||||
template <typename Iterator, typename IteratorCategory>
|
||||
bool advance(Iterator& first, Iterator const& last
|
||||
, IteratorCategory) const
|
||||
{
|
||||
Int n = dist;
|
||||
Iterator i = first;
|
||||
while (n)
|
||||
{
|
||||
if (i == last) return false;
|
||||
++i;
|
||||
--n;
|
||||
}
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is a specialization for random access iterators
|
||||
template <typename Iterator>
|
||||
bool advance(Iterator& first, Iterator const& last
|
||||
, std::random_access_iterator_tag) const
|
||||
{
|
||||
Iterator const it = first + dist;
|
||||
if (it > last) return false;
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
|
||||
Int const dist;
|
||||
};
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// instantiation of the parser
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
template <typename Modifiers, typename A0>
|
||||
struct make_primitive<
|
||||
terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> >
|
||||
, Modifiers>
|
||||
{
|
||||
typedef repository::qi::advance_parser<A0> result_type;
|
||||
|
||||
template <typename Terminal>
|
||||
result_type operator()(Terminal const& term, unused_type) const
|
||||
{
|
||||
return result_type(fusion::at_c<0>(term.args));
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_QI_FLUSH_MULTI_PASS_JUL_10_2009_0535PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_FLUSH_MULTI_PASS_JUL_10_2009_0535PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/qi/domain.hpp>
|
||||
#include <boost/spirit/home/qi/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/support/common_terminals.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/attributes.hpp>
|
||||
#include <boost/spirit/home/support/multi_pass.hpp>
|
||||
|
||||
#include <boost/spirit/repository/home/support/flush_multi_pass.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// enables flush_multi_pass
|
||||
template <>
|
||||
struct use_terminal<qi::domain, repository::tag::flush_multi_pass>
|
||||
: mpl::true_ {};
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
using repository::flush_multi_pass_type;
|
||||
using repository::flush_multi_pass;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// for a flush_multi_pass_parser generated parser
|
||||
struct flush_multi_pass_parser
|
||||
: spirit::qi::primitive_parser<flush_multi_pass_parser>
|
||||
{
|
||||
template <typename Context, typename Unused>
|
||||
struct attribute
|
||||
{
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& context, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
spirit::traits::clear_queue(first, traits::clear_mode::clear_always);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context const& ctx) const
|
||||
{
|
||||
return info("flush_multi_pass");
|
||||
}
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Modifiers>
|
||||
struct make_primitive<repository::tag::flush_multi_pass, Modifiers>
|
||||
{
|
||||
typedef repository::qi::flush_multi_pass_parser result_type;
|
||||
result_type operator()(unused_type, unused_type) const
|
||||
{
|
||||
return result_type();
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_QI_ITER_POS_NOV_20_2009_1245PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_QI_ITER_POS_NOV_20_2009_1245PM
|
||||
|
||||
#include <boost/spirit/include/qi_parse.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// definition the place holder
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
BOOST_SPIRIT_TERMINAL(iter_pos);
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// implementation the enabler
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
// We want custom_parser::iter_pos to be usable as a terminal only,
|
||||
// and only for parser expressions (qi::domain).
|
||||
template <>
|
||||
struct use_terminal<qi::domain, repository::qi::tag::iter_pos>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// implementation of the parser
|
||||
namespace boost { namespace spirit { namespace repository { namespace qi
|
||||
{
|
||||
struct iter_pos_parser
|
||||
: boost::spirit::qi::primitive_parser<iter_pos_parser>
|
||||
{
|
||||
// Define the attribute type exposed by this parser component
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
typedef Iterator type;
|
||||
};
|
||||
|
||||
// This function is called during the actual parsing process
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context&, Skipper const& skipper, Attribute& attr) const
|
||||
{
|
||||
boost::spirit::qi::skip_over(first, last, skipper);
|
||||
boost::spirit::traits::assign_to(first, attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function is called during error handling to create
|
||||
// a human readable string for the error context.
|
||||
template <typename Context>
|
||||
boost::spirit::info what(Context&) const
|
||||
{
|
||||
return boost::spirit::info("iter_pos");
|
||||
}
|
||||
};
|
||||
}}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// instantiation of the parser
|
||||
namespace boost { namespace spirit { namespace qi
|
||||
{
|
||||
// This is the factory function object invoked in order to create
|
||||
// an instance of our iter_pos_parser.
|
||||
template <typename Modifiers>
|
||||
struct make_primitive<repository::qi::tag::iter_pos, Modifiers>
|
||||
{
|
||||
typedef repository::qi::iter_pos_parser result_type;
|
||||
|
||||
result_type operator()(unused_type, unused_type) const
|
||||
{
|
||||
return result_type();
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_SUPPORT_CONFIX_APR_28_2009_0110PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_CONFIX_APR_28_2009_0110PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/terminal.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
// The confix extended terminal
|
||||
BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(( confix, confix_type ))
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_SUPPORT_DISTINCT_APR_28_2009_0110PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_DISTINCT_APR_28_2009_0110PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/terminal.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
// The distinct extended terminal
|
||||
BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(( distinct, distinct_type ))
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2001-2011 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_REPOSITORY_SUPPORT_FLUSH_MULTI_PASS_JUL_11_2009_0823PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_FLUSH_MULTI_PASS_JUL_11_2009_0823PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/terminal.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
// The flush_multi_pass extended terminal
|
||||
BOOST_SPIRIT_TERMINAL( flush_multi_pass )
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2001-2011 Thomas Bernard
|
||||
//
|
||||
// Distributed under the 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_REPOSITORY_SUPPORT_KWD_OCT_20_2010_0110PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_KWD_OCT_20_2010_0110PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/terminal.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
// The distinct extended terminal
|
||||
BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(( kwd, kwd_type )( ikwd, ikwd_type )(dkwd, dkwd_type)(idkwd, idkwd_type) )
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Copyright (c) 2011 Jamboree
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//////////////////////////////////////////////////////////////////////////////*/
|
||||
#ifndef BOOST_SPIRIT_REPOSITORY_SUPPORT_SEEK
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_SEEK
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/spirit/home/support/terminal.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
// The seek terminal
|
||||
BOOST_SPIRIT_DEFINE_TERMINALS_NAME(( seek, seek_type ))
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Francois Barel
|
||||
Copyright (c) 2001-2010 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_REPOSITORY_SUPPORT_SUBRULE_CONTEXT_AUGUST_12_2009_0539PM)
|
||||
#define BOOST_SPIRIT_REPOSITORY_SUPPORT_SUBRULE_CONTEXT_AUGUST_12_2009_0539PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/context.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// subrule_context: special context used with subrules, to pass around
|
||||
// the current set of subrule definitions (subrule_group)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Group, typename Attributes, typename Locals>
|
||||
struct subrule_context
|
||||
: context<Attributes, Locals>
|
||||
{
|
||||
typedef context<Attributes, Locals> base_type;
|
||||
typedef Group group_type;
|
||||
|
||||
subrule_context(
|
||||
Group const& group
|
||||
, typename Attributes::car_type attribute
|
||||
) : base_type(attribute), group(group)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Args, typename Context>
|
||||
subrule_context(
|
||||
Group const& group
|
||||
, typename Attributes::car_type attribute
|
||||
, Args const& args
|
||||
, Context& caller_context
|
||||
) : base_type(attribute, args, caller_context), group(group)
|
||||
{
|
||||
}
|
||||
|
||||
subrule_context(Group const& group, Attributes const& attributes)
|
||||
: base_type(attributes), group(group)
|
||||
{
|
||||
}
|
||||
|
||||
Group const& group;
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user