#include "parser.h" #define CCM_TRY(rule) parser_try_new_rule(self, rule) void parser_init(parser_t* self, lexer_t* lexer) { assert(self); assert(lexer); self->lexer = lexer; err_init(&self->err); self->current = NULL; } void parser_free(parser_t* self) { err_free(&self->err); } node_t* parser_try_new_parse(parser_t* self) { assert(self); return CCM_TRY(parser_try_new_module); } node_t* parser_try_new_rule(parser_t* self, rule_t rule) { if (!err_is_ok(&self->err)) { return NULL; } lexer_state_t state = lexer_state(self->lexer); node_t* result = rule(self); if (result) { return result; } lexer_restore(self->lexer, state); return (void*) NULL; } int parser_ensure(parser_t* self, node_t* node, NodeKind kind) { assert(self); if (!node) { err_push(&self->err, self->lexer->line, "expected token '%s', got nothing", NodeKindStr[kind] + strlen("NODE_")); return 0; } if (node->kind != kind) { err_push(&self->err, self->lexer->line, "expected token '%s', got '%s'", NodeKindStr[kind] + strlen("NODE_"), NodeKindStr[node->kind] + strlen("NODE_")); return 0; } return 1; } node_t* parser_try_new_module(parser_t* self) { assert(self); node_t* module = malloc(sizeof(node_t)); node_init(module, NODE_MODULE, "", self->lexer->line); node_t* node = NULL; do { node = CCM_TRY(parser_try_new_expr); if (!node) { node_free(module); free(module); return NULL; } node_push_new_child(module, node); lexer_skip_spaces(self->lexer); } while(self->lexer->cursor < (ssize_t) strlen(self->lexer->source)); return module; } node_t* parser_try_new_expr(parser_t* self) { assert(self); if (lexer_peek_kind(self->lexer, NODE_ASSERT_EQ, 0) || lexer_peek_kind(self->lexer, NODE_ASSERT_NE, 0)) { return CCM_TRY(parser_try_new_assert); } return CCM_TRY(parser_try_new_term); } node_t* parser_try_new_assert(parser_t* self) { assert(self); node_t* node = malloc(sizeof(node_t)); if (lexer_peek_kind(self->lexer, NODE_ASSERT_EQ, 0)) { lexer_consume_next(self->lexer, NODE_ASSERT_EQ); node_init(node, NODE_ASSERT_EQ, "", self->lexer->line); } else if (lexer_peek_kind(self->lexer, NODE_ASSERT_NE, 0)) { lexer_consume_next(self->lexer, NODE_ASSERT_NE); node_init(node, NODE_ASSERT_NE, "", self->lexer->line); } else { free(node); return NULL; } node_t* tuple = CCM_TRY(parser_try_new_tuple); if (!tuple) { node_free(node); free(node); return NULL; } node_push_new_child(node, tuple); return node; } node_t* parser_try_new_term(parser_t* self) { assert(self); node_t* lhs = CCM_TRY(parser_try_new_factor); if (!lhs) { return NULL; } while (lexer_peek_kind(self->lexer, NODE_ADD, 0) || lexer_peek_kind(self->lexer, NODE_SUB, 0)) { node_t* node = lexer_try_new_next(self->lexer); node_t* rhs = CCM_TRY(parser_try_new_factor); if (!rhs) { node_free(lhs); free(lhs); node_free(node); free(node); return NULL; } node_push_new_child(node, lhs); node_push_new_child(node, rhs); lhs = node; } return lhs; } node_t* parser_try_new_factor(parser_t* self) { assert(self); node_t* lhs = CCM_TRY(parser_try_new_usub); if (!lhs) { return NULL; } while (lexer_peek_kind(self->lexer, NODE_MUL, 0) || lexer_peek_kind(self->lexer, NODE_DIV, 0) || lexer_peek_kind(self->lexer, NODE_MOD, 0)) { node_t* node = lexer_try_new_next(self->lexer); node_t* rhs = CCM_TRY(parser_try_new_usub); if (!rhs) { node_free(lhs); free(lhs); node_free(node); free(node); return NULL; } node_push_new_child(node, lhs); node_push_new_child(node, rhs); lhs = node; } return lhs; } node_t* parser_try_new_usub(parser_t* self) { assert(self); if (lexer_peek_kind(self->lexer, NODE_SUB, 0)) { lexer_consume_next(self->lexer, NODE_SUB); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_SUB, "", self->lexer->line); node_t* rhs = CCM_TRY(parser_try_new_usub); if (!rhs) { node_free(node); free(node); return NULL; } node_push_new_child(node, rhs); return node; } else { return CCM_TRY(parser_try_new_pow); } return NULL; } node_t* parser_try_new_pow(parser_t* self) { assert(self); node_t* lhs = CCM_TRY(parser_try_new_literal); if (!lhs) { return NULL; } if (lexer_peek_kind(self->lexer, NODE_POW, 0)) { if (!lexer_consume_next(self->lexer, NODE_POW)) { node_free(lhs); free(lhs); return NULL; } node_t* rhs = CCM_TRY(parser_try_new_literal); if (!rhs) { node_free(lhs); free(lhs); return NULL; } node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_POW, "", self->lexer->line); node_push_new_child(node, lhs); node_push_new_child(node, rhs); lhs = node; } return lhs; } node_t* parser_try_new_literal(parser_t* self) { assert(self); if (lexer_peek_kind(self->lexer, NODE_OPAR, 0)) { node_t* tuple = CCM_TRY(parser_try_new_tuple); if (tuple) { return tuple; } if (!lexer_consume_next(self->lexer, NODE_OPAR)) { return NULL; } node_t* expr = CCM_TRY(parser_try_new_expr); if (!lexer_consume_next(self->lexer, NODE_CPAR)) { if (expr) { node_free(expr); free(expr); } return NULL; } return expr; } return CCM_TRY(parser_try_new_builtin); } node_t* parser_try_new_tuple(parser_t* self) { assert(self); node_t* node = malloc(sizeof(node_t)); node_init(node, NODE_TUPLE, "", self->lexer->line); if (!lexer_consume_next(self->lexer, NODE_OPAR)) { node_free(node); free(node); return NULL; } node_t* lhs = CCM_TRY(parser_try_new_expr); if (!lhs) { node_free(node); free(node); return NULL; } node_push_new_child(node, lhs); int contains_more_than_one_expr = 0; while (lexer_peek_kind(self->lexer, NODE_COMMA, 0)) { lexer_consume_next(self->lexer, NODE_COMMA); node_t* child = CCM_TRY(parser_try_new_expr); if (!child) { node_free(node); free(node); return NULL; } node_push_new_child(node, child); contains_more_than_one_expr = 1; } lexer_consume_next(self->lexer, NODE_CPAR); if (!contains_more_than_one_expr) { node_free(node); free(node); return NULL; } return node; } node_t* parser_try_new_builtin(parser_t* self) { assert(self); node_t* node = lexer_try_new_next(self->lexer); parser_ensure(self, node, NODE_NUM); if (node && node->kind == NODE_NUM) { return node; } if (node) { node_free(node); free(node); } return NULL; }