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