From c03fddf47f524ef238973d752a54d04d47052f9e Mon Sep 17 00:00:00 2001 From: samsonium Date: Sun, 25 Oct 2026 04:52:18 +0300 Subject: [PATCH] fix: fixes in compiler --- src/compiler/checkers/fzl_loop_check.c | 2 + src/compiler/fzl_parser.c | 122 +++++++++++-------------- 2 files changed, 56 insertions(+), 68 deletions(-) diff --git a/src/compiler/checkers/fzl_loop_check.c b/src/compiler/checkers/fzl_loop_check.c index 8e3966d..2ce2288 100644 --- a/src/compiler/checkers/fzl_loop_check.c +++ b/src/compiler/checkers/fzl_loop_check.c @@ -11,6 +11,8 @@ ssize_t check_top; fzl_nodetype_t check_tree[256]; +// Ghost walk AST tree (w/o adding opcodes) to check if +// variable used in condition is changed void ghost_walk_changed(fzl_node_t *node, bool *changed, fzl_sym_t *sym) { if (!node || !changed || *changed) diff --git a/src/compiler/fzl_parser.c b/src/compiler/fzl_parser.c index 010bc03..5203385 100644 --- a/src/compiler/fzl_parser.c +++ b/src/compiler/fzl_parser.c @@ -158,7 +158,8 @@ fzl_node_t *parse_primary(fzl_parser_t *parser) if (!is(parser, FZL_TOKTYPE_RPAREN)) { snprintf(plast_err, sizeof(plast_err), "'%s': expected ')' at %ld:%ld", - peek(parser)->filename, peek(parser)->ln, peek(parser)->cn); + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); fzl_freeast(node); return NULL; } @@ -181,11 +182,12 @@ fzl_node_t *parse_primary(fzl_parser_t *parser) { fzl_token_t *type = consume(parser); fzl_token_t *name = consume(parser); - if (name->type != FZL_TOKTYPE_NAME) + if (!name || 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); + "'%s': expected name after type at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); return NULL; } @@ -197,8 +199,8 @@ fzl_node_t *parse_primary(fzl_parser_t *parser) 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); + "'%s': expected expression at %ld:%ld", last_known_tok->filename, + last_known_tok->ln, last_known_tok->cn); return NULL; } @@ -211,13 +213,7 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser) fzl_node_t *left = parse_primary(parser); if (!left) - { - 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; - } if (is(parser, FZL_TOKTYPE_LPAREN) || is(parser, FZL_TOKTYPE_DOT)) { @@ -260,7 +256,8 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser) fzl_freeast(left); snprintf(plast_err, sizeof(plast_err), "'%s': expected ')' after argument list at %ld:%ld", - peek(parser)->filename, peek(parser)->ln, peek(parser)->cn); + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); return NULL; } @@ -327,13 +324,7 @@ fzl_node_t *parse_power(fzl_parser_t *parser) fzl_node_t *right = NULL; if (!left) - { - 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; - } if (is(parser, FZL_TOKTYPE_CARET)) { @@ -345,8 +336,9 @@ fzl_node_t *parse_power(fzl_parser_t *parser) fzl_freeast(left); 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); + "'%s': expected expression at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); return NULL; } @@ -370,13 +362,7 @@ fzl_node_t *parse_factor(fzl_parser_t *parser) fzl_node_t *right = NULL; if (!left) - { - 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; - } while (is(parser, FZL_TOKTYPE_STAR) || is(parser, FZL_TOKTYPE_SLASH) || is(parser, FZL_TOKTYPE_PERCENT)) @@ -389,8 +375,9 @@ fzl_node_t *parse_factor(fzl_parser_t *parser) fzl_freeast(left); 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); + "'%s': expected expression at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); return NULL; } @@ -413,13 +400,7 @@ fzl_node_t *parse_term(fzl_parser_t *parser) fzl_node_t *right = NULL; if (!left) - { - 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; - } while (is(parser, FZL_TOKTYPE_PLUS) || is(parser, FZL_TOKTYPE_MINUS)) { @@ -431,8 +412,9 @@ fzl_node_t *parse_term(fzl_parser_t *parser) fzl_freeast(left); 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); + "'%s': expected expression at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); return NULL; } @@ -466,10 +448,6 @@ fzl_node_t *parse_cond(fzl_parser_t *parser) if (!right) { fzl_freeast(left); - if (!plast_err[0]) - snprintf(plast_err, sizeof(plast_err), - "'%s': unfinished expression at %ld:%ld", op->filename, op->ln, - op->cn); return NULL; } @@ -525,10 +503,6 @@ fzl_node_t *parse_and(fzl_parser_t *parser) if (!right) { fzl_freeast(left); - if (!plast_err[0]) - snprintf(plast_err, sizeof(plast_err), - "'%s': unfinished expression at %ld:%ld", or->filename, or->ln, - or->cn); return NULL; } @@ -560,10 +534,6 @@ fzl_node_t *parse_or(fzl_parser_t *parser) if (!right) { fzl_freeast(left); - if (!plast_err[0]) - snprintf(plast_err, sizeof(plast_err), - "'%s': unfinished expression at %ld:%ld", or->filename, or->ln, - or->cn); return NULL; } @@ -589,7 +559,7 @@ fzl_node_t *parse_new(fzl_parser_t *parser) { fzl_freeast(objname); snprintf(plast_err, sizeof(plast_err), - "'%s': expect class name after 'new' keyword at %ld:%ld", + "'%s': expected class name after 'new' keyword at %ld:%ld", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } @@ -610,14 +580,15 @@ fzl_node_t *parse_assignment(fzl_parser_t *parser) if (is(parser, FZL_TOKTYPE_EQ)) { fzl_token_t *asn = consume(parser); - if (left->type != FZL_NODETYPE_IDENTIFIER && - left->type != FZL_NODETYPE_DECLARATION && - left->type != FZL_NODETYPE_FIELD) + if (!left || (left->type != FZL_NODETYPE_IDENTIFIER && + left->type != FZL_NODETYPE_DECLARATION && + left->type != FZL_NODETYPE_FIELD)) { fzl_freeast(left); snprintf(plast_err, sizeof(plast_err), - "'%s': cannot assign to '%s' at %ld:%ld", left->token->filename, - (char *)left->token->value, asn->ln, asn->cn); + "'%s': cannot assign to '%s' at %ld:%ld", + last_known_tok->filename, (char *)left->token->value, + last_known_tok->ln, last_known_tok->cn); return NULL; } @@ -654,20 +625,20 @@ fzl_node_t *parse_class(fzl_parser_t *parser) fzl_token_t *class = consume(parser); fzl_token_t *name = consume(parser); - if (name->type != FZL_TOKTYPE_NAME) + if (!name || name->type != FZL_TOKTYPE_NAME) { snprintf(plast_err, sizeof(plast_err), - "'%s': expected class name at %ld:%ld", name->filename, name->ln, - name->cn); + "'%s': expected class name at %ld:%ld", last_known_tok->filename, + last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_token_t *lbrace = consume(parser); - if (lbrace->type != FZL_TOKTYPE_LBRACE) + if (!lbrace || lbrace->type != FZL_TOKTYPE_LBRACE) { snprintf(plast_err, sizeof(plast_err), - "'%s': expected '{' after class name at %ld:%ld", lbrace->filename, - lbrace->ln, lbrace->cn); + "'%s': expected '{' after class name at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } @@ -706,9 +677,9 @@ fzl_node_t *parse_class(fzl_parser_t *parser) fields = realloc(fields, fremainder * sizeof(fzl_node_t *)); if (!fields) { - fzl_freeast(node); snprintf(plast_err, sizeof(plast_err), "failed to resize fields array"); + fzl_freeast(node); free(methods); return NULL; } @@ -724,9 +695,9 @@ fzl_node_t *parse_class(fzl_parser_t *parser) methods = realloc(methods, mremainder * sizeof(fzl_node_t *)); if (!methods) { - fzl_freeast(node); snprintf(plast_err, sizeof(plast_err), "failed to resize methods array"); + fzl_freeast(node); free(fields); return NULL; } @@ -761,7 +732,8 @@ fzl_node_t *parse_class(fzl_parser_t *parser) fzl_freeast(node); snprintf(plast_err, sizeof(plast_err), "'%s': unknown type of class member at %ld:%ld", - node->token->filename, node->token->ln, node->token->cn); + last_known_tok->filename, last_known_tok->ln, + last_known_tok->cn); free(fields); free(methods); return NULL; @@ -795,7 +767,7 @@ fzl_node_t *parse_function(fzl_parser_t *parser) return NULL; fzl_token_t *fn = consume(parser); - if (fn->type != FZL_TOKTYPE_FUNCTION) + if (!fn || fn->type != FZL_TOKTYPE_FUNCTION) { snprintf(plast_err, sizeof(plast_err), "'%s': expected keyword 'fn' at %ld:%ld", last_known_tok->filename, @@ -1003,8 +975,8 @@ fzl_node_t *parse_block(fzl_parser_t *parser) free(stmts); snprintf(plast_err, sizeof(plast_err), - "'%s': missing '}' after block at %ld:%ld", rbrace->filename, - rbrace->ln, rbrace->cn); + "'%s': missing '}' after block at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } @@ -1019,7 +991,7 @@ fzl_node_t *parse_for(fzl_parser_t *parser) { fzl_token_t *tok = consume(parser); fzl_token_t *lpar = consume(parser); - if (lpar->type != FZL_TOKTYPE_LPAREN) + if (!lpar || lpar->type != FZL_TOKTYPE_LPAREN) { snprintf(plast_err, sizeof(plast_err), "'%s': expected '(' after for keyword at %ld:%ld", @@ -1202,6 +1174,13 @@ fzl_node_t *parse_loop(fzl_parser_t *parser) fzl_node_t *parse_break(fzl_parser_t *parser) { fzl_token_t *tok = consume(parser); + if (!tok) + { + snprintf(plast_err, sizeof(plast_err), "'%s': EOF", + last_known_tok->filename); + return NULL; + } + return fzl_mknode(FZL_NODETYPE_BREAK, tok); } @@ -1231,8 +1210,15 @@ fzl_node_t *parse_statement(fzl_parser_t *parser) if (!res) res = parse_expression(parser); + if (!res) + { + fzl_freeast(res); + return NULL; + } + if (!is(parser, FZL_TOKTYPE_SEMICOLON)) { + fzl_freeast(res); 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;