MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
expr.hpp
Go to the documentation of this file.
1
6#ifndef __EXPR__H_
7#define __EXPR__H_
9#include "scanner/scanner.hpp"
10#include <string>
11#include <unordered_map>
12
13namespace expr_parser {
14
42
44 struct ExprToken {
46 uint64_t value;
47 };
48
50 inline std::unordered_map<std::string, uint64_t> vars;
51
58 class ExprLexer {
59 public:
60 std::string variable;
65 ExprLexer(const std::string &input) : scanner(input), pos(0) {
66 scanner.scan();
67 next();
68 }
69
71 void next() {
72 if (pos >= scanner.size()) {
74 return;
75 }
76 auto t = scanner[pos++];
77 auto val = t.getTokenValue();
78 if (t.getTokenType() == types::TokenType::TT_NUM) {
79 current = {ExprTokenType::NUMBER, std::stoull(val)};
80 } else if (t.getTokenType() == types::TokenType::TT_HEX) {
81 current = {ExprTokenType::NUMBER, std::stoull(val, nullptr, 16)};
82 } else if (t.getTokenType() == types::TokenType::TT_ID) {
84 variable = val;
85 } else if (val == "+") {
87 } else if (val == "-") {
89 } else if (val == "*") {
91 } else if (val == "/") {
93 } else if (val == "%") {
95 } else if (val == "(") {
97 } else if (val == ")") {
99 } else if (val == "+=") {
101 } else if (val == "-=") {
103 } else if (val == "^") {
105 } else if (val == "|") {
107 } else if (val == "&") {
109 } else if (val == "&&") {
111 } else if (val == "||") {
113 } else if (val == "!") {
115 } else if (val == "==") {
117 } else if (val == "!=") {
119 } else if (val == ">") {
121 } else if (val == ">=") {
123 } else if (val == "<") {
125 } else if (val == "<=") {
127 } else {
129 }
130 }
131
133 ExprToken peek() const { return current; }
135 void consume() { next(); }
136
137 private:
139 size_t pos;
141 };
142
151 public:
161 uint64_t parse() { return parseLogical(); }
162
163 private:
165
167 uint64_t parseAdd() {
168 uint64_t val = parseTerm();
169 while (lexer.peek().type == ExprTokenType::PLUS ||
170 lexer.peek().type == ExprTokenType::MINUS) {
171 if (lexer.peek().type == ExprTokenType::PLUS) {
172 lexer.consume();
173 val += parseTerm();
174 } else {
175 lexer.consume();
176 val -= parseTerm();
177 }
178 }
179 return val;
180 }
181
183 uint64_t parseBitwise() {
184 uint64_t val = parseAdd();
185 while (lexer.peek().type == ExprTokenType::XOR ||
186 lexer.peek().type == ExprTokenType::OR ||
187 lexer.peek().type == ExprTokenType::AND) {
188 if (lexer.peek().type == ExprTokenType::XOR) {
189 lexer.consume();
190 val ^= parseAdd();
191 } else if (lexer.peek().type == ExprTokenType::OR) {
192 lexer.consume();
193 val |= parseAdd();
194 } else {
195 lexer.consume();
196 val &= parseAdd();
197 }
198 }
199 return val;
200 }
201
203 uint64_t parseComparison() {
204 uint64_t val = parseBitwise();
205 while (lexer.peek().type == ExprTokenType::EQ ||
206 lexer.peek().type == ExprTokenType::NEQ ||
207 lexer.peek().type == ExprTokenType::GT ||
208 lexer.peek().type == ExprTokenType::GTE ||
209 lexer.peek().type == ExprTokenType::LT ||
210 lexer.peek().type == ExprTokenType::LTE) {
211 if (lexer.peek().type == ExprTokenType::EQ) {
212 lexer.consume();
213 val = (val == parseBitwise());
214 } else if (lexer.peek().type == ExprTokenType::NEQ) {
215 lexer.consume();
216 val = (val != parseBitwise());
217 } else if (lexer.peek().type == ExprTokenType::GT) {
218 lexer.consume();
219 val = (val > parseBitwise());
220 } else if (lexer.peek().type == ExprTokenType::GTE) {
221 lexer.consume();
222 val = (val >= parseBitwise());
223 } else if (lexer.peek().type == ExprTokenType::LT) {
224 lexer.consume();
225 val = (val < parseBitwise());
226 } else {
227 lexer.consume();
228 val = (val <= parseBitwise());
229 }
230 }
231 return val;
232 }
233
235 uint64_t parseLogical() {
236 uint64_t val = parseComparison();
237 while (lexer.peek().type == ExprTokenType::LOGICAL_OR ||
238 lexer.peek().type == ExprTokenType::LOGICAL_AND) {
239 if (lexer.peek().type == ExprTokenType::LOGICAL_OR) {
240 lexer.consume();
241 val = val || parseComparison();
242 } else {
243 lexer.consume();
244 val = val && parseComparison();
245 }
246 }
247 return val;
248 }
249
251 uint64_t parseTerm() {
252 uint64_t val = parseFactor();
253 while (lexer.peek().type == ExprTokenType::MUL ||
254 lexer.peek().type == ExprTokenType::DIV ||
255 lexer.peek().type == ExprTokenType::MOD) {
256 if (lexer.peek().type == ExprTokenType::MUL) {
257 lexer.consume();
258 val *= parseFactor();
259 } else if (lexer.peek().type == ExprTokenType::DIV) {
260 lexer.consume();
261 uint64_t d = parseFactor();
262 if (d == 0)
263 throw std::runtime_error("Division by zero");
264 val /= d;
265 } else {
266 lexer.consume();
267 uint64_t d = parseFactor();
268 if (d == 0)
269 throw std::runtime_error("Modulo by zero");
270 val %= d;
271 }
272 }
273 return val;
274 }
275
277 uint64_t parseFactor() {
278 if (lexer.peek().type == ExprTokenType::NOT) {
279 lexer.consume();
280 return !parseFactor();
281 } else if (lexer.peek().type == ExprTokenType::MINUS) {
282 lexer.consume();
283 return -parseFactor();
284 } else if (lexer.peek().type == ExprTokenType::NUMBER) {
285 uint64_t v = lexer.peek().value;
286 lexer.consume();
287 return v;
288 } else if (lexer.peek().type == ExprTokenType::VARIABLE) {
289 std::string var_name = lexer.variable;
290 lexer.consume();
291 auto v = vars.find(var_name);
292 if (v == vars.end()) {
293 throw mx::Exception("Error variable name not found...\n");
294 }
295 return vars[var_name];
296 } else if (lexer.peek().type == ExprTokenType::LPAREN) {
297 lexer.consume();
298 uint64_t v = parseLogical();
299 if (lexer.peek().type != ExprTokenType::RPAREN)
300 throw std::runtime_error("Expected ')'");
301 lexer.consume();
302 return v;
303 }
304 throw std::runtime_error("Unexpected token");
305 }
306 };
307} // namespace expr_parser
308
309#endif
Lexer for constant integer expressions.
Definition expr.hpp:58
std::string variable
last scanned variable name
Definition expr.hpp:60
ExprLexer(const std::string &input)
Construct a lexer and scan the input string.
Definition expr.hpp:65
ExprToken current
most recently read token
Definition expr.hpp:140
void consume()
Consume the current token and advance to the next.
Definition expr.hpp:135
scan::Scanner scanner
underlying scanner for tokenization
Definition expr.hpp:138
void next()
Advance to the next token and update current.
Definition expr.hpp:71
size_t pos
current position in the token stream
Definition expr.hpp:139
ExprToken peek() const
Return the current token without consuming it.
Definition expr.hpp:133
uint64_t parseAdd()
Parse additive expressions (+, -).
Definition expr.hpp:167
uint64_t parseBitwise()
Parse bitwise expressions (^, |, &).
Definition expr.hpp:183
ExprParser(ExprLexer &lexer)
Construct a parser bound to a lexer.
Definition expr.hpp:156
uint64_t parseLogical()
Parse logical expressions (&&, ||) — lowest precedence.
Definition expr.hpp:235
uint64_t parse()
Parse and evaluate the expression.
Definition expr.hpp:161
uint64_t parseTerm()
Parse multiplicative expressions (*, /, %).
Definition expr.hpp:251
uint64_t parseFactor()
Parse primary expressions: numbers, variables, unary ops, and parenthesised sub-expressions.
Definition expr.hpp:277
ExprLexer & lexer
reference to the token source
Definition expr.hpp:164
uint64_t parseComparison()
Parse comparison expressions (==, !=, >, >=, <, <=).
Definition expr.hpp:203
General-purpose exception with errno-aware factory method.
Definition exception.hpp:38
Lexical scanner that tokenizes source text.
Definition scanner.hpp:28
Exception class, hex formatting utilities, and terminal color definitions.
@ NOT
Definition instruct.hpp:33
@ MUL
Definition instruct.hpp:28
@ MOD
Definition instruct.hpp:34
@ DIV
Definition instruct.hpp:29
@ AND
Definition instruct.hpp:31
@ OR
Definition instruct.hpp:30
@ XOR
Definition instruct.hpp:32
std::unordered_map< std::string, uint64_t > vars
Global variable map for the expression evaluator.
Definition expr.hpp:50
ExprTokenType
Token types for the constant expression parser.
Definition expr.hpp:16
@ NUMBER
numeric literal
Definition expr.hpp:18
@ END
end of expression
Definition expr.hpp:17
@ VARIABLE
named variable reference
Definition expr.hpp:40
@ TT_HEX
hexadecimal numeric literal
Definition types.hpp:22
@ TT_ID
identifier or keyword
Definition types.hpp:17
@ TT_NUM
decimal numeric literal
Definition types.hpp:21
Lexical scanner that tokenizes source text into typed tokens.
A single expression token holding its type and optional numeric value.
Definition expr.hpp:44
uint64_t value
numeric value (valid when type == NUMBER)
Definition expr.hpp:46
ExprTokenType type
token classification
Definition expr.hpp:45