summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-parser.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2020-08-20 08:23:51 -0700
committerGitHub <noreply@github.com>2020-08-20 08:23:51 -0700
commit11748a75e66c2bd3fa7ef7635fd35363465f599c (patch)
treec1920f54ac59dcd79806b475df3e4c1ba85756ba /source/slang/slang-parser.cpp
parentb5a4161a801a573179b1f552e5c53748d2667b03 (diff)
Initial support for a using construct (#1506)
The basic idea is that if you have a namespace: namespace MyCoolNamespace { void f() { ... } ... } then you can bring the declarations from that namespace into scope with: using MyCoolNamespace; f(); The `using` construct is allowed in any scope where declarations are allowed. As an additional feature, the construct allows and then ignores the keyword `namespace` if it occurs right after `using`: using namespace MyCoolNamespace; Note that unlike in C++, `using` a namespace inside another namespace doesn't implicitly make the symbols available to clients of that namespace: namespace hidden { void secret() {...} ... } namespace api { using hidden; ... } api.secret(); // ERROR: `secret()` isn't a member of `api` The implementation of this feature was relatively simple, although it does leave out more advanced features that might be desirable in the future: * No support for `using MCN = MyCoolNamespace` sorts of tricks to define a short name * No support for `using` anything that isn't a namespace (e.g., to make the members of a type available without qualification) * No support for cases where multiple visible modules have a namespace of the same name (or dealing with overloaded namespaces in general)
Diffstat (limited to 'source/slang/slang-parser.cpp')
-rw-r--r--source/slang/slang-parser.cpp50
1 files changed, 44 insertions, 6 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index f2bc2eb9a..e02ccf245 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -933,12 +933,16 @@ namespace Slang
return parser->getNamePool()->getName(text);
}
+ static bool expect(Parser* parser, TokenType tokenType)
+ {
+ return parser->ReadToken(tokenType).type == tokenType;
+ }
+
static NameLoc expectIdentifier(Parser* parser)
{
return NameLoc(parser->ReadToken(TokenType::Identifier));
}
-
static NodeBase* parseImportDecl(
Parser* parser, void* /*userData*/)
{
@@ -2629,6 +2633,44 @@ namespace Slang
return result;
}
+ static NodeBase* parseUsingDecl(Parser* parser, void* /*userData*/)
+ {
+ UsingDecl* decl = parser->astBuilder->create<UsingDecl>();
+ parser->FillPosition(decl);
+
+ // A `using` declaration will need to know about the current
+ // scope at the point where it appears, so that it can know
+ // the scope it is attempting to extend.
+ //
+ decl->scope = parser->currentScope;
+
+ // TODO: We may eventually want to support declarations
+ // of the form `using <id> = <expr>;` which introduce
+ // a shorthand alias for a namespace/type/whatever.
+ //
+ // For now we are just sticking to the most basic form.
+
+ // As a compatibility feature for programmers used to C++,
+ // we allow the `namespace` keyword to come after `using`,
+ // where it has no effect.
+ //
+ if(parser->LookAheadToken("namespace"))
+ {
+ advanceToken(parser);
+ }
+
+ // The entity that is going to be used is identified
+ // using an arbitrary expression (although we expect
+ // that valid code will not typically use the full
+ // freedom of what the expression grammar supports.
+ //
+ decl->arg = parser->ParseExpression();
+
+ expect(parser, TokenType::Semicolon);
+
+ return decl;
+ }
+
static NodeBase* parseConstructorDecl(Parser* parser, void* /*userData*/)
{
ConstructorDecl* decl = parser->astBuilder->create<ConstructorDecl>();
@@ -2750,11 +2792,6 @@ namespace Slang
return decl;
}
- static bool expect(Parser* parser, TokenType tokenType)
- {
- return parser->ReadToken(tokenType).type == tokenType;
- }
-
/// Peek in the token stream and return `true` if it looks like a modern-style variable declaration is coming up.
static bool _peekModernStyleVarDecl(Parser* parser)
{
@@ -5659,6 +5696,7 @@ namespace Slang
DECL(typealias, parseTypeAliasDecl);
DECL(__generic_value_param, parseGlobalGenericValueParamDecl);
DECL(namespace, parseNamespaceDecl);
+ DECL(using, parseUsingDecl);
#undef DECL