1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 Copyright (c) 2013 Agustin Berge 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_X3_PARSER_OCTOBER_16_2008_0254PM) 9 #define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM 10 11 #include <boost/mpl/bool.hpp> 12 #include <boost/type_traits/is_base_of.hpp> 13 #include <boost/type_traits/remove_cv.hpp> 14 #include <boost/type_traits/remove_reference.hpp> 15 #include <boost/utility/declval.hpp> 16 #include <boost/utility/enable_if.hpp> 17 #include <boost/spirit/home/x3/support/unused.hpp> 18 #include <boost/spirit/home/x3/support/context.hpp> 19 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp> 20 #include <boost/spirit/home/x3/support/utility/sfinae.hpp> 21 #include <boost/core/ignore_unused.hpp> 22 #include <boost/assert.hpp> 23 #include <string> 24 25 #if !defined(BOOST_SPIRIT_X3_NO_RTTI) 26 #include <typeinfo> 27 #endif 28 29 namespace boost { namespace spirit { namespace x3 30 { 31 template <typename Subject, typename Action> 32 struct action; 33 34 template <typename Subject, typename Handler> 35 struct guard; 36 37 struct parser_base {}; 38 struct parser_id; 39 40 template <typename Derived> 41 struct parser : parser_base 42 { 43 typedef Derived derived_type; 44 static bool const handles_container = false; 45 static bool const is_pass_through_unary = false; 46 static bool const has_action = false; 47 derivedboost::spirit::x3::parser48 constexpr Derived const& derived() const 49 { 50 return *static_cast<Derived const*>(this); 51 } 52 53 template <typename Action> operator []boost::spirit::x3::parser54 constexpr action<Derived, Action> operator[](Action f) const 55 { 56 return { this->derived(), f }; 57 } 58 59 template <typename Handler> on_errorboost::spirit::x3::parser60 constexpr guard<Derived, Handler> on_error(Handler f) const 61 { 62 return { this->derived(), f }; 63 } 64 }; 65 66 struct unary_category; 67 struct binary_category; 68 69 template <typename Subject, typename Derived> 70 struct unary_parser : parser<Derived> 71 { 72 typedef unary_category category; 73 typedef Subject subject_type; 74 static bool const has_action = Subject::has_action; 75 unary_parserboost::spirit::x3::unary_parser76 constexpr unary_parser(Subject const& subject) 77 : subject(subject) {} 78 get_unaryboost::spirit::x3::unary_parser79 unary_parser const& get_unary() const { return *this; } 80 81 Subject subject; 82 }; 83 84 template <typename Left, typename Right, typename Derived> 85 struct binary_parser : parser<Derived> 86 { 87 typedef binary_category category; 88 typedef Left left_type; 89 typedef Right right_type; 90 static bool const has_action = 91 left_type::has_action || right_type::has_action; 92 binary_parserboost::spirit::x3::binary_parser93 constexpr binary_parser(Left const& left, Right const& right) 94 : left(left), right(right) {} 95 get_binaryboost::spirit::x3::binary_parser96 binary_parser const& get_binary() const { return *this; } 97 98 Left left; 99 Right right; 100 }; 101 102 /////////////////////////////////////////////////////////////////////////// 103 // as_parser: convert a type, T, into a parser. 104 /////////////////////////////////////////////////////////////////////////// 105 namespace extension 106 { 107 namespace detail 108 { 109 namespace as_parser_guard 110 { 111 void as_spirit_parser(...); 112 113 template<typename T, typename R = 114 decltype(as_spirit_parser(boost::declval<T const&>()))> 115 struct deduce_as_parser 116 { 117 typedef R type; 118 typedef typename 119 boost::remove_cv< 120 typename boost::remove_reference<R>::type 121 >::type 122 value_type; 123 callboost::spirit::x3::extension::detail::as_parser_guard::deduce_as_parser124 static type call(T const& v) 125 { 126 return as_spirit_parser(v); 127 } 128 }; 129 template<typename T> 130 struct deduce_as_parser<T, void> 131 {}; 132 } 133 using as_parser_guard::deduce_as_parser; 134 } 135 136 template <typename T, typename Enable = void> 137 struct as_parser : detail::deduce_as_parser<T> {}; 138 139 template <> 140 struct as_parser<unused_type> 141 { 142 typedef unused_type type; 143 typedef unused_type value_type; callboost::spirit::x3::extension::as_parser144 static constexpr type call(unused_type) 145 { 146 return unused; 147 } 148 }; 149 150 template <typename Derived> 151 struct as_parser<Derived 152 , typename enable_if<is_base_of<parser_base, Derived>>::type> 153 { 154 typedef Derived const& type; 155 typedef Derived value_type; callboost::spirit::x3::extension::as_parser156 static constexpr type call(Derived const& p) 157 { 158 return p; 159 } 160 }; 161 162 template <typename Derived> 163 struct as_parser<parser<Derived>> 164 { 165 typedef Derived const& type; 166 typedef Derived value_type; callboost::spirit::x3::extension::as_parser167 static constexpr type call(parser<Derived> const& p) 168 { 169 return p.derived(); 170 } 171 }; 172 } 173 174 template <typename T> 175 constexpr typename extension::as_parser<T>::type as_parser(T const & x)176 as_parser(T const& x) 177 { 178 return extension::as_parser<T>::call(x); 179 } 180 181 template <typename Derived> 182 constexpr Derived const& as_parser(parser<Derived> const & p)183 as_parser(parser<Derived> const& p) 184 { 185 return p.derived(); 186 } 187 188 /////////////////////////////////////////////////////////////////////////// 189 // The main what function 190 // 191 // Note: unlike Spirit2, spirit parsers are no longer required to have a 192 // "what" member function. In X3, we specialize the get_info struct 193 // below where needed. If a specialization is not provided, the default 194 // below will be used. The default "what" result will be the typeid 195 // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise 196 // "undefined" 197 /////////////////////////////////////////////////////////////////////////// 198 template <typename Parser, typename Enable = void> 199 struct get_info 200 { 201 typedef std::string result_type; operator ()boost::spirit::x3::get_info202 std::string operator()(Parser const&) const 203 { 204 #if !defined(BOOST_SPIRIT_X3_NO_RTTI) 205 return typeid(Parser).name(); 206 #else 207 return "undefined"; 208 #endif 209 } 210 }; 211 212 template <typename Parser> what(Parser const & p)213 std::string what(Parser const& p) 214 { 215 return get_info<Parser>()(p); 216 } 217 }}} 218 219 namespace boost { namespace spirit { namespace x3 { namespace traits 220 { 221 template <typename Subject, typename Derived, typename Context> 222 struct has_attribute<x3::unary_parser<Subject, Derived>, Context> 223 : has_attribute<Subject, Context> {}; 224 225 template <typename Left, typename Right, typename Derived, typename Context> 226 struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context> 227 : mpl::bool_<has_attribute<Left, Context>::value || 228 has_attribute<Right, Context>::value> {}; 229 }}}} 230 231 #endif 232