164 lines
3.1 KiB
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;
|
|
}
|