Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2011 Joel de Guzman Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ==============================================================================*/ Chris@16: #if !defined(BOOST_SPIRIT_LAZY_MARCH_27_2007_1002AM) Chris@16: #define BOOST_SPIRIT_LAZY_MARCH_27_2007_1002AM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Enablers Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct use_terminal > // enables phoenix actors Chris@16: : mpl::true_ {}; Chris@16: Chris@16: // forward declaration Chris@16: template Chris@16: struct lazy_terminal; Chris@16: }} Chris@16: Chris@16: namespace boost { namespace spirit { namespace qi Chris@16: { Chris@16: using spirit::lazy; Chris@16: typedef modify qi_modify; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: bool lazy_parse_impl(Parser const& p Chris@16: , Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper Chris@16: , Attribute& attr, mpl::false_) Chris@16: { Chris@16: return p.parse(first, last, context, skipper, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: bool lazy_parse_impl(Parser const& p Chris@16: , Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper Chris@16: , Attribute& /*attr*/, mpl::true_) Chris@16: { Chris@16: // If DeducedAuto is false (semantic actions is present), the Chris@16: // component's attribute is unused. Chris@16: return p.parse(first, last, context, skipper, unused); Chris@16: } Chris@16: Chris@16: template Chris@16: bool lazy_parse_impl_main(Parser const& p Chris@16: , Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper Chris@16: , Attribute& attr) Chris@16: { Chris@16: // If DeducedAuto is true (no semantic action), we pass the parser's Chris@16: // attribute on to the component. Chris@16: typedef typename traits::has_semantic_action::type auto_rule; Chris@16: return lazy_parse_impl(p, first, last, context, skipper, attr, auto_rule()); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: struct lazy_parser : parser > Chris@16: { Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef typename Chris@16: boost::result_of::type Chris@16: modifier; Chris@16: Chris@16: typedef typename Chris@16: remove_reference< Chris@16: typename boost::result_of::type Chris@16: >::type Chris@16: expr_type; Chris@16: Chris@16: // If you got an error_invalid_expression error message here, Chris@16: // then the expression (expr_type) is not a valid spirit qi Chris@16: // expression. Chris@16: BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type); Chris@16: Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: parser_type; Chris@16: Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: lazy_parser(Function const& function_, Modifiers const& modifiers_) Chris@16: : function(function_), modifiers(modifiers_) {} Chris@16: Chris@16: template Chris@16: bool parse(Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper Chris@16: , Attribute& attr) const Chris@16: { Chris@16: return detail::lazy_parse_impl_main( Chris@16: compile(function(unused, context) Chris@16: , qi_modify()(tag::lazy_eval(), modifiers)) Chris@16: , first, last, context, skipper, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("lazy" Chris@16: , compile(function(unused, context) Chris@16: , qi_modify()(tag::lazy_eval(), modifiers)) Chris@16: .what(context) Chris@16: ); Chris@16: } Chris@16: Chris@16: Function function; Chris@16: Modifiers modifiers; Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct lazy_directive Chris@16: : unary_parser > Chris@16: { Chris@16: typedef Subject subject_type; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef typename Chris@16: boost::result_of::type Chris@16: modifier; Chris@16: Chris@16: typedef typename Chris@16: remove_reference< Chris@16: typename boost::result_of::type Chris@16: >::type Chris@16: directive_expr_type; Chris@16: Chris@16: typedef typename Chris@16: proto::result_of::make_expr< Chris@16: proto::tag::subscript Chris@16: , directive_expr_type Chris@16: , Subject Chris@16: >::type Chris@16: expr_type; Chris@16: Chris@16: // If you got an error_invalid_expression error message here, Chris@16: // then the expression (expr_type) is not a valid spirit qi Chris@16: // expression. Chris@16: BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type); Chris@16: Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: parser_type; Chris@16: Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: lazy_directive( Chris@16: Function const& function_ Chris@16: , Subject const& subject_ Chris@16: , Modifiers const& modifiers_) Chris@16: : function(function_), subject(subject_), modifiers(modifiers_) {} Chris@16: Chris@16: template Chris@16: bool parse(Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper Chris@16: , Attribute& attr) const Chris@16: { Chris@16: return detail::lazy_parse_impl_main(compile( Chris@16: proto::make_expr( Chris@16: function(unused, context) Chris@16: , subject) Chris@16: , qi_modify()(tag::lazy_eval(), modifiers)) Chris@16: , first, last, context, skipper, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("lazy-directive" Chris@16: , compile( Chris@16: proto::make_expr( Chris@16: function(unused, context) Chris@16: , subject Chris@16: ), qi_modify()(tag::lazy_eval(), modifiers)) Chris@16: .what(context) Chris@16: ); Chris@16: } Chris@16: Chris@16: Function function; Chris@16: Subject subject; Chris@16: Modifiers modifiers; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Parser generators: make_xxx function (objects) Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct make_primitive, Modifiers> Chris@16: { Chris@16: typedef lazy_parser, Modifiers> result_type; Chris@16: result_type operator()(phoenix::actor const& f Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(f, modifiers); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_primitive, Modifiers> Chris@16: { Chris@16: typedef lazy_parser result_type; Chris@16: result_type operator()( Chris@16: lazy_terminal const& lt Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(lt.actor, modifiers); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_directive, Subject, Modifiers> Chris@16: { Chris@16: typedef lazy_directive result_type; Chris@16: result_type operator()( Chris@16: lazy_terminal const& lt Chris@16: , Subject const& subject, Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(lt.actor, subject, modifiers); Chris@16: } Chris@16: }; Chris@16: }}} Chris@16: Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct handles_container< Chris@16: qi::lazy_parser, Attribute, Context, Iterator> Chris@16: : handles_container< Chris@16: typename qi::lazy_parser::template Chris@16: attribute::parser_type Chris@16: , Attribute, Context, Iterator> Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct handles_container< Chris@16: qi::lazy_directive, Attribute Chris@16: , Context, Iterator> Chris@16: : handles_container< Chris@16: typename qi::lazy_directive::template Chris@16: attribute::parser_type Chris@16: , Attribute, Context, Iterator> Chris@16: {}; Chris@16: }}} Chris@16: Chris@16: #endif