-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse_expr.cpp
117 lines (98 loc) · 2.61 KB
/
parse_expr.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
#include "hspp.h"
#include "parser.h"
#include <cassert>
#include "common.h"
using namespace hspp;
using namespace hspp::parser;
using namespace hspp::doN;
using namespace std::literals;
enum class Op
{
kADD,
kSUB,
kMUL,
kDIV
};
class OpFunc
{
Op mOp;
public:
constexpr OpFunc(Op op)
: mOp{op}
{}
template <typename T>
constexpr auto operator()(T x, T y) const
{
switch (mOp)
{
case Op::kADD: return x + y;
case Op::kSUB: return x - y;
case Op::kMUL: return x * y;
case Op::kDIV: return x / y;
}
throw std::runtime_error{"Never reach here!"};
}
};
namespace op
{
constexpr auto add = toGFunc<2> | OpFunc{Op::kADD};
constexpr auto sub = toGFunc<2> | OpFunc{Op::kSUB};
constexpr auto mul = toGFunc<2> | OpFunc{Op::kMUL};
constexpr auto div = toGFunc<2> | OpFunc{Op::kDIV};
static_assert((add | 1 | 2) == 3);
static_assert((sub | 1 | 2) == -1);
static_assert((mul | 1 | 2) == 2);
static_assert((div | 4 | 2) == 2);
auto const addOp = do_(symb | "+", return_ | add) <alt> do_(symb | "-", return_ | sub);
auto const mulOp = do_(symb | "*", return_ | mul) <alt> do_(symb | "/", return_ | div);
} // namespace op
using op::addOp;
using op::mulOp;
constexpr auto isDigit = toFunc<> | [](char x)
{
return isdigit(x);
};
Id<char> x;
auto const digit = do_(
x <= (token || sat | isDigit),
return_ | (x - '0')
);
extern TEParser<int> const expr;
Id<int> n;
auto const factor =
digit <alt>
do_(
symb | "("s,
n <= expr,
symb | ")"s,
return_ | n
);
auto const term = factor <chainl1> mulOp;
TEParser<int> const expr = toTEParser || (term <chainl1> addOp);
int main()
{
{
auto const rawResult = apply || many | digit || " 1 2 34";
auto const& result = std::get<0>(rawResult.at(0));
auto const expected = std::vector{1, 2, 3, 4};
expectTrue(std::equal(result.begin(), result.end(), expected.begin()));
}
{
auto const result = apply || addOp || " + * /-";
expectEq(std::get<0>(result.at(0))| 1 | 2, 3);
auto const result2 = apply || mulOp || " * /-";
expectEq(std::get<0>(result2.at(0))| 1 | 2, 2);
}
{
auto const p = digit <chainl1> addOp;
auto const result = runParser | p | "1 + 2";
auto const expected = 3;
expectEq(std::get<0>(result.at(0)), expected);
}
{
auto const result = apply | expr | "1 - 2 * 3 + 4";
auto const expected = -1;
expectEq(std::get<0>(result.at(0)), expected);
}
return 0;
}