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)
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/foldr_start_with_parser.hpp>
16 #include <boost/metaparse/one_of.hpp>
17 #include <boost/metaparse/get_result.hpp>
18 #include <boost/metaparse/token.hpp>
19 #include <boost/metaparse/entire_input.hpp>
20 #include <boost/metaparse/string.hpp>
21 #include <boost/metaparse/build_parser.hpp>
23 #include <boost/mpl/apply_wrap.hpp>
24 #include <boost/mpl/fold.hpp>
25 #include <boost/mpl/front.hpp>
26 #include <boost/mpl/back.hpp>
27 #include <boost/mpl/plus.hpp>
28 #include <boost/mpl/minus.hpp>
29 #include <boost/mpl/times.hpp>
30 #include <boost/mpl/divides.hpp>
31 #include <boost/mpl/bool.hpp>
32 #include <boost/mpl/equal_to.hpp>
33 #include <boost/mpl/eval_if.hpp>
34 #include <boost/mpl/bool.hpp>
35 #include <boost/mpl/negate.hpp>
36 #include <boost/mpl/char.hpp>
38 using boost::metaparse::sequence
;
39 using boost::metaparse::lit_c
;
40 using boost::metaparse::last_of
;
41 using boost::metaparse::first_of
;
42 using boost::metaparse::middle_of
;
43 using boost::metaparse::space
;
44 using boost::metaparse::repeated
;
45 using boost::metaparse::build_parser
;
46 using boost::metaparse::int_
;
47 using boost::metaparse::foldl_reject_incomplete_start_with_parser
;
48 using boost::metaparse::foldr_start_with_parser
;
49 using boost::metaparse::get_result
;
50 using boost::metaparse::one_of
;
51 using boost::metaparse::token
;
52 using boost::metaparse::entire_input
;
54 using boost::mpl::apply_wrap1
;
55 using boost::mpl::fold
;
56 using boost::mpl::front
;
57 using boost::mpl::back
;
58 using boost::mpl::plus
;
59 using boost::mpl::minus
;
60 using boost::mpl::times
;
61 using boost::mpl::divides
;
62 using boost::mpl::eval_if
;
63 using boost::mpl::bool_
;
64 using boost::mpl::equal_to
;
65 using boost::mpl::bool_
;
66 using boost::mpl::negate
;
67 using boost::mpl::char_
;
72 * expression ::= plus_exp
73 * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*
74 * prod_exp ::= int_token ((mult_token | div_token) simple_exp)*
75 * simple_exp ::= (plus_token | minus_token)* (int_token | paren_exp)
76 * paren_exp ::= open_paren_token expression close_paren_token
79 typedef token
<lit_c
<'+'> > plus_token
;
80 typedef token
<lit_c
<'-'> > minus_token
;
81 typedef token
<lit_c
<'*'> > mult_token
;
82 typedef token
<lit_c
<'/'> > div_token
;
84 typedef token
<lit_c
<'('> > open_paren_token
;
85 typedef token
<lit_c
<')'> > close_paren_token
;
87 typedef token
<int_
> int_token
;
89 template <class T
, char C
>
90 struct is_c
: bool_
<T::type::value
== C
> {};
94 template <class State
, class C
>
98 plus
<typename
State::type
, typename back
<C
>::type
>,
99 minus
<typename
State::type
, typename back
<C
>::type
>
106 template <class State
, class C
>
110 times
<typename
State::type
, typename back
<C
>::type
>,
111 divides
<typename
State::type
, typename back
<C
>::type
>
116 struct eval_unary_plus
118 template <class State
, class C
>
121 typename equal_to
<char_
<'+'>, typename
C::type
>::type
,
122 State
, // +State is State
123 negate
<typename
State::type
>
130 typedef middle_of
<open_paren_token
, plus_exp
, close_paren_token
> paren_exp
;
133 foldr_start_with_parser
<
134 one_of
<plus_token
, minus_token
>,
135 one_of
<int_token
, paren_exp
>,
141 foldl_reject_incomplete_start_with_parser
<
142 sequence
<one_of
<mult_token
, div_token
>, simple_exp
>,
149 foldl_reject_incomplete_start_with_parser
<
150 sequence
<one_of
<plus_token
, minus_token
>, prod_exp
>,
156 typedef last_of
<repeated
<space
>, plus_exp
> expression
;
158 typedef build_parser
<entire_input
<expression
> > calculator_parser
;
161 # error _STR already defined
163 #define _STR BOOST_METAPARSE_STRING
165 #if BOOST_METAPARSE_STD < 2011
168 std::cout
<< "Please use a compiler that support constexpr" << std::endl
;
177 << apply_wrap1
<calculator_parser
, _STR("13")>::type::value
<< endl
178 << apply_wrap1
<calculator_parser
, _STR(" 1+ 2*4-6/2")>::type::value
<< endl
179 << apply_wrap1
<calculator_parser
, _STR("1+2*3+4")>::type::value
<< endl
180 << apply_wrap1
<calculator_parser
, _STR("(1+2)*(3+4)")>::type::value
<< endl
181 << apply_wrap1
<calculator_parser
, _STR("(2*3)+(4*5)")>::type::value
<< endl
182 << apply_wrap1
<calculator_parser
, _STR("2 * 3 + 4")>::type::value
<< endl
183 << apply_wrap1
<calculator_parser
, _STR("2 + (3 * 4)")>::type::value
<< endl
184 << apply_wrap1
<calculator_parser
, _STR("+3")>::type::value
<< endl
185 << apply_wrap1
<calculator_parser
, _STR("-21")>::type::value
<< endl
186 << apply_wrap1
<calculator_parser
, _STR("24 + - 21")>::type::value
<< endl
187 << apply_wrap1
<calculator_parser
, _STR("- - 21")>::type::value
<< endl
188 << apply_wrap1
<calculator_parser
, _STR("-(3 * 4)")>::type::value
<< endl