moka/lib/parser.c

241 lines
5.6 KiB
C

#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;
}