harec

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

commit 3d72f5250685098c7513d4bca48c7a4717616a4f
parent 5bed9c64bbf2e52bb8c79a172a2a561eac018020
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date:   Wed, 16 Mar 2022 10:44:31 +0100

parse: add support for complex import variants

Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>

Diffstat:
Minclude/ast.h | 10+++++-----
Msrc/check.c | 3++-
Msrc/parse.c | 72+++++++++++++++++++++++++++++++++++++++++++-----------------------------
3 files changed, 50 insertions(+), 35 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -9,15 +9,15 @@ struct ast_type; -enum ast_import_mode { - AST_IMPORT_IDENTIFIER, // use foo::bar; - AST_IMPORT_ALIAS, // use foo::bar = x::y; - AST_IMPORT_MEMBERS, // use foo::bar::{a, b, c}; +enum ast_import_mode_flags { + AST_IMPORT_ALIAS = 1 << 0, // use foo::bar = x::y; + AST_IMPORT_MEMBERS = 1 << 1, // use foo::bar::{a, b, c}; + AST_IMPORT_WILDCARD = 1 << 2, // use foo::bar::*; }; struct ast_imports { struct location loc; - enum ast_import_mode mode; + enum ast_import_mode_flags mode; struct identifier ident; struct identifier *alias; struct ast_imports *members; diff --git a/src/check.c b/src/check.c @@ -3507,7 +3507,7 @@ load_import(struct context *ctx, struct ast_imports *import, ctx->store->check_context = old_ctx; switch (import->mode) { - case AST_IMPORT_IDENTIFIER: + default: for (struct scope_object *obj = mod->objects; obj; obj = obj->lnext) { if (obj->otype == O_SCAN) { @@ -3538,6 +3538,7 @@ load_import(struct context *ctx, struct ast_imports *import, } } break; + case AST_IMPORT_WILDCARD: case AST_IMPORT_ALIAS: for (struct scope_object *obj = mod->objects; obj; obj = obj->lnext) { diff --git a/src/parse.c b/src/parse.c @@ -167,11 +167,15 @@ parse_name_list(struct lexer *lexer, struct ast_imports *name) next = &name->next; } break; + case T_EQUAL: + name->alias = xcalloc(1, sizeof(struct identifier)); + *name->alias = name->ident; + break; case T_RBRACE: more = false; break; default: - synassert(false, &tok, T_RBRACE, T_COMMA, T_EOF); + synassert(false, &tok, T_RBRACE, T_EQUAL, T_COMMA, T_EOF); break; } } @@ -181,35 +185,45 @@ static void parse_import(struct lexer *lexer, struct ast_imports *imports) { struct identifier ident = {0}; - bool trailing_colon = parse_identifier(lexer, &ident, true); - struct token tok = {0}; - switch (lex(lexer, &tok)) { - case T_EQUAL: - synassert(!trailing_colon, &tok, T_NAME, T_EOF); - imports->mode = AST_IMPORT_ALIAS; - imports->alias = xcalloc(1, sizeof(struct identifier)); - *imports->alias = ident; - parse_identifier(lexer, &imports->ident, false); - want(lexer, T_SEMICOLON, &tok); - break; - case T_LBRACE: - synassert(trailing_colon, &tok, T_DOUBLE_COLON, T_EOF); - imports->mode = AST_IMPORT_MEMBERS; - imports->ident = ident; - imports->members = xcalloc(1, sizeof(struct ast_imports)); - parse_name_list(lexer, imports->members); - want(lexer, T_SEMICOLON, &tok); - break; - case T_SEMICOLON: - synassert(!trailing_colon, &tok, T_NAME, T_EOF); - imports->mode = AST_IMPORT_IDENTIFIER; - imports->ident = ident; - break; - default: - synassert(!trailing_colon, &tok, T_EQUAL, T_SEMICOLON, T_EOF); - synassert(trailing_colon, &tok, T_NAME, T_LBRACE, T_EOF); - break; + imports->mode = 0; + while (true) { + bool trailing_colon = parse_identifier(lexer, &ident, true); + switch (lex(lexer, &tok)) { + case T_EQUAL: + synassert(!trailing_colon, &tok, T_NAME, T_EOF); + synassert(!(imports->mode & AST_IMPORT_ALIAS), &tok, + T_SEMICOLON, T_LBRACE, T_EOF); + imports->mode |= AST_IMPORT_ALIAS; + imports->alias = xcalloc(1, sizeof(struct identifier)); + *imports->alias = ident; + break; + case T_LBRACE: + synassert(trailing_colon, &tok, T_DOUBLE_COLON, T_EOF); + imports->mode |= AST_IMPORT_MEMBERS; + imports->ident = ident; + imports->members = xcalloc(1, sizeof(struct ast_imports)); + parse_name_list(lexer, imports->members); + want(lexer, T_SEMICOLON, &tok); + return; + case T_SEMICOLON: + synassert(!trailing_colon, &tok, T_NAME, T_EOF); + imports->ident = ident; + return; + case T_TIMES: + synassert(trailing_colon, &tok, T_DOUBLE_COLON, T_EOF); + synassert(!(imports->mode & AST_IMPORT_ALIAS), &tok, + T_SEMICOLON, T_LBRACE, T_EOF); + imports->mode |= AST_IMPORT_WILDCARD; + imports->alias = NULL; + imports->ident = ident; + want(lexer, T_SEMICOLON, &tok); + return; + default: + synassert(!trailing_colon, &tok, T_EQUAL, T_SEMICOLON, T_EOF); + synassert(trailing_colon, &tok, T_NAME, T_LBRACE, T_EOF); + break; + } } }