commit d3b19ed080fb15073d1ed3199b1f346c7420c19f
parent 61844caf78f788b0e47303d34f1b81fadc91ac7b
Author: amin <dev@aminmesbah.com>
Date: Sun, 21 Feb 2021 06:24:16 +0000
Clean things up and deduplicate enums
FossilOrigin-Name: 5a002befd910ccd3e610ad39083f6694d429491148c2122d9862088871b2041e
Diffstat:
M | calc.c | | | 252 | +++++++++++++++++++++++++++++++------------------------------------------------ |
1 file changed, 97 insertions(+), 155 deletions(-)
diff --git a/calc.c b/calc.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <ctype.h>
+#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -70,16 +71,57 @@ void buf_test(void) {
//printf("\n");
}
+#define TOKEN_LIST \
+ X(TOKEN_NONE, "") \
+ X(TOKEN_OP_ADD, "+") \
+ X(TOKEN_OP_SUB, "-") \
+ X(TOKEN_OP_BIN_OR, "|") \
+ X(TOKEN_OP_BIN_XOR, "^") \
+ X(TOKEN_OP_MUL, "*") \
+ X(TOKEN_OP_DIV, "/") \
+ X(TOKEN_OP_MOD, "%") \
+ X(TOKEN_OP_SHIFT_L, "<<") \
+ X(TOKEN_OP_SHIFT_R, ">>") \
+ X(TOKEN_OP_BIN_AND, "&") \
+ X(TOKEN_OP_BIN_NOT, "~") \
+ X(TOKEN_INT, "") \
+ \
+ X(_TOKEN_KIND_COUNT, "")
+
enum TokenKind {
- TOKEN_NONE = 0,
- // first 128 values reserved to match up with ascii
- TOKEN_INT = 128,
- TOKEN_SHIFT_L,
- TOKEN_SHIFT_R,
+#define X(kind, glyph) kind,
+ TOKEN_LIST
+#undef X
+};
+
+char *TokenKindNames[] = {
+#define X(kind, glyph) [kind] = #kind,
+ TOKEN_LIST
+#undef X
+};
+
+char *TokenKindGlyphs[] = {
+#define X(kind, glyph) [kind] = glyph,
+ TOKEN_LIST
+#undef X
};
+#undef TOKEN_LIST
+
+char *token_kind_glyph(enum TokenKind k) {
+ assert(k >= TOKEN_NONE && k < TOKEN_INT);
+ assert(k <= (sizeof TokenKindNames / sizeof TokenKindGlyphs[0]));
+ return TokenKindGlyphs[k];
+}
+
+char *token_kind_name(enum TokenKind k) {
+ assert(k >= TOKEN_NONE && k < _TOKEN_KIND_COUNT);
+ assert(k <= (sizeof TokenKindNames / sizeof TokenKindNames[0]));
+ return TokenKindNames[k];
+}
+
typedef struct Token {
- uint32_t kind;
+ enum TokenKind kind;
uint64_t val;
} Token;
@@ -88,27 +130,20 @@ global_variable char *g_stream;
#define ERROR() assert(false && "error")
void print_token(struct Token token) {
- switch(token.kind) {
- case TOKEN_INT:
- printf("TOKEN_INT: %lu\n", token.val);
- break;
- case TOKEN_SHIFT_L:
- printf("TOKEN: '<<'\n");
- break;
- case TOKEN_SHIFT_R:
- printf("TOKEN: '>>'\n");
- break;
- case TOKEN_NONE: // fallthrough
- default:
- printf("TOKEN: '%c'\n", token.kind);
- break;
+ bool has_val = token.kind == TOKEN_INT;
+ if (has_val) {
+ printf("T: %s: %" PRIu64 "\n", token_kind_name(token.kind), token.val);
+ } else {
+ printf("T: %s\n", token_kind_name(token.kind));
}
}
char *lex_next_token(Token *out_t) {
assert(out_t);
+ // TODO: bounds check cursor advances
char *cursor = g_stream;
+
while (*cursor == ' ') {
cursor++;
}
@@ -136,7 +171,7 @@ char *lex_next_token(Token *out_t) {
case '<':
cursor++;
if (*cursor == '<') {
- out_t->kind = TOKEN_SHIFT_L;
+ out_t->kind = TOKEN_OP_SHIFT_L;
cursor++;
} else {
ERROR();
@@ -145,14 +180,27 @@ char *lex_next_token(Token *out_t) {
case '>':
cursor++;
if (*cursor == '>') {
- out_t->kind = TOKEN_SHIFT_R;
+ out_t->kind = TOKEN_OP_SHIFT_R;
cursor++;
} else {
ERROR();
}
break;
+ case '+': out_t->kind = TOKEN_OP_ADD; cursor++; break;
+ case '-': out_t->kind = TOKEN_OP_SUB; cursor++; break;
+ case '|': out_t->kind = TOKEN_OP_BIN_OR; cursor++; break;
+ case '^': out_t->kind = TOKEN_OP_BIN_XOR; cursor++; break;
+ case '*': out_t->kind = TOKEN_OP_MUL; cursor++; break;
+ case '/': out_t->kind = TOKEN_OP_DIV; cursor++; break;
+ case '%': out_t->kind = TOKEN_OP_MOD; cursor++; break;
+ case '&': out_t->kind = TOKEN_OP_BIN_AND; cursor++; break;
+ case '~': out_t->kind = TOKEN_OP_BIN_NOT; cursor++; break;
+ case '\0':
+ out_t->kind = TOKEN_NONE;
+ break;
default:
- out_t->kind = *cursor++;
+ printf("ERROR: '%c' %i\n", *cursor, (int)*cursor);
+ ERROR();
break;
}
@@ -194,34 +242,16 @@ Token token_require_kind(enum TokenKind kind) {
}
void lex_test(void) {
- char *source = "+()_HELLO 1,23<<>>4+FOO!994";
+ char *source = "+123<<>>4+ ~994";
+ printf("lex_test: '%s'\n", source);
g_stream = source;
Token t = token_consume();
while (t.kind) {
- //print_token(t);
+ print_token(t);
t = token_consume();
}
}
-enum OpKind {
- OP_NONE,
-
- OP_ADD,
- OP_SUB,
- OP_BIN_OR,
- OP_BIN_XOR,
-
- OP_MUL,
- OP_DIV,
- OP_MOD,
- OP_SHIFT_L,
- OP_SHIFT_R,
- OP_BIN_AND,
-
- OP_NEG,
- OP_BIN_NOT,
-};
-
enum ExprKind {
EXPR_NONE,
EXPR_OPERAND,
@@ -229,95 +259,23 @@ enum ExprKind {
EXPR_BINARY,
};
-bool unary_op(enum OpKind *op) {
- assert(op);
- enum OpKind kind = OP_NONE;
-
- Token next = token_peek();
- switch (next.kind) {
- case '-':
- kind = OP_NEG;
- break;
- case '~':
- kind = OP_BIN_NOT;
- break;
- }
-
- if (kind != OP_NONE) {
- *op = kind;
- token_consume();
- return true;
- }
-
- return false;
+bool is_unary_op(enum TokenKind o) {
+ return o == TOKEN_OP_SUB || o == TOKEN_OP_BIN_NOT;
}
-bool mul_op(enum OpKind *op) {
- assert(op);
- enum OpKind kind = OP_NONE;
-
- Token next = token_peek();
- switch (next.kind) {
- case '*':
- kind = OP_MUL;
- break;
- case '/':
- kind = OP_DIV;
- break;
- case '%':
- kind = OP_MOD;
- break;
- case TOKEN_SHIFT_L:
- kind = OP_SHIFT_L;
- break;
- case TOKEN_SHIFT_R:
- kind = OP_SHIFT_R;
- break;
- }
-
- if (kind != OP_NONE) {
- *op = kind;
- token_consume();
- return true;
- }
-
- return false;
+bool is_mul_op(enum TokenKind o) {
+ return o == TOKEN_OP_MUL || o == TOKEN_OP_DIV || o == TOKEN_OP_MOD || o == TOKEN_OP_SHIFT_L || o == TOKEN_OP_SHIFT_R || o == TOKEN_OP_BIN_AND;
}
-bool add_op(enum OpKind *op) {
- assert(op);
- enum OpKind kind = OP_NONE;
-
- Token next = token_peek();
- switch (next.kind) {
- case '+':
- kind = OP_ADD;
- break;
- case '-':
- kind = OP_SUB;
- break;
- case '|':
- kind = OP_BIN_OR;
- break;
- case '^':
- kind = OP_BIN_XOR;
- break;
- }
-
- if (kind != OP_NONE) {
- *op = kind;
- token_consume();
- return true;
- }
-
- return false;
+bool is_add_op(enum TokenKind o) {
+ return o == TOKEN_OP_ADD || o == TOKEN_OP_SUB || o == TOKEN_OP_BIN_OR || o == TOKEN_OP_BIN_XOR;
}
typedef struct Expr Expr;
struct Expr {
enum ExprKind kind;
- enum OpKind op;
+ enum TokenKind op;
Expr *left;
Expr *right;
int32_t operand;
@@ -329,7 +287,8 @@ Expr *expr_alloc(void) {
return e;
}
-Expr *expr_unary(enum OpKind o, Expr *u) {
+Expr *expr_unary(enum TokenKind o, Expr *u) {
+ assert(is_unary_op(o));
Expr *e = expr_alloc();
*e = (Expr) {
.kind = EXPR_UNARY,
@@ -339,7 +298,8 @@ Expr *expr_unary(enum OpKind o, Expr *u) {
return e;
}
-Expr *expr_binary(enum OpKind o, Expr *l, Expr *r) {
+Expr *expr_binary(enum TokenKind o, Expr *l, Expr *r) {
+ assert(is_mul_op(o) || is_add_op(o));
Expr *e = expr_alloc();
*e = (Expr) {
.kind = EXPR_BINARY,
@@ -353,25 +313,7 @@ Expr *expr_binary(enum OpKind o, Expr *l, Expr *r) {
void print_expr(Expr *e) {
assert(e);
- char *op = NULL;
- switch (e->op) {
- case OP_NONE: break;
- case OP_ADD: op = "+"; break;
- case OP_SUB: op = "-"; break;
- case OP_BIN_OR: op = "|"; break;
- case OP_BIN_XOR: op = "^"; break;
- case OP_MUL: op = "*"; break;
- case OP_DIV: op = "/"; break;
- case OP_MOD: op = "%"; break;
- case OP_SHIFT_L: op = "<<"; break;
- case OP_SHIFT_R: op = ">>"; break;
- case OP_BIN_AND: op = "&"; break;
- case OP_NEG: op = "-"; break;
- case OP_BIN_NOT: op = "~"; break;
- default:
- ERROR();
- break;
- }
+ char *op = token_kind_glyph(e->op);
if (e->kind != EXPR_OPERAND) {
printf("(");
@@ -382,9 +324,7 @@ void print_expr(Expr *e) {
printf("%i", e->operand);
break;
case EXPR_UNARY:
- if (op) {
- printf("%s ", op);
- }
+ printf("%s ", op);
print_expr(e->left);
break;
case EXPR_BINARY:
@@ -419,8 +359,8 @@ Expr *parse_expr_operand(void) {
}
Expr *parse_expr_unary(void) {
- enum OpKind op = 0;
- if (unary_op(&op)) {
+ if (is_unary_op(token_peek().kind)) {
+ enum TokenKind op = token_consume().kind;
return expr_unary(op, parse_expr_unary());
} else {
return parse_expr_operand();
@@ -429,8 +369,8 @@ Expr *parse_expr_unary(void) {
Expr *parse_expr_mul(void) {
Expr *e = parse_expr_unary();
- enum OpKind op = 0;
- while (mul_op(&op)) {
+ while (is_mul_op(token_peek().kind)) {
+ enum TokenKind op = token_consume().kind;
e = expr_binary(op, e, parse_expr_unary());
}
return e;
@@ -438,8 +378,8 @@ Expr *parse_expr_mul(void) {
Expr *parse_expr_add(void) {
Expr *e = parse_expr_mul();
- enum OpKind op = 0;
- while (add_op(&op)) {
+ while (is_add_op(token_peek().kind)) {
+ enum TokenKind op = token_consume().kind;
e = expr_binary(op, e, parse_expr_mul());
}
@@ -461,8 +401,8 @@ Expr *parse_expr(void) {
// expr = expr_add.
// number = "0" .. "9" {"0" .. "9"}.
void parse_test(void) {
- char *source = "12*34 + 45/56 + -25";
- printf("%s\n", source);
+ char *source = "12*34 + 45/56 + ~-25";
+ printf("parse_test: '%s'\n", source);
g_stream = source;
Expr *e = parse_expr();
print_expr(e);
@@ -472,4 +412,6 @@ int main(void) {
buf_test();
lex_test();
parse_test();
+ printf("\n");
+ return 0;
}