From efa0e3bacd16d72ef5c1340c3899084cbf603eb2 Mon Sep 17 00:00:00 2001 From: laentropia Date: Wed, 13 May 2026 12:13:07 -0600 Subject: [PATCH] refactor: evaluator incomplete. SO, i forgot to implement nud and led correctly and the parser cant tell apart from - as unary and - as binary (+ as well), i need to correct that, move Node * to TreeResult so to use NodeResult with nud and led --- include/evaluator.h | 19 ++++++++- include/parser.h | 1 + src/evaluator.c | 93 +++++++++++++++++++++++++++++++++++++-------- src/lexer.c | 3 ++ src/parser.c | 15 +++++++- 5 files changed, 111 insertions(+), 20 deletions(-) diff --git a/include/evaluator.h b/include/evaluator.h index 7b34e2b..5d5b4fe 100644 --- a/include/evaluator.h +++ b/include/evaluator.h @@ -5,7 +5,22 @@ #include "parser.h" #include -int64_t evaluate(ParseResult context); -int64_t evaluate_tree(ASTNode *tree); +typedef enum { + EVALUATOR_OK, + EVALUATOR_MATH_ERR, + EVALUATOR_INVALID_PARSING, + EVALUATOR_INVALID_TREE, // just to shut up the compiler with the swithces +} EvaluatorErr; + +typedef struct { + bool is_valid; + union { + int64_t val; + EvaluatorErr err; + }; +} EvaluatorResult; + +EvaluatorResult evaluate(ParserResult context); +EvaluatorResult evaluate_tree(Node *tree); #endif // !EVALUATOR_H diff --git a/include/parser.h b/include/parser.h index 0937d70..0139fca 100644 --- a/include/parser.h +++ b/include/parser.h @@ -37,6 +37,7 @@ typedef enum { PARSER_MISSING_OPERAND, PARSER_UNMATCHED_PAREN, PARSER_OUT_OF_MEMORY, + PARSER_INVALID_TOKENIZE, } ParserErr; typedef struct { diff --git a/src/evaluator.c b/src/evaluator.c index 551f779..9a8adaf 100644 --- a/src/evaluator.c +++ b/src/evaluator.c @@ -2,36 +2,97 @@ #include "arena.h" #include "lexer.h" #include "parser.h" +#include #include #include -int64_t evaluate_tree(ASTNode *tree) { +EvaluatorResult evaluate_tree(Node *tree) { if (tree->type == NODE_BINARY_OP) { - Operator op = tree->data.binary.op; - ASTNode *left = tree->data.binary.left; - ASTNode *right = tree->data.binary.right; + Operator op = tree->binary.op; + Node *left = tree->binary.left; + Node *right = tree->binary.right; switch (op) { - case OP_ADD: - return evaluate_tree(left) + evaluate_tree(right); - case OP_SUB: - return evaluate_tree(left) - evaluate_tree(right); - case OP_MUL: - return evaluate_tree(left) * evaluate_tree(right); - case OP_DIV: - return evaluate_tree(left) / evaluate_tree(right); - case OP_POW: - return pow(evaluate_tree(left), evaluate_tree(right)); + case OP_ADD: { + EvaluatorResult left_result = evaluate_tree(left); + EvaluatorResult right_result = evaluate_tree(right); + if (!left_result.is_valid || !right_result.is_valid) { + return left_result; + } + return (EvaluatorResult) { + .is_valid = true, + .val = left_result.val + right_result.val, + }; + } + case OP_SUB: { + EvaluatorResult left_result = evaluate_tree(left); + EvaluatorResult right_result = evaluate_tree(right); + if (!left_result.is_valid || !right_result.is_valid) { + return left_result; + } + return (EvaluatorResult) { + .is_valid = true, + .val = left_result.val - right_result.val, + }; + } + case OP_MUL: { + EvaluatorResult left_result = evaluate_tree(left); + EvaluatorResult right_result = evaluate_tree(right); + if (!left_result.is_valid || !right_result.is_valid) { + return left_result; + } + return (EvaluatorResult) { + .is_valid = true, + .val = left_result.val * right_result.val, + }; + } + case OP_DIV: { + EvaluatorResult left_result = evaluate_tree(left); + EvaluatorResult right_result = evaluate_tree(right); + if (!left_result.is_valid || !right_result.is_valid) { + return left_result; + } + return (EvaluatorResult) { + .is_valid = true, + .val = left_result.val / right_result.val, + }; + } + case OP_POW: { + EvaluatorResult left_result = evaluate_tree(left); + EvaluatorResult right_result = evaluate_tree(right); + if (!left_result.is_valid || !right_result.is_valid) { + return left_result; + } + return (EvaluatorResult) { + .is_valid = true, + .val = pow(left_result.val, right_result.val), + }; + } + default: + return (EvaluatorResult) { + .is_valid = false, + .err = EVALUATOR_INVALID_TREE, + }; } + } else if (tree->type == NODE_UNARY_OP) { + } int64_t return_val = tree->data.integer; return return_val; } -int64_t evaluate(ParseResult context) { - int64_t result = evaluate_tree(context.tree); +EvaluatorResult evaluate(ParseResult context) { + if (!context.is_valid) { + return (EvaluatorResult) { + .is_valid = false, + .err = EVALUATOR_INVALID_PARSING, + }; + } + + EvaluatorResult result = evaluate_tree(context.tree); + arena_destroy(&context.arena); return result; diff --git a/src/lexer.c b/src/lexer.c index 67655a2..d71d5ea 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -27,6 +27,7 @@ TokenizeResult tokenize(const char *input) { TokenResult result = tokenize_number(input, &offset); if (!result.is_valid) { + arraylist_destroy(&arr); return (TokenizeResult) {.is_valid = false, .err = result.err}; } @@ -41,6 +42,7 @@ TokenizeResult tokenize(const char *input) { } else if (isspace(input[offset])) { // Nothing... } else { + arraylist_destroy(&arr); return (TokenizeResult) { .is_valid = false, .err = LEXER_NOT_RECOGNIZED_SYMBOL}; @@ -50,6 +52,7 @@ TokenizeResult tokenize(const char *input) { } if (arraylist_size(arr) < 1) { + arraylist_destroy(&arr); return (TokenizeResult) {.is_valid = false, .err = LEXER_EMPTY_INPUT}; } diff --git a/src/parser.c b/src/parser.c index f110657..e112394 100644 --- a/src/parser.c +++ b/src/parser.c @@ -120,6 +120,8 @@ ParserU8Result infix_rbp(Node node) { } } + + Node token_to_node(Token token) { if (token.type == TOKEN_INTEGER) { return (Node) { @@ -151,7 +153,7 @@ Node token_to_node(Token token) { }; case OP_POW: return (Node) { - .type = NODE_UNARY_OP, + .type = NODE_BINARY_OP, .binary.op = token.op, }; case OP_FACTORIAL: @@ -173,17 +175,27 @@ Node token_to_node(Token token) { } ParserResult parse(TokenizeResult tokens) { + if (!tokens.is_valid) { + return (ParserResult) { + .is_valid = false, + .err = PARSER_INVALID_TOKENIZE, + }; + } + ArraySlice *context = arraylist_slice(tokens.arr, 0, arraylist_size(tokens.arr)); Arena arena = arena_init(sizeof(Node) * arraylist_size(tokens.arr)).arena; NodeResult result = parse_expr(context, &arena, 0); if (!result.is_valid) { + arena_destroy(&arena); + arraylist_destroy(&tokens.arr); return (ParserResult) { .is_valid = false, .err = result.err, }; } + arraylist_destroy(&tokens.arr); return (ParserResult) { .is_valid = true, .arena = arena, @@ -352,7 +364,6 @@ NodeResult parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { break; } - // Final: return left side return (NodeResult){ .is_valid = true,