• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Abel Sinkovics (abel@sinkovics.hu)  2011.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/metaparse/repeated.hpp>
7 #include <boost/metaparse/sequence.hpp>
8 #include <boost/metaparse/lit_c.hpp>
9 #include <boost/metaparse/last_of.hpp>
10 #include <boost/metaparse/first_of.hpp>
11 #include <boost/metaparse/space.hpp>
12 #include <boost/metaparse/int_.hpp>
13 #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
14 #include <boost/metaparse/one_of.hpp>
15 #include <boost/metaparse/get_result.hpp>
16 #include <boost/metaparse/token.hpp>
17 #include <boost/metaparse/entire_input.hpp>
18 #include <boost/metaparse/string.hpp>
19 #include <boost/metaparse/build_parser.hpp>
20 
21 #include <boost/mpl/apply_wrap.hpp>
22 #include <boost/mpl/fold.hpp>
23 #include <boost/mpl/front.hpp>
24 #include <boost/mpl/back.hpp>
25 #include <boost/mpl/plus.hpp>
26 #include <boost/mpl/minus.hpp>
27 #include <boost/mpl/times.hpp>
28 #include <boost/mpl/divides.hpp>
29 #include <boost/mpl/bool.hpp>
30 #include <boost/mpl/equal_to.hpp>
31 #include <boost/mpl/eval_if.hpp>
32 #include <boost/mpl/bool.hpp>
33 
34 using boost::metaparse::sequence;
35 using boost::metaparse::lit_c;
36 using boost::metaparse::last_of;
37 using boost::metaparse::first_of;
38 using boost::metaparse::space;
39 using boost::metaparse::repeated;
40 using boost::metaparse::build_parser;
41 using boost::metaparse::int_;
42 using boost::metaparse::foldl_reject_incomplete_start_with_parser;
43 using boost::metaparse::get_result;
44 using boost::metaparse::one_of;
45 using boost::metaparse::token;
46 using boost::metaparse::entire_input;
47 
48 using boost::mpl::apply_wrap1;
49 using boost::mpl::fold;
50 using boost::mpl::front;
51 using boost::mpl::back;
52 using boost::mpl::plus;
53 using boost::mpl::minus;
54 using boost::mpl::times;
55 using boost::mpl::divides;
56 using boost::mpl::eval_if;
57 using boost::mpl::bool_;
58 using boost::mpl::equal_to;
59 using boost::mpl::bool_;
60 
61 /*
62  * The grammar
63  *
64  * expression ::= plus_exp
65  * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*
66  * prod_exp ::= int_token ((mult_token | div_token) int_token)*
67  */
68 
69 typedef token<lit_c<'+'> > plus_token;
70 typedef token<lit_c<'-'> > minus_token;
71 typedef token<lit_c<'*'> > mult_token;
72 typedef token<lit_c<'/'> > div_token;
73 
74 typedef token<int_> int_token;
75 
76 template <class T, char C>
77 struct is_c : bool_<T::type::value == C> {};
78 
79 struct eval_plus
80 {
81   template <class State, class C>
82   struct apply :
83     eval_if<
84       is_c<front<C>, '+'>,
85       plus<typename State::type, typename back<C>::type>,
86       minus<typename State::type, typename back<C>::type>
87     >
88   {};
89 };
90 
91 struct eval_mult
92 {
93   template <class State, class C>
94   struct apply :
95     eval_if<
96       is_c<front<C>, '*'>,
97       times<typename State::type, typename back<C>::type>,
98       divides<typename State::type, typename back<C>::type>
99     >
100   {};
101 };
102 
103 typedef
104   foldl_reject_incomplete_start_with_parser<
105     sequence<one_of<mult_token, div_token>, int_token>,
106     int_token,
107     eval_mult
108   >
109   prod_exp;
110 
111 typedef
112   foldl_reject_incomplete_start_with_parser<
113     sequence<one_of<plus_token, minus_token>, prod_exp>,
114     prod_exp,
115     eval_plus
116   >
117   plus_exp;
118 
119 typedef last_of<repeated<space>, plus_exp> expression;
120 
121 typedef build_parser<entire_input<expression> > calculator_parser;
122 
123 #ifdef _STR
124 #  error _STR already defined
125 #endif
126 #define _STR BOOST_METAPARSE_STRING
127 
128 #if BOOST_METAPARSE_STD < 2011
main()129 int main()
130 {
131   using std::cout;
132   using std::endl;
133   using boost::metaparse::string;
134 
135   cout
136     << apply_wrap1<calculator_parser, string<'1','3'> >::type::value << endl
137     <<
138       apply_wrap1<
139         calculator_parser, string<' ','1','+',' ','2','*','4','-','6','/','2'>
140       >::type::value
141     << endl
142     ;
143 }
144 #else
main()145 int main()
146 {
147   using std::cout;
148   using std::endl;
149 
150   cout
151     << apply_wrap1<calculator_parser, _STR("13")>::type::value << endl
152     << apply_wrap1<calculator_parser, _STR(" 1+ 2*4-6/2")>::type::value << endl
153     ;
154 }
155 #endif
156 
157 
158