-
Notifications
You must be signed in to change notification settings - Fork 61
Make parser recognize AliasAssign #441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -188,6 +188,25 @@ class Parser | |
| return attachCommentFromSemicolon(node, startIndex); | ||
| } | ||
|
|
||
| /** | ||
| * Parses an AliasAssign. | ||
| * | ||
| * $(GRAMMAR $(RULEDEF aliasAssign): | ||
| * $(LITERAL Identifier) $(LITERAL '=') $(RULE type) | ||
| */ | ||
| AliasAssign parseAliasAssign() | ||
| { | ||
| mixin(traceEnterAndExit!(__FUNCTION__)); | ||
| auto startIndex = index; | ||
| auto node = allocator.make!AliasAssign; | ||
| node.comment = comment; | ||
| comment = null; | ||
| mixin(tokenCheck!(`node.identifier`, "identifier")); | ||
| mixin(tokenCheck!"="); | ||
| mixin(parseNodeQ!(`node.type`, `Type`)); | ||
| return attachCommentFromSemicolon(node, startIndex); | ||
| } | ||
|
|
||
| /** | ||
| * Parses an AliasInitializer. | ||
| * | ||
|
|
@@ -1809,7 +1828,7 @@ class Parser | |
| * | $(RULE compileCondition) $(LITERAL ':') $(RULE declaration)+ $(LITERAL 'else') $(LITERAL ':') $(RULE declaration)* | ||
| * ;) | ||
| */ | ||
| ConditionalDeclaration parseConditionalDeclaration(bool strict) | ||
| ConditionalDeclaration parseConditionalDeclaration(bool strict, bool inTemplateDeclaration = false) | ||
| { | ||
| mixin(traceEnterAndExit!(__FUNCTION__)); | ||
| auto startIndex = index; | ||
|
|
@@ -1825,7 +1844,7 @@ class Parser | |
| while (moreTokens() && !currentIs(tok!"}") && !currentIs(tok!"else")) | ||
| { | ||
| immutable c = allocator.setCheckpoint(); | ||
| if (!trueDeclarations.put(parseDeclaration(strict, true))) | ||
| if (!trueDeclarations.put(parseDeclaration(strict, true, inTemplateDeclaration))) | ||
| { | ||
| allocator.rollback(c); | ||
| return null; | ||
|
|
@@ -1836,7 +1855,7 @@ class Parser | |
| } | ||
| else | ||
| { | ||
| if (!trueDeclarations.put(parseDeclaration(strict, true))) | ||
| if (!trueDeclarations.put(parseDeclaration(strict, true, inTemplateDeclaration))) | ||
| return null; | ||
| node.trueStyle = DeclarationListStyle.single; | ||
| } | ||
|
|
@@ -1861,14 +1880,14 @@ class Parser | |
| node.falseStyle = brace ? DeclarationListStyle.block : DeclarationListStyle.colon; | ||
| advance(); | ||
| while (moreTokens() && !currentIs(tok!"}")) | ||
| if (!falseDeclarations.put(parseDeclaration(strict, true))) | ||
| if (!falseDeclarations.put(parseDeclaration(strict, true, inTemplateDeclaration))) | ||
| return null; | ||
| if (brace) | ||
| mixin(tokenCheck!"}"); | ||
| } | ||
| else | ||
| { | ||
| if (!falseDeclarations.put(parseDeclaration(strict, true))) | ||
| if (!falseDeclarations.put(parseDeclaration(strict, true, inTemplateDeclaration))) | ||
| return null; | ||
| node.falseStyle = DeclarationListStyle.single; | ||
| } | ||
|
|
@@ -2063,13 +2082,15 @@ class Parser | |
| * Params: | ||
| * strict = if true, do not return partial AST nodes on errors. | ||
| * mustBeDeclaration = do not parse as a declaration if it could be parsed as a function call | ||
| * inTemplateDeclaration = if this function is called from a templated context | ||
| * | ||
| * $(GRAMMAR $(RULEDEF declaration): | ||
| * $(RULE attribute)* $(RULE declaration2) | ||
| * | $(RULE attribute)+ $(LITERAL '{') $(RULE declaration)* $(LITERAL '}') | ||
| * ; | ||
| * $(RULEDEF declaration2): | ||
| * $(RULE aliasDeclaration) | ||
| * | $(RULR aliasAssign) | ||
| * | $(RULE aliasThisDeclaration) | ||
| * | $(RULE anonymousEnumDeclaration) | ||
| * | $(RULE attributeDeclaration) | ||
|
|
@@ -2100,7 +2121,7 @@ class Parser | |
| * | $(RULE versionSpecification) | ||
| * ;) | ||
| */ | ||
| Declaration parseDeclaration(bool strict = false, bool mustBeDeclaration = false) | ||
| Declaration parseDeclaration(bool strict = false, bool mustBeDeclaration = false, bool inTemplateDeclaration = false) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are alias assignments only strictly allowed in templates? Additionally you are missing this parameter in a lot of sub-calls here. Example that would break as far as I can see: // parseConditionalDeclaration
static if (true)
{
A = B;
}There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I see a static if (true) in there at release I'm gonna burn down Adam's shed
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I could tell from the implementation [1], AliasAssign is allowed only inside I understand your point, however, it is not possible to deduce whether the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you want to nest the inTemplateDeclaration parameter into all calls that should keep it, ie. here the parseConditionalDeclaration function and all the other I personally think it would be more pretty doing this with some kind of parse state struct that is passed as argument in all related functions though if this is expected to expand in the future to more edge cases.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this will work. Consider this case: template X(T)
{
alias X = int;
static if (cond)
X = float; // this one is currently accepted by dmd
void fun()
{
X = T; // while this one is not because the assignment
// does not have the same parent as the declaration of X
}
}This is not going to get solved by passing the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the parseFunctionDeclaration body would reset back the boolean value that you are in a template, (implicitly by simply not passing it down as parameter or for a struct explicitly) you will want to do that with anything adding scope.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, I'll try that out. Thanks for your assistance! |
||
| { | ||
| mixin(traceEnterAndExit!(__FUNCTION__)); | ||
| auto startIndex = index; | ||
|
|
@@ -2200,7 +2221,7 @@ class Parser | |
| while (moreTokens() && !currentIs(tok!"}")) | ||
| { | ||
| auto c = allocator.setCheckpoint(); | ||
| if (!declarations.put(parseDeclaration(strict))) | ||
| if (!declarations.put(parseDeclaration(strict, false, inTemplateDeclaration))) | ||
| { | ||
| allocator.rollback(c); | ||
| return null; | ||
|
|
@@ -2335,11 +2356,11 @@ class Parser | |
| else if (peekIs(tok!"~")) | ||
| mixin(parseNodeQ!(`node.staticDestructor`, `StaticDestructor`)); | ||
| else if (peekIs(tok!"if")) | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict)`); | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); | ||
| else if (peekIs(tok!"assert")) | ||
| mixin(parseNodeQ!(`node.staticAssertDeclaration`, `StaticAssertDeclaration`)); | ||
| else if (peekIs(tok!"foreach") || peekIs(tok!"foreach_reverse")) | ||
| mixin(parseNodeQ!(`node.staticForeachDeclaration`, `StaticForeachDeclaration`)); | ||
| mixin(nullCheck!(`node.staticForeachDeclaration = parseStaticForeachDeclaration(inTemplateDeclaration)`)); | ||
| else | ||
| goto type; | ||
| break; | ||
|
|
@@ -2359,6 +2380,13 @@ class Parser | |
| mixin(parseNodeQ!(`node.unittest_`, `Unittest`)); | ||
| break; | ||
| case tok!"identifier": | ||
| if (inTemplateDeclaration && peekIs(tok!"=")) | ||
| { | ||
| mixin(parseNodeQ!(`node.aliasAssign`, `AliasAssign`)); | ||
| break; | ||
| } | ||
| else | ||
| goto type; | ||
| case tok!".": | ||
| case tok!"const": | ||
| case tok!"immutable": | ||
|
|
@@ -2395,7 +2423,7 @@ class Parser | |
| break; | ||
| case tok!"version": | ||
| if (peekIs(tok!"(")) | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict)`); | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); | ||
| else if (peekIs(tok!"=")) | ||
| mixin(parseNodeQ!(`node.versionSpecification`, `VersionSpecification`)); | ||
| else | ||
|
|
@@ -2408,7 +2436,7 @@ class Parser | |
| if (peekIs(tok!"=")) | ||
| mixin(parseNodeQ!(`node.debugSpecification`, `DebugSpecification`)); | ||
| else | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict)`); | ||
| mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); | ||
| break; | ||
| default: | ||
| error("Declaration expected"); | ||
|
|
@@ -3139,12 +3167,12 @@ class Parser | |
| * | $(LITERAL 'static') ($(LITERAL 'foreach') | $(LITERAL 'foreach_reverse')) $(LITERAL '$(LPAREN)') $(RULE foreachType) $(LITERAL ';') $(RULE expression) $(LITERAL '..') $(RULE expression) $(LITERAL '$(RPAREN)') ($(RULE declaration) | $(LITERAL '{') $(RULE declaration)* $(LITERAL '}')) | ||
| * ;) | ||
| */ | ||
| StaticForeachDeclaration parseStaticForeachDeclaration() | ||
| StaticForeachDeclaration parseStaticForeachDeclaration(bool inTemplateDeclaration = false) | ||
| { | ||
| mixin(traceEnterAndExit!(__FUNCTION__)); | ||
| auto startIndex = index; | ||
| mixin(tokenCheck!"static"); | ||
| auto decl = parseForeach!true(); | ||
| auto decl = parseForeach!true(inTemplateDeclaration); | ||
| if (decl) decl.tokens = tokens[startIndex .. index]; | ||
| return decl; | ||
| } | ||
|
|
@@ -3177,7 +3205,7 @@ class Parser | |
| return parseForeach!false(); | ||
| } | ||
|
|
||
| Foreach!declOnly parseForeach(bool declOnly = false)() | ||
| Foreach!declOnly parseForeach(bool declOnly = false)(bool inTemplateDeclaration = false) | ||
| { | ||
| mixin(traceEnterAndExit!(__FUNCTION__)); | ||
| auto startIndex = index; | ||
|
|
@@ -3233,7 +3261,7 @@ class Parser | |
| { | ||
| immutable b = setBookmark(); | ||
| immutable c = allocator.setCheckpoint(); | ||
| if (declarations.put(parseDeclaration(true, true))) | ||
| if (declarations.put(parseDeclaration(true, true, inTemplateDeclaration))) | ||
| abandonBookmark(b); | ||
| else | ||
| { | ||
|
|
@@ -3244,7 +3272,7 @@ class Parser | |
| } | ||
| mixin(tokenCheck!"}"); | ||
| } | ||
| else if (!declarations.put(parseDeclaration(true, true))) | ||
| else if (!declarations.put(parseDeclaration(true, true, inTemplateDeclaration))) | ||
| return null; | ||
| ownArray(node.declarations, declarations); | ||
| } | ||
|
|
@@ -6684,7 +6712,7 @@ class Parser | |
| while (moreTokens() && !currentIs(tok!"}")) | ||
| { | ||
| immutable c = allocator.setCheckpoint(); | ||
| if (!declarations.put(parseDeclaration(true, true))) | ||
| if (!declarations.put(parseDeclaration(true, true, true))) | ||
WebFreak001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| allocator.rollback(c); | ||
| } | ||
| ownArray(node.declarations, declarations); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| template T(X) | ||
| { | ||
| alias A = int; | ||
WebFreak001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| A = X; | ||
| struct B | ||
| { | ||
| A t; | ||
| } | ||
| } | ||
|
|
||
| void fun() | ||
| { | ||
| auto b = T!float.B(); | ||
| } | ||
WebFreak001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // https://github.com/dlang/phobos/pull/8033 | ||
| template EraseAll(args...) | ||
| if (args.length >= 1) | ||
| { | ||
| alias EraseAll = AliasSeq!(); | ||
| static foreach (arg; args[1 .. $]) | ||
| static if (!isSame!(args[0], arg)) | ||
| EraseAll = AliasSeq!(EraseAll, arg); | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8034 | ||
| template NoDuplicates(args...) | ||
| { | ||
| alias NoDuplicates = AliasSeq!(); | ||
| static foreach (arg; args) | ||
| NoDuplicates = AppendUnique!(NoDuplicates, arg); | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8036 | ||
| template ReplaceAll(args...) | ||
| { | ||
| alias ReplaceAll = AliasSeq!(); | ||
| static foreach (arg; args[2 .. $]) | ||
| { | ||
| static if (isSame!(args[0], arg)) | ||
| ReplaceAll = AliasSeq!(ReplaceAll, args[1]); | ||
| else | ||
| ReplaceAll = AliasSeq!(ReplaceAll, arg); | ||
| } | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8037 | ||
| template Reverse(args...) | ||
| { | ||
| alias Reverse = AliasSeq!(); | ||
| static foreach_reverse (arg; args) | ||
| Reverse = AliasSeq!(Reverse, arg); | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8038 | ||
| template MostDerived(T, TList...) | ||
| { | ||
| import std.traits : Select; | ||
| alias MostDerived = T; | ||
| static foreach (U; TList) | ||
| MostDerived = Select!(is(U : MostDerived), U, MostDerived); | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8044 | ||
| template Repeat(size_t n, items...) | ||
| { | ||
| static if (n == 0) | ||
| { | ||
| alias Repeat = AliasSeq!(); | ||
| } | ||
| else | ||
| { | ||
| alias Repeat = items; | ||
| enum log2n = | ||
| { | ||
| uint result = 0; | ||
| auto x = n; | ||
| while (x >>= 1) | ||
| ++result; | ||
| return result; | ||
| }(); | ||
| static foreach (i; 0 .. log2n) | ||
| { | ||
| Repeat = AliasSeq!(Repeat, Repeat); | ||
| } | ||
| Repeat = AliasSeq!(Repeat, Repeat!(n - (1u << log2n), items)); | ||
| } | ||
| } | ||
|
|
||
| // https://github.com/dlang/phobos/pull/8047 | ||
| template Stride(int stepSize, Args...) | ||
| if (stepSize != 0) | ||
| { | ||
| alias Stride = AliasSeq!(); | ||
| static if (stepSize > 0) | ||
| { | ||
| static foreach (i; 0 .. (Args.length + stepSize - 1) / stepSize) | ||
| Stride = AliasSeq!(Stride, Args[i * stepSize]); | ||
| } | ||
| else | ||
| { | ||
| static foreach (i; 0 .. (Args.length - stepSize - 1) / -stepSize) | ||
| Stride = AliasSeq!(Stride, Args[$ - 1 + i * stepSize]); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.