ref: split parser into separate files
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// For-loop parsing
|
||||
fzl_node_t *pa_for(fzl_parser_t *parser)
|
||||
{
|
||||
fzl_token_t *tok = consume(parser);
|
||||
fzl_token_t *lpar = consume(parser);
|
||||
if (!lpar || lpar->type != FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected '(' after for keyword at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *start = NULL;
|
||||
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||
{
|
||||
start = pa_expression(parser);
|
||||
if (!start)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected loop init or ';' at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *sc = consume(parser);
|
||||
if (!sc || sc->type != FZL_TOKTYPE_SEMICOLON)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': missing ';' after init section at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
consume(parser);
|
||||
|
||||
fzl_node_t *condition = NULL;
|
||||
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||
{
|
||||
condition = pa_expression(parser);
|
||||
if (!condition)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected loop condition or ';' at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *sc = consume(parser);
|
||||
if (!sc || sc->type != FZL_TOKTYPE_SEMICOLON)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
fzl_freeast(condition);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': missing ';' after condition at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
consume(parser);
|
||||
|
||||
fzl_node_t *step = NULL;
|
||||
if (!is(parser, FZL_TOKTYPE_RPAREN))
|
||||
{
|
||||
step = pa_expression(parser);
|
||||
if (!step)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
fzl_freeast(condition);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected loop step end or ')' at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fzl_token_t *rpar = consume(parser);
|
||||
if (!rpar || rpar->type != FZL_TOKTYPE_RPAREN)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
fzl_freeast(condition);
|
||||
fzl_freeast(step);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': missing ')' after loop setup at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *body = pa_statement(parser);
|
||||
if (!body)
|
||||
{
|
||||
fzl_freeast(start);
|
||||
fzl_freeast(condition);
|
||||
fzl_freeast(step);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': missing body of for loop at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_LOOP, tok);
|
||||
node->loop.init = start;
|
||||
node->loop.cond = condition;
|
||||
node->loop.step = step;
|
||||
node->loop.body = body;
|
||||
|
||||
return node;
|
||||
}
|
||||
Reference in New Issue
Block a user