Chris@16: /*============================================================================== Chris@16: Copyright (c) 2006 Tobias Schwinger Chris@16: http://spirit.sourceforge.net/ 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: // The comment below contains a unnamed 'namespace {', which is flagged by the Chris@16: // Boost inspect tool as a violation of common C++ programming rules. Since it's Chris@16: // in a comment, well, we switch it off :-P Chris@16: // boostinspect:nounnamed Chris@16: Chris@16: // Chris@16: // About: Chris@16: // ===== Chris@16: // Chris@16: // Using a typeof operator or Boost.Typeof to automatically set the type of Chris@16: // variables (as done in the Spirit example demonstrating typeof) is by far not Chris@101: // all we can do to tighten up our grammars as there are some significant Chris@16: // drawbacks of this approach: Chris@16: // - the types complexity scales with the complexity of the grammar (sooner or Chris@16: // later hitting the limits of the compiler), Chris@16: // - recursive grammars are not possible, and Chris@16: // - all parser objects are embedded by value. Chris@16: // Chris@16: // The Spirit documentation therefore recommends creating custom parser classes Chris@16: // (derived from the a sub_grammar template): Chris@16: // Chris@16: // http://www.boost.org/libs/spirit/doc/techniques.html#no_rules Chris@16: // http://www.boost.org/libs/spirit/doc/techniques.html#typeof Chris@16: // Chris@16: // In practice manually applying this technique leads to rather lengthy code and Chris@16: // overthis requires the user to have a solid understanding of Spirit details. Chris@16: // Chris@101: // Here is a generalized, macro-based approach to easily create typeof-based Chris@16: // grammars that can be recursive and arbitrarily complex. Chris@16: // Chris@16: // Chris@16: // Quick manual: Chris@16: // ============ Chris@101: // Chris@16: // 1. Setup Chris@101: // Chris@101: // Before the rule parser macro (the protagonist of the facility) can be used Chris@101: // the user must define the macro BOOST_SPIRIT__NAMESPACE (note the double Chris@16: // underscore characeter) and setup a registration group for Boost.Typeof. Chris@101: // Chris@16: // Examples: Chris@101: // Chris@16: // // should come after regular #includeS Chris@16: // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@101: // Chris@16: // // [...] Chris@101: // Chris@16: // #define BOOST_SPIRIT__NAMESPACE (2,(my_project, my_module)) Chris@16: // // | | +- outer +- inner Chris@16: // // ! space ! -+ | namespace namespace Chris@16: // // | Chris@16: // // +--- number of nested namespaces Chris@101: // Chris@16: // namespace my_project { namespace my_module { Chris@101: // Chris@16: // // [...] Chris@101: // Chris@16: // --- Chris@101: // Chris@16: // // should come after regular #includeS Chris@16: // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@101: // Chris@16: // // [...] Chris@101: // Chris@16: // #define BOOST_SPIRIT__NAMESPACE (2,(my_project, (anonymous) )) Chris@101: // Chris@16: // namespace my_project { namespace { Chris@101: // Chris@16: // // [...] Chris@101: // Chris@16: // --- Chris@101: // Chris@16: // // should come after regular #includeS Chris@16: // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@101: // Chris@16: // // [...] Chris@101: // Chris@101: // Chris@16: // #define BOOST_SPIRIT__NAMESPACE - Chris@16: // // we're working at root namespace Chris@101: // Chris@101: // Chris@16: // Why do I have to do this? Chris@101: // Chris@16: // Boost.Typeof needs to assign a unique ID for each registration. This ID is Chris@101: // created composed of the line number and the registration group. The Chris@16: // facility performs Typeof registration and thus requires the source file to Chris@16: // have its own registration group. Further Boost.Typeof requires registration Chris@16: // to happen at root namespace so we have to close and reopen the namespace Chris@16: // we're in. Chris@16: // Chris@101: // Chris@16: // 2. The rule parser macro Chris@101: // Chris@16: // A simple rule parser definition looks like that: Chris@101: // Chris@16: // // we're at namespace scope here Chris@101: // Chris@16: // // Skip parser for C/C++ comments and whitespace Chris@101: // BOOST_SPIRIT_RULE_PARSER(skipper, Chris@101: // -,-,-, Chris@101: // Chris@101: // +( confix_p("//",*anychar_p,eol_p) Chris@16: // | confix_p("/*",*anychar_p,"*/") Chris@101: // | space_p Chris@16: // ) Chris@16: // ) Chris@101: // Chris@16: // Now we can use 'skipper' in other Spirit expressions. Chris@101: // Chris@101: // The code above creates a parser (template) class 'skpper_t' and (in this Chris@101: // case, because there are no parameters) a static const instance 'skipper' of Chris@16: // that class. The class is automatically registered with Boost.Typeof. The type Chris@16: // name our parser is skipper_t here. Chris@101: // Chris@101: // Chris@16: // 2.1. Parametrized rule parsers Chris@101: // Chris@16: // Rule parser definitions can have parameters. Chris@101: // Chris@16: // Parameters are passed to the BOOST_SPIRIT_RULE_PARSER macro as its second Chris@101: // argument (just pass '-' if there are no parameters) with the following Chris@16: // format: Chris@101: // Chris@16: // (N,( param1,param2, / ... / paramN )) Chris@16: // +-- number of parameters Chris@101: // Chris@16: // Example of a whole rule parser: Chris@101: // Chris@16: // BOOST_SPIRIT_RULE_PARSER(new_name, Chris@16: // (1,( symbol_table )),-,-, Chris@101: // Chris@16: // lexeme_d[ (alpha_p >> *alnum_p)[ symbol_table.add ] ] Chris@16: // ) Chris@101: // Chris@16: // The expression 'new_name(my_symbols)' parses a string literal and adds it to Chris@16: // the symbol table 'my_symbols'. Chris@101: // Chris@16: // The rule parser macro creates a function template as called 'new_name' that Chris@16: // takes one parameter of deduced reference type and returns a specialization of Chris@16: // 'new_name_t' in this case. Chris@101: // Chris@101: // Since parsers that require to be fast and lightweight often also require to Chris@101: // be reentrant, it's quite common to pass in some semantic controller (the Chris@16: // symbol table in the example above). Chris@101: // However, parameters are templated so they can be anything (including parsers Chris@16: // of course) so refactoring tasks can be abstracted with rule parsers as well. Chris@101: // Chris@16: // BOOST_SPIRIT_RULE_PARSER(enumeration_parser, Chris@16: // (2,( element_parser, delimiter_parser )),-,-, Chris@101: // Chris@16: // element_parser >> *(delimiter_parser >> element_parser) Chris@101: // ) Chris@101: // Chris@101: // The expression 'enumeration_parser(int_p[ some_action ], ',')' creates a Chris@16: // parser for a comma-separated list of integers. Chris@101: // Chris@101: // Chris@16: // 2.2. Rule parsrs and semantic actions Chris@101: // Chris@16: // While semantic actions can be globally attached to a rule parser or passed Chris@101: // to a parametrized rule parser as (part of) an argument, even more control is Chris@16: // possible by using action placeholders. E.g: Chris@101: // Chris@16: // BOOST_SPIRIT_ACTION_PLACEHOLDER(int_action) Chris@101: // Chris@16: // BOOST_SPIRIT_RULE_PARSER(int_list, Chris@16: // -,(1,( int_action )),-, Chris@101: // Chris@16: // int_p[ int_action ] >> *(',' >> int_p[ int_action ]) Chris@16: // ) Chris@101: // Chris@101: // The expression 'int_list[ my_action ]' parses a comma separated list of Chris@16: // integers and calls 'my_action' for every integer parsed therein. Chris@101: // Chris@101: // Of course multiple actions can be attached to one placeholder as usual (in Chris@16: // this case 'int_list[ my_action1 ][ my_action2 ] would call two actions). Chris@101: // Chris@16: // Further there can be multiple action placeholders for a single rule parser: Chris@101: // Chris@16: // BOOST_SPIRIT_ACTION_PLACEHOLDER(feed_int) Chris@16: // BOOST_SPIRIT_ACTION_PLACEHOLDER(next_int) Chris@101: // Chris@16: // BOOST_SPIRIT_RULE_PARSER(int_list, Chris@16: // -,(2,( feed_int, next_int )),-, Chris@101: // Chris@16: // int_p[ feed_int ] >> *(',' >> int_p[ next_int ][ feed_int ]) Chris@16: // ) Chris@101: // Chris@16: // The expression 'int_list[ (feed_int = my_action1), (next_int = my_action2) ]' Chris@101: // creates a parser for a comma separated list of integers with the actions Chris@16: // attached appropriately. Chris@101: // Chris@16: // int_list[ feed_int = my_action1,my_action2, next_int = my_action3 ] Chris@101: // Chris@101: // works too (in this case the action placeholder 'feed_int' has two actions Chris@16: // attached to it). Chris@101: // Chris@101: // You can both override and append actions associated with an action Chris@16: // placeholder: Chris@101: // Chris@16: // var = int_list[ feed_int = my_action1, next_int = my_action2 ] Chris@101: // Chris@16: // // [...] Chris@101: // Chris@101: // ... var[ feed_int = another_action ] Chris@16: // // 'another_action' overrides the actions previously attached to 'feed_int' Chris@101: // Chris@16: // ... var[ next_int += another_action ] Chris@101: // // 'another_action' is appended to the list of actions attached to Chris@16: // // 'next_int' Chris@101: // Chris@16: // Action placeholders are not entirely for free -- they add to the size and the Chris@101: // initialization time of the rule parser. However, the impact on an already Chris@16: // initialized rule parser instance should be quite small. Chris@101: // Chris@101: // Chris@16: // 2.3. Member variables Chris@101: // Chris@101: // You can add member variables to the rule parser class using the third Chris@16: // parameter of the rule parser macro: Chris@101: // Chris@16: // BOOST_SPIRIT_RULE_PARSER( calc, Chris@16: // -, Chris@16: // -, Chris@16: // (3,( ((subrule<0>),expression,()), Chris@16: // ((subrule<1>),term,()), Chris@16: // ((subrule<2>),factor,() )) ), Chris@101: // Chris@16: // // [...] Chris@101: // Chris@16: // adds three subrules to the rule parser. Chris@16: // Each parameter must have the following type to allow commas to be handled Chris@16: // safely from within the preprocessing code: Chris@101: // Chris@16: // ((type)),name,(constructor argument(s))) Chris@101: // Chris@16: // Chris@16: // 2.4. The opaque rule parser Chris@16: // Chris@101: // Rule parsers usually are templates. Building large grammars pushes the Chris@101: // compiler really hard (and eventually to its limits) because of the Chris@16: // metafunction complexity involved. Chris@101: // If a rule parser without parameters and action placeholders is defined, a Chris@16: // non-template class is created. Non-templated rule parsers can also be created Chris@101: // explicitly by using BOOST_SPIRIT_OPAQUE_RULE_PARSER. Chris@16: // Opaque rule parsers can have parameters and member variables (note: no action Chris@101: // placeholders are possible). The parameters of an opaque rule parsers are Chris@16: // strictly typed, e.g: Chris@16: // Chris@16: // BOOST_SPIRIT_OPAQUE_RULE_PARSER(new_identifier, Chris@16: // (1,( ((my_symbol_table_t &),symbol_table) )) Chris@16: // ,-, Chris@16: // (alpha_p >> *alnum_p) [ symbol_table.add ] Chris@101: // ) Chris@16: // Chris@101: // Note it's also possible to have opaque rule parsers accept parameters of Chris@16: // non-const reference types which is not possible with regular rule parsers. Chris@16: // Chris@16: // Chris@16: // 3. Utilities for by-reference embedding Chris@101: // Chris@101: // When using parsers mutiple times or recursively it can be helpful to embed Chris@16: // them by-reference into the final parser expression. Chris@16: // For this purpose the library provides a wrapper template 'parser_reference'. Chris@16: // There is also a function template to create a wrapped parser which can deduce Chris@16: // the parser's type from its argument. Chris@16: // Chris@16: // --- --- - - --- - - --- - - - - --- - - - - - - - - - - - - - - - - - - - - - Chris@16: #if !defined(BOOST_SPIRIT_UTILITY_RULE_PARSER_HPP_INCLUDED) Chris@16: # define BOOST_SPIRIT_UTILITY_RULE_PARSER_HPP_INCLUDED Chris@16: //============================================================================== Chris@16: // Dependencies Chris@16: //============================================================================== Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include 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: # 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: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: //============================================================================== Chris@16: // Interface Chris@16: //============================================================================== Chris@16: // Creates a rule parser. Use at namespace scope. Chris@16: # define BOOST_SPIRIT_RULE_PARSER(name,params,actions,members,rule) \ Chris@16: BOOST_SPIRIT_RP_IMPL_I(name,params,actions,members,rule) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // Creates a non-templated rule parser. Use at namespace scope. Chris@16: # define BOOST_SPIRIT_OPAQUE_RULE_PARSER(name,params,members,rule) \ Chris@16: BOOST_SPIRIT_RP_OPAQUE_IMPL_I(name,params,members,rule) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // Defines an action placeholder. Use at namespace scope. Chris@16: # define BOOST_SPIRIT_ACTION_PLACEHOLDER(name) \ Chris@16: BOOST_SPIRIT_RP_AP_IMPL(name,::BOOST_SPIRIT_CLASSIC_NS::type_of) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // Utilities to embed parsers by reference. Chris@16: namespace boost Chris@16: { Chris@16: namespace spirit Chris@16: { Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN Chris@16: Chris@16: template class parser_reference; Chris@16: template parser_reference

embed_by_reference(parser

const &); Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_END Chris@16: } Chris@16: } Chris@16: //============================================================================== Chris@16: // Implementation Chris@16: //============================================================================== Chris@16: #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_REGISTER_TEMPLATE Chris@16: // Chris@101: // Boost.Typeof registration from within BOOST_SPIRIT__NAMESPACE Chris@16: # define BOOST_SPIRIT_RP_REGISTER_TEMPLATE(name,params) \ Chris@16: BOOST_SPIRIT_RP_EMIT(NS_CLOSE,BOOST_SPIRIT__NAMESPACE,-) \ Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE( \ Chris@16: BOOST_SPIRIT_RP_EMIT(NS_QUALIFY,BOOST_SPIRIT__NAMESPACE,-) name, \ Chris@16: params) \ Chris@101: BOOST_SPIRIT_RP_EMIT(NS_OPEN,BOOST_SPIRIT__NAMESPACE,-) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_REGISTER_TYPE Chris@16: // Chris@101: // Boost.Typeof registration from within BOOST_SPIRIT__NAMESPACE Chris@16: # define BOOST_SPIRIT_RP_REGISTER_TYPE(name) \ Chris@16: BOOST_SPIRIT_RP_EMIT(NS_CLOSE,BOOST_SPIRIT__NAMESPACE,-) \ Chris@16: BOOST_TYPEOF_REGISTER_TYPE( \ Chris@16: BOOST_SPIRIT_RP_EMIT(NS_QUALIFY,BOOST_SPIRIT__NAMESPACE,-) name ) \ Chris@101: BOOST_SPIRIT_RP_EMIT(NS_OPEN,BOOST_SPIRIT__NAMESPACE,-) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_AP_IMPL Chris@16: // Chris@16: // The action placeholder definition Chris@16: # define BOOST_SPIRIT_RP_AP_IMPL(name,ns) \ Chris@16: namespace __action_placeholder \ Chris@16: { \ Chris@16: struct name \ Chris@16: { \ Chris@16: template \ Chris@16: ns :: action_chain< name, ns :: replace, Action> \ Chris@16: operator=(Action const & __a) const \ Chris@16: { return ns :: action_chain< name, ns :: replace, Action>(__a); } \ Chris@16: \ Chris@16: template \ Chris@16: ns :: action_chain< name, ns :: append, Action> \ Chris@16: operator+=(Action const & __a) const \ Chris@16: { return ns :: action_chain< name, ns :: append, Action> (__a); } \ Chris@16: }; \ Chris@16: } \ Chris@101: __action_placeholder:: name const name = __action_placeholder:: name (); Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_IMPL_I Chris@16: // Chris@16: // Does some precalculation so RP_IMPL_II can look cleaner Chris@16: # define BOOST_SPIRIT_RP_IMPL_I(name,pars,acts,mbrs,expr) \ Chris@16: BOOST_SPIRIT_RP_IMPL_II(name, name ## _t , \ Chris@16: pars, BOOST_SPIRIT_RP_ARRAY_SIZE(pars), \ Chris@16: acts, BOOST_SPIRIT_RP_ARRAY_SIZE(acts), \ Chris@16: mbrs, BOOST_SPIRIT_RP_ARRAY_SIZE(mbrs), expr) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_IMPL_II Chris@16: # define BOOST_SPIRIT_RP_IMPL_II(name,name_t,pars,np,acts,na,mbrs,nm,x) \ Chris@16: BOOST_PP_IIF(BOOST_PP_OR(np,na),BOOST_SPIRIT_RP_IMPL_III, \ Chris@16: BOOST_SPIRIT_RP_OPAQUE_IMPL_II) \ Chris@16: (name,name_t,pars,np,acts,na,mbrs,nm,x) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_IMPL_III Chris@16: // Chris@16: // The rule parser definition Chris@16: # define BOOST_SPIRIT_RP_IMPL_III(name,name_t,pars,np,acts,na,mbrs,nm,x) \ Chris@16: \ Chris@16: template< BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,typename __,1) > \ Chris@16: class name_t \ Chris@101: : public ::BOOST_SPIRIT_CLASSIC_NS::parser< name_t \ Chris@16: < BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,__,0) > > \ Chris@16: { \ Chris@16: class __rule \ Chris@16: { \ Chris@16: BOOST_SPIRIT_RP_EMIT(PM_STATIC,pars,__T) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_STATIC,acts,-) \ Chris@16: BOOST_SPIRIT_RP_EMIT(MV_STATIC,mbrs,BOOST_PP_IDENTITY(typename)) \ Chris@16: public: \ Chris@16: BOOST_TYPEOF_NESTED_TYPEDEF_TPL(__expr, \ Chris@101: ::BOOST_SPIRIT_CLASSIC_NS::type_of::depend_on_type<__Dummy>(x) ) \ Chris@16: }; \ Chris@16: \ Chris@16: public: \ Chris@16: \ Chris@16: typedef name_t self_t; \ Chris@16: typedef typename __rule::__expr::type::parser_category_t \ Chris@16: parser_category_t; \ Chris@16: \ Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_NOR(np,na),typedef self_t const & embed_t;) \ Chris@16: \ Chris@16: protected: \ Chris@16: \ Chris@16: BOOST_SPIRIT_RP_EMIT(MV_NONSTATIC,mbrs,BOOST_PP_IDENTITY(typename)) \ Chris@16: BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_AP_EXTRA_MBRS,2)(np,na) \ Chris@16: \ Chris@16: typename __rule::__expr::type::embed_t __parser; \ Chris@16: \ Chris@16: public: \ Chris@16: \ Chris@16: explicit name_t ( BOOST_SPIRIT_RP_CTOR(PARAMS,pars,np,acts) ) \ Chris@16: : BOOST_SPIRIT_RP_EMIT(MV_CTOR_INIT_LIST,mbrs,-) \ Chris@16: BOOST_PP_COMMA_IF(nm) \ Chris@16: BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_CTOR_COMMA,4)(INIT_LIST,pars,np,acts)\ Chris@16: __parser(x) \ Chris@16: { } \ Chris@16: \ Chris@16: name_t( name_t const & that) \ Chris@16: : BOOST_SPIRIT_RP_EMIT(MV_CTOR_COPY_INIT_LIST,mbrs,that) \ Chris@16: BOOST_PP_COMMA_IF(nm) \ Chris@16: BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_CTOR_COMMA,4) \ Chris@16: (COPY_INIT_LIST,pars,np,acts) \ Chris@16: __parser(that.__parser) \ Chris@16: { } \ Chris@16: \ Chris@16: template struct result \ Chris@16: { \ Chris@16: typedef typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result< \ Chris@16: typename __rule::__expr::type, Scanner>::type type; \ Chris@16: }; \ Chris@16: \ Chris@16: template \ Chris@16: typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result::type \ Chris@16: parse(Scanner const & s) const { return __parser.parse(s); } \ Chris@16: \ Chris@16: BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_AP_HANDLER,5) \ Chris@16: (name_t,np,acts,na,::BOOST_SPIRIT_CLASSIC_NS::type_of) \ Chris@16: }; \ Chris@16: \ Chris@16: BOOST_PP_IF(np,BOOST_SPIRIT_RP_GEN_FUNC,BOOST_SPIRIT_RP_GLOB_VAR) \ Chris@16: (name,name_t,np,na) \ Chris@16: BOOST_SPIRIT_RP_REGISTER_TEMPLATE \ Chris@101: (name_t,BOOST_PP_INC(BOOST_PP_ADD(np,na))) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_OPAQUE_IMPL_I Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_OPAQUE_IMPL_I(name,pars,mbrs,expr) \ Chris@16: BOOST_SPIRIT_RP_OPAQUE_IMPL_II(name, name ## _t, \ Chris@16: pars,BOOST_SPIRIT_RP_ARRAY_SIZE(pars),-,-,\ Chris@16: mbrs,BOOST_SPIRIT_RP_ARRAY_SIZE(mbrs),expr) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_OPAQUE_IMPL_II Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_OPAQUE_IMPL_II(name,name_t,pars,np,_1,_2,mbrs,nm,x) \ Chris@16: class name_t; \ Chris@16: \ Chris@16: BOOST_SPIRIT_RP_REGISTER_TYPE(name_t) \ Chris@16: \ Chris@16: class name_t \ Chris@16: : public ::BOOST_SPIRIT_CLASSIC_NS::parser< name_t > \ Chris@16: { \ Chris@16: class __rule \ Chris@16: { \ Chris@16: BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_STATIC,pars,-) \ Chris@16: BOOST_SPIRIT_RP_EMIT(MV_STATIC,mbrs,BOOST_PP_EMPTY) \ Chris@16: public: \ Chris@16: BOOST_TYPEOF_NESTED_TYPEDEF(__expr,x) \ Chris@16: }; \ Chris@16: \ Chris@16: public: \ Chris@16: \ Chris@16: typedef name_t self_t; \ Chris@16: typedef __rule::__expr::type::parser_category_t parser_category_t; \ Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_NOT(np),typedef self_t const & embed_t;) \ Chris@16: \ Chris@16: protected: \ Chris@16: \ Chris@16: BOOST_SPIRIT_RP_EMIT(MV_NONSTATIC,mbrs,BOOST_PP_EMPTY) \ Chris@16: \ Chris@16: __rule::__expr::type::embed_t __parser; \ Chris@16: \ Chris@16: public: \ Chris@16: \ Chris@16: explicit name_t (BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_CTOR_PARAMS,pars,-)) \ Chris@16: : BOOST_SPIRIT_RP_EMIT(MV_CTOR_INIT_LIST,mbrs,-) \ Chris@16: BOOST_PP_COMMA_IF(nm) __parser(x) \ Chris@16: { } \ Chris@16: \ Chris@16: name_t(name_t const & that) \ Chris@16: : BOOST_SPIRIT_RP_EMIT(MV_CTOR_COPY_INIT_LIST,mbrs,that) \ Chris@16: BOOST_PP_COMMA_IF(nm) __parser(that.__parser) \ Chris@16: { } \ Chris@16: \ Chris@16: template struct result \ Chris@16: { \ Chris@16: typedef typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result< \ Chris@16: __rule::__expr::type, Scanner>::type type; \ Chris@16: }; \ Chris@16: \ Chris@16: template \ Chris@16: typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result::type \ Chris@16: parse(Scanner const & s) const { return __parser.parse(s); } \ Chris@16: }; \ Chris@16: \ Chris@16: BOOST_PP_IF(np,BOOST_SPIRIT_RP_GEN_OPAQUE,BOOST_SPIRIT_RP_GLOB_OPAQUE) \ Chris@16: (name,name_t,np,pars) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@101: // RP_AP_HANDLER Chris@16: // Chris@16: // Part of the rule parser definition for handling action placeholders Chris@16: # define BOOST_SPIRIT_RP_AP_HANDLER(name_t,np,acts,na,ns) \ Chris@16: private: \ Chris@16: template struct __rebound_1st \ Chris@16: { \ Chris@16: typedef name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,__T) , \ Chris@16: typename ns ::action_concatenator<__A0,A>::type \ Chris@16: BOOST_PP_COMMA_IF(BOOST_PP_DEC(na)) \ Chris@16: BOOST_PP_ENUM_SHIFTED_PARAMS(na,__A) \ Chris@16: > type; \ Chris@16: }; \ Chris@16: \ Chris@16: template struct __rebound \ Chris@16: { \ Chris@16: typedef name_t < \ Chris@16: void BOOST_PP_ENUM_TRAILING_PARAMS(np,__T) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_REBOUND_TPL_ARGS,acts,X) \ Chris@16: > type; \ Chris@16: }; \ Chris@16: public: \ Chris@16: template \ Chris@16: typename __rebound_1st::type const operator[](A const & a) const \ Chris@16: { \ Chris@16: return typename __rebound_1st::type ( \ Chris@16: BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \ Chris@16: ns ::concatenate_actions(__a0,a) \ Chris@16: BOOST_PP_COMMA_IF(BOOST_PP_DEC(na)) \ Chris@16: BOOST_PP_ENUM_SHIFTED_PARAMS(na,__a) ); \ Chris@16: } \ Chris@16: template \ Chris@16: typename __rebound< ns ::action_chain >::type const \ Chris@16: operator[]( ns ::action_chain const & x) const \ Chris@16: { \ Chris@16: return typename __rebound< ns ::action_chain >::type ( \ Chris@16: BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_REBOUND_ARGS,acts,x) ); \ Chris@16: } \ Chris@16: template \ Chris@16: typename __rebound< ns ::action_chains >::type const \ Chris@16: operator[]( ns ::action_chains const & x) const \ Chris@16: { \ Chris@16: return typename __rebound< ns ::action_chains >::type ( \ Chris@16: BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_REBOUND_ARGS,acts,x) ); \ Chris@16: } Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_AP_EXTRA_MBRS Chris@16: // Chris@16: // Extra members we need for rebinding if there are action placeholders Chris@16: # define BOOST_SPIRIT_RP_AP_EXTRA_MBRS(np,na) \ Chris@16: private: \ Chris@16: BOOST_PP_REPEAT(np,BOOST_SPIRIT_RP_PM_MBRS,-) \ Chris@101: BOOST_PP_REPEAT(na,BOOST_SPIRIT_RP_AP_MBRS,-) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_PM_MBRS Chris@16: // Chris@16: // Member variables to remember parameters if there are action placeholder Chris@16: # define BOOST_SPIRIT_RP_PM_MBRS(z,i,d) __T ## i __p ## i ; Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_AP_MBRS Chris@16: // Chris@16: // Member variables to remember action placeholder substitutes Chris@16: # define BOOST_SPIRIT_RP_AP_MBRS(z,i,d) __A ## i __a ## i ; Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_CTOR Chris@16: // Chris@16: // Expands to a fragment of a constructor (parameters or init-list) Chris@16: # define BOOST_SPIRIT_RP_CTOR(what,pars,np,acts) \ Chris@16: BOOST_SPIRIT_RP_EMIT(PM_CTOR_ ## what,pars,__T) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_CTOR_ ## what,acts,np) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_CTOR_COMMA Chris@16: // Chris@16: // RP_CTOR with a trailing comma Chris@16: # define BOOST_SPIRIT_RP_CTOR_COMMA(what,pars,np,acts) \ Chris@16: BOOST_SPIRIT_RP_CTOR(what,pars,np,acts) , Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_TPL_PARAMS Chris@16: // Chris@101: // Expands to the template parameters or arguments of the rule parser template Chris@16: # define BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,prefix,defaults) \ Chris@16: prefix ## Dummy \ Chris@16: BOOST_SPIRIT_RP_EMIT(PM_TEMPLATE_PARAMS,pars,prefix ## T) \ Chris@16: BOOST_SPIRIT_RP_EMIT(AP_TEMPLATE_PARAMS,acts,(prefix ## A,defaults)) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_GEN_FUNC Chris@16: // Chris@16: // Generator function Chris@16: # define BOOST_SPIRIT_RP_GEN_FUNC(name,name_t,np,na) \ Chris@16: template< BOOST_PP_ENUM_PARAMS(np,typename T) > \ Chris@16: inline name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,T) > \ Chris@16: name( BOOST_PP_ENUM_BINARY_PARAMS(np,T, const & p) ) \ Chris@16: { return name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,T) > \ Chris@16: (BOOST_PP_ENUM_PARAMS(np,p) BOOST_PP_ENUM_TRAILING_PARAMS(na, \ Chris@16: ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor() BOOST_PP_INTERCEPT) ); \ Chris@16: } Chris@16: // RP_GEN_OPAQUE Chris@16: // Chris@16: // non-templated version for opaque rule parsers. Chris@16: # define BOOST_SPIRIT_RP_GEN_OPAQUE(name,name_t,np,pars) \ Chris@16: inline name_t name( BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_GEN_PARAMS,pars,p)) \ Chris@16: { return name_t (BOOST_PP_ENUM_PARAMS(np,p)); } Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_GLOB_VAR Chris@16: // Chris@16: // Global variable -- used instead of the generator function if there are no Chris@16: // parameters Chris@16: # define BOOST_SPIRIT_RP_GLOB_VAR(name,name_t,np,na) \ Chris@16: static name_t const name = name_t (BOOST_PP_ENUM_PARAMS(na, \ Chris@16: ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor() BOOST_PP_INTERCEPT) ); Chris@16: Chris@16: // RP_GLOB_OPAQUE Chris@16: // Chris@16: // non-templated version for opaque rule parsers. Chris@16: # define BOOST_SPIRIT_RP_GLOB_OPAQUE(name,name_t,np,pars) \ Chris@16: static name_t const name = name_t () ; Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // PP_EMIT operations (fragment emittion based on array input) Chris@16: Chris@16: // - - Namespace handling Chris@16: Chris@16: // NS_OPEN Chris@16: # define BOOST_SPIRIT_RP__NS_OPEN(r,data,i,elem) \ Chris@16: namespace BOOST_SPIRIT_RP_OPTIONAL(elem) { Chris@16: Chris@16: // NS_QUALIFY Chris@16: # define BOOST_SPIRIT_RP__NS_QUALIFY(r,data,i,elem) \ Chris@16: BOOST_SPIRIT_RP_OPTIONAL(elem ::) Chris@16: Chris@16: // NS_CLOSE Chris@16: # define BOOST_SPIRIT_RP__NS_CLOSE(r,data,i,elem) } Chris@16: Chris@16: // - - Parameter handling Chris@16: Chris@16: // PM_STATIC Chris@16: # define BOOST_SPIRIT_RP__PM_STATIC(r,data,i,elem) \ Chris@16: static typename ::boost::call_traits< data ## i >::reference elem ; Chris@16: Chris@16: // PM_CTOR_PARAMS Chris@16: # define BOOST_SPIRIT_RP__PM_CTOR_PARAMS(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) \ Chris@101: typename ::boost::call_traits< data ## i >::param_type elem Chris@16: Chris@16: // PM_CTOR_ARGS Chris@16: # define BOOST_SPIRIT_RP__PM_CTOR_ARGS(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) elem Chris@16: Chris@16: // PM_CTOR_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__PM_CTOR_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) __p ## i ( elem ) Chris@16: Chris@16: // PM_CTOR_COPY_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__PM_CTOR_COPY_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) __p ## i ( that. __p ## i ) Chris@16: Chris@16: Chris@16: // PM_TEMPLATE_PARAMS Chris@16: # define BOOST_SPIRIT_RP__PM_TEMPLATE_PARAMS(r,data,i,elem) , data ## i Chris@16: Chris@16: // - strictly typed parameters of the opaque rule_parser Chris@16: Chris@16: // PM_OPAQUE_STATIC Chris@16: # define BOOST_SPIRIT_RP__PM_OPAQUE_STATIC(r,data,i,elem) \ Chris@16: static ::boost::call_traits< \ Chris@16: BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \ Chris@16: >::reference BOOST_PP_TUPLE_ELEM(2,1,elem) ; Chris@16: Chris@16: // PM_OPAQUE_CTOR_PARAMS Chris@16: # define BOOST_SPIRIT_RP__PM_OPAQUE_CTOR_PARAMS(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) ::boost::call_traits< \ Chris@16: BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \ Chris@16: >::param_type BOOST_PP_TUPLE_ELEM(2,1,elem) Chris@16: Chris@16: // PM_OPAQUE_GEN_PARAMS Chris@16: # define BOOST_SPIRIT_RP__PM_OPAQUE_GEN_PARAMS(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) ::boost::call_traits< \ Chris@16: BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \ Chris@16: >::param_type data ## i Chris@16: Chris@16: // - - Member variable handling Chris@16: Chris@16: // MV_NONSTATIC Chris@16: # define BOOST_SPIRIT_RP__MV_NONSTATIC(r,data,i,elem) \ Chris@16: data() BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(3,0,elem)) \ Chris@16: BOOST_PP_TUPLE_ELEM(3,1,elem) ; Chris@16: Chris@16: // MV_STATIC Chris@16: # define BOOST_SPIRIT_RP__MV_STATIC(r,data,i,elem) \ Chris@16: static data() ::boost::call_traits< \ Chris@16: data() BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(3,0,elem)) \ Chris@16: >::reference BOOST_PP_TUPLE_ELEM(3,1,elem) ; Chris@16: Chris@16: // MV_CTOR_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__MV_CTOR_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) \ Chris@16: BOOST_PP_TUPLE_ELEM(3,1,elem) BOOST_PP_TUPLE_ELEM(3,2,elem) Chris@16: Chris@16: // MV_CTOR_COPY_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__MV_CTOR_COPY_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) \ Chris@16: BOOST_PP_TUPLE_ELEM(3,1,elem) (data . BOOST_PP_TUPLE_ELEM(3,1,elem)) Chris@16: Chris@16: // - - Action placeholder handling Chris@16: Chris@16: // AP_STATIC Chris@16: # define BOOST_SPIRIT_RP__AP_STATIC(r,data,i,elem) static __A ## i & elem ; Chris@16: Chris@16: // AP_CTOR_PARAMS Chris@16: # define BOOST_SPIRIT_RP__AP_CTOR_PARAMS(r,data,i,elem) \ Chris@16: BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) \ Chris@16: typename ::boost::call_traits< __A ## i >::param_type elem Chris@16: Chris@16: // AP_CTOR_ARGS Chris@16: # define BOOST_SPIRIT_RP__AP_CTOR_ARGS(r,data,i,elem) \ Chris@16: BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) elem Chris@16: Chris@16: // AP_CTOR_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__AP_CTOR_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) __a ## i ( elem ) Chris@16: Chris@16: // AP_CTOR_COPY_INIT_LIST Chris@16: # define BOOST_SPIRIT_RP__AP_CTOR_COPY_INIT_LIST(r,data,i,elem) \ Chris@16: BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) __a ## i ( that. __a ## i ) Chris@16: Chris@16: // AP_TEMPLATE_PARAMS Chris@16: # define BOOST_SPIRIT_RP__AP_TEMPLATE_PARAMS(r,data,i,elem) \ Chris@16: , BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,data),i) \ Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_TUPLE_ELEM(2,1,data), \ Chris@16: = ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor) Chris@16: Chris@16: // AP_REBOUND_ARGS Chris@16: # define BOOST_SPIRIT_RP__AP_REBOUND_ARGS(r,data,i,elem) \ Chris@16: BOOST_PP_COMMA_IF(i) \ Chris@16: ::BOOST_SPIRIT_CLASSIC_NS::type_of::get_placeholdee< __action_placeholder:: elem > \ Chris@16: ( __a ## i , data ) Chris@16: Chris@16: // AP_REBOUND_TPL_ARGS Chris@16: # define BOOST_SPIRIT_RP__AP_REBOUND_TPL_ARGS(r,data,i,elem) \ Chris@16: , typename ::BOOST_SPIRIT_CLASSIC_NS::type_of::placeholdee< \ Chris@101: __action_placeholder:: elem , __A ## i, data >::type Chris@16: Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // PP_EMIT Chris@16: // Chris@16: // Performs one of the operations in the above section on an optional array. Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_EMIT(op, array, data) \ Chris@16: BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I(BOOST_SPIRIT_RP__ ## op,data,array) Chris@16: // --- --- - - --- - - --- - - - - --- - - - - - - - - - - - - - - - - - - - - - Chris@101: // RP_ARRAY_FOR_EACH_I Chris@16: // Chris@16: // Iterates an optional array. That is you can pass e.g.'-' or 'none' to denote Chris@16: // emptiness. Chris@16: # define BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I(macro,data,optional_array) \ Chris@16: BOOST_PP_IIF(BOOST_PP_IS_BINARY(optional_array), \ Chris@16: BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I_IMPL, \ Chris@16: BOOST_PP_TUPLE_EAT(3))(macro,data,optional_array) Chris@16: Chris@101: // RP_ARRAY_FOR_EACH_I_IMPL Chris@16: # define BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I_IMPL(macro,data,array) \ Chris@16: BOOST_SPIRIT_RP_IF(BOOST_PP_ARRAY_SIZE(array),PP_SEQ_FOR_EACH_I,3) \ Chris@16: (macro,data, BOOST_SPIRIT_RP_IF(BOOST_PP_ARRAY_SIZE(array), \ Chris@16: PP_TUPLE_TO_SEQ,2) array) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@101: // RP_ARRAY_SIZE Chris@16: // Chris@16: // Expands to the size of an "optional array". Chris@16: // Chris@16: // Examples: Chris@16: // Chris@16: // BOOST_SPIRIT_RP_ARRAY_SIZE( (2,(a,b)) ) // 2 Chris@16: // BOOST_SPIRIT_RP_ARRAY_SIZE( (0,()) ) // 0 Chris@16: // BOOST_SPIRIT_RP_ARRAY_SIZE( none ) // 0 Chris@16: // BOOST_SPIRIT_RP_ARRAY_SIZE( - ) // 0 Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_ARRAY_SIZE(optional_array) \ Chris@16: BOOST_PP_IIF(BOOST_PP_IS_BINARY(optional_array), \ Chris@16: BOOST_PP_ARRAY_SIZE, 0 BOOST_PP_TUPLE_EAT(1))(optional_array) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_OPTIONAL Chris@101: // Chris@16: // Expands to nothing if the argument is parenthesized. Chris@16: // Chris@16: // Examples: Chris@16: // Chris@16: // BOOST_SPIRIT_RP_OPTIONAL( foobar ) // foobar Chris@16: // BOOST_SPIRIT_RP_OPTIONAL( (none) ) // evaluates to nothing Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_OPTIONAL(elem) \ Chris@101: BOOST_PP_EXPR_IIF(BOOST_PP_COMPL(BOOST_PP_IS_UNARY(elem)),elem) Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_COMMA_IF_OR Chris@16: // Chris@16: // Expands to nothing if both arguments are zero, otherwise expands to a comma. Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_COMMA_IF_OR(a,b) \ Chris@16: BOOST_PP_IIF(BOOST_PP_OR(a,b),BOOST_PP_COMMA,BOOST_PP_EMPTY)() Chris@16: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@16: // RP_IF Chris@16: // Chris@16: // BOOST_SPIRIT_RP_IF(cond,name,arity) Chris@16: // Chris@16: // is equivalent to: Chris@16: // Chris@16: // BOOST_PP_IF(cond,BOOST_name,BOOST_PP_TUPLE_EAT(arity)) Chris@16: // Chris@16: # define BOOST_SPIRIT_RP_IF(cond,name,arity) \ Chris@16: BOOST_PP_IF(cond,BOOST_ ## name,BOOST_PP_TUPLE_EAT(arity)) Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: // Wrapper and gernator function to embed a parser by reference Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@101: namespace boost { namespace spirit { Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN Chris@16: Chris@16: // Wrapper to embed a parser by reference Chris@16: Chris@101: template class parser_reference Chris@16: : public parser< parser_reference

> Chris@16: { Chris@16: P const & ref_that; Chris@16: public: Chris@16: parser_reference(P & that) Chris@16: // we allow implicit conversion but forbid temporaries. Chris@16: : ref_that(that) Chris@16: { } Chris@16: Chris@16: typedef parser_reference

self_t; Chris@101: typedef self_t const & embed_t; Chris@16: typedef typename P::parser_category_t parser_category_t; Chris@16: Chris@101: template struct result Chris@16: { typedef typename P::BOOST_NESTED_TEMPLATE result::type type; }; Chris@16: Chris@101: template Chris@16: typename result::type Chris@16: parse(ScannerT const & scan) const Chris@16: { return this->ref_that.parse(scan); } Chris@16: }; Chris@16: Chris@101: template parser_reference

Chris@16: embed_by_reference(::BOOST_SPIRIT_CLASSIC_NS::parser

& p) Chris@16: { return p; } Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_END Chris@16: Chris@16: } } // namespace ::BOOST_SPIRIT_CLASSIC_NS Chris@16: Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::parser_reference, 1) Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: // Expression templates for action placeholders. Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@101: namespace boost { namespace spirit { Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN Chris@16: Chris@101: namespace type_of { Chris@16: Chris@16: // No-operation functor Chris@16: Chris@101: struct nop_functor Chris@16: { Chris@16: template Chris@101: bool operator()(T const &) const Chris@16: { return false; } Chris@16: template Chris@16: bool operator()(T const &, U const &) const Chris@16: { return false; } Chris@16: Chris@16: typedef bool result_type; Chris@16: }; Chris@16: Chris@16: // Composite action Chris@16: Chris@16: template Chris@16: class composite_action Chris@16: { Chris@16: Action1 fnc_a1; Chris@16: Action2 fnc_a2; Chris@16: public: Chris@16: composite_action(Action1 const & a1, Action2 const & a2) Chris@16: : fnc_a1(a1), fnc_a2(a2) Chris@16: { } Chris@16: Chris@16: template Chris@16: void operator()(T const & inp) const Chris@16: { fnc_a1(inp); fnc_a2(inp); } Chris@16: Chris@16: template Chris@16: void operator()(T const & inp1, U const inp2) const Chris@16: { fnc_a1(inp1, inp2); fnc_a2(inp1, inp2); } Chris@16: }; Chris@16: Chris@16: // Action concatenation (and optimize away nop_functorS) Chris@16: Chris@16: template Chris@16: struct action_concatenator Chris@16: { Chris@16: typedef composite_action type; Chris@16: Chris@16: static type concatenate(Action1 const & a1, Action2 const & a2) Chris@16: { return composite_action(a1,a2); } Chris@16: }; Chris@16: template struct action_concatenator Chris@16: { Chris@16: typedef Action type; Chris@16: Chris@101: static type concatenate(nop_functor const &, Action const & a) Chris@16: { return a; } Chris@16: }; Chris@16: template struct action_concatenator Chris@16: { Chris@16: typedef Action type; Chris@16: Chris@101: static type concatenate(Action const & a, nop_functor const &) Chris@16: { return a; } Chris@16: }; Chris@16: template<> struct action_concatenator Chris@16: { Chris@16: typedef nop_functor type; Chris@16: Chris@101: static type concatenate(nop_functor const &, nop_functor const &) Chris@16: { return nop_functor(); } Chris@16: }; Chris@16: Chris@16: template Chris@101: typename action_concatenator::type Chris@16: concatenate_actions(Action1 const & a1, Action2 const & a2) Chris@16: { Chris@16: return action_concatenator::concatenate(a1,a2); Chris@16: } Chris@16: Chris@16: // Action chains Chris@16: Chris@16: enum action_chain_mode { replace, append }; Chris@16: Chris@16: template Chris@16: class action_chain Chris@16: { Chris@16: Action fnc_action; Chris@16: public: Chris@16: action_chain(Action const & a) Chris@16: : fnc_action(a) Chris@16: { } Chris@16: Chris@16: typedef Action action_type; Chris@16: Chris@16: Action const & action() const { return fnc_action; } Chris@16: }; Chris@16: Chris@16: // This operator adds actions to an action chain definition Chris@16: template Chris@16: action_chain::type> Chris@16: operator, (action_chain const & chain, A2 const & a) Chris@16: { Chris@16: return action_chain::type> Chris@16: ( concatenate_actions(chain.action(), a) ); Chris@16: } Chris@16: Chris@16: // Expression template for mutiple action chain assignments Chris@16: template Chris@16: class action_chains Chris@16: { Chris@16: ChainOrChains obj_head; Chris@16: LastChain obj_tail; Chris@16: public: Chris@16: action_chains(ChainOrChains const & head, LastChain const & tail) Chris@16: : obj_head(head), obj_tail(tail) Chris@16: { } Chris@16: Chris@16: typedef ChainOrChains head_type; Chris@16: typedef LastChain tail_type; Chris@16: Chris@16: head_type const & head() const { return obj_head; } Chris@16: tail_type const & tail() const { return obj_tail; } Chris@101: }; Chris@16: Chris@16: // Action chain concatenation Chris@16: template Chris@16: action_chains make_chain(Head const & h, Tail const & t) Chris@16: { return action_chains(h,t); } Chris@16: Chris@101: template Chris@16: action_chains< action_chain, action_chain > Chris@101: operator, (action_chain const & h, Chris@16: action_chain const & t) Chris@16: { return make_chain(h,t); } Chris@16: Chris@16: template Chris@16: action_chains< action_chains, action_chain > Chris@16: operator, (action_chains const & h, action_chain const & t) Chris@16: { return make_chain(h,t); } Chris@16: Chris@16: Chris@101: // Extract the (maybe composite) action associated with an action Chris@16: // placeholders from the chains with a fold algorithm. Chris@16: template Chris@16: struct placeholdee Chris@16: { Chris@101: typedef StartAction type; Chris@16: Chris@16: static type get(StartAction const & a, NewChainOrChains const &) Chris@16: { return a; } Chris@16: }; Chris@16: Chris@16: template Chris@16: typename placeholdee::type Chris@16: get_placeholdee(StartAction const & a, NewChainOrChains const & c) Chris@16: { return placeholdee::get(a,c); } Chris@16: Chris@101: template Chris@16: struct placeholdee Chris@16: < Placeholder, StartAction, action_chains > Chris@16: { Chris@16: typedef typename placeholdee::type, Tail >::type Chris@16: type; Chris@16: Chris@16: static type get(StartAction const & a, action_chains const & c) Chris@16: { Chris@16: return get_placeholdee( Chris@16: get_placeholdee(a,c.head()), c.tail() ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct placeholdee Chris@16: < Placeholder, StartAction, action_chain > Chris@16: { Chris@16: typedef A type; Chris@16: Chris@101: static type get(StartAction const &, Chris@16: action_chain const & c) Chris@16: { return c.action(); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct placeholdee Chris@16: < Placeholder, StartAction, action_chain > Chris@16: { Chris@16: typedef typename action_concatenator::type type; Chris@16: Chris@101: static type get(StartAction const & a, Chris@16: action_chain const & c) Chris@16: { return concatenate_actions(a,c.action()); } Chris@16: }; Chris@16: Chris@101: } Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_END Chris@16: Chris@16: } } // namespace ::BOOST_SPIRIT_CLASSIC_NS::type_of Chris@16: Chris@16: BOOST_TYPEOF_REGISTER_TYPE(BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor) Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::type_of::composite_action,2) Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: // Misc.utilities Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@101: namespace boost { namespace spirit { Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN Chris@16: Chris@16: namespace type_of { Chris@16: Chris@16: // Utility function to create a dependency to a template argument. Chris@16: Chris@16: template Chris@101: X const & depend_on_type(X const & x) Chris@16: { return x; } Chris@16: Chris@16: // Utility to allow use parenthesized type expressions with commas inside Chris@16: // as a type within macros. Thanks to Dave Abrahams for telling me this nice Chris@16: // trick. Chris@16: Chris@16: #define BOOST_SPIRIT_RP_TYPE(x) \ Chris@16: ::BOOST_SPIRIT_CLASSIC_NS::type_of::remove_special_fptr \ Chris@16: < ::BOOST_SPIRIT_CLASSIC_NS::type_of::special_result & (*) x >::type Chris@16: Chris@16: struct special_result; Chris@16: Chris@16: template struct remove_special_fptr { }; Chris@16: template struct remove_special_fptr< special_result & (*)(T) > Chris@16: { typedef T type; }; Chris@16: Chris@101: } Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_END Chris@16: Chris@16: } } // namespace ::BOOST_SPIRIT_CLASSIC_NS::type_of Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@101: #endif Chris@16: //------------------------------------------------------------------------------ Chris@16: