diff options
author | Himbeer <himbeer@disroot.org> | 2025-05-05 11:54:58 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2025-05-05 11:54:58 +0200 |
commit | 828f7cfe05eec5547837867101fc662c3dea60f1 (patch) | |
tree | d42580915bc74937c9d5bf14f678679bc3ab3d35 | |
parent | c640c9856b499af2ed5faedbf03e9945d74aafa9 (diff) |
Define overhauled AST data structures
-rw-r--r-- | include/cmd.h | 66 | ||||
-rw-r--r-- | include/expr.h | 289 | ||||
-rw-r--r-- | include/literal.h | 20 | ||||
-rw-r--r-- | include/parse.h | 170 | ||||
-rw-r--r-- | src/parse.c | 1479 |
5 files changed, 260 insertions, 1764 deletions
diff --git a/include/cmd.h b/include/cmd.h deleted file mode 100644 index 2cf69b4..0000000 --- a/include/cmd.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef CERC_CMD_H -#define CERC_CMD_H -#include "type.h" - -struct ast_return { - struct ast_expr *value; -}; - -struct ast_break { - const char *label; - struct ast_expr *value; -}; - -struct ast_declaration { - bool mut; - const char *name; - struct ast_expr *value; -}; - -enum statement { - STM_RETURN, - STM_BREAK, - STM_CONTINUE, - STM_DECL, - STM_DEFER, -}; - -struct ast_statement { - enum statement action; - union { - struct ast_return ret; - struct ast_break brk; - struct ast_declaration decl; - struct assign_e *assign; - struct call_e *call; - } stmt; -}; - -struct ast_func { - bool exported; - const char *name; - struct type *ret; - struct ast_param *params; - int paramsz, paramlen; - struct ast_block *block; -}; -struct ast_block { - const char *label; - struct ast_cmd *cmds; - int cmdsz, cmdlen; -}; - -enum command { - CMD_BLOCK, - CMD_STATEMENT, -}; - -struct ast_cmd { - enum command kind; - union { - struct ast_block blk; - struct ast_statement stmt; - } cmd; -}; - -#endif diff --git a/include/expr.h b/include/expr.h index 5f57349..9d4d50a 100644 --- a/include/expr.h +++ b/include/expr.h @@ -1,249 +1,178 @@ #ifndef CERC_EXPR_H #define CERC_EXPR_H #include <stdbool.h> -#include "cmd.h" #include "lex.h" +#include "literal.h" #include "type.h" -struct number_e { - struct number value; - struct type *type; +enum valuekind { + V_LITERAL, + V_NAME, }; -struct array_e { - struct cer_array *meta; - struct disjunction_e *elems; - int elemsz, elemlen; -}; - -struct elseif { - struct disjunction_e *cond; - struct ast_block blk; -}; - -struct if_e { - struct disjunction_e *cond; - struct ast_block blk; - struct elseif *alts; - struct ast_block *alt; - int altsz, altlen; -}; - -struct for_e { - struct ast_assign *init, *action; - struct disjunction_e *cond; - struct ast_block blk; -}; - -enum control { - CTL_IF, - CTL_FOR, -}; - -struct control_e { - enum control kind; +struct value_e { + enum valuekind kind; union { - struct if_e branch; - struct for_e loop; - } ctl; + struct literal lit; + const char *name; + } v; }; -enum literal { - LIT_BOOL, - LIT_STRING, - LIT_NUMBER, - LIT_ARRAY, -}; - -struct literal_e { - enum literal kind; +struct grp_e { + int isgrouped; union { - bool b; - char *str; - struct number_e num; - struct array_e arr; - } lit; -}; - -struct location_e { - struct path *path; - struct loc_postfix *subs; - int subsz, sublen; -}; - -struct assign_e { - struct location_e dst; - struct ast_expr *value; + struct expr *grouped; + struct value_e value; + } inner; }; struct call_e { - struct location_e *loc; - struct disjunction_e *args; + struct expr *args; int argsz, arglen; }; -enum named { - NMD_ASSIGN, - NMD_CALL, - NMD_LOCATION, +enum access { + AC_NONE, + AC_FIELD, + AC_INDEX, + AC_CALL, }; -struct named_e { - enum named kind; - struct location_e loc; +struct access_e { + struct grp_e grp; + enum access kind; union { - struct assign_e assign; + const char *field; + struct expr *index; struct call_e call; - } nmd; + } ac; + struct access_e *next; }; -enum primary { - PRM_CONTROL, - PRM_GROUPING, - PRM_LITERAL, - PRM_NAMED, +struct tag_e { + int dotagof; + struct access_e access; }; -struct primary_e { - enum primary kind; - union { - struct control_e ctl; - struct disjunction_e *grp; - struct literal_e lit; - struct named_e nmd; - } prim; +enum signop { + SIGN_NONE, + SIGN_POS, + SIGN_NEG, }; -enum unary_postfix { - UPS_NONE, - UPS_DEREF, - UPS_TRY, - UPS_ASSERT, +struct sign_e { + enum signop op; + struct tag_e tag; }; -struct unarypost_e { - enum unary_postfix op; - struct primary_e prim; +enum invop { + INV_NONE, + INV_BITS, + INV_BOOL, }; -enum unary_prefix { - UPR_NONE, - UPR_NEG, - UPR_INVERT, - UPR_BNEG, -}; - -struct unarypre_e { - enum unary_prefix op; - struct unarypost_e post; +struct inv_e { + enum invop op; + union { + struct inv_e *inv; + struct sign_e sign; + } oper; }; -struct bitfactor_e { - struct unarypre_e lhs, *rhs; - int rhssz, rhslen; +struct deref_e { + int doderef; + union { + struct deref_e *deref; + struct inv_e inv; + } inner; }; -struct bitsummand_e { - struct bitfactor_e lhs, *rhs; - int rhssz, rhslen; +struct ref_e { + int doref; + struct deref_e inner; }; -struct bin_e { - struct bitsummand_e lhs, *rhs; - int rhssz, rhslen; +struct as_e { + struct ref_e lhs; + struct type *cast; }; -enum factor { - FCT_MUL, - FCT_DIV, - FCT_REM, +struct bitand_e { + struct as_e lhs; + struct bitand_e *rhs; }; -struct factor_rhs { - enum factor factor; - struct bin_e bin; +struct bitxor_e { + struct bitand_e lhs; + struct bitxor_e *rhs; }; -struct factor_e { - struct bin_e lhs; - struct factor_rhs *rhs; - int rhssz, rhslen; +struct bitor_e { + struct bitxor_e lhs; + struct bitor_e *rhs; }; -enum numeral { - NUM_ADD, - NUM_SUB, +enum productop { + PRODUCT_NONE, + PRODUCT_MUL, + PRODUCT_DIV, + PRODUCT_REM, }; -struct num_rhs { - enum numeral num; - struct factor_e factor; +struct product_e { + struct bitor_e lhs; + enum productop op; + struct product_e *rhs; }; -struct num_e { - struct factor_e lhs; - struct num_rhs *rhs; - int rhssz, rhslen; +enum sumop { + SUM_NONE, + SUM_ADD, + SUM_SUB, }; -enum term { - TRM_NUM, - TRM_SHL, - TRM_SHR, +struct sum_e { + struct product_e lhs; + enum sumop op; + struct sum_e *rhs; }; -struct term_e { - enum term term; - struct num_e lhs, *rhs; +enum shiftop { + SHIFT_NONE, + SHIFT_LEFT, + SHIFT_RIGHT, }; -enum comparison { - CMP_LT, - CMP_LE, - CMP_GT, - CMP_GE, +struct shift_e { + struct sum_e lhs; + enum shiftop op; + struct shift_e *rhs; }; -struct cmp_rhs { - enum comparison cmp; - struct term_e term; +enum cmpop { + CMP_NONE, + CMP_LESS, + CMP_LESS_EQ, + CMP_EQ, + CMP_NEQ, + CMP_GREATER_EQ, + CMP_GREATER, }; struct cmp_e { - struct term_e lhs; - struct cmp_rhs *rhs; - int rhssz, rhslen; -}; - -struct eq_e { - bool invert; - struct cmp_e lhs, *rhs; -}; - -enum boolean { - B_EQ, - B_CMP, -}; - -struct bool_e { - enum boolean kind; - union { - struct eq_e eq; - struct cmp_e cmp; - } cond; + struct shift_e lhs; + enum cmpop op; + struct shift_e *rhs; }; struct conjunction_e { - // At least one required - struct bool_e *bools; - int boolsz, boollen; + struct cmp_e lhs; + struct conjunction_e *rhs; }; -// Entry point -struct disjunction_e { - // At least one required - struct conjunction_e *cons; - int consz, conlen; +struct expr { + struct conjunction_e lhs; + struct expr *rhs; }; #endif diff --git a/include/literal.h b/include/literal.h new file mode 100644 index 0000000..912dce0 --- /dev/null +++ b/include/literal.h @@ -0,0 +1,20 @@ +#ifndef CERC_LITERAL_H +#define CERC_LITERAL_H +enum litkind { + LIT_INT, + LIT_FLOAT, + LIT_CHR, + LIT_STR, +}; + +struct literal { + enum litkind kind; + union { + int n; + double x; + int c; + const char *s; + } v; +}; + +#endif diff --git a/include/parse.h b/include/parse.h index 5b97353..64d1eac 100644 --- a/include/parse.h +++ b/include/parse.h @@ -2,77 +2,167 @@ #define CERC_PARSE_H #include "expr.h" -struct ast_expr { - struct disjunction_e dis; +struct ast_local { + const char *name; + struct type type; + struct expr *init; }; -struct ast_externfunc { - const char *name; - struct type ret; - struct type *params; - int paramsz, paramlen; +struct ast_assign { + struct expr lhs; + struct expr rhs; +}; + +enum crement { + INCREMENT, + DECREMENT, +}; + +struct ast_elsebody { + struct ast_stmt *stmts; + int stmtsz, stmtlen; +}; + +struct ast_else { + int cond; + union { + struct ast_if *conditional; + struct ast_elsebody body; + } action; +}; + +struct ast_if { + struct expr cond; + struct ast_stmt *stmts; + int stmtsz, stmtlen; + struct ast_else *alt; +}; + +struct ast_for { + struct ast_stmt *init; + struct expr cond; + struct ast_stmt *step; + struct ast_stmt *stmts; + int stmtsz, stmtlen; +}; + +struct ast_return { + struct expr *value; +}; + +enum stmt { + S_LOCALVAR, + S_ASSIGN, + S_ADDASSIGN, + S_SUBASSIGN, + S_MULASSIGN, + S_DIVASSIGN, + S_REMASSIGN, + S_ANDASSIGN, + S_ORASSIGN, + S_XORASSIGN, + S_INCR, + S_DECR, + S_IF, + S_FOR, + S_RETURN, + S_EXPR, }; -struct ast_param { +struct ast_stmt { + enum stmt kind; + union { + struct ast_local localvar; + struct ast_assign assign; + enum crement cre; + struct ast_if conditional; + struct ast_for loop; + struct ast_return ret; + struct expr e; + } stmt; +}; + +struct ast_include { + const char *path; +}; + +struct ast_global { const char *name; + int ispub; + int isextern; struct type type; }; -enum subfield { - SUB_INDEX, - SUB_FIELD, +struct ast_const { + const char *name; + struct expr value; }; -struct loc_postfix { - enum subfield sub; - union { - struct ast_expr index; - const char *field; - } id; +struct ast_enumvar { + const char *name; + struct expr *override; }; -enum const_global { - CST_TYPE, - CST_BOOL, - CST_NUMBER, - CST_STRING, +struct ast_enum { + struct expr init; + struct ast_enumvar *variants; + int variantsz, variantlen; }; -struct ast_const_global { +struct ast_field { const char *name; - enum const_global kind; - union { - struct type type; - bool b; - struct number num; - char *str; - } value; + struct type type; }; -struct ast_import { - struct path path; +struct ast_struct { const char *name; + int align; + struct ast_field *fields; + int fieldsz, fieldlen; +}; + +struct ast_union { + const char *name; + struct type *types; + int typesz, typelen; +}; + +struct ast_func { + int ispub; + int isextern; + const char *name; + struct ast_field *params; + int paramsz, paramlen; + struct type *ret; + struct ast_stmt *stmts; + int stmtsz, stmtlen; }; enum toplevel { - TOP_EXTERNFUNC, - TOP_FUNC, + TOP_INCLUDE, + TOP_GLOBAL, TOP_CONST, + TOP_ENUM, + TOP_STRUCT, + TOP_UNION, + TOP_FUNC, }; struct ast_toplevel { enum toplevel kind; union { - struct ast_externfunc *extfn; - struct ast_func *function; - struct ast_const_global *constant; - } decl; + struct ast_include include; + struct ast_global globalvar; + struct ast_const constant; + struct ast_enum enumconst; + struct ast_struct structdecl; + struct ast_union uniondecl; + struct ast_func function; + } tl; }; struct ast_unit { - struct ast_import *imports; struct ast_toplevel *tops; - int impsz, implen; int topsz, toplen; }; diff --git a/src/parse.c b/src/parse.c index 86035cb..3d01562 100644 --- a/src/parse.c +++ b/src/parse.c @@ -7,15 +7,6 @@ #include "parse.h" #include "util.h" -static bool parse_disjunction_e(struct lexer *lexer, - struct disjunction_e *out); -static bool parse_array(struct lexer *lexer, struct type *out); -static bool parse_type(struct lexer *lexer, struct type *out); -static bool parse_block(struct lexer *lexer, struct ast_block *out); -static bool parse_control_e(struct lexer *lexer, struct control_e *out); -static bool parse_location(struct lexer *lexer, struct location_e *out); -static bool parse_assignment_e(struct lexer *lexer, struct assign_e *out); - static noreturn void error(struct location loc, const char *fmt, ...) { @@ -67,1475 +58,7 @@ parse_path(struct lexer *lexer, struct path *out) return true; } -static bool -parse_grouping_e(struct lexer *lexer, struct disjunction_e *out) -{ - if (!match(lexer, T_LPAREN)) { - return false; - } - - if (!parse_disjunction_e(lexer, out)) { - error(lex_loc(lexer), "syntax error: expected expression"); - } - - if (!match(lexer, T_RPAREN)) { - error(lex_loc(lexer), "syntax error: expected ')'"); - } - - return true; -} - -static bool -parse_bool_lit(struct lexer *lexer, bool *out) -{ - if (match(lexer, T_TRUE)) { - *out = true; - } else if (match(lexer, T_FALSE)) { - *out = false; - } else { - return false; - } - - return true; -} - -static bool -parse_string(struct lexer *lexer, char **out) -{ - *out = NULL; - - struct token s; - bool isstr = false; - while (lex(lexer, &s) == T_STRING) { - if (*out) { - size_t sz = strlen(*out) + strlen(s.info.str) + 1; - *out = must_realloc(*out, sz); - } else { - *out = strdup(s.info.str); - } - - isstr = true; - } - unlex(lexer, &s); - - return isstr; -} - -static bool -parse_number_e(struct lexer *lexer, struct number_e *out) -{ - struct token num; - if (lex(lexer, &num) != T_NUMBER) { - unlex(lexer, &num); - return false; - } - out->value = num.info.num; - - out->type = must_malloc(sizeof(struct type)); - if (!parse_type(lexer, out->type)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - - return true; -} - -static bool -parse_array_e(struct lexer *lexer, struct array_e *out) -{ - struct type type; - if (!parse_array(lexer, &type)) { - return false; - } - out->meta = must_malloc(sizeof(struct cer_array)); - *out->meta = type.desc.array; - - out->elems = must_calloc(1, sizeof(struct disjunction_e)); - out->elemsz = 1; - out->elemlen = 0; - - struct disjunction_e elem; - while (parse_disjunction_e(lexer, &elem)) { - if (out->elemlen >= out->elemsz) { - out->elemsz *= 2; - size_t sz = sizeof(struct disjunction_e) * out->elemsz; - out->elems = must_realloc(out->elems, sz); - } - out->elems[out->elemlen++] = elem; - } - - return true; -} - -static bool -parse_literal_e(struct lexer *lexer, struct literal_e *out) -{ - if (parse_bool_lit(lexer, &out->lit.b)) { - out->kind = LIT_BOOL; - return true; - } - if (parse_string(lexer, &out->lit.str)) { - out->kind = LIT_STRING; - return true; - } - if (parse_number_e(lexer, &out->lit.num)) { - out->kind = LIT_NUMBER; - return true; - } - if (parse_array_e(lexer, &out->lit.arr)) { - out->kind = LIT_ARRAY; - return true; - } - - return false; -} - -// Invariant: Only called from parse_primary_e with path already consumed. -static bool -parse_call_e(struct lexer *lexer, struct call_e *out, struct location_e *loc) -{ - if (!match(lexer, T_LPAREN)) { - return false; - } - - out->loc = loc; - - out->args = must_calloc(1, sizeof(struct disjunction_e)); - out->argsz = 1; - out->arglen = 0; - - struct disjunction_e expr; - while (parse_disjunction_e(lexer, &expr)) { - if (out->arglen >= out->argsz) { - out->argsz *= 2; - size_t sz = sizeof(struct disjunction_e) * out->argsz; - out->args = must_realloc(out->args, sz); - } - out->args[out->arglen++] = expr; - } - - if (!match(lexer, T_RPAREN)) { - error(lex_loc(lexer), "syntax error: expected ')'"); - } - - return true; -} - -static bool -parse_named_e(struct lexer *lexer, struct named_e *out) -{ - if (!parse_location(lexer, &out->loc)) { - return false; - } - - if (parse_assignment_e(lexer, &out->nmd.assign)) { - out->kind = NMD_ASSIGN; - return true; - } - if (parse_call_e(lexer, &out->nmd.call, &out->loc)) { - out->kind = NMD_CALL; - return true; - } - - out->kind = NMD_LOCATION; - return true; -} - -static bool -parse_primary_e(struct lexer *lexer, struct primary_e *out) -{ - if (parse_control_e(lexer, &out->prim.ctl)) { - out->kind = PRM_CONTROL; - return true; - } - out->prim.grp = must_malloc(sizeof(struct disjunction_e)); - if (parse_grouping_e(lexer, out->prim.grp)) { - out->kind = PRM_GROUPING; - return true; - } - free(out->prim.grp); - if (parse_literal_e(lexer, &out->prim.lit)) { - out->kind = PRM_LITERAL; - return true; - } - if (parse_named_e(lexer, &out->prim.nmd)) { - out->kind = PRM_NAMED; - return true; - } - - return false; -} - -static bool -parse_unarypost_e(struct lexer *lexer, struct unarypost_e *out) -{ - if (!parse_primary_e(lexer, &out->prim)) { - return false; - } - - if (match(lexer, T_STAR)) { - out->op = UPS_DEREF; - } else if (match(lexer, T_QUESTION)) { - out->op = UPS_TRY; - } else if (match(lexer, T_BANG)) { - out->op = UPS_ASSERT; - } else { - out->op = UPS_NONE; - } - - return true; -} - -static bool -parse_unarypre_e(struct lexer *lexer, struct unarypre_e *out) -{ - if (match(lexer, T_MINUS)) { - out->op = UPR_NEG; - } else if (match(lexer, T_BANG)) { - out->op = UPR_INVERT; - } else if (match(lexer, T_BNOT)) { - out->op = UPR_BNEG; - } else { - out->op = UPR_NONE; - } - - bool post_ok = parse_unarypost_e(lexer, &out->post); - if (!post_ok) { - if (out->op == UPR_NONE) { - return false; - } - - error(lex_loc(lexer), - "syntax error: expected unary postfix expression"); - } - - return true; -} - -static bool -parse_bitfactor_rhs(struct lexer *lexer, struct unarypre_e *out) -{ - if (!match(lexer, T_BAND)) { - return false; - } - - if (!parse_unarypre_e(lexer, out)) { - error(lex_loc(lexer), - "syntax error: expected unary prefix expression"); - } - - return true; -} - -static bool -parse_bitfactor_e(struct lexer *lexer, struct bitfactor_e *out) -{ - if (!parse_unarypre_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct unarypre_e)); - out->rhssz = 1; - out->rhslen = 0; - - struct unarypre_e rhs; - while (parse_bitfactor_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct unarypre_e) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_bitsummand_rhs(struct lexer *lexer, struct bitfactor_e *out) -{ - if (!match(lexer, T_BXOR)) { - return false; - } - - if (!parse_bitfactor_e(lexer, out)) { - error(lex_loc(lexer), "syntax error: expected bit factor"); - } - - return true; -} - -static bool -parse_bitsummand_e(struct lexer *lexer, struct bitsummand_e *out) -{ - if (!parse_bitfactor_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct bitfactor_e)); - out->rhssz = 1; - out->rhslen = 0; - - struct bitfactor_e rhs; - while (parse_bitsummand_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct bitfactor_e) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_bin_rhs(struct lexer *lexer, struct bitsummand_e *out) -{ - if (!match(lexer, T_BOR)) { - return false; - } - - if (!parse_bitsummand_e(lexer, out)) { - error(lex_loc(lexer), "syntax error: expected bit summand"); - } - - return true; -} - -static bool -parse_bin_e(struct lexer *lexer, struct bin_e *out) -{ - if (!parse_bitsummand_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct bitsummand_e)); - out->rhssz = 1; - out->rhslen = 0; - - struct bitsummand_e rhs; - while (parse_bin_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct bitsummand_e) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_factor_rhs(struct lexer *lexer, struct factor_rhs *out) -{ - if (match(lexer, T_STAR)) { - out->factor = FCT_MUL; - } else if (match(lexer, T_DIV)) { - out->factor = FCT_DIV; - } else if (match(lexer, T_MODULO)) { - out->factor = FCT_REM; - } else { - return false; - } - - if (!parse_bin_e(lexer, &out->bin)) { - error(lex_loc(lexer), - "syntax error: expected bitwise expression"); - } - - return true; -} - -static bool -parse_factor_e(struct lexer *lexer, struct factor_e *out) -{ - if (!parse_bin_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct factor_rhs)); - out->rhssz = 1; - out->rhslen = 0; - - struct factor_rhs rhs; - while (parse_factor_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct factor_rhs) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_num_rhs(struct lexer *lexer, struct num_rhs *out) -{ - if (match(lexer, T_ADD)) { - out->num = NUM_ADD; - } else if (match(lexer, T_MINUS)) { - out->num = NUM_SUB; - } else { - return false; - } - - if (!parse_factor_e(lexer, &out->factor)) { - error(lex_loc(lexer), - "syntax error: expected factor expression"); - } - - return true; -} - -static bool -parse_num_e(struct lexer *lexer, struct num_e *out) -{ - if (!parse_factor_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct num_rhs)); - out->rhssz = 1; - out->rhslen = 0; - - struct num_rhs rhs; - while (parse_num_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct num_rhs) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_term_e(struct lexer *lexer, struct term_e *out) -{ - if (!parse_num_e(lexer, &out->lhs)) { - return false; - } - - if (match(lexer, T_BSHL)) { - out->term = TRM_SHL; - } else if (match(lexer, T_BSHR)) { - out->term = TRM_SHL; - } else { - out->term = TRM_NUM; - out->rhs = NULL; - return true; - } - - out->rhs = must_malloc(sizeof(struct num_e)); - if (!parse_num_e(lexer, out->rhs)) { - error(lex_loc(lexer), - "syntax error: expected numeral expression"); - } - - return true; -} - -static bool -parse_comparison_rhs(struct lexer *lexer, struct cmp_rhs *out) -{ - if (match(lexer, T_LT)) { - out->cmp = CMP_LT; - } else if (match(lexer, T_LE)) { - out->cmp = CMP_LE; - } else if (match(lexer, T_GT)) { - out->cmp = CMP_GT; - } else if (match(lexer, T_GE)) { - out->cmp = CMP_GE; - } else { - return false; - } - - if (!parse_term_e(lexer, &out->term)) { - error(lex_loc(lexer), "syntax error: expected term"); - } - - return true; -} - -static bool -parse_comparison_e(struct lexer *lexer, struct cmp_e *out) -{ - if (!parse_term_e(lexer, &out->lhs)) { - return false; - } - - out->rhs = must_calloc(1, sizeof(struct cmp_rhs)); - out->rhssz = 1; - out->rhslen = 0; - - struct cmp_rhs rhs; - while (parse_comparison_rhs(lexer, &rhs)) { - if (out->rhslen >= out->rhssz) { - out->rhssz *= 2; - size_t sz = sizeof(struct cmp_rhs) * out->rhssz; - out->rhs = must_realloc(out->rhs, sz); - } - out->rhs[out->rhslen++] = rhs; - } - - return true; -} - -static bool -parse_equality_e(struct lexer *lexer, struct eq_e *out) -{ - if (!parse_comparison_e(lexer, &out->lhs)) { - return false; - } - - if (match(lexer, T_EQ)) { - out->invert = false; - } else if (match(lexer, T_NEQ)) { - out->invert = true; - } else { - out->rhs = NULL; - return true; - } - - out->rhs = must_malloc(sizeof(struct cmp_e)); - if (!parse_comparison_e(lexer, out->rhs)) { - error(lex_loc(lexer), "syntax error: expected comparison"); - } - - return true; -} - -static bool -parse_bool_e(struct lexer *lexer, struct bool_e *out) -{ - if (parse_equality_e(lexer, &out->cond.eq)) { - out->kind = B_EQ; - return true; - } - if (parse_comparison_e(lexer, &out->cond.cmp)) { - out->kind = B_CMP; - return true; - } - - return false; -} - -static bool -parse_conjunction_e(struct lexer *lexer, struct conjunction_e *out) -{ - out->bools = must_calloc(1, sizeof(struct bool_e)); - out->boolsz = 1; - out->boollen = 0; - - struct bool_e b; - if (!parse_bool_e(lexer, &b)) { - return false; - } - out->bools[out->boollen++] = b; - - while (match(lexer, T_AND)) { - if (!parse_bool_e(lexer, &b)) { - error(lex_loc(lexer), - "syntax error: expected boolean expression"); - } - - if (out->boollen >= out->boolsz) { - out->boolsz *= 2; - size_t sz = sizeof(struct bool_e) * out->boolsz; - out->bools = must_realloc(out->bools, sz); - } - out->bools[out->boollen++] = b; - } - - return true; -} - -static bool -parse_disjunction_e(struct lexer *lexer, struct disjunction_e *out) -{ - out->cons = must_calloc(1, sizeof(struct conjunction_e)); - out->consz = 1; - out->conlen = 0; - - struct conjunction_e con; - if (!parse_conjunction_e(lexer, &con)) { - return false; - } - out->cons[out->conlen++] = con; - - while (match(lexer, T_OR)) { - if (!parse_conjunction_e(lexer, &con)) { - error(lex_loc(lexer), - "syntax error: expected conjunction"); - } - - if (out->conlen >= out->consz) { - out->consz *= 2; - size_t sz = sizeof(struct conjunction_e) * out->consz; - out->cons = must_realloc(out->cons, sz); - } - out->cons[out->conlen++] = con; - } - - return true; -} - -static bool -parse_expr(struct lexer *lexer, struct ast_expr *out) -{ - return parse_disjunction_e(lexer, &out->dis); -} - -static bool -parse_integer(struct lexer *lexer, struct type *out) -{ - struct token token; - switch(lex(lexer, &token)) { - case T_INT8: - out->kind = TYP_INT; - out->desc.i.sign = true; - out->desc.i.bits = 8; - return true; - case T_UINT8: - out->kind = TYP_INT; - out->desc.i.sign = false; - out->desc.i.bits = 8; - return true; - case T_INT16: - out->kind = TYP_INT; - out->desc.i.sign = true; - out->desc.i.bits = 16; - return true; - case T_UINT16: - out->kind = TYP_INT; - out->desc.i.sign = false; - out->desc.i.bits = 16; - return true; - case T_INT32: - out->kind = TYP_INT; - out->desc.i.sign = true; - out->desc.i.bits = 32; - return true; - case T_UINT32: - out->kind = TYP_INT; - out->desc.i.sign = false; - out->desc.i.bits = 32; - return true; - case T_INT64: - out->kind = TYP_INT; - out->desc.i.sign = true; - out->desc.i.bits = 64; - return true; - case T_UINT64: - out->kind = TYP_INT; - out->desc.i.sign = false; - out->desc.i.bits = 64; - return true; - case T_INT: - out->kind = TYP_INT; - out->desc.i.sign = true; - out->desc.i.bits = PLATBITS; - return true; - case T_UINT: - out->kind = TYP_INT; - out->desc.i.sign = false; - out->desc.i.bits = PLATBITS; - return true; - default: - unlex(lexer, &token); - return false; - } -} - -static bool -parse_float(struct lexer *lexer, struct type *out) -{ - struct token token; - switch (lex(lexer, &token)) { - case T_FLOAT32: - out->kind = TYP_FLOAT; - out->desc.f.is64 = false; - return true; - case T_FLOAT64: - out->kind = TYP_FLOAT; - out->desc.f.is64 = true; - default: - unlex(lexer, &token); - return false; - } -} - -static bool -parse_field(struct lexer *lexer, struct field *out) -{ - struct token name; - if (lex(lexer, &name) != T_NAME) { - unlex(lexer, &name); - return false; - } - out->name = name.info.str; - - struct type *type = must_malloc(sizeof(struct type)); - if (!parse_type(lexer, type)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - out->type = type; - - return true; -} - -static bool -parse_struct(struct lexer *lexer, struct type *out) -{ - if (!match(lexer, T_STRUCT)) { - return false; - } - if (!match(lexer, T_LBRACE)) { - error(lex_loc(lexer), "syntax error: expected '{'"); - } - - out->kind = TYP_STRUCT; - out->desc.s.fields = must_calloc(1, sizeof(struct field)); - out->desc.s.fieldsz = 1; - out->desc.s.fieldlen = 0; - - struct field field; - while (parse_field(lexer, &field)) { - if (out->desc.s.fieldlen >= out->desc.s.fieldsz) { - out->desc.s.fieldsz *= 2; - size_t sz = sizeof(struct field) * out->desc.s.fieldsz; - out->desc.s.fields = must_realloc(out->desc.s.fields, - sz); - } - out->desc.s.fields[out->desc.s.fieldlen++] = field; - - if (!match(lexer, T_COMMA)) { - break; - } - } - - if (!match(lexer, T_RBRACE)) { - error(lex_loc(lexer), "syntax error: expected '}'"); - } - - return true; -} - -static bool parse_union(struct lexer *lexer, struct type *out) -{ - if (!match(lexer, T_UNION)) { - return false; - } - - out->desc.un.tag_type = NULL; - if (match(lexer, T_LPAREN)) { - out->desc.un.tag_type = must_malloc(sizeof(struct type)); - if (!parse_type(lexer, out->desc.un.tag_type)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - - if (!match(lexer, T_RPAREN)) { - error(lex_loc(lexer), "syntax error: expected ')'"); - } - } - - if (!match(lexer, T_LBRACE)) { - error(lex_loc(lexer), "syntax error: expected '{'"); - } - - out->kind = TYP_UNION; - out->desc.un.alts = must_calloc(1, sizeof(struct type)); - out->desc.un.altsz = 1; - out->desc.un.altlen = 0; - - struct type alt; - while (parse_type(lexer, &alt)) { - if (out->desc.un.altlen >= out->desc.un.altsz) { - out->desc.un.altsz *= 2; - size_t sz = sizeof(struct type) * out->desc.un.altsz; - out->desc.un.alts = must_realloc(out->desc.un.alts, sz); - } - out->desc.un.alts[out->desc.un.altlen++] = alt; - - if (!match(lexer, T_COMMA)) { - break; - } - } - - if (!match(lexer, T_RBRACE)) { - error(lex_loc(lexer), "syntax error: expected '}'"); - } - - return true; -} - -static bool -parse_array(struct lexer *lexer, struct type *out) -{ - if (!match(lexer, T_LBRACKET)) { - return false; - } - - out->kind = TYP_ARRAY; - - out->desc.array.length = must_malloc(sizeof(struct disjunction_e)); - if (!parse_disjunction_e(lexer, out->desc.array.length)) { - out->kind = TYP_SLICE; - } - - if (!match(lexer, T_RBRACKET)) { - error(lex_loc(lexer), "syntax error: expected ']'"); - } - - struct type *type = must_malloc(sizeof(struct type)); - if (!parse_type(lexer, type)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - out->desc.array.member_type = type; - - return true; -} - -static bool -parse_type(struct lexer *lexer, struct type *out) -{ - struct token token; - switch (lex(lexer, &token)) { - case T_STAR: - out->kind = TYP_POINTER; - out->desc.inner = must_malloc(sizeof(struct type)); - - if (!parse_type(lexer, out->desc.inner)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - return true; - case T_QUESTION: - out->kind = TYP_OPTIONAL; - out->desc.inner = must_malloc(sizeof(struct type)); - - if (!parse_type(lexer, out->desc.inner)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - return true; - case T_BANG: - out->kind = TYP_FALLIBLE; - out->desc.inner = must_malloc(sizeof(struct type)); - - if (!parse_type(lexer, out->desc.inner)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - return true; - case T_BOOL: - out->kind = TYP_BOOL; - return true; - } - unlex(lexer, &token); - - if (parse_integer(lexer, out)) { - return true; - } - if (parse_float(lexer, out)) { - return true; - } - if (parse_struct(lexer, out)) { - return true; - } - if (parse_union(lexer, out)) { - return true; - } - if (parse_array(lexer, out)) { - return true; - } - - struct path path; - if (parse_path(lexer, &path)) { - out->kind = TYP_PATH; - out->desc.path = path; - return true; - } - - return false; -} - -static bool -parse_externfunc(struct lexer *lexer, struct ast_externfunc *out) -{ - out->params = must_calloc(1, sizeof(struct type)); - out->paramsz = 1; - out->paramlen = 0; - - if (!match(lexer, T_EXTERN)) { - return false; - } - if (!match(lexer, T_FUNC)) { - error(lex_loc(lexer), "syntax error: expected keyword 'func'"); - } - - struct token name; - if (lex(lexer, &name) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->name = name.info.str; - - if (!match(lexer, T_LPAREN)) { - error(lex_loc(lexer), "syntax error: expected '('"); - } - - struct type paramtype; - while (parse_type(lexer, ¶mtype)) { - if (out->paramlen >= out->paramsz) { - out->paramsz *= 2; - size_t sz = sizeof(struct type) * out->paramsz; - out->params = must_realloc(out->params, sz); - } - out->params[out->paramlen++] = paramtype; - - if (!match(lexer, T_COMMA)) { - break; - } - } - - if (!match(lexer, T_RPAREN)) { - error(lex_loc(lexer), "syntax error: expected ')'"); - } - - bool nonvoid = parse_type(lexer, &out->ret); - - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - - return true; -} - -static bool -parse_return(struct lexer *lexer, struct ast_return *out) -{ - if (!match(lexer, T_RETURN)) { - return false; - } - - out->value = must_malloc(sizeof(struct ast_expr)); - if (!parse_expr(lexer, out->value)) { - free(out->value); - out->value = NULL; - } - - return true; -} - -static bool -parse_break(struct lexer *lexer, struct ast_break *out) -{ - if (!match(lexer, T_BREAK)) { - return false; - } - - if (!match(lexer, T_COLON)) { - out->label = NULL; - return true; - } - - struct token label; - if (lex(lexer, &label) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->label = label.info.str; - - out->value = must_malloc(sizeof(struct ast_expr)); - if (!parse_expr(lexer, out->value)) { - free(out->value); - out->value = NULL; - } - - return true; -} - -static bool -parse_continue(struct lexer *lexer, struct ast_break *out) -{ - if (!match(lexer, T_CONTINUE)) { - return false; - } - - if (!match(lexer, T_COLON)) { - out->label = NULL; - return true; - } - - struct token label; - if (lex(lexer, &label) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->label = label.info.str; - - out->value = NULL; - return true; -} - -static bool -parse_declaration(struct lexer *lexer, struct ast_declaration *out) -{ - if (!match(lexer, T_LET)) { - return false; - } - - out->mut = false; - - struct token name; - if (lex(lexer, &name) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->name = name.info.str; - - if (!match(lexer, T_ASSIGN)) { - error(lex_loc(lexer), "syntax error: expected '='"); - } - - out->value = must_malloc(sizeof(struct ast_expr)); - if (!parse_expr(lexer, out->value)) { - error(lex_loc(lexer), "syntax error: expected expression"); - } - - return true; -} - -static bool -parse_subindex(struct lexer *lexer, struct ast_expr *out) -{ - if (!match(lexer, T_LBRACKET)) { - return false; - } - - if (!parse_expr(lexer, out)) { - error(lex_loc(lexer), "syntax error: expected expression"); - } - - if (!match(lexer, T_RBRACKET)) { - error(lex_loc(lexer), "syntax error: expected ']'"); - } - - return true; -} - -static bool -parse_subfield(struct lexer *lexer, const char **out) -{ - if (!match(lexer, T_DOT)) { - return false; - } - - struct token name; - if (lex(lexer, &name) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - *out = name.info.str; - - return true; -} - -static bool -parse_loc_postfix(struct lexer *lexer, struct loc_postfix *out) -{ - if (parse_subindex(lexer, &out->id.index)) { - out->sub = SUB_INDEX; - return true; - } - if (parse_subfield(lexer, &out->id.field)) { - out->sub = SUB_FIELD; - return true; - } - - return false; -} - -static bool -parse_location(struct lexer *lexer, struct location_e *out) -{ - out->path = must_malloc(sizeof(struct path)); - if (!parse_path(lexer, out->path)) { - free(out->path); - return false; - } - - out->subs = must_calloc(1, sizeof(struct loc_postfix)); - out->subsz = 1; - out->sublen = 0; - - struct loc_postfix sub; - while (parse_loc_postfix(lexer, &sub)) { - if (out->sublen >= out->subsz) { - out->subsz *= 2; - size_t sz = sizeof(struct loc_postfix) * out->subsz; - out->subs = must_realloc(out->subs, sz); - } - out->subs[out->sublen++] = sub; - } - - return true; -} - -static bool -parse_assignment_e(struct lexer *lexer, struct assign_e *out) -{ - if (!parse_location(lexer, &out->dst)) { - return false; - } - - if (!match(lexer, T_ASSIGN)) { - error(lex_loc(lexer), "syntax error: expected '='"); - } - - out->value = must_malloc(sizeof(struct ast_expr)); - if (!parse_expr(lexer, out->value)) { - error(lex_loc(lexer), "syntax error: expected expression"); - } - - return true; -} - -static bool -parse_call(struct lexer *lexer, struct call_e *out) -{ - /* TODO */ - return false; -} - -static bool -parse_defer(struct lexer *lexer, struct call_e *out) -{ - if (!match(lexer, T_DEFER)) { - return false; - } - - struct location_e *loc = must_malloc(sizeof(struct location_e)); - if (!parse_location(lexer, loc)) { - error(lex_loc(lexer), "syntax error: expected path"); - } - - if (!parse_call_e(lexer, out, loc)) { - error(lex_loc(lexer), "syntax error: expected call"); - } - - return true; -} - -static bool -parse_statement(struct lexer *lexer, struct ast_statement *out) -{ - if (parse_return(lexer, &out->stmt.ret)) { - out->action = STM_RETURN; - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - return true; - } - if (parse_break(lexer, &out->stmt.brk)) { - out->action = STM_BREAK; - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - return true; - } - if (parse_continue(lexer, &out->stmt.brk)) { - out->action = STM_CONTINUE; - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - return true; - } - if (parse_declaration(lexer, &out->stmt.decl)) { - out->action = STM_DECL; - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - return true; - } - out->stmt.call = must_malloc(sizeof(struct call_e)); - if (parse_defer(lexer, out->stmt.call)) { - out->action = STM_DEFER; - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), "syntax error: expected semicolon"); - } - return true; - } - free(out->stmt.call); - - return false; -} - -static bool -parse_control_e(struct lexer *lexer, struct control_e *out) -{ - /* TODO */ - return false; -} - -static bool -parse_command(struct lexer *lexer, struct ast_cmd *out) -{ - if (parse_block(lexer, &out->cmd.blk)) { - out->kind = CMD_BLOCK; - return true; - } - if (parse_statement(lexer, &out->cmd.stmt)) { - out->kind = CMD_STATEMENT; - return true; - } - - return false; -} - -static bool -parse_block(struct lexer *lexer, struct ast_block *out) -{ - if (!match(lexer, T_LBRACE)) { - return false; - } - - out->cmds = must_calloc(1, sizeof(struct ast_cmd)); - out->cmdsz = 1; - out->cmdlen = 0; - - struct ast_cmd cmd; - while (parse_command(lexer, &cmd)) { - if (out->cmdlen >= out->cmdsz) { - out->cmdsz *= 2; - size_t sz = sizeof(struct ast_cmd) * out->cmdsz; - out->cmds = must_realloc(out->cmds, sz); - } - out->cmds[out->cmdlen++] = cmd; - } - - if (!match(lexer, T_RBRACE)) { - error(lex_loc(lexer), "syntax error: expected '}'"); - } - - return true; -} - -static bool -parse_param(struct lexer *lexer, struct ast_param *out) -{ - struct token name; - if (lex(lexer, &name) != T_NAME) { - unlex(lexer, &name); - return false; - } - out->name = name.info.str; - - if (!parse_type(lexer, &out->type)) { - error(lex_loc(lexer), "syntax error: expected type"); - } - - return true; -} - -static bool -parse_function(struct lexer *lexer, struct ast_func *out) -{ - out->params = must_calloc(1, sizeof(struct ast_param)); - out->paramsz = 1; - out->paramlen = 0; - - if (!match(lexer, T_FUNC)) { - if (out->exported) { - error(lex_loc(lexer), - "syntax error: expected keyword 'func'"); - } - return false; - } - - struct token name; - if (lex(lexer, &name) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->name = name.info.str; - - if (!match(lexer, T_LPAREN)) { - error(lex_loc(lexer), "syntax error: expected '('"); - } - - struct ast_param param; - while (parse_param(lexer, ¶m)) { - if (out->paramlen >= out->paramsz) { - out->paramsz *= 2; - size_t sz = sizeof(struct ast_param) * out->paramsz; - out->params = must_realloc(out->params, sz); - } - out->params[out->paramlen++] = param; - - if (!match(lexer, T_COMMA)) { - break; - } - } - - if (!match(lexer, T_RPAREN)) { - error(lex_loc(lexer), "syntax error: expected ')'"); - } - - out->ret = must_malloc(sizeof(struct type)); - bool nonvoid = parse_type(lexer, out->ret); - - out->block = must_malloc(sizeof(struct ast_block)); - if (!parse_block(lexer, out->block)) { - error(lex_loc(lexer), "syntax error: expected block"); - } - - return true; -} - -static bool -parse_bool(struct lexer *lexer, bool *out) -{ - struct token token; - switch (lex(lexer, &token)) { - case T_FALSE: - *out = false; - return true; - case T_TRUE: - *out = true; - return true; - default: - unlex(lexer, &token); - return false; - } -} - -static bool -parse_const_global(struct lexer *lexer, struct ast_const_global *out) -{ - if (!match(lexer, T_CONST)) { - return false; - } - - struct token name; - if (lex(lexer, &name) != T_NAME) { - error(lex_loc(lexer), "syntax error: expected name"); - } - out->name = name.info.str; - - if (!match(lexer, T_ASSIGN)) { - error(lex_loc(lexer), "syntax error: expected '='"); - } - - struct token token; - if (lex(lexer, &token) == T_NUMBER) { - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), - "syntax error: expected semicolon"); - } - - out->kind = CST_NUMBER; - out->value.num = token.info.num; - return true; - } - unlex(lexer, &token); - - if (parse_bool(lexer, &out->value.b)) { - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), - "syntax error: expected semicolon"); - } - - out->kind = CST_BOOL; - return true; - } - - bool isstr = false; - out->value.str = must_malloc(1); - memset(out->value.str, 0, 1); - while (lex(lexer, &token) == T_STRING) { - size_t sz = strlen(out->value.str) + strlen(token.info.str) + 1; - out->value.str = must_realloc(out->value.str, sz); - strcat(out->value.str, token.info.str); - isstr = true; - } - unlex(lexer, &token); - - if (isstr) { - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), - "syntax error: expected semicolon"); - } - - out->kind = CST_STRING; - return true; - } - - if (parse_type(lexer, &out->value.type)) { - if (!match(lexer, T_SEMICOLON)) { - error(lex_loc(lexer), - "syntax error: expected semicolon"); - } - - out->kind = CST_TYPE; - return true; - } - - error(lex_loc(lexer), - "syntax error: expected number, bool, string or type"); -} - -static bool -parse_toplevel(struct lexer *lexer, struct ast_toplevel *out) -{ - struct ast_externfunc *extfn = - must_malloc(sizeof(struct ast_externfunc)); - if (parse_externfunc(lexer, extfn)) { - out->kind = TOP_EXTERNFUNC; - out->decl.extfn = extfn; - return true; - } - free(extfn); - - struct ast_func *func = must_malloc(sizeof(struct ast_func)); - if (parse_function(lexer, func)) { - out->kind = TOP_FUNC; - out->decl.function = func; - return true; - } - free(func); - - struct ast_const_global *c = - must_malloc(sizeof(struct ast_const_global)); - if (parse_const_global(lexer, c)) { - out->kind = TOP_CONST; - out->decl.constant = c; - return true; - } - free(c); - - if (!match(lexer, T_EOF)) { - error(lex_loc(lexer), - "syntax error: expected top-level declaration"); - } - - return false; -} - void -parse(struct lexer *lexer, struct ast_unit *ast) +parse(struct lexer *lexer, struct ast_unit *u) { - ast->imports = must_calloc(1, sizeof(struct ast_import)); - ast->tops = must_calloc(1, sizeof(struct ast_toplevel)); - ast->impsz = 1; - ast->implen = 0; - ast->topsz = 1; - ast->toplen = 0; - - struct ast_toplevel top; - while (parse_toplevel(lexer, &top)) { - if (ast->toplen >= ast->topsz) { - ast->topsz *= 2; - size_t sz = sizeof(struct ast_toplevel) * ast->topsz; - ast->tops = must_realloc(ast->tops, sz); - } - ast->tops[ast->toplen++] = top; - } } |