feat: enhance compiler
- Add comments and test for it - Add semicolon as required end of some expressions - Add new arguments parser - Add multi-file compilation - Add colors in output
This commit is contained in:
+129
-79
@@ -7,6 +7,7 @@
|
||||
#include <string.h>
|
||||
|
||||
char plast_err[256];
|
||||
fzl_token_t *last_known_tok = NULL;
|
||||
|
||||
fzl_parser_t *fzl_mkparser(fzl_reader_ll_t *first)
|
||||
{
|
||||
@@ -50,6 +51,8 @@ static fzl_token_t *peek(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !parser->cursor)
|
||||
return NULL;
|
||||
|
||||
last_known_tok = parser->cursor->token;
|
||||
return parser->cursor->token;
|
||||
}
|
||||
|
||||
@@ -157,8 +160,8 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
|
||||
fzl_node_t *node = parse_expression(parser);
|
||||
if (!is(parser, FZL_TOKTYPE_RPAREN))
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "expected ')' at %ld:%ld",
|
||||
parser->cursor->token->ln, parser->cursor->token->cn);
|
||||
snprintf(plast_err, sizeof(plast_err), "'%s': expected ')' at %ld:%ld",
|
||||
peek(parser)->filename, peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
consume(parser);
|
||||
@@ -169,9 +172,28 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
|
||||
fzl_token_t *name = consume(parser);
|
||||
return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
||||
}
|
||||
else if (is(parser, FZL_TOKTYPE_TYPE))
|
||||
{
|
||||
fzl_token_t *type = consume(parser);
|
||||
fzl_token_t *name = consume(parser);
|
||||
if (name->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected name after type at %ld:%ld", type->filename,
|
||||
type->ln, type->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err), "failed to parse primary at %ld:%ld",
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
fzl_node_t *decl = fzl_mknode(FZL_NODETYPE_DECLARATION, type);
|
||||
decl->var.type = type;
|
||||
decl->var.identifier = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
||||
return decl;
|
||||
}
|
||||
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': failed to parse primary at %ld:%ld", peek(parser)->filename,
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -186,8 +208,10 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser)
|
||||
|
||||
if (!left)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "failed to parse postfix at %ld:%ld",
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': failed to parse postfix at %ld:%ld",
|
||||
peek(parser)->filename, peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -226,8 +250,8 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser)
|
||||
{
|
||||
free(args);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected ')' after argument list at %ld:%ld", peek(parser)->ln,
|
||||
peek(parser)->cn);
|
||||
"'%s': expected ')' after argument list at %ld:%ld",
|
||||
peek(parser)->filename, peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -274,8 +298,10 @@ fzl_node_t *parse_power(fzl_parser_t *parser)
|
||||
|
||||
if (!left)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "failed to parse power at %ld:%ld",
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': failed to parse power at %ld:%ld", peek(parser)->filename,
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -286,9 +312,10 @@ fzl_node_t *parse_power(fzl_parser_t *parser)
|
||||
right = parse_unary(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"failed to parse right side of power at %ld:%ld",
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': failed to parse right side of power at %ld:%ld",
|
||||
peek(parser)->filename, peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -314,8 +341,9 @@ fzl_node_t *parse_factor(fzl_parser_t *parser)
|
||||
if (!left)
|
||||
{
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err), "invalid expression at %ld:%ld",
|
||||
parser->cursor->token->ln, parser->cursor->token->cn);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': invalid expression at %ld:%ld", peek(parser)->filename,
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -327,9 +355,10 @@ fzl_node_t *parse_factor(fzl_parser_t *parser)
|
||||
right = parse_factor(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"unfinished factor (mul/div) expression at %ld:%ld",
|
||||
left->token->ln, left->token->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': unfinished factor (mul/div) expression at %ld:%ld",
|
||||
left->token->filename, left->token->ln, left->token->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -353,8 +382,10 @@ fzl_node_t *parse_term(fzl_parser_t *parser)
|
||||
|
||||
if (!left)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "invalid expression at %ld:%ld",
|
||||
parser->cursor->token->ln, parser->cursor->token->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': invalid expression at %ld:%ld", peek(parser)->filename,
|
||||
peek(parser)->ln, peek(parser)->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -365,9 +396,10 @@ fzl_node_t *parse_term(fzl_parser_t *parser)
|
||||
right = parse_factor(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"unfinished term (add/sub) expression at %ld:%ld",
|
||||
left->token->ln, left->token->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': unfinished term (add/sub) expression at %ld:%ld",
|
||||
left->token->filename, left->token->ln, left->token->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -400,8 +432,10 @@ fzl_node_t *parse_cond(fzl_parser_t *parser)
|
||||
right = parse_term(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
|
||||
op->ln, op->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': unfinished expression at %ld:%ld", op->filename, op->ln,
|
||||
op->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -456,8 +490,10 @@ fzl_node_t *parse_and(fzl_parser_t *parser)
|
||||
right = parse_cond(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
|
||||
or->ln, or->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': unfinished expression at %ld:%ld", or->filename, or->ln,
|
||||
or->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -488,8 +524,10 @@ fzl_node_t *parse_or(fzl_parser_t *parser)
|
||||
right = parse_and(parser);
|
||||
if (!right)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
|
||||
or->ln, or->cn);
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': unfinished expression at %ld:%ld", or->filename, or->ln,
|
||||
or->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -508,6 +546,8 @@ fzl_node_t *parse_expression(fzl_parser_t *parser) { return parse_and(parser); }
|
||||
// Statement parsing
|
||||
fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
{
|
||||
fzl_node_t *res = NULL;
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_TYPE))
|
||||
{
|
||||
fzl_token_t *type = peek(parser);
|
||||
@@ -521,8 +561,8 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (tok->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected name in function definition at %ld:%ld", tok->ln,
|
||||
tok->cn);
|
||||
"'%s': expected name in function definition at %ld:%ld",
|
||||
tok->filename, tok->ln, tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -530,7 +570,8 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected '(' after name at %ld:%ld", lparen->ln, lparen->cn);
|
||||
"'%s': expected '(' after name at %ld:%ld", lparen->filename,
|
||||
lparen->ln, lparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -540,7 +581,7 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
|
||||
while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN))
|
||||
{
|
||||
fzl_node_t *arg = parse_statement(parser);
|
||||
fzl_node_t *arg = parse_expression(parser);
|
||||
if (!arg)
|
||||
return NULL;
|
||||
|
||||
@@ -560,16 +601,16 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected ')' after argument list at %ld:%ld", rparen->ln,
|
||||
rparen->cn);
|
||||
"'%s': expected ')' after argument list at %ld:%ld",
|
||||
rparen->filename, rparen->ln, rparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!is(parser, FZL_TOKTYPE_LBRACE))
|
||||
{
|
||||
fzl_token_t *tok = peek(parser);
|
||||
snprintf(plast_err, sizeof(plast_err), "expected '{' at %ld:%ld",
|
||||
tok->ln, tok->cn);
|
||||
snprintf(plast_err, sizeof(plast_err), "'%s': expected '{' at %ld:%ld",
|
||||
tok->filename, tok->ln, tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -586,14 +627,15 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
if (type->type == FZL_TOKTYPE_TYPE || next(parser)->type == FZL_TOKTYPE_EQ)
|
||||
else if (type->type == FZL_TOKTYPE_TYPE ||
|
||||
next(parser)->type == FZL_TOKTYPE_EQ)
|
||||
{
|
||||
|
||||
fzl_node_t *identifier = parse_primary(parser);
|
||||
if (!identifier || identifier->type != FZL_NODETYPE_IDENTIFIER)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "expected identifier at %ld:%ld",
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s': expected identifier at %ld:%ld", type->filename,
|
||||
type->ln, type->cn);
|
||||
return NULL;
|
||||
}
|
||||
@@ -602,29 +644,28 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
left->var.type = type;
|
||||
left->var.identifier = identifier;
|
||||
|
||||
if (!is(parser, FZL_TOKTYPE_EQ))
|
||||
return left;
|
||||
|
||||
fzl_node_t *right;
|
||||
while (is(parser, FZL_TOKTYPE_EQ))
|
||||
if (is(parser, FZL_TOKTYPE_EQ))
|
||||
{
|
||||
fzl_token_t *asn = consume(parser);
|
||||
right = parse_expression(parser);
|
||||
if (!right)
|
||||
return NULL;
|
||||
fzl_node_t *right;
|
||||
while (is(parser, FZL_TOKTYPE_EQ))
|
||||
{
|
||||
fzl_token_t *asn = consume(parser);
|
||||
right = parse_expression(parser);
|
||||
if (!right)
|
||||
return NULL;
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_ASSIGN, asn);
|
||||
node->binary_op.left = left;
|
||||
node->binary_op.right = right;
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_ASSIGN, asn);
|
||||
node->binary_op.left = left;
|
||||
node->binary_op.right = right;
|
||||
|
||||
left = node;
|
||||
left = node;
|
||||
}
|
||||
}
|
||||
|
||||
return left;
|
||||
res = left;
|
||||
}
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_NAME) && next(parser)->type == FZL_TOKTYPE_EQ)
|
||||
else if (is(parser, FZL_TOKTYPE_NAME) && next(parser)->type == FZL_TOKTYPE_EQ)
|
||||
{
|
||||
fzl_token_t *name = consume(parser);
|
||||
fzl_node_t *left = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
||||
@@ -644,37 +685,33 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
left = assn;
|
||||
}
|
||||
|
||||
return left;
|
||||
res = left;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_RETURN))
|
||||
else if (is(parser, FZL_TOKTYPE_RETURN))
|
||||
{
|
||||
fzl_token_t *ret = consume(parser);
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret);
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_DOT))
|
||||
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||
{
|
||||
consume(parser);
|
||||
return node;
|
||||
fzl_node_t *retval = parse_expression(parser);
|
||||
if (!retval)
|
||||
return NULL;
|
||||
|
||||
node->ret.value = retval;
|
||||
}
|
||||
|
||||
fzl_node_t *retval = parse_expression(parser);
|
||||
if (!retval)
|
||||
return NULL;
|
||||
|
||||
node->ret.value = retval;
|
||||
return node;
|
||||
res = node;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_IF))
|
||||
else if (is(parser, FZL_TOKTYPE_IF))
|
||||
{
|
||||
fzl_token_t *if_tok = consume(parser);
|
||||
fzl_token_t *lparen = consume(parser);
|
||||
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected '(' before condition at %ld:%ld", lparen->ln,
|
||||
lparen->cn);
|
||||
"'%s': expected '(' before condition at %ld:%ld",
|
||||
lparen->filename, lparen->ln, lparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -686,8 +723,8 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected ')' after condition at %ld:%ld", rparen->ln,
|
||||
rparen->cn);
|
||||
"'%s': expected ')' after condition at %ld:%ld",
|
||||
rparen->filename, rparen->ln, rparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -711,8 +748,7 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
|
||||
return stmt_node;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_LBRACE))
|
||||
else if (is(parser, FZL_TOKTYPE_LBRACE))
|
||||
{
|
||||
fzl_token_t *block_tok = consume(parser);
|
||||
|
||||
@@ -735,10 +771,11 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
stmts[count++] = node;
|
||||
}
|
||||
fzl_token_t *rbrace = consume(parser);
|
||||
if (!rbrace || rbrace->type != FZL_TOKTYPE_RBRACE)
|
||||
if (rbrace && rbrace->type != FZL_TOKTYPE_RBRACE)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"missing '}' after block at %ld:%ld", rbrace->ln, rbrace->cn);
|
||||
"'%s': missing '}' after block at %ld:%ld", rbrace->filename,
|
||||
rbrace->ln, rbrace->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -748,7 +785,20 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
return node;
|
||||
}
|
||||
|
||||
return parse_expression(parser);
|
||||
if (!res)
|
||||
res = parse_expression(parser);
|
||||
|
||||
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||
{
|
||||
printf("Current token are %d\n", last_known_tok->type);
|
||||
snprintf(plast_err, sizeof(plast_err), "'%s': missing ';' at %ld:%ld",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
while (is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||
consume(parser);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Internal parsing entry point
|
||||
|
||||
Reference in New Issue
Block a user