aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authoronelin <oscar@nelin.dk>2026-09-22 21:21:33 +0000
committeronelin <oscar@nelin.dk>2026-09-22 21:21:33 +0000
commit357c336082b176c6734d9f78da4640644b3772d0 (patch)
tree34af52d5c932b5c353ae04a86b91963b808a657b /main.c
parent6cb929f1d70a5a832971b6d8c6558ea5376ecee8 (diff)
chore: Refactor readability of parser
Also fix how precedence is checked
Diffstat (limited to 'main.c')
-rw-r--r--main.c126
1 files changed, 71 insertions, 55 deletions
diff --git a/main.c b/main.c
index db86d05..4130099 100644
--- a/main.c
+++ b/main.c
@@ -69,12 +69,27 @@ typedef struct AExp {
// Token_t* t;
} AExp_t;
+static const union {
+ struct {
+ u8 grouping;
+ u8 operator;
+ } parts;
+ u16 sum;
+} precedence_tbl[] = {
+ [e_error] = {0},
+ [e_mul] = {.parts = {.grouping = 0, .operator = 2}},
+ [e_div] = {.parts = {.grouping = 0, .operator = 2}},
+ [e_add] = {.parts = {.grouping = 0, .operator = 1}},
+ [e_sub] = {.parts = {.grouping = 0, .operator = 1}},
+ [e_number] = {.parts = {.grouping = 0, .operator = 3}},
+};
+
static usize f_read(FILE* restrict stream, char** restrict dst);
static usize f_size(FILE* restrict stream);
static line_offsets_t* l_read(char const* restrict text, usize text_length,
TokenList_t** restrict dst);
static AExp_t* p_arith(char const* restrict text, TokenList_t* restrict tokens);
-static AExp_t p_number(char const* restrict text, Token_t* restrict tnum);
+static AExp_t p_number(char const* restrict text, Token_t const* restrict tnum);
static void print_aexp(AExp_t* t);
int
@@ -341,83 +356,84 @@ p_arith(char const* restrict text, TokenList_t* restrict tokens) {
// Root is the "current working root"
AExp_t* root = NULL;
- // Exp is the return expression, or the "root" of the expression that has
- // parsed.
- AExp_t* exp = NULL;
+ // Top is the "top-level" return expression, or the "root" of the expression
+ // that has parsed.
+ AExp_t* top = NULL;
for (int tokenidx = 0; tokenidx < num_tokens; tokenidx++) {
+ // Currently inspected token
+ Token_t const* const token = &tokens->elements[tokenidx];
+ // Destination for currently fabricated expression
+ AExp_t* const expr = &expression[exp_idx];
+
// ignore whitespace
- if (tokens->elements[tokenidx].type == t_space ||
- tokens->elements[tokenidx].type == t_tab ||
- tokens->elements[tokenidx].type == t_newline) {
+ if (token->type == t_space || token->type == t_tab ||
+ token->type == t_newline) {
continue;
}
- if (tokens->elements[tokenidx].type == t_number && root == NULL) {
- expression[exp_idx] = p_number(text, &tokens->elements[tokenidx]);
- root = &expression[exp_idx];
- exp = &expression[exp_idx];
+ if (token->type == t_number && root == NULL) {
+ *expr = p_number(text, token);
+ root = expr;
+ top = expr;
exp_idx++;
- } else if (tokens->elements[tokenidx].type == t_number && root != NULL &&
+ } else if (token->type == t_number && root != NULL &&
root->type == e_number) {
- fprintf(stderr, "Unexpected number at %d:%d\n",
- tokens->elements[tokenidx].pos.line,
- tokens->elements[tokenidx].pos.column);
- return exp;
+ fprintf(stderr, "Unexpected number at %d:%d\n", token->pos.line,
+ token->pos.column);
+ return top;
- } else if (tokens->elements[tokenidx].type == t_number && root != NULL &&
+ } else if (token->type == t_number && root != NULL &&
root->type != e_number) {
+
+ // Consequtive nullary expressions are invalid
if (exp_idx > 0 && expression[exp_idx - 1].type == e_number) {
- fprintf(stderr, "Unexpected number at %d:%d\n",
- tokens->elements[tokenidx].pos.line,
- tokens->elements[tokenidx].pos.column);
- return exp;
+ fprintf(stderr, "Unexpected number at %d:%d\n", token->pos.line,
+ token->pos.column);
+ return top;
}
- expression[exp_idx] = p_number(text, &tokens->elements[tokenidx]);
- root->data.e_binary.b = &expression[exp_idx];
+ *expr = p_number(text, token);
+ root->data.e_binary.b = expr;
// "pop" "root" stack here?
- root = exp;
+ root = top;
exp_idx++;
- } else if (tokens->elements[tokenidx].type != t_number && root == NULL) {
- fprintf(stderr, "Unexpected operator at %d:%d\n",
- tokens->elements[tokenidx].pos.line,
- tokens->elements[tokenidx].pos.column);
- return exp;
+ } else if (token->type != t_number && root == NULL) {
+ fprintf(stderr, "Unexpected operator at %d:%d\n", token->pos.line,
+ token->pos.column);
+ return top;
- } else if (tokens->elements[tokenidx].type != t_number && root != NULL) {
+ } else if (token->type != t_number && root != NULL) {
- if (tokens->elements[tokenidx].type == t_multiply) {
- expression[exp_idx] = (AExp_t){.type = e_mul};
- } else if (tokens->elements[tokenidx].type == t_divide) {
- expression[exp_idx] = (AExp_t){.type = e_div};
- } else if (tokens->elements[tokenidx].type == t_add) {
- expression[exp_idx] = (AExp_t){.type = e_add};
- } else if (tokens->elements[tokenidx].type == t_subtract) {
- expression[exp_idx] = (AExp_t){.type = e_sub};
+ if (token->type == t_multiply) {
+ *expr = (AExp_t){.type = e_mul};
+ } else if (token->type == t_divide) {
+ *expr = (AExp_t){.type = e_div};
+ } else if (token->type == t_add) {
+ *expr = (AExp_t){.type = e_add};
+ } else if (token->type == t_subtract) {
+ *expr = (AExp_t){.type = e_sub};
}
// Currently best way to test if "leaf" or binary operator, also only
// binary are handled
if (root->type == e_number) {
- expression[exp_idx].data.e_binary.a = root;
- root = &expression[exp_idx];
- exp = root;
+ expr->data.e_binary.a = root;
+ root = expr;
+ top = root;
} else {
- // Currently best way to test precendence (root < expression) :(
- if ((expression[exp_idx].type == e_mul ||
- expression[exp_idx].type == e_div) &&
- (root->type == e_add || root->type == e_sub)) {
- expression[exp_idx].data.e_binary.a = root->data.e_binary.b;
- // TODO: check precedence of exp vs root
- exp = root;
- root->data.e_binary.b = &expression[exp_idx];
- root = &expression[exp_idx];
+ // If expr has stronger precedence than root, yoink rhs of root
+ if (precedence_tbl[root->type].sum < precedence_tbl[expr->type].sum) {
+ expr->data.e_binary.a = root->data.e_binary.b;
+ // TODO: check precedence of top vs root
+ top = root;
+ root->data.e_binary.b = expr;
+ root = expr;
} else {
- expression[exp_idx].data.e_binary.a = root;
- root = &expression[exp_idx];
- exp = root;
+ expr->data.e_binary.a = root;
+ root = expr;
+ top = root;
}
}
@@ -427,12 +443,12 @@ p_arith(char const* restrict text, TokenList_t* restrict tokens) {
// We store the "root" as the first element, returning a pointer to the
// beginning of the memory also makes it much easier to free.
- expression[0] = *exp;
+ expression[0] = *top;
return expression;
}
static AExp_t
-p_number(char const* restrict text, Token_t* restrict tnum) {
+p_number(char const* restrict text, Token_t const* restrict tnum) {
i32 number = 0;
char* start = (char*)&text[tnum->pos.offset];