harec

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

commit ea6d4c92cd331f1177eaea69e41d3d91a116b130
parent 5acdebf6a1c0e0a5021b0a02da5745dd5b69c0a7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 26 Dec 2020 13:35:25 -0500

parse: slicing and indexing expressions

This also refactors postfix expression to handle nested postfix
expressions, e.g. foo()(), x.y.z, or x[0][1]

Diffstat:
Minclude/ast.h | 16++++++++++++++--
Msrc/parse.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 102 insertions(+), 18 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -98,9 +98,15 @@ struct ast_type { }; struct ast_expression_access { - struct identifier ident; enum access_type type; - // TODO: Details for index, field selection + union { + struct identifier ident; + struct { + struct ast_expression *object; + struct ast_expression *index; + }; + // TODO: Field selection + }; }; struct ast_expression_assign { @@ -171,6 +177,11 @@ struct ast_expression_return { struct ast_expression *value; }; +struct ast_expression_slice { + struct ast_expression *object; + struct ast_expression *start, *end; +}; + struct ast_expression_unarithm { enum unarithm_operator op; struct ast_expression *operand; @@ -188,6 +199,7 @@ struct ast_expression { struct ast_expression_list list; struct ast_expression_measure measure; struct ast_expression_return _return; + struct ast_expression_slice slice; struct ast_expression_unarithm unarithm; }; }; diff --git a/src/parse.c b/src/parse.c @@ -606,6 +606,7 @@ parse_access(struct parser *par) trace(TR_PARSE, "access"); struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); exp->type = EXPR_ACCESS; + exp->access.type = ACCESS_IDENTIFIER; parse_identifier(par, &exp->access.ident); return exp; } @@ -731,7 +732,9 @@ parse_plain_expression(struct parser *par) trace(TR_PARSE, "plain"); struct token tok; + struct ast_expression *exp; switch (lex(par->lex, &tok)) { + // plain-expression case T_LITERAL: case T_TRUE: case T_FALSE: @@ -747,14 +750,20 @@ parse_plain_expression(struct parser *par) return parse_array_literal(par); case T_STRUCT: assert(0); // TODO: Struct literal + // nested-expression + case T_LPAREN: + exp = parse_complex_expression(par); + want(par, T_RPAREN, &tok); + return exp; default: synassert(false, &tok, T_LITERAL, T_NAME, - T_LBRACKET, T_STRUCT, T_EOF); + T_LBRACKET, T_STRUCT, T_LPAREN, T_EOF); } assert(0); // Unreachable } -static struct ast_expression *parse_postfix_expression(struct parser *par); +static struct ast_expression *parse_postfix_expression(struct parser *par, + struct ast_expression *exp); static struct ast_expression * parse_measurement_expression(struct parser *par) @@ -775,7 +784,7 @@ parse_measurement_expression(struct parser *par) break; case T_LEN: exp->measure.op = M_LEN; - exp->measure.value = parse_postfix_expression(par); + exp->measure.value = parse_postfix_expression(par, NULL); break; case T_OFFSET: exp->measure.op = M_OFFSET; @@ -793,11 +802,13 @@ parse_call_expression(struct parser *par, struct ast_expression *lvalue) { trenter(TR_PARSE, "call"); + struct token tok; + want(par, T_LPAREN, &tok); + struct ast_expression *expr = xcalloc(1, sizeof(struct ast_expression)); expr->type = EXPR_CALL; expr->call.lvalue = lvalue; - struct token tok; struct ast_call_argument *arg, **next = &expr->call.args; while (lex(par->lex, &tok) != T_RPAREN) { unlex(par->lex, &tok); @@ -831,11 +842,69 @@ parse_call_expression(struct parser *par, struct ast_expression *lvalue) } static struct ast_expression * -parse_postfix_expression(struct parser *par) +parse_index_slice_expression(struct parser *par, struct ast_expression *lvalue) +{ + trenter(TR_PARSE, "slice-index"); + + struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *start = NULL, *end = NULL; + struct token tok; + want(par, T_LBRACKET, &tok); + + bool is_slice = false; + switch (lex(par->lex, &tok)) { + case T_SLICE: + is_slice = true; + break; + default: + unlex(par->lex, &tok); + start = parse_simple_expression(par); + break; + } + + switch (lex(par->lex, &tok)) { + case T_SLICE: + is_slice = true; + break; + case T_RBRACKET: + break; + default: + synassert(false, &tok, T_SLICE, T_RBRACKET, T_EOF); + break; + } + + if (!is_slice) { + exp->type = EXPR_ACCESS; + exp->access.type = ACCESS_INDEX; + exp->access.object = lvalue; + exp->access.index = start; + trleave(TR_PARSE, "slice-index (index)"); + return exp; + } + + switch (lex(par->lex, &tok)) { + case T_RBRACKET: + break; + default: + end = parse_simple_expression(par); + break; + } + + exp->type = EXPR_SLICE; + exp->slice.object = lvalue; + exp->slice.start = start; + exp->slice.end = end; + trleave(TR_PARSE, "slice-index (slice)"); + return exp; +} + +static struct ast_expression * +parse_postfix_expression(struct parser *par, struct ast_expression *lvalue) { trace(TR_PARSE, "postfix"); - struct ast_expression *lvalue; + // TODO: The builtins should probably be moved outside of + // postfix-expression in the specification struct token tok; switch (lex(par->lex, &tok)) { case T_ABORT: @@ -847,29 +916,32 @@ parse_postfix_expression(struct parser *par) case T_OFFSET: unlex(par->lex, &tok); return parse_measurement_expression(par); - case T_LPAREN: - lvalue = parse_complex_expression(par); - want(par, T_RPAREN, &tok); - break; default: unlex(par->lex, &tok); - lvalue = parse_plain_expression(par); break; } + if (lvalue == NULL) { + lvalue = parse_plain_expression(par); + } + switch (lex(par->lex, &tok)) { case T_LPAREN: - return parse_call_expression(par, lvalue); + unlex(par->lex, &tok); + lvalue = parse_call_expression(par, lvalue); + break; case T_DOT: assert(0); // TODO: field access expression case T_LBRACKET: - assert(0); // TODO: indexing/slicing expression + unlex(par->lex, &tok); + lvalue = parse_index_slice_expression(par, lvalue); + break; default: unlex(par->lex, &tok); return lvalue; } - assert(0); // Unreachable + return parse_postfix_expression(par, lvalue); } static enum unarithm_operator @@ -901,7 +973,7 @@ parse_object_selector(struct parser *par) struct token tok; lex(par->lex, &tok); unlex(par->lex, &tok); - struct ast_expression *exp = parse_postfix_expression(par); + struct ast_expression *exp = parse_postfix_expression(par, NULL); synassert_msg(exp->type == EXPR_ACCESS, "expected object", &tok); return exp; } @@ -931,7 +1003,7 @@ parse_unary_expression(struct parser *par) return exp; default: unlex(par->lex, &tok); - return parse_postfix_expression(par); + return parse_postfix_expression(par, NULL); } }