2026-03-13 07:58:38 -06:00
|
|
|
#include "parser.h"
|
2026-04-24 09:06:47 -06:00
|
|
|
#include "arraylist.h"
|
2026-03-13 07:58:38 -06:00
|
|
|
#include "lexer.h"
|
2026-04-13 06:40:31 -06:00
|
|
|
#include "arena.h"
|
2026-04-13 07:57:36 -06:00
|
|
|
#include <stdalign.h>
|
2026-03-24 21:51:28 -06:00
|
|
|
#include <stdbool.h>
|
2026-03-24 21:36:14 -06:00
|
|
|
#include <stdint.h>
|
2026-03-13 07:58:38 -06:00
|
|
|
|
2026-03-24 21:36:14 -06:00
|
|
|
uint8_t node_lbp(ASTNode node) {
|
2026-03-24 21:04:36 -06:00
|
|
|
if (node.type == NODE_INTEGER) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (node.data.binary.op) {
|
2026-03-13 07:58:38 -06:00
|
|
|
case OP_ADD:
|
|
|
|
|
case OP_SUB:
|
|
|
|
|
return 10;
|
|
|
|
|
break;
|
|
|
|
|
case OP_DIV:
|
|
|
|
|
case OP_MUL:
|
2026-03-25 12:25:15 -06:00
|
|
|
return 20;
|
2026-03-24 21:04:36 -06:00
|
|
|
default:
|
|
|
|
|
return 0;
|
2026-03-13 07:58:38 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 21:36:14 -06:00
|
|
|
uint8_t node_rbp(ASTNode node) {
|
2026-03-24 21:04:36 -06:00
|
|
|
if (node.type == NODE_INTEGER) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (node.data.binary.op) {
|
2026-03-13 07:58:38 -06:00
|
|
|
case OP_ADD:
|
|
|
|
|
case OP_SUB:
|
2026-03-25 12:25:15 -06:00
|
|
|
return 11;
|
2026-03-13 07:58:38 -06:00
|
|
|
break;
|
|
|
|
|
case OP_DIV:
|
|
|
|
|
case OP_MUL:
|
2026-03-25 12:25:15 -06:00
|
|
|
return 21;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
2026-03-13 07:58:38 -06:00
|
|
|
}
|
|
|
|
|
}
|
2026-03-24 21:04:36 -06:00
|
|
|
|
2026-04-24 09:06:47 -06:00
|
|
|
ParseResult parse(TokenizeResult tokens) {
|
|
|
|
|
ArraySlice *context = arraylist_slice(tokens.arr, 0, arraylist_size(tokens.arr));
|
|
|
|
|
Arena arena = arena_init(sizeof(ASTNode) * arraylist_size(tokens.arr)).arena;
|
2026-03-24 21:44:08 -06:00
|
|
|
|
2026-04-13 08:44:30 -06:00
|
|
|
return (ParseResult) {
|
2026-04-24 09:06:47 -06:00
|
|
|
.is_valid = true,
|
2026-04-13 08:44:30 -06:00
|
|
|
.arena = arena,
|
2026-04-24 09:06:47 -06:00
|
|
|
.tree = parse_expr(context, &arena, 0)};
|
2026-03-24 21:44:08 -06:00
|
|
|
}
|
|
|
|
|
|
2026-04-24 09:06:47 -06:00
|
|
|
ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) {
|
2026-04-13 07:57:36 -06:00
|
|
|
arena_ensure_capacity(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ASTNode *left_side = arena_unwrap_pointer(
|
|
|
|
|
arena_alloc(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-24 09:06:47 -06:00
|
|
|
arrayslice_next(slice, left_side);
|
2026-03-24 21:36:14 -06:00
|
|
|
|
|
|
|
|
while (true) {
|
2026-04-24 09:06:47 -06:00
|
|
|
if (!arrayslice_is_valid(slice)) {
|
2026-03-24 21:36:14 -06:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-24 09:06:47 -06:00
|
|
|
ASTNode operator;
|
|
|
|
|
arrayslice_peek(slice, &operator);
|
2026-03-24 21:36:14 -06:00
|
|
|
uint8_t rbp = node_rbp(operator);
|
|
|
|
|
uint8_t lbp = node_lbp(operator);
|
|
|
|
|
|
|
|
|
|
if (lbp < min_bp) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-24 09:06:47 -06:00
|
|
|
arrayslice_next(slice, NULL);
|
2026-04-13 07:57:36 -06:00
|
|
|
ASTNode *right_side = parse_expr(slice, arena, rbp);
|
2026-03-24 21:36:14 -06:00
|
|
|
|
2026-04-13 08:44:30 -06:00
|
|
|
arena_ensure_capacity(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode));
|
|
|
|
|
ASTNode *new_node = arena_unwrap_pointer(
|
|
|
|
|
arena_alloc(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode)
|
|
|
|
|
)
|
|
|
|
|
);
|
2026-03-24 21:36:14 -06:00
|
|
|
*new_node = operator;
|
|
|
|
|
|
|
|
|
|
new_node->data.binary.left = left_side;
|
|
|
|
|
new_node->data.binary.right = right_side;
|
2026-03-24 21:04:36 -06:00
|
|
|
|
2026-03-24 21:36:14 -06:00
|
|
|
left_side = new_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return left_side;
|
|
|
|
|
}
|
2026-03-25 06:59:52 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|