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(SPIRIT_DIFFERENCE_FEBRUARY_11_2007_1250PM) 8 #define SPIRIT_DIFFERENCE_FEBRUARY_11_2007_1250PM 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/meta_compiler.hpp> 16 #include <boost/spirit/home/qi/parser.hpp> 17 #include <boost/spirit/home/qi/detail/attributes.hpp> 18 #include <boost/spirit/home/support/info.hpp> 19 #include <boost/spirit/home/support/has_semantic_action.hpp> 20 #include <boost/spirit/home/support/handles_container.hpp> 21 #include <boost/fusion/include/at.hpp> 22 23 namespace boost { namespace spirit 24 { 25 /////////////////////////////////////////////////////////////////////////// 26 // Enablers 27 /////////////////////////////////////////////////////////////////////////// 28 template <> 29 struct use_operator<qi::domain, proto::tag::minus> // enables - 30 : mpl::true_ {}; 31 }} 32 33 namespace boost { namespace spirit { namespace qi 34 { 35 template <typename Left, typename Right> 36 struct difference : binary_parser<difference<Left, Right> > 37 { 38 typedef Left left_type; 39 typedef Right right_type; 40 41 template <typename Context, typename Iterator> 42 struct attribute 43 { 44 typedef typename 45 traits::attribute_of<left_type, Context, Iterator>::type 46 type; 47 }; 48 differenceboost::spirit::qi::difference49 difference(Left const& left_, Right const& right_) 50 : left(left_), right(right_) {} 51 52 template <typename Iterator, typename Context 53 , typename Skipper, typename Attribute> parseboost::spirit::qi::difference54 bool parse(Iterator& first, Iterator const& last 55 , Context& context, Skipper const& skipper 56 , Attribute& attr_) const 57 { 58 // Unlike classic Spirit, with this version of difference, the rule 59 // lit("policeman") - "police" will always fail to match. 60 61 // Spirit2 does not count the matching chars while parsing and 62 // there is no reliable and fast way to check if the LHS matches 63 // more than the RHS. 64 65 // Try RHS first 66 Iterator start = first; 67 if (right.parse(first, last, context, skipper, unused)) 68 { 69 // RHS succeeds, we fail. 70 first = start; 71 return false; 72 } 73 // RHS fails, now try LHS 74 return left.parse(first, last, context, skipper, attr_); 75 } 76 77 template <typename Context> whatboost::spirit::qi::difference78 info what(Context& context) const 79 { 80 return info("difference", 81 std::make_pair(left.what(context), right.what(context))); 82 } 83 84 Left left; 85 Right right; 86 }; 87 88 /////////////////////////////////////////////////////////////////////////// 89 // Parser generators: make_xxx function (objects) 90 /////////////////////////////////////////////////////////////////////////// 91 template <typename Elements, typename Modifiers> 92 struct make_composite<proto::tag::minus, Elements, Modifiers> 93 : make_binary_composite<Elements, difference> 94 {}; 95 }}} 96 97 namespace boost { namespace spirit { namespace traits 98 { 99 /////////////////////////////////////////////////////////////////////////// 100 template <typename Left, typename Right> 101 struct has_semantic_action<qi::difference<Left, Right> > 102 : binary_has_semantic_action<Left, Right> {}; 103 104 /////////////////////////////////////////////////////////////////////////// 105 template <typename Left, typename Right, typename Attribute 106 , typename Context, typename Iterator> 107 struct handles_container<qi::difference<Left, Right>, Attribute, Context 108 , Iterator> 109 : binary_handles_container<Left, Right, Attribute, Context, Iterator> {}; 110 }}} 111 112 #endif 113