diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-04-04 17:06:09 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-04-04 17:06:09 -0400 |
| commit | 0b8074154e2671691050bdb3bcb33245625a056c (patch) | |
| tree | 1410e0c4e05c6372e876cd08f16d117e12868f41 /src/parse.c | |
| parent | fadcb45baf1274e06cfe37b87655b9146aa52874 (diff) | |
First working compile of refactor to add explicit typing to declarations
and support untyped empty collections and `none`s
Diffstat (limited to 'src/parse.c')
| -rw-r--r-- | src/parse.c | 180 |
1 files changed, 69 insertions, 111 deletions
diff --git a/src/parse.c b/src/parse.c index 63f5deb0..0aa26002 100644 --- a/src/parse.c +++ b/src/parse.c @@ -48,16 +48,16 @@ typedef struct { #define PARSER(name) ast_t *name(parse_ctx_t *ctx, const char *pos) int op_tightness[] = { - [BINOP_POWER]=9, - [BINOP_MULT]=8, [BINOP_DIVIDE]=8, [BINOP_MOD]=8, [BINOP_MOD1]=8, - [BINOP_PLUS]=7, [BINOP_MINUS]=7, - [BINOP_CONCAT]=6, - [BINOP_LSHIFT]=5, [BINOP_RSHIFT]=5, - [BINOP_MIN]=4, [BINOP_MAX]=4, - [BINOP_EQ]=3, [BINOP_NE]=3, - [BINOP_LT]=2, [BINOP_LE]=2, [BINOP_GT]=2, [BINOP_GE]=2, - [BINOP_CMP]=2, - [BINOP_AND]=1, [BINOP_OR]=1, [BINOP_XOR]=1, + [Power]=9, + [Multiply]=8, [Divide]=8, [Mod]=8, [Mod1]=8, + [Plus]=7, [Minus]=7, + [Concat]=6, + [LeftShift]=5, [RightShift]=5, [UnsignedLeftShift]=5, [UnsignedRightShift]=5, + [Min]=4, [Max]=4, + [Equals]=3, [NotEquals]=3, + [LessThan]=2, [LessThanOrEquals]=2, [GreaterThan]=2, [GreaterThanOrEquals]=2, + [Compare]=2, + [And]=1, [Or]=1, [Xor]=1, }; static const char *keywords[] = { @@ -79,7 +79,7 @@ static INLINE const char* get_word(const char **pos); static INLINE const char* get_id(const char **pos); static INLINE bool comment(const char **pos); static INLINE bool indent(parse_ctx_t *ctx, const char **pos); -static INLINE binop_e match_binary_operator(const char **pos); +static INLINE ast_e match_binary_operator(const char **pos); static ast_t *parse_comprehension_suffix(parse_ctx_t *ctx, ast_t *expr); static ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs); static ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn); @@ -685,15 +685,6 @@ PARSER(parse_array) { whitespace(&pos); ast_list_t *items = NULL; - type_ast_t *item_type = NULL; - if (match(&pos, ":")) { - whitespace(&pos); - item_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a type for this array"); - whitespace(&pos); - match(&pos, ","); - whitespace(&pos); - } - for (;;) { ast_t *item = optional(ctx, &pos, parse_extended_expr); if (!item) break; @@ -711,7 +702,7 @@ PARSER(parse_array) { expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this array"); REVERSE_LIST(items); - return NewAST(ctx->file, start, pos, Array, .item_type=item_type, .items=items); + return NewAST(ctx->file, start, pos, Array, .items=items); } PARSER(parse_table) { @@ -722,20 +713,6 @@ PARSER(parse_table) { whitespace(&pos); ast_list_t *entries = NULL; - type_ast_t *key_type = NULL, *value_type = NULL; - if (match(&pos, ":")) { - whitespace(&pos); - key_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a key type for this table"); - whitespace(&pos); - if (match(&pos, "=")) { - value_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse the value type for this table"); - } else { - return NULL; - } - whitespace(&pos); - match(&pos, ","); - } - for (;;) { const char *entry_start = pos; ast_t *key = optional(ctx, &pos, parse_extended_expr); @@ -787,8 +764,7 @@ PARSER(parse_table) { whitespace(&pos); expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this table"); - return NewAST(ctx->file, start, pos, Table, .key_type=key_type, .value_type=value_type, - .default_value=default_value, .entries=entries, .fallback=fallback); + return NewAST(ctx->file, start, pos, Table, .default_value=default_value, .entries=entries, .fallback=fallback); } PARSER(parse_set) { @@ -801,18 +777,6 @@ PARSER(parse_set) { whitespace(&pos); ast_list_t *items = NULL; - type_ast_t *item_type = NULL; - if (match(&pos, ":")) { - whitespace(&pos); - item_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a key type for this set"); - whitespace(&pos); - if (match(&pos, ",")) - return NULL; - whitespace(&pos); - match(&pos, ","); - whitespace(&pos); - } - for (;;) { ast_t *item = optional(ctx, &pos, parse_extended_expr); if (!item) break; @@ -834,7 +798,7 @@ PARSER(parse_set) { whitespace(&pos); expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this set"); - return NewAST(ctx->file, start, pos, Set, .item_type=item_type, .items=items); + return NewAST(ctx->file, start, pos, Set, .items=items); } ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs) { @@ -874,11 +838,11 @@ PARSER(parse_reduction) { if (!match(&pos, "(")) return NULL; whitespace(&pos); - binop_e op = match_binary_operator(&pos); - if (op == BINOP_UNKNOWN) return NULL; + ast_e op = match_binary_operator(&pos); + if (op == Unknown) return NULL; ast_t *key = NULL; - if (op == BINOP_MIN || op == BINOP_MAX) { + if (op == Min || op == Max) { key = NewAST(ctx->file, pos, pos, Var, .name="$"); for (bool progress = true; progress; ) { ast_t *new_term; @@ -1425,16 +1389,7 @@ PARSER(parse_none) { const char *start = pos; if (!match_word(&pos, "none")) return NULL; - - const char *none_end = pos; - spaces(&pos); - if (!match(&pos, ":")) - return NewAST(ctx->file, start, none_end, None, .type=NULL); - - spaces(&pos); - type_ast_t *type = parse_type(ctx, pos); - if (!type) return NULL; - return NewAST(ctx->file, start, type->end, None, .type=type); + return NewAST(ctx->file, start, pos, None); } PARSER(parse_deserialize) { @@ -1602,53 +1557,53 @@ ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn) { return NewAST(ctx->file, start, pos, FunctionCall, .fn=fn, .args=args); } -binop_e match_binary_operator(const char **pos) +ast_e match_binary_operator(const char **pos) { switch (**pos) { case '+': { *pos += 1; - return match(pos, "+") ? BINOP_CONCAT : BINOP_PLUS; + return match(pos, "+") ? Concat : Plus; } case '-': { *pos += 1; if ((*pos)[0] != ' ' && (*pos)[-2] == ' ') // looks like `fn -5` - return BINOP_UNKNOWN; - return BINOP_MINUS; + return Unknown; + return Minus; } - case '*': *pos += 1; return BINOP_MULT; - case '/': *pos += 1; return BINOP_DIVIDE; - case '^': *pos += 1; return BINOP_POWER; + case '*': *pos += 1; return Multiply; + case '/': *pos += 1; return Divide; + case '^': *pos += 1; return Power; case '<': { *pos += 1; - if (match(pos, "=")) return BINOP_LE; // "<=" - else if (match(pos, ">")) return BINOP_CMP; // "<>" + if (match(pos, "=")) return LessThanOrEquals; // "<=" + else if (match(pos, ">")) return Compare; // "<>" else if (match(pos, "<")) { if (match(pos, "<")) - return BINOP_ULSHIFT; // "<<<" - return BINOP_LSHIFT; // "<<" - } else return BINOP_LT; + return UnsignedLeftShift; // "<<<" + return LeftShift; // "<<" + } else return LessThan; } case '>': { *pos += 1; - if (match(pos, "=")) return BINOP_GE; // ">=" + if (match(pos, "=")) return GreaterThanOrEquals; // ">=" if (match(pos, ">")) { if (match(pos, ">")) - return BINOP_URSHIFT; // ">>>" - return BINOP_RSHIFT; // ">>" + return UnsignedRightShift; // ">>>" + return RightShift; // ">>" } - return BINOP_GT; + return GreaterThan; } default: { - if (match(pos, "!=")) return BINOP_NE; - else if (match(pos, "==") && **pos != '=') return BINOP_EQ; - else if (match_word(pos, "and")) return BINOP_AND; - else if (match_word(pos, "or")) return BINOP_OR; - else if (match_word(pos, "xor")) return BINOP_XOR; - else if (match_word(pos, "mod1")) return BINOP_MOD1; - else if (match_word(pos, "mod")) return BINOP_MOD; - else if (match_word(pos, "_min_")) return BINOP_MIN; - else if (match_word(pos, "_max_")) return BINOP_MAX; - else return BINOP_UNKNOWN; + if (match(pos, "!=")) return NotEquals; + else if (match(pos, "==") && **pos != '=') return Equals; + else if (match_word(pos, "and")) return And; + else if (match_word(pos, "or")) return Or; + else if (match_word(pos, "xor")) return Xor; + else if (match_word(pos, "mod1")) return Mod1; + else if (match_word(pos, "mod")) return Mod; + else if (match_word(pos, "_min_")) return Min; + else if (match_word(pos, "_max_")) return Max; + else return Unknown; } } } @@ -1660,9 +1615,9 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn int64_t starting_line = get_line_number(ctx->file, pos); int64_t starting_indent = get_indent(ctx, pos); spaces(&pos); - for (binop_e op; (op=match_binary_operator(&pos)) != BINOP_UNKNOWN && op_tightness[op] >= min_tightness; spaces(&pos)) { + for (ast_e op; (op=match_binary_operator(&pos)) != Unknown && op_tightness[op] >= min_tightness; spaces(&pos)) { ast_t *key = NULL; - if (op == BINOP_MIN || op == BINOP_MAX) { + if (op == Min || op == Max) { key = NewAST(ctx->file, pos, pos, Var, .name="$"); for (bool progress = true; progress; ) { ast_t *new_term; @@ -1688,12 +1643,12 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn if (!rhs) break; pos = rhs->end; - if (op == BINOP_MIN) { + if (op == Min) { return NewAST(ctx->file, lhs->start, rhs->end, Min, .lhs=lhs, .rhs=rhs, .key=key); - } else if (op == BINOP_MAX) { + } else if (op == Max) { return NewAST(ctx->file, lhs->start, rhs->end, Max, .lhs=lhs, .rhs=rhs, .key=key); } else { - lhs = NewAST(ctx->file, lhs->start, rhs->end, BinaryOp, .lhs=lhs, .op=op, .rhs=rhs); + lhs = new(ast_t, .file=ctx->file, .start=lhs->start, .end=rhs->end, .tag=op, .__data.Plus.lhs=lhs, .__data.Plus.rhs=rhs); } } return lhs; @@ -1709,8 +1664,11 @@ PARSER(parse_declaration) { if (!var) return NULL; pos = var->end; spaces(&pos); - if (!match(&pos, ":=")) return NULL; + if (!match(&pos, ":")) return NULL; + spaces(&pos); + type_ast_t *type = optional(ctx, &pos, parse_type); spaces(&pos); + if (!match(&pos, "=")) return NULL; ast_t *val = optional(ctx, &pos, parse_extended_expr); if (!val) { if (optional(ctx, &pos, parse_use)) @@ -1718,7 +1676,7 @@ PARSER(parse_declaration) { else parser_err(ctx, pos, eol(pos), "This is not a valid expression"); } - return NewAST(ctx->file, start, pos, Declare, .var=var, .value=val); + return NewAST(ctx->file, start, pos, Declare, .var=var, .type=type, .value=val); } PARSER(parse_update) { @@ -1726,23 +1684,23 @@ PARSER(parse_update) { ast_t *lhs = optional(ctx, &pos, parse_expr); if (!lhs) return NULL; spaces(&pos); - binop_e op; - if (match(&pos, "+=")) op = BINOP_PLUS; - else if (match(&pos, "++=")) op = BINOP_CONCAT; - else if (match(&pos, "-=")) op = BINOP_MINUS; - else if (match(&pos, "*=")) op = BINOP_MULT; - else if (match(&pos, "/=")) op = BINOP_DIVIDE; - else if (match(&pos, "^=")) op = BINOP_POWER; - else if (match(&pos, "<<=")) op = BINOP_LSHIFT; - else if (match(&pos, "<<<=")) op = BINOP_ULSHIFT; - else if (match(&pos, ">>=")) op = BINOP_RSHIFT; - else if (match(&pos, ">>>=")) op = BINOP_URSHIFT; - else if (match(&pos, "and=")) op = BINOP_AND; - else if (match(&pos, "or=")) op = BINOP_OR; - else if (match(&pos, "xor=")) op = BINOP_XOR; + ast_e op; + if (match(&pos, "+=")) op = Plus; + else if (match(&pos, "++=")) op = Concat; + else if (match(&pos, "-=")) op = Minus; + else if (match(&pos, "*=")) op = Multiply; + else if (match(&pos, "/=")) op = Divide; + else if (match(&pos, "^=")) op = Power; + else if (match(&pos, "<<=")) op = LeftShift; + else if (match(&pos, "<<<=")) op = UnsignedLeftShift; + else if (match(&pos, ">>=")) op = RightShift; + else if (match(&pos, ">>>=")) op = UnsignedRightShift; + else if (match(&pos, "and=")) op = And; + else if (match(&pos, "or=")) op = Or; + else if (match(&pos, "xor=")) op = Xor; else return NULL; ast_t *rhs = expect(ctx, start, &pos, parse_extended_expr, "I expected an expression here"); - return NewAST(ctx->file, start, pos, UpdateAssign, .lhs=lhs, .rhs=rhs, .op=op); + return new(ast_t, .file=ctx->file, .start=start, .end=pos, .tag=op, .__data.PlusUpdate.lhs=lhs, .__data.PlusUpdate.rhs=rhs); } PARSER(parse_assignment) { |
