refactor-error-handling #12

Merged
laentropia merged 11 commits from refactor-error-handling into main 2026-05-13 19:05:55 -06:00
3 changed files with 85 additions and 72 deletions
Showing only changes of commit 3ec73559ee - Show all commits

View File

@@ -1,7 +1,6 @@
#ifndef EVALUATOR_H #ifndef EVALUATOR_H
#define EVALUATOR_H #define EVALUATOR_H
#include "lexer.h"
#include "parser.h" #include "parser.h"
#include <stdint.h> #include <stdint.h>
@@ -20,6 +19,9 @@ typedef struct {
}; };
} EvaluatorResult; } EvaluatorResult;
EvaluatorResult evaluate_binary(Node *tree);
EvaluatorResult evaluate_unary(Node *tree);
EvaluatorResult evaluate(ParserResult context); EvaluatorResult evaluate(ParserResult context);
EvaluatorResult evaluate_tree(Node *tree); EvaluatorResult evaluate_tree(Node *tree);

View File

@@ -11,7 +11,6 @@ typedef enum {
NODE_INT, NODE_INT,
NODE_BINARY_OP, NODE_BINARY_OP,
NODE_UNARY_OP, NODE_UNARY_OP,
NODE_PARENTHESIS,
} NodeType; } NodeType;
typedef struct Node { typedef struct Node {

View File

@@ -9,81 +9,93 @@
EvaluatorResult evaluate_tree(Node *tree) { EvaluatorResult evaluate_tree(Node *tree) {
if (tree->type == NODE_BINARY_OP) { if (tree->type == NODE_BINARY_OP) {
return evaluate_binary(tree);
} else if (tree->type == NODE_UNARY_OP) {
return evaluate_unary(tree);
}
return (EvaluatorResult) {
.is_valid = true,
.val = tree->num,
};
}
EvaluatorResult evaluate_binary(Node *tree) {
Operator op = tree->binary.op; Operator op = tree->binary.op;
Node *left = tree->binary.left; Node *left = tree->binary.left;
Node *right = tree->binary.right; Node *right = tree->binary.right;
switch (op) {
case OP_ADD: {
EvaluatorResult left_result = evaluate_tree(left); EvaluatorResult left_result = evaluate_tree(left);
EvaluatorResult right_result = evaluate_tree(right); EvaluatorResult right_result = evaluate_tree(right);
if (!left_result.is_valid || !right_result.is_valid) { if (!left_result.is_valid || !right_result.is_valid) {
return left_result; return left_result;
} }
switch (op) {
case OP_ADD:
return (EvaluatorResult) { return (EvaluatorResult) {
.is_valid = true, .is_valid = true,
.val = left_result.val + right_result.val, .val = left_result.val + right_result.val,
}; };
} case OP_SUB:
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) { return (EvaluatorResult) {
.is_valid = true, .is_valid = true,
.val = left_result.val - right_result.val, .val = left_result.val - right_result.val,
}; };
} case OP_MUL:
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) { return (EvaluatorResult) {
.is_valid = true, .is_valid = true,
.val = left_result.val * right_result.val, .val = left_result.val * right_result.val,
}; };
} case OP_DIV:
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) { return (EvaluatorResult) {
.is_valid = true, .is_valid = true,
.val = left_result.val / right_result.val, .val = left_result.val / right_result.val,
}; };
} case OP_POW:
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) { return (EvaluatorResult) {
.is_valid = true, .is_valid = true,
.val = pow(left_result.val, right_result.val), .val = pow(left_result.val, right_result.val),
}; };
}
default: default:
return (EvaluatorResult) { return (EvaluatorResult) {
.is_valid = false, .is_valid = false,
.err = EVALUATOR_INVALID_TREE, .err = EVALUATOR_INVALID_TREE,
}; };
} }
} else if (tree->type == NODE_UNARY_OP) {
}
int64_t return_val = tree->data.integer;
return return_val;
} }
EvaluatorResult evaluate(ParseResult context) { EvaluatorResult evaluate_unary(Node *tree) {
Operator op = tree->unary.op;
Node *to = tree->unary.to;
EvaluatorResult result = evaluate_tree(to);
if (!result.is_valid) {
return result;
}
switch (op) {
case OP_ADD:
return result;
case OP_SUB:
return (EvaluatorResult) {
.is_valid = true,
.val = -result.val,
};
case OP_FACTORIAL:
return (EvaluatorResult) {
.is_valid = true,
.val = tgamma(result.val + 1),
};
default:
return (EvaluatorResult) {
.is_valid = false,
.err = EVALUATOR_INVALID_TREE,
};
}
}
EvaluatorResult evaluate(ParserResult context) {
if (!context.is_valid) { if (!context.is_valid) {
return (EvaluatorResult) { return (EvaluatorResult) {
.is_valid = false, .is_valid = false,