-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsample-4.cpp
141 lines (119 loc) · 2.79 KB
/
sample-4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <iostream>
#include <string>
#include <numeric>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include "peg.hpp"
namespace fusion = boost::fusion;
using namespace peg;
using namespace std;
template<class T>
struct t : public T
{
void action(const T& t, const rep<peg::ws>&) {
*static_cast<T*>(this) = t;
}
};
template<char c, class T>
struct op_t : public T
{
void action(t<ch<c> >) {}
};
template<class T, class U>
struct op_or : public boost::function<int(int,int)>
{
typedef boost::function<int(int,int)> Base;
op_or& operator=(const Base& x) {
*static_cast<Base *>(this) = x;
return *this;
}
void action_0(const T& t) {
*this = t;
}
void action_1(const U& u) {
*this = u;
}
};
typedef op_t<'+', std::plus<int> > op_plus;
typedef op_t<'-', std::minus<int> > op_minus;
typedef op_t<'*', std::multiplies<int> > op_multiplies;
typedef op_t<'/', std::divides<int> > op_divides;
struct int_lit_s
{
int v;
void action(const replus<digit>& s) {
v = boost::lexical_cast<int>(s);
}
};
typedef t<int_lit_s> int_lit;
typedef t<ch<'('> > open_paren;
typedef t<ch<')'> > close_paren;
struct tree;
typedef boost::shared_ptr<tree> ptree;
struct tree
{
typedef ptree result_type;
virtual ~tree() {}
virtual int eval() const = 0;
};
struct binary_tree : public tree
{
boost::function<int(int,int)> op;
ptree left;
ptree right;
int eval() const { return op(left->eval(), right->eval()); }
};
template<class T, class Op>
struct left_assoc_expr : public binary_tree
{
typedef left_assoc_expr<T, Op> self_type;
struct f {
ptree operator()(const ptree e, const fusion::vector<Op, ptr<T> >& x) {
self_type *p = new self_type;
p->op = fusion::at_c<0>(x);
p->left = e;
p->right = fusion::at_c<1>(x);
return ptree(p);
}
};
static ptree action(const ptr<T>& e, const rep<fusion::vector<Op, ptr<T> > >& elist) {
return std::accumulate(elist.begin(), elist.end(), e, f());
}
};
struct primary_expr;
typedef left_assoc_expr<primary_expr, op_or<op_multiplies, op_divides> > multi_expr;
typedef left_assoc_expr<multi_expr, op_or<op_plus, op_minus> > expr;
struct primary_expr : public tree
{
int v;
int eval() const { return v; }
static ptree action_0(int_lit lit) {
primary_expr *p = new primary_expr;
p->v = lit.v;
return ptree(p);
}
static ptree action_1(open_paren, const ptr<expr>& e, close_paren) {
return e;
}
};
void test(const string& s)
{
cout << s << " ---> ";
parser<ptr<expr> > parser;
ptr<expr> e;
if (!parser.parse(e, s.begin(), s.end())) {
cout << "parse error" << endl;
} else {
cout << e->eval() << endl;
}
}
int main()
{
test("1");
test("42");
test("10 + 13");
test("10 + 20 * 3");
test("(2 + 4) * (5 - 2)");
test("2 * 4 / 8");
return 0;
}