harec

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

commit dcce8b33f57727f8b29dce99a5bf0785b20cb99e
parent cdf2ef220d0bb146988bc074431133fcbbf2601a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 23 Dec 2020 13:14:45 -0500

parse: fix up scope-expression

Diffstat:
Minclude/ast.h | 2++
Minclude/expr.h | 9++++++++-
Msrc/check.c | 1-
Msrc/gen.c | 1-
Msrc/parse.c | 77++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
5 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -86,6 +86,8 @@ struct ast_type { struct ast_expression_access { struct identifier ident; + enum access_type type; + // TODO: Details for index, field selection }; struct ast_expression_assign { diff --git a/include/expr.h b/include/expr.h @@ -21,7 +21,6 @@ enum expr_type { EXPR_FOR, EXPR_FREE, EXPR_IF, - EXPR_INDEX, EXPR_LIST, EXPR_MATCH, EXPR_MEASURE, @@ -33,8 +32,16 @@ enum expr_type { EXPR_WHILE, }; +enum access_type { + ACCESS_IDENTIFIER, + ACCESS_INDEX, + ACCESS_FIELD, +}; + struct expression_access { const struct scope_object *object; + enum access_type type; + // TODO: Details for index, field selection }; enum binarithm_operator { diff --git a/src/check.c b/src/check.c @@ -281,7 +281,6 @@ check_expression(struct context *ctx, case EXPR_FOR: case EXPR_FREE: case EXPR_IF: - case EXPR_INDEX: assert(0); // TODO case EXPR_LIST: check_expr_list(ctx, aexpr, expr); diff --git a/src/gen.c b/src/gen.c @@ -304,7 +304,6 @@ gen_expression(struct gen_context *ctx, case EXPR_FOR: case EXPR_FREE: case EXPR_IF: - case EXPR_INDEX: assert(0); // TODO case EXPR_LIST: gen_expr_list(ctx, expr, out); diff --git a/src/parse.c b/src/parse.c @@ -780,67 +780,82 @@ parse_binding_list(struct parser *par) static struct ast_expression * parse_assignment(struct parser *par, struct ast_expression *lvalue, bool indirect) { + trenter(TR_PARSE, "assign"); 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; + trleave(TR_PARSE, NULL); return expr; } static struct ast_expression * parse_scope_expression(struct parser *par) { - struct ast_expression *value; - - bool indirect = false; + // This is one of the more complicated non-terminals to parse. struct token tok; + bool indirect = false; + switch (lex(par->lex, &tok)) { + case T_TIMES: // *ptr = value (or unary-expression) + // TODO: indirect access is untested (pending support for + // dereferencing in unary-expression) + indirect = true; + break; + default: + unlex(par->lex, &tok); + break; + } + + struct ast_expression *value; switch (lex(par->lex, &tok)) { case T_LET: case T_CONST: unlex(par->lex, &tok); return parse_binding_list(par); case T_STATIC: - assert(0); // TODO: Binding list or assert - case T_TIMES: // *ptr = val - indirect = true; - lex(par->lex, &tok); - // fallthrough - default: + assert(0); // TODO: This is a static binding list or assert + 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_BAND: + case T_TIMES: // unary-expression unlex(par->lex, &tok); - 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 - if (indirect) { - assert(0); // TODO: Wrap in unary dereference - } - return parse_complex_expression(par); - default: // postfix-expression - value = parse_postfix_expression(par); + value = parse_complex_expression(par); + if (indirect) { + assert(0); // TODO: Wrap value in unary dereference + } + return value; + default: // postfix-expression + unlex(par->lex, &tok); + if (indirect) { + value = parse_unary_expression(par); break; } + value = parse_postfix_expression(par); + if (value->type != EXPR_ACCESS) { + return value; + } + // Is possible object-selector, try for assignment break; } switch (lex(par->lex, &tok)) { case T_EQUAL: - return parse_assignment(par, value, false); + return parse_assignment(par, value, indirect); default: + unlex(par->lex, &tok); + value = parse_bin_expression(par, value, 0); if (indirect) { - assert(0); // TODO: Wrap in unary dereference + assert(0); // TODO: Wrap value in unary dereference } - unlex(par->lex, &tok); - // Fall back to simple-expression - return parse_bin_expression(par, value, 0); + return value; } }