1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 #if !defined(BOOST_SPIRIT_CHAR_PARSER_APR_16_2006_0906AM) 8 #define BOOST_SPIRIT_CHAR_PARSER_APR_16_2006_0906AM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/qi/domain.hpp> 15 #include <boost/spirit/home/qi/parser.hpp> 16 #include <boost/spirit/home/qi/detail/assign_to.hpp> 17 #include <boost/spirit/home/qi/meta_compiler.hpp> 18 #include <boost/spirit/home/qi/skip_over.hpp> 19 #include <boost/spirit/home/support/unused.hpp> 20 #include <boost/spirit/home/support/info.hpp> 21 #include <boost/proto/operators.hpp> 22 #include <boost/proto/tags.hpp> 23 24 namespace boost { namespace spirit 25 { 26 /////////////////////////////////////////////////////////////////////////// 27 // Enablers 28 /////////////////////////////////////////////////////////////////////////// 29 template <> 30 struct use_operator<qi::domain, proto::tag::complement> // enables ~ 31 : mpl::true_ {}; 32 }} 33 34 namespace boost { namespace spirit { namespace traits // classification 35 { 36 namespace detail 37 { 38 BOOST_MPL_HAS_XXX_TRAIT_DEF(char_parser_id) 39 } 40 41 template <typename T> 42 struct is_char_parser : detail::has_char_parser_id<T> {}; 43 }}} 44 45 namespace boost { namespace spirit { namespace qi 46 { 47 /////////////////////////////////////////////////////////////////////////// 48 // The base char_parser 49 /////////////////////////////////////////////////////////////////////////// 50 template <typename Derived, typename Char, typename Attr = Char> 51 struct char_parser : primitive_parser<Derived> 52 { 53 typedef Char char_type; 54 struct char_parser_id; 55 56 // if Attr is unused_type, Derived must supply its own attribute 57 // metafunction 58 template <typename Context, typename Iterator> 59 struct attribute 60 { 61 typedef Attr type; 62 }; 63 64 template <typename Iterator, typename Context, typename Skipper, typename Attribute> parseboost::spirit::qi::char_parser65 bool parse(Iterator& first, Iterator const& last 66 , Context& context, Skipper const& skipper, Attribute& attr_) const 67 { 68 qi::skip_over(first, last, skipper); 69 70 if (first != last && this->derived().test(*first, context)) 71 { 72 spirit::traits::assign_to(*first, attr_); 73 ++first; 74 return true; 75 } 76 return false; 77 } 78 79 // Requirement: p.test(ch, context) -> bool 80 // 81 // ch: character being parsed 82 // context: enclosing rule context 83 }; 84 85 /////////////////////////////////////////////////////////////////////////// 86 // negated_char_parser handles ~cp expressions (cp is a char_parser) 87 /////////////////////////////////////////////////////////////////////////// 88 template <typename Positive> 89 struct negated_char_parser : 90 char_parser<negated_char_parser<Positive>, typename Positive::char_type> 91 { negated_char_parserboost::spirit::qi::negated_char_parser92 negated_char_parser(Positive const& positive_) 93 : positive(positive_) {} 94 95 template <typename CharParam, typename Context> testboost::spirit::qi::negated_char_parser96 bool test(CharParam ch, Context& context) const 97 { 98 return !positive.test(ch, context); 99 } 100 101 template <typename Context> whatboost::spirit::qi::negated_char_parser102 info what(Context& context) const 103 { 104 return info("not", positive.what(context)); 105 } 106 107 Positive positive; 108 }; 109 110 /////////////////////////////////////////////////////////////////////////// 111 // Parser generators: make_xxx function (objects) 112 /////////////////////////////////////////////////////////////////////////// 113 namespace detail 114 { 115 template <typename Positive> 116 struct make_negated_char_parser 117 { 118 typedef negated_char_parser<Positive> result_type; operator ()boost::spirit::qi::detail::make_negated_char_parser119 result_type operator()(Positive const& positive) const 120 { 121 return result_type(positive); 122 } 123 }; 124 125 template <typename Positive> 126 struct make_negated_char_parser<negated_char_parser<Positive> > 127 { 128 typedef Positive result_type; operator ()boost::spirit::qi::detail::make_negated_char_parser129 result_type operator()(negated_char_parser<Positive> const& ncp) const 130 { 131 return ncp.positive; 132 } 133 }; 134 } 135 136 template <typename Elements, typename Modifiers> 137 struct make_composite<proto::tag::complement, Elements, Modifiers> 138 { 139 typedef typename 140 fusion::result_of::value_at_c<Elements, 0>::type 141 subject; 142 143 BOOST_SPIRIT_ASSERT_MSG(( 144 traits::is_char_parser<subject>::value 145 ), subject_is_not_negatable, (subject)); 146 147 typedef typename 148 detail::make_negated_char_parser<subject>::result_type 149 result_type; 150 operator ()boost::spirit::qi::make_composite151 result_type operator()(Elements const& elements, unused_type) const 152 { 153 return detail::make_negated_char_parser<subject>()( 154 fusion::at_c<0>(elements)); 155 } 156 }; 157 }}} 158 159 #endif 160