roza/lib/parser.c

164 lines
3.1 KiB
C

#include "parser.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 = lexer_peek(parser->lexer, 1);
if (type == -1)
{
return NULL;
}
if (type == NODE_ASSERT)
{
return parser_try_new_assert(parser);
}
return parser_try_new_eqne(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_eqne(parser_t* parser)
{
assert(parser);
node_t* lhs = parser_try_new_cmp(parser);
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_builtin(parser);
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_builtin(parser));
lhs = node;
}
return lhs;
}
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)
{
return parser_try_new_consume(parser, next);
}
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);
return NULL;
}
return next;
}