aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-16 22:03:13 +0200
committerBad Diode <bd@badd10de.dev>2024-06-16 22:03:13 +0200
commit3922b262aef17be3fcee90db969aca5b0edc617e (patch)
treec297ec5200e0c9002dfa3ea522c41cb48d6e1110
parentbf4aa41a445986658f4ee931305d9caf496e9072 (diff)
downloadbdl-3922b262aef17be3fcee90db969aca5b0edc617e.tar.gz
bdl-3922b262aef17be3fcee90db969aca5b0edc617e.zip
Add bitwise parsing operations
-rw-r--r--Makefile2
-rw-r--r--src/lexer.c22
-rw-r--r--src/main.c45
-rw-r--r--tests/bitops.bad7
4 files changed, 58 insertions, 18 deletions
diff --git a/Makefile b/Makefile
index 082ab87..d7eb968 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
5SRC_DIR := src 5SRC_DIR := src
6BUILD_DIR := build 6BUILD_DIR := build
7SRC_MAIN := $(SRC_DIR)/main.c 7SRC_MAIN := $(SRC_DIR)/main.c
8SRC_BAD := tests/comparisons.bad 8SRC_BAD := tests/bitops.bad
9WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h") 9WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h")
10INC_DIRS := $(shell find $(SRC_DIR) -type d) 10INC_DIRS := $(shell find $(SRC_DIR) -type d)
11INC_FLAGS := $(addprefix -I,$(INC_DIRS)) 11INC_FLAGS := $(addprefix -I,$(INC_DIRS))
diff --git a/src/lexer.c b/src/lexer.c
index 997a9f3..0aa26c1 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -43,15 +43,15 @@ typedef enum TokenKind {
43 TOK_MOD, // % 43 TOK_MOD, // %
44 44
45 // Logical ops. 45 // Logical ops.
46 TOK_NOT, // ! 46 TOK_NOT, // !
47 TOK_AND, // && 47 TOK_AND, // &&
48 TOK_OR, // || 48 TOK_OR, // ||
49 TOK_EQ, // == 49 TOK_EQ, // ==
50 TOK_NOTEQ, // != 50 TOK_NEQ, // !=
51 TOK_LT, // < 51 TOK_LT, // <
52 TOK_GT, // > 52 TOK_GT, // >
53 TOK_LE, // <= 53 TOK_LE, // <=
54 TOK_GE, // >= 54 TOK_GE, // >=
55 55
56 // Bitwise ops. 56 // Bitwise ops.
57 TOK_BITNOT, // ~ 57 TOK_BITNOT, // ~
@@ -115,7 +115,7 @@ Str token_str[] = {
115 [TOK_AND] = cstr("AND"), 115 [TOK_AND] = cstr("AND"),
116 [TOK_OR] = cstr("OR"), 116 [TOK_OR] = cstr("OR"),
117 [TOK_EQ] = cstr("EQ"), 117 [TOK_EQ] = cstr("EQ"),
118 [TOK_NOTEQ] = cstr("NOTEQ"), 118 [TOK_NEQ] = cstr("NEQ"),
119 [TOK_LT] = cstr("LT"), 119 [TOK_LT] = cstr("LT"),
120 [TOK_GT] = cstr("GT"), 120 [TOK_GT] = cstr("GT"),
121 [TOK_LE] = cstr("LE"), 121 [TOK_LE] = cstr("LE"),
@@ -436,7 +436,7 @@ scan_token(Scanner *scanner) {
436 case '!': { 436 case '!': {
437 if (scan_peek(scanner) == '=') { 437 if (scan_peek(scanner) == '=') {
438 scan_next(scanner); 438 scan_next(scanner);
439 return emit_token(current, scanner, TOK_NOTEQ); 439 return emit_token(current, scanner, TOK_NEQ);
440 } 440 }
441 return emit_token(current, scanner, TOK_NOT); 441 return emit_token(current, scanner, TOK_NOT);
442 }; 442 };
diff --git a/src/main.c b/src/main.c
index 1c71a6e..8892a60 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,11 +50,17 @@ typedef enum NodeKind {
50 NODE_AND, 50 NODE_AND,
51 NODE_OR, 51 NODE_OR,
52 NODE_EQ, 52 NODE_EQ,
53 NODE_NOTEQ, 53 NODE_NEQ,
54 NODE_LT, 54 NODE_LT,
55 NODE_GT, 55 NODE_GT,
56 NODE_LE, 56 NODE_LE,
57 NODE_GE, 57 NODE_GE,
58 // Bitwise ops.
59 NODE_BITNOT,
60 NODE_BITAND,
61 NODE_BITOR,
62 NODE_BITLSHIFT,
63 NODE_BITRSHIFT,
58 // Literals. 64 // Literals.
59 NODE_NUM_INT, 65 NODE_NUM_INT,
60 NODE_NUM_FLOAT, 66 NODE_NUM_FLOAT,
@@ -75,11 +81,17 @@ Str node_str[] = {
75 [NODE_AND] = cstr("AND"), 81 [NODE_AND] = cstr("AND"),
76 [NODE_OR] = cstr("OR"), 82 [NODE_OR] = cstr("OR"),
77 [NODE_EQ] = cstr("EQ"), 83 [NODE_EQ] = cstr("EQ"),
78 [NODE_NOTEQ] = cstr("NOTEQ"), 84 [NODE_NEQ] = cstr("NEQ"),
79 [NODE_LT] = cstr("LT"), 85 [NODE_LT] = cstr("LT"),
80 [NODE_GT] = cstr("GT"), 86 [NODE_GT] = cstr("GT"),
81 [NODE_LE] = cstr("LE"), 87 [NODE_LE] = cstr("LE"),
82 [NODE_GE] = cstr("GE"), 88 [NODE_GE] = cstr("GE"),
89 // Bitwise ops.
90 [NODE_BITNOT] = cstr("BITNOT"),
91 [NODE_BITAND] = cstr("BITAND"),
92 [NODE_BITOR] = cstr("BITOR"),
93 [NODE_BITLSHIFT] = cstr("BITLSHIFT"),
94 [NODE_BITRSHIFT] = cstr("BITRSHIFT"),
83 // Literals. 95 // Literals.
84 [NODE_NUM_INT] = cstr("INT"), 96 [NODE_NUM_INT] = cstr("INT"),
85 [NODE_NUM_FLOAT] = cstr("FLOAT"), 97 [NODE_NUM_FLOAT] = cstr("FLOAT"),
@@ -135,6 +147,8 @@ typedef struct Parser {
135typedef enum { 147typedef enum {
136 PREC_NONE = 0, 148 PREC_NONE = 0,
137 PREC_LOW, // lowest precedence 149 PREC_LOW, // lowest precedence
150 PREC_BITLOGIC, // & |
151 PREC_BITSHIFT, // << >>
138 PREC_OR, // || 152 PREC_OR, // ||
139 PREC_AND, // && 153 PREC_AND, // &&
140 PREC_EQUALITY, // == != 154 PREC_EQUALITY, // == !=
@@ -176,11 +190,17 @@ ParseRule parse_rules[] = {
176 [TOK_AND] = {NULL, parse_binary, PREC_AND}, 190 [TOK_AND] = {NULL, parse_binary, PREC_AND},
177 [TOK_OR] = {NULL, parse_binary, PREC_OR}, 191 [TOK_OR] = {NULL, parse_binary, PREC_OR},
178 [TOK_EQ] = {NULL, parse_binary, PREC_EQUALITY}, 192 [TOK_EQ] = {NULL, parse_binary, PREC_EQUALITY},
179 [TOK_NOTEQ] = {NULL, parse_binary, PREC_EQUALITY}, 193 [TOK_NEQ] = {NULL, parse_binary, PREC_EQUALITY},
180 [TOK_LT] = {NULL, parse_binary, PREC_COMPARISON}, 194 [TOK_LT] = {NULL, parse_binary, PREC_COMPARISON},
181 [TOK_GT] = {NULL, parse_binary, PREC_COMPARISON}, 195 [TOK_GT] = {NULL, parse_binary, PREC_COMPARISON},
182 [TOK_LE] = {NULL, parse_binary, PREC_COMPARISON}, 196 [TOK_LE] = {NULL, parse_binary, PREC_COMPARISON},
183 [TOK_GE] = {NULL, parse_binary, PREC_COMPARISON}, 197 [TOK_GE] = {NULL, parse_binary, PREC_COMPARISON},
198 // Bitwise ops.
199 [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE},
200 [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC},
201 [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC},
202 [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
203 [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
184 // Literals. 204 // Literals.
185 [TOK_NUM_INT] = {parse_number, NULL, PREC_NONE}, 205 [TOK_NUM_INT] = {parse_number, NULL, PREC_NONE},
186 [TOK_NUM_FLOAT] = {parse_number, NULL, PREC_NONE}, 206 [TOK_NUM_FLOAT] = {parse_number, NULL, PREC_NONE},
@@ -255,6 +275,9 @@ parse_unary(Parser *parser) {
255 Node *node = NULL; 275 Node *node = NULL;
256 switch (prev.kind) { 276 switch (prev.kind) {
257 case TOK_NOT: node = node_alloc(NODE_NOT, prev, parser->storage); break; 277 case TOK_NOT: node = node_alloc(NODE_NOT, prev, parser->storage); break;
278 case TOK_BITNOT: {
279 node = node_alloc(NODE_BITNOT, prev, parser->storage);
280 } break;
258 default: break; // Unreachable. 281 default: break; // Unreachable.
259 } 282 }
260 node->left = array_pop(parser->nodes); 283 node->left = array_pop(parser->nodes);
@@ -304,13 +327,23 @@ parse_binary(Parser *parser) {
304 case TOK_AND: node = node_alloc(NODE_AND, prev, parser->storage); break; 327 case TOK_AND: node = node_alloc(NODE_AND, prev, parser->storage); break;
305 case TOK_OR: node = node_alloc(NODE_OR, prev, parser->storage); break; 328 case TOK_OR: node = node_alloc(NODE_OR, prev, parser->storage); break;
306 case TOK_EQ: node = node_alloc(NODE_EQ, prev, parser->storage); break; 329 case TOK_EQ: node = node_alloc(NODE_EQ, prev, parser->storage); break;
307 case TOK_NOTEQ: 330 case TOK_NEQ: node = node_alloc(NODE_NEQ, prev, parser->storage); break;
308 node = node_alloc(NODE_NOTEQ, prev, parser->storage);
309 break;
310 case TOK_LT: node = node_alloc(NODE_LT, prev, parser->storage); break; 331 case TOK_LT: node = node_alloc(NODE_LT, prev, parser->storage); break;
311 case TOK_GT: node = node_alloc(NODE_GT, prev, parser->storage); break; 332 case TOK_GT: node = node_alloc(NODE_GT, prev, parser->storage); break;
312 case TOK_LE: node = node_alloc(NODE_LE, prev, parser->storage); break; 333 case TOK_LE: node = node_alloc(NODE_LE, prev, parser->storage); break;
313 case TOK_GE: node = node_alloc(NODE_GE, prev, parser->storage); break; 334 case TOK_GE: node = node_alloc(NODE_GE, prev, parser->storage); break;
335 case TOK_BITAND: {
336 node = node_alloc(NODE_BITAND, prev, parser->storage);
337 } break;
338 case TOK_BITOR: {
339 node = node_alloc(NODE_BITOR, prev, parser->storage);
340 } break;
341 case TOK_BITLSHIFT: {
342 node = node_alloc(NODE_BITLSHIFT, prev, parser->storage);
343 } break;
344 case TOK_BITRSHIFT: {
345 node = node_alloc(NODE_BITRSHIFT, prev, parser->storage);
346 } break;
314 default: { 347 default: {
315 parse_emit_err(parser, prev, cstr("unreachable")); 348 parse_emit_err(parser, prev, cstr("unreachable"));
316 return; 349 return;
diff --git a/tests/bitops.bad b/tests/bitops.bad
new file mode 100644
index 0000000..5582d36
--- /dev/null
+++ b/tests/bitops.bad
@@ -0,0 +1,7 @@
10x0f << 4
20xff >> 4
30x0f << 4 * 2 >> 3
4
50xff & 0xf >> 4 | 123
6~0xff
7~(0xff >> 4)