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
This commit is contained in:
@@ -5,7 +5,22 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
int64_t evaluate(ParseResult context);
|
typedef enum {
|
||||||
int64_t evaluate_tree(ASTNode *tree);
|
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
|
#endif // !EVALUATOR_H
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ typedef enum {
|
|||||||
PARSER_MISSING_OPERAND,
|
PARSER_MISSING_OPERAND,
|
||||||
PARSER_UNMATCHED_PAREN,
|
PARSER_UNMATCHED_PAREN,
|
||||||
PARSER_OUT_OF_MEMORY,
|
PARSER_OUT_OF_MEMORY,
|
||||||
|
PARSER_INVALID_TOKENIZE,
|
||||||
} ParserErr;
|
} ParserErr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -2,36 +2,97 @@
|
|||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
int64_t evaluate_tree(ASTNode *tree) {
|
EvaluatorResult evaluate_tree(Node *tree) {
|
||||||
if (tree->type == NODE_BINARY_OP) {
|
if (tree->type == NODE_BINARY_OP) {
|
||||||
Operator op = tree->data.binary.op;
|
Operator op = tree->binary.op;
|
||||||
ASTNode *left = tree->data.binary.left;
|
Node *left = tree->binary.left;
|
||||||
ASTNode *right = tree->data.binary.right;
|
Node *right = tree->binary.right;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_ADD:
|
case OP_ADD: {
|
||||||
return evaluate_tree(left) + evaluate_tree(right);
|
EvaluatorResult left_result = evaluate_tree(left);
|
||||||
case OP_SUB:
|
EvaluatorResult right_result = evaluate_tree(right);
|
||||||
return evaluate_tree(left) - evaluate_tree(right);
|
if (!left_result.is_valid || !right_result.is_valid) {
|
||||||
case OP_MUL:
|
return left_result;
|
||||||
return evaluate_tree(left) * evaluate_tree(right);
|
}
|
||||||
case OP_DIV:
|
return (EvaluatorResult) {
|
||||||
return evaluate_tree(left) / evaluate_tree(right);
|
.is_valid = true,
|
||||||
case OP_POW:
|
.val = left_result.val + right_result.val,
|
||||||
return pow(evaluate_tree(left), evaluate_tree(right));
|
};
|
||||||
|
}
|
||||||
|
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;
|
int64_t return_val = tree->data.integer;
|
||||||
return return_val;
|
return return_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t evaluate(ParseResult context) {
|
EvaluatorResult evaluate(ParseResult context) {
|
||||||
int64_t result = evaluate_tree(context.tree);
|
if (!context.is_valid) {
|
||||||
|
return (EvaluatorResult) {
|
||||||
|
.is_valid = false,
|
||||||
|
.err = EVALUATOR_INVALID_PARSING,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
EvaluatorResult result = evaluate_tree(context.tree);
|
||||||
|
|
||||||
arena_destroy(&context.arena);
|
arena_destroy(&context.arena);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ TokenizeResult tokenize(const char *input) {
|
|||||||
TokenResult result = tokenize_number(input, &offset);
|
TokenResult result = tokenize_number(input, &offset);
|
||||||
|
|
||||||
if (!result.is_valid) {
|
if (!result.is_valid) {
|
||||||
|
arraylist_destroy(&arr);
|
||||||
return (TokenizeResult) {.is_valid = false, .err = result.err};
|
return (TokenizeResult) {.is_valid = false, .err = result.err};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ TokenizeResult tokenize(const char *input) {
|
|||||||
} else if (isspace(input[offset])) {
|
} else if (isspace(input[offset])) {
|
||||||
// Nothing...
|
// Nothing...
|
||||||
} else {
|
} else {
|
||||||
|
arraylist_destroy(&arr);
|
||||||
return (TokenizeResult) {
|
return (TokenizeResult) {
|
||||||
.is_valid = false,
|
.is_valid = false,
|
||||||
.err = LEXER_NOT_RECOGNIZED_SYMBOL};
|
.err = LEXER_NOT_RECOGNIZED_SYMBOL};
|
||||||
@@ -50,6 +52,7 @@ TokenizeResult tokenize(const char *input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arraylist_size(arr) < 1) {
|
if (arraylist_size(arr) < 1) {
|
||||||
|
arraylist_destroy(&arr);
|
||||||
return (TokenizeResult) {.is_valid = false, .err = LEXER_EMPTY_INPUT};
|
return (TokenizeResult) {.is_valid = false, .err = LEXER_EMPTY_INPUT};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/parser.c
15
src/parser.c
@@ -120,6 +120,8 @@ ParserU8Result infix_rbp(Node node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Node token_to_node(Token token) {
|
Node token_to_node(Token token) {
|
||||||
if (token.type == TOKEN_INTEGER) {
|
if (token.type == TOKEN_INTEGER) {
|
||||||
return (Node) {
|
return (Node) {
|
||||||
@@ -151,7 +153,7 @@ Node token_to_node(Token token) {
|
|||||||
};
|
};
|
||||||
case OP_POW:
|
case OP_POW:
|
||||||
return (Node) {
|
return (Node) {
|
||||||
.type = NODE_UNARY_OP,
|
.type = NODE_BINARY_OP,
|
||||||
.binary.op = token.op,
|
.binary.op = token.op,
|
||||||
};
|
};
|
||||||
case OP_FACTORIAL:
|
case OP_FACTORIAL:
|
||||||
@@ -173,17 +175,27 @@ Node token_to_node(Token token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ParserResult parse(TokenizeResult tokens) {
|
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));
|
ArraySlice *context = arraylist_slice(tokens.arr, 0, arraylist_size(tokens.arr));
|
||||||
Arena arena = arena_init(sizeof(Node) * arraylist_size(tokens.arr)).arena;
|
Arena arena = arena_init(sizeof(Node) * arraylist_size(tokens.arr)).arena;
|
||||||
|
|
||||||
NodeResult result = parse_expr(context, &arena, 0);
|
NodeResult result = parse_expr(context, &arena, 0);
|
||||||
if (!result.is_valid) {
|
if (!result.is_valid) {
|
||||||
|
arena_destroy(&arena);
|
||||||
|
arraylist_destroy(&tokens.arr);
|
||||||
return (ParserResult) {
|
return (ParserResult) {
|
||||||
.is_valid = false,
|
.is_valid = false,
|
||||||
.err = result.err,
|
.err = result.err,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arraylist_destroy(&tokens.arr);
|
||||||
return (ParserResult) {
|
return (ParserResult) {
|
||||||
.is_valid = true,
|
.is_valid = true,
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
@@ -352,7 +364,6 @@ NodeResult parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Final: return left side
|
// Final: return left side
|
||||||
return (NodeResult){
|
return (NodeResult){
|
||||||
.is_valid = true,
|
.is_valid = true,
|
||||||
|
|||||||
Reference in New Issue
Block a user