2024-03-26 18:31:33 +00:00
|
|
|
#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))
|
|
|
|
{
|
2024-03-27 10:49:10 +00:00
|
|
|
struct node* expr = MK_TRY(parser_try_new_expr);
|
|
|
|
if (!expr && !lexer_end(self->lexer))
|
2024-03-26 18:31:33 +00:00
|
|
|
{
|
|
|
|
node_free(root);
|
|
|
|
free(root);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-03-27 10:49:10 +00:00
|
|
|
node_add_new_child(root, expr);
|
2024-03-26 18:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
2024-03-27 10:49:10 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
return MK_TRY(parser_try_new_atom);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-26 18:31:33 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-03-27 10:49:10 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2024-03-26 18:31:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|