commit e81307e4dc2f4eea650499cdc6a635c0b04aaf54
parent 064f0240f37e483ff6d1019b1172930953142814
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 20 Dec 2020 15:18:45 -0500
parse: parse control-statement
Diffstat:
5 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -102,11 +102,16 @@ struct ast_expression_list {
struct ast_expression_list *next;
};
+struct ast_return_expression {
+ struct ast_expression *value;
+};
+
struct ast_expression {
enum expr_type type;
union {
struct ast_constant_expression constant;
struct ast_expression_list list;
+ struct ast_return_expression _return;
};
};
diff --git a/include/expr.h b/include/expr.h
@@ -9,10 +9,11 @@ enum expr_type {
EXPR_ASSIGN,
EXPR_BINARITHM,
EXPR_BINDING_LIST,
+ EXPR_BREAK,
EXPR_CALL,
EXPR_CAST,
EXPR_CONSTANT,
- EXPR_CONTROL,
+ EXPR_CONTINUE,
EXPR_FOR,
EXPR_FREE,
EXPR_FUNC,
@@ -21,6 +22,7 @@ enum expr_type {
EXPR_LIST,
EXPR_MATCH,
EXPR_MEASURE,
+ EXPR_RETURN,
EXPR_SLICE,
EXPR_STRUCT,
EXPR_SWITCH,
diff --git a/src/check.c b/src/check.c
@@ -119,13 +119,14 @@ check_expression(struct context *ctx,
case EXPR_ASSIGN:
case EXPR_BINARITHM:
case EXPR_BINDING_LIST:
+ case EXPR_BREAK:
case EXPR_CALL:
case EXPR_CAST:
assert(0); // TODO
case EXPR_CONSTANT:
check_expr_constant(ctx, aexpr, expr);
break;
- case EXPR_CONTROL:
+ case EXPR_CONTINUE:
case EXPR_FOR:
case EXPR_FREE:
case EXPR_FUNC:
@@ -137,6 +138,7 @@ check_expression(struct context *ctx,
break;
case EXPR_MATCH:
case EXPR_MEASURE:
+ case EXPR_RETURN:
case EXPR_SLICE:
case EXPR_STRUCT:
case EXPR_SWITCH:
diff --git a/src/gen.c b/src/gen.c
@@ -157,13 +157,14 @@ gen_expression(struct gen_context *ctx,
case EXPR_ASSIGN:
case EXPR_BINARITHM:
case EXPR_BINDING_LIST:
+ case EXPR_BREAK:
case EXPR_CALL:
case EXPR_CAST:
assert(0); // TODO
case EXPR_CONSTANT:
gen_constant(ctx, expr, out);
break;
- case EXPR_CONTROL:
+ case EXPR_CONTINUE:
case EXPR_FOR:
case EXPR_FREE:
case EXPR_FUNC:
@@ -175,6 +176,7 @@ gen_expression(struct gen_context *ctx,
break;
case EXPR_MATCH:
case EXPR_MEASURE:
+ case EXPR_RETURN:
case EXPR_SLICE:
case EXPR_STRUCT:
case EXPR_SWITCH:
diff --git a/src/parse.c b/src/parse.c
@@ -394,6 +394,40 @@ parse_scope_expression(struct parser *par, struct ast_expression *exp)
}
static void
+parse_control_statement(struct parser *par, struct ast_expression *exp)
+{
+ trenter(TR_PARSE, "control-expression");
+
+ struct token tok;
+ switch (lex(par->lex, &tok)) {
+ case T_BREAK:
+ case T_CONTINUE:
+ assert(0); // TODO
+ case T_RETURN:
+ trace(TR_PARSE, "return");
+ exp->type = EXPR_RETURN;
+ exp->_return.value = NULL;
+ struct token tok;
+ switch (lex(par->lex, &tok)) {
+ case T_SEMICOLON:
+ unlex(par->lex, &tok);
+ break;
+ default:
+ unlex(par->lex, &tok);
+ exp->_return.value =
+ calloc(1, sizeof(struct ast_expression));
+ parse_complex_expression(par, exp->_return.value);
+ break;
+ }
+ break;
+ default:
+ synassert(false, &tok, T_BREAK, T_CONTINUE, T_RETURN, T_EOF);
+ }
+
+ trleave(TR_PARSE, NULL);
+}
+
+static void
parse_expression_list(struct parser *par, struct ast_expression *exp)
{
trenter(TR_PARSE, "expression-list");
@@ -417,6 +451,21 @@ parse_expression_list(struct parser *par, struct ast_expression *exp)
case T_RBRACE:
more = false;
break;
+ case T_BREAK:
+ case T_CONTINUE:
+ case T_RETURN:
+ unlex(par->lex, &tok);
+ *next = calloc(1, sizeof(struct ast_expression_list));
+ cur = *next;
+
+ curexp = calloc(1, sizeof(struct ast_expression));
+ parse_control_statement(par, curexp);
+ cur->expr = curexp;
+
+ want(par, T_SEMICOLON, &tok);
+ want(par, T_RBRACE, &tok);
+ more = false;
+ break;
default:
*next = calloc(1, sizeof(struct ast_expression_list));
cur = *next;