123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- /*=============================================================================
- 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
- #include <boost/core/ignore_unused.hpp>
- #include <boost/spirit/home/x3/auxiliary/guard.hpp>
- #include <boost/spirit/home/x3/core/parser.hpp>
- #include <boost/spirit/home/x3/core/skip_over.hpp>
- #include <boost/spirit/home/x3/directive/expect.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
- #include <type_traits>
- namespace boost { namespace spirit { namespace x3
- {
- template <typename ID>
- struct identity;
- template <typename ID, typename Attribute = unused_type, bool force_attribute = false>
- struct rule;
- struct parse_pass_context_tag;
- namespace detail
- {
- template <typename ID>
- struct rule_id {};
- // 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 Iterator
- , typename Context, typename ActualAttribute>
- inline detail::default_parse_rule_result
- parse_rule(
- detail::rule_id<ID>
- , 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,
- decltype(void(
- std::declval<ID>().on_error(
- std::declval<Iterator&>()
- , std::declval<Iterator>()
- , std::declval<expectation_failure<Iterator>>()
- , std::declval<Context>()
- )
- ))
- >
- : 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,
- decltype(void(
- std::declval<ID>().on_success(
- std::declval<Iterator&>()
- , std::declval<Iterator&>()
- , std::declval<Attribute&>()
- , std::declval<Context>()
- )
- ))
- >
- : 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, bool skip_definition_injection = false>
- struct rule_parser
- {
- template <typename Iterator, typename Context, typename ActualAttribute>
- static bool call_on_success(
- Iterator& /* before */, Iterator& /* after */
- , 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& before, Iterator& after
- , Context const& context, ActualAttribute& attr
- , mpl::true_ /* Has on_success handler */)
- {
- x3::skip_over(before, after, context);
- bool pass = true;
- ID().on_success(
- before
- , after
- , 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(
- detail::rule_id<ID>{}, first, last
- , make_unique_context<ID>(rhs, context), std::declval<Attribute&>()))
- 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 start = first;
- bool r = rhs.parse(
- first
- , last
- , make_rule_context<ID>(rhs, context, std::conditional_t<skip_definition_injection, mpl::false_, is_default_parse_rule>())
- , rcontext
- , attr
- );
- if (r)
- {
- r = call_on_success(start, first, context, attr
- , has_on_success<ID, Iterator, Context, ActualAttribute>());
- }
- 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)
- {
- boost::ignore_unused(rule_name);
- // do down-stream transformation, provides attribute for
- // rhs parser
- typedef traits::transform_attribute<
- ActualAttribute, Attribute, parser_id>
- transform;
- typedef typename transform::type transform_attr;
- transform_attr attr_ = transform::pre(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
- // transform::post when, for example,
- // ActualAttribute is a recursive variant).
- #if defined(BOOST_SPIRIT_X3_DEBUG)
- context_debug<Iterator, transform_attr>
- 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
- transform::post(attr, std::forward<transform_attr>(attr_));
- }
- return ok_parse;
- }
- };
- }}}}
- #endif
|