commit 5a58ba55c2b8e8119ffd28f1c6af348e6bad85d9
parent cba5917f5dd3cfc7336db55f3150fb1a5baa6e0e
Author: Eyal Sawady <ecs@d2evs.net>
Date: Mon, 11 Jan 2021 11:26:56 -0500
parse: implement allocation expressions
Diffstat:
M | include/ast.h | | | 23 | +++++++++++++++++++++++ |
M | src/parse.c | | | 75 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 98 insertions(+), 0 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -116,6 +116,28 @@ struct ast_expression_access {
};
};
+enum alloc_kind {
+ ALLOC_KIND_ALLOC,
+ ALLOC_KIND_APPEND,
+ ALLOC_KIND_FREE,
+};
+
+struct ast_append_values {
+ struct ast_expression *value;
+ struct ast_append_values *next;
+};
+
+struct ast_expression_allocation {
+ enum alloc_kind kind;
+ struct ast_expression *expr;
+ // For allocs only
+ struct ast_type *type;
+ // For appends only
+ bool variadic;
+ struct ast_append_values *values;
+ struct ast_expression *cap;
+};
+
struct ast_expression_assert {
struct ast_expression *cond;
struct ast_expression *message;
@@ -245,6 +267,7 @@ struct ast_expression {
enum expr_type type;
union {
struct ast_expression_access access;
+ struct ast_expression_allocation alloc;
struct ast_expression_assert assert;
struct ast_expression_assign assign;
struct ast_expression_binarithm binarithm;
diff --git a/src/parse.c b/src/parse.c
@@ -1120,6 +1120,72 @@ parse_index_slice_expression(struct lexer *lexer, struct ast_expression *lvalue)
}
static struct ast_expression *
+parse_allocation_expression(struct lexer *lexer)
+{
+ trenter(TR_PARSE, "allocation");
+ struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression));
+ struct token tok = {0};
+ switch (lex(lexer, &tok)) {
+ case T_ALLOC:
+ trace(TR_PARSE, "alloc");
+ exp->alloc.kind = ALLOC_KIND_ALLOC;
+ want(lexer, T_LPAREN, NULL);
+ exp->alloc.type = parse_type(lexer);
+ want(lexer, T_COMMA, NULL);
+ exp->alloc.expr = parse_simple_expression(lexer);
+ switch (lex(lexer, &tok)) {
+ case T_COMMA:
+ exp->alloc.cap = parse_simple_expression(lexer);
+ want(lexer, T_RPAREN, NULL);
+ break;
+ case T_RPAREN:
+ break;
+ default:
+ synassert(false, &tok, T_COMMA, T_RPAREN, T_EOF);
+ }
+ break;
+ case T_APPEND:
+ trace(TR_PARSE, "append");
+ exp->alloc.kind = ALLOC_KIND_APPEND;
+ want(lexer, T_LPAREN, NULL);
+ exp->alloc.expr = parse_simple_expression(lexer);
+ want(lexer, T_COMMA, NULL);
+ struct ast_append_values **next = &exp->alloc.values;
+ while (tok.token != T_RPAREN) {
+ *next = xcalloc(1, sizeof(struct ast_append_values));
+ if (lex(lexer, &tok) == T_ELLIPSIS) {
+ exp->alloc.variadic = true;
+ (*next)->value = parse_simple_expression(lexer);
+ if (lex(lexer, &tok) != T_COMMA) {
+ unlex(lexer, &tok);
+ }
+ want(lexer, T_RPAREN, &tok);
+ break;
+ }
+ unlex(lexer, &tok);
+ (*next)->value = parse_simple_expression(lexer);
+ if (lex(lexer, &tok) != T_COMMA) {
+ unlex(lexer, &tok);
+ want(lexer, T_RPAREN, &tok);
+ }
+ next = &(*next)->next;
+ }
+ break;
+ case T_FREE:
+ trace(TR_PARSE, "free");
+ exp->alloc.kind = ALLOC_KIND_FREE;
+ want(lexer, T_LPAREN, NULL);
+ exp->alloc.expr = parse_simple_expression(lexer);
+ want(lexer, T_RPAREN, NULL);
+ break;
+ default:
+ assert(0);
+ }
+ trleave(TR_PARSE, NULL);
+ return exp;
+}
+
+static struct ast_expression *
parse_postfix_expression(struct lexer *lexer, struct ast_expression *lvalue)
{
trace(TR_PARSE, "postfix");
@@ -1128,9 +1194,18 @@ parse_postfix_expression(struct lexer *lexer, struct ast_expression *lvalue)
// postfix-expression in the specification
struct token tok;
switch (lex(lexer, &tok)) {
+ case T_ALLOC:
+ case T_APPEND:
+ case T_FREE:
+ synassert(lvalue == NULL, &tok, T_LPAREN, T_DOT, T_LBRACKET,
+ T_EOF);
+ unlex(lexer, &tok);
+ return parse_allocation_expression(lexer);
case T_ABORT:
case T_ASSERT:
case T_STATIC:
+ synassert(lvalue == NULL, &tok, T_LPAREN, T_DOT, T_LBRACKET,
+ T_EOF);
unlex(lexer, &tok);
return parse_assertion_expression(lexer);
case T_SIZE: