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