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-05-12 18:15:36 -06:00
|
|
|
uint8_t prefix_rbp(ASTNode node) {
|
|
|
|
|
if (node.type == NODE_INTEGER) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (node.data.unary.op) {
|
|
|
|
|
case OP_SUB:
|
|
|
|
|
case OP_ADD:
|
|
|
|
|
return 5;
|
|
|
|
|
default:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t infix_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-05-12 18:15:36 -06:00
|
|
|
case OP_POW:
|
|
|
|
|
return 31;
|
2026-03-24 21:04:36 -06:00
|
|
|
default:
|
|
|
|
|
return 0;
|
2026-03-13 07:58:38 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 18:15:36 -06:00
|
|
|
uint8_t infix_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;
|
2026-05-12 18:15:36 -06:00
|
|
|
case OP_POW:
|
|
|
|
|
return 30;
|
2026-03-25 12:25:15 -06:00
|
|
|
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-05-12 18:15:36 -06:00
|
|
|
// First: Consume a first number
|
2026-04-13 07:57:36 -06:00
|
|
|
arena_ensure_capacity(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode)
|
2026-05-12 18:15:36 -06:00
|
|
|
); // shouldn't fail but if it does then what a shame
|
2026-04-13 07:57:36 -06:00
|
|
|
|
2026-05-12 18:15:36 -06:00
|
|
|
// Get pointer in the arena
|
2026-04-13 07:57:36 -06:00
|
|
|
ASTNode *left_side = arena_unwrap_pointer(
|
|
|
|
|
arena_alloc(
|
|
|
|
|
arena,
|
|
|
|
|
sizeof(ASTNode),
|
|
|
|
|
alignof(ASTNode)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
2026-05-12 18:33:52 -06:00
|
|
|
// if is unary then take prefix bp and continue
|
|
|
|
|
// to the right, no need to allocate left side
|
|
|
|
|
// because we just did and right side
|
|
|
|
|
// WILL return a valid allocated pointer.
|
|
|
|
|
if (left_side->type == NODE_UNARY_OP) {
|
|
|
|
|
uint8_t rbp = prefix_rbp(*left_side);
|
|
|
|
|
ASTNode *righ_side = parse_expr(slice, arena, rbp);
|
|
|
|
|
|
|
|
|
|
left_side->data.unary.val = righ_side;
|
|
|
|
|
return left_side;
|
|
|
|
|
}
|
2026-05-12 18:15:36 -06:00
|
|
|
// Should check if is Integer or number
|
2026-04-24 09:06:47 -06:00
|
|
|
arrayslice_next(slice, left_side);
|
2026-03-24 21:36:14 -06:00
|
|
|
|
|
|
|
|
while (true) {
|
2026-05-12 18:15:36 -06:00
|
|
|
// Second: Get next one and checn bp
|
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;
|
2026-05-12 18:15:36 -06:00
|
|
|
// Here should chekc if is operator not some bs
|
|
|
|
|
// Third, get operator and binding powers
|
2026-04-24 09:06:47 -06:00
|
|
|
arrayslice_peek(slice, &operator);
|
2026-05-12 18:15:36 -06:00
|
|
|
uint8_t rbp = infix_rbp(operator);
|
|
|
|
|
uint8_t lbp = infix_lbp(operator);
|
2026-03-24 21:36:14 -06:00
|
|
|
|
2026-05-12 18:15:36 -06:00
|
|
|
// If lbp is LESS then stop recursion,
|
|
|
|
|
// we found the next smaller binding power
|
|
|
|
|
// or the one with more precedence
|
2026-03-24 21:36:14 -06:00
|
|
|
if (lbp < min_bp) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 18:15:36 -06:00
|
|
|
|
|
|
|
|
// If NOT, then we continue wtching ahead
|
|
|
|
|
// for the next one but taking our current
|
|
|
|
|
// concern that is rbp of the current operator
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-05-12 18:15:36 -06:00
|
|
|
// Final: return left side
|
2026-03-24 21:36:14 -06:00
|
|
|
return left_side;
|
|
|
|
|
}
|
2026-03-25 06:59:52 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|