diff options
Diffstat (limited to 'boost/spirit/home/x3/nonterminal/detail/rule.hpp')
-rw-r--r-- | boost/spirit/home/x3/nonterminal/detail/rule.hpp | 385 |
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 |