• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright (c) 2011 Aaron Graham
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_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM)
7 #define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM
8 
9 #include <boost/spirit/home/support/terminal.hpp>
10 #include <boost/spirit/include/qi_parse.hpp>
11 
12 ///////////////////////////////////////////////////////////////////////////////
13 // definition the place holder
14 namespace boost { namespace spirit { namespace repository { namespace qi
15 {
16     BOOST_SPIRIT_TERMINAL_EX(advance)
17 }}}}
18 
19 ///////////////////////////////////////////////////////////////////////////////
20 // implementation the enabler
21 namespace boost { namespace spirit
22 {
23     template <typename A0>
24     struct use_terminal<qi::domain
25       , terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > >
26       : mpl::or_<is_integral<A0>, is_enum<A0> >
27     {};
28 
29     template <>
30     struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1>
31       : mpl::true_
32     {};
33 }}
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // implementation of the parser
37 namespace boost { namespace spirit { namespace repository { namespace qi
38 {
39     template <typename Int>
40     struct advance_parser
41       : boost::spirit::qi::primitive_parser< advance_parser<Int> >
42     {
43         // Define the attribute type exposed by this parser component
44         template <typename Context, typename Iterator>
45         struct attribute
46         {
47             typedef boost::spirit::unused_type type;
48         };
49 
advance_parserboost::spirit::repository::qi::advance_parser50         advance_parser(Int dist)
51           : dist(dist)
52         {}
53 
54         // This function is called during the actual parsing process
55         template <typename Iterator, typename Context
56             , typename Skipper, typename Attribute>
parseboost::spirit::repository::qi::advance_parser57         bool parse(Iterator& first, Iterator const& last
58             , Context&, Skipper&, Attribute&) const
59         {
60             // This series of checks is designed to fail parsing on negative
61             // values, without generating a "expression always evaluates true"
62             // warning on unsigned types.
63             if (dist == Int(0)) return true;
64             if (dist < Int(1)) return false;
65 
66             typedef typename std::iterator_traits<Iterator>::iterator_category
67                 iterator_category;
68             return advance(first, last, iterator_category());
69         }
70 
71         // This function is called during error handling to create
72         // a human readable string for the error context.
73         template <typename Context>
whatboost::spirit::repository::qi::advance_parser74         boost::spirit::info what(Context&) const
75         {
76             return boost::spirit::info("advance");
77         }
78 
79     private:
80         // this is the general implementation used by most iterator categories
81         template <typename Iterator, typename IteratorCategory>
advanceboost::spirit::repository::qi::advance_parser82         bool advance(Iterator& first, Iterator const& last
83             , IteratorCategory) const
84         {
85             Int n = dist;
86             Iterator i = first;
87             while (n)
88             {
89                 if (i == last) return false;
90                 ++i;
91                 --n;
92             }
93             first = i;
94             return true;
95         }
96 
97         // this is a specialization for random access iterators
98         template <typename Iterator>
advanceboost::spirit::repository::qi::advance_parser99         bool advance(Iterator& first, Iterator const& last
100             , std::random_access_iterator_tag) const
101         {
102             Iterator const it = first + dist;
103             if (it > last) return false;
104             first = it;
105             return true;
106         }
107 
108         Int const dist;
109     };
110 }}}}
111 
112 ///////////////////////////////////////////////////////////////////////////////
113 // instantiation of the parser
114 namespace boost { namespace spirit { namespace qi
115 {
116     template <typename Modifiers, typename A0>
117     struct make_primitive<
118           terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> >
119         , Modifiers>
120     {
121         typedef repository::qi::advance_parser<A0> result_type;
122 
123         template <typename Terminal>
operator ()boost::spirit::qi::make_primitive124         result_type operator()(Terminal const& term, unused_type) const
125         {
126             return result_type(fusion::at_c<0>(term.args));
127         }
128     };
129 }}}
130 
131 #endif
132