From 8d12b9d339ad375ce4e6edc4f083dc991df1b01c Mon Sep 17 00:00:00 2001 From: shabani005 Date: Tue, 5 Aug 2025 12:06:22 +0300 Subject: [PATCH] math AST parser finished. later more complex stuff --- lexer.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 16 deletions(-) diff --git a/lexer.c b/lexer.c index ee602f4..d1da94a 100644 --- a/lexer.c +++ b/lexer.c @@ -43,6 +43,7 @@ typedef enum{ TOKEN_DIV, intdef, TOKEN_UNKNOWN, + TOKEN_EOF, } symbols; typedef enum{ @@ -92,24 +93,19 @@ typedef enum{ AST_BINARY_OP, } ASTNodeType; -typedef struct{ +typedef struct ASTNode ASTNode; + +struct ASTNode { ASTNodeType type; union { - struct { - double value; - } number; + struct { double value; } number; struct { char op; - struct ASTNode* left; - struct ASTNode* right; - // x = 5 + 3 parsed into - // = - // / \ - // x / \ - // 5 3 + ASTNode* left; + ASTNode* right; } binary; - }; -} ASTNode; + } data; +}; typedef struct{ Token* tokens; @@ -144,6 +140,89 @@ bool parser_match(parser* p, symbols tokent){ } } +ASTNode* ast_new_number(double val){ + ASTNode* node = malloc(sizeof(ASTNode)); + node->type = AST_NUMBER; + node->data.number.value = val; + return node; +} + +ASTNode* ast_new_binary(char op, ASTNode* l, ASTNode* r){ + ASTNode* node = malloc(sizeof(ASTNode)); + node->type = AST_BINARY_OP; + node->data.binary.op = op; + node->data.binary.left = l; + node->data.binary.right = r; + // maybe need to fix + return node; +} + +ASTNode* parse_factor(parser* p) { + Token tok = parser_peek(p); + if (tok.type == TOKEN_EOF) { + fprintf(stderr, "Unexpected end of input in factor\n"); + exit(EXIT_FAILURE); + } + if (tok.type == TOKEN_INTEGER || tok.type == TOKEN_FLOAT) { + parser_advance(p); + double v = atof(tok.text); + return ast_new_number(v); + } + fprintf(stderr, "Unexpected token '%s' in factor\n", tok.text); + exit(EXIT_FAILURE); +} + + +ASTNode* parse_term(parser* p) { + ASTNode* node = parse_factor(p); + while (true) { + Token tok = parser_peek(p); + if (tok.type == TOKEN_MUL || tok.type == TOKEN_DIV) { + parser_advance(p); + ASTNode* right = parse_factor(p); + node = ast_new_binary(tok.text[0], node, right); + } else { + break; + } + } + return node; +} + + +ASTNode* parse_expression(parser* p) { + ASTNode* node = parse_term(p); + while (true) { + Token tok = parser_peek(p); + if (tok.type == TOKEN_PLUS || tok.type == TOKEN_MINUS) { + parser_advance(p); + ASTNode* right = parse_term(p); + node = ast_new_binary(tok.text[0], node, right); + } else { + break; + } + } + return node; +} + +double eval_ast(ASTNode* node) { + if (node->type == AST_NUMBER) { + return node->data.number.value; + } + double L = eval_ast(node->data.binary.left); + double R = eval_ast(node->data.binary.right); + switch (node->data.binary.op) { + case '+': return L + R; + case '-': return L - R; + case '*': return L * R; + case '/': return L / R; + default: + fprintf(stderr, "Unknown op '%c'\n", node->data.binary.op); + exit(EXIT_FAILURE); + } +} + + + // will implement a stack for arithmetic later. do I want a compiler or interpreter? since this is a learning experience im gonna do the easier thing first @@ -256,15 +335,25 @@ TokenArr tokenize_all(const char* input) { size_t len = strlen(input); while (i < len) { Token tok = read_from_tok((char*)input, i); - tokenarr_push(&arr, tok); i += tok.cursor_skip; + if (tok.type == TOKEN_SPACE) { + free(tok.text); + continue; + } + tokenarr_push(&arr, tok); } + Token eof = {0}; + eof.type = TOKEN_EOF; + eof.text = strdup("EOF"); + eof.text_len = 3; + eof.behaviour = BHV_UNDEFINED; + eof.cursor_skip = 0; + tokenarr_push(&arr, eof); return arr; } - // Token* c void token_parser(Token mytok, char* input){ @@ -422,8 +511,24 @@ int main4() { -int main(){ +int main5(){ char* input = "40/2.3 * 10 + 400"; printf("input: %s\n", input); mathparser(input); } + + +int main() { + const char* input = "40/2.3 * 10 + 400 - 5"; + printf("Input: %s\n", input); + + TokenArr toks = tokenize_all(input); + + parser p = { toks.unit, 0 }; + ASTNode* root = parse_expression(&p); + + double result = eval_ast(root); + printf("AST Result: %f\n", result); + return 0; +} +