| 1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
| 2 | // |
| 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 5 | |
| 6 | #if !defined(BOOST_SPIRIT_LEX_PLAIN_TOKENID_MASK_JUN_03_2011_0929PM) |
| 7 | #define BOOST_SPIRIT_LEX_PLAIN_TOKENID_MASK_JUN_03_2011_0929PM |
| 8 | |
| 9 | #if defined(_MSC_VER) |
| 10 | #pragma once |
| 11 | #endif |
| 12 | |
| 13 | #include <boost/spirit/home/support/info.hpp> |
| 14 | #include <boost/spirit/home/qi/detail/attributes.hpp> |
| 15 | #include <boost/spirit/home/support/common_terminals.hpp> |
| 16 | #include <boost/spirit/home/support/handles_container.hpp> |
| 17 | #include <boost/spirit/home/qi/skip_over.hpp> |
| 18 | #include <boost/spirit/home/qi/domain.hpp> |
| 19 | #include <boost/spirit/home/qi/parser.hpp> |
| 20 | #include <boost/spirit/home/qi/meta_compiler.hpp> |
| 21 | #include <boost/spirit/home/qi/detail/assign_to.hpp> |
| 22 | |
| 23 | #include <boost/fusion/include/vector.hpp> |
| 24 | #include <boost/fusion/include/at.hpp> |
| 25 | #include <boost/mpl/or.hpp> |
| 26 | #include <boost/range/iterator_range_core.hpp> |
| 27 | #include <boost/type_traits/is_integral.hpp> |
| 28 | #include <boost/type_traits/is_enum.hpp> |
| 29 | #include <iterator> // for std::iterator_traits |
| 30 | #include <sstream> |
| 31 | |
| 32 | namespace boost { namespace spirit |
| 33 | { |
| 34 | /////////////////////////////////////////////////////////////////////////// |
| 35 | // Enablers |
| 36 | /////////////////////////////////////////////////////////////////////////// |
| 37 | |
| 38 | // enables tokenid_mask(id) |
| 39 | template <typename A0> |
| 40 | struct use_terminal<qi::domain |
| 41 | , terminal_ex<tag::tokenid_mask, fusion::vector1<A0> > |
| 42 | > : mpl::or_<is_integral<A0>, is_enum<A0> > {}; |
| 43 | |
| 44 | // enables *lazy* tokenid_mask(id) |
| 45 | template <> |
| 46 | struct use_lazy_terminal< |
| 47 | qi::domain, tag::tokenid_mask, 1 |
| 48 | > : mpl::true_ {}; |
| 49 | }} |
| 50 | |
| 51 | namespace boost { namespace spirit { namespace qi |
| 52 | { |
| 53 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS |
| 54 | using spirit::tokenid_mask; |
| 55 | #endif |
| 56 | using spirit::tokenid_mask_type; |
| 57 | |
| 58 | /////////////////////////////////////////////////////////////////////////// |
| 59 | // The plain_tokenid represents a simple token defined by the lexer inside |
| 60 | // a Qi grammar. The difference to plain_token is that it exposes the |
| 61 | // matched token id instead of the iterator_range of the matched input. |
| 62 | // Additionally it applies the given mask to the matched token id. |
| 63 | template <typename Mask> |
| 64 | struct plain_tokenid_mask |
| 65 | : primitive_parser<plain_tokenid_mask<Mask> > |
| 66 | { |
| 67 | template <typename Context, typename Iterator> |
| 68 | struct attribute |
| 69 | { |
| 70 | typedef Mask type; |
| 71 | }; |
| 72 | |
| 73 | plain_tokenid_mask(Mask const& mask) |
| 74 | : mask(mask) {} |
| 75 | |
| 76 | template <typename Iterator, typename Context |
| 77 | , typename Skipper, typename Attribute> |
| 78 | bool parse(Iterator& first, Iterator const& last |
| 79 | , Context& /*context*/, Skipper const& skipper |
| 80 | , Attribute& attr) const |
| 81 | { |
| 82 | qi::skip_over(first, last, skipper); // always do a pre-skip |
| 83 | |
| 84 | if (first != last) { |
| 85 | // simply match the token id with the mask this component has |
| 86 | // been initialized with |
| 87 | |
| 88 | typedef typename |
| 89 | std::iterator_traits<Iterator>::value_type |
| 90 | token_type; |
| 91 | typedef typename token_type::id_type id_type; |
| 92 | |
| 93 | token_type const& t = *first; |
| 94 | if ((t.id() & mask) == id_type(mask)) |
| 95 | { |
| 96 | spirit::traits::assign_to(t.id(), attr); |
| 97 | ++first; |
| 98 | return true; |
| 99 | } |
| 100 | } |
| 101 | return false; |
| 102 | } |
| 103 | |
| 104 | template <typename Context> |
| 105 | info what(Context& /*context*/) const |
| 106 | { |
| 107 | std::stringstream ss; |
| 108 | ss << "tokenid_mask(" << mask << ")" ; |
| 109 | return info("tokenid_mask" , ss.str()); |
| 110 | } |
| 111 | |
| 112 | Mask mask; |
| 113 | }; |
| 114 | |
| 115 | /////////////////////////////////////////////////////////////////////////// |
| 116 | // Parser generators: make_xxx function (objects) |
| 117 | /////////////////////////////////////////////////////////////////////////// |
| 118 | template <typename Modifiers, typename Mask> |
| 119 | struct make_primitive<terminal_ex<tag::tokenid_mask, fusion::vector1<Mask> > |
| 120 | , Modifiers> |
| 121 | { |
| 122 | typedef plain_tokenid_mask<Mask> result_type; |
| 123 | |
| 124 | template <typename Terminal> |
| 125 | result_type operator()(Terminal const& term, unused_type) const |
| 126 | { |
| 127 | return result_type(fusion::at_c<0>(term.args)); |
| 128 | } |
| 129 | }; |
| 130 | }}} |
| 131 | |
| 132 | namespace boost { namespace spirit { namespace traits |
| 133 | { |
| 134 | /////////////////////////////////////////////////////////////////////////// |
| 135 | template<typename Mask, typename Attr, typename Context, typename Iterator> |
| 136 | struct handles_container<qi::plain_tokenid_mask<Mask>, Attr, Context, Iterator> |
| 137 | : mpl::true_ |
| 138 | {}; |
| 139 | }}} |
| 140 | |
| 141 | #endif |
| 142 | |