-
Notifications
You must be signed in to change notification settings - Fork 0
/
BFParser.h
135 lines (118 loc) · 5.98 KB
/
BFParser.h
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
// 2020 by Stephan Roslen
#ifndef _BFTMP__BFPARSER_H_
#define _BFTMP__BFPARSER_H_
#include <boost/hana.hpp>
#include "BFExpression.h"
#include "BFMachine.h"
namespace bf::parser {
template<typename TInput, typename TAdd>
static constexpr auto parseAddExpression(TInput input, TAdd add) {
namespace hana = boost::hana;
if constexpr (hana::is_empty(input)) {
return hana::make_tuple(input, hana::type_c<bf::expression::Add<static_cast<Machine::SignedElemType>(add)>>);
} else {
auto input0 = hana::at_c<0>(input);
[[maybe_unused]] auto inputResidual = hana::drop_front(input);
if constexpr (input0 == hana::char_c<'+'>) {
return parseAddExpression(inputResidual, add + hana::int_c<1>);
} else if constexpr (input0 == hana::char_c<'-'>) {
return parseAddExpression(inputResidual, add + hana::int_c<-1>);
} else if constexpr (hana::contains(BOOST_HANA_STRING(".,<>[]"), input0)) {
return hana::make_tuple(input, hana::type_c<bf::expression::Add<static_cast<Machine::SignedElemType>(add)>>);
} else {
return parseAddExpression(inputResidual, add);
}
}
}
template<typename TInput, typename TMove>
static constexpr auto parseMoveExpression(TInput input, TMove move) {
namespace hana = boost::hana;
if constexpr (hana::is_empty(input)) {
return hana::make_tuple(input, hana::type_c<bf::expression::Move<static_cast<Machine::SignedIdxType>(move)>>);
} else {
auto input0 = hana::at_c<0>(input);
[[maybe_unused]] auto inputResidual = hana::drop_front(input);
if constexpr (input0 == hana::char_c<'<'>) {
return parseMoveExpression(inputResidual, move + hana::int_c<-1>);
} else if constexpr (input0 == hana::char_c<'>'>) {
return parseMoveExpression(inputResidual, move + hana::int_c<1>);
} else if constexpr (hana::contains(BOOST_HANA_STRING("+-.,[]"), input0)) {
return hana::make_tuple(input, hana::type_c<bf::expression::Move<static_cast<Machine::SignedIdxType>(move)>>);
} else {
return parseMoveExpression(inputResidual, move);
}
}
}
template<typename TInput, typename TExpression>
static constexpr auto parseExpression(TInput input, TExpression expression) {
namespace hana = boost::hana;
if constexpr (hana::is_empty(input)) {
return hana::make_tuple(input, expression);
} else {
auto input0 = hana::at_c<0>(input);
auto inputResidual = hana::drop_front(input);
if constexpr (input0 == hana::char_c<'+'>) {
auto result = parseAddExpression(inputResidual, hana::int_c<1>);
auto inputResidualResult = hana::at_c<0>(result);
auto addExpressionResult = hana::at_c<1>(result);
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<
typename decltype(addExpressionResult)::type>>;
return parseExpression(inputResidualResult, newExpression);
} else if constexpr (input0 == hana::char_c<'-'>) {
auto result = parseAddExpression(inputResidual, hana::int_c<-1>);
auto inputResidualResult = hana::at_c<0>(result);
auto addExpressionResult = hana::at_c<1>(result);
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<
typename decltype(addExpressionResult)::type>>;
return parseExpression(inputResidualResult, newExpression);
} else if constexpr (input0 == hana::char_c<','>) {
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<bf::expression::Read>>;
return parseExpression(inputResidual, newExpression);
} else if constexpr (input0 == hana::char_c<'.'>) {
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<bf::expression::Write>>;
return parseExpression(inputResidual, newExpression);
} else if constexpr (input0 == hana::char_c<'<'>) {
auto result = parseMoveExpression(inputResidual, hana::int_c<-1>);
auto inputResidualResult = hana::at_c<0>(result);
auto moveExpressionResult = hana::at_c<1>(result);
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<
typename decltype(moveExpressionResult)::type>>;
return parseExpression(inputResidualResult, newExpression);
} else if constexpr (input0 == hana::char_c<'>'>) {
auto result = parseMoveExpression(inputResidual, hana::int_c<1>);
auto inputResidualResult = hana::at_c<0>(result);
auto moveExpressionResult = hana::at_c<1>(result);
auto newExpression = hana::type_c<typename decltype(expression)::type::template AppendT<
typename decltype(moveExpressionResult)::type>>;
return parseExpression(inputResidualResult, newExpression);
} else if constexpr (input0 == hana::char_c<'['>) {
// Parse the loop body into new expression
auto emptyExpression = hana::type_c<bf::expression::Expression<>>;
auto result = parseExpression(inputResidual, emptyExpression);
auto inputResidualResult = hana::at_c<0>(result);
auto expressionResult = hana::at_c<1>(result);
// Wrap the expression
auto loopExpressionResult = hana::type_c<bf::expression::Loop<typename decltype(expressionResult)::type>>;
// Concat
auto newExpression = hana::type_c<
typename decltype(expression)::type::template AppendT<typename decltype(loopExpressionResult)::type>>;
// Continue parsing
return parseExpression(inputResidualResult, newExpression);
} else if constexpr (input0 == hana::char_c<']'>) {
// Return and don't continue parsing - '[' opened a nested parser which is closed here
return hana::make_tuple(inputResidual, expression);
} else {
// Ignore everything else
return parseExpression(inputResidual, expression);
}
}
};
template<typename TInput>
static constexpr auto parse(TInput &&input) {
namespace hana = boost::hana;
auto empty_expression = hana::type_c<bf::expression::Expression<>>;
auto result = parseExpression(input, empty_expression);
return hana::at_c<1>(result);
};
}// namespace bf::parser
#endif// _BFTMP__BFPARSER_H_