#include "parser.h" #include "arraylist.h" #include "lexer.h" #include "arena.h" #include #include #include 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 30; default: return -1; } } uint8_t postfix_lbp(ASTNode node) { if (node.type == NODE_INTEGER) { return 0; } switch (node.data.unary.op) { case OP_FACTORIAL: return 40; default: // needs to be dealt with with resulttypes return 255; } } uint8_t infix_lbp(ASTNode node) { if (node.type == NODE_INTEGER) { return 0; } switch (node.data.binary.op) { case OP_ADD: case OP_SUB: return 10; break; case OP_DIV: case OP_MUL: return 20; case OP_POW: return 51; default: return 0; } } uint8_t infix_rbp(ASTNode node) { if (node.type == NODE_INTEGER) { return 0; } switch (node.data.binary.op) { case OP_ADD: case OP_SUB: return 11; break; case OP_DIV: case OP_MUL: return 21; case OP_POW: return 50; default: return 0; } } 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; return (ParseResult) { .is_valid = true, .arena = arena, .tree = parse_expr(context, &arena, 0)}; } ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { // First: Consume a first number arena_ensure_capacity( arena, sizeof(ASTNode), alignof(ASTNode) ); // shouldn't fail but if it does then what a shame // Get pointer in the arena ASTNode *left_side = arena_unwrap_pointer( arena_alloc( arena, sizeof(ASTNode), alignof(ASTNode) ) ); // 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; } // Should check if is Integer or number arrayslice_next(slice, left_side); while (true) { // Second: Get next one and checn bp if (!arrayslice_is_valid(slice)) { break; } // Here check if not OP error ASTNode operator; // Here should chekc if is operator not some bs // Third, get operator and binding powers arrayslice_peek(slice, &operator); // temporary for bad error handling if (postfix_lbp(operator) != 255) { if (postfix_lbp(operator) < min_bp) { break; } // allocate operator arrayslice_next(slice, NULL); arena_ensure_capacity( arena, sizeof(ASTNode), alignof(ASTNode)); ASTNode *new_node = arena_unwrap_pointer( arena_alloc( arena, sizeof(ASTNode), alignof(ASTNode) ) ); *new_node = operator; new_node->data.unary.val = left_side; left_side = new_node; } uint8_t rbp = infix_rbp(operator); uint8_t lbp = infix_lbp(operator); // If lbp is LESS then stop recursion, // we found the next smaller binding power // or the one with more precedence if (lbp < min_bp) { break; } // If NOT, then we continue wtching ahead // for the next one but taking our current // concern that is rbp of the current operator arrayslice_next(slice, NULL); ASTNode *right_side = parse_expr(slice, arena, rbp); arena_ensure_capacity( arena, sizeof(ASTNode), alignof(ASTNode)); ASTNode *new_node = arena_unwrap_pointer( arena_alloc( arena, sizeof(ASTNode), alignof(ASTNode) ) ); *new_node = operator; new_node->data.binary.left = left_side; new_node->data.binary.right = right_side; left_side = new_node; } // Final: return left side return left_side; }