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 #if !defined(BOOST_SPIRIT_MATCH_HPP) 9 #define BOOST_SPIRIT_MATCH_HPP 10 11 #include <boost/spirit/home/classic/namespace.hpp> 12 #include <boost/spirit/home/classic/core/config.hpp> 13 #include <boost/spirit/home/classic/core/nil.hpp> 14 #include <boost/call_traits.hpp> 15 #include <boost/optional.hpp> 16 #include <boost/spirit/home/classic/core/assert.hpp> 17 #include <boost/spirit/home/classic/core/safe_bool.hpp> 18 #include <boost/spirit/home/classic/core/impl/match_attr_traits.ipp> 19 #include <boost/type_traits/add_const.hpp> 20 #include <boost/type_traits/add_reference.hpp> 21 #include <boost/type_traits/conditional.hpp> 22 #include <boost/type_traits/is_reference.hpp> 23 24 namespace boost { namespace spirit { 25 26 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 27 28 /////////////////////////////////////////////////////////////////////////// 29 // 30 // match class 31 // 32 // The match holds the result of a parser. A match object evaluates 33 // to true when a successful match is found, otherwise false. The 34 // length of the match is the number of characters (or tokens) that 35 // is successfully matched. This can be queried through its length() 36 // member function. A negative value means that the match is 37 // unsuccessful. 38 // 39 // Each parser may have an associated attribute. This attribute is 40 // also returned back to the client on a successful parse through 41 // the match object. The match's value() member function returns the 42 // match's attribute. 43 // 44 // A match attribute is valid: 45 // 46 // * on a successful match 47 // * when its value is set through the value(val) member function 48 // * if it is assigned or copied from a compatible match object 49 // (e.g. match<double> from match<int>) with a valid attribute. 50 // 51 // The match attribute is undefined: 52 // 53 // * on an unsuccessful match 54 // * when an attempt to copy or assign from another match object 55 // with an incompatible attribute type (e.g. match<std::string> 56 // from match<int>). 57 // 58 // The member function has_valid_attribute() can be queried to know if 59 // it is safe to get the match's attribute. The attribute may be set 60 // through the member function value(v) where v is the new attribute 61 // value. 62 // 63 /////////////////////////////////////////////////////////////////////////// 64 template <typename T = nil_t> 65 class match : public safe_bool<match<T> > 66 { 67 typedef typename 68 conditional< 69 is_reference<T>::value 70 , T 71 , typename add_reference< 72 typename add_const<T>::type 73 >::type 74 >::type attr_ref_t; 75 76 public: 77 78 typedef typename boost::optional<T> optional_type; 79 typedef attr_ref_t ctor_param_t; 80 typedef attr_ref_t return_t; 81 typedef T attr_t; 82 83 match(); 84 explicit match(std::size_t length); 85 match(std::size_t length, ctor_param_t val); 86 87 bool operator!() const; 88 std::ptrdiff_t length() const; 89 bool has_valid_attribute() const; 90 return_t value() const; 91 void swap(match& other); 92 93 template <typename T2> match(match<T2> const & other)94 match(match<T2> const& other) 95 : len(other.length()), val() 96 { 97 impl::match_attr_traits<T>::copy(val, other); 98 } 99 100 template <typename T2> 101 match& operator =(match<T2> const & other)102 operator=(match<T2> const& other) 103 { 104 impl::match_attr_traits<T>::assign(val, other); 105 len = other.length(); 106 return *this; 107 } 108 109 template <typename MatchT> 110 void concat(MatchT const & other)111 concat(MatchT const& other) 112 { 113 BOOST_SPIRIT_ASSERT(*this && other); 114 len += other.length(); 115 } 116 117 template <typename ValueT> 118 void value(ValueT const & val_)119 value(ValueT const& val_) 120 { 121 impl::match_attr_traits<T>::set_value(val, val_, is_reference<T>()); 122 } 123 operator_bool() const124 bool operator_bool() const 125 { 126 return len >= 0; 127 } 128 129 private: 130 131 std::ptrdiff_t len; 132 optional_type val; 133 }; 134 135 /////////////////////////////////////////////////////////////////////////// 136 // 137 // match class specialization for nil_t values 138 // 139 /////////////////////////////////////////////////////////////////////////// 140 template <> 141 class match<nil_t> : public safe_bool<match<nil_t> > 142 { 143 public: 144 145 typedef nil_t attr_t; 146 typedef nil_t return_t; 147 148 match(); 149 explicit match(std::size_t length); 150 match(std::size_t length, nil_t); 151 152 bool operator!() const; 153 bool has_valid_attribute() const; 154 std::ptrdiff_t length() const; 155 nil_t value() const; 156 void value(nil_t); 157 void swap(match& other); 158 159 template <typename T> match(match<T> const & other)160 match(match<T> const& other) 161 : len(other.length()) {} 162 163 template <typename T> 164 match<>& operator =(match<T> const & other)165 operator=(match<T> const& other) 166 { 167 len = other.length(); 168 return *this; 169 } 170 171 template <typename T> 172 void concat(match<T> const & other)173 concat(match<T> const& other) 174 { 175 BOOST_SPIRIT_ASSERT(*this && other); 176 len += other.length(); 177 } 178 operator_bool() const179 bool operator_bool() const 180 { 181 return len >= 0; 182 } 183 184 private: 185 186 std::ptrdiff_t len; 187 }; 188 189 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 190 191 }} // namespace BOOST_SPIRIT_CLASSIC_NS 192 193 #endif 194 #include <boost/spirit/home/classic/core/impl/match.ipp> 195 196