519 lines
10 KiB
C
519 lines
10 KiB
C
#include "parser.h"
|
|
#include "lib/commons.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_1 = lexer_peek(parser->lexer, 1);
|
|
NodeType type_2 = lexer_peek(parser->lexer, 2);
|
|
|
|
if (type_1 == -1)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (type_1 == NODE_IDENT
|
|
&& type_2 == NODE_ASSIGN)
|
|
{
|
|
return parser_try_new_varset(parser);
|
|
}
|
|
|
|
if (type_1 == NODE_IF)
|
|
{
|
|
return parser_try_new_if(parser);
|
|
}
|
|
|
|
if (type_1 == NODE_ASSERT)
|
|
{
|
|
return parser_try_new_assert(parser);
|
|
}
|
|
|
|
if (type_1 == NODE_LET)
|
|
{
|
|
return parser_try_new_vardecl(parser);
|
|
}
|
|
|
|
if (type_1 == NODE_BEGIN)
|
|
{
|
|
return parser_try_new_scope(parser);
|
|
}
|
|
|
|
return parser_try_new_or(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_vardecl(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
|
|
parser_skip(parser, NODE_LET);
|
|
node_t* ident = parser_try_new_consume(parser, NODE_IDENT);
|
|
parser_skip(parser, NODE_ASSIGN);
|
|
node_t* expr = parser_try_new_expr(parser);
|
|
|
|
node_t* node = malloc(sizeof(node_t));
|
|
node_init(node, NODE_VARDECL, "", parser->lexer->line);
|
|
|
|
node_add_new_child(node, ident);
|
|
node_add_new_child(node, expr);
|
|
|
|
return node;
|
|
}
|
|
|
|
node_t* parser_try_new_varset(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
|
|
node_t* node = malloc(sizeof(node_t));
|
|
node_init(node, NODE_VARSET, "", parser->lexer->line);
|
|
|
|
node_t* ident = parser_try_new_consume(parser, NODE_IDENT);
|
|
assert(ident);
|
|
|
|
parser_skip(parser, NODE_ASSIGN);
|
|
|
|
node_t* expr = parser_try_new_expr(parser);
|
|
assert(expr);
|
|
|
|
node_add_new_child(node, ident);
|
|
node_add_new_child(node, expr);
|
|
|
|
return node;
|
|
}
|
|
|
|
node_t* parser_try_new_block(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
|
|
node_t* block = malloc(sizeof(node_t));
|
|
node_init(block, NODE_BLOCK, "", parser->lexer->line);
|
|
|
|
while (1)
|
|
{
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_END
|
|
|| next == NODE_ELSE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
node_add_new_child(block, parser_try_new_expr(parser));
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
node_t* parser_try_new_scope(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
parser_skip(parser, NODE_BEGIN);
|
|
node_t* block = parser_try_new_block(parser);
|
|
parser_skip(parser, NODE_END);
|
|
|
|
node_t* scope = malloc(sizeof(node_t));
|
|
node_init(scope, NODE_SCOPE, "", parser->lexer->line);
|
|
node_add_new_child(scope, block);
|
|
|
|
return scope;
|
|
}
|
|
|
|
node_t* parser_try_new_if(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
|
|
node_t* node = parser_try_new_consume(parser, NODE_IF);
|
|
node_add_new_child(node, parser_try_new_expr(parser));
|
|
|
|
parser_skip(parser, NODE_THEN);
|
|
node_add_new_child(node, parser_try_new_block(parser));
|
|
|
|
int next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_ELSE)
|
|
{
|
|
parser_skip(parser, NODE_ELSE);
|
|
int n = lexer_peek(parser->lexer, 1);
|
|
|
|
if (n == NODE_IF)
|
|
{
|
|
node_add_new_child(node, parser_try_new_if(parser));
|
|
}
|
|
else
|
|
{
|
|
node_add_new_child(node, parser_try_new_block(parser));
|
|
parser_skip(parser, NODE_END);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
parser_skip(parser, NODE_END);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
node_t* parser_try_new_or(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_and(parser);
|
|
|
|
while (1)
|
|
{
|
|
int next = lexer_peek(parser->lexer, 1);
|
|
if (next != NODE_OR) { break; }
|
|
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
node_add_new_child(node, lhs);
|
|
node_add_new_child(node, parser_try_new_and(parser));
|
|
lhs = node;
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
node_t* parser_try_new_and(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_eqne(parser);
|
|
|
|
while (1)
|
|
{
|
|
int next = lexer_peek(parser->lexer, 1);
|
|
if (next != NODE_AND) { break; }
|
|
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
assert(node);
|
|
node_add_new_child(node, lhs);
|
|
node_t* eqne = parser_try_new_eqne(parser);
|
|
assert(eqne);
|
|
node_add_new_child(node, eqne);
|
|
lhs = node;
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
node_t* parser_try_new_eqne(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_cmp(parser);
|
|
assert(lhs);
|
|
|
|
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_term(parser);
|
|
assert(lhs);
|
|
|
|
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_term(parser));
|
|
lhs = node;
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
|
|
node_t* parser_try_new_term(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_factor(parser);
|
|
assert(lhs);
|
|
|
|
while (1)
|
|
{
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_ADD
|
|
|| next == NODE_SUB)
|
|
{
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
node_add_new_child(node, lhs);
|
|
node_add_new_child(node, parser_try_new_factor(parser));
|
|
|
|
lhs = node;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
node_t* parser_try_new_factor(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_power(parser);
|
|
assert(lhs);
|
|
|
|
while (1)
|
|
{
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_MUL
|
|
|| next == NODE_DIV
|
|
|| next == NODE_MODULO)
|
|
{
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
node_add_new_child(node, lhs);
|
|
node_add_new_child(node, parser_try_new_power(parser));
|
|
|
|
lhs = node;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
node_t* parser_try_new_power(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
node_t* lhs = parser_try_new_unary(parser);
|
|
assert(lhs);
|
|
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_POW)
|
|
{
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
node_add_new_child(node, lhs);
|
|
node_add_new_child(node, parser_try_new_unary(parser));
|
|
lhs = node;
|
|
}
|
|
|
|
return lhs;
|
|
}
|
|
|
|
node_t* parser_try_new_unary(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_SUB)
|
|
{
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
assert(node);
|
|
|
|
node_add_new_child(node, parser_try_new_group(parser));
|
|
assert(node);
|
|
|
|
return node;
|
|
}
|
|
|
|
if (next == NODE_NOT)
|
|
{
|
|
node_t* node = parser_try_new_consume(parser, next);
|
|
assert(node);
|
|
node_add_new_child(node, parser_try_new_unary(parser));
|
|
|
|
return node;
|
|
}
|
|
|
|
node_t* group = parser_try_new_group(parser);
|
|
assert(group);
|
|
|
|
return group;
|
|
}
|
|
|
|
node_t* parser_try_new_group(parser_t* parser)
|
|
{
|
|
assert(parser);
|
|
NodeType next = lexer_peek(parser->lexer, 1);
|
|
|
|
if (next == NODE_OPAR)
|
|
{
|
|
lexer_skip_next(parser->lexer);
|
|
node_t* node = parser_try_new_expr(parser);
|
|
assert(node);
|
|
assert(lexer_peek(parser->lexer, 1) == NODE_CPAR);
|
|
lexer_skip_next(parser->lexer);
|
|
return node;
|
|
}
|
|
|
|
node_t* builtin = parser_try_new_builtin(parser);
|
|
|
|
assert(builtin);
|
|
|
|
return builtin;
|
|
}
|
|
|
|
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
|
|
|| next == NODE_IDENT)
|
|
{
|
|
return parser_try_new_consume(parser, next);
|
|
}
|
|
|
|
if (next)
|
|
{
|
|
node_t* node = lexer_try_new_next(parser->lexer);
|
|
char nstr[RZ_STR_LIMIT];
|
|
node_str(node, nstr, RZ_STR_LIMIT);
|
|
node_free(node);
|
|
free(node);
|
|
|
|
size_t limit = RZ_STR_LIMIT + strlen(nstr);
|
|
char msg[limit];
|
|
snprintf(msg, limit, "unexpected node '%s'.", nstr);
|
|
|
|
err_fatal(parser->err, msg, parser->lexer->line);
|
|
err_dump(parser->err);
|
|
}
|
|
|
|
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);
|
|
|
|
err_dump(parser->err);
|
|
return NULL;
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
int parser_skip(parser_t* parser, NodeType type)
|
|
{
|
|
assert(parser);
|
|
|
|
node_t* next = lexer_try_new_next(parser->lexer);
|
|
assert(next);
|
|
|
|
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);
|
|
err_dump(parser->err);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
node_free(next);
|
|
free(next);
|
|
|
|
return 1;
|
|
}
|
|
}
|