#include "parser.h" #define MK_TRY(func) parser_try(self, func) void parser_init(struct parser* self, struct lexer* lexer) { assert(self); assert(lexer); self->lexer = lexer; } void parser_free(struct parser* self) { assert(self); } struct node* parser_try_new_parse(struct parser* self) { assert(self); return MK_TRY(parser_try_new_root); } struct node* parser_try(struct parser* self, struct node* (*rule)(struct parser*)) { assert(self); assert(rule); struct lex_context ctx = lexer_state(self->lexer); struct node* node = rule(self); if (node == NULL) { lexer_restore(self->lexer, ctx); } return node; } struct node* parser_try_new_root(struct parser* self) { assert(self); struct node* root = malloc(sizeof(struct node)); node_init(root, NODE_ROOT, NULL, self->lexer->context.line); while (!lexer_end(self->lexer)) { struct node* expr = MK_TRY(parser_try_new_expr); if (!expr && !lexer_end(self->lexer)) { node_free(root); free(root); return NULL; } node_add_new_child(root, expr); } return root; } struct node* parser_try_new_expr(struct parser* self) { assert(self); if (lexer_next_is(self->lexer, TOKEN_OPAR, 0)) { return MK_TRY(parser_try_new_call); } if (lexer_next_is(self->lexer, TOKEN_OSQUARE, 0)) { return MK_TRY(parser_try_new_array); } return MK_TRY(parser_try_new_atom); } struct node* parser_try_new_array(struct parser* self) { if (!lexer_next_is(self->lexer, TOKEN_OSQUARE, 0)) { return NULL; } lexer_skip(self->lexer, TOKEN_OSQUARE); struct node* array = malloc(sizeof(struct node)); node_init(array, NODE_CALL, NULL, self->lexer->context.line); while (!lexer_next_is(self->lexer, TOKEN_CSQUARE, 0)) { struct node* expr = MK_TRY(parser_try_new_expr); if (!expr) { node_free(array); free(array); return NULL; } node_add_new_child(array, expr); } if (!lexer_next_is(self->lexer, TOKEN_CSQUARE, 0)) { return NULL; } lexer_skip(self->lexer, TOKEN_CSQUARE); struct node* node = malloc(sizeof(struct node)); node_init(node, NODE_CALL, NULL, self->lexer->context.line); struct node* ident = malloc(sizeof(struct node)); struct token* tok = malloc(sizeof(struct token)); token_init(tok, TOKEN_IDENT, "quote"); node_init(ident, NODE_IDENT, tok, self->lexer->context.line); node_add_new_child(node, ident); node_add_new_child(node, array); return node; } struct node* parser_try_new_call(struct parser* self) { assert(self); if (!lexer_next_is(self->lexer, TOKEN_OPAR, 0)) { return NULL; } lexer_skip(self->lexer, TOKEN_OPAR); struct node* target = MK_TRY(parser_try_new_expr); if (!target) { return NULL; } struct node* call = malloc(sizeof(struct node)); node_init(call, NODE_CALL, NULL, target->line); node_add_new_child(call, target); while (!lexer_next_is(self->lexer, TOKEN_CPAR, 0)) { struct node* arg = MK_TRY(parser_try_new_expr); if (!arg) { node_free(target); free(target); node_free(call); free(call); node_free(arg); free(arg); return NULL; } node_add_new_child(call, arg); } if (!lexer_next_is(self->lexer, TOKEN_CPAR, 0)) { node_free(target); free(target); node_free(call); free(call); return NULL; } lexer_skip(self->lexer, TOKEN_CPAR); return call; } struct node* parser_try_new_atom(struct parser* self) { assert(self); if (lexer_next_is(self->lexer, TOKEN_FLOAT, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_FLOAT, tok, self->lexer->context.line); return node; } if (lexer_next_is(self->lexer, TOKEN_INT, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_INT, tok, self->lexer->context.line); return node; } if (lexer_next_is(self->lexer, TOKEN_BOOL, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_BOOL, tok, self->lexer->context.line); return node; } if (lexer_next_is(self->lexer, TOKEN_STRING, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_STRING, tok, self->lexer->context.line); return node; } if (lexer_next_is(self->lexer, TOKEN_SYMBOL, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_SYMBOL, tok, self->lexer->context.line); return node; } if (lexer_next_is(self->lexer, TOKEN_IDENT, 0)) { struct node* node = malloc(sizeof(struct node)); struct token* tok = lexer_try_new_next(self->lexer); assert(tok); node_init(node, NODE_IDENT, tok, self->lexer->context.line); return node; } return NULL; }