commit a46a5164ef7c3c35f811316c843d7004b11ef0d2
parent 7e165462b67706c380de17d194ee09a928f4f635
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 29 Dec 2020 14:41:10 -0500
parse: implement for loops
Diffstat:
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