]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/config.hpp> | |
7 | ||
b32b8144 | 8 | #if BOOST_METAPARSE_STD < 2011 |
7c673cae FG |
9 | #include <iostream> |
10 | ||
11 | int main() | |
12 | { | |
13 | std::cout << "Please use a compiler that supports constexpr" << std::endl; | |
14 | } | |
15 | #else | |
16 | ||
17 | #define BOOST_MPL_LIMIT_STRING_SIZE 64 | |
18 | #define BOOST_METAPARSE_LIMIT_STRING_SIZE BOOST_MPL_LIMIT_STRING_SIZE | |
19 | ||
20 | #include <boost/metaparse/grammar.hpp> | |
21 | #include <boost/metaparse/entire_input.hpp> | |
22 | #include <boost/metaparse/build_parser.hpp> | |
23 | #include <boost/metaparse/token.hpp> | |
24 | #include <boost/metaparse/string.hpp> | |
25 | #include <boost/metaparse/util/digit_to_int.hpp> | |
26 | ||
27 | #include <boost/mpl/apply_wrap.hpp> | |
28 | #include <boost/mpl/fold.hpp> | |
29 | #include <boost/mpl/front.hpp> | |
30 | #include <boost/mpl/back.hpp> | |
31 | #include <boost/mpl/plus.hpp> | |
32 | #include <boost/mpl/minus.hpp> | |
33 | #include <boost/mpl/times.hpp> | |
34 | #include <boost/mpl/divides.hpp> | |
35 | #include <boost/mpl/equal_to.hpp> | |
36 | #include <boost/mpl/eval_if.hpp> | |
37 | #include <boost/mpl/lambda.hpp> | |
38 | #include <boost/mpl/char.hpp> | |
39 | #include <boost/mpl/int.hpp> | |
40 | ||
41 | using boost::metaparse::build_parser; | |
42 | using boost::metaparse::entire_input; | |
43 | using boost::metaparse::token; | |
44 | using boost::metaparse::grammar; | |
45 | ||
46 | using boost::metaparse::util::digit_to_int; | |
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::equal_to; | |
58 | using boost::mpl::_1; | |
59 | using boost::mpl::_2; | |
60 | using boost::mpl::char_; | |
61 | using boost::mpl::lambda; | |
62 | using boost::mpl::int_; | |
63 | ||
64 | #ifdef _STR | |
65 | #error _STR already defined | |
66 | #endif | |
67 | #define _STR BOOST_METAPARSE_STRING | |
68 | ||
69 | template <class A, class B> | |
70 | struct lazy_plus : plus<typename A::type, typename B::type> {}; | |
71 | ||
72 | template <class A, class B> | |
73 | struct lazy_minus : minus<typename A::type, typename B::type> {}; | |
74 | ||
75 | template <class A, class B> | |
76 | struct lazy_times : times<typename A::type, typename B::type> {}; | |
77 | ||
78 | template <class A, class B> | |
79 | struct lazy_divides : divides<typename A::type, typename B::type> {}; | |
80 | ||
81 | template <class C, class T, class F> | |
82 | struct lazy_eval_if : eval_if<typename C::type, T, F> {}; | |
83 | ||
84 | template <class A, class B> | |
85 | struct lazy_equal_to : equal_to<typename A::type, typename B::type> {}; | |
86 | ||
87 | template <class Sequence, class State, class ForwardOp> | |
88 | struct lazy_fold : | |
89 | fold<typename Sequence::type, typename State::type, typename ForwardOp::type> | |
90 | {}; | |
91 | ||
92 | typedef | |
93 | lazy_fold< | |
94 | back<_1>, | |
95 | front<_1>, | |
96 | lambda< | |
97 | lazy_eval_if< | |
98 | lazy_equal_to<front<_2>, char_<'*'>>, | |
99 | lazy_times<_1, back<_2>>, | |
100 | lazy_divides<_1, back<_2>> | |
101 | > | |
102 | >::type | |
103 | > | |
104 | prod_action; | |
105 | ||
106 | typedef | |
107 | lazy_fold< | |
108 | back<_1>, | |
109 | front<_1>, | |
110 | lambda< | |
111 | lazy_eval_if< | |
112 | lazy_equal_to<front<_2>, char_<'+'>>, | |
113 | lazy_plus<_1, back<_2>>, | |
114 | lazy_minus<_1, back<_2>> | |
115 | > | |
116 | >::type | |
117 | > | |
118 | plus_action; | |
119 | ||
120 | typedef | |
121 | lambda< | |
122 | lazy_fold< | |
123 | _1, | |
124 | int_<0>, | |
125 | lambda< | |
126 | lazy_plus<lazy_times<_1, int_<10>>, apply_wrap1<digit_to_int<>, _2>> | |
127 | >::type | |
128 | > | |
129 | >::type | |
130 | int_action; | |
131 | ||
132 | typedef | |
133 | grammar<_STR("plus_exp")> | |
134 | ||
135 | ::rule<_STR("int ::= ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')+"), int_action>::type | |
136 | ::rule<_STR("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type | |
137 | ::rule<_STR("int_token ::= int ws"), front<_1>>::type | |
138 | ::rule<_STR("plus_token ::= '+' ws"), front<_1>>::type | |
139 | ::rule<_STR("minus_token ::= '-' ws"), front<_1>>::type | |
140 | ::rule<_STR("mult_token ::= '*' ws"), front<_1>>::type | |
141 | ::rule<_STR("div_token ::= '/' ws"), front<_1>>::type | |
142 | ::rule<_STR("plus_token ::= '+' ws")>::type | |
143 | ::rule<_STR("plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*"), plus_action>::type | |
144 | ::rule<_STR("prod_exp ::= int_token ((mult_token | div_token) int_token)*"), prod_action>::type | |
145 | expression; | |
146 | ||
147 | typedef build_parser<entire_input<expression>> calculator_parser; | |
148 | ||
149 | int main() | |
150 | { | |
151 | using std::cout; | |
152 | using std::endl; | |
153 | ||
154 | cout | |
155 | << apply_wrap1<calculator_parser, _STR("13")>::type::value << endl | |
156 | << apply_wrap1<calculator_parser, _STR("1+ 2*4-6/2")>::type::value << endl | |
157 | ; | |
158 | } | |
159 | #endif | |
160 |