1 /*============================================================================= 2 Copyright (c) 1998-2003 Joel de Guzman 3 http://spirit.sourceforge.net/ 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #ifndef BOOST_SPIRIT_ACTIONS_HPP 9 #define BOOST_SPIRIT_ACTIONS_HPP 10 11 #include <boost/spirit/home/classic/namespace.hpp> 12 #include <boost/spirit/home/classic/core/parser.hpp> 13 #include <boost/spirit/home/classic/core/composite/composite.hpp> 14 #include <boost/core/ignore_unused.hpp> 15 16 namespace boost { namespace spirit { 17 18 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 19 20 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 21 #pragma warning(push) 22 #pragma warning(disable:4512) //assignment operator could not be generated 23 #endif 24 25 /////////////////////////////////////////////////////////////////////////// 26 // 27 // action class 28 // 29 // The action class binds a parser with a user defined semantic 30 // action. Instances of action are never created manually. Instead, 31 // action objects are typically created indirectly through 32 // expression templates of the form: 33 // 34 // p[f] 35 // 36 // where p is a parser and f is a function or functor. The semantic 37 // action may be a function or a functor. When the parser is 38 // successful, the actor calls the scanner's action_policy policy 39 // (see scanner.hpp): 40 // 41 // scan.do_action(actor, attribute, first, last); 42 // 43 // passing in these information: 44 // 45 // actor: The action's function or functor 46 // attribute: The match (returned by the parser) object's 47 // attribute (see match.hpp) 48 // first: Iterator pointing to the start of the matching 49 // portion of the input 50 // last: Iterator pointing to one past the end of the 51 // matching portion of the input 52 // 53 // It is the responsibility of the scanner's action_policy policy to 54 // dispatch the function or functor as it sees fit. The expected 55 // function or functor signature depends on the parser being 56 // wrapped. In general, if the attribute type of the parser being 57 // wrapped is a nil_t, the function or functor expect the signature: 58 // 59 // void func(Iterator first, Iterator last); // functions 60 // 61 // struct ftor // functors 62 // { 63 // void func(Iterator first, Iterator last) const; 64 // }; 65 // 66 // where Iterator is the type of the iterator that is being used and 67 // first and last are the iterators pointing to the matching portion 68 // of the input. 69 // 70 // If the attribute type of the parser being wrapped is not a nil_t, 71 // the function or functor usually expect the signature: 72 // 73 // void func(T val); // functions 74 // 75 // struct ftor // functors 76 // { 77 // void func(T val) const; 78 // }; 79 // 80 // where T is the attribute type and val is the attribute value 81 // returned by the parser being wrapped. 82 // 83 /////////////////////////////////////////////////////////////////////////// 84 template <typename ParserT, typename ActionT> 85 class action : public unary<ParserT, parser<action<ParserT, ActionT> > > 86 { 87 public: 88 89 typedef action<ParserT, ActionT> self_t; 90 typedef action_parser_category parser_category_t; 91 typedef unary<ParserT, parser<self_t> > base_t; 92 typedef ActionT predicate_t; 93 94 template <typename ScannerT> 95 struct result 96 { 97 typedef typename parser_result<ParserT, ScannerT>::type type; 98 }; 99 action(ParserT const & p,ActionT const & a)100 action(ParserT const& p, ActionT const& a) 101 : base_t(p) 102 , actor(a) {} 103 104 template <typename ScannerT> 105 typename parser_result<self_t, ScannerT>::type parse(ScannerT const & scan) const106 parse(ScannerT const& scan) const 107 { 108 typedef typename ScannerT::iterator_t iterator_t; 109 typedef typename parser_result<self_t, ScannerT>::type result_t; 110 111 ignore_unused(scan.at_end()); // allow skipper to take effect 112 iterator_t save = scan.first; 113 result_t hit = this->subject().parse(scan); 114 if (hit) 115 { 116 typename result_t::return_t val = hit.value(); 117 scan.do_action(actor, val, save, scan.first); 118 } 119 return hit; 120 } 121 predicate() const122 ActionT const& predicate() const { return actor; } 123 124 private: 125 126 ActionT actor; 127 }; 128 129 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 130 #pragma warning(pop) 131 #endif 132 133 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 134 135 }} // namespace BOOST_SPIRIT_CLASSIC_NS 136 137 #endif 138