harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit a46a5164ef7c3c35f811316c843d7004b11ef0d2
parent 7e165462b67706c380de17d194ee09a928f4f635
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 29 Dec 2020 14:41:10 -0500

parse: implement for loops

Diffstat:
Minclude/ast.h | 8++++++++
Minclude/expr.h | 1-
Msrc/check.c | 2--
Msrc/eval.c | 3+--
Msrc/gen.c | 2--
Msrc/parse.c | 43+++++++++++++++++++++++++++++++++++++++++++
6 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -162,6 +162,13 @@ struct ast_expression_constant { }; }; +struct ast_expression_for { + struct ast_expression *bindings; + struct ast_expression *cond; + struct ast_expression *afterthought; + struct ast_expression *body; +}; + struct ast_expression_if { struct ast_expression *cond; struct ast_expression *true_branch, *false_branch; @@ -225,6 +232,7 @@ struct ast_expression { struct ast_expression_binding binding; struct ast_expression_call call; struct ast_expression_constant constant; + struct ast_expression_for _for; struct ast_expression_if _if; struct ast_expression_list list; struct ast_expression_measure measure; diff --git a/include/expr.h b/include/expr.h @@ -28,7 +28,6 @@ enum expr_type { EXPR_STRUCT, EXPR_SWITCH, EXPR_UNARITHM, - EXPR_WHILE, }; enum access_type { diff --git a/src/check.c b/src/check.c @@ -583,8 +583,6 @@ check_expression(struct context *ctx, case EXPR_UNARITHM: check_expr_unarithm(ctx, aexpr, expr); break; - case EXPR_WHILE: - assert(0); // TODO } trleave(TR_CHECK, NULL); diff --git a/src/eval.c b/src/eval.c @@ -26,7 +26,6 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_CONSTANT: return eval_const(ctx, in, out); case EXPR_CONTINUE: - case EXPR_FOR: case EXPR_MEASURE: case EXPR_SLICE: case EXPR_STRUCT: @@ -37,12 +36,12 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_BINDING: case EXPR_BREAK: case EXPR_CALL: + case EXPR_FOR: case EXPR_IF: case EXPR_LIST: case EXPR_MATCH: case EXPR_RETURN: case EXPR_SWITCH: - case EXPR_WHILE: // Excluded from translation-compatible subset return EVAL_INVALID; } diff --git a/src/gen.c b/src/gen.c @@ -796,8 +796,6 @@ gen_expression(struct gen_context *ctx, case EXPR_UNARITHM: gen_expr_unarithm(ctx, expr, out); break; - case EXPR_WHILE: - assert(0); // TODO } } diff --git a/src/parse.c b/src/parse.c @@ -332,6 +332,8 @@ parse_primitive_type(struct parser *par) static struct ast_expression *parse_simple_expression(struct parser *par); static struct ast_expression *parse_complex_expression(struct parser *par); static struct ast_expression *parse_compound_expression(struct parser *par); +static struct ast_expression *parse_scope_expression(struct parser *par); +static struct ast_expression *parse_binding_list(struct parser *par); static struct ast_type * parse_enum_type(struct parser *par) @@ -1328,6 +1330,46 @@ parse_if_expression(struct parser *par) } static struct ast_expression * +parse_for_expression(struct parser *par) +{ + trenter(TR_PARSE, "for"); + struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + exp->type = EXPR_FOR; + + struct token tok = {0}; + want(par, T_LPAREN, &tok); + switch (lex(par->lex, &tok)) { + case T_LET: + case T_CONST: + unlex(par->lex, &tok); + exp->_for.bindings = parse_binding_list(par); + want(par, T_SEMICOLON, &tok); + break; + default: + unlex(par->lex, &tok); + break; + } + + exp->_for.cond = parse_simple_expression(par); + + switch (lex(par->lex, &tok)) { + case T_SEMICOLON: + exp->_for.afterthought = parse_scope_expression(par); + want(par, T_RPAREN, &tok); + break; + case T_RPAREN: + break; + default: + synassert(false, &tok, T_SEMICOLON, T_RPAREN, T_EOF); + } + + exp->_for.body = parse_compound_expression(par); + + trleave(TR_PARSE, NULL); + return exp; +} + +static struct ast_expression * parse_complex_expression(struct parser *par) { struct token tok; @@ -1335,6 +1377,7 @@ parse_complex_expression(struct parser *par) case T_IF: return parse_if_expression(par); case T_FOR: + return parse_for_expression(par); case T_MATCH: case T_SWITCH: assert(0); // TODO