#include "parser.h" #include "lib/commons.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_1 = lexer_peek(parser->lexer, 1); NodeType type_2 = lexer_peek(parser->lexer, 2); if (type_1 == -1) { return NULL; } if (type_1 == NODE_IDENT && type_2 == NODE_ASSIGN) { return parser_try_new_varset(parser); } if (type_1 == NODE_IF) { return parser_try_new_if(parser); } if (type_1 == NODE_ASSERT) { return parser_try_new_assert(parser); } if (type_1 == NODE_LET) { return parser_try_new_vardecl(parser); } if (type_1 == NODE_FUN) { return parser_try_new_fundecl(parser); } if (type_1 == NODE_RETURN) { return parser_try_new_return(parser); } if (type_1 == NODE_BEGIN) { return parser_try_new_scope(parser); } return parser_try_new_or(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_vardecl(parser_t* parser) { assert(parser); parser_skip(parser, NODE_LET); node_t* ident = parser_try_new_consume(parser, NODE_IDENT); parser_skip(parser, NODE_ASSIGN); node_t* expr = parser_try_new_expr(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_VARDECL, "", parser->lexer->line); node_add_new_child(node, ident); node_add_new_child(node, expr); return node; } node_t* parser_try_new_fundecl(parser_t* parser) { assert(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_FUNDECL, "", parser->lexer->line); parser_skip(parser, NODE_FUN); node_t* ident = parser_try_new_consume(parser, NODE_IDENT); node_add_new_child(node, ident); parser_skip(parser, NODE_OPAR); node_add_new_child(node, parser_try_new_params(parser)); parser_skip(parser, NODE_CPAR); node_add_new_child(node, parser_try_new_block(parser)); parser_skip(parser, NODE_END); return node; } node_t* parser_try_new_params(parser_t* parser) { assert(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_PARAMS, "", parser->lexer->line); int next = lexer_peek(parser->lexer, 1); if (next == NODE_CPAR) { return node; } node_add_new_child(node, parser_try_new_consume(parser, NODE_IDENT)); while (1) { int next_1 = lexer_peek(parser->lexer, 1); if (next_1 != NODE_COMMA) { break; } parser_skip(parser, NODE_COMMA); node_add_new_child(node, parser_try_new_consume(parser, NODE_IDENT)); } return node; } node_t* parser_try_new_return(parser_t* parser) { assert(parser); node_t* node = parser_try_new_consume(parser, NODE_RETURN); node_add_new_child(node, parser_try_new_expr(parser)); return node; } node_t* parser_try_new_varset(parser_t* parser) { assert(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_VARSET, "", parser->lexer->line); node_t* ident = parser_try_new_consume(parser, NODE_IDENT); assert(ident); parser_skip(parser, NODE_ASSIGN); node_t* expr = parser_try_new_expr(parser); assert(expr); node_add_new_child(node, ident); node_add_new_child(node, expr); return node; } node_t* parser_try_new_block(parser_t* parser) { assert(parser); node_t* block = malloc(sizeof(node_t)); node_init(block, NODE_BLOCK, "", parser->lexer->line); while (1) { NodeType next = lexer_peek(parser->lexer, 1); if (next == NODE_END || next == NODE_ELSE) { break; } node_add_new_child(block, parser_try_new_expr(parser)); } return block; } node_t* parser_try_new_scope(parser_t* parser) { assert(parser); parser_skip(parser, NODE_BEGIN); node_t* block = parser_try_new_block(parser); parser_skip(parser, NODE_END); node_t* scope = malloc(sizeof(node_t)); node_init(scope, NODE_SCOPE, "", parser->lexer->line); node_add_new_child(scope, block); return scope; } node_t* parser_try_new_if(parser_t* parser) { assert(parser); node_t* node = parser_try_new_consume(parser, NODE_IF); node_add_new_child(node, parser_try_new_expr(parser)); parser_skip(parser, NODE_THEN); node_add_new_child(node, parser_try_new_block(parser)); int next = lexer_peek(parser->lexer, 1); if (next == NODE_ELSE) { parser_skip(parser, NODE_ELSE); int n = lexer_peek(parser->lexer, 1); if (n == NODE_IF) { node_add_new_child(node, parser_try_new_if(parser)); } else { node_add_new_child(node, parser_try_new_block(parser)); parser_skip(parser, NODE_END); } } else { parser_skip(parser, NODE_END); } return node; } node_t* parser_try_new_or(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_and(parser); while (1) { int next = lexer_peek(parser->lexer, 1); if (next != NODE_OR) { break; } node_t* node = parser_try_new_consume(parser, next); node_add_new_child(node, lhs); node_add_new_child(node, parser_try_new_and(parser)); lhs = node; } return lhs; } node_t* parser_try_new_and(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_eqne(parser); while (1) { int next = lexer_peek(parser->lexer, 1); if (next != NODE_AND) { break; } node_t* node = parser_try_new_consume(parser, next); assert(node); node_add_new_child(node, lhs); node_t* eqne = parser_try_new_eqne(parser); assert(eqne); node_add_new_child(node, eqne); lhs = node; } return lhs; } node_t* parser_try_new_eqne(parser_t* parser) { assert(parser); node_t* lhs = parser_try_new_cmp(parser); assert(lhs); 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); assert(lhs); 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); assert(lhs); 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); assert(lhs); 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); assert(lhs); 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); assert(node); node_add_new_child(node, parser_try_new_group(parser)); assert(node); return node; } if (next == NODE_NOT) { node_t* node = parser_try_new_consume(parser, next); assert(node); node_add_new_child(node, parser_try_new_unary(parser)); return node; } node_t* group = parser_try_new_group(parser); assert(group); return group; } 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); assert(node); assert(lexer_peek(parser->lexer, 1) == NODE_CPAR); lexer_skip_next(parser->lexer); return node; } return parser_try_new_literal(parser); } node_t* parser_try_new_literal(parser_t* parser) { assert(parser); int type_1 = lexer_peek(parser->lexer, 1); int type_2 = lexer_peek(parser->lexer, 2); if (type_1 == NODE_IDENT && type_2 == NODE_OPAR) { return parser_try_new_funcall(parser); } return parser_try_new_builtin(parser); } node_t* parser_try_new_funcall(parser_t* parser) { assert(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_FUNCALL, "", parser->lexer->line); node_add_new_child(node, parser_try_new_consume(parser, NODE_IDENT)); parser_skip(parser, NODE_OPAR); node_add_new_child(node, parser_try_new_args(parser)); parser_skip(parser, NODE_CPAR); return node; } node_t* parser_try_new_args(parser_t* parser) { assert(parser); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_ARGS, "", parser->lexer->line); int next = lexer_peek(parser->lexer, 1); if (next == NODE_CPAR) { return node; } node_t* arg = parser_try_new_expr(parser); node_add_new_child(node, arg); while ((next = lexer_peek(parser->lexer, 1)) == NODE_COMMA) { parser_skip(parser, NODE_COMMA); node_add_new_child(node, parser_try_new_expr(parser)); } return node; } 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 || next == NODE_IDENT) { return parser_try_new_consume(parser, next); } if (next) { node_t* node = lexer_try_new_next(parser->lexer); char nstr[RZ_STR_LIMIT]; node_str(node, nstr, RZ_STR_LIMIT); node_free(node); free(node); size_t limit = RZ_STR_LIMIT + strlen(nstr); char msg[limit]; snprintf(msg, limit, "unexpected node '%s'.", nstr); err_fatal(parser->err, msg, parser->lexer->line); err_dump(parser->err); } 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); err_dump(parser->err); return NULL; } return next; } int parser_skip(parser_t* parser, NodeType type) { assert(parser); node_t* next = lexer_try_new_next(parser->lexer); assert(next); 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); err_dump(parser->err); return 0; } else { node_free(next); free(next); return 1; } }