]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
b32b8144 | 141 | #if BOOST_METAPARSE_STD < 2011 |
7c673cae FG |
142 | int main() |
143 | { | |
144 | std::cout << "Please use a compiler that support constexpr" << std::endl; | |
145 | } | |
146 | #else | |
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 |