14 _depends(), _atomics(), _operations() {
18 _evaluated(false), _result(), _literalConstant(false),
19 _depends(), _atomics(), _operations() {
20 parse(expression, lineSymbol);
25 expr._evaluated =
true;
27 expr._atomics.emplace_back(
Atomic(AtomicType::INTEGER, value.value));
33 expr._atomics.emplace_back(
Atomic(AtomicType::SYMBOL, symbol));
34 expr._depends.insert(symbol);
40 expr._atomics = {
Atomic(AtomicType::SYMBOL, symbol),
Atomic(AtomicType::INTEGER, offset)};
41 expr._operations = {Operation::ADD};
42 expr._depends.insert(symbol);
47 return isalnum(ch) || ch ==
'+' || ch ==
'-' || ch ==
'*' || ch ==
'=';
86 return ch ==
'+' || ch ==
'-' || ch ==
'*' || ch ==
'/' || ch ==
':';
91 const char END_CHAR =
'#';
92 const int INIT_INDEX = -1;
94 int lastAtomicStart = INIT_INDEX;
95 int lastOperationStart = INIT_INDEX;
99 int exprLen =
static_cast<int>(expression.size());
100 if (exprLen > 2 && expression[0] ==
'=' && expression[exprLen - 1] ==
'=') {
101 _literalConstant =
true;
107 for (
int i = start; i <= exprLen; ++i) {
108 char ch = i < exprLen ? expression[i] : END_CHAR;
110 case ExprParseState::START:
111 if (ch ==
'+' || ch ==
'-' || ch ==
'*' || isalnum(ch)) {
112 state = ExprParseState::ATOMIC;
114 }
else if (ch == END_CHAR) {
118 "Invalid character found at the start of the expression: " + std::string(1, ch));
122 case ExprParseState::ATOMIC:
123 assert(lastAtomicStart != INIT_INDEX);
124 if (expression[lastAtomicStart] ==
'*' ||
125 (lastAtomicStart + 1 < i &&
126 (expression[lastAtomicStart] ==
'+' || expression[lastAtomicStart] ==
'-') &&
127 expression[lastAtomicStart + 1] ==
'*')) {
129 if (ch == END_CHAR) {
130 state = ExprParseState::END;
132 state = ExprParseState::OPERATION;
133 lastOperationStart = i;
136 "Invalid character found while trying to find an operation: " + std::string(1, ch));
138 bool negative = expression[lastAtomicStart] ==
'-';
139 _atomics.emplace_back(
Atomic(AtomicType::ASTERISK, lineSymbol, negative));
140 _depends.insert(lineSymbol);
141 }
else if (isalnum(ch) ||
142 ((expression[lastAtomicStart] ==
'+' || expression[lastAtomicStart] ==
'-') &&
143 lastAtomicStart + 1 == i && ch ==
'*')) {
145 if (ch == END_CHAR) {
146 state = ExprParseState::END;
148 state = ExprParseState::OPERATION;
149 lastOperationStart = i;
152 "Invalid character found while trying to find an operation: " + std::string(1, ch));
154 bool isInteger =
true, negative =
false;
155 int32_t integerValue = 0;
156 if (expression[lastAtomicStart] ==
'-') {
159 }
else if (expression[lastAtomicStart] ==
'+') {
162 if (lastAtomicStart == i) {
164 std::to_string(expression[lastAtomicStart - 1]));
167 for (
int j = lastAtomicStart; j < i; ++j) {
168 if (isalpha(expression[j])) {
172 int32_t digit = expression[j] -
'0';
173 if (integerValue > (std::numeric_limits<int32_t>::max() - digit) / 10) {
175 expression.substr(lastAtomicStart, i - lastAtomicStart));
177 integerValue = integerValue * 10 + digit;
180 _atomics.emplace_back(
Atomic(AtomicType::INTEGER, integerValue, negative));
182 auto symbol = expression.substr(lastAtomicStart, i - lastAtomicStart);
183 _atomics.emplace_back(
Atomic(AtomicType::SYMBOL, symbol, negative));
184 _depends.insert(symbol);
189 case ExprParseState::OPERATION:
190 assert(lastOperationStart != INIT_INDEX);
193 }
else if (ch == END_CHAR) {
196 state = ExprParseState::ATOMIC;
198 if (i - lastOperationStart == 1) {
199 switch (expression[lastOperationStart]) {
201 _operations.emplace_back(Operation::ADD);
204 _operations.emplace_back(Operation::SUBTRACT);
207 _operations.emplace_back(Operation::MULTIPLY);
210 _operations.emplace_back(Operation::FLOOR_DIV);
213 _operations.emplace_back(Operation::FIELD);
223 case ExprParseState::END:
228 assert(state == ExprParseState::END);
230 assert(_atomics.size() == _operations.size() + 1);
234 if (_atomics.size() == 0) {
238 if (atomic.
type == AtomicType::INTEGER) {
245 auto it = constants.find(atomic.
symbol);
246 if (it == constants.end()) {
258 if (!evalAtomic(_atomics[0], &first)) {
261 for (
size_t i = 0; i < _operations.size(); ++i) {
262 if (!evalAtomic(_atomics[i + 1], &second)) {
265 switch (_operations[i]) {
267 first.value += second.value;
269 case Operation::SUBTRACT:
270 first.value -= second.value;
272 case Operation::MULTIPLY:
273 first.value *= second.value;
275 case Operation::FLOOR_DIV:
276 first.value /= second.value;
278 case Operation::FIELD:
279 first.value = first.value * 8 + second.value;
282 if (first.value > 0) {
283 first.negative =
false;
284 }
else if (first.value < 0) {
285 first.negative =
true;
294 for (
auto& atomic : _atomics) {
295 if (atomic.type == AtomicType::SYMBOL) {
296 auto it = mapping.find(atomic.symbol);
297 if (it != mapping.end()) {
298 atomic.replaceSymbol(it->second);
299 _depends.erase(it->first);
300 _depends.insert(it->second);
308 _literalConstant =
false;
315 if (_atomics.size() != expression._atomics.size()) {
318 for (
size_t i = 0; i < _atomics.size(); ++i) {
319 if (_atomics[i] != expression._atomics[i]) {
323 for (
size_t i = 0; i < _operations.size(); ++i) {
324 if (_operations[i] != expression._operations[i]) {
332 return !((*this) == expression);
337 case Operation::ADD: out <<
'+';
break;
338 case Operation::SUBTRACT: out <<
'-';
break;
339 case Operation::MULTIPLY: out <<
'*';
break;
340 case Operation::FLOOR_DIV: out <<
'/';
break;
341 case Operation::FIELD: out <<
':';
break;
347 if (expression._atomics.size() > 0) {
348 out << expression._atomics[0];
350 for (
size_t i = 0; i < expression._operations.size(); ++i) {
351 out << expression._operations[i];
352 out << expression._atomics[i + 1];