harec

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

commit 07196daba75a25dcde6f2f20dca666ad662467c7
parent 9fc2f079bbef9ac7491174b547b146b572a0f876
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 22 Jan 2021 19:24:41 -0500

parse: implement match expressions

Diffstat:
Minclude/ast.h | 43++++++++++++++++++++++++++++---------------
Msrc/parse.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 115 insertions(+), 16 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -224,6 +224,18 @@ struct ast_expression_list { struct ast_expression_list *next; }; +struct ast_match_case { + char *name; // May be null + struct ast_type *type; + struct ast_expression *value; + struct ast_match_case *next; +}; + +struct ast_expression_match { + struct ast_expression *value; + struct ast_match_case *cases; +}; + struct ast_expression_measure { enum measure_operator op; union { @@ -242,21 +254,6 @@ struct ast_expression_slice { struct ast_expression *start, *end; }; -struct ast_expression_struct; - -struct ast_field_value { - bool is_embedded; - union { - struct { - char *name; - struct ast_type *type; - struct ast_expression *initializer; - } field; - struct ast_expression *embedded; - }; - struct ast_field_value *next; -}; - struct ast_case_option { struct ast_expression *value; struct ast_case_option *next; @@ -273,6 +270,21 @@ struct ast_expression_switch { struct ast_switch_case *cases; }; +struct ast_expression_struct; + +struct ast_field_value { + bool is_embedded; + union { + struct { + char *name; + struct ast_type *type; + struct ast_expression *initializer; + } field; + struct ast_expression *embedded; + }; + struct ast_field_value *next; +}; + struct ast_expression_struct { bool autofill; struct identifier type; @@ -302,6 +314,7 @@ struct ast_expression { struct ast_expression_for _for; struct ast_expression_if _if; struct ast_expression_list list; + struct ast_expression_match match; struct ast_expression_measure measure; struct ast_expression_return _return; struct ast_expression_slice slice; diff --git a/src/parse.c b/src/parse.c @@ -1691,6 +1691,92 @@ parse_switch_expression(struct lexer *lexer) } static struct ast_expression * +parse_match_expression(struct lexer *lexer) +{ + trenter(TR_PARSE, "match"); + struct ast_expression *exp = mkexpr(&lexer->loc); + exp->type = EXPR_MATCH; + + struct token tok = {0}; + want(lexer, T_LPAREN, &tok); + exp->match.value = parse_simple_expression(lexer); + want(lexer, T_RPAREN, &tok); + want(lexer, T_LBRACE, &tok); + + bool more = true; + struct ast_match_case **next_case = &exp->match.cases; + while (more) { + struct ast_match_case *_case = + *next_case = xcalloc(1, sizeof(struct ast_match_case)); + + struct token tok2 = {0}; + switch (lex(lexer, &tok)) { + case T_NAME: + switch (lex(lexer, &tok2)) { + case T_COLON: + _case->name = tok.name; // Assumes ownership + _case->type = parse_type(lexer); + break; + case T_DOUBLE_COLON: + _case->type = parse_type(lexer); + assert(_case->type->storage == TYPE_STORAGE_ALIAS); + struct identifier ident = { + .name = tok.name, // Assumes ownership + .ns = xcalloc(1, sizeof(struct identifier)), + }; + *ident.ns = _case->type->alias; + _case->type->alias = ident; + break; + case T_CASE: + unlex(lexer, &tok); + _case->type = parse_type(lexer); + assert(_case->type->storage == TYPE_STORAGE_ALIAS); + unlex(lexer, &tok2); + break; + default: + synassert(false, &tok, T_COLON, + T_DOUBLE_COLON, T_CASE, T_EOF); + break; + } + break; + case T_TIMES: + want(lexer, T_CASE, &tok); + break; + default: + unlex(lexer, &tok); + _case->type = parse_type(lexer); + want(lexer, T_CASE, &tok); + break; + } + + _case->value = parse_compound_expression(lexer); + + switch (lex(lexer, &tok)) { + case T_COMMA: + switch (lex(lexer, &tok)) { + case T_RBRACE: + more = false; + break; + default: + unlex(lexer, &tok); + break; + } + break; + case T_RBRACE: + more = false; + break; + default: + synassert(false, &tok, T_COMMA, T_RBRACE, T_EOF); + } + + next_case = &_case->next; + } + + trleave(TR_PARSE, NULL); + return exp; +} + +static struct ast_expression * parse_complex_expression(struct lexer *lexer) { struct token tok; @@ -1702,7 +1788,7 @@ parse_complex_expression(struct lexer *lexer) unlex(lexer, &tok); return parse_for_expression(lexer); case T_MATCH: - assert(0); // TODO + return parse_match_expression(lexer); case T_SWITCH: return parse_switch_expression(lexer); default: