#include "parser.h" #include "lib/lexer.h" #include "lib/node.h" void parser_init(parser_t* parser, lexer_t* lexer, err_t* err) { assert(parser); parser->lexer = lexer; parser->err = err; } void parser_free(parser_t* parser) { assert(parser); } node_t* parser_try_new_tree(parser_t* parser) { assert(parser); return parser_try_new_mod(parser); } node_t* parser_try_new_mod(parser_t* parser) { assert(parser); node_t* mod = malloc(sizeof(node_t)); node_init(mod, NODE_MOD, "", parser->lexer->line); size_t len = strlen(parser->lexer->source); while (parser->lexer->cursor < len) { node_t* expr = parser_try_new_expr(parser); if (expr) { node_add_new_child(mod, expr); } else { node_free(mod); free(mod); return NULL; } } return mod; } node_t* parser_try_new_expr(parser_t* parser) { assert(parser); NodeType type = lexer_peek(parser->lexer, 1); if (type == -1) { return NULL; } if (type == NODE_ASSERT) { return parser_try_new_assert(parser); } return parser_try_new_eqne(parser); } node_t* parser_try_new_assert(parser_t* parser) { assert(parser); node_t* node = parser_try_new_consume(parser, NODE_ASSERT); assert(node); node_t* expr = parser_try_new_expr(parser); assert(expr); node_add_new_child(node, expr); return node; } node_t* parser_try_new_eqne(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_cmp(parser); while (1) { NodeType next_type = lexer_peek(parser->lexer, 1); if (next_type == NODE_EQ || next_type == NODE_NE) { node_t* node = lexer_try_new_next(parser->lexer); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_cmp(parser)); lhs = node; } else { break; } } return lhs; } node_t* parser_try_new_cmp(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_term(parser); int next = lexer_peek(parser->lexer, 1); if (next == NODE_LT || next == NODE_GT || next == NODE_LE || next == NODE_GE) { node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_term(parser)); lhs = node; } return lhs; } node_t* parser_try_new_term(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_factor(parser); while (1) { NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_ADD || next == NODE_SUB) { node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_factor(parser)); lhs = node; } else { break; } } return lhs; } node_t* parser_try_new_factor(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_power(parser); while (1) { NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_MUL || next == NODE_DIV || next == NODE_MODULO) { node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_power(parser)); lhs = node; } else { break; } } return lhs; } node_t* parser_try_new_power(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_unary(parser); NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_POW) { node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_unary(parser)); lhs = node; } return lhs; } node_t* parser_try_new_unary(parser_t* parser) { assert(parser); NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_SUB) { node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, parser_try_new_group(parser)); return node; } return parser_try_new_group(parser); } node_t* parser_try_new_group(parser_t* parser) { assert(parser); NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_OPAR) { lexer_skip_next(parser->lexer); node_t* node = parser_try_new_expr(parser); lexer_skip_next(parser->lexer); return node; } return parser_try_new_builtin(parser); } node_t* parser_try_new_builtin(parser_t* parser) { assert(parser); NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_NUM || next == NODE_BOOL || next == NODE_STR) { return parser_try_new_consume(parser, next); } return NULL; } node_t* parser_try_new_consume(parser_t* parser, NodeType type) { assert(parser); node_t* next = lexer_try_new_next(parser->lexer); if (!next) { return NULL; } if (next->type != type) { size_t const SZ = RZ_STR_LIMIT; char err_msg[SZ]; snprintf(err_msg, SZ, "unexpected node '%s'", NodeTypeStr[next->type]); err_fatal(parser->err, err_msg, next->line); node_free(next); free(next); return NULL; } return next; }