refactor-error-handling #12
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
152
src/evaluator.c
152
src/evaluator.c
@@ -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) {
|
||||||
Operator op = tree->binary.op;
|
return evaluate_binary(tree);
|
||||||
Node *left = tree->binary.left;
|
|
||||||
Node *right = tree->binary.right;
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
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) {
|
} else if (tree->type == NODE_UNARY_OP) {
|
||||||
|
return evaluate_unary(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t return_val = tree->data.integer;
|
return (EvaluatorResult) {
|
||||||
return return_val;
|
.is_valid = true,
|
||||||
|
.val = tree->num,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
EvaluatorResult evaluate(ParseResult context) {
|
EvaluatorResult evaluate_binary(Node *tree) {
|
||||||
|
Operator op = tree->binary.op;
|
||||||
|
Node *left = tree->binary.left;
|
||||||
|
Node *right = tree->binary.right;
|
||||||
|
|
||||||
|
EvaluatorResult left_result = evaluate_tree(left);
|
||||||
|
EvaluatorResult right_result = evaluate_tree(right);
|
||||||
|
if (!left_result.is_valid || !right_result.is_valid) {
|
||||||
|
return left_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case OP_ADD:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = true,
|
||||||
|
.val = left_result.val + right_result.val,
|
||||||
|
};
|
||||||
|
case OP_SUB:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = true,
|
||||||
|
.val = left_result.val - right_result.val,
|
||||||
|
};
|
||||||
|
case OP_MUL:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = true,
|
||||||
|
.val = left_result.val * right_result.val,
|
||||||
|
};
|
||||||
|
case OP_DIV:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = true,
|
||||||
|
.val = left_result.val / right_result.val,
|
||||||
|
};
|
||||||
|
case OP_POW:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = true,
|
||||||
|
.val = pow(left_result.val, right_result.val),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = false,
|
||||||
|
.err = EVALUATOR_INVALID_TREE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
|||||||
Reference in New Issue
Block a user