1 // Written in the D programming language.
2 
3 /**
4  * This module defines an Abstract Syntax Tree for the D language
5  *
6  * Examples:
7  * ---
8  * // TODO
9  * ---
10  *
11  * Copyright: Brian Schott 2013
12  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt Boost, License 1.0)
13  * Authors: Brian Schott
14  */
15 
16 module dparse.ast;
17 
18 import dparse.lexer;
19 import std.traits;
20 import std.algorithm;
21 import std.array;
22 import std.string;
23 
24 private immutable uint[TypeInfo] typeMap;
25 
26 shared static this()
27 {
28     typeMap[typeid(AddExpression)] = 1;
29     typeMap[typeid(AndAndExpression)] = 2;
30     typeMap[typeid(AndExpression)] = 3;
31     typeMap[typeid(AsmAddExp)] = 4;
32     typeMap[typeid(AsmAndExp)] = 5;
33     typeMap[typeid(AsmBrExp)] = 6;
34     typeMap[typeid(AsmExp)] = 7;
35     typeMap[typeid(AsmEqualExp)] = 8;
36     typeMap[typeid(AsmLogAndExp)] = 9;
37     typeMap[typeid(AsmLogOrExp)] = 10;
38     typeMap[typeid(AsmMulExp)] = 11;
39     typeMap[typeid(AsmOrExp)] = 12;
40     typeMap[typeid(AsmRelExp)] = 13;
41     typeMap[typeid(AsmUnaExp)] = 14;
42     typeMap[typeid(AsmShiftExp)] = 15;
43     typeMap[typeid(AsmXorExp)] = 16;
44     typeMap[typeid(AssertExpression)] = 17;
45     typeMap[typeid(AssignExpression)] = 18;
46     typeMap[typeid(CmpExpression)] = 19;
47     typeMap[typeid(DeleteExpression)] = 20;
48     typeMap[typeid(EqualExpression)] = 21;
49     typeMap[typeid(Expression)] = 22;
50     typeMap[typeid(FunctionCallExpression)] = 23;
51     typeMap[typeid(FunctionLiteralExpression)] = 24;
52     typeMap[typeid(IdentityExpression)] = 25;
53     typeMap[typeid(ImportExpression)] = 26;
54     typeMap[typeid(IndexExpression)] = 27;
55     typeMap[typeid(InExpression)] = 28;
56     typeMap[typeid(IsExpression)] = 29;
57     typeMap[typeid(MixinExpression)] = 30;
58     typeMap[typeid(MulExpression)] = 31;
59     typeMap[typeid(NewAnonClassExpression)] = 32;
60     typeMap[typeid(NewExpression)] = 33;
61     typeMap[typeid(OrExpression)] = 34;
62     typeMap[typeid(OrOrExpression)] = 35;
63     typeMap[typeid(PowExpression)] = 36;
64     typeMap[typeid(PragmaExpression)] = 37;
65     typeMap[typeid(PrimaryExpression)] = 38;
66     typeMap[typeid(RelExpression)] = 39;
67     typeMap[typeid(ShiftExpression)] = 40;
68     typeMap[typeid(Index)] = 41;
69     typeMap[typeid(TemplateMixinExpression)] = 42;
70     typeMap[typeid(TernaryExpression)] = 43;
71     typeMap[typeid(TraitsExpression)] = 44;
72     typeMap[typeid(TypeidExpression)] = 45;
73     typeMap[typeid(TypeofExpression)] = 46;
74     typeMap[typeid(UnaryExpression)] = 47;
75     typeMap[typeid(XorExpression)] = 48;
76 }
77 
78 /// Describes which syntax was used in a list of declarations in the containing AST node
79 enum DeclarationListStyle : ubyte
80 {
81     /// A declaration directly after the containing AST node making it the only child
82     single,
83     /// A colon (`:`) was used in the containing AST node meaning all following declarations are part here.
84     colon,
85     /// The declarations have been specified in a block denoted by starting `{` and ending `}` tokens.
86     block
87 }
88 
89 /**
90  * Implements the $(LINK2 http://en.wikipedia.org/wiki/Visitor_pattern, Visitor Pattern)
91  * for the various AST classes
92  */
93 abstract class ASTVisitor
94 {
95 
96     /** */
97     void visit(const ExpressionNode n)
98     {
99         switch (typeMap[typeid(n)])
100         {
101         case 1: visit(cast(AddExpression) n); break;
102         case 2: visit(cast(AndAndExpression) n); break;
103         case 3: visit(cast(AndExpression) n); break;
104         case 4: visit(cast(AsmAddExp) n); break;
105         case 5: visit(cast(AsmAndExp) n); break;
106         case 6: visit(cast(AsmBrExp) n); break;
107         case 7: visit(cast(AsmExp) n); break;
108         case 8: visit(cast(AsmEqualExp) n); break;
109         case 9: visit(cast(AsmLogAndExp) n); break;
110         case 10: visit(cast(AsmLogOrExp) n); break;
111         case 11: visit(cast(AsmMulExp) n); break;
112         case 12: visit(cast(AsmOrExp) n); break;
113         case 13: visit(cast(AsmRelExp) n); break;
114         case 14: visit(cast(AsmUnaExp) n); break;
115         case 15: visit(cast(AsmShiftExp) n); break;
116         case 16: visit(cast(AsmXorExp) n); break;
117         case 17: visit(cast(AssertExpression) n); break;
118         case 18: visit(cast(AssignExpression) n); break;
119         case 19: visit(cast(CmpExpression) n); break;
120         case 20: visit(cast(DeleteExpression) n); break;
121         case 21: visit(cast(EqualExpression) n); break;
122         case 22: visit(cast(Expression) n); break;
123         case 23: visit(cast(FunctionCallExpression) n); break;
124         case 24: visit(cast(FunctionLiteralExpression) n); break;
125         case 25: visit(cast(IdentityExpression) n); break;
126         case 26: visit(cast(ImportExpression) n); break;
127         case 27: visit(cast(IndexExpression) n); break;
128         case 28: visit(cast(InExpression) n); break;
129         case 29: visit(cast(IsExpression) n); break;
130         case 30: visit(cast(MixinExpression) n); break;
131         case 31: visit(cast(MulExpression) n); break;
132         case 32: visit(cast(NewAnonClassExpression) n); break;
133         case 33: visit(cast(NewExpression) n); break;
134         case 34: visit(cast(OrExpression) n); break;
135         case 35: visit(cast(OrOrExpression) n); break;
136         case 36: visit(cast(PowExpression) n); break;
137         case 37: visit(cast(PragmaExpression) n); break;
138         case 38: visit(cast(PrimaryExpression) n); break;
139         case 39: visit(cast(RelExpression) n); break;
140         case 40: visit(cast(ShiftExpression) n); break;
141         case 41: visit(cast(Index) n); break;
142         case 42: visit(cast(TemplateMixinExpression) n); break;
143         case 43: visit(cast(TernaryExpression) n); break;
144         case 44: visit(cast(TraitsExpression) n); break;
145         case 45: visit(cast(TypeidExpression) n); break;
146         case 46: visit(cast(TypeofExpression) n); break;
147         case 47: visit(cast(UnaryExpression) n); break;
148         case 48: visit(cast(XorExpression) n); break;
149         default: assert(false, __MODULE__ ~ " has a bug");
150         }
151     }
152 
153     /** */ void visit(const AddExpression addExpression) { addExpression.accept(this); }
154     /** */ void visit(const AliasDeclaration aliasDeclaration) { aliasDeclaration.accept(this); }
155     /** */ void visit(const AliasAssign aliasAssign) { aliasAssign.accept(this); }
156     /** */ void visit(const AliasInitializer aliasInitializer) { aliasInitializer.accept(this); }
157     /** */ void visit(const AliasThisDeclaration aliasThisDeclaration) { aliasThisDeclaration.accept(this); }
158     /** */ void visit(const AlignAttribute alignAttribute) { alignAttribute.accept(this); }
159     /** */ void visit(const AndAndExpression andAndExpression) { andAndExpression.accept(this); }
160     /** */ void visit(const AndExpression andExpression) { andExpression.accept(this); }
161     /** */ void visit(const AnonymousEnumDeclaration anonymousEnumDeclaration) { anonymousEnumDeclaration.accept(this); }
162     /** */ void visit(const AnonymousEnumMember anonymousEnumMember) { anonymousEnumMember.accept(this); }
163     /** */ void visit(const ArgumentList argumentList) { argumentList.accept(this); }
164     /** */ void visit(const Arguments arguments) { arguments.accept(this); }
165     /** */ void visit(const ArrayInitializer arrayInitializer) { arrayInitializer.accept(this); }
166     /** */ void visit(const ArrayLiteral arrayLiteral) { arrayLiteral.accept(this); }
167     /** */ void visit(const ArrayMemberInitialization arrayMemberInitialization) { arrayMemberInitialization.accept(this); }
168     /** */ void visit(const AsmAddExp asmAddExp) { asmAddExp.accept(this); }
169     /** */ void visit(const AsmAndExp asmAndExp) { asmAndExp.accept(this); }
170     /** */ void visit(const AsmBrExp asmBrExp) { asmBrExp.accept(this); }
171     /** */ void visit(const AsmEqualExp asmEqualExp) { asmEqualExp.accept(this); }
172     /** */ void visit(const AsmExp asmExp) { asmExp.accept(this); }
173     /** */ void visit(const AsmInstruction asmInstruction) { asmInstruction.accept(this); }
174     /** */ void visit(const AsmLogAndExp asmLogAndExp) { asmLogAndExp.accept(this); }
175     /** */ void visit(const AsmLogOrExp asmLogOrExp) { asmLogOrExp.accept(this); }
176     /** */ void visit(const AsmMulExp asmMulExp) { asmMulExp.accept(this); }
177     /** */ void visit(const AsmOrExp asmOrExp) { asmOrExp.accept(this); }
178     /** */ void visit(const AsmPrimaryExp asmPrimaryExp) { asmPrimaryExp.accept(this); }
179     /** */ void visit(const AsmRelExp asmRelExp) { asmRelExp.accept(this); }
180     /** */ void visit(const AsmShiftExp asmShiftExp) { asmShiftExp.accept(this); }
181     /** */ void visit(const AsmStatement asmStatement) { asmStatement.accept(this); }
182     /** */ void visit(const AsmTypePrefix asmTypePrefix) { asmTypePrefix.accept(this); }
183     /** */ void visit(const AsmUnaExp asmUnaExp) { asmUnaExp.accept(this); }
184     /** */ void visit(const AsmXorExp asmXorExp) { asmXorExp.accept(this); }
185     /** */ void visit(const AssertArguments assertArguments) { assertArguments.accept(this); }
186     /** */ void visit(const AssertExpression assertExpression) { assertExpression.accept(this); }
187     /** */ void visit(const AssignExpression assignExpression) { assignExpression.accept(this); }
188     /** */ void visit(const AssocArrayLiteral assocArrayLiteral) { assocArrayLiteral.accept(this); }
189     /** */ void visit(const AtAttribute atAttribute) { atAttribute.accept(this); }
190     /** */ void visit(const Attribute attribute) { attribute.accept(this); }
191     /** */ void visit(const AttributeDeclaration attributeDeclaration) { attributeDeclaration.accept(this); }
192     /** */ void visit(const AutoDeclaration autoDeclaration) { autoDeclaration.accept(this); }
193     /** */ void visit(const AutoDeclarationPart autoDeclarationPart) { autoDeclarationPart.accept(this); }
194     /** */ void visit(const BlockStatement blockStatement) { blockStatement.accept(this); }
195     /** */ void visit(const BreakStatement breakStatement) { breakStatement.accept(this); }
196     /** */ void visit(const BaseClass baseClass) { baseClass.accept(this); }
197     /** */ void visit(const BaseClassList baseClassList) { baseClassList.accept(this); }
198     /** */ void visit(const BitfieldWidth bitfieldWidth) { bitfieldWidth.accept(this); }
199     /** */ void visit(const CaseRangeStatement caseRangeStatement) { caseRangeStatement.accept(this); }
200     /** */ void visit(const CaseStatement caseStatement) { caseStatement.accept(this); }
201     /** */ void visit(const CastExpression castExpression) { castExpression.accept(this); }
202     /** */ void visit(const CastQualifier castQualifier) { castQualifier.accept(this); }
203     /** */ void visit(const Catch catch_) { catch_.accept(this); }
204     /** */ void visit(const Catches catches) { catches.accept(this); }
205     /** */ void visit(const ClassDeclaration classDeclaration) { classDeclaration.accept(this); }
206     /** */ void visit(const CmpExpression cmpExpression) { cmpExpression.accept(this); }
207     /** */ void visit(const CompileCondition compileCondition) { compileCondition.accept(this); }
208     /** */ void visit(const ConditionalDeclaration conditionalDeclaration) { conditionalDeclaration.accept(this); }
209     /** */ void visit(const ConditionalStatement conditionalStatement) { conditionalStatement.accept(this); }
210     /** */ void visit(const Constraint constraint) { constraint.accept(this); }
211     /** */ void visit(const Constructor constructor) { constructor.accept(this); }
212     /** */ void visit(const ContinueStatement continueStatement) { continueStatement.accept(this); }
213     /** */ void visit(const DebugCondition debugCondition) { debugCondition.accept(this); }
214     /** */ void visit(const DebugSpecification debugSpecification) { debugSpecification.accept(this); }
215     /** */ void visit(const Declaration declaration) { declaration.accept(this); }
216     /** */ void visit(const DeclarationOrStatement declarationsOrStatement) { declarationsOrStatement.accept(this); }
217     /** */ void visit(const DeclarationsAndStatements declarationsAndStatements) { declarationsAndStatements.accept(this); }
218     /** */ void visit(const Declarator declarator) { declarator.accept(this); }
219     /** */ void visit(const DefaultStatement defaultStatement) { defaultStatement.accept(this); }
220     /** */ void visit(const DeleteExpression deleteExpression) { deleteExpression.accept(this); }
221     /** */ void visit(const DeleteStatement deleteStatement) { deleteStatement.accept(this); }
222     /** */ void visit(const Deprecated deprecated_) { deprecated_.accept(this); }
223     /** */ void visit(const Destructor destructor) { destructor.accept(this); }
224     /** */ void visit(const DoStatement doStatement) { doStatement.accept(this); }
225     /** */ void visit(const EnumBody enumBody) { enumBody.accept(this); }
226     /** */ void visit(const EnumDeclaration enumDeclaration) { enumDeclaration.accept(this); }
227     /** */ void visit(const EnumMember enumMember) { enumMember.accept(this); }
228     /** */ void visit(const EnumMemberAttribute enumMemberAttribute) { enumMemberAttribute.accept(this); }
229     /** */ void visit(const EponymousTemplateDeclaration eponymousTemplateDeclaration) { eponymousTemplateDeclaration.accept(this); }
230     /** */ void visit(const EqualExpression equalExpression) { equalExpression.accept(this); }
231     /** */ void visit(const Expression expression) { expression.accept(this); }
232     /** */ void visit(const ExpressionStatement expressionStatement) { expressionStatement.accept(this); }
233     /** */ void visit(const FinalSwitchStatement finalSwitchStatement) { finalSwitchStatement.accept(this); }
234     /** */ void visit(const Finally finally_) { finally_.accept(this); }
235     /** */ void visit(const ForStatement forStatement) { forStatement.accept(this); }
236     /** */ void visit(const ForeachStatement foreachStatement) { foreachStatement.accept(this); }
237     /** */ void visit(const StaticForeachDeclaration staticForeachDeclaration) { staticForeachDeclaration.accept(this); }
238     /** */ void visit(const StaticForeachStatement staticForeachStatement) { staticForeachStatement.accept(this); }
239     /** */ void visit(const ForeachType foreachType) { foreachType.accept(this); }
240     /** */ void visit(const ForeachTypeList foreachTypeList) { foreachTypeList.accept(this); }
241     /** */ void visit(const FunctionAttribute functionAttribute) { functionAttribute.accept(this); }
242     /** */ void visit(const FunctionBody functionBody) { functionBody.accept(this); }
243     /** */ void visit(const FunctionCallExpression functionCallExpression) { functionCallExpression.accept(this); }
244     /** */ void visit(const FunctionContract functionContract) { functionContract.accept(this); }
245     /** */ void visit(const FunctionDeclaration functionDeclaration) { functionDeclaration.accept(this); }
246     /** */ void visit(const FunctionLiteralExpression functionLiteralExpression) { functionLiteralExpression.accept(this); }
247     /** */ void visit(const GccAsmInstruction gccAsmInstruction) { gccAsmInstruction.accept(this); }
248     /** */ void visit(const GccAsmOperandList gccAsmOperands) { gccAsmOperands.accept(this); }
249     /** */ void visit(const GccAsmOperand gccAsmOperand) { gccAsmOperand.accept(this); }
250     /** */ void visit(const GotoStatement gotoStatement) { gotoStatement.accept(this); }
251     /** */ void visit(const IdentifierChain identifierChain) { identifierChain.accept(this); }
252     /** */ void visit(const DeclaratorIdentifierList identifierList) { identifierList.accept(this); }
253     /** */ void visit(const IdentifierOrTemplateChain identifierOrTemplateChain) { identifierOrTemplateChain.accept(this); }
254     /** */ void visit(const IdentifierOrTemplateInstance identifierOrTemplateInstance) { identifierOrTemplateInstance.accept(this); }
255     /** */ void visit(const IdentityExpression identityExpression) { identityExpression.accept(this); }
256     /** */ void visit(const IfStatement ifStatement) { ifStatement.accept(this); }
257     /** */ void visit(const IfCondition ifCondition) { ifCondition.accept(this); }
258     /** */ void visit(const ImportBind importBind) { importBind.accept(this); }
259     /** */ void visit(const ImportBindings importBindings) { importBindings.accept(this); }
260     /** */ void visit(const ImportDeclaration importDeclaration) { importDeclaration.accept(this); }
261     /** */ void visit(const ImportExpression importExpression) { importExpression.accept(this); }
262     /** */ void visit(const IndexExpression indexExpression) { indexExpression.accept(this); }
263     /** */ void visit(const InContractExpression inContractExpression) { inContractExpression.accept(this); }
264     /** */ void visit(const InExpression inExpression) { inExpression.accept(this); }
265     /** */ void visit(const InOutContractExpression inOutContractExpression) { inOutContractExpression.accept(this); }
266     /** */ void visit(const InOutStatement inOutStatement) { inOutStatement.accept(this); }
267     /** */ void visit(const InStatement inStatement) { inStatement.accept(this); }
268     /** */ void visit(const Initialize initialize) { initialize.accept(this); }
269     /** */ void visit(const Initializer initializer) { initializer.accept(this); }
270     /** */ void visit(const InterfaceDeclaration interfaceDeclaration) { interfaceDeclaration.accept(this); }
271     /** */ void visit(const Invariant invariant_) { invariant_.accept(this); }
272     /** */ void visit(const IsExpression isExpression) { isExpression.accept(this); }
273     /** */ void visit(const KeyValuePair keyValuePair) { keyValuePair.accept(this); }
274     /** */ void visit(const KeyValuePairs keyValuePairs) { keyValuePairs.accept(this); }
275     /** */ void visit(const LabeledStatement labeledStatement) { labeledStatement.accept(this); }
276     /** */ void visit(const LastCatch lastCatch) { lastCatch.accept(this); }
277     /** */ void visit(const LinkageAttribute linkageAttribute) { linkageAttribute.accept(this); }
278     /** */ void visit(const MemberFunctionAttribute memberFunctionAttribute) { memberFunctionAttribute.accept(this); }
279     /** */ void visit(const MissingFunctionBody missingFunctionBody) { missingFunctionBody.accept(this); }
280     /** */ void visit(const MixinDeclaration mixinDeclaration) { mixinDeclaration.accept(this); }
281     /** */ void visit(const MixinExpression mixinExpression) { mixinExpression.accept(this); }
282     /** */ void visit(const MixinTemplateDeclaration mixinTemplateDeclaration) { mixinTemplateDeclaration.accept(this); }
283     /** */ void visit(const MixinTemplateName mixinTemplateName) { mixinTemplateName.accept(this); }
284     /** */ void visit(const Module module_) { module_.accept(this); }
285     /** */ void visit(const ModuleDeclaration moduleDeclaration) { moduleDeclaration.accept(this); }
286     /** */ void visit(const MulExpression mulExpression) { mulExpression.accept(this); }
287     /** */ void visit(const NamespaceList namespaceList) { namespaceList.accept(this); }
288     /** */ void visit(const NewAnonClassExpression newAnonClassExpression) { newAnonClassExpression.accept(this); }
289     /** */ void visit(const NewExpression newExpression) { newExpression.accept(this); }
290     /** */ void visit(const NonVoidInitializer nonVoidInitializer) { nonVoidInitializer.accept(this); }
291     /** */ void visit(const Operands operands) { operands.accept(this); }
292     /** */ void visit(const OrExpression orExpression) { orExpression.accept(this); }
293     /** */ void visit(const OrOrExpression orOrExpression) { orOrExpression.accept(this); }
294     /** */ void visit(const OutContractExpression outContractExpression) { outContractExpression.accept(this); }
295     /** */ void visit(const OutStatement outStatement) { outStatement.accept(this); }
296     /** */ void visit(const ParameterAttribute parameterAttribute) { parameterAttribute.accept(this); }
297     /** */ void visit(const Parameter parameter) { parameter.accept(this); }
298     /** */ void visit(const Parameters parameters) { parameters.accept(this); }
299     /** */ void visit(const Postblit postblit) { postblit.accept(this); }
300     /** */ void visit(const PowExpression powExpression) { powExpression.accept(this); }
301     /** */ void visit(const PragmaDeclaration pragmaDeclaration) { pragmaDeclaration.accept(this); }
302     /** */ void visit(const PragmaStatement pragmaStatement) { pragmaStatement.accept(this); }
303     /** */ void visit(const PragmaExpression pragmaExpression) { pragmaExpression.accept(this); }
304     /** */ void visit(const PrimaryExpression primaryExpression) { primaryExpression.accept(this); }
305     /** */ void visit(const Register register) { register.accept(this); }
306     /** */ void visit(const RelExpression relExpression) { relExpression.accept(this); }
307     /** */ void visit(const ReturnStatement returnStatement) { returnStatement.accept(this); }
308     /** */ void visit(const ScopeGuardStatement scopeGuardStatement) { scopeGuardStatement.accept(this); }
309     /** */ void visit(const SharedStaticConstructor sharedStaticConstructor) { sharedStaticConstructor.accept(this); }
310     /** */ void visit(const SharedStaticDestructor sharedStaticDestructor) { sharedStaticDestructor.accept(this); }
311     /** */ void visit(const ShiftExpression shiftExpression) { shiftExpression.accept(this); }
312     /** */ void visit(const ShortenedFunctionBody shortenedFunctionBody) { shortenedFunctionBody.accept(this); }
313     /** */ void visit(const SingleImport singleImport) { singleImport.accept(this); }
314     /** */ void visit(const Index index) { index.accept(this); }
315     /** */ void visit(const SpecifiedFunctionBody specifiedFunctionBody) { specifiedFunctionBody.accept(this); }
316     /** */ void visit(const Statement statement) { statement.accept(this); }
317     /** */ void visit(const StatementNoCaseNoDefault statementNoCaseNoDefault) { statementNoCaseNoDefault.accept(this); }
318     /** */ void visit(const StaticAssertDeclaration staticAssertDeclaration) { staticAssertDeclaration.accept(this); }
319     /** */ void visit(const StaticAssertStatement staticAssertStatement) { staticAssertStatement.accept(this); }
320     /** */ void visit(const StaticConstructor staticConstructor) { staticConstructor.accept(this); }
321     /** */ void visit(const StaticDestructor staticDestructor) { staticDestructor.accept(this); }
322     /** */ void visit(const StaticIfCondition staticIfCondition) { staticIfCondition.accept(this); }
323     /** */ void visit(const StorageClass storageClass) { storageClass.accept(this); }
324     /** */ void visit(const StringLiteralList stringLiteralList) { stringLiteralList.accept(this); }
325     /** */ void visit(const StructBody structBody) { structBody.accept(this); }
326     /** */ void visit(const StructDeclaration structDeclaration) { structDeclaration.accept(this); }
327     /** */ void visit(const StructInitializer structInitializer) { structInitializer.accept(this); }
328     /** */ void visit(const StructMemberInitializer structMemberInitializer) { structMemberInitializer.accept(this); }
329     /** */ void visit(const StructMemberInitializers structMemberInitializers) { structMemberInitializers.accept(this); }
330     /** */ void visit(const SwitchStatement switchStatement) { switchStatement.accept(this); }
331     /** */ void visit(const Symbol symbol) { symbol.accept(this); }
332     /** */ void visit(const SynchronizedStatement synchronizedStatement) { synchronizedStatement.accept(this); }
333     /** */ void visit(const TemplateAliasParameter templateAliasParameter) { templateAliasParameter.accept(this); }
334     /** */ void visit(const TemplateArgument templateArgument) { templateArgument.accept(this); }
335     /** */ void visit(const TemplateArgumentList templateArgumentList) { templateArgumentList.accept(this); }
336     /** */ void visit(const TemplateArguments templateArguments) { templateArguments.accept(this); }
337     /** */ void visit(const TemplateDeclaration templateDeclaration) { templateDeclaration.accept(this); }
338     /** */ void visit(const TemplateInstance templateInstance) { templateInstance.accept(this); }
339     /** */ void visit(const TemplateMixinExpression templateMixinExpression) { templateMixinExpression.accept(this); }
340     /** */ void visit(const TemplateParameter templateParameter) { templateParameter.accept(this); }
341     /** */ void visit(const TemplateParameterList templateParameterList) { templateParameterList.accept(this); }
342     /** */ void visit(const TemplateParameters templateParameters) { templateParameters.accept(this); }
343     /** */ void visit(const TemplateSingleArgument templateSingleArgument) { templateSingleArgument.accept(this); }
344     /** */ void visit(const TemplateThisParameter templateThisParameter) { templateThisParameter.accept(this); }
345     /** */ void visit(const TemplateTupleParameter templateTupleParameter) { templateTupleParameter.accept(this); }
346     /** */ void visit(const TemplateTypeParameter templateTypeParameter) { templateTypeParameter.accept(this); }
347     /** */ void visit(const TemplateValueParameter templateValueParameter) { templateValueParameter.accept(this); }
348     /** */ void visit(const TemplateValueParameterDefault templateValueParameterDefault) { templateValueParameterDefault.accept(this); }
349     /** */ void visit(const TernaryExpression ternaryExpression) { ternaryExpression.accept(this); }
350     /** */ void visit(const ThrowExpression throwExpression) { throwExpression.accept(this); }
351     /** */ void visit(const Token) { }
352     /** */ void visit(const TraitsExpression traitsExpression) { traitsExpression.accept(this); }
353     /** */ void visit(const TryStatement tryStatement) { tryStatement.accept(this); }
354     /** */ void visit(const Type type) { type.accept(this); }
355     /** */ void visit(const TypeIdentifierPart typeIdentChain) { typeIdentChain.accept(this); }
356     /** */ void visit(const Type2 type2) { type2.accept(this); }
357     /** */ void visit(const TypeSpecialization typeSpecialization) { typeSpecialization.accept(this); }
358     /** */ void visit(const TypeSuffix typeSuffix) { typeSuffix.accept(this); }
359     /** */ void visit(const TypeidExpression typeidExpression) { typeidExpression.accept(this); }
360     /** */ void visit(const TypeofExpression typeofExpression) { typeofExpression.accept(this); }
361     /** */ void visit(const UnaryExpression unaryExpression) { unaryExpression.accept(this); }
362     /** */ void visit(const UnionDeclaration unionDeclaration) { unionDeclaration.accept(this); }
363     /** */ void visit(const Unittest unittest_) { unittest_.accept(this); }
364     /** */ void visit(const VariableDeclaration variableDeclaration) { variableDeclaration.accept(this); }
365     /** */ void visit(const Vector vector) { vector.accept(this); }
366     /** */ void visit(const VersionCondition versionCondition) { versionCondition.accept(this); }
367     /** */ void visit(const VersionSpecification versionSpecification) { versionSpecification.accept(this); }
368     /** */ void visit(const WhileStatement whileStatement) { whileStatement.accept(this); }
369     /** */ void visit(const WithStatement withStatement) { withStatement.accept(this); }
370     /** */ void visit(const XorExpression xorExpression) { xorExpression.accept(this); }
371 }
372 
373 interface ASTNode
374 {
375     /** */ void accept(ASTVisitor visitor) const;
376 }
377 
378 template visitIfNotNull(fields ...)
379 {
380     static if (fields.length > 1)
381         immutable visitIfNotNull = visitIfNotNull!(fields[0]) ~ visitIfNotNull!(fields[1..$]);
382     else
383     {
384         static if (typeof(fields[0]).stringof[$ - 2 .. $] == "[]")
385         {
386             static if (__traits(hasMember, typeof(fields[0][0]), "classinfo"))
387                 immutable visitIfNotNull = "foreach (i; " ~ fields[0].stringof ~ ") if (i !is null) visitor.visit(i);\n";
388             else
389                 immutable visitIfNotNull = "foreach (i; " ~ fields[0].stringof ~ ") visitor.visit(i);\n";
390         }
391         else static if (__traits(hasMember, typeof(fields[0]), "classinfo"))
392             immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ " !is null) visitor.visit(" ~ fields[0].stringof ~ ");\n";
393         else static if (is(Unqual!(typeof(fields[0])) == Token))
394             immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ ` != tok!""` ~ ") visitor.visit(" ~ fields[0].stringof ~ ");\n";
395         else
396             immutable visitIfNotNull = "visitor.visit(" ~ fields[0].stringof ~ ");\n";
397     }
398 }
399 
400 mixin template OpEquals(bool print = false)
401 {
402     override bool opEquals(Object other) const
403     {
404         if (auto obj = cast(typeof(this)) other)
405         {
406             foreach (i, field; this.tupleof)
407             {
408                 if (typeof(this).tupleof[i].stringof.among(
409                     "comment", "line", "column", "endLocation", "startLocation",
410                     "index", "dotLocation"
411                 ))
412                     continue;
413 
414                 if (field != obj.tupleof[i])
415                     return false;
416             }
417             return true;
418         }
419         return false;
420     }
421 }
422 
423 unittest
424 {
425     auto lhs = new AddExpression();
426     auto rhs = new AddExpression();
427     assert(lhs == rhs);
428     lhs.line = 4;
429     assert(lhs == rhs);
430     lhs.operator = tok!"-";
431     assert(lhs != rhs);
432     rhs.operator = tok!"-";
433     assert(lhs == rhs);
434 }
435 
436 unittest
437 {
438     auto lhs = new AssertArguments();
439     auto rhs = new AssertArguments();
440     lhs.assertion = new AddExpression();
441     rhs.assertion = new AddExpression();
442     lhs.messageParts = [new NewExpression(), new AddExpression()];
443     rhs.messageParts = [new NewExpression(), new AddExpression()];
444     assert(lhs == rhs);
445     lhs.messageParts = [new NewExpression(), new AddExpression()];
446     rhs.messageParts = [new AddExpression(), new NewExpression()];
447     assert(lhs != rhs);
448 }
449 
450 abstract class BaseNode : ASTNode
451 {
452     /** List of tokens consumed by this AST node */ const(Token)[] tokens;
453 
454     abstract void accept(ASTVisitor visitor) const;
455 }
456 
457 abstract class ExpressionNode : BaseNode
458 {
459     override void accept(ASTVisitor visitor) const
460     {
461         assert (false);
462     }
463 }
464 
465 mixin template BinaryExpressionBody()
466 {
467     ExpressionNode left;
468     ExpressionNode right;
469     size_t line;
470     size_t column;
471 }
472 
473 ///
474 final class AddExpression : ExpressionNode
475 {
476     override void accept(ASTVisitor visitor) const
477     {
478         mixin (visitIfNotNull!(left, right));
479     }
480     mixin OpEquals;
481     /** */ IdType operator;
482     mixin BinaryExpressionBody;
483 }
484 
485 ///
486 final class AliasDeclaration : BaseNode
487 {
488     override void accept(ASTVisitor visitor) const
489     {
490         mixin (visitIfNotNull!(storageClasses, type, declaratorIdentifierList,
491             initializers, parameters, memberFunctionAttributes));
492     }
493     mixin OpEquals;
494     /** */ StorageClass[] storageClasses;
495     /** */ Type type;
496     /** */ DeclaratorIdentifierList declaratorIdentifierList;
497     /** */ AliasInitializer[] initializers;
498     /** */ string comment;
499     /** */ Parameters parameters;
500     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
501 }
502 
503 ///
504 final class AliasAssign : BaseNode
505 {
506     override void accept(ASTVisitor visitor) const
507     {
508         mixin (visitIfNotNull!(identifier, type));
509     }
510     mixin OpEquals;
511     /** */ Token identifier;
512     /** */ Type type;
513     /** */ string comment;
514 }
515 
516 ///
517 final class AliasInitializer : BaseNode
518 {
519     override void accept(ASTVisitor visitor) const
520     {
521         mixin (visitIfNotNull!(name, templateParameters, storageClasses, type,
522                 functionLiteralExpression));
523     }
524     mixin OpEquals;
525     /** */ Token name;
526     /** */ StorageClass[] storageClasses;
527     /** */ TemplateParameters templateParameters;
528     /** */ Type type;
529     /** */ FunctionLiteralExpression functionLiteralExpression;
530     /** */ Parameters parameters;
531     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
532 }
533 
534 ///
535 final class AliasThisDeclaration : BaseNode
536 {
537     override void accept(ASTVisitor visitor) const
538     {
539         mixin (visitIfNotNull!(identifier));
540     }
541     mixin OpEquals;
542     /** */ Token identifier;
543     /** */ string comment;
544 }
545 
546 ///
547 final class AlignAttribute : BaseNode
548 {
549     override void accept(ASTVisitor visitor) const
550     {
551         mixin (visitIfNotNull!(assignExpression));
552     }
553     mixin OpEquals;
554     /** */ ExpressionNode assignExpression;
555 }
556 
557 ///
558 final class AndAndExpression : ExpressionNode
559 {
560     override void accept(ASTVisitor visitor) const
561     {
562         mixin (visitIfNotNull!(left, right));
563     }
564     mixin OpEquals;
565     mixin BinaryExpressionBody;
566 }
567 
568 ///
569 final class AndExpression : ExpressionNode
570 {
571     override void accept(ASTVisitor visitor) const
572     {
573         mixin (visitIfNotNull!(left, right));
574     }
575     mixin OpEquals;
576     mixin BinaryExpressionBody;
577 }
578 
579 ///
580 final class AnonymousEnumDeclaration : BaseNode
581 {
582     override void accept(ASTVisitor visitor) const
583     {
584         mixin (visitIfNotNull!(baseType, members));
585     }
586     mixin OpEquals;
587     /** */ Type baseType;
588     /** */ AnonymousEnumMember[] members;
589 }
590 
591 ///
592 final class AnonymousEnumMember : BaseNode
593 {
594     override void accept(ASTVisitor visitor) const
595     {
596         mixin (visitIfNotNull!(type, name, assignExpression));
597     }
598     /** */ Type type;
599     /** */ Token name;
600     /** */ ExpressionNode assignExpression;
601     /** */ string comment;
602 }
603 
604 ///
605 final class ArgumentList : BaseNode
606 {
607     override void accept(ASTVisitor visitor) const
608     {
609         mixin (visitIfNotNull!(items));
610     }
611     mixin OpEquals;
612     /** */ ExpressionNode[] items;
613     /** */ size_t startLocation;
614     /** */ size_t endLocation;
615 }
616 
617 ///
618 final class Arguments : BaseNode
619 {
620     override void accept(ASTVisitor visitor) const
621     {
622         mixin (visitIfNotNull!(argumentList));
623     }
624     mixin OpEquals;
625     /** */ ArgumentList argumentList;
626 }
627 
628 ///
629 final class ArrayInitializer : BaseNode
630 {
631     override void accept(ASTVisitor visitor) const
632     {
633         mixin (visitIfNotNull!(arrayMemberInitializations));
634     }
635     mixin OpEquals;
636     /** */ size_t startLocation;
637     /** */ size_t endLocation;
638     /** */ ArrayMemberInitialization[] arrayMemberInitializations;
639 }
640 
641 ///
642 final class ArrayLiteral : BaseNode
643 {
644     override void accept(ASTVisitor visitor) const
645     {
646         mixin (visitIfNotNull!(argumentList));
647     }
648     mixin OpEquals;
649     /** */ ArgumentList argumentList;
650 }
651 
652 ///
653 final class ArrayMemberInitialization : BaseNode
654 {
655     override void accept(ASTVisitor visitor) const
656     {
657         mixin (visitIfNotNull!(assignExpression, nonVoidInitializer));
658     }
659     mixin OpEquals;
660     /** */ ExpressionNode assignExpression;
661     /** */ NonVoidInitializer nonVoidInitializer;
662 }
663 
664 ///
665 final class AsmAddExp : ExpressionNode
666 {
667     override void accept(ASTVisitor visitor) const
668     {
669         mixin (visitIfNotNull!(left, right));
670     }
671     mixin OpEquals;
672     /** */ IdType operator;
673     mixin BinaryExpressionBody;
674 }
675 
676 ///
677 final class AsmAndExp : ExpressionNode
678 {
679     override void accept(ASTVisitor visitor) const
680     {
681         mixin (visitIfNotNull!(left, right));
682     }
683     mixin OpEquals;
684     mixin BinaryExpressionBody;
685 }
686 
687 ///
688 final class AsmBrExp : ExpressionNode
689 {
690     override void accept(ASTVisitor visitor) const
691     {
692         mixin (visitIfNotNull!(asmBrExp, asmExp, asmUnaExp));
693     }
694     mixin OpEquals;
695     size_t line;
696     size_t column;
697     /** */ AsmBrExp asmBrExp;
698     /** */ ExpressionNode asmExp;
699     /** */ AsmUnaExp asmUnaExp;
700 }
701 
702 ///
703 final class AsmEqualExp : ExpressionNode
704 {
705     override void accept(ASTVisitor visitor) const
706     {
707         mixin (visitIfNotNull!(left, right));
708     }
709     mixin BinaryExpressionBody;
710     mixin OpEquals;
711     /** */ IdType operator;
712 }
713 
714 ///
715 final class AsmExp : ExpressionNode
716 {
717     override void accept(ASTVisitor visitor) const
718     {
719         mixin (visitIfNotNull!(left, middle, right));
720     }
721     mixin OpEquals;
722     /** */ ExpressionNode left;
723     /** */ ExpressionNode middle;
724     /** */ ExpressionNode right;
725 }
726 
727 ///
728 final class AsmInstruction : BaseNode
729 {
730     override void accept(ASTVisitor visitor) const
731     {
732         mixin (visitIfNotNull!(identifierOrIntegerOrOpcode, asmInstruction, operands));
733     }
734     mixin OpEquals;
735     /** */ Token identifierOrIntegerOrOpcode;
736     /** */ bool hasAlign;
737     /** */ bool isLabel;
738     /** */ AsmInstruction asmInstruction;
739     /** */ Operands operands;
740 }
741 
742 ///
743 final class AsmLogAndExp : ExpressionNode
744 {
745     override void accept(ASTVisitor visitor) const
746     {
747         mixin (visitIfNotNull!(left, right));
748     }
749     mixin BinaryExpressionBody;
750     mixin OpEquals;
751 }
752 
753 ///
754 final class AsmLogOrExp : ExpressionNode
755 {
756     override void accept(ASTVisitor visitor) const
757     {
758         mixin (visitIfNotNull!(left, right));
759     }
760     mixin BinaryExpressionBody;
761     mixin OpEquals;
762 }
763 
764 ///
765 final class AsmMulExp : ExpressionNode
766 {
767     override void accept(ASTVisitor visitor) const
768     {
769         mixin (visitIfNotNull!(left, right));
770     }
771     /** */ IdType operator;
772     mixin BinaryExpressionBody;
773     mixin OpEquals;
774 
775 }
776 
777 ///
778 final class AsmOrExp : ExpressionNode
779 {
780     override void accept(ASTVisitor visitor) const
781     {
782         mixin (visitIfNotNull!(left, right));
783     }
784     mixin BinaryExpressionBody;
785     mixin OpEquals;
786 }
787 
788 ///
789 final class AsmPrimaryExp : BaseNode
790 {
791     override void accept(ASTVisitor visitor) const
792     {
793         mixin (visitIfNotNull!(token, register, asmExp, identifierChain,
794             segmentOverrideSuffix));
795     }
796     /** */ ExpressionNode asmExp;
797     /** */ IdentifierChain identifierChain;
798     /** */ Register register;
799     /** */ ExpressionNode segmentOverrideSuffix;
800     /** */ Token token;
801     mixin OpEquals;
802 }
803 
804 ///
805 final class AsmRelExp : ExpressionNode
806 {
807     override void accept(ASTVisitor visitor) const
808     {
809         mixin (visitIfNotNull!(left, right));
810     }
811     mixin BinaryExpressionBody;
812     /** */ IdType operator;
813     mixin OpEquals;
814 }
815 
816 ///
817 final class AsmShiftExp : ExpressionNode
818 {
819     override void accept(ASTVisitor visitor) const
820     {
821         mixin (visitIfNotNull!(left, right));
822     }
823     mixin BinaryExpressionBody;
824     /** */ IdType operator;
825     mixin OpEquals;
826 }
827 
828 ///
829 final class AsmStatement : BaseNode
830 {
831     override void accept(ASTVisitor visitor) const
832     {
833         mixin (visitIfNotNull!(functionAttributes, asmInstructions, gccAsmInstructions));
834     }
835     /** */ AsmInstruction[] asmInstructions;
836     /** */ GccAsmInstruction[] gccAsmInstructions;
837     /** */ FunctionAttribute[] functionAttributes;
838     mixin OpEquals;
839 }
840 
841 ///
842 final class AsmTypePrefix : BaseNode
843 {
844     override void accept(ASTVisitor visitor) const
845     {
846         mixin (visitIfNotNull!(left, right));
847     }
848     /** */ Token left;
849     /** */ Token right;
850     mixin OpEquals;
851 }
852 
853 ///
854 final class AsmUnaExp : BaseNode
855 {
856     override void accept(ASTVisitor visitor) const
857     {
858         mixin (visitIfNotNull!(prefix, asmTypePrefix, asmExp, asmPrimaryExp, asmUnaExp));
859     }
860     /** */ AsmTypePrefix asmTypePrefix;
861     /** */ ExpressionNode asmExp;
862     /** */ Token prefix;
863     /** */ AsmPrimaryExp asmPrimaryExp;
864     /** */ AsmUnaExp asmUnaExp;
865     mixin OpEquals;
866 }
867 
868 ///
869 final class AsmXorExp : ExpressionNode
870 {
871     override void accept(ASTVisitor visitor) const
872     {
873         mixin (visitIfNotNull!(left, right));
874     }
875     mixin BinaryExpressionBody;
876     mixin OpEquals;
877 }
878 
879 ///
880 final class AssertArguments : BaseNode
881 {
882     override void accept(ASTVisitor visitor) const
883     {
884         mixin (visitIfNotNull!(assertion, messageParts));
885     }
886 
887     /** */ ExpressionNode assertion;
888     /** */ ExpressionNode[] messageParts;
889     mixin OpEquals;
890 
891     deprecated("use firstMessage or process all messageParts instead")
892     alias message = firstMessage;
893 
894     /// Returns `messageParts[0]` or `null` if no messageParts.
895     inout(ExpressionNode) firstMessage() inout nothrow pure @nogc @safe
896     {
897         return messageParts.length ? messageParts[0] : null;
898     }
899 }
900 
901 ///
902 final class AssertExpression : ExpressionNode
903 {
904     override void accept(ASTVisitor visitor) const
905     {
906         mixin (visitIfNotNull!(assertArguments));
907     }
908     /** */ size_t line;
909     /** */ size_t column;
910     /** */ AssertArguments assertArguments;
911     mixin OpEquals;
912 }
913 
914 ///
915 final class AssignExpression : ExpressionNode
916 {
917     override void accept(ASTVisitor visitor) const
918     {
919         mixin (visitIfNotNull!(ternaryExpression, expression));
920     }
921     /** */ ExpressionNode ternaryExpression;
922     /** */ ExpressionNode expression;
923     /** */ IdType operator;
924     /** */ size_t line;
925     /** */ size_t column;
926     mixin OpEquals;
927 }
928 
929 ///
930 final class AssocArrayLiteral : BaseNode
931 {
932     override void accept(ASTVisitor visitor) const
933     {
934         mixin (visitIfNotNull!(keyValuePairs));
935     }
936     /** */ KeyValuePairs keyValuePairs;
937     mixin OpEquals;
938 }
939 
940 ///
941 final class AtAttribute : BaseNode
942 {
943     override void accept(ASTVisitor visitor) const
944     {
945         mixin (visitIfNotNull!(templateInstance, argumentList));
946     }
947     /** */ ArgumentList argumentList;
948     /** */ TemplateInstance templateInstance;
949     /** */ Token identifier;
950     /** */ bool useParen;
951     /** */ size_t startLocation;
952     /** */ size_t endLocation;
953     mixin OpEquals;
954 }
955 
956 ///
957 final class Attribute : BaseNode
958 {
959     override void accept(ASTVisitor visitor) const
960     {
961         mixin (visitIfNotNull!(pragmaExpression, deprecated_, atAttribute,
962             alignAttribute, identifierChain, linkageAttribute));
963     }
964     /** */ PragmaExpression pragmaExpression;
965     /** */ Deprecated deprecated_;
966     /** */ AtAttribute atAttribute;
967     /** */ AlignAttribute alignAttribute;
968     /** */ LinkageAttribute linkageAttribute;
969     /** */ Token attribute;
970     /** */ IdentifierChain identifierChain;
971     mixin OpEquals;
972 }
973 
974 ///
975 final class AttributeDeclaration : BaseNode
976 {
977     override void accept(ASTVisitor visitor) const
978     {
979         mixin (visitIfNotNull!(attribute));
980     }
981     /** */ Attribute attribute;
982     /** */ size_t line;
983     mixin OpEquals;
984 }
985 
986 ///
987 final class AutoDeclaration : BaseNode
988 {
989     override void accept(ASTVisitor visitor) const
990     {
991         foreach (sc; storageClasses)
992             visitor.visit(sc);
993         foreach (part; parts)
994             visitor.visit(part);
995     }
996     /** */ AutoDeclarationPart[] parts;
997     /** */ StorageClass[] storageClasses;
998     /** */ string comment;
999     mixin OpEquals;
1000 }
1001 
1002 final class AutoDeclarationPart : BaseNode
1003 {
1004     override void accept(ASTVisitor visitor) const
1005     {
1006         if (templateParameters !is null)
1007             visitor.visit(templateParameters);
1008         visitor.visit(initializer);
1009     }
1010 
1011     /** */ Token identifier;
1012     /** */ Initializer initializer;
1013     /** */ TemplateParameters templateParameters;
1014 }
1015 
1016 ///
1017 final class BlockStatement : BaseNode
1018 {
1019     override void accept(ASTVisitor visitor) const
1020     {
1021         mixin (visitIfNotNull!(declarationsAndStatements));
1022     }
1023 
1024     /**
1025      * Byte position of the opening brace
1026      */
1027     size_t startLocation;
1028 
1029     /**
1030      * Byte position of the closing brace
1031      */
1032     size_t endLocation;
1033 
1034     /** */ DeclarationsAndStatements declarationsAndStatements;
1035     mixin OpEquals;
1036 }
1037 
1038 ///
1039 final class BreakStatement : BaseNode
1040 {
1041     override void accept(ASTVisitor visitor) const
1042     {
1043         mixin (visitIfNotNull!(label));
1044     }
1045     /** */ Token label;
1046     mixin OpEquals;
1047 }
1048 
1049 ///
1050 final class BaseClass : BaseNode
1051 {
1052     override void accept(ASTVisitor visitor) const
1053     {
1054         mixin (visitIfNotNull!(type2));
1055     }
1056     /** */ Type2 type2;
1057     mixin OpEquals;
1058 }
1059 
1060 ///
1061 final class BaseClassList : BaseNode
1062 {
1063     override void accept(ASTVisitor visitor) const
1064     {
1065         mixin (visitIfNotNull!(items));
1066     }
1067     /** */ BaseClass[] items;
1068     mixin OpEquals;
1069 }
1070 
1071 ///
1072 final class CaseRangeStatement : BaseNode
1073 {
1074     override void accept(ASTVisitor visitor) const
1075     {
1076         mixin (visitIfNotNull!(low, high, declarationsAndStatements));
1077     }
1078     /** */ ExpressionNode low;
1079     /** */ ExpressionNode high;
1080     /** */ DeclarationsAndStatements declarationsAndStatements;
1081     /** */ size_t colonLocation;
1082     mixin OpEquals;
1083 }
1084 
1085 ///
1086 final class CaseStatement: BaseNode
1087 {
1088     override void accept(ASTVisitor visitor) const
1089     {
1090         mixin (visitIfNotNull!(argumentList, declarationsAndStatements));
1091     }
1092     /** */ ArgumentList argumentList;
1093     /** */ DeclarationsAndStatements declarationsAndStatements;
1094     /** */ size_t colonLocation;
1095     mixin OpEquals;
1096 }
1097 
1098 ///
1099 final class CastExpression: BaseNode
1100 {
1101     override void accept(ASTVisitor visitor) const
1102     {
1103         mixin (visitIfNotNull!(type, castQualifier, unaryExpression));
1104     }
1105     /** */ Type type;
1106     /** */ CastQualifier castQualifier;
1107     /** */ UnaryExpression unaryExpression;
1108     mixin OpEquals;
1109 }
1110 
1111 ///
1112 final class CastQualifier: BaseNode
1113 {
1114     override void accept(ASTVisitor visitor) const
1115     {
1116         mixin (visitIfNotNull!(first, second));
1117     }
1118     /** */ Token first;
1119     /** */ Token second;
1120     mixin OpEquals;
1121 }
1122 
1123 ///
1124 final class Catches: BaseNode
1125 {
1126     override void accept(ASTVisitor visitor) const
1127     {
1128         mixin (visitIfNotNull!(catches, lastCatch));
1129     }
1130     /** */ Catch[] catches;
1131     /** */ LastCatch lastCatch;
1132     mixin OpEquals;
1133 }
1134 
1135 ///
1136 final class Catch: BaseNode
1137 {
1138     override void accept(ASTVisitor visitor) const
1139     {
1140         mixin (visitIfNotNull!(type, identifier, declarationOrStatement));
1141     }
1142     /** */ Type type;
1143     /** */ Token identifier;
1144     /** */ DeclarationOrStatement declarationOrStatement;
1145     mixin OpEquals;
1146 }
1147 
1148 ///
1149 final class ClassDeclaration: BaseNode
1150 {
1151     override void accept(ASTVisitor visitor) const
1152     {
1153         mixin (visitIfNotNull!(templateParameters, constraint, baseClassList,
1154             structBody));
1155     }
1156 
1157     /** */ Token name;
1158     /** */ TemplateParameters templateParameters;
1159     /** */ Constraint constraint;
1160     /** */ BaseClassList baseClassList;
1161     /** */ StructBody structBody;
1162     /** */ string comment;
1163     mixin OpEquals;
1164 }
1165 
1166 ///
1167 final class CmpExpression : ExpressionNode
1168 {
1169     override void accept(ASTVisitor visitor) const
1170     {
1171         mixin (visitIfNotNull!(shiftExpression, equalExpression,
1172             identityExpression, relExpression, inExpression));
1173     }
1174     /** */ ExpressionNode shiftExpression;
1175     /** */ ExpressionNode equalExpression;
1176     /** */ ExpressionNode identityExpression;
1177     /** */ ExpressionNode relExpression;
1178     /** */ ExpressionNode inExpression;
1179     mixin OpEquals;
1180 }
1181 
1182 ///
1183 final class CompileCondition : BaseNode
1184 {
1185     override void accept(ASTVisitor visitor) const
1186     {
1187         mixin (visitIfNotNull!(versionCondition, debugCondition, staticIfCondition));
1188     }
1189     /** */ VersionCondition versionCondition;
1190     /** */ DebugCondition debugCondition;
1191     /** */ StaticIfCondition staticIfCondition;
1192     mixin OpEquals;
1193 }
1194 
1195 ///
1196 final class ConditionalDeclaration : BaseNode
1197 {
1198     override void accept(ASTVisitor visitor) const
1199     {
1200         mixin (visitIfNotNull!(compileCondition, trueDeclarations, falseDeclarations));
1201     }
1202     /** */ CompileCondition compileCondition;
1203     /** */ Declaration[] trueDeclarations;
1204     /** */ Declaration[] falseDeclarations;
1205     /** */ bool hasElse;
1206     /** */ DeclarationListStyle trueStyle;
1207     /** */ DeclarationListStyle falseStyle;
1208     mixin OpEquals;
1209 }
1210 
1211 ///
1212 final class ConditionalStatement : BaseNode
1213 {
1214     override void accept(ASTVisitor visitor) const
1215     {
1216         mixin (visitIfNotNull!(compileCondition, trueStatement, falseStatement));
1217     }
1218     /** */ CompileCondition compileCondition;
1219     /** */ DeclarationOrStatement trueStatement;
1220     /** */ DeclarationOrStatement falseStatement;
1221     mixin OpEquals;
1222 }
1223 
1224 ///
1225 final class Constraint : BaseNode
1226 {
1227     override void accept(ASTVisitor visitor) const
1228     {
1229         mixin (visitIfNotNull!(expression));
1230     }
1231     /** */ Expression expression;
1232     /** */ size_t location;
1233     mixin OpEquals;
1234 }
1235 
1236 ///
1237 final class Constructor : BaseNode
1238 {
1239     override void accept(ASTVisitor visitor) const
1240     {
1241         mixin (visitIfNotNull!(parameters, templateParameters, constraint,
1242             memberFunctionAttributes, functionBody));
1243     }
1244     /** */ Parameters parameters;
1245     /** */ FunctionBody functionBody;
1246     /** */ Constraint constraint;
1247     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
1248     /** */ TemplateParameters templateParameters;
1249     /** */ size_t location;
1250     /** */ size_t line;
1251     /** */ size_t column;
1252     /** */ string comment;
1253     mixin OpEquals;
1254 }
1255 
1256 ///
1257 final class ContinueStatement : BaseNode
1258 {
1259     override void accept(ASTVisitor visitor) const
1260     {
1261         mixin (visitIfNotNull!(label));
1262     }
1263     /** */ Token label;
1264     mixin OpEquals;
1265 }
1266 
1267 ///
1268 final class DebugCondition : BaseNode
1269 {
1270     override void accept(ASTVisitor visitor) const
1271     {
1272         mixin (visitIfNotNull!(identifierOrInteger));
1273     }
1274     /** */ size_t debugIndex;
1275     /** */ Token identifierOrInteger;
1276     mixin OpEquals;
1277 }
1278 
1279 ///
1280 final class DebugSpecification : BaseNode
1281 {
1282     override void accept(ASTVisitor visitor) const
1283     {
1284         mixin (visitIfNotNull!(identifierOrInteger));
1285     }
1286     /** */ Token identifierOrInteger;
1287     mixin OpEquals;
1288 }
1289 
1290 ///
1291 final class Declaration : BaseNode
1292 {
1293 
1294     override void accept(ASTVisitor visitor) const
1295     {
1296 
1297         foreach (attr; attributes)
1298             visitor.visit(attr);
1299         foreach (dec; declarations)
1300             visitor.visit(dec);
1301         foreach (Type; DeclarationTypes)
1302         {
1303             const(Type)* value = storage.peek!Type;
1304             if (value !is null)
1305             {
1306                 static if (isArray!Type)
1307                     foreach (item; *(cast(Type*) value))
1308                         visitor.visit(item);
1309                 else if (*value !is null)
1310                     visitor.visit(*(cast(Type*) value));
1311             }
1312         }
1313     }
1314 
1315     private import std.variant:Algebraic;
1316     private import std.typetuple:TypeTuple;
1317 
1318     alias DeclarationTypes = TypeTuple!(AliasDeclaration, AliasAssign, AliasThisDeclaration,
1319         AnonymousEnumDeclaration, AttributeDeclaration,
1320         ClassDeclaration, ConditionalDeclaration, Constructor, DebugSpecification,
1321         Destructor, EnumDeclaration, EponymousTemplateDeclaration,
1322         FunctionDeclaration, ImportDeclaration, InterfaceDeclaration, Invariant,
1323         MixinDeclaration, MixinTemplateDeclaration, Postblit, PragmaDeclaration,
1324         SharedStaticConstructor, SharedStaticDestructor, StaticAssertDeclaration,
1325         StaticConstructor, StaticDestructor, StructDeclaration,
1326         TemplateDeclaration, UnionDeclaration, Unittest, VariableDeclaration,
1327         VersionSpecification, StaticForeachDeclaration);
1328 
1329     private Algebraic!(DeclarationTypes) storage;
1330 
1331     private static string generateProperty(string type, string name)
1332     {
1333         return "const(" ~ type ~ ") " ~ name ~ "() const @property { auto p = storage.peek!" ~ type ~ "; return p is null? null : *p;}\n"
1334             ~ "const(" ~ type ~ ") " ~ name ~ "(" ~ type ~ " node) @property { storage = node; return node; }";
1335     }
1336 
1337     /** */ Attribute[] attributes;
1338     /** */ Declaration[] declarations;
1339 
1340     mixin(generateProperty("AliasDeclaration", "aliasDeclaration"));
1341     mixin(generateProperty("AliasAssign", "aliasAssign"));
1342     mixin(generateProperty("AliasThisDeclaration", "aliasThisDeclaration"));
1343     mixin(generateProperty("AnonymousEnumDeclaration", "anonymousEnumDeclaration"));
1344     mixin(generateProperty("AttributeDeclaration", "attributeDeclaration"));
1345     mixin(generateProperty("ClassDeclaration", "classDeclaration"));
1346     mixin(generateProperty("ConditionalDeclaration", "conditionalDeclaration"));
1347     mixin(generateProperty("Constructor", "constructor"));
1348     mixin(generateProperty("DebugSpecification", "debugSpecification"));
1349     mixin(generateProperty("Destructor", "destructor"));
1350     mixin(generateProperty("EnumDeclaration", "enumDeclaration"));
1351     mixin(generateProperty("EponymousTemplateDeclaration", "eponymousTemplateDeclaration"));
1352     mixin(generateProperty("FunctionDeclaration", "functionDeclaration"));
1353     mixin(generateProperty("ImportDeclaration", "importDeclaration"));
1354     mixin(generateProperty("InterfaceDeclaration", "interfaceDeclaration"));
1355     mixin(generateProperty("Invariant", "invariant_"));
1356     mixin(generateProperty("MixinDeclaration", "mixinDeclaration"));
1357     mixin(generateProperty("MixinTemplateDeclaration", "mixinTemplateDeclaration"));
1358     mixin(generateProperty("Postblit", "postblit"));
1359     mixin(generateProperty("PragmaDeclaration", "pragmaDeclaration"));
1360     mixin(generateProperty("SharedStaticConstructor", "sharedStaticConstructor"));
1361     mixin(generateProperty("SharedStaticDestructor", "sharedStaticDestructor"));
1362     mixin(generateProperty("StaticAssertDeclaration", "staticAssertDeclaration"));
1363     mixin(generateProperty("StaticConstructor", "staticConstructor"));
1364     mixin(generateProperty("StaticDestructor", "staticDestructor"));
1365     mixin(generateProperty("StructDeclaration", "structDeclaration"));
1366     mixin(generateProperty("TemplateDeclaration", "templateDeclaration"));
1367     mixin(generateProperty("UnionDeclaration", "unionDeclaration"));
1368     mixin(generateProperty("Unittest", "unittest_"));
1369     mixin(generateProperty("VariableDeclaration", "variableDeclaration"));
1370     mixin(generateProperty("VersionSpecification", "versionSpecification"));
1371     mixin(generateProperty("StaticForeachDeclaration", "staticForeachDeclaration"));
1372 
1373     override bool opEquals(Object other) const
1374     {
1375         auto otherDeclaration = cast(Declaration) other;
1376         if (otherDeclaration is null)
1377             return false;
1378         return attributes == otherDeclaration.attributes
1379             && declarations == otherDeclaration.declarations
1380             && storage == otherDeclaration.storage;
1381     }
1382 }
1383 
1384 ///
1385 final class DeclarationsAndStatements : BaseNode
1386 {
1387     override void accept(ASTVisitor visitor) const
1388     {
1389         mixin (visitIfNotNull!(declarationsAndStatements));
1390     }
1391 
1392     /** */ DeclarationOrStatement[] declarationsAndStatements;
1393     mixin OpEquals;
1394 }
1395 
1396 ///
1397 final class DeclarationOrStatement : BaseNode
1398 {
1399     override void accept(ASTVisitor visitor) const
1400     {
1401         mixin (visitIfNotNull!(declaration, statement));
1402     }
1403 
1404     /** */ Declaration declaration;
1405     /** */ Statement statement;
1406     /** */ size_t startLocation;
1407     /** */ size_t endLocation;
1408     mixin OpEquals;
1409 }
1410 
1411 ///
1412 final class Declarator : BaseNode
1413 {
1414     override void accept(ASTVisitor visitor) const
1415     {
1416         mixin (visitIfNotNull!(templateParameters, bitfieldWidth, initializer));
1417     }
1418     /** */ Token name;
1419     /** */ TemplateParameters templateParameters;
1420     /** */ BitfieldWidth bitfieldWidth;
1421     /** */ Initializer initializer;
1422     /** */ TypeSuffix[] cstyle;
1423     /** */ string comment;
1424     mixin OpEquals;
1425 }
1426 
1427 ///
1428 final class BitfieldWidth : BaseNode
1429 {
1430     override void accept(ASTVisitor visitor) const
1431     {
1432         mixin (visitIfNotNull!(expression));
1433     }
1434     /** */ ExpressionNode expression;
1435     mixin OpEquals;
1436 }
1437 
1438 ///
1439 final class DeclaratorIdentifierList : BaseNode
1440 {
1441     override void accept(ASTVisitor visitor) const
1442     {
1443         mixin (visitIfNotNull!(identifiers));
1444     }
1445     /** */ Token[] identifiers;
1446     mixin OpEquals;
1447 }
1448 
1449 ///
1450 final class DefaultStatement : BaseNode
1451 {
1452     override void accept(ASTVisitor visitor) const
1453     {
1454         mixin (visitIfNotNull!(declarationsAndStatements));
1455     }
1456     /** */ DeclarationsAndStatements declarationsAndStatements;
1457     /** */ size_t colonLocation;
1458     mixin OpEquals;
1459 }
1460 
1461 ///
1462 final class DeleteExpression : ExpressionNode
1463 {
1464     override void accept(ASTVisitor visitor) const
1465     {
1466         mixin (visitIfNotNull!(unaryExpression));
1467     }
1468     /** */ UnaryExpression unaryExpression;
1469     /** */ size_t line;
1470     /** */ size_t column;
1471     mixin OpEquals;
1472 }
1473 
1474 ///
1475 final class DeleteStatement : BaseNode
1476 {
1477     override void accept(ASTVisitor visitor) const
1478     {
1479         mixin (visitIfNotNull!(deleteExpression));
1480     }
1481     /** */ DeleteExpression deleteExpression;
1482     mixin OpEquals;
1483 }
1484 
1485 ///
1486 final class Deprecated : BaseNode
1487 {
1488     override void accept(ASTVisitor visitor) const
1489     {
1490         mixin (visitIfNotNull!(assignExpression));
1491     }
1492     /** */ ExpressionNode assignExpression;
1493     mixin OpEquals;
1494 }
1495 
1496 ///
1497 final class Destructor : BaseNode
1498 {
1499     override void accept(ASTVisitor visitor) const
1500     {
1501         mixin (visitIfNotNull!(memberFunctionAttributes, functionBody));
1502     }
1503     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
1504     /** */ FunctionBody functionBody;
1505     /** */ size_t line;
1506     /** */ size_t column;
1507     /** */ size_t index;
1508     /** */ string comment;
1509     mixin OpEquals;
1510 }
1511 
1512 ///
1513 final class DoStatement : BaseNode
1514 {
1515     override void accept(ASTVisitor visitor) const
1516     {
1517         mixin (visitIfNotNull!(expression, statementNoCaseNoDefault));
1518     }
1519     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
1520     /** */ Expression expression;
1521     mixin OpEquals;
1522 }
1523 
1524 ///
1525 final class EnumBody : BaseNode
1526 {
1527     override void accept(ASTVisitor visitor) const
1528     {
1529         mixin (visitIfNotNull!(enumMembers));
1530     }
1531     /** */ EnumMember[] enumMembers;
1532 
1533     /**
1534      * Byte position of the opening brace
1535      */
1536     size_t startLocation;
1537 
1538     /**
1539      * Byte position of the closing brace
1540      */
1541     size_t endLocation;
1542     mixin OpEquals;
1543 }
1544 
1545 ///
1546 final class EnumDeclaration : BaseNode
1547 {
1548     override void accept(ASTVisitor visitor) const
1549     {
1550         mixin (visitIfNotNull!(type, enumBody));
1551     }
1552     /** */ Token name;
1553     /** */ Type type;
1554     /** */ EnumBody enumBody;
1555     /** */ string comment;
1556     mixin OpEquals;
1557 }
1558 
1559 final class EnumMemberAttribute : BaseNode
1560 {
1561     override void accept(ASTVisitor visitor) const
1562     {
1563         mixin (visitIfNotNull!(deprecated_, atAttribute));
1564     }
1565     /** */ Deprecated deprecated_;
1566     /** */ AtAttribute atAttribute;
1567     mixin OpEquals;
1568 }
1569 
1570 ///
1571 final class EnumMember : BaseNode
1572 {
1573     override void accept(ASTVisitor visitor) const
1574     {
1575         mixin (visitIfNotNull!(enumMemberAttributes, name, type, assignExpression));
1576     }
1577     /** */ EnumMemberAttribute[] enumMemberAttributes;
1578     /** */ Token name;
1579     /** */ Type type;
1580     /** */ ExpressionNode assignExpression;
1581     /** */ string comment;
1582     mixin OpEquals;
1583 }
1584 
1585 ///
1586 final class EponymousTemplateDeclaration : BaseNode
1587 {
1588     override void accept(ASTVisitor visitor) const
1589     {
1590         mixin (visitIfNotNull!(name, templateParameters, assignExpression));
1591     }
1592     /** */ Token name;
1593     /** */ TemplateParameters templateParameters;
1594     /** */ ExpressionNode assignExpression;
1595     /** */ Type type;
1596     /** */ string comment;
1597     mixin OpEquals;
1598 }
1599 
1600 ///
1601 final class EqualExpression : ExpressionNode
1602 {
1603     override void accept(ASTVisitor visitor) const
1604     {
1605         mixin (visitIfNotNull!(left, right));
1606     }
1607     /** */ IdType operator;
1608     mixin BinaryExpressionBody;
1609     mixin OpEquals;
1610 }
1611 
1612 ///
1613 final class Expression : ExpressionNode
1614 {
1615     override void accept(ASTVisitor visitor) const
1616     {
1617         mixin (visitIfNotNull!(items));
1618     }
1619     /** */ ExpressionNode[] items;
1620     /** */ size_t line;
1621     /** */ size_t column;
1622     mixin OpEquals;
1623 }
1624 
1625 ///
1626 final class ExpressionStatement : BaseNode
1627 {
1628     override void accept(ASTVisitor visitor) const
1629     {
1630         mixin (visitIfNotNull!(expression));
1631     }
1632     /** */ Expression expression;
1633     mixin OpEquals;
1634 }
1635 
1636 ///
1637 final class FinalSwitchStatement : BaseNode
1638 {
1639     override void accept(ASTVisitor visitor) const
1640     {
1641         mixin (visitIfNotNull!(switchStatement));
1642     }
1643     /** */ SwitchStatement switchStatement;
1644     mixin OpEquals;
1645 }
1646 
1647 ///
1648 final class Finally : BaseNode
1649 {
1650     override void accept(ASTVisitor visitor) const
1651     {
1652         mixin (visitIfNotNull!(declarationOrStatement));
1653     }
1654     /** */ DeclarationOrStatement declarationOrStatement;
1655     mixin OpEquals;
1656 }
1657 
1658 ///
1659 final class ForStatement : BaseNode
1660 {
1661     override void accept(ASTVisitor visitor) const
1662     {
1663         mixin (visitIfNotNull!(initialization, test, increment,
1664             declarationOrStatement));
1665     }
1666     /** */ DeclarationOrStatement initialization;
1667     /** */ Expression test;
1668     /** */ Expression increment;
1669     /** */ DeclarationOrStatement declarationOrStatement;
1670     /** */ size_t startIndex;
1671     mixin OpEquals;
1672 }
1673 
1674 
1675 ///
1676 final class Foreach(bool declOnly) : BaseNode
1677 {
1678     override void accept(ASTVisitor visitor) const
1679     {
1680         mixin (visitIfNotNull!(foreachType, foreachTypeList, low, high));
1681         static if (declOnly)
1682             mixin (visitIfNotNull!(declarations));
1683         else
1684             mixin (visitIfNotNull!(declarationOrStatement));
1685     }
1686     /** */ IdType type;
1687     /** */ ForeachTypeList foreachTypeList;
1688     /** */ ForeachType foreachType;
1689     /** */ Expression low;
1690     /** */ Expression high;
1691     /** */ size_t startIndex;
1692     static if (declOnly)
1693     {
1694         /** */ Declaration[] declarations;
1695         /** */ DeclarationListStyle style;
1696     }
1697     else
1698     {
1699         /** */ DeclarationOrStatement declarationOrStatement;
1700     }
1701     mixin OpEquals;
1702 }
1703 
1704 ///
1705 alias StaticForeachDeclaration = Foreach!true;
1706 
1707 ///
1708 alias ForeachStatement = Foreach!false;
1709 
1710 ///
1711 final class StaticForeachStatement : BaseNode
1712 {
1713     override void accept(ASTVisitor visitor) const
1714     {
1715         mixin (visitIfNotNull!(foreachStatement));
1716     }
1717     /** */ ForeachStatement foreachStatement;
1718     mixin OpEquals;
1719 }
1720 
1721 ///
1722 final class ForeachType : BaseNode
1723 {
1724     override void accept(ASTVisitor visitor) const
1725     {
1726         mixin (visitIfNotNull!(type, identifier));
1727     }
1728     /** */ bool isAlias;
1729     /** */ bool isEnum;
1730     /** */ bool isRef;
1731     /** */ bool isScope;
1732     /** */ IdType[] typeConstructors;
1733     /** */ Type type;
1734     /** */ Token identifier;
1735     mixin OpEquals;
1736 }
1737 
1738 ///
1739 final class ForeachTypeList : BaseNode
1740 {
1741     override void accept(ASTVisitor visitor) const
1742     {
1743         mixin (visitIfNotNull!(items));
1744     }
1745     /** */ ForeachType[] items;
1746     mixin OpEquals;
1747 }
1748 
1749 ///
1750 final class FunctionAttribute : BaseNode
1751 {
1752     override void accept(ASTVisitor visitor) const
1753     {
1754         mixin (visitIfNotNull!(token, atAttribute));
1755     }
1756     /** */ Token token;
1757     /** */ AtAttribute atAttribute;
1758     mixin OpEquals;
1759 }
1760 
1761 ///
1762 final class FunctionBody : BaseNode
1763 {
1764     override void accept(ASTVisitor visitor) const
1765     {
1766         mixin (visitIfNotNull!(specifiedFunctionBody, missingFunctionBody, shortenedFunctionBody));
1767     }
1768 
1769     /** */ size_t endLocation;
1770     /** */ SpecifiedFunctionBody specifiedFunctionBody;
1771     /** */ MissingFunctionBody missingFunctionBody;
1772     /** */ ShortenedFunctionBody shortenedFunctionBody;
1773     mixin OpEquals;
1774 }
1775 
1776 ///
1777 final class FunctionCallExpression : ExpressionNode
1778 {
1779     override void accept(ASTVisitor visitor) const
1780     {
1781         mixin (visitIfNotNull!(type, unaryExpression, templateArguments, arguments));
1782     }
1783     /** */ Type type;
1784     /** */ UnaryExpression unaryExpression;
1785     /** */ TemplateArguments templateArguments;
1786     /** */ Arguments arguments;
1787     mixin OpEquals;
1788 }
1789 
1790 ///
1791 final class FunctionContract : BaseNode
1792 {
1793     override void accept(ASTVisitor visitor) const
1794     {
1795         mixin (visitIfNotNull!(inOutContractExpression, inOutStatement));
1796     }
1797     /** */ InOutContractExpression inOutContractExpression;
1798     /** */ InOutStatement inOutStatement;
1799     mixin OpEquals;
1800 }
1801 
1802 ///
1803 final class FunctionDeclaration : BaseNode
1804 {
1805     override void accept(ASTVisitor visitor) const
1806     {
1807         mixin (visitIfNotNull!(attributes, storageClasses, returnType, parameters,
1808             templateParameters, constraint, memberFunctionAttributes,
1809             functionBody));
1810     }
1811     /** */ bool hasAuto;
1812     /** */ bool hasRef;
1813     /** */ Type returnType;
1814     /** */ Token name;
1815     /** */ TemplateParameters templateParameters;
1816     /** */ Parameters parameters;
1817     /** */ Constraint constraint;
1818     /** */ FunctionBody functionBody;
1819     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
1820     /** */ string comment;
1821     /** */ Attribute[] attributes;
1822     /** */ StorageClass[] storageClasses;
1823     mixin OpEquals;
1824 }
1825 
1826 ///
1827 final class FunctionLiteralExpression : ExpressionNode
1828 {
1829     override void accept(ASTVisitor visitor) const
1830     {
1831         mixin (visitIfNotNull!(returnType, parameters, functionAttributes,
1832                 memberFunctionAttributes, specifiedFunctionBody, assignExpression));
1833     }
1834     /** */ ExpressionNode assignExpression;
1835     /** */ FunctionAttribute[] functionAttributes;
1836     /** */ SpecifiedFunctionBody specifiedFunctionBody;
1837     /** */ IdType functionOrDelegate;
1838     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
1839     /** */ Parameters parameters;
1840     /** */ Token identifier;
1841     /** */ Type returnType;
1842     /** */ ReturnRefType returnRefType;
1843     /** */ size_t line;
1844     /** */ size_t column;
1845     mixin OpEquals;
1846 
1847     deprecated("Use returnRefType") bool isReturnRef() const
1848     {
1849         return returnRefType == ReturnRefType.ref_
1850             || returnRefType == ReturnRefType.autoRef;
1851     }
1852 }
1853 
1854 ///
1855 enum ReturnRefType : ubyte
1856 {
1857     noRef = 0,
1858     ref_ = 1,
1859     autoRef = 2
1860 }
1861 
1862 ///
1863 final class GccAsmInstruction : BaseNode
1864 {
1865     override void accept(ASTVisitor visitor) const
1866     {
1867         mixin (visitIfNotNull!(assemblerTemplate, inputOperands, outputOperands, registers, gotos));
1868     }
1869 
1870     /** */ Expression assemblerTemplate;
1871     /** */ GccAsmOperandList inputOperands;
1872     /** */ GccAsmOperandList outputOperands;
1873     /** */ StringLiteralList registers;
1874     /** */ DeclaratorIdentifierList gotos;
1875     mixin OpEquals;
1876 }
1877 
1878 ///
1879 final class GccAsmOperand : BaseNode
1880 {
1881     override void accept(ASTVisitor visitor) const
1882     {
1883         mixin (visitIfNotNull!(expression, constraint, symbolicName));
1884     }
1885 
1886     /** */ Token symbolicName;
1887     /** */ Token constraint;
1888     /** */ ExpressionNode expression;
1889     mixin OpEquals;
1890 }
1891 
1892 ///
1893 final class GccAsmOperandList : BaseNode
1894 {
1895     override void accept(ASTVisitor visitor) const
1896     {
1897         mixin (visitIfNotNull!(items));
1898     }
1899 
1900     /** */ GccAsmOperand[] items;
1901     mixin OpEquals;
1902 }
1903 
1904 ///
1905 final class GotoStatement : BaseNode
1906 {
1907     override void accept(ASTVisitor visitor) const
1908     {
1909         mixin (visitIfNotNull!(label, expression));
1910     }
1911     /** */ Expression expression;
1912     /** */ Token label;
1913     mixin OpEquals;
1914 }
1915 
1916 ///
1917 final class IdentifierChain : BaseNode
1918 {
1919     override void accept(ASTVisitor visitor) const
1920     {
1921         mixin (visitIfNotNull!(identifiers));
1922     }
1923     /** */ Token[] identifiers;
1924     mixin OpEquals;
1925 }
1926 
1927 ///
1928 final class TypeIdentifierPart : BaseNode
1929 {
1930     override void accept(ASTVisitor visitor) const
1931     {
1932         mixin (visitIfNotNull!(identifierOrTemplateInstance, typeIdentifierPart,
1933             indexer));
1934     }
1935     /** */ bool dot;
1936     /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance;
1937     /** */ TypeIdentifierPart typeIdentifierPart ;
1938     /** */ ExpressionNode indexer;
1939     mixin OpEquals;
1940 }
1941 
1942 ///
1943 final class IdentifierOrTemplateChain : BaseNode
1944 {
1945     override void accept(ASTVisitor visitor) const
1946     {
1947         mixin (visitIfNotNull!(identifiersOrTemplateInstances));
1948     }
1949 
1950     /** */ IdentifierOrTemplateInstance[] identifiersOrTemplateInstances;
1951     mixin OpEquals;
1952 }
1953 
1954 ///
1955 final class IdentifierOrTemplateInstance : BaseNode
1956 {
1957     override void accept(ASTVisitor visitor) const
1958     {
1959         mixin (visitIfNotNull!(identifier, templateInstance));
1960     }
1961 
1962     /** */ Token identifier;
1963     /** */ TemplateInstance templateInstance;
1964     mixin OpEquals;
1965 }
1966 
1967 ///
1968 final class IdentityExpression : ExpressionNode
1969 {
1970     override void accept(ASTVisitor visitor) const
1971     {
1972         mixin (visitIfNotNull!(left, right));
1973     }
1974     /** */ bool negated;
1975     mixin BinaryExpressionBody;
1976     mixin OpEquals;
1977 }
1978 
1979 ///
1980 final class IfStatement : BaseNode
1981 {
1982     override void accept(ASTVisitor visitor) const
1983     {
1984         mixin (visitIfNotNull!(condition, thenStatement, elseStatement));
1985     }
1986     /** */ IfCondition condition;
1987     /** */ DeclarationOrStatement thenStatement;
1988     /** */ DeclarationOrStatement elseStatement;
1989     /** */ size_t startIndex;
1990     /** */ size_t line;
1991     /** */ size_t column;
1992     mixin OpEquals;
1993 
1994     deprecated("use condition.typeCtors") inout(IdType[]) typeCtors() inout @property
1995     {
1996         if (!condition)
1997             return null;
1998         return condition.typeCtors;
1999     }
2000 
2001     deprecated("use condition.type") inout(Type) type() inout @property
2002     {
2003         if (!condition)
2004             return null;
2005         return condition.type;
2006     }
2007 
2008     deprecated("use condition.identifier") inout(Token) identifier() inout @property
2009     {
2010         if (!condition)
2011             return Token.init;
2012         return condition.identifier;
2013     }
2014 
2015     deprecated("use condition.expression") inout(Expression) expression() inout @property
2016     {
2017         if (!condition)
2018             return null;
2019         return condition.expression;
2020     }
2021 }
2022 
2023 /**
2024 In an if (or while) condition this represents:
2025 ```
2026 if (auto x = readln)
2027     ^^^^^^^^^^^^^^^
2028 
2029 if (a == b || c == d)
2030     ^^^^^^^^^^^^^^^^
2031 ```
2032 */
2033 final class IfCondition : BaseNode
2034 {
2035     override void accept(ASTVisitor visitor) const
2036     {
2037         mixin (visitIfNotNull!(type, identifier, expression));
2038     }
2039     /// In an assignment-condition, these are the optional type constructors
2040     IdType[] typeCtors;
2041     /// In an assignment-condition, this is the optional explicit type
2042     Type type;
2043     /// In an assignment-condition, in `if (auto x = ...)` this is the `x`
2044     Token identifier;
2045     /**
2046     In an assignment-condition, this is true if `scope` is used to construct
2047     the variable.
2048     */
2049     bool scope_;
2050     /**
2051     In an assignment-condition, this is the part after the equals sign.
2052     Otherwise this is any other expression that is evaluated to be a boolean.
2053     (e.g. UnaryExpression, AndAndExpression, CmpExpression, etc.)
2054     */
2055     Expression expression;
2056     mixin OpEquals;
2057 }
2058 
2059 ///
2060 final class ImportBind : BaseNode
2061 {
2062     override void accept(ASTVisitor visitor) const
2063     {
2064         mixin (visitIfNotNull!(left, right));
2065     }
2066     /** */ Token left;
2067     /** */ Token right;
2068     mixin OpEquals;
2069 }
2070 
2071 ///
2072 final class ImportBindings : BaseNode
2073 {
2074     override void accept(ASTVisitor visitor) const
2075     {
2076         mixin (visitIfNotNull!(singleImport, importBinds));
2077     }
2078     /** */ SingleImport singleImport;
2079     /** */ ImportBind[] importBinds;
2080     mixin OpEquals;
2081 }
2082 
2083 ///
2084 final class ImportDeclaration : BaseNode
2085 {
2086     override void accept(ASTVisitor visitor) const
2087     {
2088         mixin (visitIfNotNull!(singleImports, importBindings));
2089     }
2090     /** */ SingleImport[] singleImports;
2091     /** */ ImportBindings importBindings;
2092     /** */ size_t startIndex;
2093     /** */ size_t endIndex;
2094     mixin OpEquals;
2095 }
2096 
2097 ///
2098 final class ImportExpression : ExpressionNode
2099 {
2100     override void accept(ASTVisitor visitor) const
2101     {
2102         mixin (visitIfNotNull!(assignExpression));
2103     }
2104     /** */ ExpressionNode assignExpression;
2105     mixin OpEquals;
2106 }
2107 
2108 ///
2109 final class Index : BaseNode
2110 {
2111     override void accept(ASTVisitor visitor) const
2112     {
2113         mixin (visitIfNotNull!(low, high));
2114     }
2115     /** */ ExpressionNode low;
2116     /** */ ExpressionNode high;
2117     mixin OpEquals;
2118 }
2119 
2120 ///
2121 final class IndexExpression : ExpressionNode
2122 {
2123     override void accept(ASTVisitor visitor) const
2124     {
2125         mixin (visitIfNotNull!(unaryExpression, indexes));
2126     }
2127     /** */ UnaryExpression unaryExpression;
2128     /** */ Index[] indexes;
2129     mixin OpEquals;
2130 }
2131 
2132 ///
2133 final class InContractExpression : BaseNode
2134 {
2135     override void accept(ASTVisitor visitor) const
2136     {
2137         mixin (visitIfNotNull!(assertArguments));
2138     }
2139     /** */ size_t inTokenLocation;
2140     /** */ AssertArguments assertArguments;
2141     mixin OpEquals;
2142 }
2143 
2144 ///
2145 final class InExpression : ExpressionNode
2146 {
2147     override void accept(ASTVisitor visitor) const
2148     {
2149         mixin (visitIfNotNull!(left, right));
2150     }
2151     mixin BinaryExpressionBody;
2152     bool negated;
2153     mixin OpEquals;
2154 }
2155 
2156 ///
2157 final class InOutContractExpression : BaseNode
2158 {
2159     override void accept(ASTVisitor visitor) const
2160     {
2161         mixin (visitIfNotNull!(inContractExpression, outContractExpression));
2162     }
2163     /** */ InContractExpression inContractExpression;
2164     /** */ OutContractExpression outContractExpression;
2165     mixin OpEquals;
2166 }
2167 
2168 ///
2169 final class InOutStatement : BaseNode
2170 {
2171     override void accept(ASTVisitor visitor) const
2172     {
2173         mixin (visitIfNotNull!(inStatement, outStatement));
2174     }
2175     /** */ InStatement inStatement;
2176     /** */ OutStatement outStatement;
2177     mixin OpEquals;
2178 }
2179 
2180 ///
2181 final class InStatement : BaseNode
2182 {
2183     override void accept(ASTVisitor visitor) const
2184     {
2185         mixin (visitIfNotNull!(blockStatement));
2186     }
2187     /** */ size_t inTokenLocation;
2188     /** */ BlockStatement blockStatement;
2189     mixin OpEquals;
2190 }
2191 
2192 ///
2193 final class Initialize : BaseNode
2194 {
2195     override void accept(ASTVisitor visitor) const
2196     {
2197         mixin (visitIfNotNull!(statementNoCaseNoDefault));
2198     }
2199     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
2200     mixin OpEquals;
2201 }
2202 
2203 ///
2204 final class Initializer : BaseNode
2205 {
2206     override void accept(ASTVisitor visitor) const
2207     {
2208         mixin (visitIfNotNull!(nonVoidInitializer));
2209     }
2210     /** */ NonVoidInitializer nonVoidInitializer;
2211     mixin OpEquals;
2212 }
2213 
2214 ///
2215 final class InterfaceDeclaration : BaseNode
2216 {
2217     override void accept(ASTVisitor visitor) const
2218     {
2219         mixin (visitIfNotNull!(templateParameters, constraint, baseClassList,
2220             structBody));
2221     }
2222     /** */ Token name;
2223     /** */ TemplateParameters templateParameters;
2224     /** */ Constraint constraint;
2225     /** */ BaseClassList baseClassList;
2226     /** */ StructBody structBody;
2227     /** */ string comment;
2228     mixin OpEquals;
2229 }
2230 
2231 ///
2232 final class Invariant : BaseNode
2233 {
2234     override void accept(ASTVisitor visitor) const
2235     {
2236         mixin (visitIfNotNull!(blockStatement, assertArguments));
2237     }
2238     /** */ BlockStatement blockStatement;
2239     /** */ AssertArguments assertArguments;
2240     /** */ bool useParen;
2241     /** */ string comment;
2242     size_t line;
2243     size_t index;
2244     mixin OpEquals;
2245 }
2246 
2247 ///
2248 final class IsExpression : ExpressionNode
2249 {
2250     override void accept(ASTVisitor visitor) const
2251     {
2252         mixin (visitIfNotNull!(type, identifier, typeSpecialization,
2253             templateParameterList));
2254     }
2255     /** */ Type type;
2256     /** */ Token identifier;
2257     /** */ TypeSpecialization typeSpecialization;
2258     /** */ TemplateParameterList templateParameterList;
2259     /** */ IdType equalsOrColon;
2260     mixin OpEquals;
2261 }
2262 
2263 ///
2264 final class KeyValuePair : BaseNode
2265 {
2266     override void accept(ASTVisitor visitor) const
2267     {
2268         mixin (visitIfNotNull!(key, value));
2269     }
2270     /** */ ExpressionNode key;
2271     /** */ ExpressionNode value;
2272     mixin OpEquals;
2273 }
2274 
2275 ///
2276 final class KeyValuePairs : BaseNode
2277 {
2278     override void accept(ASTVisitor visitor) const
2279     {
2280         mixin (visitIfNotNull!(keyValuePairs));
2281     }
2282     /** */ KeyValuePair[] keyValuePairs;
2283     mixin OpEquals;
2284 }
2285 
2286 ///
2287 final class LabeledStatement : BaseNode
2288 {
2289     override void accept(ASTVisitor visitor) const
2290     {
2291         mixin (visitIfNotNull!(identifier, declarationOrStatement));
2292     }
2293     /** */ Token identifier;
2294     /** */ DeclarationOrStatement declarationOrStatement;
2295     mixin OpEquals;
2296 }
2297 
2298 ///
2299 final class LastCatch : BaseNode
2300 {
2301     override void accept(ASTVisitor visitor) const
2302     {
2303         mixin (visitIfNotNull!(statementNoCaseNoDefault));
2304     }
2305     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
2306     size_t line;
2307     size_t column;
2308     mixin OpEquals;
2309 }
2310 
2311 ///
2312 final class LinkageAttribute : BaseNode
2313 {
2314     override void accept(ASTVisitor visitor) const
2315     {
2316         mixin (visitIfNotNull!(identifier, typeIdentifierPart, cppNamespaces));
2317     }
2318     /** */ Token identifier;
2319     /** */ bool hasPlusPlus;
2320     /** */ TypeIdentifierPart typeIdentifierPart;
2321     /** */ IdType classOrStruct;
2322     /** */ NamespaceList cppNamespaces;
2323     mixin OpEquals;
2324 }
2325 
2326 ///
2327 final class MemberFunctionAttribute : BaseNode
2328 {
2329     override void accept(ASTVisitor visitor) const
2330     {
2331         mixin (visitIfNotNull!(atAttribute));
2332     }
2333     /** */ IdType tokenType;
2334     /** */ AtAttribute atAttribute;
2335     mixin OpEquals;
2336 }
2337 
2338 ///
2339 final class MissingFunctionBody : BaseNode
2340 {
2341     override void accept(ASTVisitor visitor) const
2342     {
2343         mixin (visitIfNotNull!(functionContracts));
2344     }
2345     /** */ FunctionContract[] functionContracts;
2346     mixin OpEquals;
2347 }
2348 
2349 ///
2350 final class MixinDeclaration : BaseNode
2351 {
2352     override void accept(ASTVisitor visitor) const
2353     {
2354         mixin (visitIfNotNull!(mixinExpression, templateMixinExpression));
2355     }
2356     /** */ MixinExpression mixinExpression;
2357     /** */ TemplateMixinExpression templateMixinExpression;
2358     mixin OpEquals;
2359 }
2360 
2361 ///
2362 final class MixinExpression : ExpressionNode
2363 {
2364     override void accept(ASTVisitor visitor) const
2365     {
2366         mixin (visitIfNotNull!(argumentList));
2367     }
2368     /** */ ArgumentList argumentList;
2369     mixin OpEquals;
2370 }
2371 
2372 ///
2373 final class MixinTemplateDeclaration : BaseNode
2374 {
2375     override void accept(ASTVisitor visitor) const
2376     {
2377         mixin (visitIfNotNull!(templateDeclaration));
2378     }
2379     /** */ TemplateDeclaration templateDeclaration;
2380     mixin OpEquals;
2381 }
2382 
2383 ///
2384 final class MixinTemplateName : BaseNode
2385 {
2386     override void accept(ASTVisitor visitor) const
2387     {
2388         mixin (visitIfNotNull!(symbol, typeofExpression, identifierOrTemplateChain));
2389     }
2390     /** */ Symbol symbol;
2391     /** */ IdentifierOrTemplateChain identifierOrTemplateChain;
2392     /** */ TypeofExpression typeofExpression;
2393     mixin OpEquals;
2394 }
2395 
2396 ///
2397 final class Module : BaseNode
2398 {
2399     override void accept(ASTVisitor visitor) const
2400     {
2401         mixin (visitIfNotNull!(scriptLine, moduleDeclaration, declarations));
2402     }
2403     /** */ Token scriptLine;
2404     /** */ ModuleDeclaration moduleDeclaration;
2405     /** */ Declaration[] declarations;
2406     mixin OpEquals;
2407 }
2408 
2409 ///
2410 final class ModuleDeclaration : BaseNode
2411 {
2412     override void accept(ASTVisitor visitor) const
2413     {
2414         mixin (visitIfNotNull!(atAttributes, deprecated_, moduleName));
2415     }
2416     /** */ AtAttribute[] atAttributes;
2417     /** */ Deprecated deprecated_;
2418     /** */ IdentifierChain moduleName;
2419     /** */ size_t startLocation;
2420     /** */ size_t endLocation;
2421     /** */ string comment;
2422     mixin OpEquals;
2423 }
2424 
2425 
2426 ///
2427 final class MulExpression : ExpressionNode
2428 {
2429     override void accept(ASTVisitor visitor) const
2430     {
2431         mixin (visitIfNotNull!(left, right));
2432     }
2433     /** */ IdType operator;
2434     mixin BinaryExpressionBody;
2435     mixin OpEquals;
2436 }
2437 
2438 ///
2439 final class NamespaceList : BaseNode
2440 {
2441     override void accept(ASTVisitor visitor) const
2442     {
2443         mixin (visitIfNotNull!(items));
2444     }
2445     mixin OpEquals;
2446     /** */ TernaryExpression[] items;
2447 }
2448 
2449 ///
2450 final class NewAnonClassExpression : ExpressionNode
2451 {
2452     override void accept(ASTVisitor visitor) const
2453     {
2454         mixin (visitIfNotNull!(allocatorArguments, constructorArguments,
2455             baseClassList, structBody));
2456     }
2457     /** */ Arguments allocatorArguments;
2458     /** */ Arguments constructorArguments;
2459     /** */ BaseClassList baseClassList;
2460     /** */ StructBody structBody;
2461     mixin OpEquals;
2462 }
2463 
2464 ///
2465 final class NewExpression : ExpressionNode
2466 {
2467     override void accept(ASTVisitor visitor) const
2468     {
2469         mixin (visitIfNotNull!(newAnonClassExpression, type, arguments,
2470             assignExpression));
2471     }
2472     /** */ Type type;
2473     /** */ NewAnonClassExpression newAnonClassExpression;
2474     /** */ Arguments arguments;
2475     /** */ ExpressionNode assignExpression;
2476     mixin OpEquals;
2477 }
2478 
2479 
2480 ///
2481 final class StatementNoCaseNoDefault : BaseNode
2482 {
2483     override void accept(ASTVisitor visitor) const
2484     {
2485         mixin (visitIfNotNull!(labeledStatement, blockStatement, ifStatement,
2486             whileStatement, doStatement, forStatement, foreachStatement,
2487             switchStatement, finalSwitchStatement, continueStatement,
2488             breakStatement, returnStatement, gotoStatement, withStatement,
2489             synchronizedStatement, tryStatement,
2490             scopeGuardStatement, asmStatement, pragmaStatement,
2491             conditionalStatement, staticAssertStatement, versionSpecification,
2492             debugSpecification, expressionStatement, staticForeachStatement));
2493     }
2494     /** */ LabeledStatement labeledStatement;
2495     /** */ BlockStatement blockStatement;
2496     /** */ IfStatement ifStatement;
2497     /** */ WhileStatement whileStatement;
2498     /** */ DoStatement doStatement;
2499     /** */ ForStatement forStatement;
2500     /** */ ForeachStatement foreachStatement;
2501     /** */ StaticForeachStatement staticForeachStatement;
2502     /** */ SwitchStatement switchStatement;
2503     /** */ FinalSwitchStatement finalSwitchStatement;
2504     /** */ ContinueStatement continueStatement;
2505     /** */ BreakStatement breakStatement;
2506     /** */ ReturnStatement returnStatement;
2507     /** */ GotoStatement gotoStatement;
2508     /** */ WithStatement withStatement;
2509     /** */ SynchronizedStatement synchronizedStatement;
2510     /** */ TryStatement tryStatement;
2511     /** */ ScopeGuardStatement scopeGuardStatement;
2512     /** */ AsmStatement asmStatement;
2513     /** */ PragmaStatement pragmaStatement;
2514     /** */ ConditionalStatement conditionalStatement;
2515     /** */ StaticAssertStatement staticAssertStatement;
2516     /** */ VersionSpecification versionSpecification;
2517     /** */ DebugSpecification debugSpecification;
2518     /** */ ExpressionStatement expressionStatement;
2519     /** */ size_t startLocation;
2520     /** */ size_t endLocation;
2521     mixin OpEquals;
2522 }
2523 
2524 ///
2525 final class NonVoidInitializer : BaseNode
2526 {
2527     override void accept(ASTVisitor visitor) const
2528     {
2529         mixin (visitIfNotNull!(assignExpression, arrayInitializer,
2530             structInitializer));
2531     }
2532     /** */ ExpressionNode assignExpression;
2533     /** */ ArrayInitializer arrayInitializer;
2534     /** */ StructInitializer structInitializer;
2535 
2536     mixin OpEquals;
2537 }
2538 
2539 ///
2540 final class Operands : BaseNode
2541 {
2542     override void accept(ASTVisitor visitor) const
2543     {
2544         mixin (visitIfNotNull!(operands));
2545     }
2546     /** */ ExpressionNode[] operands;
2547     mixin OpEquals;
2548 }
2549 
2550 ///
2551 final class OrExpression : ExpressionNode
2552 {
2553     override void accept(ASTVisitor visitor) const
2554     {
2555         mixin (visitIfNotNull!(left, right));
2556     }
2557     mixin BinaryExpressionBody;
2558     mixin OpEquals;
2559 }
2560 
2561 ///
2562 final class OrOrExpression : ExpressionNode
2563 {
2564     override void accept(ASTVisitor visitor) const
2565     {
2566         mixin (visitIfNotNull!(left, right));
2567     }
2568     mixin BinaryExpressionBody;
2569     mixin OpEquals;
2570 }
2571 
2572 ///
2573 final class OutContractExpression : BaseNode
2574 {
2575     override void accept(ASTVisitor visitor) const
2576     {
2577         mixin (visitIfNotNull!(parameter, assertArguments));
2578     }
2579     /** */ size_t outTokenLocation;
2580     /** */ Token parameter;
2581     /** */ AssertArguments assertArguments;
2582     mixin OpEquals;
2583 }
2584 
2585 ///
2586 final class OutStatement : BaseNode
2587 {
2588     override void accept(ASTVisitor visitor) const
2589     {
2590         mixin (visitIfNotNull!(parameter, blockStatement));
2591     }
2592     /** */ size_t outTokenLocation;
2593     /** */ Token parameter;
2594     /** */ BlockStatement blockStatement;
2595     mixin OpEquals;
2596 }
2597 
2598 final class ParameterAttribute : BaseNode
2599 {
2600     override void accept(ASTVisitor visitor) const
2601     {
2602         mixin (visitIfNotNull!(atAttribute));
2603     }
2604     /** */ IdType idType;
2605     /** */ AtAttribute atAttribute;
2606 }
2607 
2608 ///
2609 final class Parameter : BaseNode
2610 {
2611     override void accept(ASTVisitor visitor) const
2612     {
2613         mixin (visitIfNotNull!(type, name, default_));
2614     }
2615 
2616     /** */ ParameterAttribute[] parameterAttributes;
2617     /** */ Type type;
2618     /** */ Token name;
2619     /** */ bool vararg;
2620     /** */ ExpressionNode default_;
2621     /** */ TypeSuffix[] cstyle;
2622 
2623     mixin OpEquals;
2624 }
2625 
2626 ///
2627 final class Parameters : BaseNode
2628 {
2629     override void accept(ASTVisitor visitor) const
2630     {
2631         mixin (visitIfNotNull!(parameters));
2632     }
2633 
2634     /** */ Parameter[] parameters;
2635     /** */ bool hasVarargs;
2636     /** */ ParameterAttribute[] varargsAttributes;
2637     mixin OpEquals;
2638 }
2639 
2640 ///
2641 final class Postblit : BaseNode
2642 {
2643     override void accept(ASTVisitor visitor) const
2644     {
2645         mixin (visitIfNotNull!(functionBody));
2646     }
2647     /** */ FunctionBody functionBody;
2648     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
2649     /** */ size_t location;
2650     /** */ size_t line;
2651     /** */ size_t column;
2652     mixin OpEquals;
2653 }
2654 
2655 ///
2656 final class PowExpression : ExpressionNode
2657 {
2658     override void accept(ASTVisitor visitor) const
2659     {
2660         mixin (visitIfNotNull!(left, right));
2661     }
2662     mixin BinaryExpressionBody;
2663     mixin OpEquals;
2664 }
2665 
2666 ///
2667 final class PragmaDeclaration : BaseNode
2668 {
2669     override void accept(ASTVisitor visitor) const
2670     {
2671         mixin (visitIfNotNull!(pragmaExpression));
2672     }
2673     /** */ PragmaExpression pragmaExpression;
2674     mixin OpEquals;
2675 }
2676 
2677 ///
2678 final class PragmaExpression : ExpressionNode
2679 {
2680     override void accept(ASTVisitor visitor) const
2681     {
2682         mixin (visitIfNotNull!(identifier, argumentList));
2683     }
2684     /** */ Token identifier;
2685     /** */ ArgumentList argumentList;
2686     mixin OpEquals;
2687 }
2688 
2689 ///
2690 final class PragmaStatement : BaseNode
2691 {
2692     override void accept(ASTVisitor visitor) const
2693     {
2694         mixin (visitIfNotNull!(pragmaExpression, statement, blockStatement));
2695     }
2696     /** */ PragmaExpression pragmaExpression;
2697     /** */ Statement statement;
2698     /** */ BlockStatement blockStatement;
2699     mixin OpEquals;
2700 }
2701 
2702 ///
2703 final class PrimaryExpression : ExpressionNode
2704 {
2705     override void accept(ASTVisitor visitor) const
2706     {
2707         mixin(visitIfNotNull!(basicType, typeConstructor, type, primary,
2708                 typeofExpression, typeidExpression, arrayLiteral, assocArrayLiteral,
2709                 expression, dot, identifierOrTemplateInstance, isExpression,
2710                 functionLiteralExpression,traitsExpression, mixinExpression,
2711                 importExpression, vector, arguments));
2712     }
2713     /** */ Token dot;
2714     /** */ Token primary;
2715     /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance;
2716     /** */ Token basicType;
2717     /** */ TypeofExpression typeofExpression;
2718     /** */ TypeidExpression typeidExpression;
2719     /** */ ArrayLiteral arrayLiteral;
2720     /** */ AssocArrayLiteral assocArrayLiteral;
2721     /** */ Expression expression;
2722     /** */ IsExpression isExpression;
2723     /** */ FunctionLiteralExpression functionLiteralExpression;
2724     /** */ TraitsExpression traitsExpression;
2725     /** */ MixinExpression mixinExpression;
2726     /** */ ImportExpression importExpression;
2727     /** */ Vector vector;
2728     /** */ Type type;
2729     /** */ Token typeConstructor;
2730     /** */ Arguments arguments;
2731     mixin OpEquals;
2732 }
2733 
2734 ///
2735 final class Register : BaseNode
2736 {
2737     override void accept(ASTVisitor visitor) const
2738     {
2739         mixin (visitIfNotNull!(identifier, intLiteral));
2740     }
2741     /** */ Token identifier;
2742     /** */ Token intLiteral;
2743     /** */ bool hasIntegerLiteral;
2744     mixin OpEquals;
2745 }
2746 
2747 ///
2748 final class RelExpression : ExpressionNode
2749 {
2750     override void accept(ASTVisitor visitor) const
2751     {
2752         mixin (visitIfNotNull!(left, right));
2753     }
2754     /** */ IdType operator;
2755     mixin BinaryExpressionBody;
2756     mixin OpEquals;
2757 }
2758 
2759 ///
2760 final class ReturnStatement : BaseNode
2761 {
2762     override void accept(ASTVisitor visitor) const
2763     {
2764         mixin (visitIfNotNull!(expression));
2765     }
2766     /** */ Expression expression;
2767     /** */ size_t startLocation;
2768     /** */ size_t endLocation;
2769     mixin OpEquals;
2770 }
2771 
2772 ///
2773 final class ScopeGuardStatement : BaseNode
2774 {
2775     override void accept(ASTVisitor visitor) const
2776     {
2777         mixin (visitIfNotNull!(identifier, statementNoCaseNoDefault));
2778     }
2779     /** */ Token identifier;
2780     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
2781     mixin OpEquals;
2782 }
2783 
2784 ///
2785 final class SharedStaticConstructor : BaseNode
2786 {
2787     override void accept(ASTVisitor visitor) const
2788     {
2789         mixin (visitIfNotNull!(memberFunctionAttributes, functionBody));
2790     }
2791     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
2792     /** */ FunctionBody functionBody;
2793     /** */ size_t location;
2794     /** */ size_t line;
2795     /** */ size_t column;
2796     /** */ string comment;
2797     mixin OpEquals;
2798 }
2799 
2800 ///
2801 final class SharedStaticDestructor : BaseNode
2802 {
2803     override void accept(ASTVisitor visitor) const
2804     {
2805         mixin (visitIfNotNull!(memberFunctionAttributes, functionBody));
2806     }
2807     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
2808     /** */ FunctionBody functionBody;
2809     /** */ size_t location;
2810     /** */ size_t line;
2811     /** */ size_t column;
2812     /** */ string comment;
2813     mixin OpEquals;
2814 }
2815 
2816 ///
2817 final class ShiftExpression : ExpressionNode
2818 {
2819     override void accept(ASTVisitor visitor) const
2820     {
2821         mixin (visitIfNotNull!(left, right));
2822     }
2823     /** */ IdType operator;
2824     mixin BinaryExpressionBody;
2825     mixin OpEquals;
2826 }
2827 
2828 ///
2829 final class SingleImport : BaseNode
2830 {
2831     override void accept(ASTVisitor visitor) const
2832     {
2833         mixin (visitIfNotNull!(rename, identifierChain));
2834     }
2835     /** */ Token rename;
2836     /** */ IdentifierChain identifierChain;
2837     mixin OpEquals;
2838 }
2839 
2840 ///
2841 final class SpecifiedFunctionBody : BaseNode
2842 {
2843     override void accept(ASTVisitor visitor) const
2844     {
2845         mixin (visitIfNotNull!(functionContracts, blockStatement));
2846     }
2847     /** */ FunctionContract[] functionContracts;
2848     /** */ BlockStatement blockStatement;
2849     /** */ bool hasDo;
2850     mixin OpEquals;
2851 }
2852 
2853 ///
2854 final class ShortenedFunctionBody : BaseNode
2855 {
2856     override void accept(ASTVisitor visitor) const
2857     {
2858         mixin(visitIfNotNull!(functionContracts, expression));
2859     }
2860 
2861     /** */ FunctionContract[] functionContracts;
2862     /** */ Expression expression;
2863     mixin OpEquals;
2864 }
2865 
2866 ///
2867 final class Statement : BaseNode
2868 {
2869     override void accept(ASTVisitor visitor) const
2870     {
2871         mixin (visitIfNotNull!(statementNoCaseNoDefault, caseStatement,
2872             caseRangeStatement, defaultStatement));
2873     }
2874     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
2875     /** */ CaseStatement caseStatement;
2876     /** */ CaseRangeStatement caseRangeStatement;
2877     /** */ DefaultStatement defaultStatement;
2878     mixin OpEquals;
2879 }
2880 
2881 ///
2882 final class StaticAssertDeclaration : BaseNode
2883 {
2884     override void accept(ASTVisitor visitor) const
2885     {
2886         mixin (visitIfNotNull!(staticAssertStatement));
2887     }
2888     /** */ StaticAssertStatement staticAssertStatement;
2889     mixin OpEquals;
2890 }
2891 
2892 ///
2893 final class StaticAssertStatement : BaseNode
2894 {
2895     override void accept(ASTVisitor visitor) const
2896     {
2897         mixin (visitIfNotNull!(assertExpression));
2898     }
2899     /** */ AssertExpression assertExpression;
2900     mixin OpEquals;
2901 }
2902 
2903 ///
2904 final class StaticConstructor : BaseNode
2905 {
2906     override void accept(ASTVisitor visitor) const
2907     {
2908         mixin (visitIfNotNull!(memberFunctionAttributes, functionBody));
2909     }
2910     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
2911     /** */ FunctionBody functionBody;
2912     /** */ size_t location;
2913     /** */ size_t line;
2914     /** */ size_t column;
2915     /** */ string comment;
2916     mixin OpEquals;
2917 }
2918 
2919 ///
2920 final class StaticDestructor : BaseNode
2921 {
2922     override void accept(ASTVisitor visitor) const
2923     {
2924         mixin (visitIfNotNull!(memberFunctionAttributes, functionBody));
2925     }
2926     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
2927     /** */ FunctionBody functionBody;
2928     /** */ size_t location;
2929     /** */ size_t line;
2930     /** */ size_t column;
2931     /** */ string comment;
2932     mixin OpEquals;
2933 }
2934 
2935 ///
2936 final class StaticIfCondition : BaseNode
2937 {
2938     override void accept(ASTVisitor visitor) const
2939     {
2940         mixin (visitIfNotNull!(assignExpression));
2941     }
2942     /** */ ExpressionNode assignExpression;
2943     mixin OpEquals;
2944 }
2945 
2946 ///
2947 final class StorageClass : BaseNode
2948 {
2949     override void accept(ASTVisitor visitor) const
2950     {
2951         mixin (visitIfNotNull!(token, alignAttribute, linkageAttribute,
2952             atAttribute, deprecated_));
2953     }
2954     /** */ AlignAttribute alignAttribute;
2955     /** */ LinkageAttribute linkageAttribute;
2956     /** */ AtAttribute atAttribute;
2957     /** */ Deprecated deprecated_;
2958     /** */ Token token;
2959     mixin OpEquals;
2960 }
2961 
2962 ///
2963 final class StringLiteralList : BaseNode
2964 {
2965     override void accept(ASTVisitor visitor) const
2966     {
2967         mixin (visitIfNotNull!(items));
2968     }
2969 
2970     /** */ Token[] items;
2971     mixin OpEquals;
2972 }
2973 
2974 ///
2975 final class StructBody : BaseNode
2976 {
2977     override void accept(ASTVisitor visitor) const
2978     {
2979         mixin (visitIfNotNull!(declarations));
2980     }
2981 
2982     /**
2983      * Byte position of the opening brace
2984      */
2985     size_t startLocation;
2986 
2987     /**
2988      * Byte position of the closing brace
2989      */
2990     size_t endLocation;
2991     /** */ Declaration[] declarations;
2992     mixin OpEquals;
2993 }
2994 
2995 ///
2996 final class StructDeclaration : BaseNode
2997 {
2998     override void accept(ASTVisitor visitor) const
2999     {
3000         mixin (visitIfNotNull!(templateParameters, constraint, structBody));
3001     }
3002     /** */ Token name;
3003     /** */ TemplateParameters templateParameters;
3004     /** */ Constraint constraint;
3005     /** */ StructBody structBody;
3006     /** */ string comment;
3007     mixin OpEquals;
3008 }
3009 
3010 ///
3011 final class StructInitializer : BaseNode
3012 {
3013     override void accept(ASTVisitor visitor) const
3014     {
3015         mixin (visitIfNotNull!(structMemberInitializers));
3016     }
3017     /** */ StructMemberInitializers structMemberInitializers;
3018     /** */ size_t startLocation;
3019     /** */ size_t endLocation;
3020     mixin OpEquals;
3021 }
3022 
3023 ///
3024 final class StructMemberInitializer : BaseNode
3025 {
3026     override void accept(ASTVisitor visitor) const
3027     {
3028         mixin (visitIfNotNull!(identifier, nonVoidInitializer));
3029     }
3030     /** */ Token identifier;
3031     /** */ NonVoidInitializer nonVoidInitializer;
3032     mixin OpEquals;
3033 }
3034 
3035 ///
3036 final class StructMemberInitializers : BaseNode
3037 {
3038     override void accept(ASTVisitor visitor) const
3039     {
3040         mixin (visitIfNotNull!(structMemberInitializers));
3041     }
3042     /** */ StructMemberInitializer[] structMemberInitializers;
3043     mixin OpEquals;
3044 }
3045 
3046 ///
3047 final class SwitchStatement : BaseNode
3048 {
3049     override void accept(ASTVisitor visitor) const
3050     {
3051         mixin (visitIfNotNull!(expression, statement));
3052     }
3053     /** */ Expression expression;
3054     /** */ Statement statement;
3055     mixin OpEquals;
3056 }
3057 
3058 ///
3059 final class Symbol : BaseNode
3060 {
3061     override void accept(ASTVisitor visitor) const
3062     {
3063         mixin (visitIfNotNull!(identifierOrTemplateChain));
3064     }
3065 
3066     /** */ IdentifierOrTemplateChain identifierOrTemplateChain;
3067     /** */ bool dot;
3068     mixin OpEquals;
3069 }
3070 
3071 ///
3072 final class SynchronizedStatement : BaseNode
3073 {
3074     override void accept(ASTVisitor visitor) const
3075     {
3076         mixin (visitIfNotNull!(expression, statementNoCaseNoDefault));
3077     }
3078     /** */ Expression expression;
3079     /** */ StatementNoCaseNoDefault statementNoCaseNoDefault;
3080     mixin OpEquals;
3081 }
3082 
3083 ///
3084 final class TemplateAliasParameter : BaseNode
3085 {
3086     override void accept(ASTVisitor visitor) const
3087     {
3088         mixin (visitIfNotNull!(type, identifier, colonType, colonExpression,
3089             assignType, assignExpression));
3090     }
3091     /** */ Type type;
3092     /** */ Token identifier;
3093     /** */ Type colonType;
3094     /** */ ExpressionNode colonExpression;
3095     /** */ Type assignType;
3096     /** */ ExpressionNode assignExpression;
3097     mixin OpEquals;
3098 }
3099 
3100 ///
3101 final class TemplateArgument : BaseNode
3102 {
3103     override void accept(ASTVisitor visitor) const
3104     {
3105         mixin (visitIfNotNull!(type, assignExpression));
3106     }
3107     /** */ Type type;
3108     /** */ ExpressionNode assignExpression;
3109     mixin OpEquals;
3110 }
3111 
3112 ///
3113 final class TemplateArgumentList : BaseNode
3114 {
3115     override void accept(ASTVisitor visitor) const
3116     {
3117         mixin (visitIfNotNull!(items));
3118     }
3119     /** */ TemplateArgument[] items;
3120     mixin OpEquals;
3121 }
3122 
3123 ///
3124 final class TemplateArguments : BaseNode
3125 {
3126     override void accept(ASTVisitor visitor) const
3127     {
3128         mixin (visitIfNotNull!(templateArgumentList, templateSingleArgument));
3129     }
3130     /** */ TemplateArgumentList templateArgumentList;
3131     /** */ TemplateSingleArgument templateSingleArgument;
3132     mixin OpEquals;
3133 }
3134 
3135 ///
3136 final class TemplateDeclaration : BaseNode
3137 {
3138     override void accept(ASTVisitor visitor) const
3139     {
3140         mixin (visitIfNotNull!(name, templateParameters, constraint,
3141             declarations));
3142     }
3143     /** */ Token name;
3144     /** */ TemplateParameters templateParameters;
3145     /** */ Constraint constraint;
3146     /** */ Declaration[] declarations;
3147     /** */ string comment;
3148     /**
3149      * Byte position of the opening brace
3150      */
3151     size_t startLocation;
3152 
3153     /**
3154      * Byte position of the closing brace
3155      */
3156     size_t endLocation;
3157     mixin OpEquals;
3158 }
3159 
3160 ///
3161 final class TemplateInstance : BaseNode
3162 {
3163     override void accept(ASTVisitor visitor) const
3164     {
3165         mixin (visitIfNotNull!(identifier, templateArguments));
3166     }
3167     /** */ Token identifier;
3168     /** */ TemplateArguments templateArguments;
3169     mixin OpEquals;
3170 }
3171 
3172 ///
3173 final class TemplateMixinExpression : ExpressionNode
3174 {
3175     override void accept(ASTVisitor visitor) const
3176     {
3177         mixin (visitIfNotNull!(identifier, templateArguments, mixinTemplateName));
3178     }
3179     /** */ Token identifier;
3180     /** */ TemplateArguments templateArguments;
3181     /** */ MixinTemplateName mixinTemplateName;
3182     mixin OpEquals;
3183 }
3184 
3185 ///
3186 final class TemplateParameter : BaseNode
3187 {
3188     override void accept(ASTVisitor visitor) const
3189     {
3190         mixin (visitIfNotNull!(templateTypeParameter, templateValueParameter,
3191             templateAliasParameter, templateTupleParameter,
3192             templateThisParameter));
3193     }
3194     /** */ TemplateTypeParameter templateTypeParameter;
3195     /** */ TemplateValueParameter templateValueParameter;
3196     /** */ TemplateAliasParameter templateAliasParameter;
3197     /** */ TemplateTupleParameter templateTupleParameter;
3198     /** */ TemplateThisParameter templateThisParameter;
3199     mixin OpEquals;
3200 }
3201 
3202 ///
3203 final class TemplateParameterList : BaseNode
3204 {
3205     override void accept(ASTVisitor visitor) const
3206     {
3207         mixin (visitIfNotNull!(items));
3208     }
3209     /** */ TemplateParameter[] items;
3210     mixin OpEquals;
3211 }
3212 
3213 ///
3214 final class TemplateParameters : BaseNode
3215 {
3216     override void accept(ASTVisitor visitor) const
3217     {
3218         mixin (visitIfNotNull!(templateParameterList));
3219     }
3220     /** */ TemplateParameterList templateParameterList;
3221     mixin OpEquals;
3222 }
3223 
3224 ///
3225 final class TemplateSingleArgument : BaseNode
3226 {
3227     override void accept(ASTVisitor visitor) const
3228     {
3229         mixin (visitIfNotNull!(token));
3230     }
3231     /** */ Token token;
3232     mixin OpEquals;
3233 }
3234 
3235 ///
3236 final class TemplateThisParameter : BaseNode
3237 {
3238     override void accept(ASTVisitor visitor) const
3239     {
3240         mixin (visitIfNotNull!(templateTypeParameter));
3241     }
3242     /** */ TemplateTypeParameter templateTypeParameter;
3243     mixin OpEquals;
3244 }
3245 
3246 ///
3247 final class TemplateTupleParameter : BaseNode
3248 {
3249     override void accept(ASTVisitor visitor) const
3250     {
3251         mixin (visitIfNotNull!(identifier));
3252     }
3253     /** */ Token identifier;
3254     mixin OpEquals;
3255 }
3256 
3257 ///
3258 final class TemplateTypeParameter : BaseNode
3259 {
3260     override void accept(ASTVisitor visitor) const
3261     {
3262         mixin (visitIfNotNull!(identifier, colonType, assignType));
3263     }
3264     /** */ Token identifier;
3265     /** */ Type colonType;
3266     /** */ Type assignType;
3267     mixin OpEquals;
3268 }
3269 
3270 ///
3271 final class TemplateValueParameter : BaseNode
3272 {
3273     override void accept(ASTVisitor visitor) const
3274     {
3275         mixin (visitIfNotNull!(type, identifier, assignExpression,
3276             templateValueParameterDefault));
3277     }
3278     /** */ Type type;
3279     /** */ Token identifier;
3280     /** */ ExpressionNode assignExpression;
3281     /** */ TemplateValueParameterDefault templateValueParameterDefault;
3282     mixin OpEquals;
3283 }
3284 
3285 ///
3286 final class TemplateValueParameterDefault : BaseNode
3287 {
3288     override void accept(ASTVisitor visitor) const
3289     {
3290         mixin (visitIfNotNull!(token, assignExpression));
3291     }
3292     /** */ ExpressionNode assignExpression;
3293     /** */ Token token;
3294     mixin OpEquals;
3295 }
3296 
3297 ///
3298 final class TernaryExpression : ExpressionNode
3299 {
3300     override void accept(ASTVisitor visitor) const
3301     {
3302         mixin (visitIfNotNull!(orOrExpression, expression, ternaryExpression));
3303     }
3304     /** */ ExpressionNode orOrExpression;
3305     /** */ ExpressionNode expression;
3306     /** */ ExpressionNode ternaryExpression;
3307     /// Store this so that we know where the ':' is
3308     Token colon;
3309     mixin OpEquals;
3310 }
3311 
3312 deprecated("Replaced by ExpressionStatement + ThrowExpression")
3313 alias ThrowStatement = ThrowExpression;
3314 
3315 ///
3316 final class ThrowExpression: ExpressionNode
3317 {
3318     override void accept(ASTVisitor visitor) const
3319     {
3320         mixin (visitIfNotNull!(expression));
3321     }
3322 
3323     /** */ ExpressionNode expression;
3324     mixin OpEquals;
3325 }
3326 
3327 ///
3328 final class TraitsExpression : ExpressionNode
3329 {
3330     override void accept(ASTVisitor visitor) const
3331     {
3332         mixin (visitIfNotNull!(identifier, templateArgumentList));
3333     }
3334     /** */ Token identifier;
3335     /** */ TemplateArgumentList templateArgumentList;
3336     mixin OpEquals;
3337 }
3338 
3339 ///
3340 final class TryStatement : BaseNode
3341 {
3342     override void accept(ASTVisitor visitor) const
3343     {
3344         mixin (visitIfNotNull!(declarationOrStatement, catches, finally_));
3345     }
3346     /** */ DeclarationOrStatement declarationOrStatement;
3347     /** */ Catches catches;
3348     /** */ Finally finally_;
3349     mixin OpEquals;
3350 }
3351 
3352 ///
3353 final class Type : BaseNode
3354 {
3355     override void accept(ASTVisitor visitor) const
3356     {
3357         mixin (visitIfNotNull!(type2, typeSuffixes));
3358     }
3359 
3360     /** */ IdType[] typeConstructors;
3361     /** */ TypeSuffix[] typeSuffixes;
3362     /** */ Type2 type2;
3363     mixin OpEquals;
3364 }
3365 
3366 ///
3367 final class Type2 : BaseNode
3368 {
3369     override void accept(ASTVisitor visitor) const
3370     {
3371         mixin (visitIfNotNull!(typeofExpression, typeIdentifierPart, type,
3372             traitsExpression, vector, mixinExpression));
3373     }
3374 
3375     /** */ IdType builtinType;
3376     /** */ alias superOrThis = builtinType;
3377     /** */ TypeofExpression typeofExpression;
3378     /** */ TypeIdentifierPart typeIdentifierPart;
3379     /** */ IdType typeConstructor;
3380     /** */ Type type;
3381     /** */ TraitsExpression traitsExpression;
3382     /** */ Vector vector;
3383     /** */ MixinExpression mixinExpression;
3384     mixin OpEquals;
3385 }
3386 
3387 ///
3388 final class TypeSpecialization : BaseNode
3389 {
3390     override void accept(ASTVisitor visitor) const
3391     {
3392         mixin (visitIfNotNull!(token, type));
3393     }
3394     /** */ Token token;
3395     /** */ Type type;
3396     mixin OpEquals;
3397 }
3398 
3399 ///
3400 final class TypeSuffix : BaseNode
3401 {
3402     override void accept(ASTVisitor visitor) const
3403     {
3404         mixin (visitIfNotNull!(type, low, high, delegateOrFunction, parameters,
3405             memberFunctionAttributes));
3406     }
3407 
3408     /** */ Token delegateOrFunction;
3409     /** */ Token star;
3410     /** */ bool array;
3411     /** */ Type type;
3412     /** */ ExpressionNode low;
3413     /** */ ExpressionNode high;
3414     /** */ Parameters parameters;
3415     /** */ MemberFunctionAttribute[] memberFunctionAttributes;
3416     mixin OpEquals;
3417 }
3418 
3419 ///
3420 final class TypeidExpression : ExpressionNode
3421 {
3422     override void accept(ASTVisitor visitor) const
3423     {
3424         mixin (visitIfNotNull!(type, expression));
3425     }
3426     /** */ Type type;
3427     /** */ Expression expression;
3428     mixin OpEquals;
3429 }
3430 
3431 ///
3432 final class TypeofExpression : ExpressionNode
3433 {
3434     override void accept(ASTVisitor visitor) const
3435     {
3436         mixin (visitIfNotNull!(expression, return_));
3437     }
3438     /** */ Expression expression;
3439     /** */ Token return_;
3440     mixin OpEquals;
3441 }
3442 
3443 ///
3444 final class UnaryExpression : ExpressionNode
3445 {
3446     override void accept(ASTVisitor visitor) const
3447     {
3448         // TODO prefix, postfix, unary
3449         mixin (visitIfNotNull!(primaryExpression, newExpression, deleteExpression,
3450             castExpression, functionCallExpression, argumentList, unaryExpression,
3451             type, identifierOrTemplateInstance, assertExpression, throwExpression,
3452             indexExpression));
3453     }
3454 
3455     /** */ Type type;
3456     /** */ PrimaryExpression primaryExpression;
3457     /** */ Token prefix;
3458     /** */ Token suffix;
3459     /** */ UnaryExpression unaryExpression;
3460     /** */ NewExpression newExpression;
3461     /** */ DeleteExpression deleteExpression;
3462     /** */ CastExpression castExpression;
3463     /** */ FunctionCallExpression functionCallExpression;
3464     /** */ ArgumentList argumentList;
3465     /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance;
3466     /** */ AssertExpression assertExpression;
3467     /** */ ThrowExpression throwExpression;
3468     /** */ IndexExpression indexExpression;
3469     /** */ size_t dotLocation;
3470     mixin OpEquals;
3471 }
3472 
3473 ///
3474 final class UnionDeclaration : BaseNode
3475 {
3476     override void accept(ASTVisitor visitor) const
3477     {
3478         mixin (visitIfNotNull!(name, templateParameters, constraint, structBody));
3479     }
3480 
3481     /** */ Token name;
3482     /** */ TemplateParameters templateParameters;
3483     /** */ Constraint constraint;
3484     /** */ StructBody structBody;
3485     /** */ string comment;
3486     mixin OpEquals;
3487 }
3488 
3489 ///
3490 final class Unittest : BaseNode
3491 {
3492     override void accept(ASTVisitor visitor) const
3493     {
3494         mixin (visitIfNotNull!(blockStatement));
3495     }
3496     /** */ BlockStatement blockStatement;
3497     /** */ string comment;
3498     /** */ size_t location;
3499     /** */ size_t line;
3500     /** */ size_t column;
3501     mixin OpEquals;
3502 }
3503 
3504 ///
3505 final class VariableDeclaration : BaseNode
3506 {
3507     override void accept(ASTVisitor visitor) const
3508     {
3509         mixin (visitIfNotNull!(storageClasses, type, declarators, autoDeclaration));
3510     }
3511     /** */ Type type;
3512     /** */ Declarator[] declarators;
3513     /** */ StorageClass[] storageClasses;
3514     /** */ AutoDeclaration autoDeclaration;
3515     /** */ string comment;
3516     mixin OpEquals;
3517 }
3518 
3519 ///
3520 final class Vector : BaseNode
3521 {
3522     override void accept(ASTVisitor visitor) const
3523     {
3524         mixin (visitIfNotNull!(type));
3525     }
3526     /** */ Type type;
3527     mixin OpEquals;
3528 }
3529 
3530 ///
3531 final class VersionCondition : BaseNode
3532 {
3533     override void accept(ASTVisitor visitor) const
3534     {
3535         mixin (visitIfNotNull!(token));
3536     }
3537     /** */ size_t versionIndex;
3538     /** */ Token token;
3539     mixin OpEquals;
3540 }
3541 
3542 ///
3543 final class VersionSpecification : BaseNode
3544 {
3545     override void accept(ASTVisitor visitor) const
3546     {
3547         mixin (visitIfNotNull!(token));
3548     }
3549     /** */ Token token;
3550     mixin OpEquals;
3551 }
3552 
3553 ///
3554 final class WhileStatement : BaseNode
3555 {
3556     override void accept(ASTVisitor visitor) const
3557     {
3558         mixin (visitIfNotNull!(condition, declarationOrStatement));
3559     }
3560 
3561     /** */ IfCondition condition;
3562     /** */ DeclarationOrStatement declarationOrStatement;
3563     /** */ size_t startIndex;
3564     mixin OpEquals;
3565 
3566     deprecated("use condition.expression") inout(Expression) expression() inout @property
3567     {
3568         if (!condition)
3569             return null;
3570         return condition.expression;
3571     }
3572 }
3573 
3574 ///
3575 final class WithStatement : BaseNode
3576 {
3577     override void accept(ASTVisitor visitor) const
3578     {
3579         mixin (visitIfNotNull!(expression, declarationOrStatement));
3580     }
3581 
3582     /** */ Expression expression;
3583     /** */ DeclarationOrStatement declarationOrStatement;
3584     mixin OpEquals;
3585 }
3586 
3587 ///
3588 final class XorExpression : ExpressionNode
3589 {
3590     override void accept(ASTVisitor visitor) const
3591     {
3592         mixin (visitIfNotNull!(left, right));
3593     }
3594     mixin BinaryExpressionBody;
3595     mixin OpEquals;
3596 }
3597 
3598 unittest // issue #133
3599 {
3600     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3601     string src = q{module test133; void main(){}};
3602     final class TkTest : ASTVisitor
3603     {
3604         alias visit = ASTVisitor.visit;
3605         override void visit(const Token t){assert(t.text.length);}
3606     }
3607     RollbackAllocator ra;
3608     LexerConfig cf = LexerConfig("", StringBehavior.source);
3609     StringCache ca = StringCache(16);
3610     Module m = ParserConfig(getTokensForParser(src, cf, &ca), "", &ra).parseModule();
3611     TkTest t = new TkTest;
3612     t.visit(m);
3613 }
3614 
3615 unittest // issue #165
3616 {
3617     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3618     string src = q{module test165; enum foo(T) = bar!T;};
3619     final class EpoTest : ASTVisitor
3620     {
3621         bool visited;
3622         alias visit = ASTVisitor.visit;
3623         override void visit(const EponymousTemplateDeclaration){visited = true;}
3624     }
3625     RollbackAllocator ra;
3626     LexerConfig cf = LexerConfig("", StringBehavior.source);
3627     StringCache ca = StringCache(16);
3628     Module m = ParserConfig(getTokensForParser(src, cf, &ca), "", &ra).parseModule();
3629     EpoTest et = new EpoTest;
3630     et.visit(m);
3631     assert(et.visited);
3632 }
3633 
3634 unittest // issue #156
3635 {
3636     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3637 
3638     final class Test : ASTVisitor
3639     {
3640         bool arrIndex, arrValue, arrValueOnly, aaLiteral;
3641         alias visit = ASTVisitor.visit;
3642         override void visit(const ArrayInitializer ai)
3643         {
3644             if (ai.arrayMemberInitializations.length == 1)
3645             {
3646                 arrIndex = ai.arrayMemberInitializations[0].assignExpression !is null;
3647                 arrValue = ai.arrayMemberInitializations[0].nonVoidInitializer !is null;
3648                 arrValueOnly = arrValue && !arrIndex;
3649             }
3650         }
3651         override void visit(const AssocArrayLiteral aal)
3652         {
3653             aaLiteral = true;
3654         }
3655     }
3656 
3657     RollbackAllocator ra;
3658     LexerConfig cf = LexerConfig("", StringBehavior.source);
3659     StringCache ca = StringCache(16);
3660 
3661     {
3662         // no colon so array.
3663         string src1 = q{void main(){const arr = [[0]];}};
3664         Module m = parseModule(ParserConfig(getTokensForParser(src1, cf, &ca), "", &ra));
3665         Test t = new Test;
3666         t.visit(m);
3667         assert(t.arrValueOnly);
3668     }
3669     {
3670         // simple primary before colon, assume array.
3671         string src2 = q{void main(){const arr = [0:0];}};
3672         Module m = ParserConfig(getTokensForParser(src2, cf, &ca), "", &ra).parseModule();
3673         Test t = new Test;
3674         t.visit(m);
3675         assert(t.arrIndex);
3676         assert(t.arrValue);
3677         assert(!t.aaLiteral);
3678     }
3679     {
3680         // more complex exp before colon, assume AA.
3681         string src3 = q{void main(){const arr = [[0]:0];}};
3682         Module m = ParserConfig(getTokensForParser(src3, cf, &ca), "", &ra).parseModule();
3683         Test t = new Test;
3684         t.visit(m);
3685         assert(!t.arrIndex);
3686         assert(!t.arrValue);
3687         assert(t.aaLiteral);
3688     }
3689 }
3690 
3691 unittest // issue #170, issue #316
3692 {
3693     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3694 
3695     abstract class TestCase : ASTVisitor
3696     {
3697         string src;
3698         bool visited;
3699         this()
3700         {
3701             RollbackAllocator ra;
3702             LexerConfig cf = LexerConfig("", StringBehavior.source);
3703             StringCache ca = StringCache(16);
3704             Module m = ParserConfig(getTokensForParser(src, cf, &ca), "", &ra).parseModule();
3705             visit(m);
3706             assert(visited);
3707         }
3708     }
3709 
3710     class FunctionLiteralExpressionTestCase : TestCase
3711     {
3712         alias visit = ASTVisitor.visit;
3713         override void visit(const FunctionLiteralExpression){visited = true;}
3714     }
3715 
3716     class StructInitializerTestCase : TestCase
3717     {
3718         alias visit = ASTVisitor.visit;
3719         override void visit(const StructInitializer){visited = true;}
3720     }
3721 
3722     new class FunctionLiteralExpressionTestCase
3723     {this(){  TestCase.src = q{ void function() a = {call();};}; super(); }};
3724 
3725     new class FunctionLiteralExpressionTestCase
3726     {this(){  TestCase.src = q{ const a = {int i;};}; super(); }};
3727 
3728     new class FunctionLiteralExpressionTestCase
3729     {this(){  TestCase.src = q{ const a = {};}; super(); }};
3730 
3731     new class StructInitializerTestCase
3732     {this(){  TestCase.src = q{A a = {member : call()};}; super(); }};
3733 
3734     new class StructInitializerTestCase
3735     {this(){  TestCase.src = q{A a = {0};}; super(); }};
3736 }
3737 
3738 unittest // issue #193
3739 {
3740     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3741 
3742     final class Test193 : ASTVisitor
3743     {
3744         static string src = q{const(Type1[immutable(Type2)]) qualAarray;};
3745         size_t tc;
3746         alias visit = ASTVisitor.visit;
3747         override void visit(const TypeIdentifierPart tip)
3748         {
3749             tip.accept(this);
3750             assert(tip.indexer is null);
3751         }
3752         override void visit(const Type type)
3753         {
3754             tc++;
3755             if (tc == 1) //const(
3756             {
3757                 assert(type.type2.typeConstructor == tok!"const");
3758                 assert(type.type2.typeIdentifierPart is null);
3759             }
3760             else if (tc == 2) //const(Type1
3761             {
3762                 assert(type.typeConstructors.length == 0);
3763                 assert(type.type2.typeIdentifierPart.identifierOrTemplateInstance
3764                     .identifier.text == "Type1");
3765                 assert(type.typeSuffixes.length == 1);
3766             }
3767             else if (tc == 3) // immutable(
3768             {
3769                 assert(type.type2.typeConstructor == tok!"immutable");
3770                 assert(type.type2.typeIdentifierPart is null);
3771             }
3772             else if (tc == 4) // immutable(Type2
3773             {
3774                 assert(type.typeConstructors.length == 0);
3775                 assert(type.type2.typeIdentifierPart.identifierOrTemplateInstance
3776                     .identifier.text == "Type2");
3777                 assert(type.typeSuffixes.length == 0);
3778             }
3779             type.accept(this);
3780         }
3781     }
3782 
3783     RollbackAllocator ra;
3784     LexerConfig cf = LexerConfig("", StringBehavior.source);
3785     StringCache ca = StringCache(16);
3786 
3787     Module m = ParserConfig(getTokensForParser(Test193.src, cf, &ca), "", &ra).parseModule();
3788     Test193 t193 = new Test193;
3789     t193.visit(m);
3790 }
3791 
3792 unittest // there used to be a small regression when adding the ParserConfig
3793 {
3794     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3795 
3796     auto src = q{module m;};
3797 
3798     RollbackAllocator ra;
3799     LexerConfig cf = LexerConfig("", StringBehavior.source);
3800     StringCache ca = StringCache(16);
3801 
3802     Module m1 = parseModule(getTokensForParser(src, cf, &ca), "", &ra , null);
3803     Module m2 = parseModule(getTokensForParser(src, cf, &ca), "", &ra);
3804 }
3805 
3806 unittest //#318 : used to segfault
3807 {
3808     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3809 
3810     auto src = q{ auto a = new TestClass( };
3811 
3812     RollbackAllocator ra;
3813     LexerConfig cf = LexerConfig("", StringBehavior.source);
3814     StringCache ca = StringCache(16);
3815 
3816     static void shut(string, size_t, size_t, string ,bool){}
3817 
3818     Module m1 = parseModule(getTokensForParser(src, cf, &ca), "", &ra , &shut);
3819 }
3820 
3821 unittest //#365 : used to segfault
3822 {
3823     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3824 
3825     auto src = " o[{scope(x ";
3826 
3827     RollbackAllocator ra;
3828     LexerConfig cf = LexerConfig("", StringBehavior.source);
3829     StringCache ca = StringCache(16);
3830 
3831     static void shut(string, size_t, size_t, string ,bool){}
3832 
3833     Module m1 = parseModule(getTokensForParser(src, cf, &ca), "", &ra , &shut);
3834 }
3835 
3836 unittest // issue #398: Support extern(C++, <string expressions...>)
3837 {
3838     import dparse.lexer : LexerConfig;
3839     import dparse.parser : ParserConfig, parseModule;
3840     import dparse.rollback_allocator : RollbackAllocator;
3841 
3842     RollbackAllocator ra;
3843     StringCache ca = StringCache(16);
3844 
3845     const(PrimaryExpression)[] getNamespaces(const string sourceCode)
3846     {
3847         final class Test398 : ASTVisitor
3848         {
3849             alias visit = ASTVisitor.visit;
3850             const(PrimaryExpression)[] namespaces;
3851 
3852             override void visit(const LinkageAttribute link)
3853             {
3854                 assert(link.identifier.text == "C");
3855                 assert(link.hasPlusPlus);
3856                 assert(!link.typeIdentifierPart);
3857                 assert(!link.classOrStruct);
3858                 assert(link.cppNamespaces);
3859                 super.visit(link);
3860             }
3861 
3862             override void visit(const NamespaceList list)
3863             {
3864                 assert(list.items.length);
3865                 assert(!namespaces);
3866                 foreach (const entry; list.items)
3867                 {
3868                     const prim = cast(PrimaryExpression) entry.expression;
3869                     assert(prim);
3870                     namespaces ~= prim;
3871                 }
3872             }
3873         }
3874 
3875         LexerConfig cf = LexerConfig("", StringBehavior.source);
3876         Module m = ParserConfig(getTokensForParser(sourceCode, cf, &ca), "", &ra).parseModule();
3877         scope visitor = new Test398();
3878         visitor.visit(m);
3879         return visitor.namespaces;
3880     }
3881 
3882     void checkText(const PrimaryExpression pe, const string exp)
3883     {
3884         assert(pe);
3885         const act = pe.primary.text;
3886         assert(act == exp, '<' ~ act ~ '>');
3887 
3888     }
3889 
3890     auto ns = getNamespaces(`extern(C++, "foo") int i;`);
3891     assert(ns.length == 1);
3892     checkText(ns[0], `"foo"`);
3893 
3894     ns = getNamespaces(`extern(C++, "foo", "bar", "baz",) int i;`);
3895     assert(ns.length == 3);
3896     checkText(ns[0], `"foo"`);
3897     checkText(ns[1], `"bar"`);
3898     checkText(ns[2], `"baz"`);
3899 }
3900 
3901 unittest // Differentiate between no and empty DDOC comments, e.g. for DDOC unittests
3902 {
3903     import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3904 
3905     auto src = q{
3906         ///
3907         unittest {}
3908 
3909         ///
3910         @safe pure unittest {}
3911 
3912         /****/ unittest {}
3913 
3914         /++++/ unittest {}
3915 
3916         /// This is a comment!
3917         unittest {}
3918 
3919         unittest {}
3920     };
3921 
3922     RollbackAllocator ra;
3923     LexerConfig cf = LexerConfig("", StringBehavior.source);
3924     StringCache ca = StringCache(16);
3925     Module m = parseModule(getTokensForParser(src, cf, &ca), "", &ra);
3926 
3927     final class UnittestVisitor : ASTVisitor
3928     {
3929         alias visit = ASTVisitor.visit;
3930         bool[size_t] found;
3931 
3932         override void visit(const Unittest test)
3933         {
3934             assert(test.line !in found);
3935             found[test.line] = true;
3936 
3937             switch (test.line)
3938             {
3939                 case 3, 6, 8, 10:
3940                     assert(test.comment !is null);
3941                     assert(test.comment == "");
3942                     break;
3943 
3944                 case 13:
3945                     assert(test.comment == "This is a comment!");
3946                     break;
3947 
3948                 case 15:
3949                     assert(test.comment is null);
3950                     break;
3951 
3952                 default:
3953                     assert(false, format("Unknown line: %d", test.line));
3954             }
3955         }
3956     }
3957 
3958     scope visitor = new UnittestVisitor();
3959     visitor.visit(m);
3960     assert(visitor.found.length == 6);
3961 }
3962 
3963 unittest // Support GCC-sytle asm statements
3964 {
3965     static void verify(T)(const string code, void function(scope const T) handler)
3966     {
3967         import dparse.lexer, dparse.parser, dparse.rollback_allocator;
3968 
3969         RollbackAllocator ra;
3970         LexerConfig cf = LexerConfig("", StringBehavior.source);
3971         StringCache ca = StringCache(16);
3972         Module m = parseModule(getTokensForParser("void main() { " ~ code ~ '}', cf, &ca), "", &ra);
3973 
3974         final class AsmVisitor : ASTVisitor
3975         {
3976             alias visit = ASTVisitor.visit;
3977             bool found;
3978 
3979             override void visit(const T node)
3980             {
3981                 assert(!found);
3982                 found = true;
3983                 handler(node);
3984             }
3985         }
3986 
3987         scope visitor = new AsmVisitor();
3988         visitor.visit(m);
3989         assert(visitor.found);
3990     }
3991 
3992     static void first(scope const AsmStatement stmt)
3993     {
3994         assert(stmt.asmInstructions.length == 0);
3995         assert(stmt.gccAsmInstructions.length == 1);
3996         with (stmt.gccAsmInstructions[0])
3997         {
3998             assert(assemblerTemplate);
3999             assert(assemblerTemplate.tokens.length == 1);
4000             assert(assemblerTemplate.tokens[0].type == tok!"stringLiteral");
4001             assert(assemblerTemplate.tokens[0].text == `"mov %0, EAX"`);
4002 
4003             assert(outputOperands);
4004             assert(outputOperands.items.length == 1);
4005             with (outputOperands.items[0])
4006             {
4007                 assert(constraint.type == tok!"stringLiteral");
4008                 assert(constraint.text == `"=r"`);
4009 
4010                 auto una = cast(UnaryExpression) expression;
4011                 assert(una);
4012                 assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var1");
4013             }
4014         }
4015     }
4016 
4017     verify(q{ asm { "mov %0, EAX" : "=r" (var1) ; } }, &first);
4018 
4019     static void second(scope const AsmStatement stmt)
4020     {
4021         first(stmt);
4022 
4023         with (stmt.gccAsmInstructions[0])
4024         {
4025             assert(inputOperands);
4026             assert(inputOperands.items.length == 2);
4027             with (inputOperands.items[0])
4028             {
4029                 assert(symbolicName.type == tok!"identifier");
4030                 assert(symbolicName.text == "xy");
4031 
4032                 assert(constraint.type == tok!"stringLiteral");
4033                 assert(constraint.text == `"=w"`);
4034 
4035                 auto una = cast(UnaryExpression) expression;
4036                 assert(una);
4037                 assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var2");
4038             }
4039 
4040             with (inputOperands.items[1])
4041             {
4042                 assert(constraint.type == tok!"stringLiteral");
4043                 assert(constraint.text == `"g"`);
4044 
4045                 auto una = cast(UnaryExpression) expression;
4046                 assert(una);
4047                 assert(una.primaryExpression.identifierOrTemplateInstance.identifier.text == "var3");
4048             }
4049         }
4050     }
4051 
4052     verify(q{ asm { "mov %0, EAX" : "=r" (var1) : [xy] "=w" (var2), "g" (var3); } }, &second);
4053 
4054     verify(q{ asm { "mov %0, EAX" : "=r" (var1) : [xy] "=w" (var2), "g" (var3) : "r0" ; } }, (scope const AsmStatement stmt)
4055     {
4056         second(stmt);
4057 
4058         with (stmt.gccAsmInstructions[0])
4059         {
4060             assert(registers);
4061             assert(registers.items.length == 1);
4062             assert(registers.items[0].type == tok!"stringLiteral");
4063             assert(registers.items[0].text == `"r0"`);
4064         }
4065     });
4066 
4067     verify(q{ asm { "mov EBX, EAX" : : : "r0", "r1" ; } }, (scope const GccAsmInstruction instr)
4068     {
4069         with (instr)
4070         {
4071             assert(registers);
4072             assert(registers.items.length == 2);
4073             assert(registers.items[0].type == tok!"stringLiteral");
4074             assert(registers.items[0].text == `"r0"`);
4075             assert(registers.items[1].type == tok!"stringLiteral");
4076             assert(registers.items[1].text == `"r1"`);
4077         }
4078     });
4079 
4080     verify(q{ asm { "jmp LEnd" : : : : LEnd ; } }, (scope const GccAsmInstruction instr)
4081     {
4082         with (instr)
4083         {
4084             assert(gotos);
4085             assert(gotos.identifiers.length == 1);
4086             assert(gotos.identifiers[0].type == tok!"identifier");
4087             assert(gotos.identifiers[0].text == `LEnd`);
4088         }
4089     });
4090 }