summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/nonterminal/detail/rule.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/spirit/home/x3/nonterminal/detail/rule.hpp')
-rw-r--r--boost/spirit/home/x3/nonterminal/detail/rule.hpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/nonterminal/detail/rule.hpp b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
new file mode 100644
index 0000000000..54e2eef234
--- /dev/null
+++ b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
@@ -0,0 +1,385 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 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_X3_DETAIL_RULE_JAN_08_2012_0326PM)
+#define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/x3/core/parser.hpp>
+#include <boost/spirit/home/x3/support/traits/make_attribute.hpp>
+#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
+#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
+#include <boost/utility/addressof.hpp>
+
+#if defined(BOOST_SPIRIT_X3_DEBUG)
+#include <boost/spirit/home/x3/nonterminal/simple_trace.hpp>
+#endif
+
+namespace boost { namespace spirit { namespace x3
+{
+ template <typename ID>
+ struct identity;
+
+ template <typename ID, typename Attribute = unused_type>
+ struct rule;
+
+ struct parse_pass_context_tag;
+
+ namespace detail
+ {
+ // we use this so we can detect if the default parse_rule
+ // is the being called.
+ struct default_parse_rule_result
+ {
+ default_parse_rule_result(bool r)
+ : r(r) {}
+ operator bool() const { return r; }
+ bool r;
+ };
+ }
+
+ // default parse_rule implementation
+ template <typename ID, typename Attribute, typename Iterator
+ , typename Context, typename ActualAttribute>
+ inline detail::default_parse_rule_result
+ parse_rule(
+ rule<ID, Attribute> rule_
+ , Iterator& first, Iterator const& last
+ , Context const& context, ActualAttribute& attr);
+}}}
+
+namespace boost { namespace spirit { namespace x3 { namespace detail
+{
+#if defined(BOOST_SPIRIT_X3_DEBUG)
+ template <typename Iterator, typename Attribute>
+ struct context_debug
+ {
+ context_debug(
+ char const* rule_name
+ , Iterator const& first, Iterator const& last
+ , Attribute const& attr
+ , bool const& ok_parse //was parse successful?
+ )
+ : ok_parse(ok_parse), rule_name(rule_name)
+ , first(first), last(last)
+ , attr(attr)
+ , f(detail::get_simple_trace())
+ {
+ f(first, last, attr, pre_parse, rule_name);
+ }
+
+ ~context_debug()
+ {
+ auto status = ok_parse ? successful_parse : failed_parse ;
+ f(first, last, attr, status, rule_name);
+ }
+
+ bool const& ok_parse;
+ char const* rule_name;
+ Iterator const& first;
+ Iterator const& last;
+ Attribute const& attr;
+ detail::simple_trace_type& f;
+ };
+#endif
+
+ template <typename ID, typename Iterator, typename Context, typename Enable = void>
+ struct has_on_error : mpl::false_ {};
+
+ template <typename ID, typename Iterator, typename Context>
+ struct has_on_error<ID, Iterator, Context,
+ typename disable_if_substitution_failure<
+ decltype(
+ std::declval<ID>().on_error(
+ std::declval<Iterator&>()
+ , std::declval<Iterator>()
+ , std::declval<expectation_failure<Iterator>>()
+ , std::declval<Context>()
+ )
+ )>::type
+ >
+ : mpl::true_
+ {};
+
+ template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void>
+ struct has_on_success : mpl::false_ {};
+
+ template <typename ID, typename Iterator, typename Attribute, typename Context>
+ struct has_on_success<ID, Iterator, Context, Attribute,
+ typename disable_if_substitution_failure<
+ decltype(
+ std::declval<ID>().on_success(
+ std::declval<Iterator&>()
+ , std::declval<Iterator>()
+ , std::declval<Attribute&>()
+ , std::declval<Context>()
+ )
+ )>::type
+ >
+ : mpl::true_
+ {};
+
+ template <typename ID>
+ struct make_id
+ {
+ typedef identity<ID> type;
+ };
+
+ template <typename ID>
+ struct make_id<identity<ID>>
+ {
+ typedef identity<ID> type;
+ };
+
+ template <typename ID, typename RHS, typename Context>
+ Context const&
+ make_rule_context(RHS const& rhs, Context const& context
+ , mpl::false_ /* is_default_parse_rule */)
+ {
+ return context;
+ }
+
+ template <typename ID, typename RHS, typename Context>
+ auto make_rule_context(RHS const& rhs, Context const& context
+ , mpl::true_ /* is_default_parse_rule */ )
+ {
+ return make_unique_context<ID>(rhs, context);
+ }
+
+ template <typename Attribute, typename ID>
+ struct rule_parser
+ {
+ template <typename Iterator, typename Context, typename ActualAttribute>
+ static bool call_on_success(
+ Iterator& first, Iterator const& last
+ , Context const& context, ActualAttribute& attr
+ , mpl::false_ /* No on_success handler */ )
+ {
+ return true;
+ }
+
+ template <typename Iterator, typename Context, typename ActualAttribute>
+ static bool call_on_success(
+ Iterator& first, Iterator const& last
+ , Context const& context, ActualAttribute& attr
+ , mpl::true_ /* Has on_success handler */)
+ {
+ bool pass = true;
+ ID().on_success(
+ first
+ , last
+ , attr
+ , make_context<parse_pass_context_tag>(pass, context)
+ );
+ return pass;
+ }
+
+ template <typename RHS, typename Iterator, typename Context
+ , typename RContext, typename ActualAttribute>
+ static bool parse_rhs_main(
+ RHS const& rhs
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, ActualAttribute& attr
+ , mpl::false_)
+ {
+ // see if the user has a BOOST_SPIRIT_DEFINE for this rule
+ typedef
+ decltype(parse_rule(
+ rule<ID, Attribute>(), first, last
+ , make_unique_context<ID>(rhs, context), attr))
+ parse_rule_result;
+
+ // If there is no BOOST_SPIRIT_DEFINE for this rule,
+ // we'll make a context for this rule tagged by its ID
+ // so we can extract the rule later on in the default
+ // (generic) parse_rule function.
+ typedef
+ is_same<parse_rule_result, default_parse_rule_result>
+ is_default_parse_rule;
+
+ Iterator i = first;
+ bool r = rhs.parse(
+ i
+ , last
+ , make_rule_context<ID>(rhs, context, is_default_parse_rule())
+ , rcontext
+ , attr
+ );
+
+ if (r)
+ {
+ auto first_ = first;
+ x3::skip_over(first_, last, context);
+ r = call_on_success(first_, i, context, attr
+ , has_on_success<ID, Iterator, Context, ActualAttribute>());
+ }
+
+ if (r)
+ first = i;
+ return r;
+ }
+
+ template <typename RHS, typename Iterator, typename Context
+ , typename RContext, typename ActualAttribute>
+ static bool parse_rhs_main(
+ RHS const& rhs
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, ActualAttribute& attr
+ , mpl::true_ /* on_error is found */)
+ {
+ for (;;)
+ {
+ try
+ {
+ return parse_rhs_main(
+ rhs, first, last, context, rcontext, attr, mpl::false_());
+ }
+ catch (expectation_failure<Iterator> const& x)
+ {
+ switch (ID().on_error(first, last, x, context))
+ {
+ case error_handler_result::fail:
+ return false;
+ case error_handler_result::retry:
+ continue;
+ case error_handler_result::accept:
+ return true;
+ case error_handler_result::rethrow:
+ throw;
+ }
+ }
+ }
+ }
+
+ template <typename RHS, typename Iterator
+ , typename Context, typename RContext, typename ActualAttribute>
+ static bool parse_rhs_main(
+ RHS const& rhs
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, ActualAttribute& attr)
+ {
+ return parse_rhs_main(
+ rhs, first, last, context, rcontext, attr
+ , has_on_error<ID, Iterator, Context>()
+ );
+ }
+
+ template <typename RHS, typename Iterator
+ , typename Context, typename RContext, typename ActualAttribute>
+ static bool parse_rhs(
+ RHS const& rhs
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, ActualAttribute& attr
+ , mpl::false_)
+ {
+ return parse_rhs_main(rhs, first, last, context, rcontext, attr);
+ }
+
+ template <typename RHS, typename Iterator
+ , typename Context, typename RContext, typename ActualAttribute>
+ static bool parse_rhs(
+ RHS const& rhs
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, ActualAttribute& attr
+ , mpl::true_)
+ {
+ return parse_rhs_main(rhs, first, last, context, rcontext, unused);
+ }
+
+ template <typename RHS, typename Iterator, typename Context
+ , typename ActualAttribute, typename ExplicitAttrPropagation>
+ static bool call_rule_definition(
+ RHS const& rhs
+ , char const* rule_name
+ , Iterator& first, Iterator const& last
+ , Context const& context, ActualAttribute& attr
+ , ExplicitAttrPropagation)
+ {
+ typedef traits::make_attribute<Attribute, ActualAttribute> make_attribute;
+
+ // do down-stream transformation, provides attribute for
+ // rhs parser
+ typedef traits::transform_attribute<
+ typename make_attribute::type, Attribute, parser_id>
+ transform;
+
+ typedef typename make_attribute::value_type value_type;
+ typedef typename transform::type transform_attr;
+ value_type made_attr = make_attribute::call(attr);
+ transform_attr attr_ = transform::pre(made_attr);
+
+ bool ok_parse
+ //Creates a place to hold the result of parse_rhs
+ //called inside the following scope.
+ ;
+ {
+ //Create a scope to cause the dbg variable below (within
+ //the #if...#endif) to call it's DTOR before any
+ //modifications are made to the attribute, attr_ passed
+ //to parse_rhs (such as might be done in
+ //traits::post_transform when, for example,
+ //ActualAttribute is a recursive variant).
+#if defined(BOOST_SPIRIT_X3_DEBUG)
+ context_debug<Iterator, typename make_attribute::value_type>
+ dbg(rule_name, first, last, attr_, ok_parse);
+#endif
+ ok_parse=parse_rhs(rhs, first, last, context, attr_, attr_
+ , mpl::bool_
+ < ( RHS::has_action
+ && !ExplicitAttrPropagation::value
+ )
+ >()
+ );
+ }
+ if(ok_parse)
+ {
+ // do up-stream transformation, this integrates the results
+ // back into the original attribute value, if appropriate
+ traits::post_transform(attr, attr_);
+ }
+ return ok_parse;
+ }
+
+// template <typename RuleDef, typename Iterator, typename Context
+// , typename ActualAttribute, typename AttributeContext>
+// static bool call_from_rule(
+// RuleDef const& rule_def
+// , char const* rule_name
+// , Iterator& first, Iterator const& last
+// , Context const& context, ActualAttribute& attr, AttributeContext& attr_ctx)
+// {
+// // This is called when a rule-body has already been established.
+// // The rule body is already established by the rule_definition class,
+// // we will not do it again. We'll simply call the RHS by calling
+// // call_rule_definition.
+//
+// return call_rule_definition(
+// rule_def.rhs, rule_name, first, last
+// , context, attr, attr_ctx.attr_ptr
+// , mpl::bool_<(RuleDef::explicit_attribute_propagation)>());
+// }
+//
+// template <typename RuleDef, typename Iterator, typename Context
+// , typename ActualAttribute>
+// static bool call_from_rule(
+// RuleDef const& rule_def
+// , char const* rule_name
+// , Iterator& first, Iterator const& last
+// , Context const& context, ActualAttribute& attr, unused_type)
+// {
+// // This is called when a rule-body has *not yet* been established.
+// // The rule body is established by the rule_definition class, so
+// // we call it to parse and establish the rule-body.
+//
+// return rule_def.parse(first, last, context, unused, attr); // $$$ fix unused param $$$
+// }
+ };
+}}}}
+
+#endif