• 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/config.hpp>
7 
8 #if BOOST_METAPARSE_STD < 2011
9 #include <iostream>
10 
main()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 
main()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 
161