diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-03-14 02:37:56 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-03-14 02:37:56 -0400 |
| commit | fdc3eadba25aff7894419e483519e73150be33d4 (patch) | |
| tree | ae0bf68e1bfa501fd9010b66d2211b0b1ef59a23 /parse.c | |
| parent | 130ddc8ea04060ec52d9a2fd03da8c9662d32f9c (diff) | |
Array comprehensions
Diffstat (limited to 'parse.c')
| -rw-r--r-- | parse.c | 36 |
1 files changed, 36 insertions, 0 deletions
@@ -68,6 +68,7 @@ static ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn, bool is_extern); static ast_t *parse_method_call_suffix(parse_ctx_t *ctx, ast_t *self); static ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs); static ast_t *parse_index_suffix(parse_ctx_t *ctx, ast_t *lhs); +static ast_t *parse_for_suffix(parse_ctx_t *ctx, ast_t *lhs); static arg_ast_t *parse_args(parse_ctx_t *ctx, const char **pos, bool allow_unnamed); static PARSER(parse_for); static PARSER(parse_while); @@ -616,6 +617,11 @@ PARSER(parse_array) { for (;;) { ast_t *item = optional(ctx, &pos, parse_extended_expr); if (!item) break; + ast_t *suffixed = parse_for_suffix(ctx, item); + if (suffixed) { + item = suffixed; + pos = suffixed->end; + } items = new(ast_list_t, .ast=item, .next=items); if (!match_separator(&pos)) break; @@ -785,6 +791,36 @@ ast_t *parse_index_suffix(parse_ctx_t *ctx, ast_t *lhs) { return NewAST(ctx->file, start, pos, Index, .indexed=lhs, .index=index, .unchecked=unchecked); } +ast_t *parse_for_suffix(parse_ctx_t *ctx, ast_t *lhs) { + // <expr> for [<index>,]<var> in <iter> [if <condition>] + if (!lhs) return NULL; + const char *start = lhs->start; + const char *pos = lhs->end; + whitespace(&pos); + if (!match_word(&pos, "for")) return NULL; + + ast_t *index = expect(ctx, start, &pos, parse_var, "I expected an iteration variable for this 'for'"); + whitespace(&pos); + ast_t *value = NULL; + if (match(&pos, ",")) { + value = expect(ctx, pos-1, &pos, parse_var, "I expected a variable after this comma"); + } else { + value = index; + index = NULL; + } + expect_str(ctx, start, &pos, "in", "I expected an 'in' for this 'for'"); + ast_t *iter = expect(ctx, start, &pos, parse_expr, "I expected an iterable value for this 'for'"); + whitespace(&pos); + ast_t *body = lhs; + if (match_word(&pos, "if")) { + ast_t *condition = expect(ctx, pos-2, &pos, parse_expr, "I expected a condition for this 'if'"); + body = NewAST(ctx->file, body->start, condition->end, Block, + .statements=new(ast_list_t, .ast=WrapAST(condition, If, .condition=condition, .else_body=FakeAST(Skip)), + .next=new(ast_list_t, .ast=body))); + } + return NewAST(ctx->file, start, pos, For, .index=index, .value=value, .iter=iter, .body=body); +} + PARSER(parse_if) { // if <condition> [then] <body> [else <body>] const char *start = pos; |
