1 /*============================================================================= 2 Copyright (c) 2002-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Hartmut Kaiser 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_HPP) 10 #define BOOST_SPIRIT_PARSER_CONTEXT_HPP 11 12 /////////////////////////////////////////////////////////////////////////////// 13 namespace boost 14 { 15 namespace spirit 16 { 17 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 18 19 20 /////////////////////////////////////////////////////////////////////////// 21 // 22 // default_parser_context_base class { default context base } 23 // 24 /////////////////////////////////////////////////////////////////////////// 25 struct default_parser_context_base 26 { 27 template <typename DerivedT> 28 struct aux {}; 29 }; 30 31 /////////////////////////////////////////////////////////////////////////// 32 // 33 // parser_context_base class { base class of all context classes } 34 // 35 /////////////////////////////////////////////////////////////////////////// 36 struct parser_context_base {}; 37 38 /////////////////////////////////////////////////////////////////////////// 39 // 40 // parser_context class { default context } 41 // 42 /////////////////////////////////////////////////////////////////////////// 43 struct nil_t; 44 template<typename ContextT> struct parser_context_linker; 45 46 template<typename AttrT = nil_t> 47 struct parser_context : parser_context_base 48 { 49 typedef AttrT attr_t; 50 typedef default_parser_context_base base_t; 51 typedef parser_context_linker<parser_context<AttrT> > context_linker_t; 52 53 template <typename ParserT> parser_contextboost::spirit::parser_context54 parser_context(ParserT const&) {} 55 56 template <typename ParserT, typename ScannerT> 57 void pre_parseboost::spirit::parser_context58 pre_parse(ParserT const&, ScannerT const&) {} 59 60 template <typename ResultT, typename ParserT, typename ScannerT> 61 ResultT& post_parseboost::spirit::parser_context62 post_parse(ResultT& hit, ParserT const&, ScannerT const&) 63 { return hit; } 64 }; 65 66 /////////////////////////////////////////////////////////////////////////// 67 // 68 // context_aux class 69 // 70 // context_aux<ContextT, DerivedT> is a class derived from the 71 // ContextT's nested base_t::base<DerivedT> template class. (see 72 // default_parser_context_base::aux for an example). 73 // 74 // Basically, this class provides ContextT dependent optional 75 // functionality to the derived class DerivedT through the CRTP 76 // idiom (Curiously recurring template pattern). 77 // 78 /////////////////////////////////////////////////////////////////////////// 79 template <typename ContextT, typename DerivedT> 80 struct context_aux : public ContextT::base_t::template aux<DerivedT> {}; 81 82 /////////////////////////////////////////////////////////////////////////// 83 // 84 // parser_scanner_linker and parser_scanner_linker classes 85 // { helper templates for the rule extensibility } 86 // 87 // This classes can be 'overloaded' (defined elsewhere), to plug 88 // in additional functionality into the non-terminal parsing process. 89 // 90 /////////////////////////////////////////////////////////////////////////// 91 #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) 92 #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED 93 94 template<typename ScannerT> 95 struct parser_scanner_linker : public ScannerT 96 { parser_scanner_linkerboost::spirit::parser_scanner_linker97 parser_scanner_linker(ScannerT const scan_) : ScannerT(scan_) {} 98 }; 99 100 #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) 101 102 ////////////////////////////////// 103 #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) 104 #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED 105 106 template<typename ContextT> 107 struct parser_context_linker : public ContextT 108 { 109 template <typename ParserT> parser_context_linkerboost::spirit::parser_context_linker110 parser_context_linker(ParserT const& p) 111 : ContextT(p) {} 112 113 template <typename ParserT, typename ScannerT> pre_parseboost::spirit::parser_context_linker114 void pre_parse(ParserT const& p, ScannerT const& scan) 115 { ContextT::pre_parse(p, scan); } 116 117 template <typename ResultT, typename ParserT, typename ScannerT> 118 ResultT& post_parseboost::spirit::parser_context_linker119 post_parse(ResultT& hit, ParserT const& p, ScannerT const& scan) 120 { return ContextT::post_parse(hit, p, scan); } 121 }; 122 123 #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) 124 125 /////////////////////////////////////////////////////////////////////////// 126 // 127 // BOOST_SPIRIT_CONTEXT_PARSE helper macro 128 // 129 // The original implementation uses a template class. However, we 130 // need to lessen the template instantiation depth to help inferior 131 // compilers that sometimes choke on deep template instantiations. 132 // The objective is to avoid code redundancy. A macro, in this case 133 // is an obvious solution. Sigh! 134 // 135 // WARNING: INTERNAL USE ONLY. NOT FOR PUBLIC CONSUMPTION. 136 // 137 /////////////////////////////////////////////////////////////////////////// 138 #define BOOST_SPIRIT_CONTEXT_PARSE(scan, this_, scanner_t, context_t, result_t) \ 139 scanner_t scan_wrap(scan); \ 140 context_t context_wrap(this_); \ 141 context_wrap.pre_parse(this_, scan_wrap); \ 142 result_t hit = parse_main(scan); \ 143 return context_wrap.post_parse(hit, this_, scan_wrap); 144 145 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 146 147 } // namespace spirit 148 } // namespace boost 149 150 #endif 151