diff --git a/src/dparse/ast.d b/src/dparse/ast.d index 90967c17..8f5a210a 100644 --- a/src/dparse/ast.d +++ b/src/dparse/ast.d @@ -22,6 +22,7 @@ import std.array; import std.string; private immutable uint[TypeInfo] typeMap; +private immutable uint[TypeInfo] unaryExpressionTypeMap; shared static this() { @@ -71,8 +72,47 @@ shared static this() typeMap[typeid(TraitsExpression)] = 44; typeMap[typeid(TypeidExpression)] = 45; typeMap[typeid(TypeofExpression)] = 46; - typeMap[typeid(UnaryExpression)] = 47; + typeMap[typeid(UnaryExpressionNode)] = 47; typeMap[typeid(XorExpression)] = 48; + typeMap[typeid(RefPrefixUnaryExpression)] = 49; + typeMap[typeid(NotPrefixUnaryExpression)] = 50; + typeMap[typeid(DerefPrefixUnaryExpression)] = 51; + typeMap[typeid(PlusPrefixUnaryExpression)] = 52; + typeMap[typeid(MinusPrefixUnaryExpression)] = 53; + typeMap[typeid(TildePrefixUnaryExpression)] = 54; + typeMap[typeid(PlusPlusPrefixUnaryExpression)] = 55; + typeMap[typeid(MinusMinusPrefixUnaryExpression)] = 56; + typeMap[typeid(PlusPlusPostfixUnaryExpression)] = 57; + typeMap[typeid(MinusMinusPostfixUnaryExpression)] = 58; + typeMap[typeid(UnaryDotIdentifierExpression)] = 59; + typeMap[typeid(UnaryDotNewExpression)] = 60; + typeMap[typeid(TypeDotIdentifierExpression)] = 61; + typeMap[typeid(CastExpression)] = 62; + typeMap[typeid(ThrowExpression)] = 63; + typeMap[typeid(DummyUnaryExpression)] = 64; + + unaryExpressionTypeMap[typeid(RefPrefixUnaryExpression)] = 1; + unaryExpressionTypeMap[typeid(NotPrefixUnaryExpression)] = 2; + unaryExpressionTypeMap[typeid(DerefPrefixUnaryExpression)] = 3; + unaryExpressionTypeMap[typeid(PlusPrefixUnaryExpression)] = 4; + unaryExpressionTypeMap[typeid(MinusPrefixUnaryExpression)] = 5; + unaryExpressionTypeMap[typeid(TildePrefixUnaryExpression)] = 6; + unaryExpressionTypeMap[typeid(PlusPlusPrefixUnaryExpression)] = 7; + unaryExpressionTypeMap[typeid(MinusMinusPrefixUnaryExpression)] = 8; + unaryExpressionTypeMap[typeid(PlusPlusPostfixUnaryExpression)] = 9; + unaryExpressionTypeMap[typeid(MinusMinusPostfixUnaryExpression)] = 10; + unaryExpressionTypeMap[typeid(UnaryDotIdentifierExpression)] = 12; + unaryExpressionTypeMap[typeid(UnaryDotNewExpression)] = 13; + unaryExpressionTypeMap[typeid(TypeDotIdentifierExpression)] = 14; + unaryExpressionTypeMap[typeid(AssertExpression)] = 15; + unaryExpressionTypeMap[typeid(CastExpression)] = 16; + unaryExpressionTypeMap[typeid(DeleteExpression)] = 17; + unaryExpressionTypeMap[typeid(FunctionCallExpression)] = 18; + unaryExpressionTypeMap[typeid(IndexExpression)] = 19; + unaryExpressionTypeMap[typeid(NewExpression)] = 20; + unaryExpressionTypeMap[typeid(PrimaryExpression)] = 21; + unaryExpressionTypeMap[typeid(ThrowExpression)] = 22; + unaryExpressionTypeMap[typeid(DummyUnaryExpression)] = 23; } /// Describes which syntax was used in a list of declarations in the containing AST node @@ -165,12 +205,66 @@ abstract class ASTVisitor case 44: visit(cast(TraitsExpression) n); break; case 45: visit(cast(TypeidExpression) n); break; case 46: visit(cast(TypeofExpression) n); break; - case 47: visit(cast(UnaryExpression) n); break; + case 47: dynamicDispatch(cast(UnaryExpressionNode) n); break; case 48: visit(cast(XorExpression) n); break; - default: assert(false, __MODULE__ ~ " has a bug"); + case 49: visit(cast(RefPrefixUnaryExpression) n); break; + case 50: visit(cast(NotPrefixUnaryExpression) n); break; + case 51: visit(cast(DerefPrefixUnaryExpression) n); break; + case 52: visit(cast(PlusPrefixUnaryExpression) n); break; + case 53: visit(cast(MinusPrefixUnaryExpression) n); break; + case 54: visit(cast(TildePrefixUnaryExpression) n); break; + case 55: visit(cast(PlusPlusPrefixUnaryExpression) n); break; + case 56: visit(cast(MinusMinusPrefixUnaryExpression) n); break; + case 57: visit(cast(PlusPlusPostfixUnaryExpression) n); break; + case 58: visit(cast(MinusMinusPostfixUnaryExpression) n); break; + case 59: visit(cast(UnaryDotIdentifierExpression) n); break; + case 60: visit(cast(UnaryDotNewExpression) n); break; + case 61: visit(cast(TypeDotIdentifierExpression) n); break; + case 62: visit(cast(CastExpression) n); break; + case 63: visit(cast(ThrowExpression) n); break; + case 64: visit(cast(DummyUnaryExpression) n); break; + default: assert(false, __MODULE__ ~ " has a bug: " ~ typeid(n).toString); } } + /// ditto + void dynamicDispatch(const UnaryExpressionNode n) + { + switch (unaryExpressionTypeMap.get(typeid(n), 0)) + { + case 1: visit(cast(RefPrefixUnaryExpression) n); break; + case 2: visit(cast(NotPrefixUnaryExpression) n); break; + case 3: visit(cast(DerefPrefixUnaryExpression) n); break; + case 4: visit(cast(PlusPrefixUnaryExpression) n); break; + case 5: visit(cast(MinusPrefixUnaryExpression) n); break; + case 6: visit(cast(TildePrefixUnaryExpression) n); break; + case 7: visit(cast(PlusPlusPrefixUnaryExpression) n); break; + case 8: visit(cast(MinusMinusPrefixUnaryExpression) n); break; + case 9: visit(cast(PlusPlusPostfixUnaryExpression) n); break; + case 10: visit(cast(MinusMinusPostfixUnaryExpression) n); break; + case 12: visit(cast(UnaryDotIdentifierExpression) n); break; + case 13: visit(cast(UnaryDotNewExpression) n); break; + case 14: visit(cast(TypeDotIdentifierExpression) n); break; + case 15: visit(cast(AssertExpression) n); break; + case 16: visit(cast(CastExpression) n); break; + case 17: visit(cast(DeleteExpression) n); break; + case 18: visit(cast(FunctionCallExpression) n); break; + case 19: visit(cast(IndexExpression) n); break; + case 20: visit(cast(NewExpression) n); break; + case 21: visit(cast(PrimaryExpression) n); break; + case 22: visit(cast(ThrowExpression) n); break; + case 23: visit(cast(DummyUnaryExpression) n); break; + default: assert(false, __MODULE__ ~ " has a bug: " ~ typeid(n).toString); + } + } + + /// ditto + void dynamicDispatch(const TokenUnaryExpression n) + { + // unary expression handles all cases + dynamicDispatch(cast(UnaryExpressionNode) n); + } + /** */ void visit(const AddExpression addExpression) { addExpression.accept(this); } /** */ void visit(const AliasDeclaration aliasDeclaration) { aliasDeclaration.accept(this); } /** */ void visit(const AliasAssign aliasAssign) { aliasAssign.accept(this); } @@ -383,7 +477,20 @@ abstract class ASTVisitor /** */ void visit(const TypeSuffix typeSuffix) { typeSuffix.accept(this); } /** */ void visit(const TypeidExpression typeidExpression) { typeidExpression.accept(this); } /** */ void visit(const TypeofExpression typeofExpression) { typeofExpression.accept(this); } - /** */ void visit(const UnaryExpression unaryExpression) { unaryExpression.accept(this); } + /** */ void visit(const RefPrefixUnaryExpression refPrefixUnaryExpression) { refPrefixUnaryExpression.accept(this); } + /** */ void visit(const NotPrefixUnaryExpression notPrefixUnaryExpression) { notPrefixUnaryExpression.accept(this); } + /** */ void visit(const DerefPrefixUnaryExpression derefPrefixUnaryExpression) { derefPrefixUnaryExpression.accept(this); } + /** */ void visit(const PlusPrefixUnaryExpression plusPrefixUnaryExpression) { plusPrefixUnaryExpression.accept(this); } + /** */ void visit(const MinusPrefixUnaryExpression minusPrefixUnaryExpression) { minusPrefixUnaryExpression.accept(this); } + /** */ void visit(const TildePrefixUnaryExpression tildePrefixUnaryExpression) { tildePrefixUnaryExpression.accept(this); } + /** */ void visit(const PlusPlusPrefixUnaryExpression plusPlusPrefixUnaryExpression) { plusPlusPrefixUnaryExpression.accept(this); } + /** */ void visit(const MinusMinusPrefixUnaryExpression minusMinusPrefixUnaryExpression) { minusMinusPrefixUnaryExpression.accept(this); } + /** */ void visit(const PlusPlusPostfixUnaryExpression plusPlusPostfixUnaryExpression) { plusPlusPostfixUnaryExpression.accept(this); } + /** */ void visit(const MinusMinusPostfixUnaryExpression minusMinusPostfixUnaryExpression) { minusMinusPostfixUnaryExpression.accept(this); } + /** */ void visit(const UnaryDotIdentifierExpression unaryDotIdentifierExpression) { unaryDotIdentifierExpression.accept(this); } + /** */ void visit(const UnaryDotNewExpression unaryDotNewExpression) { unaryDotNewExpression.accept(this); } + /** */ void visit(const TypeDotIdentifierExpression typeDotIdentifierExpression) { typeDotIdentifierExpression.accept(this); } + /** */ void visit(const DummyUnaryExpression dummyUnaryExpression) { dummyUnaryExpression.accept(this); } /** */ void visit(const UnionDeclaration unionDeclaration) { unionDeclaration.accept(this); } /** */ void visit(const Unittest unittest_) { unittest_.accept(this); } /** */ void visit(const VariableDeclaration variableDeclaration) { variableDeclaration.accept(this); } @@ -955,7 +1062,7 @@ final class AssertArguments : BaseNode } /// -final class AssertExpression : ExpressionNode +final class AssertExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { @@ -1186,7 +1293,7 @@ final class CaseStatement: BaseNode } /// -final class CastExpression: BaseNode +final class CastExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { @@ -1194,7 +1301,7 @@ final class CastExpression: BaseNode } /** */ Type type; /** */ CastQualifier castQualifier; - /** */ UnaryExpression unaryExpression; + /** */ UnaryExpressionNode unaryExpression; mixin OpEquals; } @@ -1549,13 +1656,13 @@ final class DefaultStatement : BaseNode } /// -final class DeleteExpression : ExpressionNode +final class DeleteExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { mixin (visitIfNotNull!(unaryExpression)); } - /** */ UnaryExpression unaryExpression; + /** */ UnaryExpressionNode unaryExpression; /** */ size_t line; /** */ size_t column; mixin OpEquals; @@ -1864,14 +1971,14 @@ final class FunctionBody : BaseNode } /// -final class FunctionCallExpression : ExpressionNode +final class FunctionCallExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { mixin (visitIfNotNull!(type, unaryExpression, templateArguments, arguments)); } /** */ Type type; - /** */ UnaryExpression unaryExpression; + /** */ UnaryExpressionNode unaryExpression; /** */ TemplateArguments templateArguments; /** */ Arguments arguments; mixin OpEquals; @@ -2140,7 +2247,7 @@ final class IfCondition : BaseNode /** In an assignment-condition, this is the part after the equals sign. Otherwise this is any other expression that is evaluated to be a boolean. - (e.g. UnaryExpression, AndAndExpression, CmpExpression, etc.) + (e.g. UnaryExpressionNode, AndAndExpression, CmpExpression, etc.) */ Expression expression; mixin OpEquals; @@ -2208,13 +2315,13 @@ final class Index : BaseNode } /// -final class IndexExpression : ExpressionNode +final class IndexExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { mixin (visitIfNotNull!(unaryExpression, indexes)); } - /** */ UnaryExpression unaryExpression; + /** */ UnaryExpressionNode unaryExpression; /** */ Index[] indexes; mixin OpEquals; } @@ -2533,7 +2640,7 @@ final class NamespaceList : BaseNode mixin (visitIfNotNull!(items)); } mixin OpEquals; - /** */ TernaryExpression[] items; + /** */ ExpressionNode[] items; } /// @@ -2552,7 +2659,7 @@ final class NewAnonClassExpression : ExpressionNode } /// -final class NewExpression : ExpressionNode +final class NewExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { @@ -2790,7 +2897,7 @@ final class PragmaStatement : BaseNode } /// -final class PrimaryExpression : ExpressionNode +final class PrimaryExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { @@ -3427,7 +3534,7 @@ deprecated("Replaced by ExpressionStatement + ThrowExpression") alias ThrowStatement = ThrowExpression; /// -final class ThrowExpression: ExpressionNode +final class ThrowExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { @@ -3555,31 +3662,194 @@ final class TypeofExpression : ExpressionNode } /// -final class UnaryExpression : ExpressionNode +abstract class UnaryExpressionNode : ExpressionNode +{ +} + +/// +final class DummyUnaryExpression : UnaryExpressionNode { override void accept(ASTVisitor visitor) const { - // TODO prefix, postfix, unary - mixin (visitIfNotNull!(primaryExpression, newExpression, deleteExpression, - castExpression, functionCallExpression, unaryExpression, - type, identifierOrTemplateInstance, assertExpression, throwExpression, - indexExpression)); } - /** */ Type type; - /** */ PrimaryExpression primaryExpression; - /** */ Token prefix; - /** */ Token suffix; - /** */ UnaryExpression unaryExpression; - /** */ NewExpression newExpression; - /** */ DeleteExpression deleteExpression; - /** */ CastExpression castExpression; - /** */ FunctionCallExpression functionCallExpression; - /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance; - /** */ AssertExpression assertExpression; - /** */ ThrowExpression throwExpression; - /** */ IndexExpression indexExpression; - /** */ size_t dotLocation; + // empty, only used as compatibility for now, may be removed in the future. +} + +/// +abstract class TokenUnaryExpression : UnaryExpressionNode +{ + override void accept(ASTVisitor visitor) const + { + mixin (visitIfNotNull!(unaryExpression)); + } + + /// Returns the operator token (including source index) before the unary + /// expression or Token.init if constructed manually. Use `tokenType` to + /// always get a valid `IdType`. + final Token token() const @property @safe nothrow pure @nogc + { + return tokens[0]; + } + + abstract IdType tokenType() const @property @safe nothrow pure @nogc; + + /// The unary expression that is affected + UnaryExpressionNode unaryExpression; +} + +/// `&unaryExpression` +final class RefPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"&"; + } + + mixin OpEquals; +} + +/// `!unaryExpression` +final class NotPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"!"; + } + + mixin OpEquals; +} + +/// `*unaryExpression` +final class DerefPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"*"; + } + + mixin OpEquals; +} + +/// `+unaryExpression` +final class PlusPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"+"; + } + + mixin OpEquals; +} + +/// `-unaryExpression` +final class MinusPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"-"; + } + + mixin OpEquals; +} + +/// `~unaryExpression` +final class TildePrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"~"; + } + + mixin OpEquals; +} + +/// `++unaryExpression` +final class PlusPlusPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"++"; + } + + mixin OpEquals; +} + +/// `--unaryExpression` +final class MinusMinusPrefixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"--"; + } + + mixin OpEquals; +} + +/// `unaryExpression++` +final class PlusPlusPostfixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"++"; + } + + mixin OpEquals; +} + +/// `unaryExpression--` +final class MinusMinusPostfixUnaryExpression : TokenUnaryExpression +{ + override IdType tokenType() const @property @safe nothrow pure @nogc + { + return tok!"--"; + } + + mixin OpEquals; +} + +/// `unaryExpression.identifierOrTemplateInstance` +final class UnaryDotIdentifierExpression : UnaryExpressionNode +{ + override void accept(ASTVisitor visitor) const + { + mixin (visitIfNotNull!(unaryExpression, identifierOrTemplateInstance)); + } + + /** lhs */ UnaryExpressionNode unaryExpression; + /** dot */ size_t dotLocation; + /** rhs */ IdentifierOrTemplateInstance identifierOrTemplateInstance; + + mixin OpEquals; +} + +/// `unaryExpression.new(...)` +final class UnaryDotNewExpression : UnaryExpressionNode +{ + override void accept(ASTVisitor visitor) const + { + mixin (visitIfNotNull!(unaryExpression, newExpression)); + } + + /** lhs */ UnaryExpressionNode unaryExpression; + /** dot */ size_t dotLocation; + /** rhs */ NewExpression newExpression; + + mixin OpEquals; +} + +/// `(Type).identifier` +final class TypeDotIdentifierExpression : UnaryExpressionNode +{ + override void accept(ASTVisitor visitor) const + { + mixin (visitIfNotNull!(type, identifierOrTemplateInstance)); + } + + /** lhs */ Type type; + /** dot */ size_t dotLocation; + /** rhs */ IdentifierOrTemplateInstance identifierOrTemplateInstance; + mixin OpEquals; } @@ -3978,8 +4248,8 @@ unittest // issue #398: Support extern(C++, ) assert(!namespaces); foreach (const entry; list.items) { - const prim = cast(PrimaryExpression) entry.expression; - assert(prim); + const prim = cast(PrimaryExpression) entry; + assert(prim, (entry ? typeid(entry).toString : "null") ~ " is not PrimaryExpression!"); namespaces ~= prim; } } @@ -4120,9 +4390,9 @@ unittest // Support GCC-sytle asm statements assert(constraint.type == tok!"stringLiteral"); assert(constraint.text == `"=r"`); - auto una = cast(UnaryExpression) expression; - assert(una); - assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var1"); + auto primary = cast(PrimaryExpression) expression; + assert(primary); + assert(primary.identifierOrTemplateInstance.identifier.text == "var1"); } } } @@ -4145,9 +4415,9 @@ unittest // Support GCC-sytle asm statements assert(constraint.type == tok!"stringLiteral"); assert(constraint.text == `"=w"`); - auto una = cast(UnaryExpression) expression; - assert(una); - assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var2"); + auto primary = cast(PrimaryExpression) expression; + assert(primary); + assert(primary.identifierOrTemplateInstance.identifier.text == "var2"); } with (inputOperands.items[1]) @@ -4155,9 +4425,9 @@ unittest // Support GCC-sytle asm statements assert(constraint.type == tok!"stringLiteral"); assert(constraint.text == `"g"`); - auto una = cast(UnaryExpression) expression; - assert(una); - assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var3"); + auto primary = cast(PrimaryExpression) expression; + assert(primary); + assert(primary.identifierOrTemplateInstance.identifier.text == "var3"); } } } diff --git a/src/dparse/astprinter.d b/src/dparse/astprinter.d index ba17f6d6..f9e1a783 100644 --- a/src/dparse/astprinter.d +++ b/src/dparse/astprinter.d @@ -986,28 +986,6 @@ class XMLPrinter : ASTVisitor } } - override void visit(const UnaryExpression unaryExpression) - { - output.writeln(""); - if (unaryExpression.prefix != tok!"") - { - output.writeln("", xmlEscape(str(unaryExpression.prefix.type)), ""); - unaryExpression.unaryExpression.accept(this); - } - else - { - if (unaryExpression.suffix != tok!"") - { - assert(unaryExpression.suffix.text == ""); - unaryExpression.unaryExpression.accept(this); - output.writeln("", str(unaryExpression.suffix.type), ""); - } - else - unaryExpression.accept(this); - } - output.writeln(""); - } - override void visit(const UnionDeclaration unionDeclaration) { output.writeln(""); @@ -1208,6 +1186,20 @@ class XMLPrinter : ASTVisitor override void visit(const WhileStatement whileStatement) { mixin (tagAndAccept!"whileStatement"); } override void visit(const WithStatement withStatement) { mixin (tagAndAccept!"withStatement"); } override void visit(const TypeidExpression typeidExpression) { mixin (tagAndAccept!"typeidExpression"); } + // unary expressions + override void visit(const RefPrefixUnaryExpression refPrefixUnaryExpression) { mixin (tagAndAccept!"refPrefixUnaryExpression"); } + override void visit(const NotPrefixUnaryExpression notPrefixUnaryExpression) { mixin (tagAndAccept!"notPrefixUnaryExpression"); } + override void visit(const DerefPrefixUnaryExpression derefPrefixUnaryExpression) { mixin (tagAndAccept!"derefPrefixUnaryExpression"); } + override void visit(const PlusPrefixUnaryExpression plusPrefixUnaryExpression) { mixin (tagAndAccept!"plusPrefixUnaryExpression"); } + override void visit(const MinusPrefixUnaryExpression minusPrefixUnaryExpression) { mixin (tagAndAccept!"minusPrefixUnaryExpression"); } + override void visit(const TildePrefixUnaryExpression tildePrefixUnaryExpression) { mixin (tagAndAccept!"tildePrefixUnaryExpression"); } + override void visit(const PlusPlusPrefixUnaryExpression plusPlusPrefixUnaryExpression) { mixin (tagAndAccept!"plusPlusPrefixUnaryExpression"); } + override void visit(const MinusMinusPrefixUnaryExpression minusMinusPrefixUnaryExpression) { mixin (tagAndAccept!"minusMinusPrefixUnaryExpression"); } + override void visit(const PlusPlusPostfixUnaryExpression plusPlusPostfixUnaryExpression) { mixin (tagAndAccept!"plusPlusPostfixUnaryExpression"); } + override void visit(const MinusMinusPostfixUnaryExpression minusMinusPostfixUnaryExpression) { mixin (tagAndAccept!"minusMinusPostfixUnaryExpression"); } + override void visit(const UnaryDotIdentifierExpression unaryDotIdentifierExpression) { mixin (tagAndAccept!"unaryDotIdentifierExpression"); } + override void visit(const UnaryDotNewExpression unaryDotNewExpression) { mixin (tagAndAccept!"unaryDotNewExpression"); } + override void visit(const TypeDotIdentifierExpression typeDotIdentifierExpression) { mixin (tagAndAccept!"typeDotIdentifierExpression"); } // dfmt on alias visit = ASTVisitor.visit; diff --git a/src/dparse/formatter.d b/src/dparse/formatter.d index a51e3eeb..4ce8dd9b 100644 --- a/src/dparse/formatter.d +++ b/src/dparse/formatter.d @@ -689,7 +689,7 @@ class Formatter(Sink) /** Type type; CastQualifier castQualifier; - UnaryExpression unaryExpression; + UnaryExpressionNode unaryExpression; **/ with(castExpression) @@ -1335,7 +1335,7 @@ class Formatter(Sink) else if (cast(TraitsExpression) n) format(cast(TraitsExpression) n); else if (cast(TypeidExpression) n) format(cast(TypeidExpression) n); else if (cast(TypeofExpression) n) format(cast(TypeofExpression) n); - else if (cast(UnaryExpression) n) format(cast(UnaryExpression) n); + else if (cast(UnaryExpressionNode) n) format(cast(UnaryExpressionNode) n); else if (cast(XorExpression) n) format(cast(XorExpression) n); } @@ -1507,7 +1507,7 @@ class Formatter(Sink) /** Type type; - UnaryExpression unaryExpression; + UnaryExpressionNode unaryExpression; TemplateArguments templateArguments; Arguments arguments; **/ @@ -1891,7 +1891,7 @@ class Formatter(Sink) debug(verbose) writeln("IndexExpression"); /** - UnaryExpression unaryExpression; + UnaryExpressionNode unaryExpression; ArgumentList argumentList; **/ @@ -3611,59 +3611,115 @@ class Formatter(Sink) put(")"); } - void format(const UnaryExpression unary) + void format(const UnaryExpressionNode unary) + { + debug(verbose) writeln("UnaryExpressionNode("); + + if (auto p = cast(RefPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(NotPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(DerefPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(PlusPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(MinusPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(TildePrefixUnaryExpression) unary) format(p); + else if (auto p = cast(PlusPlusPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(MinusMinusPrefixUnaryExpression) unary) format(p); + else if (auto p = cast(PlusPlusPostfixUnaryExpression) unary) format(p); + else if (auto p = cast(MinusMinusPostfixUnaryExpression) unary) format(p); + else if (auto p = cast(UnaryDotIdentifierExpression) unary) format(p); + else if (auto p = cast(UnaryDotNewExpression) unary) format(p); + else if (auto p = cast(TypeDotIdentifierExpression) unary) format(p); + else if (auto p = cast(AssertExpression) unary) format(p); + else if (auto p = cast(CastExpression) unary) format(p); + else if (auto p = cast(DeleteExpression) unary) format(p); + else if (auto p = cast(FunctionCallExpression) unary) format(p); + else if (auto p = cast(IndexExpression) unary) format(p); + else if (auto p = cast(NewExpression) unary) format(p); + else if (auto p = cast(PrimaryExpression) unary) format(p); + else if (auto p = cast(ThrowExpression) unary) format(p); + + debug(verbose) writeln(")"); + } + + void format(const RefPrefixUnaryExpression unary) { - debug(verbose) writeln("UnaryExpression("); + put("&"); + format(unary.unaryExpression); + } - /** - Type type; - PrimaryExpression primaryExpression; - Token prefix; - Token suffix; - UnaryExpression unaryExpression; - NewExpression newExpression; - DeleteExpression deleteExpression; - CastExpression castExpression; - FunctionCallExpression functionCallExpression; - ArgumentList argumentList; - IdentifierOrTemplateInstance identifierOrTemplateInstance; - AssertExpression assertExpression; - SliceExpression sliceExpression; - IndexExpression indexExpression; - **/ + void format(const NotPrefixUnaryExpression unary) + { + put("!"); + format(unary.unaryExpression); + } - with(unary) - { - if (prefix != tok!"") format(prefix); + void format(const DerefPrefixUnaryExpression unary) + { + put("*"); + format(unary.unaryExpression); + } - if (type && identifierOrTemplateInstance) - { - // handle things like (void*).sizeof - put("("); - format(type); - put(")"); - } + void format(const PlusPrefixUnaryExpression unary) + { + put("+"); + format(unary.unaryExpression); + } - if (primaryExpression) format(primaryExpression); - if (newExpression) format(newExpression); - if (deleteExpression) format(deleteExpression); - if (castExpression) format(castExpression); - if (functionCallExpression) format(functionCallExpression); - if (assertExpression) format(assertExpression); - if (throwExpression) format(throwExpression); - if (indexExpression) format(indexExpression); + void format(const MinusPrefixUnaryExpression unary) + { + put("-"); + format(unary.unaryExpression); + } - if (unaryExpression) format(unaryExpression); - if (suffix != tok!"") format(suffix); + void format(const TildePrefixUnaryExpression unary) + { + put("~"); + format(unary.unaryExpression); + } - if (identifierOrTemplateInstance) - { - put("."); - format(identifierOrTemplateInstance); - } - } + void format(const PlusPlusPrefixUnaryExpression unary) + { + put("++"); + format(unary.unaryExpression); + } - debug(verbose) writeln(")"); + void format(const MinusMinusPrefixUnaryExpression unary) + { + put("--"); + format(unary.unaryExpression); + } + + void format(const PlusPlusPostfixUnaryExpression unary) + { + format(unary.unaryExpression); + put("++"); + } + + void format(const MinusMinusPostfixUnaryExpression unary) + { + format(unary.unaryExpression); + put("--"); + } + + void format(const UnaryDotIdentifierExpression unary) + { + format(unary.unaryExpression); + put("."); + format(unary.identifierOrTemplateInstance); + } + + void format(const UnaryDotNewExpression unary) + { + format(unary.unaryExpression); + put("."); + format(unary.newExpression); + } + + void format(const TypeDotIdentifierExpression unary) + { + put("("); + format(unary.type); + put(")."); + format(unary.identifierOrTemplateInstance); } void format(const UnionDeclaration decl, const Attribute[] attrs = null) @@ -4183,6 +4239,9 @@ unittest testFormatNode!(VariableDeclaration)(`T!(0)[] t;`); testFormatNode!(VariableDeclaration)(`T!(0)[dim] t;`); testFormatNode!(VariableDeclaration)(`const shared t = [0, 1];`); + testFormatNode!(VariableDeclaration)(`auto x = foo();`); + testFormatNode!(VariableDeclaration)(`auto x = foo("bar");`); + testFormatNode!(VariableDeclaration)(`auto x = foo(baz: "bar");`); testFormatNode!(OutStatement)( ` diff --git a/src/dparse/parser.d b/src/dparse/parser.d index 533e4468..c32fedea 100644 --- a/src/dparse/parser.d +++ b/src/dparse/parser.d @@ -12,6 +12,7 @@ import std.conv; import std.algorithm; import std.array; import std.string : format; +import std.typecons : Flag; // Uncomment this if you want ALL THE OUTPUT // Caution: generates 180 megabytes of logging for std.datetime @@ -118,6 +119,9 @@ Module parseModule(F)(const(Token)[] tokens, string fileName, RollbackAllocator* */ class Parser { + /// Flag type for some parsing arguments + alias FromUnary = Flag!"fromUnary"; + /** * Parses an AddExpression. * @@ -1659,7 +1663,7 @@ class Parser mixin(parseNodeQ!(`node.type`, `Type`)); } mixin(tokenCheck!")"); - mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpression`)); + mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpressionNode`)); node.tokens = tokens[startIndex .. index]; return node; } @@ -2771,7 +2775,7 @@ class Parser node.line = current.line; node.column = current.column; mixin(tokenCheck!"delete"); - mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpression`)); + mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpressionNode`)); node.tokens = tokens[startIndex .. index]; return node; } @@ -3555,7 +3559,13 @@ class Parser * | $(RULE type) $(RULE arguments) * ;) */ - FunctionCallExpression parseFunctionCallExpression(UnaryExpression unary = null) + FunctionCallExpression parseFunctionCallExpression() + { + return parseFunctionCallExpression(null, FromUnary.no); + } + + /// ditto + FunctionCallExpression parseFunctionCallExpression(UnaryExpressionNode unary, FromUnary fromUnary = FromUnary.yes) { mixin(traceEnterAndExit!(__FUNCTION__)); auto startIndex = index; @@ -3573,13 +3583,13 @@ class Parser mixin(parseNodeQ!(`node.arguments`, `Arguments`)); break; default: - if (unary !is null) + if (fromUnary) node.unaryExpression = unary; else - mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpression`)); + mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpressionNode`)); if (currentIs(tok!"!")) mixin(parseNodeQ!(`node.templateArguments`, `TemplateArguments`)); - if (unary !is null) + if (fromUnary) mixin(parseNodeQ!(`node.arguments`, `Arguments`)); } node.tokens = tokens[startIndex .. index]; @@ -4413,12 +4423,18 @@ class Parser * ; * ) */ - IndexExpression parseIndexExpression(UnaryExpression unaryExpression = null) + IndexExpression parseIndexExpression() + { + return parseIndexExpression(null, false); + } + + /// ditto + IndexExpression parseIndexExpression(UnaryExpressionNode unaryExpression, bool fromUnary = true) { mixin(traceEnterAndExit!(__FUNCTION__)); auto startIndex = index; auto node = allocator.make!IndexExpression; - mixin(nullCheck!`node.unaryExpression = unaryExpression is null ? parseUnaryExpression() : unaryExpression`); + mixin(nullCheck!`node.unaryExpression = fromUnary ? unaryExpression : parseUnaryExpressionNode()`); mixin(tokenCheck!"["); StackBuffer indexes; while (true) @@ -5636,7 +5652,7 @@ class Parser { pragma(inline, true); mixin (traceEnterAndExit!(__FUNCTION__)); - return parseLeftAssocBinaryExpression!(PowExpression, UnaryExpression, + return parseLeftAssocBinaryExpression!(PowExpression, UnaryExpressionNode, tok!"^^")(); } @@ -7777,7 +7793,7 @@ class Parser } /** - * Parses a UnaryExpression + * Parses a UnaryExpression (flattened from parsed child) * * $(GRAMMAR $(RULEDEF unaryExpression): * $(RULE primaryExpression) @@ -7803,13 +7819,13 @@ class Parser * | $(RULE unaryExpression) $(LITERAL '++') * ;) */ - UnaryExpression parseUnaryExpression() + UnaryExpressionNode parseUnaryExpressionNode() { mixin(traceEnterAndExit!(__FUNCTION__)); auto startIndex = index; if (!moreTokens()) return null; - auto node = allocator.make!UnaryExpression; + UnaryExpressionNode node; switch (current.type) { case tok!"const": @@ -7832,33 +7848,70 @@ class Parser case tok!"scope": case tok!"pure": case tok!"nothrow": - mixin(parseNodeQ!(`node.functionCallExpression`, `FunctionCallExpression`)); + mixin(parseNodeQ!(`node`, `FunctionCallExpression`)); break; case tok!"&": + advance(); + auto n = allocator.make!RefPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"!": + advance(); + auto n = allocator.make!NotPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"*": + advance(); + auto n = allocator.make!DerefPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"+": + advance(); + auto n = allocator.make!PlusPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"-": + advance(); + auto n = allocator.make!MinusPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"~": + advance(); + auto n = allocator.make!TildePrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"++": + advance(); + auto n = allocator.make!PlusPlusPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; + break; case tok!"--": - node.prefix = advance(); - mixin(parseNodeQ!(`node.unaryExpression`, `UnaryExpression`)); + advance(); + auto n = allocator.make!MinusMinusPrefixUnaryExpression; + mixin(parseNodeQ!(`n.unaryExpression`, `UnaryExpressionNode`)); + node = n; break; case tok!"new": - mixin(parseNodeQ!(`node.newExpression`, `NewExpression`)); + mixin(parseNodeQ!(`node`, `NewExpression`)); break; case tok!"delete": - mixin(parseNodeQ!(`node.deleteExpression`, `DeleteExpression`)); + mixin(parseNodeQ!(`node`, `DeleteExpression`)); break; case tok!"cast": - mixin(parseNodeQ!(`node.castExpression`, `CastExpression`)); + mixin(parseNodeQ!(`node`, `CastExpression`)); break; case tok!"assert": - mixin(parseNodeQ!(`node.assertExpression`, `AssertExpression`)); + mixin(parseNodeQ!(`node`, `AssertExpression`)); break; case tok!"throw": - mixin(parseNodeQ!(`node.throwExpression`, `ThrowExpression`)); + mixin(parseNodeQ!(`node`, `ThrowExpression`)); break; case tok!"(": // handle (type).identifier @@ -7877,10 +7930,13 @@ class Parser goto default; } abandonBookmark(b2); - node.type = t; + auto n = allocator.make!TypeDotIdentifierExpression; + n.type = t; advance(); // ) + n.dotLocation = current.index; advance(); // . - mixin(parseNodeQ!(`node.identifierOrTemplateInstance`, `IdentifierOrTemplateInstance`)); + mixin(parseNodeQ!(`n.identifierOrTemplateInstance`, `IdentifierOrTemplateInstance`)); + node = n; break; } else @@ -7890,7 +7946,7 @@ class Parser goto default; } default: - mixin(parseNodeQ!(`node.primaryExpression`, `PrimaryExpression`)); + mixin(parseNodeQ!(`node`, `PrimaryExpression`)); break; } @@ -7912,46 +7968,60 @@ class Parser else break loop; case tok!"(": - auto newUnary = allocator.make!UnaryExpression(); // Allows DCD to get the call tips // see https://github.com/dlang-community/DCD/issues/405 if (peekIs(tok!"}")) { error("Error, expected parameters or `)`", false); advance(); - if (newUnary) newUnary.tokens = tokens[startIndex .. index]; - return newUnary; + node = allocator.make!DummyUnaryExpression; + node.tokens = tokens[startIndex .. index]; + return node; } - mixin (nullCheck!`newUnary.functionCallExpression = parseFunctionCallExpression(node)`); - node = newUnary; + mixin (nullCheck!`node = parseFunctionCallExpression(node)`); break; case tok!"++": + advance(); + auto n = allocator.make!PlusPlusPostfixUnaryExpression; + n.unaryExpression = node; + node = n; + break; case tok!"--": - auto n = allocator.make!UnaryExpression(); + advance(); + auto n = allocator.make!MinusMinusPostfixUnaryExpression; n.unaryExpression = node; - n.suffix = advance(); node = n; break; case tok!"[": - auto n = allocator.make!UnaryExpression; - n.indexExpression = parseIndexExpression(node); - node = n; + node = parseIndexExpression(node); break; case tok!".": - node.dotLocation = current.index; - advance(); - auto n = allocator.make!UnaryExpression(); - n.unaryExpression = node; - if (currentIs(tok!"new")) - mixin(parseNodeQ!(`node.newExpression`, `NewExpression`)); + if (peekIs(tok!"new")) + { + auto n = allocator.make!UnaryDotNewExpression(); + n.dotLocation = current.index; + advance(); + n.unaryExpression = node; + mixin(parseNodeQ!(`n.newExpression`, `NewExpression`)); + node = n; + } else + { + auto n = allocator.make!UnaryDotIdentifierExpression(); + n.dotLocation = current.index; + advance(); + n.unaryExpression = node; n.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance(); - node = n; + node = n; + } break; default: break loop; } - node.tokens = tokens[startIndex .. index]; + if (node) + node.tokens = tokens[startIndex .. index]; + else + error("Expected UnaryExpression", false); return node; } @@ -8335,7 +8405,7 @@ protected: final: immutable b = setBookmark(); scope(exit) goToBookmark(b); advance(); - immutable bool result = !currentIs(tok!"]") && parseExpression() !is null && currentIs(tok!":"); + immutable bool result = !currentIs(tok!"]") && parseAssignExpression() !is null && currentIs(tok!":"); cachedAAChecks[currentIndex] = result; return result; } @@ -8735,6 +8805,12 @@ protected: final: node.line = current.line; node.column = current.column; } + static assert(is(immutable typeof(node.items[0]) == immutable typeof(mixin("parse" ~ ItemType.stringof ~ "()"))), + "cannot use parseCommaSeparatedRule on " ~ ListType.stringof + ~ " with function parse" ~ ItemType.stringof ~ ", since it expects " + ~ "items of type " ~ typeof(node.items[0]).stringof + ~ ", but the parse function returns " + ~ typeof(mixin("parse" ~ ItemType.stringof ~ "()")).stringof); StackBuffer items; while (moreTokens()) { diff --git a/test/ast_checks/assert_args.txt b/test/ast_checks/assert_args.txt index 22e08b9c..37c85f4b 100644 --- a/test/ast_checks/assert_args.txt +++ b/test/ast_checks/assert_args.txt @@ -1,4 +1,4 @@ -./module/declaration/staticAssertDeclaration//assertArguments/unaryExpression[1]//identifierOrTemplateInstance/identifier[text()="foo"] -./module/declaration/staticAssertDeclaration//assertArguments/unaryExpression[2]/primaryExpression/stringLiteral[text()='"a"'] -./module/declaration/staticAssertDeclaration//assertArguments/unaryExpression[3]//identifierOrTemplateInstance/identifier[text()="b"] -./module/declaration/staticAssertDeclaration//assertArguments/unaryExpression[4]/primaryExpression/stringLiteral[text()='"c"'] +./module/declaration/staticAssertDeclaration//assertArguments/primaryExpression[1]/identifierOrTemplateInstance/identifier[text()="foo"] +./module/declaration/staticAssertDeclaration//assertArguments/primaryExpression[2]/stringLiteral[text()='"a"'] +./module/declaration/staticAssertDeclaration//assertArguments/primaryExpression[3]/identifierOrTemplateInstance/identifier[text()="b"] +./module/declaration/staticAssertDeclaration//assertArguments/primaryExpression[4]/stringLiteral[text()='"c"'] diff --git a/test/ast_checks/named_arguments.txt b/test/ast_checks/named_arguments.txt index a7006618..555e4d88 100644 --- a/test/ast_checks/named_arguments.txt +++ b/test/ast_checks/named_arguments.txt @@ -1,5 +1,5 @@ -//functionCallExpression[unaryExpression//identifier='b']//namedArgument[identifier='x'] -//functionCallExpression[unaryExpression//identifier='c']//namedArgument[identifier='x'] -//functionCallExpression[unaryExpression//identifier='c']//namedArgument[identifier='y'] -//functionCallExpression[unaryExpression//identifier='d']//namedTemplateArgument[identifier='a'] -//functionCallExpression[unaryExpression//identifier='d']//namedTemplateArgument[identifier='b'] +//functionCallExpression[primaryExpression//identifier='b']//namedArgument[identifier='x'] +//functionCallExpression[primaryExpression//identifier='c']//namedArgument[identifier='x'] +//functionCallExpression[primaryExpression//identifier='c']//namedArgument[identifier='y'] +//functionCallExpression[primaryExpression//identifier='d']//namedTemplateArgument[identifier='a'] +//functionCallExpression[primaryExpression//identifier='d']//namedTemplateArgument[identifier='b'] diff --git a/test/ast_checks/throw_expressions.txt b/test/ast_checks/throw_expressions.txt index 005c53bd..be9fed43 100644 --- a/test/ast_checks/throw_expressions.txt +++ b/test/ast_checks/throw_expressions.txt @@ -1,8 +1,8 @@ //functionDeclaration[name = 'main'] -//functionCallExpression/unaryExpression/primaryExpression/identifierOrTemplateInstance[identifier='foo'] -//functionCallExpression/arguments/namedArgumentList/namedArgument[1]/unaryExpression/throwExpression//*[identifier='someThrowable'] -//functionCallExpression/arguments/namedArgumentList/namedArgument[2]/unaryExpression/primaryExpression/*[identifier='bar'] +//functionCallExpression/primaryExpression/identifierOrTemplateInstance[identifier='foo'] +//functionCallExpression/arguments/namedArgumentList/namedArgument[1]/throwExpression//*[identifier='someThrowable'] +//functionCallExpression/arguments/namedArgumentList/namedArgument[2]/primaryExpression/*[identifier='bar'] //ternaryExpression/*[1]//*[identifier='foo'] //ternaryExpression/*[2]//*[identifier='bar'] -//ternaryExpression/*[3]/throwExpression/unaryExpression/newExpression/type[@pretty='Exception'] -//ternaryExpression/*[3]/throwExpression/unaryExpression/newExpression/arguments//stringLiteral +//ternaryExpression/*[3]/newExpression/type[@pretty='Exception'] +//ternaryExpression/*[3]/newExpression/arguments//stringLiteral diff --git a/test/ast_checks/unary_expressions.d b/test/ast_checks/unary_expressions.d new file mode 100644 index 00000000..11497ef6 --- /dev/null +++ b/test/ast_checks/unary_expressions.d @@ -0,0 +1,18 @@ +unittest { i++; } +unittest { ++i; } +unittest { i--; } +unittest { --i; } +unittest { i -= +j; } +unittest { i += -j; } +unittest { i -= ~j; } +unittest { i += !j; } +unittest { i -= *j; } +unittest { i += &j; } +unittest { i = cast(int)j; } +unittest { x = assert(0); } +unittest { x = throw y; } +unittest { x = delete f; } +unittest { x = new F(); } +unittest { + *&~(+1 | (int).init).new T(2); +} \ No newline at end of file diff --git a/test/ast_checks/unary_expressions.txt b/test/ast_checks/unary_expressions.txt new file mode 100644 index 00000000..046dd8ef --- /dev/null +++ b/test/ast_checks/unary_expressions.txt @@ -0,0 +1,21 @@ +/module/declaration[1]/unittest/blockStatement//expression/plusPlusPostfixUnaryExpression//identifier +/module/declaration[2]/unittest/blockStatement//expression/plusPlusPrefixUnaryExpression//identifier +/module/declaration[3]/unittest/blockStatement//expression/minusMinusPostfixUnaryExpression//identifier +/module/declaration[4]/unittest/blockStatement//expression/minusMinusPrefixUnaryExpression//identifier +/module/declaration[5]/unittest/blockStatement//expression/expression[@operator="-="]/plusPrefixUnaryExpression +/module/declaration[6]/unittest/blockStatement//expression/expression[@operator="+="]/minusPrefixUnaryExpression +/module/declaration[7]/unittest/blockStatement//expression/expression[@operator="-="]/tildePrefixUnaryExpression +/module/declaration[8]/unittest/blockStatement//expression/expression[@operator="+="]/notPrefixUnaryExpression +/module/declaration[9]/unittest/blockStatement//expression/expression[@operator="-="]/derefPrefixUnaryExpression +/module/declaration[10]/unittest/blockStatement//expression/expression[@operator="+="]/refPrefixUnaryExpression +/module/declaration[11]/unittest/blockStatement//expression/expression[@operator="="]/castExpression/type[@pretty="int"] +/module/declaration[11]/unittest/blockStatement//expression/expression[@operator="="]/castExpression/primaryExpression/identifierOrTemplateInstance/identifier[text()="j"] +/module/declaration[12]/unittest/blockStatement//expression/expression[@operator="="]/assertExpression/assertArguments/primaryExpression/intLiteral[text()="0"] +/module/declaration[13]/unittest/blockStatement//expression/expression[@operator="="]/throwExpression/primaryExpression/identifierOrTemplateInstance/identifier[text()="y"] +/module/declaration[14]/unittest/blockStatement//expression/expression[@operator="="]/deleteExpression/primaryExpression/identifierOrTemplateInstance/identifier[text()="f"] +/module/declaration[15]/unittest/blockStatement//expression/expression[@operator="="]/newExpression/type[@pretty="F"] +/module/declaration[16]/unittest/blockStatement//expression/derefPrefixUnaryExpression/refPrefixUnaryExpression/tildePrefixUnaryExpression/unaryDotNewExpression/primaryExpression/expression/orExpression/plusPrefixUnaryExpression +/module/declaration[16]/unittest/blockStatement//expression/derefPrefixUnaryExpression/refPrefixUnaryExpression/tildePrefixUnaryExpression/unaryDotNewExpression/primaryExpression/expression/orExpression/typeDotIdentifierExpression/type[@pretty="int"] +/module/declaration[16]/unittest/blockStatement//expression/derefPrefixUnaryExpression/refPrefixUnaryExpression/tildePrefixUnaryExpression/unaryDotNewExpression/primaryExpression/expression/orExpression/typeDotIdentifierExpression/identifierOrTemplateInstance/identifier[text()="init"] +/module/declaration[16]/unittest/blockStatement//expression/derefPrefixUnaryExpression/refPrefixUnaryExpression/tildePrefixUnaryExpression/unaryDotNewExpression/newExpression/type[@pretty="T"] +/module/declaration[16]/unittest/blockStatement//expression/derefPrefixUnaryExpression/refPrefixUnaryExpression/tildePrefixUnaryExpression/unaryDotNewExpression/newExpression/arguments//primaryExpression/intLiteral[text()="2"] diff --git a/test/ast_checks/while_condition.txt b/test/ast_checks/while_condition.txt index 4cb02888..1e1d310f 100644 --- a/test/ast_checks/while_condition.txt +++ b/test/ast_checks/while_condition.txt @@ -1,20 +1,20 @@ //functionDeclaration[name = 'a']//functionBody//whileStatement/condition/auto not(//functionDeclaration[name = 'a']//functionBody//whileStatement/condition/scope) //functionDeclaration[name = 'a']//functionBody//whileStatement/condition/identifier[text()='line'] -//functionDeclaration[name = 'a']//functionBody//whileStatement/condition/unaryExpression//identifier[text()='readln'] +//functionDeclaration[name = 'a']//functionBody//whileStatement/condition/primaryExpression//identifier[text()='readln'] //functionDeclaration[name = 'a']//functionBody//whileStatement/declarationOrStatement//identifier[text()='line'] //functionDeclaration[name = 'a']//functionBody//whileStatement/declarationOrStatement//identifier[text()='strip'] not(//functionDeclaration[name = 'b']//functionBody//whileStatement/condition/auto) //functionDeclaration[name = 'b']//functionBody//whileStatement/condition/scope //functionDeclaration[name = 'b']//functionBody//whileStatement/condition/identifier[text()='line'] -//functionDeclaration[name = 'b']//functionBody//whileStatement/condition/unaryExpression//identifier[text()='readln'] +//functionDeclaration[name = 'b']//functionBody//whileStatement/condition/primaryExpression//identifier[text()='readln'] //functionDeclaration[name = 'b']//functionBody//whileStatement/declarationOrStatement//identifier[text()='line'] //functionDeclaration[name = 'b']//functionBody//whileStatement/declarationOrStatement//identifier[text()='strip'] not(//functionDeclaration[name = 'c']//functionBody//whileStatement/condition/auto) not(//functionDeclaration[name = 'c']//functionBody//whileStatement/condition/scope) //functionDeclaration[name = 'c']//functionBody//whileStatement/condition/typeConstructor[text()='const'] //functionDeclaration[name = 'c']//functionBody//whileStatement/condition/identifier[text()='line'] -//functionDeclaration[name = 'c']//functionBody//whileStatement/condition/unaryExpression//identifier[text()='readln'] +//functionDeclaration[name = 'c']//functionBody//whileStatement/condition/primaryExpression//identifier[text()='readln'] //functionDeclaration[name = 'c']//functionBody//whileStatement/declarationOrStatement//identifier[text()='line'] //functionDeclaration[name = 'c']//functionBody//whileStatement/declarationOrStatement//identifier[text()='strip'] not(//functionDeclaration[name = 'd']//functionBody//whileStatement/condition/auto) @@ -23,6 +23,6 @@ not(//functionDeclaration[name = 'd']//functionBody//whileStatement/condition/sc //functionDeclaration[name = 'd']//functionBody//whileStatement/condition/typeConstructor[text()='inout'] //functionDeclaration[name = 'd']//functionBody//whileStatement/condition/type[@pretty='string'] //functionDeclaration[name = 'd']//functionBody//whileStatement/condition/identifier[text()='line'] -//functionDeclaration[name = 'd']//functionBody//whileStatement/condition/unaryExpression//identifier[text()='readln'] +//functionDeclaration[name = 'd']//functionBody//whileStatement/condition/primaryExpression//identifier[text()='readln'] //functionDeclaration[name = 'd']//functionBody//whileStatement/declarationOrStatement//identifier[text()='line'] //functionDeclaration[name = 'd']//functionBody//whileStatement/declarationOrStatement//identifier[text()='strip'] diff --git a/test/tester.d b/test/tester.d index 99ff3f3a..23ced520 100644 --- a/test/tester.d +++ b/test/tester.d @@ -310,9 +310,9 @@ int main(string[] args) // increase stack size in case of segfault: // stack usage in debug / non-optimized mode is _much_ higher version (D_Coverage) - enum maxStackSize = 256 * 4096; + enum maxStackSize = 512 * 4096; else debug - enum maxStackSize = 256 * 4096; + enum maxStackSize = 512 * 4096; else enum maxStackSize = 40 * 4096;