harec

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

commit f81c51801a0fb3f5c02675e20ba288cfb9949de8
parent 17b195626bb22c94cea9927e803dc9bb9afccfe3
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 23 Dec 2020 12:09:21 -0500

parse: implement assignment expressions

Diffstat:
Minclude/ast.h | 6++++++
Msrc/parse.c | 89+++++++++++++++++++++++++++++++++++++++++++------------------------------------
2 files changed, 55 insertions(+), 40 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -88,6 +88,11 @@ struct ast_expression_access { struct identifier ident; }; +struct ast_expression_assign { + struct ast_expression *lvalue, *rvalue; + bool indirect; +}; + struct ast_expression_binarithm { enum binarithm_operator op; struct ast_expression *lvalue, *rvalue; @@ -126,6 +131,7 @@ struct ast_expression { enum expr_type type; union { struct ast_expression_access access; + struct ast_expression_assign assign; struct ast_expression_binarithm binarithm; struct ast_expression_binding binding; struct ast_expression_constant constant; diff --git a/src/parse.c b/src/parse.c @@ -65,43 +65,6 @@ want(struct parser *par, enum lexical_token ltok, struct token *tok) } } -// Returns true if this token may be the first token of a complex-expression -/* -static bool -is_expr_start(struct token *tok) -{ - switch (tok->token) { - case T_ABORT: - case T_ASSERT: - case T_FALSE: - case T_FOR: - case T_IF: - case T_LEN: - case T_MATCH: - case T_NULL: - case T_RUNE: - case T_STRUCT: - case T_SWITCH: - case T_TRUE: - case T_UNION: - case T_VOID: - case T_WHILE: - case T_LNOT: - case T_LPAREN: - case T_MINUS: - case T_PLUS: - case T_TIMES: - case T_LABEL: - case T_LITERAL: - case T_NAME: - return true; - default: - return false; - } - assert(0); // Unreachable -} -*/ - static void parse_identifier(struct parser *par, struct identifier *ident) { @@ -815,8 +778,23 @@ parse_binding_list(struct parser *par) } static struct ast_expression * +parse_assignment(struct parser *par, struct ast_expression *lvalue, bool indirect) +{ + struct ast_expression *rvalue = parse_complex_expression(par); + struct ast_expression *expr = calloc(1, sizeof(struct ast_expression)); + expr->type = EXPR_ASSIGN; + expr->assign.lvalue = lvalue; + expr->assign.rvalue = rvalue; + expr->assign.indirect = indirect; + return expr; +} + +static struct ast_expression * parse_scope_expression(struct parser *par) { + struct ast_expression *value; + + bool indirect = false; struct token tok; switch (lex(par->lex, &tok)) { case T_LET: @@ -824,11 +802,42 @@ parse_scope_expression(struct parser *par) unlex(par->lex, &tok); return parse_binding_list(par); case T_STATIC: - assert(0); // Binding list or assert + assert(0); // TODO: Binding list or assert + case T_TIMES: // *ptr = val + indirect = true; + lex(par->lex, &tok); + // fallthrough default: unlex(par->lex, &tok); - return parse_complex_expression(par); - // TODO: allocations, assignments + switch (tok.token) { + case T_IF: + case T_FOR: + case T_MATCH: + case T_SWITCH: // complex-expression + case T_PLUS: + case T_MINUS: + case T_BNOT: + case T_LNOT: + case T_TIMES: + case T_BAND: // unary-expression + return parse_complex_expression(par); + default: // postfix-expression + value = parse_postfix_expression(par); + break; + } + break; + } + + switch (lex(par->lex, &tok)) { + case T_EQUAL: + return parse_assignment(par, value, false); + default: + if (indirect) { + assert(0); // TODO: Wrap in unary dereference + } + unlex(par->lex, &tok); + // Fall back to simple-expression + return parse_bin_expression(par, value, 0); } }