From 3922b262aef17be3fcee90db969aca5b0edc617e Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 16 Jun 2024 22:03:13 +0200 Subject: Add bitwise parsing operations --- Makefile | 2 +- src/lexer.c | 22 +++++++++++----------- src/main.c | 45 +++++++++++++++++++++++++++++++++++++++------ tests/bitops.bad | 7 +++++++ 4 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 tests/bitops.bad diff --git a/Makefile b/Makefile index 082ab87..d7eb968 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ SRC_DIR := src BUILD_DIR := build SRC_MAIN := $(SRC_DIR)/main.c -SRC_BAD := tests/comparisons.bad +SRC_BAD := tests/bitops.bad WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h") INC_DIRS := $(shell find $(SRC_DIR) -type d) INC_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 { TOK_MOD, // % // Logical ops. - TOK_NOT, // ! - TOK_AND, // && - TOK_OR, // || - TOK_EQ, // == - TOK_NOTEQ, // != - TOK_LT, // < - TOK_GT, // > - TOK_LE, // <= - TOK_GE, // >= + TOK_NOT, // ! + TOK_AND, // && + TOK_OR, // || + TOK_EQ, // == + TOK_NEQ, // != + TOK_LT, // < + TOK_GT, // > + TOK_LE, // <= + TOK_GE, // >= // Bitwise ops. TOK_BITNOT, // ~ @@ -115,7 +115,7 @@ Str token_str[] = { [TOK_AND] = cstr("AND"), [TOK_OR] = cstr("OR"), [TOK_EQ] = cstr("EQ"), - [TOK_NOTEQ] = cstr("NOTEQ"), + [TOK_NEQ] = cstr("NEQ"), [TOK_LT] = cstr("LT"), [TOK_GT] = cstr("GT"), [TOK_LE] = cstr("LE"), @@ -436,7 +436,7 @@ scan_token(Scanner *scanner) { case '!': { if (scan_peek(scanner) == '=') { scan_next(scanner); - return emit_token(current, scanner, TOK_NOTEQ); + return emit_token(current, scanner, TOK_NEQ); } return emit_token(current, scanner, TOK_NOT); }; 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 { NODE_AND, NODE_OR, NODE_EQ, - NODE_NOTEQ, + NODE_NEQ, NODE_LT, NODE_GT, NODE_LE, NODE_GE, + // Bitwise ops. + NODE_BITNOT, + NODE_BITAND, + NODE_BITOR, + NODE_BITLSHIFT, + NODE_BITRSHIFT, // Literals. NODE_NUM_INT, NODE_NUM_FLOAT, @@ -75,11 +81,17 @@ Str node_str[] = { [NODE_AND] = cstr("AND"), [NODE_OR] = cstr("OR"), [NODE_EQ] = cstr("EQ"), - [NODE_NOTEQ] = cstr("NOTEQ"), + [NODE_NEQ] = cstr("NEQ"), [NODE_LT] = cstr("LT"), [NODE_GT] = cstr("GT"), [NODE_LE] = cstr("LE"), [NODE_GE] = cstr("GE"), + // Bitwise ops. + [NODE_BITNOT] = cstr("BITNOT"), + [NODE_BITAND] = cstr("BITAND"), + [NODE_BITOR] = cstr("BITOR"), + [NODE_BITLSHIFT] = cstr("BITLSHIFT"), + [NODE_BITRSHIFT] = cstr("BITRSHIFT"), // Literals. [NODE_NUM_INT] = cstr("INT"), [NODE_NUM_FLOAT] = cstr("FLOAT"), @@ -135,6 +147,8 @@ typedef struct Parser { typedef enum { PREC_NONE = 0, PREC_LOW, // lowest precedence + PREC_BITLOGIC, // & | + PREC_BITSHIFT, // << >> PREC_OR, // || PREC_AND, // && PREC_EQUALITY, // == != @@ -176,11 +190,17 @@ ParseRule parse_rules[] = { [TOK_AND] = {NULL, parse_binary, PREC_AND}, [TOK_OR] = {NULL, parse_binary, PREC_OR}, [TOK_EQ] = {NULL, parse_binary, PREC_EQUALITY}, - [TOK_NOTEQ] = {NULL, parse_binary, PREC_EQUALITY}, + [TOK_NEQ] = {NULL, parse_binary, PREC_EQUALITY}, [TOK_LT] = {NULL, parse_binary, PREC_COMPARISON}, [TOK_GT] = {NULL, parse_binary, PREC_COMPARISON}, [TOK_LE] = {NULL, parse_binary, PREC_COMPARISON}, [TOK_GE] = {NULL, parse_binary, PREC_COMPARISON}, + // Bitwise ops. + [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, + [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, + [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, + [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, + [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, // Literals. [TOK_NUM_INT] = {parse_number, NULL, PREC_NONE}, [TOK_NUM_FLOAT] = {parse_number, NULL, PREC_NONE}, @@ -255,6 +275,9 @@ parse_unary(Parser *parser) { Node *node = NULL; switch (prev.kind) { case TOK_NOT: node = node_alloc(NODE_NOT, prev, parser->storage); break; + case TOK_BITNOT: { + node = node_alloc(NODE_BITNOT, prev, parser->storage); + } break; default: break; // Unreachable. } node->left = array_pop(parser->nodes); @@ -304,13 +327,23 @@ parse_binary(Parser *parser) { case TOK_AND: node = node_alloc(NODE_AND, prev, parser->storage); break; case TOK_OR: node = node_alloc(NODE_OR, prev, parser->storage); break; case TOK_EQ: node = node_alloc(NODE_EQ, prev, parser->storage); break; - case TOK_NOTEQ: - node = node_alloc(NODE_NOTEQ, prev, parser->storage); - break; + case TOK_NEQ: node = node_alloc(NODE_NEQ, prev, parser->storage); break; case TOK_LT: node = node_alloc(NODE_LT, prev, parser->storage); break; case TOK_GT: node = node_alloc(NODE_GT, prev, parser->storage); break; case TOK_LE: node = node_alloc(NODE_LE, prev, parser->storage); break; case TOK_GE: node = node_alloc(NODE_GE, prev, parser->storage); break; + case TOK_BITAND: { + node = node_alloc(NODE_BITAND, prev, parser->storage); + } break; + case TOK_BITOR: { + node = node_alloc(NODE_BITOR, prev, parser->storage); + } break; + case TOK_BITLSHIFT: { + node = node_alloc(NODE_BITLSHIFT, prev, parser->storage); + } break; + case TOK_BITRSHIFT: { + node = node_alloc(NODE_BITRSHIFT, prev, parser->storage); + } break; default: { parse_emit_err(parser, prev, cstr("unreachable")); 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 @@ +0x0f << 4 +0xff >> 4 +0x0f << 4 * 2 >> 3 + +0xff & 0xf >> 4 | 123 +~0xff +~(0xff >> 4) -- cgit v1.2.1