aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2025-05-05 11:54:58 +0200
committerHimbeer <himbeer@disroot.org>2025-05-05 11:54:58 +0200
commit828f7cfe05eec5547837867101fc662c3dea60f1 (patch)
treed42580915bc74937c9d5bf14f678679bc3ab3d35
parentc640c9856b499af2ed5faedbf03e9945d74aafa9 (diff)
Define overhauled AST data structures
-rw-r--r--include/cmd.h66
-rw-r--r--include/expr.h289
-rw-r--r--include/literal.h20
-rw-r--r--include/parse.h170
-rw-r--r--src/parse.c1479
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, &paramtype)) {
- 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, &param)) {
- 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;
- }
}