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:
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;
+ }
}
}