1 // Written in the D programming language
2 
3 module dparse.parser;
4 
5 import dparse.lexer;
6 import dparse.ast;
7 import std.experimental.allocator.mallocator;
8 import std.experimental.allocator;
9 import std.conv;
10 import std.algorithm;
11 import std.array;
12 import std..string : format;
13 
14 // Uncomment this if you want ALL THE OUTPUT
15 // Caution: generates 180 megabytes of logging for std.datetime
16 //version = std_parser_verbose;
17 
18 enum minimize_memory = true;
19 
20 alias ParseAllocator = CAllocatorImpl!(Mallocator);
21 
22 /**
23  * Params:
24  *     tokens = the tokens parsed by dparse.lexer
25  *     fileName = the name of the file being parsed
26  *     messageFunction = a function to call on error or warning messages.
27  *         The parameters are the file name, line number, column number,
28  *         the error or warning message, and a boolean (true means error, false
29  *         means warning).
30  * Returns: the parsed module
31  */
32 Module parseModule(const(Token)[] tokens, string fileName, IAllocator allocator = null,
33     void function(string, size_t, size_t, string, bool) messageFunction = null,
34     uint* errorCount = null, uint* warningCount = null)
35 {
36     auto parser = new Parser();
37     parser.fileName = fileName;
38     parser.tokens = tokens;
39     parser.messageFunction = messageFunction;
40     parser.allocator = allocator;
41     auto mod = parser.parseModule();
42     if (warningCount !is null)
43         *warningCount = parser.warningCount;
44     if (errorCount !is null)
45         *errorCount = parser.errorCount;
46     return mod;
47 }
48 
49 /**
50  * D Parser.
51  *
52  * It is sometimes useful to sub-class Parser to skip over things that are not
53  * interesting. For example, DCD skips over function bodies when caching symbols
54  * from imported files.
55  */
56 class Parser
57 {
58     /**
59      * Parses an AddExpression.
60      *
61      * $(GRAMMAR $(RULEDEF addExpression):
62      *       $(RULE mulExpression)
63      *     | $(RULE addExpression) $(LPAREN)$(LITERAL '+') | $(LITERAL'-') | $(LITERAL'~')$(RPAREN) $(RULE mulExpression)
64      *     ;)
65      */
66     ExpressionNode parseAddExpression()
67     {
68         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
69         return parseLeftAssocBinaryExpression!(AddExpression, MulExpression,
70             tok!"+", tok!"-", tok!"~")();
71     }
72 
73     /**
74      * Parses an AliasDeclaration.
75      *
76      * $(GRAMMAR $(RULEDEF aliasDeclaration):
77      *       $(LITERAL 'alias') $(RULE aliasInitializer) $(LPAREN)$(LITERAL ',') $(RULE aliasInitializer)$(RPAREN)* $(LITERAL ';')
78      *     | $(LITERAL 'alias') $(RULE storageClass)* $(RULE type) $(LITERAL identifierList) $(LITERAL ';')
79      *     ;)
80      */
81     AliasDeclaration parseAliasDeclaration()
82     {
83         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
84         auto node = allocate!AliasDeclaration;
85         mixin(nullCheck!`expect(tok!"alias")`);
86         node.comment = comment;
87         comment = null;
88 	node.line = current.line;
89 
90         if (startsWith(tok!"identifier", tok!"=") || startsWith(tok!"identifier", tok!"("))
91         {
92             AliasInitializer[] initializers;
93             do
94             {
95                 auto initializer = parseAliasInitializer();
96                 mixin(nullCheck!`initializer`);
97                 initializers ~= initializer;
98                 if (currentIs(tok!","))
99                     advance();
100                 else
101                     break;
102             }
103             while (moreTokens());
104             node.initializers = ownArray(initializers);
105         }
106         else
107         {
108             StorageClass[] storageClasses;
109             while (moreTokens() && isStorageClass())
110             storageClasses ~= parseStorageClass();
111             if (storageClasses.length > 0)
112                 node.storageClasses = ownArray(storageClasses);
113 	    /*
114             warn("Prefer the new \"'alias' identifier '=' type ';'\" syntax"
115                 ~ " to the  old \"'alias' type identifier ';'\" syntax");
116 	*/
117             mixin(nullCheck!`node.type = parseType()`);
118 	    if(startsWith(tok!"identifier", tok!"(")) {
119 	    	// this is the insane
120 		// alias int GetterType() @property;
121 		// stuff... I just want to skip that shit.
122             	mixin(nullCheck!`node.identifierList = parseIdentifierList()`);
123 		while(!currentIs(tok!";"))
124 			advance;
125 		//parseFunctionDeclaration();
126 
127 	    } else
128             	mixin(nullCheck!`node.identifierList = parseIdentifierList()`);
129         }
130         mixin(nullCheck!`expect(tok!";")`);
131         return node;
132     }
133 
134     /**
135      * Parses an AliasInitializer.
136      *
137      * $(GRAMMAR $(RULEDEF aliasInitializer):
138      *     $(LITERAL Identifier) $(RULE templateParameters)? $(LITERAL '=') $(RULE storageClass)* $(RULE type)
139      *     ;)
140      */
141     AliasInitializer parseAliasInitializer()
142     {
143         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
144         auto node = allocate!AliasInitializer;
145         const i = expect(tok!"identifier");
146         mixin(nullCheck!`i`);
147         node.name = *i;
148         if (currentIs(tok!"("))
149             mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
150         mixin(nullCheck!`expect(tok!"=")`);
151         StorageClass[] storageClasses;
152         while (moreTokens() && isStorageClass())
153             storageClasses ~= parseStorageClass();
154         if (storageClasses.length > 0)
155             node.storageClasses = ownArray(storageClasses);
156         mixin(nullCheck!`node.type = parseType()`);
157         return node;
158     }
159 
160     /**
161      * Parses an AliasThisDeclaration.
162      *
163      * $(GRAMMAR $(RULEDEF aliasThisDeclaration):
164      *     $(LITERAL 'alias') $(LITERAL Identifier) $(LITERAL 'this') $(LITERAL ';')
165      *     ;)
166      */
167     AliasThisDeclaration parseAliasThisDeclaration()
168     {
169         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
170         auto node = allocate!AliasThisDeclaration;
171 	node.comment = comment;
172 	comment = null;
173         mixin(nullCheck!`expect(tok!"alias")`);
174         const ident = expect(tok!"identifier");
175         mixin(nullCheck!`ident`);
176         node.identifier = *ident;
177         mixin(nullCheck!`expect(tok!"this")`);
178         mixin(nullCheck!`expect(tok!";")`);
179         return node;
180     }
181 
182     /**
183      * Parses an AlignAttribute.
184      *
185      * $(GRAMMAR $(RULEDEF alignAttribute):
186      *     $(LITERAL 'align') ($(LITERAL '$(LPAREN)') $(LITERAL IntegerLiteral) $(LITERAL '$(RPAREN)'))?
187      *     ;)
188      */
189     AlignAttribute parseAlignAttribute()
190     {
191         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
192         auto node = allocate!AlignAttribute;
193         expect(tok!"align");
194         if (currentIs(tok!"("))
195         {
196             mixin(nullCheck!`expect(tok!"(")`);
197             const intLit = expect(tok!"intLiteral");
198             mixin(nullCheck!`intLit`);
199             node.intLiteral = *intLit;
200             mixin(nullCheck!`expect(tok!")")`);
201         }
202         return node;
203     }
204 
205     /**
206      * Parses an AndAndExpression.
207      *
208      * $(GRAMMAR $(RULEDEF andAndExpression):
209      *       $(RULE orExpression)
210      *     | $(RULE andAndExpression) $(LITERAL '&&') $(RULE orExpression)
211      *     ;)
212      */
213     ExpressionNode parseAndAndExpression()
214     {
215         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
216         return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression,
217             tok!"&&")();
218     }
219 
220     /**
221      * Parses an AndExpression.
222      *
223      * $(GRAMMAR $(RULEDEF andExpression):
224      *       $(RULE cmpExpression)
225      *     | $(RULE andExpression) $(LITERAL '&') $(RULE cmpExpression)
226      *     ;)
227      */
228     ExpressionNode parseAndExpression()
229     {
230         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
231         return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression,
232             tok!"&")();
233     }
234 
235     /**
236      * Parses an ArgumentList.
237      *
238      * $(GRAMMAR $(RULEDEF argumentList):
239      *     $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression)?)*
240      *     ;)
241      */
242     ArgumentList parseArgumentList()
243     {
244         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
245         if (!moreTokens)
246         {
247             error("argument list expected instead of EOF");
248             return null;
249         }
250         size_t startLocation = current().index;
251         auto node = parseCommaSeparatedRule!(ArgumentList, AssignExpression)(true);
252         mixin(nullCheck!`node`);
253         node.startLocation = startLocation;
254         if (moreTokens) node.endLocation = current().index;
255         return node;
256     }
257 
258     /**
259      * Parses Arguments.
260      *
261      * $(GRAMMAR $(RULEDEF arguments):
262      *     $(LITERAL '$(LPAREN)') $(RULE argumentList)? $(LITERAL '$(RPAREN)')
263      *     ;)
264      */
265     Arguments parseArguments()
266     {
267         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
268         auto node = allocate!Arguments;
269         mixin(nullCheck!`expect(tok!"(")`);
270         if (!currentIs(tok!")"))
271             mixin(nullCheck!`node.argumentList = parseArgumentList()`);
272         mixin(nullCheck!`expect(tok!")")`);
273         return node;
274     }
275 
276     /**
277      * Parses an ArrayInitializer.
278      *
279      * $(GRAMMAR $(RULEDEF arrayInitializer):
280      *       $(LITERAL '[') $(LITERAL ']')
281      *     | $(LITERAL '[') $(RULE arrayMemberInitialization) ($(LITERAL ',') $(RULE arrayMemberInitialization)?)* $(LITERAL ']')
282      *     ;)
283      */
284     ArrayInitializer parseArrayInitializer()
285     {
286         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
287         auto node = allocate!ArrayInitializer;
288         const open = expect(tok!"[");
289         mixin(nullCheck!`open`);
290         node.startLocation = open.index;
291         ArrayMemberInitialization[] arrayMemberInitializations;
292         while (moreTokens())
293         {
294             if (currentIs(tok!"]"))
295                 break;
296             arrayMemberInitializations ~= parseArrayMemberInitialization();
297             if (currentIs(tok!","))
298                 advance();
299             else
300                 break;
301         }
302         node.arrayMemberInitializations = ownArray(arrayMemberInitializations);
303         const close = expect(tok!"]");
304         mixin(nullCheck!`close`);
305         node.endLocation = close.index;
306         return node;
307     }
308 
309     /**
310      * Parses an ArrayLiteral.
311      *
312      * $(GRAMMAR $(RULEDEF arrayLiteral):
313      *     $(LITERAL '[') $(RULE argumentList)? $(LITERAL ']')
314      *     ;)
315      */
316     ArrayLiteral parseArrayLiteral()
317     {
318         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
319         auto node = allocate!ArrayLiteral;
320         mixin(nullCheck!`expect(tok!"[")`);
321         if (!currentIs(tok!"]"))
322             mixin(nullCheck!`node.argumentList = parseArgumentList()`);
323         mixin(nullCheck!`expect(tok!"]")`);
324         return node;
325     }
326 
327     /**
328      * Parses an ArrayMemberInitialization.
329      *
330      * $(GRAMMAR $(RULEDEF arrayMemberInitialization):
331      *     ($(RULE assignExpression) $(LITERAL ':'))? $(RULE nonVoidInitializer)
332      *     ;)
333      */
334     ArrayMemberInitialization parseArrayMemberInitialization()
335     {
336         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
337         auto node = allocate!ArrayMemberInitialization;
338         switch (current.type)
339         {
340         case tok!"[":
341             auto b = setBookmark();
342             skipBrackets();
343             if (currentIs(tok!":"))
344             {
345                 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
346                 advance(); // :
347                 mixin(nullCheck!`node.nonVoidInitializer`);
348                 break;
349             }
350             else
351             {
352                 goToBookmark(b);
353                 goto case;
354             }
355         case tok!"{":
356             mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`);
357             break;
358         default:
359             auto assignExpression = parseAssignExpression();
360             mixin(nullCheck!`assignExpression`);
361             if (currentIs(tok!":"))
362             {
363                 node.assignExpression = assignExpression;
364                 advance();
365                 mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`);
366             }
367             else
368             {
369                 node.nonVoidInitializer = allocate!NonVoidInitializer;
370                 node.nonVoidInitializer.assignExpression = assignExpression;
371             }
372         }
373         return node;
374     }
375 
376     /**
377      * Parses an AsmAddExp
378      *
379      * $(GRAMMAR $(RULEDEF asmAddExp):
380      *       $(RULE asmMulExp)
381      *     | $(RULE asmAddExp) ($(LITERAL '+') | $(LITERAL '-')) $(RULE asmMulExp)
382      *     ;)
383      */
384     ExpressionNode parseAsmAddExp()
385     {
386         mixin(traceEnterAndExit!(__FUNCTION__));
387         return parseLeftAssocBinaryExpression!(AsmAddExp, AsmMulExp,
388             tok!"+", tok!"-")();
389     }
390 
391     /**
392      * Parses an AsmAndExp
393      *
394      * $(GRAMMAR $(RULEDEF asmAndExp):
395      *       $(RULE asmEqualExp)
396      *     | $(RULE asmAndExp) $(LITERAL '&') $(RULE asmEqualExp)
397      *     ;)
398      */
399     ExpressionNode parseAsmAndExp()
400     {
401         mixin(traceEnterAndExit!(__FUNCTION__));
402         return parseLeftAssocBinaryExpression!(AsmAndExp, AsmEqualExp, tok!"&");
403     }
404 
405     /**
406      * Parses an AsmBrExp
407      *
408      * $(GRAMMAR $(RULEDEF asmBrExp):
409      *       $(RULE asmUnaExp)
410      *     | $(RULE asmBrExp)? $(LITERAL '[') $(RULE asmExp) $(LITERAL ']')
411      *     ;)
412      */
413     AsmBrExp parseAsmBrExp()
414     {
415         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
416         AsmBrExp node = allocate!AsmBrExp();
417         size_t line = current.line;
418         size_t column = current.column;
419         if (currentIs(tok!"["))
420         {
421             advance(); // [
422             mixin(nullCheck!`node.asmExp = parseAsmExp()`);
423             mixin(nullCheck!`expect(tok!"]")`);
424             if (currentIs(tok!"["))
425                 goto brLoop;
426         }
427         else
428         {
429             mixin(nullCheck!`node.asmUnaExp = parseAsmUnaExp()`);
430             brLoop: while (currentIs(tok!"["))
431             {
432                 AsmBrExp br = allocate!AsmBrExp(); // huehuehuehue
433                 br.asmBrExp = node;
434                 br.line = current().line;
435                 br.column = current().column;
436                 node = br;
437                 node.line = line;
438                 node.column = column;
439                 advance(); // [
440                 mixin(nullCheck!`node.asmExp = parseAsmExp()`);
441                 mixin(nullCheck!`expect(tok!"]")`);
442             }
443         }
444         return node;
445     }
446 
447     /**
448      * Parses an AsmEqualExp
449      *
450      * $(GRAMMAR $(RULEDEF asmEqualExp):
451      *       $(RULE asmRelExp)
452      *     | $(RULE asmEqualExp) ('==' | '!=') $(RULE asmRelExp)
453      *     ;)
454      */
455     ExpressionNode parseAsmEqualExp()
456     {
457         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
458         return parseLeftAssocBinaryExpression!(AsmEqualExp, AsmRelExp, tok!"==", tok!"!=")();
459     }
460 
461     /**
462      * Parses an AsmExp
463      *
464      * $(GRAMMAR $(RULEDEF asmExp):
465      *     $(RULE asmLogOrExp) ($(LITERAL '?') $(RULE asmExp) $(LITERAL ':') $(RULE asmExp))?
466      *     ;)
467      */
468     ExpressionNode parseAsmExp()
469     {
470         mixin(traceEnterAndExit!(__FUNCTION__));
471         AsmExp node = allocate!AsmExp;
472         mixin(nullCheck!`node.left = parseAsmLogOrExp()`);
473         if (currentIs(tok!"?"))
474         {
475             advance();
476             mixin(nullCheck!`(node.middle = parseAsmExp())`);
477             mixin(nullCheck!`expect(tok!":")`);
478             mixin(nullCheck!`(node.right = parseAsmExp())`);
479         }
480         return node;
481     }
482 
483     /**
484      * Parses an AsmInstruction
485      *
486      * $(GRAMMAR $(RULEDEF asmInstruction):
487      *       $(LITERAL Identifier)
488      *     | $(LITERAL 'align') $(LITERAL IntegerLiteral)
489      *     | $(LITERAL 'align') $(LITERAL Identifier)
490      *     | $(LITERAL Identifier) $(LITERAL ':') $(RULE asmInstruction)
491      *     | $(LITERAL Identifier) $(RULE operands)
492      *     | $(LITERAL 'in') $(RULE operands)
493      *     | $(LITERAL 'out') $(RULE operands)
494      *     | $(LITERAL 'int') $(RULE operands)
495      *     ;)
496      */
497     AsmInstruction parseAsmInstruction()
498     {
499         import std.range : assumeSorted;
500         mixin(traceEnterAndExit!(__FUNCTION__));
501         AsmInstruction node = allocate!AsmInstruction;
502         if (currentIs(tok!"align"))
503         {
504             advance(); // align
505             node.hasAlign = true;
506             if (currentIsOneOf(tok!"intLiteral", tok!"identifier"))
507                 node.identifierOrIntegerOrOpcode = advance();
508             else
509                 error("Identifier or integer literal expected.");
510         }
511         else if (currentIsOneOf(tok!"identifier", tok!"in", tok!"out", tok!"int"))
512         {
513             node.identifierOrIntegerOrOpcode = advance();
514             if (node.identifierOrIntegerOrOpcode == tok!"identifier" && currentIs(tok!":"))
515             {
516                 advance(); // :
517                 mixin(nullCheck!`node.asmInstruction = parseAsmInstruction()`);
518             }
519             else if (!currentIs(tok!";"))
520                 mixin(nullCheck!`node.operands = parseOperands()`);
521         }
522         return node;
523     }
524 
525     /**
526      * Parses an AsmLogAndExp
527      *
528      * $(GRAMMAR $(RULEDEF asmLogAndExp):
529      *     $(RULE asmOrExp)
530      *     $(RULE asmLogAndExp) $(LITERAL '&&') $(RULE asmOrExp)
531      *     ;)
532      */
533     ExpressionNode parseAsmLogAndExp()
534     {
535         mixin(traceEnterAndExit!(__FUNCTION__));
536         return parseLeftAssocBinaryExpression!(AsmLogAndExp, AsmOrExp, tok!"&&");
537     }
538 
539     /**
540      * Parses an AsmLogOrExp
541      *
542      * $(GRAMMAR $(RULEDEF asmLogOrExp):
543      *       $(RULE asmLogAndExp)
544      *     | $(RULE asmLogOrExp) '||' $(RULE asmLogAndExp)
545      *     ;)
546      */
547     ExpressionNode parseAsmLogOrExp()
548     {
549         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
550         return parseLeftAssocBinaryExpression!(AsmLogOrExp, AsmLogAndExp, tok!"||")();
551     }
552 
553     /**
554      * Parses an AsmMulExp
555      *
556      * $(GRAMMAR $(RULEDEF asmMulExp):
557      *       $(RULE asmBrExp)
558      *     | $(RULE asmMulExp) ($(LITERAL '*') | $(LITERAL '/') | $(LITERAL '%')) $(RULE asmBrExp)
559      *     ;)
560      */
561     ExpressionNode parseAsmMulExp()
562     {
563         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
564         return parseLeftAssocBinaryExpression!(AsmMulExp, AsmBrExp, tok!"*", tok!"/", tok!"%")();
565     }
566 
567     /**
568      * Parses an AsmOrExp
569      *
570      * $(GRAMMAR $(RULEDEF asmOrExp):
571      *       $(RULE asmXorExp)
572      *     | $(RULE asmOrExp) $(LITERAL '|') $(RULE asmXorExp)
573      *     ;)
574      */
575     ExpressionNode parseAsmOrExp()
576     {
577         mixin(traceEnterAndExit!(__FUNCTION__));
578         return parseLeftAssocBinaryExpression!(AsmOrExp, AsmXorExp, tok!"|")();
579     }
580 
581     /**
582      * Parses an AsmPrimaryExp
583      *
584      * $(GRAMMAR $(RULEDEF asmPrimaryExp):
585      *       $(LITERAL IntegerLiteral)
586      *     | $(LITERAL FloatLiteral)
587      *     | $(LITERAL StringLiteral)
588      *     | $(RULE register)
589      *     | $(RULE identifierChain)
590      *     | $(LITERAL '$')
591      *     ;)
592      */
593     AsmPrimaryExp parseAsmPrimaryExp()
594     {
595         import std.range : assumeSorted;
596         mixin(traceEnterAndExit!(__FUNCTION__));
597         AsmPrimaryExp node = allocate!AsmPrimaryExp();
598         switch (current().type)
599         {
600         case tok!"doubleLiteral":
601         case tok!"floatLiteral":
602         case tok!"intLiteral":
603         case tok!"longLiteral":
604         case tok!"stringLiteral":
605         case tok!"$":
606             node.token = advance();
607             break;
608         case tok!"identifier":
609             if (assumeSorted(REGISTER_NAMES).equalRange(current().text).length > 0)
610             {
611                 trace("Found register");
612                 mixin(nullCheck!`(node.register = parseRegister())`);
613             }
614             else
615                 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`);
616             break;
617         default:
618             error("Float literal, integer literal, $, or identifier expected.");
619             return null;
620         }
621         return node;
622     }
623 
624     /**
625      * Parses an AsmRelExp
626      *
627      * $(GRAMMAR $(RULEDEF asmRelExp):
628      *       $(RULE asmShiftExp)
629      *     | $(RULE asmRelExp) (($(LITERAL '<') | $(LITERAL '<=') | $(LITERAL '>') | $(LITERAL '>=')) $(RULE asmShiftExp))?
630      *     ;)
631      */
632     ExpressionNode parseAsmRelExp()
633     {
634         mixin(traceEnterAndExit!(__FUNCTION__));
635         return parseLeftAssocBinaryExpression!(AsmRelExp, AsmShiftExp, tok!"<",
636             tok!"<=", tok!">", tok!">=")();
637     }
638 
639     /**
640      * Parses an AsmShiftExp
641      *
642      * $(GRAMMAR $(RULEDEF asmShiftExp):
643      *     $(RULE asmAddExp)
644      *     $(RULE asmShiftExp) ($(LITERAL '<<') | $(LITERAL '>>') | $(LITERAL '>>>')) $(RULE asmAddExp)
645      *     ;)
646      */
647     ExpressionNode parseAsmShiftExp()
648     {
649         mixin(traceEnterAndExit!(__FUNCTION__));
650         return parseLeftAssocBinaryExpression!(AsmShiftExp, AsmAddExp, tok!"<<",
651             tok!">>", tok!">>>");
652     }
653 
654     /**
655      * Parses an AsmStatement
656      *
657      * $(GRAMMAR $(RULEDEF asmStatement):
658      *     $(LITERAL 'asm') $(RULE functionAttributes)? $(LITERAL '{') $(RULE asmInstruction)+ $(LITERAL '}')
659      *     ;)
660      */
661     AsmStatement parseAsmStatement()
662     {
663         mixin(traceEnterAndExit!(__FUNCTION__));
664         AsmStatement node = allocate!AsmStatement;
665         AsmInstruction[] instructions;
666         advance(); // asm
667         FunctionAttribute[] functionAttributes;
668         while (isAttribute())
669         {
670             auto attr = parseFunctionAttribute();
671             if (attr is null)
672             {
673                 error("Function attribute or '{' expected");
674                 return null;
675             }
676             functionAttributes ~= attr;
677         }
678         node.functionAttributes = ownArray(functionAttributes);
679         advance(); // {
680         while (moreTokens() && !currentIs(tok!"}"))
681         {
682             AsmInstruction instruction = parseAsmInstruction();
683             if (instruction is null)
684                 return null;
685             if (!expect(tok!";"))
686                 return null;
687             instructions ~= instruction;
688         }
689         node.asmInstructions = ownArray(instructions);
690         expect(tok!"}");
691         return node;
692     }
693 
694     /**
695      * Parses an AsmTypePrefix
696      *
697      * Note that in the following grammar definition the first identifier must
698      * be "near", "far", "word", "dword", or "qword". The second identifier must
699      * be "ptr".
700      *
701      * $(GRAMMAR $(RULEDEF asmTypePrefix):
702      *       $(LITERAL Identifier) $(LITERAL Identifier)?
703      *     | $(LITERAL 'byte') $(LITERAL Identifier)?
704      *     | $(LITERAL 'short') $(LITERAL Identifier)?
705      *     | $(LITERAL 'int') $(LITERAL Identifier)?
706      *     | $(LITERAL 'float') $(LITERAL Identifier)?
707      *     | $(LITERAL 'double') $(LITERAL Identifier)?
708      *     | $(LITERAL 'real') $(LITERAL Identifier)?
709      *     ;)
710      */
711     AsmTypePrefix parseAsmTypePrefix()
712     {
713         mixin(traceEnterAndExit!(__FUNCTION__));
714         switch (current().type)
715         {
716         case tok!"identifier":
717         case tok!"byte":
718         case tok!"short":
719         case tok!"int":
720         case tok!"float":
721         case tok!"double":
722         case tok!"real":
723             AsmTypePrefix prefix = allocate!AsmTypePrefix();
724             prefix.left = advance();
725             if (prefix.left.type == tok!"identifier") switch (prefix.left.text)
726             {
727             case "near":
728             case "far":
729             case "word":
730             case "dword":
731             case "qword":
732                 break;
733             default:
734                 error("ASM type prefix expected");
735                 return null;
736             }
737             if (currentIs(tok!"identifier") && current().text == "ptr")
738                 prefix.right = advance();
739             return prefix;
740         default:
741             error("Expected an identifier, 'byte', 'short', 'int', 'float', 'double', or 'real'");
742             return null;
743         }
744     }
745 
746     /**
747      * Parses an AsmUnaExp
748      *
749      * $(GRAMMAR $(RULEDEF asmUnaExp):
750      *       $(RULE asmTypePrefix) $(RULE asmExp)
751      *     | $(LITERAL Identifier) $(RULE asmExp)
752      *     | $(LITERAL '+') $(RULE asmUnaExp)
753      *     | $(LITERAL '-') $(RULE asmUnaExp)
754      *     | $(LITERAL '!') $(RULE asmUnaExp)
755      *     | $(LITERAL '~') $(RULE asmUnaExp)
756      *     | $(RULE asmPrimaryExp)
757      *     ;)
758      */
759     AsmUnaExp parseAsmUnaExp()
760     {
761         mixin(traceEnterAndExit!(__FUNCTION__));
762         AsmUnaExp node = allocate!AsmUnaExp();
763         switch (current().type)
764         {
765         case tok!"+":
766         case tok!"-":
767         case tok!"!":
768         case tok!"~":
769             node.prefix = advance();
770             mixin(nullCheck!`node.asmUnaExp = parseAsmUnaExp()`);
771             break;
772         case tok!"byte":
773         case tok!"short":
774         case tok!"int":
775         case tok!"float":
776         case tok!"double":
777         case tok!"real":
778         typePrefix:
779             mixin(nullCheck!`node.asmTypePrefix = parseAsmTypePrefix()`);
780             mixin(nullCheck!`node.asmExp = parseAsmExp()`);
781             break;
782         case tok!"identifier":
783             switch (current().text)
784             {
785             case "offsetof":
786             case "seg":
787                 node.prefix = advance();
788                 mixin(nullCheck!`node.asmExp = parseAsmExp()`);
789                 break;
790             case "near":
791             case "far":
792             case "word":
793             case "dword":
794             case "qword":
795                 goto typePrefix;
796             default:
797                 goto outerDefault;
798             }
799             break;
800         outerDefault:
801         default:
802             mixin(nullCheck!`node.asmPrimaryExp = parseAsmPrimaryExp()`);
803             break;
804         }
805         return node;
806     }
807 
808     /**
809      * Parses an AsmXorExp
810      *
811      * $(GRAMMAR $(RULEDEF asmXorExp):
812      *       $(RULE asmAndExp)
813      *     | $(RULE asmXorExp) $(LITERAL '^') $(RULE asmAndExp)
814      *     ;)
815      */
816     ExpressionNode parseAsmXorExp()
817     {
818         mixin(traceEnterAndExit!(__FUNCTION__));
819         return parseLeftAssocBinaryExpression!(AsmXorExp, AsmAndExp, tok!"^")();
820     }
821 
822     /**
823      * Parses an AssertExpression
824      *
825      * $(GRAMMAR $(RULEDEF assertExpression):
826      *     $(LITERAL 'assert') $(LITERAL '$(LPAREN)') $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression))? $(LITERAL '$(RPAREN)')
827      *     ;)
828      */
829     AssertExpression parseAssertExpression()
830     {
831         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
832         auto node = allocate!AssertExpression;
833         node.line = current.line;
834         node.column = current.column;
835         advance(); // "assert"
836         mixin(nullCheck!`expect(tok!"(")`);
837         mixin(nullCheck!`node.assertion = parseAssignExpression()`);
838         if (currentIs(tok!","))
839         {
840             advance();
841             mixin(nullCheck!`node.message = parseAssignExpression()`);
842         }
843         mixin(nullCheck!`expect(tok!")")`);
844         return node;
845     }
846 
847     /**
848      * Parses an AssignExpression
849      *
850      * $(GRAMMAR $(RULEDEF assignExpression):
851      *     $(RULE ternaryExpression) ($(RULE assignOperator) $(RULE expression))?
852      *     ;
853      *$(RULEDEF assignOperator):
854      *       $(LITERAL '=')
855      *     | $(LITERAL '>>>=')
856      *     | $(LITERAL '>>=')
857      *     | $(LITERAL '<<=')
858      *     | $(LITERAL '+=')
859      *     | $(LITERAL '-=')
860      *     | $(LITERAL '*=')
861      *     | $(LITERAL '%=')
862      *     | $(LITERAL '&=')
863      *     | $(LITERAL '/=')
864      *     | $(LITERAL '|=')
865      *     | $(LITERAL '^^=')
866      *     | $(LITERAL '^=')
867      *     | $(LITERAL '~=')
868      *     ;)
869      */
870     ExpressionNode parseAssignExpression()
871     {
872         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
873         if (!moreTokens)
874         {
875             error("Assign expression expected instead of EOF");
876             return null;
877         }
878         auto ternary = parseTernaryExpression();
879         if (ternary is null)
880             return null;
881         if (currentIsOneOf(tok!"=", tok!">>>=",
882             tok!">>=", tok!"<<=",
883             tok!"+=", tok!"-=", tok!"*=",
884             tok!"%=", tok!"&=", tok!"/=",
885             tok!"|=", tok!"^^=", tok!"^=",
886             tok!"~="))
887         {
888             auto node = allocate!AssignExpression;
889             node.line = current().line;
890             node.column = current().column;
891             node.ternaryExpression = ternary;
892             node.operator = advance().type;
893             mixin(nullCheck!`node.expression = parseExpression()`);
894             return node;
895         }
896         return ternary;
897     }
898 
899     /**
900      * Parses an AssocArrayLiteral
901      *
902      * $(GRAMMAR $(RULEDEF assocArrayLiteral):
903      *     $(LITERAL '[') $(RULE keyValuePairs) $(LITERAL ']')
904      *     ;)
905      */
906     AssocArrayLiteral parseAssocArrayLiteral()
907     {
908         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
909         mixin(simpleParse!(AssocArrayLiteral, tok!"[",
910             "keyValuePairs|parseKeyValuePairs", tok!"]"));
911     }
912 
913     /**
914      * Parses an AtAttribute
915      *
916      * $(GRAMMAR $(RULEDEF atAttribute):
917      *       $(LITERAL '@') $(LITERAL Identifier)
918      *     | $(LITERAL '@') $(LITERAL Identifier) $(LITERAL '$(LPAREN)') $(RULE argumentList)? $(LITERAL '$(RPAREN)')
919      *     | $(LITERAL '@') $(LITERAL '$(LPAREN)') $(RULE argumentList) $(LITERAL '$(RPAREN)')
920      *     ;)
921      */
922     AtAttribute parseAtAttribute()
923     {
924         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
925         auto node = allocate!AtAttribute;
926         const start = expect(tok!"@");
927         mixin(nullCheck!`start`);
928         if (!moreTokens)
929         {
930             error(`"(", or identifier expected`);
931             return null;
932         }
933         node.startLocation = start.index;
934 
935 	if(currentIs(tok!"(")) {
936 		advance();
937         	mixin(nullCheck!`node.argumentList = parseArgumentList()`);
938 		expect(tok!")");
939 	} else {
940             if(currentIs(tok!"identifier")) {
941                 node.argumentList = new ArgumentList;
942                 ExpressionNode wtf = parseUnaryExpression();
943                 node.argumentList.items ~= wtf;
944 
945         	//mixin(nullCheck!`node.argumentList = parseArgumentList()`);
946             } else
947                 error("( or identifier expected");
948 	}
949 
950 	    // I don't think any of this following spam is necessary and I know it isn't correct, let's just use this one thing and see how it goes
951 	    version(none)
952         switch (current.type)
953         {
954         case tok!"identifier":
955             node.identifier = advance();
956             if (currentIs(tok!"("))
957             {
958                 advance(); // (
959                 if (!currentIs(tok!")"))
960                     mixin(nullCheck!`node.argumentList = parseArgumentList()`);
961                 expect(tok!")");
962             } else if(currentIs(tok!("!")))
963 	    {
964 	    advance(); // !
965             advance();
966             mixin(nullCheck!`node.argumentList = parseArgumentList()`);
967             expect(tok!")");
968 
969 	    }
970             break;
971         case tok!"(":
972             advance();
973             mixin(nullCheck!`node.argumentList = parseArgumentList()`);
974             expect(tok!")");
975             break;
976         default:
977             error(`"(", or identifier expected`);
978             return null;
979         }
980         if (moreTokens) node.endLocation = current().index;
981         return node;
982     }
983 
984     /**
985      * Parses an Attribute
986      *
987      * $(GRAMMAR $(RULEDEF attribute):
988      *     | $(RULE pragmaExpression)
989      *     | $(RULE alignAttribute)
990      *     | $(RULE deprecated)
991      *     | $(RULE atAttribute)
992      *     | $(RULE linkageAttribute)
993      *     | $(LITERAL 'export')
994      *     | $(LITERAL 'package')
995      *     | $(LITERAL 'private')
996      *     | $(LITERAL 'protected')
997      *     | $(LITERAL 'public')
998      *     | $(LITERAL 'static')
999      *     | $(LITERAL 'extern')
1000      *     | $(LITERAL 'abstract')
1001      *     | $(LITERAL 'final')
1002      *     | $(LITERAL 'override')
1003      *     | $(LITERAL 'synchronized')
1004      *     | $(LITERAL 'auto')
1005      *     | $(LITERAL 'scope')
1006      *     | $(LITERAL 'const')
1007      *     | $(LITERAL 'immutable')
1008      *     | $(LITERAL 'inout')
1009      *     | $(LITERAL 'shared')
1010      *     | $(LITERAL '__gshared')
1011      *     | $(LITERAL 'nothrow')
1012      *     | $(LITERAL 'pure')
1013      *     | $(LITERAL 'ref')
1014      *     ;)
1015      */
1016     Attribute parseAttribute()
1017     {
1018         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1019         auto node = allocate!Attribute;
1020         switch (current.type)
1021         {
1022         case tok!"pragma":
1023             mixin(nullCheck!`node.pragmaExpression = parsePragmaExpression()`);
1024             break;
1025         case tok!"deprecated":
1026             mixin(nullCheck!`node.deprecated_ = parseDeprecated()`);
1027             break;
1028         case tok!"align":
1029             mixin(nullCheck!`node.alignAttribute = parseAlignAttribute()`);
1030             break;
1031         case tok!"@":
1032             mixin(nullCheck!`node.atAttribute = parseAtAttribute()`);
1033             break;
1034         case tok!"extern":
1035             if (peekIs(tok!"("))
1036             {
1037                 mixin(nullCheck!`node.linkageAttribute = parseLinkageAttribute()`);
1038                 break;
1039             }
1040             else
1041                 goto case;
1042         case tok!"package":
1043             node.attribute = advance();
1044             if (currentIs(tok!"("))
1045             {
1046                 expect(tok!"(");
1047                 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`);
1048                 expect(tok!")");
1049             }
1050             break;
1051         case tok!"private":
1052         case tok!"protected":
1053         case tok!"public":
1054         case tok!"export":
1055         case tok!"static":
1056         case tok!"abstract":
1057         case tok!"final":
1058         case tok!"override":
1059         case tok!"synchronized":
1060         case tok!"auto":
1061         case tok!"scope":
1062         case tok!"const":
1063         case tok!"immutable":
1064         case tok!"inout":
1065         case tok!"shared":
1066         case tok!"__gshared":
1067         case tok!"nothrow":
1068         case tok!"pure":
1069         case tok!"ref":
1070             node.attribute = advance();
1071             break;
1072         default:
1073             deallocate(node);
1074             return null;
1075         }
1076         return node;
1077     }
1078 
1079     /**
1080      * Parses an AttributeDeclaration
1081      *
1082      * $(GRAMMAR $(RULEDEF attributeDeclaration):
1083      *     $(RULE attribute) $(LITERAL ':')
1084      *     ;)
1085      */
1086     AttributeDeclaration parseAttributeDeclaration(Attribute attribute = null)
1087     {
1088         auto node = allocate!AttributeDeclaration;
1089         node.line = current.line;
1090         node.attribute = attribute is null ? parseAttribute() : attribute;
1091         expect(tok!":");
1092         return node;
1093     }
1094 
1095     /**
1096      * Parses an AutoDeclaration
1097      *
1098      * $(GRAMMAR $(RULEDEF autoDeclaration):
1099      *     $(RULE storageClass)+ $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer) ($(LITERAL ',') $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer))* $(LITERAL ';')
1100      *     ;)
1101      */
1102     AutoDeclaration parseAutoDeclaration()
1103     {
1104         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1105         auto node = allocate!AutoDeclaration;
1106         node.comment = comment;
1107         comment = null;
1108         StorageClass[] storageClasses;
1109         while (isStorageClass())
1110         {
1111             auto s = parseStorageClass();
1112             mixin(nullCheck!`s`);
1113             storageClasses ~= s;
1114         }
1115         node.storageClasses = ownArray(storageClasses);
1116         Token[] identifiers;
1117         Initializer[] initializers;
1118         do
1119         {
1120             const ident = expect(tok!"identifier");
1121             mixin(nullCheck!`ident`);
1122             identifiers ~= *ident;
1123             mixin(nullCheck!`expect(tok!"=")`);
1124             auto init = parseInitializer();
1125             mixin(nullCheck!`init`);
1126             initializers ~= init;
1127             if (currentIs(tok!","))
1128                 advance();
1129             else
1130                 break;
1131         } while (moreTokens());
1132         node.identifiers = ownArray(identifiers);
1133         node.initializers = ownArray(initializers);
1134         auto semicolon = expect(tok!";");
1135 	if(semicolon !is null)
1136 	        node.comment ~= semicolon.trailingComment;
1137         return node;
1138     }
1139 
1140     /**
1141      * Parses a BlockStatement
1142      *
1143      * $(GRAMMAR $(RULEDEF blockStatement):
1144      *     $(LITERAL '{') $(RULE declarationsAndStatements)? $(LITERAL '}')
1145      *     ;)
1146      */
1147     BlockStatement parseBlockStatement()
1148     {
1149         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1150         auto node = allocate!BlockStatement;
1151         const openBrace = expect(tok!"{");
1152         mixin(nullCheck!`openBrace`);
1153         node.startLocation = openBrace.index;
1154         if (!currentIs(tok!"}"))
1155         {
1156             mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`);
1157         }
1158         const closeBrace = expect(tok!"}");
1159         if (closeBrace !is null)
1160             node.endLocation = closeBrace.index;
1161         else
1162         {
1163 	//import std.stdio; writeln(node.startLocation);
1164 	//assert(0);
1165             trace("Could not find end of block statement.");
1166             node.endLocation = size_t.max;
1167         }
1168 
1169         return node;
1170     }
1171 
1172     /**
1173      * Parses a BodyStatement
1174      *
1175      * $(GRAMMAR $(RULEDEF bodyStatement):
1176      *     $(LITERAL 'body') $(RULE blockStatement)
1177      *     ;)
1178      */
1179     BodyStatement parseBodyStatement()
1180     {
1181 	advance();
1182 	hackFunctionBody();
1183 	return new BodyStatement();
1184 
1185         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1186         mixin(simpleParse!(BodyStatement, tok!"body",
1187             "blockStatement|parseBlockStatement"));
1188     }
1189 
1190     BodyStatement parseBodyDoStatement()
1191     {
1192 	advance();
1193 	hackFunctionBody();
1194 	return new BodyStatement;
1195 
1196         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1197         mixin(simpleParse!(BodyStatement, tok!"do",
1198             "blockStatement|parseBlockStatement"));
1199     }
1200 
1201     void hackFunctionBody() {
1202     	int braceCount = 1;
1203 	assert(currentIs(tok!"{"));
1204 	advance();
1205 	while(braceCount > 0) {
1206 		if(currentIs(tok!"{"))
1207 			braceCount++;
1208 		else if(currentIs(tok!"}"))
1209 			braceCount--;
1210 		advance();
1211 	}
1212     }
1213 
1214     /**
1215      * Parses a BreakStatement
1216      *
1217      * $(GRAMMAR $(RULEDEF breakStatement):
1218      *     $(LITERAL 'break') $(LITERAL Identifier)? $(LITERAL ';')
1219      *     ;)
1220      */
1221     BreakStatement parseBreakStatement()
1222     {
1223         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1224         expect(tok!"break");
1225         auto node = allocate!BreakStatement;
1226         switch (current.type)
1227         {
1228         case tok!"identifier":
1229             node.label = advance();
1230             mixin(nullCheck!`expect(tok!";")`);
1231             break;
1232         case tok!";":
1233             advance();
1234             break;
1235         default:
1236             error("Identifier or semicolon expected following \"break\"");
1237             return null;
1238         }
1239         return node;
1240     }
1241 
1242     /**
1243      * Parses a BaseClass
1244      *
1245      * $(GRAMMAR $(RULEDEF baseClass):
1246      *     $(RULE type2)
1247      *     ;)
1248      */
1249     BaseClass parseBaseClass()
1250     {
1251         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1252         auto node = allocate!BaseClass;
1253         if (current.type.isProtection())
1254         {
1255             warn("Use of base class protection is deprecated.");
1256             advance();
1257         }
1258         if ((node.type2 = parseType2()) is null)
1259         {
1260             deallocate(node);
1261             return null;
1262         }
1263         return node;
1264     }
1265 
1266     /**
1267      * Parses a BaseClassList
1268      *
1269      * $(GRAMMAR $(RULEDEF baseClassList):
1270      *     $(RULE baseClass) ($(LITERAL ',') $(RULE baseClass))*
1271      *     ;)
1272      */
1273     BaseClassList parseBaseClassList()
1274     {
1275         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1276         return parseCommaSeparatedRule!(BaseClassList, BaseClass)();
1277     }
1278 
1279     /**
1280      * Parses an BuiltinType
1281      *
1282      * $(GRAMMAR $(RULEDEF builtinType):
1283      *      $(LITERAL 'bool')
1284      *    | $(LITERAL 'byte')
1285      *    | $(LITERAL 'ubyte')
1286      *    | $(LITERAL 'short')
1287      *    | $(LITERAL 'ushort')
1288      *    | $(LITERAL 'int')
1289      *    | $(LITERAL 'uint')
1290      *    | $(LITERAL 'long')
1291      *    | $(LITERAL 'ulong')
1292      *    | $(LITERAL 'char')
1293      *    | $(LITERAL 'wchar')
1294      *    | $(LITERAL 'dchar')
1295      *    | $(LITERAL 'float')
1296      *    | $(LITERAL 'double')
1297      *    | $(LITERAL 'real')
1298      *    | $(LITERAL 'ifloat')
1299      *    | $(LITERAL 'idouble')
1300      *    | $(LITERAL 'ireal')
1301      *    | $(LITERAL 'cfloat')
1302      *    | $(LITERAL 'cdouble')
1303      *    | $(LITERAL 'creal')
1304      *    | $(LITERAL 'void')
1305      *    ;)
1306      */
1307     IdType parseBuiltinType()
1308     {
1309         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1310         return advance().type;
1311     }
1312 
1313     /**
1314      * Parses a CaseRangeStatement
1315      *
1316      * $(GRAMMAR $(RULEDEF caseRangeStatement):
1317      *     $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(LITERAL '...') $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(RULE declarationsAndStatements)
1318      *     ;)
1319      */
1320     CaseRangeStatement parseCaseRangeStatement(ExpressionNode low)
1321     {
1322         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1323         auto node = allocate!CaseRangeStatement;
1324         assert (low !is null);
1325         node.low = low;
1326         mixin(nullCheck!`expect(tok!":")`);
1327         mixin(nullCheck!`expect(tok!"..")`);
1328         expect(tok!"case");
1329         mixin(nullCheck!`node.high = parseAssignExpression()`);
1330         const colon = expect(tok!":");
1331         if (colon is null)
1332         {
1333             deallocate(node);
1334             return null;
1335         }
1336         node.colonLocation = colon.index;
1337         mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`);
1338         return node;
1339     }
1340 
1341     /**
1342      * Parses an CaseStatement
1343      *
1344      * $(GRAMMAR $(RULEDEF caseStatement):
1345      *     $(LITERAL 'case') $(RULE argumentList) $(LITERAL ':') $(RULE declarationsAndStatements)
1346      *     ;)
1347      */
1348     CaseStatement parseCaseStatement(ArgumentList argumentList = null)
1349     {
1350         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1351         auto node = allocate!CaseStatement;
1352         node.argumentList = argumentList;
1353         const colon = expect(tok!":");
1354         if (colon is null)
1355         {
1356             deallocate(node);
1357             return null;
1358         }
1359         node.colonLocation = colon.index;
1360         mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`);
1361         return node;
1362     }
1363 
1364     /**
1365      * Parses a CastExpression
1366      *
1367      * $(GRAMMAR $(RULEDEF castExpression):
1368      *     $(LITERAL 'cast') $(LITERAL '$(LPAREN)') ($(RULE type) | $(RULE castQualifier))? $(LITERAL '$(RPAREN)') $(RULE unaryExpression)
1369      *     ;)
1370      */
1371     CastExpression parseCastExpression()
1372     {
1373         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1374         auto node = allocate!CastExpression;
1375         expect(tok!"cast");
1376         mixin(nullCheck!`expect(tok!"(")`);
1377         if (!currentIs(tok!")"))
1378         {
1379             if (isCastQualifier())
1380                 mixin(nullCheck!`node.castQualifier = parseCastQualifier()`);
1381             else
1382                 mixin(nullCheck!`node.type = parseType()`);
1383         }
1384         mixin(nullCheck!`expect(tok!")")`);
1385         mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`);
1386         return node;
1387     }
1388 
1389     /**
1390      * Parses a CastQualifier
1391      *
1392      * $(GRAMMAR $(RULEDEF castQualifier):
1393      *      $(LITERAL 'const')
1394      *    | $(LITERAL 'const') $(LITERAL 'shared')
1395      *    | $(LITERAL 'immutable')
1396      *    | $(LITERAL 'inout')
1397      *    | $(LITERAL 'inout') $(LITERAL 'shared')
1398      *    | $(LITERAL 'shared')
1399      *    | $(LITERAL 'shared') $(LITERAL 'const')
1400      *    | $(LITERAL 'shared') $(LITERAL 'inout')
1401      *    ;)
1402      */
1403     CastQualifier parseCastQualifier()
1404     {
1405         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1406         auto node = allocate!CastQualifier;
1407         switch (current.type)
1408         {
1409         case tok!"inout":
1410         case tok!"const":
1411             node.first = advance();
1412             if (currentIs(tok!"shared"))
1413                 node.second = advance();
1414             break;
1415         case tok!"shared":
1416             node.first = advance();
1417             if (currentIsOneOf(tok!"const", tok!"inout"))
1418                 node.second = advance();
1419             break;
1420         case tok!"immutable":
1421             node.first = advance();
1422             break;
1423         default:
1424             error("const, immutable, inout, or shared expected");
1425             return null;
1426         }
1427         return node;
1428     }
1429 
1430     /**
1431      * Parses a Catch
1432      *
1433      * $(GRAMMAR $(RULEDEF catch):
1434      *     $(LITERAL 'catch') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL Identifier)? $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement)
1435      *     ;)
1436      */
1437     Catch parseCatch()
1438     {
1439         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1440         auto node = allocate!Catch;
1441         expect(tok!"catch");
1442         mixin(nullCheck!`expect(tok!"(")`);
1443         mixin(nullCheck!`node.type = parseType()`);
1444         if (currentIs(tok!"identifier"))
1445             node.identifier = advance();
1446         mixin(nullCheck!`expect(tok!")")`);
1447         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
1448         return node;
1449     }
1450 
1451     /**
1452      * Parses a Catches
1453      *
1454      * $(GRAMMAR $(RULEDEF catches):
1455      *       $(RULE catch)+
1456      *     | $(RULE catch)* $(RULE lastCatch)
1457      *     ;)
1458      */
1459     Catches parseCatches()
1460     {
1461         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1462         auto node = allocate!Catches;
1463         Catch[] catches;
1464         while (moreTokens())
1465         {
1466             if (!currentIs(tok!"catch"))
1467                 break;
1468             if (peekIs(tok!"("))
1469                 catches ~= parseCatch();
1470             else
1471             {
1472                 node.lastCatch  = parseLastCatch();
1473                 break;
1474             }
1475         }
1476         node.catches = ownArray(catches);
1477         return node;
1478     }
1479 
1480     /**
1481      * Parses a ClassDeclaration
1482      *
1483      * $(GRAMMAR $(RULEDEF classDeclaration):
1484      *       $(LITERAL 'class') $(LITERAL Identifier) $(LITERAL ';')
1485      *     | $(LITERAL 'class') $(LITERAL Identifier) ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody)
1486      *     | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(RULE structBody) | $(LITERAL ';'))
1487      *     | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody)
1488      *     | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) ($(LITERAL ':') $(RULE baseClassList))? $(RULE constraint)? $(RULE structBody)
1489      *     ;)
1490      */
1491     ClassDeclaration parseClassDeclaration()
1492     {
1493         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1494         auto node = allocate!ClassDeclaration;
1495         expect(tok!"class");
1496         mixin(PARSE_INTERFACE_OR_CLASS);
1497     }
1498 
1499     /**
1500      * Parses a CmpExpression
1501      *
1502      * $(GRAMMAR $(RULEDEF cmpExpression):
1503      *       $(RULE shiftExpression)
1504      *     | $(RULE equalExpression)
1505      *     | $(RULE identityExpression)
1506      *     | $(RULE relExpression)
1507      *     | $(RULE inExpression)
1508      *     ;)
1509      */
1510     ExpressionNode parseCmpExpression()
1511     {
1512         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1513         auto shift = parseShiftExpression();
1514         if (shift is null)
1515             return null;
1516         if (!moreTokens())
1517             return shift;
1518         switch (current.type)
1519         {
1520         case tok!"is":
1521             auto node = allocate!CmpExpression;
1522             mixin(nullCheck!`node.identityExpression = parseIdentityExpression(shift)`);
1523             return node;
1524         case tok!"in":
1525             auto node = allocate!CmpExpression;
1526             mixin(nullCheck!`node.inExpression = parseInExpression(shift)`);
1527             return node;
1528         case tok!"!":
1529             auto node = allocate!CmpExpression;
1530             if (peekIs(tok!"is"))
1531                 mixin(nullCheck!`node.identityExpression = parseIdentityExpression(shift)`);
1532             else if (peekIs(tok!"in"))
1533                 mixin(nullCheck!`node.inExpression = parseInExpression(shift)`);
1534             return node;
1535         case tok!"<":
1536         case tok!"<=":
1537         case tok!">":
1538         case tok!">=":
1539         case tok!"!<>=":
1540         case tok!"!<>":
1541         case tok!"<>":
1542         case tok!"<>=":
1543         case tok!"!>":
1544         case tok!"!>=":
1545         case tok!"!<":
1546         case tok!"!<=":
1547             auto node = allocate!CmpExpression;
1548             mixin(nullCheck!`node.relExpression = parseRelExpression(shift)`);
1549             return node;
1550         case tok!"==":
1551         case tok!"!=":
1552             auto node = allocate!CmpExpression;
1553             mixin(nullCheck!`node.equalExpression = parseEqualExpression(shift)`);
1554             return node;
1555         default:
1556             return shift;
1557         }
1558     }
1559 
1560     /**
1561      * Parses a CompileCondition
1562      *
1563      * $(GRAMMAR $(RULEDEF compileCondition):
1564      *       $(RULE versionCondition)
1565      *     | $(RULE debugCondition)
1566      *     | $(RULE staticIfCondition)
1567      *     ;)
1568      */
1569     CompileCondition parseCompileCondition()
1570     {
1571         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1572         auto node = allocate!CompileCondition;
1573         switch (current.type)
1574         {
1575         case tok!"version":
1576             mixin(nullCheck!`node.versionCondition = parseVersionCondition()`);
1577             break;
1578         case tok!"debug":
1579             mixin(nullCheck!`node.debugCondition = parseDebugCondition()`);
1580             break;
1581         case tok!"static":
1582             mixin(nullCheck!`node.staticIfCondition = parseStaticIfCondition()`);
1583             break;
1584         default:
1585             error(`"version", "debug", or "static" expected`);
1586             return null;
1587         }
1588         return node;
1589     }
1590 
1591     /**
1592      * Parses a ConditionalDeclaration
1593      *
1594      * $(GRAMMAR $(RULEDEF conditionalDeclaration):
1595      *       $(RULE compileCondition) $(RULE declaration)
1596      *     | $(RULE compileCondition) $(LITERAL ':') $(RULE declaration)+
1597      *     | $(RULE compileCondition) $(RULE declaration) $(LITERAL 'else') $(RULE declaration)
1598      *     ;)
1599      */
1600     ConditionalDeclaration parseConditionalDeclaration()
1601     {
1602         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1603         auto node = allocate!ConditionalDeclaration;
1604         mixin(nullCheck!`node.compileCondition = parseCompileCondition()`);
1605 
1606         Declaration[] trueDeclarations;
1607         if (currentIs(tok!":"))
1608         {
1609             advance();
1610             while (moreTokens() && !currentIs(tok!"}"))
1611             {
1612                 auto b = setBookmark();
1613                 auto d = parseDeclaration();
1614                 if (d !is null)
1615                 {
1616                     abandonBookmark(b);
1617                     trueDeclarations ~= d;
1618                 }
1619                 else
1620                 {
1621                     goToBookmark(b);
1622                     deallocate(node);
1623                     return null;
1624                 }
1625             }
1626             node.trueDeclarations = ownArray(trueDeclarations);
1627             return node;
1628         }
1629 
1630         auto dec = parseDeclaration(suppressMessages > 0);
1631         mixin(nullCheck!`dec`);
1632         trueDeclarations ~= dec;
1633         node.trueDeclarations = ownArray(trueDeclarations);
1634 
1635         if (currentIs(tok!"else"))
1636             advance();
1637         else
1638             return node;
1639 
1640         if ((node.falseDeclaration = parseDeclaration(suppressMessages > 0)) is null)
1641         {
1642             deallocate(node);
1643             return null;
1644         }
1645         return node;
1646     }
1647 
1648     /**
1649      * Parses a ConditionalStatement
1650      *
1651      * $(GRAMMAR $(RULEDEF conditionalStatement):
1652      *     $(RULE compileCondition) $(RULE declarationOrStatement) ($(LITERAL 'else') $(RULE declarationOrStatement))?
1653      *     ;)
1654      */
1655     ConditionalStatement parseConditionalStatement()
1656     {
1657         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1658         auto node = allocate!ConditionalStatement;
1659         mixin(nullCheck!`node.compileCondition = parseCompileCondition()`);
1660         mixin(nullCheck!`node.trueStatement = parseDeclarationOrStatement()`);
1661         if (currentIs(tok!"else"))
1662         {
1663             advance();
1664             mixin(nullCheck!`node.falseStatement = parseDeclarationOrStatement()`);
1665         }
1666         return node;
1667     }
1668 
1669     /**
1670      * Parses a Constraint
1671      *
1672      * $(GRAMMAR $(RULEDEF constraint):
1673      *     $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)')
1674      *     ;)
1675      */
1676     Constraint parseConstraint()
1677     {
1678         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1679         auto node = allocate!Constraint;
1680         mixin(nullCheck!`expect(tok!"if")`);
1681         mixin(nullCheck!`expect(tok!"(")`);
1682         mixin(nullCheck!`node.expression = parseExpression()`);
1683         mixin(nullCheck!`expect(tok!")")`);
1684         return node;
1685     }
1686 
1687     /**
1688      * Parses a Constructor
1689      *
1690      * $(GRAMMAR $(RULEDEF constructor):
1691      *       $(LITERAL 'this') $(RULE templateParameters)? $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';'))
1692      *     ;)
1693      */
1694     Constructor parseConstructor()
1695     {
1696         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1697         Constructor node = allocate!Constructor;
1698         node.comment = comment;
1699         comment = null;
1700         const t = expect(tok!"this");
1701         mixin(nullCheck!`t`);
1702         node.location = t.index;
1703         node.line = t.line;
1704         node.column = t.column;
1705         const p = peekPastParens();
1706         bool isTemplate = false;
1707         if (p !is null && p.type == tok!"(")
1708         {
1709             isTemplate = true;
1710             mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
1711         }
1712         mixin(nullCheck!`node.parameters = parseParameters()`);
1713         mixin(nullCheck!`node.parameters`);
1714 
1715         MemberFunctionAttribute[] memberFunctionAttributes;
1716         while (moreTokens() && currentIsMemberFunctionAttribute())
1717             memberFunctionAttributes ~= parseMemberFunctionAttribute();
1718         node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
1719 
1720         if (isTemplate && currentIs(tok!"if"))
1721             mixin(nullCheck!`node.constraint = parseConstraint()`);
1722 
1723         if (currentIs(tok!";"))
1724             advance();
1725         else
1726         {
1727             mixin(nullCheck!`node.functionBody = parseFunctionBody()`);
1728             mixin(nullCheck!`node.functionBody`);
1729         }
1730 
1731         return node;
1732     }
1733 
1734     /**
1735      * Parses an ContinueStatement
1736      *
1737      * $(GRAMMAR $(RULEDEF continueStatement):
1738      *     $(LITERAL 'continue') $(LITERAL Identifier)? $(LITERAL ';')
1739      *     ;)
1740      */
1741     ContinueStatement parseContinueStatement()
1742     {
1743         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1744         if (expect(tok!"continue") is null) return null;
1745         auto node = allocate!ContinueStatement;
1746         switch (current.type)
1747         {
1748         case tok!"identifier":
1749             node.label = advance();
1750             mixin(nullCheck!`expect(tok!";")`);
1751             break;
1752         case tok!";":
1753             advance();
1754             break;
1755         default:
1756             error(`Identifier or semicolon expected following "continue"`);
1757             return null;
1758         }
1759         return node;
1760     }
1761 
1762     /**
1763      * Parses a DebugCondition
1764      *
1765      * $(GRAMMAR $(RULEDEF debugCondition):
1766      *     $(LITERAL 'debug') ($(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier)) $(LITERAL '$(RPAREN)'))?
1767      *     ;)
1768      */
1769     DebugCondition parseDebugCondition()
1770     {
1771         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1772         auto node = allocate!DebugCondition;
1773 
1774         const d = expect(tok!"debug");
1775         mixin(nullCheck!`d`);
1776         node.debugIndex = d.index;
1777 
1778         if (currentIs(tok!"("))
1779         {
1780             advance();
1781             if (currentIsOneOf(tok!"intLiteral", tok!"identifier"))
1782                 node.identifierOrInteger = advance();
1783             else
1784             {
1785                 error(`Integer literal or identifier expected`);
1786                 return null;
1787             }
1788             mixin(nullCheck!`expect(tok!")")`);
1789         }
1790         return node;
1791     }
1792 
1793     /**
1794      * Parses a DebugSpecification
1795      *
1796      * $(GRAMMAR $(RULEDEF debugSpecification):
1797      *     $(LITERAL 'debug') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';')
1798      *     ;)
1799      */
1800     DebugSpecification parseDebugSpecification()
1801     {
1802         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1803         auto node = allocate!DebugSpecification;
1804         mixin(nullCheck!`expect(tok!"debug")`);
1805         mixin(nullCheck!`expect(tok!"=")`);
1806         if (currentIsOneOf(tok!"identifier", tok!"intLiteral"))
1807             node.identifierOrInteger = advance();
1808         else
1809         {
1810             error("Integer literal or identifier expected");
1811             return null;
1812         }
1813         mixin(nullCheck!`expect(tok!";")`);
1814         return node;
1815     }
1816 
1817     /**
1818      * Parses a Declaration
1819      *
1820      * Params: strict = if true, do not return partial AST nodes on errors.
1821      *
1822      * $(GRAMMAR $(RULEDEF declaration):
1823      *     $(RULE attribute)* $(RULE declaration2)
1824      *     ;
1825      * $(RULEDEF declaration2):
1826      *       $(RULE aliasDeclaration)
1827      *     | $(RULE aliasThisDeclaration)
1828      *     | $(RULE anonymousEnumDeclaration)
1829      *     | $(RULE attributeDeclaration)
1830      *     | $(RULE classDeclaration)
1831      *     | $(RULE conditionalDeclaration)
1832      *     | $(RULE constructor)
1833      *     | $(RULE debugSpecification)
1834      *     | $(RULE destructor)
1835      *     | $(RULE enumDeclaration)
1836      *     | $(RULE eponymousTemplateDeclaration)
1837      *     | $(RULE functionDeclaration)
1838      *     | $(RULE importDeclaration)
1839      *     | $(RULE interfaceDeclaration)
1840      *     | $(RULE invariant)
1841      *     | $(RULE mixinDeclaration)
1842      *     | $(RULE mixinTemplateDeclaration)
1843      *     | $(RULE pragmaDeclaration)
1844      *     | $(RULE sharedStaticConstructor)
1845      *     | $(RULE sharedStaticDestructor)
1846      *     | $(RULE staticAssertDeclaration)
1847      *     | $(RULE staticConstructor)
1848      *     | $(RULE staticDestructor)
1849      *     | $(RULE structDeclaration)
1850      *     | $(RULE templateDeclaration)
1851      *     | $(RULE unionDeclaration)
1852      *     | $(RULE unittest)
1853      *     | $(RULE variableDeclaration)
1854      *     | $(RULE versionSpecification)
1855      *     | $(LITERAL '{') $(RULE declaration)+ $(LITERAL '}')
1856      *     ;)
1857      */
1858     Declaration parseDeclaration(bool strict = false)
1859     {
1860         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
1861         auto node = allocate!Declaration;
1862         if (!moreTokens)
1863         {
1864             error("declaration expected instead of EOF");
1865             return null;
1866         }
1867         if (current.comment !is null)
1868             comment = current.comment;
1869         Attribute[] attributes;
1870         do
1871         {
1872             if (!isAttribute())
1873                 break;
1874             auto attr = parseAttribute();
1875             if (attr is null)
1876             {
1877                 error("attribute is null");
1878                 break;
1879             }
1880             if (currentIs(tok!":"))
1881             {
1882                 node.attributeDeclaration = parseAttributeDeclaration(attr);
1883                 node.attributes = ownArray(attributes);
1884                 return node;
1885             }
1886             else
1887                 attributes ~= attr;
1888         } while (moreTokens());
1889         node.attributes = ownArray(attributes);
1890 
1891         if (!moreTokens)
1892         {
1893             error("declaration expected instead of EOF");
1894             deallocate(node);
1895             return null;
1896         }
1897 
1898         switch (current.type)
1899         {
1900         case tok!"asm":
1901         case tok!"break":
1902         case tok!"case":
1903         case tok!"continue":
1904         case tok!"default":
1905         case tok!"do":
1906         case tok!"for":
1907         case tok!"foreach":
1908         case tok!"foreach_reverse":
1909         case tok!"goto":
1910         case tok!"if":
1911         case tok!"return":
1912         case tok!"switch":
1913         case tok!"throw":
1914         case tok!"try":
1915         case tok!"while":
1916         case tok!"assert":
1917             goto default;
1918         case tok!";":
1919             // http://d.puremagic.com/issues/show_bug.cgi?id=4559
1920             warn("Empty declaration");
1921             advance();
1922             break;
1923         case tok!"{":
1924             advance();
1925             Declaration[] declarations;
1926             while (moreTokens() && !currentIs(tok!"}"))
1927             {
1928                 auto declaration = parseDeclaration(strict);
1929                 if (declaration !is null)
1930                     declarations ~= declaration;
1931                 else if (strict)
1932                 {
1933                     deallocate(node);
1934                     return null;
1935                 }
1936             }
1937             node.declarations = ownArray(declarations);
1938             mixin(nullCheck!`expect(tok!"}")`);
1939             break;
1940         case tok!"alias":
1941             if (startsWith(tok!"alias", tok!"identifier", tok!"this"))
1942                 mixin(nullCheck!`node.aliasThisDeclaration = parseAliasThisDeclaration()`);
1943             else
1944                 mixin(nullCheck!`node.aliasDeclaration = parseAliasDeclaration()`);
1945             break;
1946         case tok!"class":
1947             mixin(nullCheck!`node.classDeclaration = parseClassDeclaration()`);
1948             break;
1949         case tok!"this":
1950             if (strict && peekIs(tok!"("))
1951             {
1952                 // If we are in strict mode, do not parse as a declaration.
1953                 // Instead this should be parsed as a function call.
1954                 ++index;
1955                 const past = peekPastParens();
1956                 --index;
1957                 if (past !is null && past.type == tok!";")
1958                 {
1959                     deallocate(node);
1960                     return null;
1961                 }
1962             }
1963             if (startsWith(tok!"this", tok!"(", tok!"this", tok!")"))
1964             {
1965                 mixin(nullCheck!`node.postblit = parsePostblit()`);
1966                 mixin(nullCheck!`node.postblit`);
1967             }
1968             else
1969             {
1970                 mixin(nullCheck!`node.constructor = parseConstructor()`);
1971                 mixin(nullCheck!`node.constructor`);
1972             }
1973             break;
1974         case tok!"~":
1975             mixin(nullCheck!`node.destructor = parseDestructor()`);
1976             mixin(nullCheck!`node.destructor`);
1977             break;
1978         case tok!"enum":
1979             auto b = setBookmark();
1980             advance(); // enum
1981             if (currentIsOneOf(tok!":", tok!"{"))
1982             {
1983                 goToBookmark(b);
1984                 mixin(nullCheck!`node.anonymousEnumDeclaration = parseAnonymousEnumDeclaration()`);
1985             }
1986             else if (currentIs(tok!"identifier"))
1987             {
1988                 advance();
1989                 if (currentIs(tok!"("))
1990                 {
1991                     skipParens(); // ()
1992                     if (currentIs(tok!"("))
1993                         skipParens();
1994                     if (!currentIs(tok!"="))
1995                     {
1996                         goToBookmark(b);
1997                         node.functionDeclaration = parseFunctionDeclaration(null, true, node.attributes);
1998                         mixin(nullCheck!`node.functionDeclaration`);
1999                     }
2000                     else
2001                     {
2002                         goToBookmark(b);
2003                         mixin(nullCheck!`node.eponymousTemplateDeclaration = parseEponymousTemplateDeclaration()`);
2004                     }
2005                 }
2006                 else if (currentIsOneOf(tok!":", tok!"{", tok!";"))
2007                 {
2008                     goToBookmark(b);
2009                     mixin(nullCheck!`node.enumDeclaration = parseEnumDeclaration()`);
2010                 }
2011                 else
2012                 {
2013                     immutable bool eq = currentIs(tok!"=");
2014                     goToBookmark(b);
2015                     mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, eq, null, true)`);
2016                 }
2017             }
2018             else
2019             {
2020                 immutable bool s = isStorageClass();
2021                 goToBookmark(b);
2022                 mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, s, null, true)`);
2023             }
2024             break;
2025         case tok!"import":
2026             mixin(nullCheck!`node.importDeclaration = parseImportDeclaration()`);
2027             break;
2028         case tok!"interface":
2029             mixin(nullCheck!`node.interfaceDeclaration = parseInterfaceDeclaration()`);
2030             break;
2031         case tok!"mixin":
2032             if (peekIs(tok!"template"))
2033                 mixin(nullCheck!`node.mixinTemplateDeclaration = parseMixinTemplateDeclaration()`);
2034             else
2035             {
2036                 auto b = setBookmark();
2037                 advance();
2038                 if (currentIs(tok!"("))
2039                 {
2040                     const t = peekPastParens();
2041                     if (t !is null && t.type == tok!";")
2042                     {
2043                         goToBookmark(b);
2044                         mixin(nullCheck!`node.mixinDeclaration = parseMixinDeclaration()`);
2045                     }
2046                     else
2047                     {
2048                         goToBookmark(b);
2049                         error("Declaration expected for mixin");
2050                         deallocate(node);
2051                         return null;
2052                     }
2053                 }
2054                 else
2055                 {
2056                     goToBookmark(b);
2057                     mixin(nullCheck!`node.mixinDeclaration = parseMixinDeclaration()`);
2058                 }
2059             }
2060             break;
2061         case tok!"pragma":
2062             mixin(nullCheck!`node.pragmaDeclaration = parsePragmaDeclaration()`);
2063             break;
2064         case tok!"shared":
2065             if (startsWith(tok!"shared", tok!"static", tok!"this"))
2066                 mixin(nullCheck!`node.sharedStaticConstructor = parseSharedStaticConstructor()`);
2067             else if (startsWith(tok!"shared", tok!"static", tok!"~"))
2068                 mixin(nullCheck!`node.sharedStaticDestructor = parseSharedStaticDestructor()`);
2069             else
2070                 goto type;
2071             break;
2072         case tok!"static":
2073             if (peekIs(tok!"this"))
2074                 mixin(nullCheck!`node.staticConstructor = parseStaticConstructor()`);
2075             else if (peekIs(tok!"~"))
2076                 mixin(nullCheck!`node.staticDestructor = parseStaticDestructor()`);
2077             else if (peekIs(tok!"if"))
2078                 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`);
2079             else if (peekIs(tok!"assert"))
2080                 mixin(nullCheck!`node.staticAssertDeclaration = parseStaticAssertDeclaration()`);
2081             else if (peekIs(tok!"foreach"))
2082                 mixin(nullCheck!`node.staticForeachDeclaration = parseStaticForeachDeclaration()`);
2083             else
2084                 goto type;
2085             break;
2086         case tok!"struct":
2087             mixin(nullCheck!`node.structDeclaration = parseStructDeclaration()`);
2088             break;
2089         case tok!"template":
2090             mixin(nullCheck!`node.templateDeclaration = parseTemplateDeclaration()`);
2091             break;
2092         case tok!"union":
2093             mixin(nullCheck!`node.unionDeclaration = parseUnionDeclaration()`);
2094             break;
2095         case tok!"invariant":
2096             mixin(nullCheck!`node.invariant_ = parseInvariant()`);
2097             break;
2098         case tok!"unittest":
2099             mixin(nullCheck!`node.unittest_ = parseUnittest()`);
2100             break;
2101         case tok!"identifier":
2102             if (node.attributes.length > 0)
2103             {
2104                 if (peekIs(tok!"="))
2105                     node.variableDeclaration = parseVariableDeclaration(null, true, node.attributes);
2106                 else if (peekIs(tok!"("))
2107                 {
2108                     auto b = setBookmark();
2109                     advance();
2110                     const t = peekPastParens();
2111                     goToBookmark(b);
2112                     if (t !is null && *t == tok!"=")
2113                         node.variableDeclaration = parseVariableDeclaration(null, true, node.attributes);
2114                     else
2115                         node.functionDeclaration = parseFunctionDeclaration(null, true, node.attributes);
2116                 }
2117                 else
2118                     goto type;
2119             }
2120             else
2121                 goto type;
2122             break;
2123         case tok!".":
2124         case tok!"const":
2125         case tok!"immutable":
2126         case tok!"inout":
2127         case tok!"scope":
2128         case tok!"typeof":
2129         case tok!"__vector":
2130         mixin(BUILTIN_TYPE_CASES);
2131         type:
2132             Type type = parseType();
2133             if (type is null || !currentIs(tok!"identifier"))
2134             {
2135                 trace("Returning null on %d".format(__LINE__));
2136                 deallocate(node);
2137                 return null;
2138             }
2139             if (peekIs(tok!"("))
2140             {
2141                 auto b = setBookmark();
2142                 advance();
2143                 const t = peekPastParens();
2144                 goToBookmark(b);
2145                 if (t is null)
2146                     return null;
2147                 if (*t != tok!"=")
2148                     node.functionDeclaration = parseFunctionDeclaration(type, false, node.attributes);
2149                 else
2150                     node.variableDeclaration = parseVariableDeclaration(type, false, node.attributes);
2151             }
2152             else
2153                 mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(type)`);
2154             break;
2155         case tok!"version":
2156             if (peekIs(tok!"("))
2157                 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`);
2158             else if (peekIs(tok!"="))
2159                 mixin(nullCheck!`node.versionSpecification = parseVersionSpecification()`);
2160             else
2161             {
2162                 error(`"=" or "(" expected following "version"`);
2163                 deallocate(node);
2164                 return null;
2165             }
2166             break;
2167         case tok!"debug":
2168             if (peekIs(tok!"="))
2169                 mixin(nullCheck!`node.debugSpecification = parseDebugSpecification()`);
2170             else
2171                 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`);
2172             break;
2173         default:
2174             error("Declaration expected for parse declartion");
2175             deallocate(node);
2176             return null;
2177         }
2178         return node;
2179     }
2180 
2181     /**
2182      * Parses DeclarationsAndStatements
2183      *
2184      * $(GRAMMAR $(RULEDEF declarationsAndStatements):
2185      *     $(RULE declarationOrStatement)+
2186      *     ;)
2187      */
2188     DeclarationsAndStatements parseDeclarationsAndStatements()
2189     {
2190         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2191         auto node = allocate!DeclarationsAndStatements;
2192         DeclarationOrStatement[] declarationsAndStatements;
2193         while (!currentIsOneOf(tok!"}", tok!"else") && moreTokens() && suppressedErrorCount <= MAX_ERRORS)
2194         {
2195             if (currentIs(tok!"while"))
2196             {
2197                 auto b = setBookmark();
2198                 scope (exit) goToBookmark(b);
2199                 advance();
2200                 if (currentIs(tok!"("))
2201                 {
2202                     const p = peekPastParens();
2203                     if (p !is null && *p == tok!";")
2204                         break;
2205                 }
2206             }
2207             auto dos = parseDeclarationOrStatement();
2208             if (dos !is null)
2209                 declarationsAndStatements ~= dos;
2210             else if (suppressMessages > 0)
2211             {
2212                 deallocate(node);
2213                 return null;
2214             }
2215         }
2216         node.declarationsAndStatements = ownArray(declarationsAndStatements);
2217         return node;
2218     }
2219 
2220     /**
2221      * Parses a DeclarationOrStatement
2222      *
2223      * $(GRAMMAR $(RULEDEF declarationOrStatement):
2224      *       $(RULE declaration)
2225      *     | $(RULE statement)
2226      *     ;)
2227      */
2228     DeclarationOrStatement parseDeclarationOrStatement()
2229     {
2230         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2231         auto node = allocate!DeclarationOrStatement;
2232         // "Any ambiguities in the grammar between Statements and
2233         // Declarations are resolved by the declarations taking precedence."
2234         auto b = setBookmark();
2235         auto d = parseDeclaration(true);
2236         if (d is null)
2237         {
2238             goToBookmark(b);
2239             mixin(nullCheck!`node.statement = parseStatement()`);
2240         }
2241         else
2242         {
2243             // TODO: Make this more efficient. Right now we parse the declaration
2244             // twice, once with errors and warnings ignored, and once with them
2245             // printed. Maybe store messages to then be abandoned or written later?
2246             deallocate(d);
2247             goToBookmark(b);
2248             node.declaration = parseDeclaration();
2249         }
2250         return node;
2251     }
2252 
2253     /**
2254      * Parses a Declarator
2255      *
2256      * $(GRAMMAR $(RULEDEF declarator):
2257      *       $(LITERAL Identifier)
2258      *     | $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer)
2259      *     | $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE initializer)
2260      *     ;)
2261      */
2262     Declarator parseDeclarator()
2263     {
2264         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2265         auto node = allocate!Declarator;
2266         const id = expect(tok!"identifier");
2267         mixin(nullCheck!`id`);
2268         node.name = *id;
2269         if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier
2270         {
2271             warn("C-style array declaration.");
2272             TypeSuffix[] typeSuffixes;
2273             while (moreTokens() && currentIs(tok!"["))
2274             {
2275                 auto suffix = parseTypeSuffix();
2276                 mixin(nullCheck!`suffix`);
2277                 typeSuffixes ~= suffix;
2278             }
2279             node.cstyle = ownArray(typeSuffixes);
2280         }
2281         if (currentIs(tok!"("))
2282         {
2283             mixin(nullCheck!`(node.templateParameters = parseTemplateParameters())`);
2284             mixin(nullCheck!`expect(tok!"=")`);
2285             mixin(nullCheck!`(node.initializer = parseInitializer())`);
2286         }
2287         else if (currentIs(tok!"="))
2288         {
2289             advance();
2290             mixin(nullCheck!`node.initializer = parseInitializer()`);
2291         }
2292         return node;
2293     }
2294 
2295     /**
2296      * Parses a DefaultStatement
2297      *
2298      * $(GRAMMAR $(RULEDEF defaultStatement):
2299      *     $(LITERAL 'default') $(LITERAL ':') $(RULE declarationsAndStatements)
2300      *     ;)
2301      */
2302     DefaultStatement parseDefaultStatement()
2303     {
2304         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2305         auto node = allocate!DefaultStatement;
2306         mixin(nullCheck!`expect(tok!"default")`);
2307         const colon = expect(tok!":");
2308         if (colon is null)
2309         {
2310             deallocate(node);
2311             return null;
2312         }
2313         node.colonLocation = colon.index;
2314         mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`);
2315         return node;
2316     }
2317 
2318     /**
2319      * Parses a DeleteExpression
2320      *
2321      * $(GRAMMAR $(RULEDEF deleteExpression):
2322      *     $(LITERAL 'delete') $(RULE unaryExpression)
2323      *     ;)
2324      */
2325     DeleteExpression parseDeleteExpression()
2326     {
2327         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2328         auto node = allocate!DeleteExpression;
2329         node.line = current.line;
2330         node.column = current.column;
2331         mixin(nullCheck!`expect(tok!"delete")`);
2332         mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`);
2333         return node;
2334     }
2335 
2336     /**
2337      * Parses a Deprecated attribute
2338      *
2339      * $(GRAMMAR $(RULEDEF deprecated):
2340      *     $(LITERAL 'deprecated') ($(LITERAL '$(LPAREN)') $(LITERAL StringLiteral)+ $(LITERAL '$(RPAREN)'))?
2341      *     ;)
2342      */
2343     Deprecated parseDeprecated()
2344     {
2345         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2346         auto node = allocate!Deprecated;
2347         mixin(nullCheck!`expect(tok!"deprecated")`);
2348         if (currentIs(tok!"("))
2349         {
2350             advance();
2351             Token[] tokens;
2352             while (currentIs(tok!"stringLiteral") || currentIs(tok!"~"))
2353                 tokens ~= advance();
2354             node.stringLiterals = ownArray(tokens);
2355             mixin(nullCheck!`expect(tok!")")`);
2356         }
2357         return node;
2358     }
2359 
2360     /**
2361      * Parses a Destructor
2362      *
2363      * $(GRAMMAR $(RULEDEF destructor):
2364      *     $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';'))
2365      *     ;)
2366      */
2367     Destructor parseDestructor()
2368     {
2369         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2370         auto node = allocate!Destructor;
2371         node.comment = comment;
2372         comment = null;
2373         mixin(nullCheck!`expect(tok!"~")`);
2374         if (!moreTokens)
2375         {
2376             error("'this' expected");
2377             deallocate(node);
2378             return null;
2379         }
2380         node.index = current.index;
2381         node.line = current.line;
2382         node.column = current.column;
2383         mixin(nullCheck!`expect(tok!"this")`);
2384         mixin(nullCheck!`expect(tok!"(")`);
2385         mixin(nullCheck!`expect(tok!")")`);
2386         if (currentIs(tok!";"))
2387             advance();
2388         else
2389         {
2390             MemberFunctionAttribute[] memberFunctionAttributes;
2391             while (moreTokens() && currentIsMemberFunctionAttribute())
2392                 memberFunctionAttributes ~= parseMemberFunctionAttribute();
2393             node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
2394             mixin(nullCheck!`node.functionBody = parseFunctionBody()`);
2395         }
2396         return node;
2397     }
2398 
2399     /**
2400      * Parses a DoStatement
2401      *
2402      * $(GRAMMAR $(RULEDEF doStatement):
2403      *     $(LITERAL 'do') $(RULE statementNoCaseNoDefault) $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(LITERAL ';')
2404      *     ;)
2405      */
2406     DoStatement parseDoStatement()
2407     {
2408         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2409         auto node = allocate!DoStatement;
2410         mixin(nullCheck!`expect(tok!"do")`);
2411         mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`);
2412         mixin(nullCheck!`expect(tok!"while")`);
2413         mixin(nullCheck!`expect(tok!"(")`);
2414         mixin(nullCheck!`node.expression = parseExpression()`);
2415         mixin(nullCheck!`expect(tok!")")`);
2416         mixin(nullCheck!`expect(tok!";")`);
2417         return node;
2418     }
2419 
2420     /**
2421      * Parses an EnumBody
2422      *
2423      * $(GRAMMAR $(RULEDEF enumBody):
2424      *     $(LITERAL '{') $(RULE enumMember) ($(LITERAL ',') $(RULE enumMember)?)* $(LITERAL '}')
2425      *     ;)
2426      */
2427     EnumBody parseEnumBody()
2428     {
2429         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2430         EnumBody node = allocate!EnumBody;
2431         const open = expect(tok!"{");
2432         mixin(nullCheck!`open`);
2433         node.startLocation = open.index;
2434         EnumMember[] enumMembers;
2435         while (moreTokens())
2436         {
2437             if (currentIs(tok!","))
2438             {
2439                 if (enumMembers.length > 0 && enumMembers[$ - 1].comment is null)
2440                     enumMembers[$ - 1].comment = current.trailingComment;
2441                 advance();
2442                 continue;
2443             }
2444             else if (currentIs(tok!"}"))
2445             {
2446                 if (enumMembers.length > 0 && enumMembers[$ - 1].comment is null)
2447                     enumMembers[$ - 1].comment = tokens[index - 1].trailingComment;
2448                 break;
2449             }
2450             else
2451             {
2452                 auto member = parseEnumMember();
2453                 if (member is null)
2454                     return null;
2455                 enumMembers ~= member;
2456             }
2457         }
2458         node.enumMembers = ownArray(enumMembers);
2459         const close = expect (tok!"}");
2460         if (close !is null)
2461             node.endLocation = close.index;
2462         return node;
2463     }
2464 
2465     /**
2466      * $(GRAMMAR $(RULEDEF anonymousEnumMember):
2467      *       $(RULE type) $(LITERAL identifier) $(LITERAL '=') $(RULE assignExpression)
2468      *     | $(LITERAL identifier) $(LITERAL '=') $(RULE assignExpression)
2469      *     | $(LITERAL identifier)
2470      *     ;)
2471      */
2472     AnonymousEnumMember parseAnonymousEnumMember(bool typeAllowed)
2473     {
2474         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2475         auto node = allocate!AnonymousEnumMember;
2476 
2477 
2478 
2479         while (moreTokens())
2480 	{
2481 		if(currentIs(tok!"@")) {
2482 			if(peek() !is null && (*peek()) == tok!"identifier" && (*peek()).text == "disable") {
2483 				advance();
2484 				advance();
2485 				node.isDisabled = true;
2486 			} else {
2487 				AtAttribute atAttribute;
2488 				mixin(nullCheck!`atAttribute = parseAtAttribute()`);
2489 				if (atAttribute is null) { deallocate(node); break; }
2490 				node.atAttributes ~= atAttribute;
2491 			}
2492 		} else if(currentIs(tok!"deprecated")) {
2493             		mixin(nullCheck!`node.deprecated_ = parseDeprecated()`);
2494 		} else {
2495 			break;
2496 		}
2497 	}
2498 
2499 
2500 
2501 	node.line = current.line;
2502 
2503         if (currentIs(tok!"identifier") && peekIsOneOf(tok!",", tok!"=", tok!"}"))
2504         {
2505             node.comment = current.comment;
2506             comment = null;
2507             mixin(tokenCheck!(`node.name`, `identifier`));
2508             if (currentIs(tok!"="))
2509             {
2510                 advance(); // =
2511                 goto assign;
2512             }
2513         }
2514         else if (typeAllowed)
2515         {
2516             node.comment = current.comment;
2517             comment = null;
2518             mixin(nullCheck!`node.type = parseType()`);
2519             mixin(tokenCheck!(`node.name`, `identifier`));
2520             mixin(nullCheck!`expect(tok!"=")`);
2521     assign:
2522             mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
2523         }
2524         else
2525         {
2526             error("Cannot specify anonymous enum member type if anonymous enum has a base type.");
2527             deallocate(node);
2528             return null;
2529         }
2530         return node;
2531     }
2532 
2533     /**
2534      * $(GRAMMAR $(RULEDEF anonymousEnumDeclaration):
2535      *     $(LITERAL 'enum') ($(LITERAL ':') $(RULE type))? $(LITERAL '{') $(RULE anonymousEnumMember)+ $(LITERAL '}')
2536      *     ;)
2537      */
2538     AnonymousEnumDeclaration parseAnonymousEnumDeclaration()
2539     {
2540         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2541         auto node = allocate!AnonymousEnumDeclaration;
2542 	node.line = current.line;
2543 	node.comment = comment;
2544         mixin(nullCheck!`expect(tok!"enum")`);
2545         immutable bool hasBaseType = currentIs(tok!":");
2546         if (hasBaseType)
2547         {
2548             advance();
2549             mixin(nullCheck!`node.baseType = parseType()`);
2550         }
2551         mixin(nullCheck!`expect(tok!"{")`);
2552         AnonymousEnumMember[] members;
2553         while (moreTokens())
2554         {
2555             if (currentIs(tok!","))
2556             {
2557                 if (members.length > 0 && members[$ - 1].comment is null)
2558                     members[$ - 1].comment = current.trailingComment;
2559                 advance();
2560                 continue;
2561             }
2562             else if (currentIs(tok!"}"))
2563             {
2564                 if (members.length > 0 && members[$ - 1].comment is null)
2565                     members[$ - 1].comment = tokens[index - 1].trailingComment;
2566                 break;
2567             }
2568             else
2569             {
2570                 auto member = parseAnonymousEnumMember(!hasBaseType);
2571                 if (member is null)
2572                     return null;
2573                 members ~= member;
2574             }
2575         }
2576         node.members = ownArray(members);
2577         mixin(nullCheck!`expect(tok!"}")`);
2578         return node;
2579     }
2580 
2581     /**
2582      * Parses an EnumDeclaration
2583      *
2584      * $(GRAMMAR $(RULEDEF enumDeclaration):
2585      *       $(LITERAL 'enum') $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? $(LITERAL ';')
2586      *     | $(LITERAL 'enum') $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? $(RULE enumBody)
2587      *     ;)
2588      */
2589     EnumDeclaration parseEnumDeclaration()
2590     {
2591         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2592         auto node = allocate!EnumDeclaration;
2593         mixin(nullCheck!`expect(tok!"enum")`);
2594         mixin(tokenCheck!(`node.name`, `identifier`));
2595         node.comment = comment;
2596         comment = null;
2597         if (currentIs(tok!";"))
2598         {
2599             advance();
2600             return node;
2601         }
2602         if (currentIs(tok!":"))
2603         {
2604             advance(); // skip ':'
2605             mixin(nullCheck!`node.type = parseType()`);
2606         }
2607         mixin(nullCheck!`node.enumBody = parseEnumBody()`);
2608         return node;
2609     }
2610 
2611     /**
2612      * Parses an EnumMember
2613      *
2614      * $(GRAMMAR $(RULEDEF enumMember):
2615      *       $(LITERAL Identifier)
2616      *     | $(LITERAL Identifier) $(LITERAL '=') $(RULE assignExpression)
2617      *     ;)
2618      */
2619     EnumMember parseEnumMember()
2620     {
2621         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2622         auto node = allocate!EnumMember;
2623         node.comment = current.comment;
2624         comment = null;
2625 
2626 
2627         while (moreTokens())
2628 	{
2629 		if(currentIs(tok!"@")) {
2630 			if(peek() !is null && (*peek()) == tok!"identifier" && (*peek()).text == "disable") {
2631 				advance();
2632 				advance();
2633 				node.isDisabled = true;
2634 			} else {
2635 				AtAttribute atAttribute;
2636 				mixin(nullCheck!`atAttribute = parseAtAttribute()`);
2637 				if (atAttribute is null) { deallocate(node); break; }
2638 				node.atAttributes ~= atAttribute;
2639 			}
2640 		} else if(currentIs(tok!"deprecated")) {
2641             		mixin(nullCheck!`node.deprecated_ = parseDeprecated()`);
2642 		} else {
2643 			break;
2644 		}
2645 	}
2646 
2647 
2648         mixin(tokenCheck!(`node.name`, `identifier`));
2649         if (currentIs(tok!"="))
2650         {
2651             advance();
2652             mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
2653         }
2654         return node;
2655     }
2656 
2657     /**
2658      * Parses an EponymousTemplateDeclaration
2659      *
2660      * $(GRAMMAR $(RULEDEF eponymousTemplateDeclaration):
2661      *     $(LITERAL 'enum') $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE assignExpression) $(LITERAL ';')
2662      *     ;)
2663      */
2664     EponymousTemplateDeclaration parseEponymousTemplateDeclaration()
2665     {
2666         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2667         auto node = allocate!EponymousTemplateDeclaration;
2668         node.comment = comment;
2669         comment = null;
2670         advance(); // enum
2671         const ident = expect(tok!"identifier");
2672         mixin(nullCheck!`ident`);
2673         node.name = *ident;
2674         mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
2675         expect(tok!"=");
2676         node.assignExpression = parseAssignExpression();
2677         if (node.assignExpression is null)
2678             mixin(nullCheck!`node.type = parseType()`);
2679         expect(tok!";");
2680         return node;
2681     }
2682 
2683     /**
2684      * Parses an EqualExpression
2685      *
2686      * $(GRAMMAR $(RULEDEF equalExpression):
2687      *     $(RULE shiftExpression) ($(LITERAL '==') | $(LITERAL '!=')) $(RULE shiftExpression)
2688      *     ;)
2689      */
2690     EqualExpression parseEqualExpression(ExpressionNode shift = null)
2691     {
2692         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2693         auto node = allocate!EqualExpression;
2694         mixin(nullCheck!`node.left = shift is null ? parseShiftExpression() : shift`);
2695         if (currentIsOneOf(tok!"==", tok!"!="))
2696             node.operator = advance().type;
2697         mixin(nullCheck!`node.right = parseShiftExpression()`);
2698         return node;
2699     }
2700 
2701     /**
2702      * Parses an Expression
2703      *
2704      * $(GRAMMAR $(RULEDEF expression):
2705      *     $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression))*
2706      *     ;)
2707      */
2708     Expression parseExpression()
2709     {
2710         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2711         if (suppressedErrorCount > MAX_ERRORS)
2712             return null;
2713         if (!moreTokens())
2714         {
2715             error("Expected expression instead of EOF");
2716             return null;
2717         }
2718         return parseCommaSeparatedRule!(Expression, AssignExpression, true)();
2719     }
2720 
2721     /**
2722      * Parses an ExpressionStatement
2723      *
2724      * $(GRAMMAR $(RULEDEF expressionStatement):
2725      *     $(RULE expression) $(LITERAL ';')
2726      *     ;)
2727      */
2728     ExpressionStatement parseExpressionStatement(Expression expression = null)
2729     {
2730         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2731         auto node = allocate!ExpressionStatement;
2732         node.expression = expression is null ? parseExpression() : expression;
2733         if (node.expression is null || expect(tok!";") is null) { deallocate(node); return null; }
2734         return node;
2735     }
2736 
2737     /**
2738      * Parses a FinalSwitchStatement
2739      *
2740      * $(GRAMMAR $(RULEDEF finalSwitchStatement):
2741      *     $(LITERAL 'final') $(RULE switchStatement)
2742      *     ;)
2743      */
2744     FinalSwitchStatement parseFinalSwitchStatement()
2745     {
2746         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2747         mixin(simpleParse!(FinalSwitchStatement, tok!"final", "switchStatement|parseSwitchStatement"));
2748     }
2749 
2750     /**
2751      * Parses a Finally
2752      *
2753      * $(GRAMMAR $(RULEDEF finally):
2754      *     $(LITERAL 'finally') $(RULE declarationOrStatement)
2755      *     ;)
2756      */
2757     Finally parseFinally()
2758     {
2759         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2760         auto node = allocate!Finally;
2761         mixin(nullCheck!`expect(tok!"finally")`);
2762         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
2763         return node;
2764     }
2765 
2766     /**
2767      * Parses a ForStatement
2768      *
2769      * $(GRAMMAR $(RULEDEF forStatement):
2770      *     $(LITERAL 'for') $(LITERAL '$(LPAREN)') ($(RULE declaration) | $(RULE statementNoCaseNoDefault)) $(RULE expression)? $(LITERAL ';') $(RULE expression)? $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement)
2771      *     ;)
2772      */
2773     ForStatement parseForStatement()
2774     {
2775         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2776         auto node = allocate!ForStatement;
2777         mixin(nullCheck!`expect(tok!"for")`);
2778         if (!moreTokens) node.startIndex = current().index;
2779         mixin(nullCheck!`expect(tok!"(")`);
2780 
2781         if (currentIs(tok!";"))
2782             advance();
2783         else
2784             mixin(nullCheck!`node.initialization = parseDeclarationOrStatement()`);
2785 
2786         if (currentIs(tok!";"))
2787             advance();
2788         else
2789         {
2790             mixin(nullCheck!`node.test = parseExpression()`);
2791             expect(tok!";");
2792         }
2793 
2794         if (!currentIs(tok!")"))
2795              mixin(nullCheck!`node.increment = parseExpression()`);
2796 
2797         mixin(nullCheck!`expect(tok!")")`);
2798         if (currentIs(tok!"}"))
2799         {
2800             error("Statement expected", false);
2801             return node; // this line makes DCD better
2802         }
2803         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
2804         return node;
2805     }
2806 
2807     /**
2808      * Parses a ForeachStatement
2809      *
2810      * $(GRAMMAR $(RULEDEF foreachStatement):
2811      *       ($(LITERAL 'foreach') | $(LITERAL 'foreach_reverse')) $(LITERAL '$(LPAREN)') $(RULE foreachTypeList) $(LITERAL ';') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement)
2812      *     | ($(LITERAL 'foreach') | $(LITERAL 'foreach_reverse')) $(LITERAL '$(LPAREN)') $(RULE foreachType) $(LITERAL ';') $(RULE expression) $(LITERAL '..') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement)
2813      *     ;)
2814      */
2815     ForeachStatement parseForeachStatement()
2816     {
2817         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2818         ForeachStatement node = allocate!ForeachStatement;
2819         if (currentIsOneOf(tok!"foreach", tok!"foreach_reverse"))
2820             node.type = advance().type;
2821         else
2822         {
2823             error(`"foreach" or "foreach_reverse" expected`);
2824             deallocate(node);
2825             return null;
2826         }
2827         node.startIndex = current().index;
2828         mixin(nullCheck!`expect(tok!"(")`);
2829         ForeachTypeList feType = parseForeachTypeList();
2830         mixin(nullCheck!`feType`);
2831         immutable bool canBeRange = feType.items.length == 1;
2832 
2833         mixin(nullCheck!`expect(tok!";")`);
2834         mixin(nullCheck!`node.low = parseExpression()`);
2835         mixin(nullCheck!`node.low`);
2836         if (currentIs(tok!".."))
2837         {
2838             if (!canBeRange)
2839             {
2840                 error(`Cannot have more than one foreach variable for a foreach range statement`);
2841                 return null;
2842             }
2843             advance();
2844             mixin(nullCheck!`node.high = parseExpression()`);
2845             node.foreachType = feType.items[0];
2846             mixin(nullCheck!`node.high`);
2847         }
2848         else
2849         {
2850             node.foreachTypeList = feType;
2851         }
2852         mixin(nullCheck!`expect(tok!")")`);
2853         if (currentIs(tok!"}"))
2854         {
2855             error("Statement expected", false);
2856             return node; // this line makes DCD better
2857         }
2858         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
2859         return node;
2860     }
2861 
2862     /**
2863      * Parses a ForeachType
2864      *
2865      * $(GRAMMAR $(RULEDEF foreachType):
2866      *       $(LITERAL 'ref')? $(RULE typeConstructors)? $(RULE type)? $(LITERAL Identifier)
2867      *     | $(RULE typeConstructors)? $(LITERAL 'ref')? $(RULE type)? $(LITERAL Identifier)
2868      *     ;)
2869      */
2870     ForeachType parseForeachType()
2871     {
2872         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2873         auto node = allocate!ForeachType;
2874         if (currentIs(tok!"ref"))
2875         {
2876             node.isRef = true;
2877             advance();
2878         }
2879         if (currentIsOneOf(tok!"const", tok!"immutable",
2880             tok!"inout", tok!"shared") && !peekIs(tok!"("))
2881         {
2882             trace("\033[01;36mType constructor");
2883             if ((node.typeConstructors = parseTypeConstructors()) is null)
2884                 return null;
2885         }
2886         if (currentIs(tok!"ref"))
2887         {
2888             node.isRef = true;
2889             advance();
2890         }
2891         if (currentIs(tok!"identifier") && peekIsOneOf(tok!",", tok!";"))
2892         {
2893             node.identifier = advance();
2894             return node;
2895         }
2896         if ((node.type = parseType()) is null) { deallocate(node); return null; }
2897         const ident = expect(tok!"identifier");
2898         if (ident is null) { deallocate(node); return null; }
2899         node.identifier = *ident;
2900         return node;
2901     }
2902 
2903     /**
2904      * Parses a ForeachTypeList
2905      *
2906      * $(GRAMMAR $(RULEDEF foreachTypeList):
2907      *     $(RULE foreachType) ($(LITERAL ',') $(RULE foreachType))*
2908      *     ;)
2909      */
2910     ForeachTypeList parseForeachTypeList()
2911     {
2912         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2913         return parseCommaSeparatedRule!(ForeachTypeList, ForeachType)();
2914     }
2915 
2916     /**
2917      * Parses a FunctionAttribute
2918      *
2919      * $(GRAMMAR $(RULEDEF functionAttribute):
2920      *       $(RULE atAttribute)
2921      *     | $(LITERAL 'pure')
2922      *     | $(LITERAL 'nothrow')
2923      *     ;)
2924      */
2925     FunctionAttribute parseFunctionAttribute(bool validate = true)
2926     {
2927         auto node = allocate!FunctionAttribute;
2928         switch (current.type)
2929         {
2930         case tok!"@":
2931             mixin(nullCheck!`node.atAttribute = parseAtAttribute()`);
2932             break;
2933         case tok!"pure":
2934         case tok!"nothrow":
2935             node.token = advance();
2936             break;
2937         default:
2938             if (validate)
2939                 error(`@attribute, "pure", or "nothrow" expected`);
2940             deallocate(node);
2941             return null;
2942         }
2943         return node;
2944     }
2945 
2946     /**
2947      * Parses a FunctionBody
2948      *
2949      * $(GRAMMAR $(RULEDEF functionBody):
2950      *       $(RULE blockStatement)
2951      *     | ($(RULE inStatement) | $(RULE outStatement) | $(RULE outStatement) $(RULE inStatement) | $(RULE inStatement) $(RULE outStatement))? $(RULE bodyStatement)?
2952      *     ;)
2953      */
2954     FunctionBody parseFunctionBody()
2955     {
2956         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
2957         auto node = allocate!FunctionBody;
2958         if (currentIs(tok!";"))
2959         {
2960             advance();
2961             return node;
2962         }
2963         else if (currentIs(tok!"{"))
2964         {
2965 
2966 		hackFunctionBody();
2967 		auto fb = new FunctionBody();
2968                 fb.hadABody = true;
2969                 return fb;
2970 
2971             if ((node.blockStatement = parseBlockStatement()) is null)
2972             {
2973                 deallocate(node);
2974                 return null;
2975             }
2976         }
2977         else
2978         {
2979 	    while(currentIs(tok!"in") || currentIs(tok!"out")) {
2980 		    if (currentIs(tok!"in"))
2981 		    {
2982 			mixin(nullCheck!`node.inStatement = parseInStatement()`);
2983 		    }
2984 		    else if (currentIs(tok!"out"))
2985 		    {
2986 			mixin(nullCheck!`node.outStatement = parseOutStatement()`);
2987 		    }
2988 	    }
2989             // Allow function bodies without body statements because this is
2990             // valid inside of interfaces.
2991             if (currentIs(tok!"body"))
2992                 mixin(nullCheck!`node.bodyStatement = parseBodyStatement()`);
2993 	    else if(currentIs(tok!"do"))
2994                 mixin(nullCheck!`node.bodyStatement = parseBodyDoStatement()`);
2995 	    else if(currentIs(tok!"{")) {
2996 		hackFunctionBody();
2997 
2998 		auto fb = new FunctionBody();
2999                 fb.hadABody = true;
3000                 return fb;
3001 	    }
3002         }
3003 	if(minimize_memory) {
3004 		.destroy(node.blockStatement);
3005 		.destroy(node.bodyStatement);
3006 	}
3007         return node;
3008     }
3009 
3010     /**
3011      * Parses a FunctionCallExpression
3012      *
3013      * $(GRAMMAR $(RULEDEF functionCallExpression):
3014      *      $(RULE symbol) $(RULE arguments)
3015      *      $(RULE unaryExpression) $(RULE arguments)
3016      *     | $(RULE type) $(RULE arguments)
3017      *     ;)
3018      */
3019     FunctionCallExpression parseFunctionCallExpression(UnaryExpression unary = null)
3020     {
3021         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3022         auto node = allocate!FunctionCallExpression;
3023         switch (current.type)
3024         {
3025         case tok!"const":
3026         case tok!"immutable":
3027         case tok!"inout":
3028         case tok!"shared":
3029         case tok!"scope":
3030         case tok!"pure":
3031         case tok!"nothrow":
3032             mixin(nullCheck!`node.type = parseType()`);
3033             mixin(nullCheck!`node.arguments = parseArguments()`);
3034             break;
3035         default:
3036             if (unary !is null)
3037                 node.unaryExpression = unary;
3038             else
3039                 mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`);
3040             if (currentIs(tok!"!"))
3041                 mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`);
3042             if (unary !is null)
3043                 mixin(nullCheck!`node.arguments = parseArguments()`);
3044         }
3045         return node;
3046     }
3047 
3048     /**
3049      * Parses a FunctionDeclaration
3050      *
3051      * $(GRAMMAR $(RULEDEF functionDeclaration):
3052      *       ($(RULE storageClass)+ | $(RULE _type)) $(LITERAL Identifier) $(RULE parameters) $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';'))
3053      *     | ($(RULE storageClass)+ | $(RULE _type)) $(LITERAL Identifier) $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';'))
3054      *     ;)
3055      */
3056     FunctionDeclaration parseFunctionDeclaration(Type type = null, bool isAuto = false,
3057         Attribute[] attributes = null)
3058     {
3059         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3060         auto node = allocate!FunctionDeclaration;
3061         node.comment = comment;
3062         comment = null;
3063         MemberFunctionAttribute[] memberFunctionAttributes;
3064 
3065         node.attributes = attributes;
3066 
3067         if (isAuto)
3068         {
3069             StorageClass[] storageClasses;
3070             while (isStorageClass())
3071             {
3072                 auto s = parseStorageClass();
3073                 if (s is null)
3074                 {
3075                     deallocate(node);
3076                     return null;
3077                 }
3078                 else
3079                     storageClasses ~= s;
3080             }
3081             node.storageClasses = storageClasses;
3082 
3083 
3084             foreach (a; node.attributes)
3085             {
3086                 if (a.attribute == tok!"auto")
3087                     node.hasAuto = true;
3088                 else if (a.attribute == tok!"ref")
3089                     node.hasRef = true;
3090                 else
3091                     continue;
3092             }
3093         }
3094         else
3095         {
3096             while (moreTokens() && currentIsMemberFunctionAttribute())
3097                 memberFunctionAttributes ~= parseMemberFunctionAttribute();
3098 
3099             node.returnType = type is null ? parseType() : type;
3100         }
3101 
3102         const ident = expect(tok!"identifier");
3103         if (ident is null) { deallocate(node); return null; }
3104 
3105         node.name = *ident;
3106 
3107         if (!currentIs(tok!"("))
3108         {
3109             error(`"(" expected`);
3110             return null;
3111         }
3112 
3113         assert (currentIs(tok!"("));
3114         const p = peekPastParens();
3115         immutable bool isTemplate = p !is null && p.type == tok!"(";
3116 
3117         if (isTemplate)
3118             mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
3119 
3120         mixin(nullCheck!`node.parameters = parseParameters()`);
3121         if (node.parameters is null) { deallocate(node); return null; }
3122 
3123         while (moreTokens() && currentIsMemberFunctionAttribute())
3124             memberFunctionAttributes ~= parseMemberFunctionAttribute();
3125 
3126         if (isTemplate && currentIs(tok!"if"))
3127             mixin(nullCheck!`node.constraint = parseConstraint()`);
3128 
3129         if (currentIs(tok!";"))
3130             advance();
3131         else
3132             mixin(nullCheck!`node.functionBody = parseFunctionBody()`);
3133         node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
3134         return node;
3135     }
3136 
3137     /**
3138      * Parses a FunctionLiteralExpression
3139      *
3140      * $(GRAMMAR $(RULEDEF functionLiteralExpression):
3141      *     (($(LITERAL 'function') | $(LITERAL 'delegate')) $(RULE type)?)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE functionBody)
3142      *     ;)
3143      */
3144     FunctionLiteralExpression parseFunctionLiteralExpression()
3145     {
3146         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3147         auto node = allocate!FunctionLiteralExpression;
3148         if (currentIsOneOf(tok!"function", tok!"delegate"))
3149         {
3150             node.functionOrDelegate = advance().type;
3151             if (!currentIsOneOf(tok!"(", tok!"in", tok!"body",
3152                 tok!"out", tok!"{"))
3153             {
3154                 mixin(nullCheck!`node.type = parseType()`);
3155                 if (node.type is null) { deallocate(node); return null; }
3156             }
3157         }
3158         if (currentIs(tok!"("))
3159         {
3160             mixin(nullCheck!`node.parameters = parseParameters()`);
3161             if (node.parameters is null) { deallocate(node); return null; }
3162             MemberFunctionAttribute[] memberFunctionAttributes;
3163             while (currentIsMemberFunctionAttribute())
3164             {
3165                 auto attr = parseMemberFunctionAttribute();
3166                 if (attr is null)
3167                     break;
3168                 else
3169                     memberFunctionAttributes ~= attr;
3170             }
3171             node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
3172         }
3173         if ((node.functionBody = parseFunctionBody()) is null) { deallocate(node); return null; }
3174         return node;
3175     }
3176 
3177     /**
3178      * Parses a GotoStatement
3179      *
3180      * $(GRAMMAR $(RULEDEF gotoStatement):
3181      *     $(LITERAL 'goto') ($(LITERAL Identifier) | $(LITERAL 'default') | $(LITERAL 'case') $(RULE expression)?) $(LITERAL ';')
3182      *     ;)
3183      */
3184     GotoStatement parseGotoStatement()
3185     {
3186         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3187         auto node = allocate!GotoStatement;
3188         if (expect(tok!"goto") is null) { deallocate(node); return null; }
3189         switch (current.type)
3190         {
3191         case tok!"identifier":
3192         case tok!"default":
3193             node.label = advance();
3194             break;
3195         case tok!"case":
3196             node.label = advance();
3197             if (!currentIs(tok!";"))
3198                 mixin(nullCheck!`node.expression = parseExpression()`);
3199             break;
3200         default:
3201             error(`Identifier, "default", or "case" expected`);
3202             return null;
3203         }
3204         if (expect(tok!";") is null) { deallocate(node); return null; }
3205         return node;
3206     }
3207 
3208     /**
3209      * Parses an IdentifierChain
3210      *
3211      * $(GRAMMAR $(RULEDEF identifierChain):
3212      *     $(LITERAL Identifier) ($(LITERAL '.') $(LITERAL Identifier))*
3213      *     ;)
3214      */
3215     IdentifierChain parseIdentifierChain()
3216     {
3217         auto node = allocate!IdentifierChain;
3218         Token[] identifiers;
3219         while (moreTokens())
3220         {
3221             const ident = expect(tok!"identifier");
3222             if (ident is null) { deallocate(node); return null; }
3223             identifiers ~= *ident;
3224             if (currentIs(tok!"."))
3225             {
3226                 advance();
3227                 continue;
3228             }
3229             else
3230                 break;
3231         }
3232         node.identifiers = ownArray(identifiers);
3233         return node;
3234     }
3235 
3236     /**
3237      * Parses an IdentifierList
3238      *
3239      * $(GRAMMAR $(RULEDEF identifierList):
3240      *     $(LITERAL Identifier) ($(LITERAL ',') $(LITERAL Identifier))*
3241      *     ;)
3242      */
3243     IdentifierList parseIdentifierList()
3244     {
3245         auto node = allocate!IdentifierList;
3246         Token[] identifiers;
3247         while (moreTokens())
3248         {
3249             const ident = expect(tok!"identifier");
3250             if (ident is null) { deallocate(node); return null; }
3251             identifiers ~= *ident;
3252             if (currentIs(tok!","))
3253             {
3254                 advance();
3255                 continue;
3256             }
3257             else
3258                 break;
3259         }
3260         node.identifiers = ownArray(identifiers);
3261         return node;
3262     }
3263 
3264     /**
3265      * Parses an IdentifierOrTemplateChain
3266      *
3267      * $(GRAMMAR $(RULEDEF identifierOrTemplateChain):
3268      *     $(RULE identifierOrTemplateInstance) ($(LITERAL '.') $(RULE identifierOrTemplateInstance))*
3269      *     ;)
3270      */
3271     IdentifierOrTemplateChain parseIdentifierOrTemplateChain()
3272     {
3273         auto node = allocate!IdentifierOrTemplateChain;
3274         IdentifierOrTemplateInstance[] identifiersOrTemplateInstances;
3275         while (moreTokens())
3276         {
3277             auto t = parseIdentifierOrTemplateInstance();
3278             if (t !is null)
3279                 identifiersOrTemplateInstances ~= t;
3280             else
3281                 break;
3282             if (!currentIs(tok!"."))
3283                 break;
3284             else
3285                 advance();
3286         }
3287         node.identifiersOrTemplateInstances = ownArray(identifiersOrTemplateInstances);
3288         return node;
3289     }
3290 
3291     /**
3292      * Parses an IdentifierOrTemplateInstance
3293      *
3294      * $(GRAMMAR $(RULEDEF identifierOrTemplateInstance):
3295      *       $(LITERAL Identifier)
3296      *     | $(RULE templateInstance)
3297      *     ;)
3298      */
3299     IdentifierOrTemplateInstance parseIdentifierOrTemplateInstance()
3300     {
3301         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3302         auto node = allocate!IdentifierOrTemplateInstance;
3303         if (peekIs(tok!"!") && !startsWith(tok!"identifier",
3304             tok!"!", tok!"is")
3305             && !startsWith(tok!"identifier", tok!"!", tok!"in"))
3306         {
3307             mixin(nullCheck!`node.templateInstance = parseTemplateInstance()`);
3308         }
3309         else
3310         {
3311             const ident = expect(tok!"identifier");
3312             if (ident is null) { deallocate(node); return null; }
3313             node.identifier = *ident;
3314         }
3315         return node;
3316     }
3317 
3318     /**
3319      * Parses an IdentityExpression
3320      *
3321      * $(GRAMMAR $(RULEDEF identityExpression):
3322      *     $(RULE shiftExpression) ($(LITERAL 'is') | ($(LITERAL '!') $(LITERAL 'is'))) $(RULE shiftExpression)
3323      *     ;)
3324      */
3325     ExpressionNode parseIdentityExpression(ExpressionNode shift = null)
3326     {
3327         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3328         auto node = allocate!IdentityExpression;
3329         node.left = shift is null ? parseShiftExpression() : shift;
3330         if (currentIs(tok!"!"))
3331         {
3332             advance();
3333             node.negated = true;
3334         }
3335         if (expect(tok!"is") is null) { deallocate(node); return null; }
3336         mixin(nullCheck!`node.right = parseShiftExpression()`);
3337         return node;
3338     }
3339 
3340     /**
3341      * Parses an IfStatement
3342      *
3343      * $(GRAMMAR $(RULEDEF ifStatement):
3344      *     $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE ifCondition) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) ($(LITERAL 'else') $(RULE declarationOrStatement))?
3345      *$(RULEDEF ifCondition):
3346      *       $(LITERAL 'auto') $(LITERAL Identifier) $(LITERAL '=') $(RULE expression)
3347      *     | $(RULE type) $(LITERAL Identifier) $(LITERAL '=') $(RULE expression)
3348      *     | $(RULE expression)
3349      *     ;)
3350      */
3351     IfStatement parseIfStatement()
3352     {
3353         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3354         auto node = allocate!IfStatement;
3355         node.line = current().line;
3356         node.column = current().column;
3357         if (expect(tok!"if") is null) { deallocate(node); return null; }
3358         node.startIndex = current().index;
3359         if (expect(tok!"(") is null) { deallocate(node); return null; }
3360 
3361         if (currentIs(tok!"auto") || currentIs(tok!"const") || currentIs(tok!"immutable") || currentIs(tok!"inout") || currentIs(tok!"shared"))
3362         {
3363         while(currentIs(tok!"auto") || currentIs(tok!"const") || currentIs(tok!"immutable") || currentIs(tok!"inout") || currentIs(tok!"shared"))
3364             advance();
3365 	/*
3366 
3367             auto b = setBookmark();
3368             auto t = parseType();
3369 
3370 	    if(t is null)
3371 	    	goToBookmark(b);
3372 		*/
3373 
3374             const i = expect(tok!"identifier");
3375             if (i !is null)
3376                 node.identifier = *i;
3377             expect(tok!"=");
3378             mixin(nullCheck!`node.expression = parseExpression()`);
3379         }
3380         else
3381         {
3382             auto b = setBookmark();
3383             auto t = parseType();
3384             if (t is null || !currentIs(tok!"identifier")
3385                 || !peekIs(tok!"="))
3386             {
3387                 goToBookmark(b);
3388                 mixin(nullCheck!`node.expression = parseExpression()`);
3389             }
3390             else
3391             {
3392                 goToBookmark(b);
3393                 mixin(nullCheck!`node.type = parseType()`);
3394                 const i = expect(tok!"identifier");
3395                 if (i !is null)
3396                     node.identifier = *i;
3397                 expect(tok!"=");
3398                 mixin(nullCheck!`node.expression = parseExpression()`);
3399             }
3400         }
3401 
3402         if (expect(tok!")") is null) { deallocate(node); return null; }
3403         if (currentIs(tok!"}"))
3404         {
3405             error("Statement expected", false);
3406             return node; // this line makes DCD better
3407         }
3408         mixin(nullCheck!`node.thenStatement = parseDeclarationOrStatement()`);
3409         if (currentIs(tok!"else"))
3410         {
3411             advance();
3412             mixin(nullCheck!`node.elseStatement = parseDeclarationOrStatement()`);
3413         }
3414         return node;
3415     }
3416 
3417     /**
3418      * Parses an ImportBind
3419      *
3420      * $(GRAMMAR $(RULEDEF importBind):
3421      *     $(LITERAL Identifier) ($(LITERAL '=') $(LITERAL Identifier))?
3422      *     ;)
3423      */
3424     ImportBind parseImportBind()
3425     {
3426         auto node = allocate!ImportBind;
3427         const ident = expect(tok!"identifier");
3428         if (ident is null) { deallocate(node); return null; }
3429         node.left = *ident;
3430         if (currentIs(tok!"="))
3431         {
3432             advance();
3433             const id = expect(tok!"identifier");
3434             if (id is null) { deallocate(node); return null; }
3435             node.right = *id;
3436         }
3437         return node;
3438     }
3439 
3440     /**
3441      * Parses ImportBindings
3442      *
3443      * $(GRAMMAR $(RULEDEF importBindings):
3444      *     $(RULE singleImport) $(LITERAL ':') $(RULE importBind) ($(LITERAL ',') $(RULE importBind))*
3445      *     ;)
3446      */
3447     ImportBindings parseImportBindings(SingleImport singleImport)
3448     {
3449         auto node = allocate!ImportBindings;
3450         node.singleImport = singleImport is null ? parseSingleImport() : singleImport;
3451         if (expect(tok!":") is null) { deallocate(node); return null; }
3452         ImportBind[] importBinds;
3453         while (moreTokens())
3454         {
3455             auto b = parseImportBind();
3456             if (b !is null)
3457             {
3458                 importBinds ~= b;
3459                 if (currentIs(tok!","))
3460                     advance();
3461                 else
3462                     break;
3463             }
3464             else
3465                 break;
3466         }
3467         node.importBinds = ownArray(importBinds);
3468         return node;
3469     }
3470 
3471     /**
3472      * Parses an ImportDeclaration
3473      *
3474      * $(GRAMMAR $(RULEDEF importDeclaration):
3475      *       $(LITERAL 'import') $(RULE singleImport) ($(LITERAL ',') $(RULE singleImport))* ($(LITERAL ',') $(RULE importBindings))? $(LITERAL ';')
3476      *     | $(LITERAL 'import') $(RULE importBindings) $(LITERAL ';')
3477      *     ;)
3478      */
3479     ImportDeclaration parseImportDeclaration()
3480     {
3481         auto node = allocate!ImportDeclaration;
3482         if (expect(tok!"import") is null) { deallocate(node); return null; }
3483 
3484         node.comment = comment;
3485         comment = null;
3486 	node.line = current.line;
3487 
3488         SingleImport si = parseSingleImport();
3489         if (currentIs(tok!":"))
3490             node.importBindings = parseImportBindings(si);
3491         else
3492         {
3493             SingleImport[] singleImports;
3494             singleImports ~= si;
3495             if (currentIs(tok!","))
3496             {
3497                 advance();
3498                 while (moreTokens())
3499                 {
3500                     auto single = parseSingleImport();
3501                     if (single is null)
3502                         return null;
3503                     if (currentIs(tok!":"))
3504                     {
3505                         node.importBindings = parseImportBindings(single);
3506                         break;
3507                     }
3508                     else
3509                     {
3510                         singleImports ~= single;
3511                         if (currentIs(tok!","))
3512                             advance();
3513                         else
3514                             break;
3515                     }
3516                 }
3517             }
3518             node.singleImports = ownArray(singleImports);
3519         }
3520         if (expect(tok!";") is null) { deallocate(node); return null; }
3521         return node;
3522     }
3523 
3524     /**
3525      * Parses an ImportExpression
3526      *
3527      * $(GRAMMAR $(RULEDEF importExpression):
3528      *     $(LITERAL 'import') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)')
3529      *     ;)
3530      */
3531     ImportExpression parseImportExpression()
3532     {
3533         auto node = allocate!ImportExpression;
3534         if (expect(tok!"import") is null) { deallocate(node); return null; }
3535         if (expect(tok!"(") is null) { deallocate(node); return null; }
3536         mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
3537         if (expect(tok!")") is null) { deallocate(node); return null; }
3538         return node;
3539     }
3540 
3541     /**
3542      * Parses an Index
3543      *
3544      * $(GRAMMAR $(RULEDEF index):
3545      *     $(RULE assignExpression) ($(LITERAL '..') $(RULE assignExpression))?
3546      *     ;
3547      * )
3548      */
3549     Index parseIndex()
3550     {
3551         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3552         auto node = allocate!Index();
3553         mixin(nullCheck!`node.low = parseAssignExpression()`);
3554         if (currentIs(tok!".."))
3555         {
3556             advance();
3557             mixin(nullCheck!`node.high = parseAssignExpression()`);
3558         }
3559         return node;
3560     }
3561 
3562     /**
3563      * Parses an IndexExpression
3564      *
3565      * $(GRAMMAR $(RULEDEF indexExpression):
3566      *       $(RULE unaryExpression) $(LITERAL '[') $(LITERAL ']')
3567      *     | $(RULE unaryExpression) $(LITERAL '[') $(RULE index) ($(LITERAL ',') $(RULE index))* $(LITERAL ']')
3568      *     ;
3569      * )
3570      */
3571     IndexExpression parseIndexExpression(UnaryExpression unaryExpression = null)
3572     {
3573         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3574         auto node = allocate!IndexExpression;
3575         node.unaryExpression = unaryExpression is null ? parseUnaryExpression() : unaryExpression;
3576         mixin(nullCheck!`node.unaryExpression`);
3577         mixin(nullCheck!`expect(tok!"[")`);
3578         Index[] indexes;
3579         while (true)
3580         {
3581             if (!moreTokens())
3582             {
3583                 error("Expected unary expression instead of EOF");
3584                 deallocate(node);
3585                 return null;
3586             }
3587             if (currentIs(tok!"]"))
3588 				break;
3589             auto index = parseIndex();
3590             mixin(nullCheck!`index`);
3591             indexes ~= index;
3592 			if (currentIs(tok!","))
3593 				advance();
3594 			else
3595 				break;
3596         }
3597         node.indexes = ownArray(indexes);
3598 		advance(); // ]
3599 		return node;
3600     }
3601 
3602     /**
3603      * Parses an InExpression
3604      *
3605      * $(GRAMMAR $(RULEDEF inExpression):
3606      *     $(RULE shiftExpression) ($(LITERAL 'in') | ($(LITERAL '!') $(LITERAL 'in'))) $(RULE shiftExpression)
3607      *     ;)
3608      */
3609     ExpressionNode parseInExpression(ExpressionNode shift = null)
3610     {
3611         auto node = allocate!InExpression;
3612         node.left = shift is null ? parseShiftExpression() : shift;
3613         if (currentIs(tok!"!"))
3614         {
3615             node.negated = true;
3616             advance();
3617         }
3618         if (expect(tok!"in") is null) { deallocate(node); return null; }
3619         mixin(nullCheck!`node.right = parseShiftExpression()`);
3620         return node;
3621     }
3622 
3623     /**
3624      * Parses an InStatement
3625      *
3626      * $(GRAMMAR $(RULEDEF inStatement):
3627      *     $(LITERAL 'in') $(RULE blockStatement)
3628      *     ;)
3629      */
3630     InStatement parseInStatement()
3631     {
3632         auto node = allocate!InStatement;
3633         const i = expect(tok!"in");
3634         mixin(nullCheck!`i`);
3635         node.inTokenLocation = i.index;
3636 	if(currentIs(tok!"(")) {
3637 		advance();
3638 		mixin(nullCheck!`node.expression = parseExpression()`);
3639 		if (node.expression is null)
3640 		    return null;
3641              version(none)
3642 	     if(currentIs(tok!",")) {
3643 		advance();
3644                 parseExpression(); // FIXME: probably should store this but it is the string message
3645 
3646              }
3647 		expect(tok!")");
3648 	} else {
3649 		mixin(nullCheck!`node.blockStatement = parseBlockStatement()`);
3650 		if (node.blockStatement is null)
3651 		    return null;
3652 	}
3653         return node;
3654     }
3655 
3656     /**
3657      * Parses an Initializer
3658      *
3659      * $(GRAMMAR $(RULEDEF initializer):
3660      *       $(LITERAL 'void')
3661      *     | $(RULE nonVoidInitializer)
3662      *     ;)
3663      */
3664     Initializer parseInitializer()
3665     {
3666         auto node = allocate!Initializer;
3667         if (currentIs(tok!"void") && peekIsOneOf(tok!",", tok!";"))
3668             advance();
3669         else
3670             mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`);
3671         return node;
3672     }
3673 
3674     /**
3675      * Parses an InterfaceDeclaration
3676      *
3677      * $(GRAMMAR $(RULEDEF interfaceDeclaration):
3678      *       $(LITERAL 'interface') $(LITERAL Identifier) $(LITERAL ';')
3679      *     | $(LITERAL 'interface') $(LITERAL Identifier) ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody)
3680      *     | $(LITERAL 'interface') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody)
3681      *     | $(LITERAL 'interface') $(LITERAL Identifier) $(RULE templateParameters) ($(LITERAL ':') $(RULE baseClassList))? $(RULE constraint)? $(RULE structBody)
3682      *     ;)
3683      */
3684     InterfaceDeclaration parseInterfaceDeclaration()
3685     {
3686         auto node = allocate!InterfaceDeclaration;
3687         expect(tok!"interface");
3688         mixin(PARSE_INTERFACE_OR_CLASS);
3689     }
3690 
3691     /**
3692      * Parses an Invariant
3693      *
3694      * $(GRAMMAR $(RULEDEF invariant):
3695      *     $(LITERAL 'invariant') ($(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)'))? $(RULE blockStatement)
3696      *     ;)
3697      */
3698     Invariant parseInvariant()
3699     {
3700         auto node = allocate!Invariant;
3701         node.index = current.index;
3702         node.line = current.line;
3703         if (expect(tok!"invariant") is null) { deallocate(node); return null; }
3704         if (currentIs(tok!"("))
3705         {
3706             advance();
3707             if (expect(tok!")") is null) { deallocate(node); return null; }
3708         }
3709         if ((node.blockStatement = parseBlockStatement()) is null) { deallocate(node); return null; }
3710         return node;
3711     }
3712 
3713     /**
3714      * Parses an IsExpression
3715      *
3716      * $(GRAMMAR $(RULEDEF isExpression):
3717      *     $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '$(RPAREN)')
3718      *     $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL ':') $(RULE typeSpecialization) $(LITERAL '$(RPAREN)')
3719      *     $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '=') $(RULE typeSpecialization) $(LITERAL '$(RPAREN)')
3720      *     $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL ':') $(RULE typeSpecialization) $(LITERAL ',') $(RULE templateParameterList) $(LITERAL '$(RPAREN)')
3721      *     $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '=') $(RULE typeSpecialization) $(LITERAL ',') $(RULE templateParameterList) $(LITERAL '$(RPAREN)')
3722      *     ;)
3723      */
3724     IsExpression parseIsExpression()
3725     {
3726         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3727         auto node = allocate!IsExpression;
3728         if (expect(tok!"is") is null) { deallocate(node); return null; }
3729         if (expect(tok!"(") is null) { deallocate(node); return null; }
3730         mixin(nullCheck!`node.type = parseType()`);
3731         if (node.type is null) { deallocate(node); return null; }
3732         if (currentIs(tok!"identifier"))
3733             node.identifier = advance();
3734         if (currentIsOneOf(tok!"==", tok!":"))
3735         {
3736             node.equalsOrColon = advance().type;
3737             mixin(nullCheck!`node.typeSpecialization = parseTypeSpecialization()`);
3738             if (currentIs(tok!","))
3739             {
3740                 advance();
3741                 mixin(nullCheck!`node.templateParameterList = parseTemplateParameterList()`);
3742             }
3743         }
3744         if (expect(tok!")") is null) { deallocate(node); return null; }
3745         return node;
3746     }
3747 
3748     /**
3749      * Parses a KeyValuePair
3750      *
3751      * $(GRAMMAR $(RULEDEF keyValuePair):
3752      *     $(RULE assignExpression) $(LITERAL ':') $(RULE assignExpression)
3753      *     ;)
3754      */
3755     KeyValuePair parseKeyValuePair()
3756     {
3757         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3758         auto node = allocate!KeyValuePair;
3759         mixin(nullCheck!`node.key = parseAssignExpression()`);
3760         if (expect(tok!":") is null) { deallocate(node); return null; }
3761         mixin(nullCheck!`node.value = parseAssignExpression()`);
3762         return node;
3763     }
3764 
3765     /**
3766      * Parses KeyValuePairs
3767      *
3768      * $(GRAMMAR $(RULEDEF keyValuePairs):
3769      *     $(RULE keyValuePair) ($(LITERAL ',') $(RULE keyValuePair))* $(LITERAL ',')?
3770      *     ;)
3771      */
3772     KeyValuePairs parseKeyValuePairs()
3773     {
3774         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3775         auto node = allocate!KeyValuePairs;
3776         KeyValuePair[] keyValuePairs;
3777         while (moreTokens())
3778         {
3779             auto kvPair = parseKeyValuePair();
3780             if (kvPair !is null)
3781                 keyValuePairs ~= kvPair;
3782             if (currentIs(tok!","))
3783             {
3784                 advance();
3785                 if (currentIs(tok!"]"))
3786                     break;
3787             }
3788             else
3789                 break;
3790         }
3791         node.keyValuePairs = ownArray(keyValuePairs);
3792         return node;
3793     }
3794 
3795     /**
3796      * Parses a LabeledStatement
3797      *
3798      * $(GRAMMAR $(RULEDEF labeledStatement):
3799      *     $(LITERAL Identifier) $(LITERAL ':') $(RULE declarationOrStatement)?
3800      *     ;)
3801      */
3802     LabeledStatement parseLabeledStatement()
3803     {
3804         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3805         auto node = allocate!LabeledStatement;
3806         const ident = expect(tok!"identifier");
3807         if (ident is null) { deallocate(node); return null; }
3808         node.identifier = *ident;
3809         expect(tok!":");
3810         if (!currentIs(tok!"}"))
3811             mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
3812         return node;
3813     }
3814 
3815     /**
3816      * Parses a LambdaExpression
3817      *
3818      * $(GRAMMAR $(RULEDEF lambdaExpression):
3819      *       $(LITERAL Identifier) $(LITERAL '=>') $(RULE assignExpression)
3820      *     | $(LITERAL 'function') $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3821      *     | $(LITERAL 'delegate') $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3822      *     | $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3823      *     ;)
3824      */
3825     LambdaExpression parseLambdaExpression()
3826     {
3827         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3828         auto node = allocate!LambdaExpression;
3829         if (currentIsOneOf(tok!"function", tok!"delegate"))
3830         {
3831             node.functionType = advance().type;
3832             if (!currentIs(tok!"("))
3833                 if ((node.returnType = parseType()) is null) { deallocate(node); return null; }
3834             goto lParen;
3835         }
3836         else if (startsWith(tok!"identifier", tok!"=>"))
3837         {
3838             node.identifier = advance();
3839             goto lambda;
3840         }
3841 
3842         if (currentIs(tok!"("))
3843         {
3844         lParen:
3845             mixin(nullCheck!`node.parameters = parseParameters()`);
3846             FunctionAttribute[] functionAttributes;
3847             while (moreTokens())
3848             {
3849                 auto attribute = parseFunctionAttribute(false);
3850                 if (attribute is null)
3851                     break;
3852                 functionAttributes ~= attribute;
3853             }
3854             node.functionAttributes = ownArray(functionAttributes);
3855         }
3856         else
3857         {
3858             error(`Identifier, type, or argument list expected`);
3859             return null;
3860         }
3861 
3862     lambda:
3863         if (expect(tok!"=>") is null) { deallocate(node); return null; }
3864         if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; }
3865         return node;
3866     }
3867 
3868     /**
3869      * Parses a LastCatch
3870      *
3871      * $(GRAMMAR $(RULEDEF lastCatch):
3872      *     $(LITERAL 'catch') $(RULE statementNoCaseNoDefault)
3873      *     ;)
3874      */
3875     LastCatch parseLastCatch()
3876     {
3877         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3878         auto node = allocate!LastCatch;
3879         const t = expect(tok!"catch");
3880         if (t is null) { deallocate(node); return null; }
3881         node.line = t.line;
3882         node.column = t.column;
3883         if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null)
3884             return null;
3885         return node;
3886     }
3887 
3888     /**
3889      * Parses a LinkageAttribute
3890      *
3891      * $(GRAMMAR $(RULEDEF linkageAttribute):
3892      *     $(LITERAL 'extern') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) ($(LITERAL '++') ($(LITERAL ',') $(RULE identifierChain))?)? $(LITERAL '$(RPAREN)')
3893      *     ;)
3894      */
3895     LinkageAttribute parseLinkageAttribute()
3896     {
3897         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3898         auto node = allocate!LinkageAttribute;
3899         expect(tok!"extern");
3900         expect(tok!"(");
3901         const ident = expect(tok!"identifier");
3902         if (ident is null) { deallocate(node); return null; }
3903         node.identifier = *ident;
3904         if (currentIs(tok!"-"))
3905         {
3906             advance(); // skip the -
3907             advance(); // skip the C
3908         } else if (currentIs(tok!"++"))
3909         {
3910             advance();
3911             node.hasPlusPlus = true;
3912             if (currentIs(tok!","))
3913             {
3914                 advance();
3915 		if(currentIs(tok!"struct") || currentIs(tok!"class")) {
3916 			advance(); // FIXME: discarding it!
3917 
3918 		} else if(currentIs(tok!"(")) {
3919 			parseExpression(); // FIXME: discarding it!
3920 		} else
3921                 	mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`);
3922             }
3923         }
3924         expect(tok!")");
3925         return node;
3926     }
3927 
3928     /**
3929      * Parses a MemberFunctionAttribute
3930      *
3931      * $(GRAMMAR $(RULEDEF memberFunctionAttribute):
3932      *       $(RULE functionAttribute)
3933      *     | $(LITERAL 'immutable')
3934      *     | $(LITERAL 'inout')
3935      *     | $(LITERAL 'shared')
3936      *     | $(LITERAL 'const')
3937      *     | $(LITERAL 'return')
3938      *     ;)
3939      */
3940     MemberFunctionAttribute parseMemberFunctionAttribute()
3941     {
3942         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3943         auto node = allocate!MemberFunctionAttribute;
3944         switch (current.type)
3945         {
3946         case tok!"@":
3947             mixin(nullCheck!`node.atAttribute = parseAtAttribute()`);
3948             break;
3949         case tok!"immutable":
3950         case tok!"inout":
3951         case tok!"shared":
3952         case tok!"const":
3953         case tok!"pure":
3954         case tok!"nothrow":
3955         case tok!"return":
3956         case tok!"scope":
3957             node.tokenType = advance().type;
3958             break;
3959         default:
3960             error(`Member function attribute expected`);
3961         }
3962         return node;
3963     }
3964 
3965     /**
3966      * Parses a MixinDeclaration
3967      *
3968      * $(GRAMMAR $(RULEDEF mixinDeclaration):
3969      *       $(RULE mixinExpression) $(LITERAL ';')
3970      *     | $(RULE templateMixinExpression) $(LITERAL ';')
3971      *     ;)
3972      */
3973     MixinDeclaration parseMixinDeclaration()
3974     {
3975         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
3976         auto node = allocate!MixinDeclaration;
3977         if (peekIsOneOf(tok!"identifier", tok!"typeof", tok!"."))
3978             mixin(nullCheck!`node.templateMixinExpression = parseTemplateMixinExpression()`);
3979         else if (peekIs(tok!"(")) {
3980             mixin(nullCheck!`node.mixinExpression = parseMixinExpression()`);
3981 
3982 	    if(auto ae = cast(UnaryExpression) node.mixinExpression.assignExpression) {
3983 	    	auto pe = ae.primaryExpression;
3984 		if(pe) {
3985 			auto txt = pe.primary.text;
3986 			if(txt.length > 5 && txt[0 .. 2] == "q{") {
3987 				txt = txt[2 .. $-1];
3988 
3989 				LexerConfig config;
3990 				StringCache* stringCache = new StringCache(128);
3991 
3992 				config.stringBehavior = StringBehavior.source;
3993 				config.whitespaceBehavior = WhitespaceBehavior.include;
3994 				config.fileName = "mixin";
3995 
3996 				auto tokens = getTokensForParser(cast(ubyte[]) txt, config, stringCache);
3997 
3998 				foreach(ref token; tokens) {
3999 					cast() token.line += pe.primary.line - 1;
4000 				}
4001 				auto m = .parseModule(tokens, "mixin");
4002 				node.trivialDeclarations = m.declarations.dup;
4003 			}
4004 		}
4005 	    }
4006 
4007 	    //node.trivialDeclarations = parseDeclaration
4008         } else
4009         {
4010             error(`"(" or identifier expected`);
4011             return null;
4012         }
4013         expect(tok!";");
4014         return node;
4015     }
4016 
4017     /**
4018      * Parses a MixinExpression
4019      *
4020      * $(GRAMMAR $(RULEDEF mixinExpression):
4021      *     $(LITERAL 'mixin') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)')
4022      *     ;)
4023      */
4024     MixinExpression parseMixinExpression()
4025     {
4026         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4027         auto node = allocate!MixinExpression;
4028         expect(tok!"mixin");
4029         expect(tok!"(");
4030 	moar:
4031 	    // FIXME: it discards the others...
4032             mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4033         if (currentIs(tok!",")) {
4034 		advance();
4035 		goto moar;
4036 	}
4037         expect(tok!")");
4038         return node;
4039     }
4040 
4041     /**
4042      * Parses a MixinTemplateDeclaration
4043      *
4044      * $(GRAMMAR $(RULEDEF mixinTemplateDeclaration):
4045      *     $(LITERAL 'mixin') $(RULE templateDeclaration)
4046      *     ;)
4047      */
4048     MixinTemplateDeclaration parseMixinTemplateDeclaration()
4049     {
4050         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4051         auto node = allocate!MixinTemplateDeclaration;
4052         if (expect(tok!"mixin") is null) { deallocate(node); return null; }
4053         mixin(nullCheck!`node.templateDeclaration = parseTemplateDeclaration()`);
4054         if (node.templateDeclaration is null) { deallocate(node); return null; }
4055         return node;
4056     }
4057 
4058     /**
4059      * Parses a MixinTemplateName
4060      *
4061      * $(GRAMMAR $(RULEDEF mixinTemplateName):
4062      *       $(RULE symbol)
4063      *     | $(RULE typeofExpression) $(LITERAL '.') $(RULE identifierOrTemplateChain)
4064      *     ;)
4065      */
4066     MixinTemplateName parseMixinTemplateName()
4067     {
4068         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4069         auto node = allocate!MixinTemplateName;
4070         if (currentIs(tok!"typeof"))
4071         {
4072             mixin(nullCheck!`node.typeofExpression = parseTypeofExpression()`);
4073             expect(tok!".");
4074             mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`);
4075         }
4076         else
4077             mixin(nullCheck!`node.symbol = parseSymbol()`);
4078         return node;
4079     }
4080 
4081     /**
4082      * Parses a Module
4083      *
4084      * $(GRAMMAR $(RULEDEF module):
4085      *     $(RULE moduleDeclaration)? $(RULE declaration)*
4086      *     ;)
4087      */
4088     Module parseModule()
4089     {
4090         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4091         Module m = allocate!Module;
4092         if (currentIs(tok!"scriptLine"))
4093             m.scriptLine = advance();
4094         bool isDeprecatedModule;
4095         if (currentIs(tok!"deprecated"))
4096         {
4097             auto b = setBookmark();
4098             advance();
4099             if (currentIs(tok!"("))
4100                 skipParens();
4101             isDeprecatedModule = currentIs(tok!"module");
4102             goToBookmark(b);
4103         }
4104         if (currentIs(tok!"module") || isDeprecatedModule)
4105             m.moduleDeclaration = parseModuleDeclaration();
4106         Declaration[] declarations;
4107         while (moreTokens())
4108         {
4109             auto declaration = parseDeclaration();
4110             if (declaration !is null)
4111                 declarations ~= declaration;
4112         }
4113         m.declarations = ownArray(declarations);
4114         return m;
4115     }
4116 
4117     /**
4118      * Parses a ModuleDeclaration
4119      *
4120      * $(GRAMMAR $(RULEDEF moduleDeclaration):
4121      *     $(RULE deprecated)? $(LITERAL 'module') $(RULE identifierChain) $(LITERAL ';')
4122      *     ;)
4123      */
4124     ModuleDeclaration parseModuleDeclaration()
4125     {
4126         auto node = allocate!ModuleDeclaration;
4127         if (currentIs(tok!"deprecated"))
4128             mixin(nullCheck!`node.deprecated_ = parseDeprecated()`);
4129         const start = expect(tok!"module");
4130         if (start is null) { deallocate(node); return null; }
4131         mixin(nullCheck!`node.moduleName = parseIdentifierChain()`);
4132         node.comment = start.comment;
4133         if (node.comment is null)
4134             node.comment = start.trailingComment;
4135         comment = null;
4136         const end = expect(tok!";");
4137         node.startLocation = start.index;
4138         if (end !is null)
4139             node.endLocation = end.index;
4140         return node;
4141     }
4142 
4143     /**
4144      * Parses a MulExpression.
4145      *
4146      * $(GRAMMAR $(RULEDEF mulExpression):
4147      *       $(RULE powExpression)
4148      *     | $(RULE mulExpression) ($(LITERAL '*') | $(LITERAL '/') | $(LITERAL '%')) $(RULE powExpression)
4149      *     ;)
4150      */
4151     ExpressionNode parseMulExpression()
4152     {
4153         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4154         return parseLeftAssocBinaryExpression!(MulExpression, PowExpression,
4155             tok!"*", tok!"/", tok!"%")();
4156     }
4157 
4158     /**
4159      * Parses a NewAnonClassExpression
4160      *
4161      * $(GRAMMAR $(RULEDEF newAnonClassExpression):
4162      *     $(LITERAL 'new') $(RULE arguments)? $(LITERAL 'class') $(RULE arguments)? $(RULE baseClassList)? $(RULE structBody)
4163      *     ;)
4164      */
4165     NewAnonClassExpression parseNewAnonClassExpression()
4166     {
4167         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4168         auto node = allocate!NewAnonClassExpression;
4169         expect(tok!"new");
4170         if (currentIs(tok!"("))
4171             mixin(nullCheck!`node.allocatorArguments = parseArguments()`);
4172         expect(tok!"class");
4173         if (currentIs(tok!"("))
4174             mixin(nullCheck!`node.constructorArguments = parseArguments()`);
4175         if (!currentIs(tok!"{"))
4176             mixin(nullCheck!`node.baseClassList = parseBaseClassList()`);
4177         mixin(nullCheck!`node.structBody = parseStructBody()`);
4178         return node;
4179     }
4180 
4181     /**
4182      * Parses a NewExpression
4183      *
4184      * $(GRAMMAR $(RULEDEF newExpression):
4185      *       $(LITERAL 'new') $(RULE type) (($(LITERAL '[') $(RULE assignExpression) $(LITERAL ']')) | $(RULE arguments))?
4186      *     | $(RULE newAnonClassExpression)
4187      *     ;)
4188      */
4189     NewExpression parseNewExpression()
4190     {
4191         // Parse ambiguity.
4192         // auto a = new int[10];
4193         //              ^^^^^^^
4194         // auto a = new int[10];
4195         //              ^^^****
4196         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4197         auto node = allocate!NewExpression;
4198         if (peekIsOneOf(tok!"class", tok!"("))
4199         {
4200             mixin(nullCheck!`node.newAnonClassExpression = parseNewAnonClassExpression()`);
4201             if (node.newAnonClassExpression is null)
4202             {
4203                 deallocate(node);
4204                 return null;
4205             }
4206         }
4207         else
4208         {
4209             expect(tok!"new");
4210             if (!moreTokens()) goto fail;
4211             if ((node.type = parseType()) is null) goto fail;
4212             if (currentIs(tok!"["))
4213             {
4214                 advance();
4215                 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4216                 expect(tok!"]");
4217             }
4218             else if (currentIs(tok!"("))
4219                 mixin(nullCheck!`node.arguments = parseArguments()`);
4220         }
4221         return node;
4222     fail:
4223         deallocate(node);
4224         return null;
4225     }
4226 
4227     /**
4228      * Parses a NonVoidInitializer
4229      *
4230      * $(GRAMMAR $(RULEDEF nonVoidInitializer):
4231      *       $(RULE assignExpression)
4232      *     | $(RULE arrayInitializer)
4233      *     | $(RULE structInitializer)
4234      *     ;)
4235      */
4236     NonVoidInitializer parseNonVoidInitializer()
4237     {
4238         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4239         auto node = allocate!NonVoidInitializer;
4240         if (currentIs(tok!"{"))
4241         {
4242             const b = peekPastBraces();
4243             if (b !is null && (b.type == tok!"("))
4244                 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4245             else
4246             {
4247                 assert (currentIs(tok!"{"));
4248                 auto m = setBookmark();
4249                 auto initializer = parseStructInitializer();
4250                 if (initializer !is null)
4251                 {
4252                     node.structInitializer = initializer;
4253                     abandonBookmark(m);
4254                 }
4255                 else
4256                 {
4257                     goToBookmark(m);
4258                     mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4259                 }
4260             }
4261         }
4262         else if (currentIs(tok!"["))
4263         {
4264             const b = peekPastBrackets();
4265             if (b !is null && (b.type == tok!","
4266                 || b.type == tok!")"
4267                 || b.type == tok!"]"
4268                 || b.type == tok!"}"
4269                 || b.type == tok!";"))
4270             {
4271                 mixin(nullCheck!`node.arrayInitializer = parseArrayInitializer()`);
4272             }
4273             else
4274                 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4275         }
4276         else
4277             mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
4278         if (node.assignExpression is null && node.arrayInitializer is null
4279             && node.structInitializer is null)
4280         {
4281             deallocate(node);
4282             return null;
4283         }
4284         return node;
4285     }
4286 
4287     /**
4288      * Parses Operands
4289      *
4290      * $(GRAMMAR $(RULEDEF operands):
4291      *       $(RULE asmExp)
4292      *     | $(RULE asmExp) $(LITERAL ',') $(RULE operands)
4293      *     ;)
4294      */
4295     Operands parseOperands()
4296     {
4297         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4298         Operands node = allocate!Operands;
4299         ExpressionNode[] expressions;
4300         while (true)
4301         {
4302             ExpressionNode exp = parseAsmExp();
4303             if (exp is null)
4304                 return null;
4305             expressions ~= exp;
4306             if (currentIs(tok!","))
4307                 advance();
4308             else
4309                 break;
4310         }
4311         node.operands = ownArray(expressions);
4312         return node;
4313     }
4314 
4315     /**
4316      * Parses an OrExpression
4317      *
4318      * $(GRAMMAR $(RULEDEF orExpression):
4319      *       $(RULE xorExpression)
4320      *     | $(RULE orExpression) $(LITERAL '|') $(RULE xorExpression)
4321      *     ;)
4322      */
4323     ExpressionNode parseOrExpression()
4324     {
4325         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4326         return parseLeftAssocBinaryExpression!(OrExpression, XorExpression,
4327             tok!"|")();
4328     }
4329 
4330     /**
4331      * Parses an OrOrExpression
4332      *
4333      * $(GRAMMAR $(RULEDEF orOrExpression):
4334      *       $(RULE andAndExpression)
4335      *     | $(RULE orOrExpression) $(LITERAL '||') $(RULE andAndExpression)
4336      *     ;)
4337      */
4338     ExpressionNode parseOrOrExpression()
4339     {
4340         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4341         return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression,
4342             tok!"||")();
4343     }
4344 
4345     /**
4346      * Parses an OutStatement
4347      *
4348      * $(GRAMMAR $(RULEDEF outStatement):
4349      *     $(LITERAL 'out') ($(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)'))? $(RULE blockStatement)
4350      *     ;)
4351      */
4352     OutStatement parseOutStatement()
4353     {
4354         auto node = allocate!OutStatement;
4355         const o = expect(tok!"out");
4356         mixin(nullCheck!`o`);
4357         node.outTokenLocation = o.index;
4358 
4359 /*
4360 	if tere's a semicolon in the parens, it is the short syntax.
4361 */
4362 
4363         if (currentIs(tok!"("))
4364         {
4365             advance();
4366 	    if(currentIs(tok!"identifier")) {
4367             	const ident = expect(tok!"identifier");
4368             	node.parameter = *ident;
4369 	}
4370 	    if(currentIs(tok!";")) {
4371 			// short syntax......
4372 			advance();
4373 			node.expression = parseExpression;
4374             		expect(tok!")");
4375 			return node;
4376 	    } else {
4377             		expect(tok!")");
4378 	    }
4379         }
4380         mixin(nullCheck!`node.blockStatement = parseBlockStatement()`);
4381         if (node.blockStatement is null)
4382             return null;
4383         return node;
4384     }
4385 
4386     /**
4387      * Parses a Parameter
4388      *
4389      * $(GRAMMAR $(RULEDEF parameter):
4390      *     $(RULE parameterAttribute)* $(RULE type)
4391      *     $(RULE parameterAttribute)* $(RULE type) $(LITERAL Identifier)? $(LITERAL '...')
4392      *     $(RULE parameterAttribute)* $(RULE type) $(LITERAL Identifier)? ($(LITERAL '=') $(RULE assignExpression))?
4393      *     ;)
4394      */
4395     Parameter parseParameter()
4396     {
4397         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4398         auto node = allocate!Parameter;
4399 
4400         node.comment = current.comment;
4401 
4402         while (moreTokens())
4403 	{
4404 		if(currentIs(tok!"@")) {
4405 			AtAttribute atAttribute;
4406 			mixin(nullCheck!`atAttribute = parseAtAttribute()`);
4407 			if (atAttribute is null) { deallocate(node); break; }
4408 			node.atAttributes ~= atAttribute;
4409 		} else {
4410 			break;
4411 		}
4412 	}
4413 
4414         IdType[] parameterAttributes;
4415         while (moreTokens())
4416         {
4417             IdType type = parseParameterAttribute(false);
4418             if (type == tok!"")
4419                 break;
4420             else
4421                 parameterAttributes ~= type;
4422         }
4423         node.parameterAttributes = ownArray(parameterAttributes);
4424         mixin(nullCheck!`node.type = parseType()`);
4425         if (node.type is null) { deallocate(node); return null; }
4426         if (currentIs(tok!"identifier"))
4427         {
4428             node.name = advance();
4429             if (currentIs(tok!"..."))
4430             {
4431                 advance();
4432                 node.vararg = true;
4433             }
4434             else if (currentIs(tok!"="))
4435             {
4436                 advance();
4437                 mixin(nullCheck!`node.default_ = parseAssignExpression()`);
4438             }
4439             else if (currentIs(tok!"["))
4440             {
4441                 TypeSuffix[] typeSuffixes;
4442                 while(moreTokens() && currentIs(tok!"["))
4443                 {
4444                     auto suffix = parseTypeSuffix();
4445                     if (suffix !is null)
4446                         typeSuffixes ~= suffix;
4447                     else
4448                         return null;
4449                 }
4450                 node.cstyle = ownArray(typeSuffixes);
4451             }
4452         }
4453         else if (currentIs(tok!"..."))
4454         {
4455             node.vararg = true;
4456             advance();
4457         }
4458         else if (currentIs(tok!"="))
4459         {
4460             advance();
4461             mixin(nullCheck!`node.default_ = parseAssignExpression()`);
4462         }
4463         return node;
4464     }
4465 
4466     /**
4467      * Parses a ParameterAttribute
4468      *
4469      * $(GRAMMAR $(RULEDEF parameterAttribute):
4470      *       $(RULE typeConstructor)
4471      *     | $(LITERAL 'final')
4472      *     | $(LITERAL 'in')
4473      *     | $(LITERAL 'lazy')
4474      *     | $(LITERAL 'out')
4475      *     | $(LITERAL 'ref')
4476      *     | $(LITERAL 'scope')
4477      *     | $(LITERAL 'auto')
4478      *     | $(LITERAL 'return')
4479      *     ;)
4480      */
4481     IdType parseParameterAttribute(bool validate = false)
4482     {
4483         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4484         switch (current.type)
4485         {
4486         case tok!"immutable":
4487         case tok!"shared":
4488         case tok!"const":
4489         case tok!"inout":
4490             if (peekIs(tok!"("))
4491                 return tok!"";
4492             else
4493                 goto case;
4494         case tok!"final":
4495         case tok!"in":
4496         case tok!"lazy":
4497         case tok!"out":
4498         case tok!"ref":
4499         case tok!"scope":
4500         case tok!"auto":
4501         case tok!"return":
4502             return advance().type;
4503         default:
4504             if (validate)
4505                 error("Parameter attribute expected");
4506             return tok!"";
4507         }
4508     }
4509 
4510     /**
4511      * Parses Parameters
4512      *
4513      * $(GRAMMAR $(RULEDEF parameters):
4514      *       $(LITERAL '$(LPAREN)') $(RULE parameter) ($(LITERAL ',') $(RULE parameter))* ($(LITERAL ',') $(LITERAL '...'))? $(LITERAL '$(RPAREN)')
4515      *     | $(LITERAL '$(LPAREN)') $(LITERAL '...') $(LITERAL '$(RPAREN)')
4516      *     | $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)')
4517      *     ;)
4518      */
4519     Parameters parseParameters()
4520     {
4521         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4522         auto node = allocate!Parameters;
4523         if (expect(tok!"(") is null) { deallocate(node); return null; }
4524         Parameter[] parameters;
4525         if (currentIs(tok!")"))
4526             goto end;
4527         if (currentIs(tok!"..."))
4528         {
4529             advance();
4530             node.hasVarargs = true;
4531             goto end;
4532         }
4533         while (moreTokens())
4534         {
4535             if (currentIs(tok!"..."))
4536             {
4537                 advance();
4538                 node.hasVarargs = true;
4539                 break;
4540             }
4541             if (currentIs(tok!")"))
4542                 break;
4543             auto param = parseParameter();
4544             if (param is null)
4545                 return null;
4546             parameters ~= param;
4547             if (currentIs(tok!","))
4548                 advance();
4549             else
4550                 break;
4551         }
4552         node.parameters = ownArray(parameters);
4553     end:
4554         if (expect(tok!")") is null)
4555             return null;
4556         return node;
4557     }
4558 
4559     /**
4560      * Parses a Postblit
4561      *
4562      * $(GRAMMAR $(RULEDEF postblit):
4563      *     $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL 'this') $(LITERAL '$(RPAREN)') $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';'))
4564      *     ;)
4565      */
4566     Postblit parsePostblit()
4567     {
4568         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4569         auto node = allocate!Postblit;
4570 	node.comment = comment;
4571 	node.line = current.line;
4572 	comment = null;
4573         expect(tok!"this");
4574         expect(tok!"(");
4575         expect(tok!"this");
4576         expect(tok!")");
4577         MemberFunctionAttribute[] memberFunctionAttributes;
4578         while (currentIsMemberFunctionAttribute())
4579             memberFunctionAttributes ~= parseMemberFunctionAttribute();
4580         node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
4581         if (currentIs(tok!";"))
4582             advance();
4583         else
4584             mixin(nullCheck!`node.functionBody = parseFunctionBody()`);
4585         return node;
4586     }
4587 
4588     /**
4589      * Parses a PowExpression
4590      *
4591      * $(GRAMMAR $(RULEDEF powExpression):
4592      *       $(RULE unaryExpression)
4593      *     | $(RULE powExpression) $(LITERAL '^^') $(RULE unaryExpression)
4594      *     ;)
4595      */
4596     ExpressionNode parsePowExpression()
4597     {
4598         mixin(traceEnterAndExit!(__FUNCTION__));
4599         return parseLeftAssocBinaryExpression!(PowExpression, UnaryExpression,
4600             tok!"^^")();
4601     }
4602 
4603     /**
4604      * Parses a PragmaDeclaration
4605      *
4606      * $(GRAMMAR $(RULEDEF pragmaDeclaration):
4607      *     $(RULE pragmaExpression) $(LITERAL ';')
4608      *     ;)
4609      */
4610     PragmaDeclaration parsePragmaDeclaration()
4611     {
4612         mixin(traceEnterAndExit!(__FUNCTION__));
4613         auto node = allocate!PragmaDeclaration;
4614         mixin(nullCheck!`node.pragmaExpression = parsePragmaExpression()`);
4615         expect(tok!";");
4616         return node;
4617     }
4618 
4619     /**
4620      * Parses a PragmaExpression
4621      *
4622      * $(GRAMMAR $(RULEDEF pragmaExpression):
4623      *     $(RULE 'pragma') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) ($(LITERAL ',') $(RULE argumentList))? $(LITERAL '$(RPAREN)')
4624      *     ;)
4625      */
4626     PragmaExpression parsePragmaExpression()
4627     {
4628         mixin(traceEnterAndExit!(__FUNCTION__));
4629         auto node = allocate!PragmaExpression;
4630         expect(tok!"pragma");
4631         expect(tok!"(");
4632         const ident = expect(tok!"identifier");
4633         if (ident is null) { deallocate(node); return null; }
4634         node.identifier = *ident;
4635         if (currentIs(tok!","))
4636         {
4637             advance();
4638             mixin(nullCheck!`node.argumentList = parseArgumentList()`);
4639         }
4640         expect(tok!")");
4641         return node;
4642     }
4643 
4644     /**
4645      * Parses a PrimaryExpression
4646      *
4647      * $(GRAMMAR $(RULEDEF primaryExpression):
4648      *       $(RULE identifierOrTemplateInstance)
4649      *     | $(LITERAL '.') $(RULE identifierOrTemplateInstance)
4650      *     | $(RULE typeConstructor) $(LITERAL '$(LPAREN)') $(RULE basicType) $(LITERAL '$(RPAREN)') $(LITERAL '.') $(LITERAL Identifier)
4651      *     | $(RULE basicType) $(LITERAL '.') $(LITERAL Identifier)
4652      *     | $(RULE basicType) $(RULE arguments)
4653      *     | $(RULE typeofExpression)
4654      *     | $(RULE typeidExpression)
4655      *     | $(RULE vector)
4656      *     | $(RULE arrayLiteral)
4657      *     | $(RULE assocArrayLiteral)
4658      *     | $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)')
4659      *     | $(RULE isExpression)
4660      *     | $(RULE lambdaExpression)
4661      *     | $(RULE functionLiteralExpression)
4662      *     | $(RULE traitsExpression)
4663      *     | $(RULE mixinExpression)
4664      *     | $(RULE importExpression)
4665      *     | $(LITERAL '$')
4666      *     | $(LITERAL 'this')
4667      *     | $(LITERAL 'super')
4668      *     | $(LITERAL '_null')
4669      *     | $(LITERAL '_true')
4670      *     | $(LITERAL '_false')
4671      *     | $(LITERAL '___DATE__')
4672      *     | $(LITERAL '___TIME__')
4673      *     | $(LITERAL '___TIMESTAMP__')
4674      *     | $(LITERAL '___VENDOR__')
4675      *     | $(LITERAL '___VERSION__')
4676      *     | $(LITERAL '___FILE__')
4677      *     | $(LITERAL '___LINE__')
4678      *     | $(LITERAL '___MODULE__')
4679      *     | $(LITERAL '___FUNCTION__')
4680      *     | $(LITERAL '___PRETTY_FUNCTION__')
4681      *     | $(LITERAL IntegerLiteral)
4682      *     | $(LITERAL FloatLiteral)
4683      *     | $(LITERAL StringLiteral)+
4684      *     | $(LITERAL CharacterLiteral)
4685      *     ;)
4686      */
4687     PrimaryExpression parsePrimaryExpression()
4688     {
4689         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4690         auto node = allocate!PrimaryExpression;
4691         if (!moreTokens())
4692         {
4693             error("Expected primary statement instead of EOF");
4694             return null;
4695         }
4696         switch (current.type)
4697         {
4698         case tok!".":
4699             node.dot = advance();
4700             goto case;
4701         case tok!"identifier":
4702             if (peekIs(tok!"=>"))
4703                 mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`);
4704             else
4705                 mixin(nullCheck!`node.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance()`);
4706             break;
4707         case tok!"immutable":
4708         case tok!"const":
4709         case tok!"inout":
4710         case tok!"shared":
4711             advance();
4712             expect(tok!"(");
4713             mixin(nullCheck!`node.type = parseType()`);
4714             expect(tok!")");
4715             expect(tok!".");
4716 	    {
4717             const ident = expect(tok!"identifier");
4718             if (ident !is null)
4719                 node.primary = *ident;
4720 	    }
4721             break;
4722         mixin(BUILTIN_TYPE_CASES);
4723             node.basicType = advance();
4724             if (currentIs(tok!"."))
4725             {
4726                 advance();
4727                 const t = expect(tok!"identifier");
4728                 if (t !is null)
4729                     node.primary = *t;
4730             }
4731             else if (currentIs(tok!"("))
4732                 mixin(nullCheck!`node.arguments = parseArguments()`);
4733             break;
4734         case tok!"function":
4735         case tok!"delegate":
4736             if (peekIs(tok!"("))
4737             {
4738                 auto b = setBookmark();
4739                 advance(); // function | delegate
4740                 skipParens();
4741                 while (isAttribute())
4742                     parseAttribute();
4743                 if (currentIs(tok!"=>"))
4744                 {
4745                     goToBookmark(b);
4746                     mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`);
4747                     break;
4748                 }
4749                 else
4750                 {
4751                     goToBookmark(b);
4752                     mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`);
4753                     break;
4754                 }
4755             }
4756             else if (peekIs(tok!"{"))
4757             {
4758                 mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`);
4759                 break;
4760             }
4761             else
4762             {
4763                 auto b = setBookmark();
4764                 advance(); // function or delegate
4765                 if (parseType() is null)
4766                 {
4767                     goToBookmark(b);
4768                     goto case;
4769                 }
4770                 if (!currentIs(tok!"("))
4771                 {
4772                     goToBookmark(b);
4773                     goto case;
4774                 }
4775                 skipParens();
4776                 while (currentIsMemberFunctionAttribute())
4777                     parseMemberFunctionAttribute();
4778                 if (!currentIs(tok!"=>"))
4779                 {
4780                     goToBookmark(b);
4781                     goto case;
4782                 }
4783                 goToBookmark(b);
4784                 if ((node.lambdaExpression = parseLambdaExpression()) is null) { deallocate(node); return null; }
4785                 return node;
4786             }
4787         case tok!"{":
4788         case tok!"in":
4789         case tok!"out":
4790         case tok!"body":
4791         case tok!"do":
4792             if ((node.functionLiteralExpression = parseFunctionLiteralExpression()) is null)
4793             {
4794                 deallocate(node);
4795                 return null;
4796             }
4797             break;
4798         case tok!"typeof":
4799             mixin(nullCheck!`node.typeofExpression = parseTypeofExpression()`);
4800             break;
4801         case tok!"typeid":
4802             mixin(nullCheck!`node.typeidExpression = parseTypeidExpression()`);
4803             break;
4804         case tok!"__vector":
4805             mixin(nullCheck!`node.vector = parseVector()`);
4806             break;
4807         case tok!"[":
4808             if (isAssociativeArrayLiteral())
4809                 mixin(nullCheck!`node.assocArrayLiteral = parseAssocArrayLiteral()`);
4810             else
4811                 mixin(nullCheck!`node.arrayLiteral = parseArrayLiteral()`);
4812             break;
4813         case tok!"(":
4814             auto b = setBookmark();
4815             skipParens();
4816             while (isAttribute())
4817                 parseAttribute();
4818             if (currentIs(tok!"=>"))
4819             {
4820                 goToBookmark(b);
4821                 mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`);
4822             }
4823             else if (currentIs(tok!"{"))
4824             {
4825                 goToBookmark(b);
4826                 mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`);
4827             }
4828             else
4829             {
4830                 goToBookmark(b);
4831                 advance();
4832                 mixin(nullCheck!`node.expression = parseExpression()`);
4833                 mixin(nullCheck!`expect(tok!")")`);
4834             }
4835             break;
4836         case tok!"is":
4837             mixin(nullCheck!`node.isExpression = parseIsExpression()`);
4838             break;
4839         case tok!"__traits":
4840             mixin(nullCheck!`node.traitsExpression = parseTraitsExpression()`);
4841             break;
4842         case tok!"mixin":
4843             mixin(nullCheck!`node.mixinExpression = parseMixinExpression()`);
4844             break;
4845         case tok!"import":
4846             mixin(nullCheck!`node.importExpression = parseImportExpression()`);
4847             break;
4848         case tok!"$":
4849         case tok!"this":
4850         case tok!"super":
4851         case tok!"null":
4852         case tok!"true":
4853         case tok!"false":
4854         mixin(SPECIAL_CASES);
4855         mixin(LITERAL_CASES);
4856             if (currentIsOneOf(tok!"stringLiteral", tok!"wstringLiteral", tok!"dstringLiteral"))
4857             {
4858                 node.primary = advance();
4859                 bool alreadyWarned = false;
4860                 while (currentIsOneOf(tok!"stringLiteral", tok!"wstringLiteral",
4861                     tok!"dstringLiteral"))
4862                 {
4863                     if (!alreadyWarned)
4864                     {
4865                         warn("Implicit concatenation of string literals");
4866                         alreadyWarned = true;
4867                     }
4868                     node.primary.text ~= advance().text;
4869                 }
4870             }
4871             else
4872                 node.primary = advance();
4873             break;
4874         default:
4875             deallocate(node);
4876             error("Primary expression expected");
4877             return null;
4878         }
4879         return node;
4880     }
4881 
4882     /**
4883      * Parses a Register
4884      *
4885      * $(GRAMMAR $(RULEDEF register):
4886      *       $(LITERAL Identifier)
4887      *     | $(LITERAL Identifier) $(LITERAL '$(LPAREN)') $(LITERAL IntegerLiteral) $(LITERAL '$(RPAREN)')
4888      *     ;)
4889      */
4890     Register parseRegister()
4891     {
4892         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4893         auto node = allocate!Register;
4894         const ident = expect(tok!"identifier");
4895         if (ident is null) { deallocate(node); return null; }
4896         node.identifier = *ident;
4897         if (currentIs(tok!"("))
4898         {
4899             advance();
4900             const intLit = expect(tok!"intLiteral");
4901             if (intLit is null) { deallocate(node); return null; }
4902             node.intLiteral = *intLit;
4903             expect(tok!")");
4904         }
4905         return node;
4906     }
4907 
4908     /**
4909      * Parses a RelExpression
4910      *
4911      * $(GRAMMAR $(RULEDEF relExpression):
4912      *       $(RULE shiftExpression)
4913      *     | $(RULE relExpression) $(RULE relOperator) $(RULE shiftExpression)
4914      *     ;
4915      *$(RULEDEF relOperator):
4916      *       $(LITERAL '<')
4917      *     | $(LITERAL '<=')
4918      *     | $(LITERAL '>')
4919      *     | $(LITERAL '>=')
4920      *     | $(LITERAL '!<>=')
4921      *     | $(LITERAL '!<>')
4922      *     | $(LITERAL '<>')
4923      *     | $(LITERAL '<>=')
4924      *     | $(LITERAL '!>')
4925      *     | $(LITERAL '!>=')
4926      *     | $(LITERAL '!<')
4927      *     | $(LITERAL '!<=')
4928      *     ;)
4929      */
4930     ExpressionNode parseRelExpression(ExpressionNode shift)
4931     {
4932         mixin(traceEnterAndExit!(__FUNCTION__));
4933         return parseLeftAssocBinaryExpression!(RelExpression, ShiftExpression,
4934             tok!"<", tok!"<=", tok!">", tok!">=", tok!"!<>=", tok!"!<>",
4935             tok!"<>", tok!"<>=", tok!"!>", tok!"!>=", tok!"!>=", tok!"!<",
4936             tok!"!<=")(shift);
4937     }
4938 
4939     /**
4940      * Parses a ReturnStatement
4941      *
4942      * $(GRAMMAR $(RULEDEF returnStatement):
4943      *     $(LITERAL 'return') $(RULE expression)? $(LITERAL ';')
4944      *     ;)
4945      */
4946     ReturnStatement parseReturnStatement()
4947     {
4948         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4949         auto node = allocate!ReturnStatement;
4950         const start = expect(tok!"return");
4951         if (start is null) { deallocate(node); return null; }
4952         node.startLocation = start.index;
4953         if (!currentIs(tok!";"))
4954         {
4955             if ((node.expression = parseExpression()) is null)
4956             {
4957                 deallocate(node);
4958                 return null;
4959             }
4960         }
4961         const semicolon = expect(tok!";");
4962         if (semicolon is null) { deallocate(node); return null; }
4963         node.endLocation = semicolon.index;
4964         return node;
4965     }
4966 
4967     /**
4968      * Parses a ScopeGuardStatement
4969      *
4970      * $(GRAMMAR $(RULEDEF scopeGuardStatement):
4971      *     $(LITERAL 'scope') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault)
4972      *     ;)
4973      */
4974     ScopeGuardStatement parseScopeGuardStatement()
4975     {
4976         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4977         auto node = allocate!ScopeGuardStatement;
4978         expect(tok!"scope");
4979         expect(tok!"(");
4980         const ident = expect(tok!"identifier");
4981         if (ident is null) { deallocate(node); return null; }
4982         node.identifier = *ident;
4983         expect(tok!")");
4984         mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`);
4985         return node;
4986     }
4987 
4988     /**
4989      * Parses a SharedStaticConstructor
4990      *
4991      * $(GRAMMAR $(RULEDEF sharedStaticConstructor):
4992      *     $(LITERAL 'shared') $(LITERAL 'static') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody)
4993      *     ;)
4994      */
4995     SharedStaticConstructor parseSharedStaticConstructor()
4996     {
4997         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
4998         mixin(simpleParse!(SharedStaticConstructor, tok!"shared", tok!"static",
4999             tok!"this", tok!"(", tok!")", "functionBody|parseFunctionBody"));
5000     }
5001 
5002     /**
5003      * Parses a SharedStaticDestructor
5004      *
5005      * $(GRAMMAR $(RULEDEF sharedStaticDestructor):
5006      *     $(LITERAL 'shared') $(LITERAL 'static') $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody)
5007      *     ;)
5008      */
5009     SharedStaticDestructor parseSharedStaticDestructor()
5010     {
5011         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5012         mixin(simpleParse!(SharedStaticDestructor, tok!"shared", tok!"static",
5013             tok!"~", tok!"this", tok!"(", tok!")",
5014             "functionBody|parseFunctionBody"));
5015     }
5016 
5017     /**
5018      * Parses a ShiftExpression
5019      *
5020      * $(GRAMMAR $(RULEDEF shiftExpression):
5021      *       $(RULE addExpression)
5022      *     | $(RULE shiftExpression) ($(LITERAL '<<') | $(LITERAL '>>') | $(LITERAL '>>>')) $(RULE addExpression)
5023      *     ;)
5024      */
5025     ExpressionNode parseShiftExpression()
5026     {
5027         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5028         return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression,
5029             tok!"<<", tok!">>", tok!">>>")();
5030     }
5031 
5032     /**
5033      * Parses a SingleImport
5034      *
5035      * $(GRAMMAR $(RULEDEF singleImport):
5036      *     ($(LITERAL Identifier) $(LITERAL '='))? $(RULE identifierChain)
5037      *     ;)
5038      */
5039     SingleImport parseSingleImport()
5040     {
5041         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5042         auto node = allocate!SingleImport;
5043         if (startsWith(tok!"identifier", tok!"="))
5044         {
5045             node.rename = advance();
5046             advance(); // =
5047         }
5048         mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`);
5049         if (node.identifierChain is null)
5050             return null;
5051         return node;
5052     }
5053 
5054     /**
5055      * Parses a Statement
5056      *
5057      * $(GRAMMAR $(RULEDEF statement):
5058      *       $(RULE statementNoCaseNoDefault)
5059      *     | $(RULE caseStatement)
5060      *     | $(RULE caseRangeStatement)
5061      *     | $(RULE defaultStatement)
5062      *     ;)
5063      */
5064     Statement parseStatement()
5065     {
5066         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5067         auto node = allocate!Statement;
5068         if (!moreTokens())
5069         {
5070             error("Expected statement instead of EOF");
5071             return null;
5072         }
5073         switch (current.type)
5074         {
5075         case tok!"case":
5076             advance();
5077             auto argumentList = parseArgumentList();
5078             if (argumentList is null)
5079             {
5080                 deallocate(node);
5081                 return null;
5082             }
5083             if (argumentList.items.length == 1 && startsWith(tok!":", tok!".."))
5084                 node.caseRangeStatement = parseCaseRangeStatement(argumentList.items[0]);
5085             else
5086                 node.caseStatement = parseCaseStatement(argumentList);
5087             break;
5088         case tok!"default":
5089             mixin(nullCheck!`node.defaultStatement = parseDefaultStatement()`);
5090             break;
5091         default:
5092             if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null)
5093             {
5094                 deallocate(node);
5095                 return null;
5096             }
5097             break;
5098         }
5099         return node;
5100     }
5101 
5102     /**
5103      * Parses a StatementNoCaseNoDefault
5104      *
5105      * $(GRAMMAR $(RULEDEF statementNoCaseNoDefault):
5106      *       $(RULE labeledStatement)
5107      *     | $(RULE blockStatement)
5108      *     | $(RULE ifStatement)
5109      *     | $(RULE whileStatement)
5110      *     | $(RULE doStatement)
5111      *     | $(RULE forStatement)
5112      *     | $(RULE foreachStatement)
5113      *     | $(RULE switchStatement)
5114      *     | $(RULE finalSwitchStatement)
5115      *     | $(RULE continueStatement)
5116      *     | $(RULE breakStatement)
5117      *     | $(RULE returnStatement)
5118      *     | $(RULE gotoStatement)
5119      *     | $(RULE withStatement)
5120      *     | $(RULE synchronizedStatement)
5121      *     | $(RULE tryStatement)
5122      *     | $(RULE throwStatement)
5123      *     | $(RULE scopeGuardStatement)
5124      *     | $(RULE asmStatement)
5125      *     | $(RULE conditionalStatement)
5126      *     | $(RULE staticAssertStatement)
5127      *     | $(RULE versionSpecification)
5128      *     | $(RULE debugSpecification)
5129      *     | $(RULE expressionStatement)
5130      *     ;)
5131      */
5132     StatementNoCaseNoDefault parseStatementNoCaseNoDefault()
5133     {
5134     version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5135         auto node = allocate!StatementNoCaseNoDefault;
5136         node.startLocation = current().index;
5137         switch (current.type)
5138         {
5139         case tok!"{":
5140             mixin(nullCheck!`node.blockStatement = parseBlockStatement()`);
5141             break;
5142         case tok!"if":
5143             mixin(nullCheck!`node.ifStatement = parseIfStatement()`);
5144             break;
5145         case tok!"while":
5146             mixin(nullCheck!`node.whileStatement = parseWhileStatement()`);
5147             break;
5148         case tok!"do":
5149             mixin(nullCheck!`node.doStatement = parseDoStatement()`);
5150             break;
5151         case tok!"for":
5152             mixin(nullCheck!`node.forStatement = parseForStatement()`);
5153             break;
5154         case tok!"foreach":
5155         case tok!"foreach_reverse":
5156             mixin(nullCheck!`node.foreachStatement = parseForeachStatement()`);
5157             break;
5158         case tok!"switch":
5159             mixin(nullCheck!`node.switchStatement = parseSwitchStatement()`);
5160             break;
5161         case tok!"continue":
5162             mixin(nullCheck!`node.continueStatement = parseContinueStatement()`);
5163             break;
5164         case tok!"break":
5165             mixin(nullCheck!`node.breakStatement = parseBreakStatement()`);
5166             break;
5167         case tok!"return":
5168             mixin(nullCheck!`node.returnStatement = parseReturnStatement()`);
5169             break;
5170         case tok!"goto":
5171             mixin(nullCheck!`node.gotoStatement = parseGotoStatement()`);
5172             break;
5173         case tok!"with":
5174             mixin(nullCheck!`node.withStatement = parseWithStatement()`);
5175             break;
5176         case tok!"synchronized":
5177             mixin(nullCheck!`node.synchronizedStatement = parseSynchronizedStatement()`);
5178             break;
5179         case tok!"try":
5180             mixin(nullCheck!`node.tryStatement = parseTryStatement()`);
5181             break;
5182         case tok!"throw":
5183             mixin(nullCheck!`node.throwStatement = parseThrowStatement()`);
5184             break;
5185         case tok!"scope":
5186             mixin(nullCheck!`node.scopeGuardStatement = parseScopeGuardStatement()`);
5187             break;
5188         case tok!"asm":
5189             mixin(nullCheck!`node.asmStatement = parseAsmStatement()`);
5190             break;
5191         case tok!"final":
5192             if (peekIs(tok!"switch"))
5193             {
5194                 mixin(nullCheck!`node.finalSwitchStatement = parseFinalSwitchStatement()`);
5195                 break;
5196             }
5197             else
5198             {
5199                 error(`"switch" expected`);
5200                 return null;
5201             }
5202         case tok!"debug":
5203             if (peekIs(tok!"="))
5204                 mixin(nullCheck!`node.debugSpecification = parseDebugSpecification()`);
5205             else
5206                 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`);
5207             break;
5208         case tok!"version":
5209             if (peekIs(tok!"="))
5210                 mixin(nullCheck!`node.versionSpecification = parseVersionSpecification()`);
5211             else
5212                 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`);
5213             break;
5214         case tok!"static":
5215             if (peekIs(tok!"if"))
5216                 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`);
5217             else if (peekIs(tok!"assert"))
5218                 mixin(nullCheck!`node.staticAssertStatement = parseStaticAssertStatement()`);
5219             else if (peekIs(tok!"foreach"))
5220                 mixin(nullCheck!`node.staticForeachStatement = parseStaticForeachStatement()`);
5221             else
5222             {
5223                 error("'if' or 'assert' expected.");
5224                 return null;
5225             }
5226             break;
5227         case tok!"identifier":
5228             if (peekIs(tok!":"))
5229             {
5230                 mixin(nullCheck!`node.labeledStatement = parseLabeledStatement()`);
5231                 break;
5232             }
5233             goto default;
5234         case tok!"delete":
5235         case tok!"assert":
5236         default:
5237             if ((node.expressionStatement = parseExpressionStatement()) is null)
5238             {
5239                 deallocate(node);
5240                 return null;
5241             }
5242             break;
5243         }
5244         node.endLocation = tokens[index - 1].index;
5245         return node;
5246     }
5247 
5248     /**
5249      * Parses a StaticAssertDeclaration
5250      *
5251      * $(GRAMMAR $(RULEDEF staticAssertDeclaration):
5252      *     $(RULE staticAssertStatement)
5253      *     ;)
5254      */
5255     StaticAssertDeclaration parseStaticAssertDeclaration()
5256     {
5257         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5258         mixin(simpleParse!(StaticAssertDeclaration,
5259             "staticAssertStatement|parseStaticAssertStatement"));
5260     }
5261 
5262 
5263     /**
5264      * Parses a StaticAssertStatement
5265      *
5266      * $(GRAMMAR $(RULEDEF staticAssertStatement):
5267      *     $(LITERAL 'static') $(RULE assertExpression) $(LITERAL ';')
5268      *     ;)
5269      */
5270     StaticAssertStatement parseStaticAssertStatement()
5271     {
5272         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5273         mixin(simpleParse!(StaticAssertStatement,
5274             tok!"static", "assertExpression|parseAssertExpression", tok!";"));
5275     }
5276 
5277 	// FIXME: so this one is kinda important but i am doing it lazily
5278     StaticForeachDeclaration parseStaticForeachDeclaration()
5279     {
5280 
5281 
5282 	auto node = new StaticForeachDeclaration();
5283 
5284 	expect(tok!"static");
5285 	expect(tok!"foreach");
5286 	expect(tok!"(");
5287 	auto n = advance();
5288 	int parensCount = 1;
5289 	while(parensCount > 0) {
5290 		if(n == tok!"(")
5291 			parensCount++;
5292 		else if(n == tok!")")
5293 			parensCount--;
5294 		n = advance();
5295 	}
5296 
5297 	if(n == tok!"{") {
5298 		int bracesCount = 1;
5299 		n = advance();
5300 		while(bracesCount > 0) {
5301 			if(n == tok!"}") {
5302 				bracesCount--;
5303 				if(bracesCount == 0) break;
5304 			} else if(n == tok!"{")
5305 				bracesCount++;
5306 			n = advance();
5307 		}
5308 	} else {
5309 		if(isDeclaration())
5310 			parseDeclaration();
5311 		else
5312 			parseStatement();
5313 	}
5314 
5315 	return node;
5316 
5317 
5318 /+
5319 
5320         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5321 	expect(tok!"static");
5322 	expect(tok!"foreach");
5323 	expect(tok!"(");
5324 	auto n = advance();
5325 	int parensCount = 1;
5326 	while(parensCount > 0) {
5327 		if(n == tok!"(")
5328 			parensCount++;
5329 		else if(n == tok!")")
5330 			parensCount--;
5331 		n = advance();
5332 	}
5333 
5334 	auto node = new StaticForeachDeclaration();
5335 
5336         Declaration[] declarations;
5337         if (currentIs(tok!"{"))
5338         {
5339             advance();
5340             while (moreTokens() && !currentIs(tok!"}"))
5341             {
5342                 auto b = setBookmark();
5343                 auto d = parseDeclaration();
5344                 if (d !is null)
5345                 {
5346                     abandonBookmark(b);
5347                     declarations ~= d;
5348                 }
5349                 else
5350                 {
5351                     goToBookmark(b);
5352                     return null;
5353                 }
5354             }
5355             node.declarations = declarations;
5356             return node;
5357         } else {
5358             node.declarations ~= parseDeclaration();
5359 	}
5360 
5361 	return node;
5362 +/
5363     }
5364 
5365     // FIXME. i don't really care about this right now but just want it
5366     // good enough to avoid errors for now
5367     StaticForeachStatement parseStaticForeachStatement()
5368     {
5369         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5370 
5371 	auto node = new StaticForeachStatement();
5372 
5373 	expect(tok!"static");
5374 	expect(tok!"foreach");
5375 	expect(tok!"(");
5376 	auto n = advance();
5377 	int parensCount = 1;
5378 	while(parensCount > 0) {
5379 		if(n == tok!"(")
5380 			parensCount++;
5381 		else if(n == tok!")")
5382 			parensCount--;
5383 		n = advance();
5384 	}
5385 
5386 	if(n == tok!"{") {
5387 		int bracesCount = 1;
5388 		n = advance();
5389 		while(bracesCount > 0) {
5390 			if(n == tok!"}") {
5391 				bracesCount--;
5392 				if(bracesCount == 0) break;
5393 			} else if(n == tok!"{")
5394 				bracesCount++;
5395 			n = advance();
5396 		}
5397 	} else {
5398 		if(isDeclaration())
5399 			parseDeclaration();
5400 		else
5401 			parseStatement();
5402 	}
5403 
5404 	return node;
5405     }
5406 
5407     /**
5408      * Parses a StaticConstructor
5409      *
5410      * $(GRAMMAR $(RULEDEF staticConstructor):
5411      *     $(LITERAL 'static') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody)
5412      *     ;)
5413      */
5414     StaticConstructor parseStaticConstructor()
5415     {
5416         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5417         mixin(simpleParse!(StaticConstructor, tok!"static", tok!"this",
5418             tok!"(", tok!")", "functionBody|parseFunctionBody"));
5419     }
5420 
5421     /**
5422      * Parses a StaticDestructor
5423      *
5424      * $(GRAMMAR $(RULEDEF staticDestructor):
5425      *     $(LITERAL 'static') $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody)
5426      *     ;)
5427      */
5428     StaticDestructor parseStaticDestructor()
5429     {
5430         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5431         mixin(simpleParse!(StaticDestructor, tok!"static", tok!"~", tok!"this",
5432             tok!"(", tok!")", "functionBody|parseFunctionBody"));
5433     }
5434 
5435     /**
5436      * Parses an StaticIfCondition
5437      *
5438      * $(GRAMMAR $(RULEDEF staticIfCondition):
5439      *     $(LITERAL 'static') $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)')
5440      *     ;)
5441      */
5442     StaticIfCondition parseStaticIfCondition()
5443     {
5444         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5445         mixin(simpleParse!(StaticIfCondition, tok!"static", tok!"if", tok!"(",
5446             "assignExpression|parseAssignExpression", tok!")"));
5447     }
5448 
5449     /**
5450      * Parses a StorageClass
5451      *
5452      * $(GRAMMAR $(RULEDEF storageClass):
5453      *       $(RULE alignAttribute)
5454      *     | $(RULE linkageAttribute)
5455      *     | $(RULE atAttribute)
5456      *     | $(RULE typeConstructor)
5457      *     | $(RULE deprecated)
5458      *     | $(LITERAL 'abstract')
5459      *     | $(LITERAL 'auto')
5460      *     | $(LITERAL 'enum')
5461      *     | $(LITERAL 'extern')
5462      *     | $(LITERAL 'final')
5463      *     | $(LITERAL 'nothrow')
5464      *     | $(LITERAL 'override')
5465      *     | $(LITERAL 'pure')
5466      *     | $(LITERAL 'ref')
5467      *     | $(LITERAL '___gshared')
5468      *     | $(LITERAL 'scope')
5469      *     | $(LITERAL 'static')
5470      *     | $(LITERAL 'synchronized')
5471      *     ;)
5472      */
5473     StorageClass parseStorageClass()
5474     {
5475         auto node = allocate!StorageClass;
5476         switch (current.type)
5477         {
5478         case tok!"@":
5479             mixin(nullCheck!`node.atAttribute = parseAtAttribute()`);
5480             if (node.atAttribute is null) { deallocate(node); return null; }
5481             break;
5482         case tok!"deprecated":
5483             mixin(nullCheck!`node.deprecated_ = parseDeprecated()`);
5484             break;
5485         case tok!"align":
5486             mixin(nullCheck!`node.alignAttribute = parseAlignAttribute()`);
5487             break;
5488         case tok!"extern":
5489             if (peekIs(tok!"("))
5490             {
5491                 mixin(nullCheck!`node.linkageAttribute = parseLinkageAttribute()`);
5492                 break;
5493             }
5494             else goto case;
5495         case tok!"const":
5496         case tok!"immutable":
5497         case tok!"inout":
5498         case tok!"shared":
5499         case tok!"abstract":
5500         case tok!"auto":
5501         case tok!"enum":
5502         case tok!"final":
5503         case tok!"nothrow":
5504         case tok!"override":
5505         case tok!"pure":
5506         case tok!"ref":
5507         case tok!"__gshared":
5508         case tok!"scope":
5509         case tok!"static":
5510         case tok!"synchronized":
5511             node.token = advance();
5512             break;
5513         default:
5514             error(`Storage class expected`);
5515             return null;
5516         }
5517         return node;
5518     }
5519 
5520     /**
5521      * Parses a StructBody
5522      *
5523      * $(GRAMMAR $(RULEDEF structBody):
5524      *     $(LITERAL '{') $(RULE declaration)* $(LITERAL '}')
5525      *     ;)
5526      */
5527     StructBody parseStructBody()
5528     {
5529         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5530         auto node = allocate!StructBody;
5531         const start = expect(tok!"{");
5532         if (start !is null) node.startLocation = start.index;
5533         Declaration[] declarations;
5534         while (!currentIs(tok!"}") && moreTokens())
5535         {
5536             auto dec = parseDeclaration();
5537             if (dec !is null)
5538                 declarations ~= dec;
5539         }
5540         node.declarations = ownArray(declarations);
5541         const end = expect(tok!"}");
5542         if (end !is null) node.endLocation = end.index;
5543         return node;
5544     }
5545 
5546     /**
5547      * Parses a StructDeclaration
5548      *
5549      * $(GRAMMAR $(RULEDEF structDeclaration):
5550      *     $(LITERAL 'struct') $(LITERAL Identifier)? ($(RULE templateParameters) $(RULE constraint)? $(RULE structBody) | ($(RULE structBody) | $(LITERAL ';')))
5551      *     ;)
5552      */
5553     StructDeclaration parseStructDeclaration()
5554     {
5555         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5556         auto node = allocate!StructDeclaration;
5557         const t = expect(tok!"struct");
5558         if (currentIs(tok!"identifier"))
5559             node.name = advance();
5560         else
5561         {
5562             node.name.line = t.line;
5563             node.name.column = t.column;
5564         }
5565         node.comment = comment;
5566         comment = null;
5567 
5568         if (currentIs(tok!"("))
5569         {
5570             mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
5571             if (currentIs(tok!"if"))
5572                 mixin(nullCheck!`node.constraint = parseConstraint()`);
5573             mixin(nullCheck!`node.structBody = parseStructBody()`);
5574         }
5575         else if (currentIs(tok!"{"))
5576         {
5577             mixin(nullCheck!`node.structBody = parseStructBody()`);
5578         }
5579         else if (currentIs(tok!";"))
5580             advance();
5581         else
5582         {
5583             error("Template Parameters, Struct Body, or Semicolon expected");
5584             return null;
5585         }
5586         return node;
5587     }
5588 
5589     /**
5590      * Parses an StructInitializer
5591      *
5592      * $(GRAMMAR $(RULEDEF structInitializer):
5593      *     $(LITERAL '{') $(RULE structMemberInitializers)? $(LITERAL '}')
5594      *     ;)
5595      */
5596     StructInitializer parseStructInitializer()
5597     {
5598         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5599         auto node = allocate!StructInitializer;
5600         const a = expect(tok!"{");
5601         node.startLocation = a.index;
5602         if (currentIs(tok!"}"))
5603         {
5604             node.endLocation = current.index;
5605             advance();
5606         }
5607         else
5608         {
5609             mixin(nullCheck!`node.structMemberInitializers = parseStructMemberInitializers()`);
5610             const e = expect(tok!"}");
5611             mixin(nullCheck!`e`);
5612             node.endLocation = e.index;
5613         }
5614         return node;
5615     }
5616 
5617     /**
5618      * Parses a StructMemberInitializer
5619      *
5620      * $(GRAMMAR $(RULEDEF structMemberInitializer):
5621      *     ($(LITERAL Identifier) $(LITERAL ':'))? $(RULE nonVoidInitializer)
5622      *     ;)
5623      */
5624     StructMemberInitializer parseStructMemberInitializer()
5625     {
5626         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5627         auto node = allocate!StructMemberInitializer;
5628         if (startsWith(tok!"identifier", tok!":"))
5629         {
5630             node.identifier = tokens[index++];
5631             index++;
5632         }
5633         mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`);
5634         return node;
5635     }
5636 
5637     /**
5638      * Parses StructMemberInitializers
5639      *
5640      * $(GRAMMAR $(RULEDEF structMemberInitializers):
5641      *     $(RULE structMemberInitializer) ($(LITERAL ',') $(RULE structMemberInitializer)?)*
5642      *     ;)
5643      */
5644     StructMemberInitializers parseStructMemberInitializers()
5645     {
5646         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5647         auto node = allocate!StructMemberInitializers;
5648         StructMemberInitializer[] structMemberInitializers;
5649         do
5650         {
5651             auto structMemberInitializer = parseStructMemberInitializer();
5652             if (structMemberInitializer is null)
5653             {
5654                 deallocate(node);
5655                 return null;
5656             }
5657             else
5658                 structMemberInitializers ~= structMemberInitializer;
5659 
5660             if (currentIs(tok!","))
5661             {
5662                 advance();
5663                 if (!currentIs(tok!"}"))
5664                     continue;
5665                 else
5666                     break;
5667             }
5668             else
5669                 break;
5670         } while (moreTokens());
5671         node.structMemberInitializers = ownArray(structMemberInitializers);
5672         return node;
5673     }
5674 
5675     /**
5676      * Parses a SwitchStatement
5677      *
5678      * $(GRAMMAR $(RULEDEF switchStatement):
5679      *     $(LITERAL 'switch') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statement)
5680      *     ;)
5681      */
5682     SwitchStatement parseSwitchStatement()
5683     {
5684         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5685         auto node = allocate!SwitchStatement;
5686         expect(tok!"switch");
5687         expect(tok!"(");
5688         mixin(nullCheck!`node.expression = parseExpression()`);
5689         expect(tok!")");
5690         mixin(nullCheck!`node.statement = parseStatement()`);
5691         return node;
5692     }
5693 
5694     /**
5695      * Parses a Symbol
5696      *
5697      * $(GRAMMAR $(RULEDEF symbol):
5698      *     $(LITERAL '.')? $(RULE identifierOrTemplateChain)
5699      *     ;)
5700      */
5701     Symbol parseSymbol()
5702     {
5703         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5704         auto node = allocate!Symbol;
5705         if (currentIs(tok!"."))
5706         {
5707             node.dot = true;
5708             advance();
5709         }
5710         mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`);
5711         return node;
5712     }
5713 
5714     /**
5715      * Parses a SynchronizedStatement
5716      *
5717      * $(GRAMMAR $(RULEDEF synchronizedStatement):
5718      *     $(LITERAL 'synchronized') ($(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)'))? $(RULE statementNoCaseNoDefault)
5719      *     ;)
5720      */
5721     SynchronizedStatement parseSynchronizedStatement()
5722     {
5723         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5724         auto node = allocate!SynchronizedStatement;
5725         expect(tok!"synchronized");
5726         if (currentIs(tok!"("))
5727         {
5728             expect(tok!"(");
5729             mixin(nullCheck!`node.expression = parseExpression()`);
5730             expect(tok!")");
5731         }
5732         mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`);
5733         return node;
5734     }
5735 
5736     /**
5737      * Parses a TemplateAliasParameter
5738      *
5739      * $(GRAMMAR $(RULEDEF templateAliasParameter):
5740      *     $(LITERAL 'alias') $(RULE type)? $(LITERAL Identifier) ($(LITERAL ':') ($(RULE type) | $(RULE assignExpression)))? ($(LITERAL '=') ($(RULE type) | $(RULE assignExpression)))?
5741      *     ;)
5742      */
5743     TemplateAliasParameter parseTemplateAliasParameter()
5744     {
5745         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5746         auto node = allocate!TemplateAliasParameter;
5747         expect(tok!"alias");
5748         if (currentIs(tok!"identifier") && !peekIs(tok!"."))
5749         {
5750             if (peekIsOneOf(tok!",", tok!")", tok!"=", tok!":"))
5751                 node.identifier = advance();
5752             else
5753                 goto type;
5754         }
5755         else
5756         {
5757     type:
5758             if ((node.type = parseType()) is null) { deallocate(node); return null; }
5759             const ident = expect(tok!"identifier");
5760             if (ident is null) { deallocate(node); return null; }
5761             node.identifier = *ident;
5762         }
5763 
5764         if (currentIs(tok!":"))
5765         {
5766             advance();
5767             if (isType())
5768                 mixin(nullCheck!`node.colonType = parseType()`);
5769             else
5770                 mixin(nullCheck!`node.colonExpression = parseAssignExpression()`);
5771         }
5772         if (currentIs(tok!"="))
5773         {
5774             advance();
5775             if (isType())
5776                 mixin(nullCheck!`node.assignType = parseType()`);
5777             else
5778                 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
5779         }
5780         return node;
5781     }
5782 
5783     /**
5784      * Parses a TemplateArgument
5785      *
5786      * $(GRAMMAR $(RULEDEF templateArgument):
5787      *       $(RULE type)
5788      *     | $(RULE assignExpression)
5789      *     ;)
5790      */
5791     TemplateArgument parseTemplateArgument()
5792     {
5793         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5794         if (suppressedErrorCount > MAX_ERRORS) return null;
5795         auto node = allocate!TemplateArgument;
5796         auto b = setBookmark();
5797         auto t = parseType();
5798         if (t !is null && currentIsOneOf(tok!",", tok!")"))
5799         {
5800             abandonBookmark(b);
5801             node.type = t;
5802         }
5803         else
5804         {
5805             goToBookmark(b);
5806             if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; }
5807         }
5808         return node;
5809     }
5810 
5811     /**
5812      * Parses a TemplateArgumentList
5813      *
5814      * $(GRAMMAR $(RULEDEF templateArgumentList):
5815      *     $(RULE templateArgument) ($(LITERAL ',') $(RULE templateArgument)?)*
5816      *     ;)
5817      */
5818     TemplateArgumentList parseTemplateArgumentList()
5819     {
5820         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5821         return parseCommaSeparatedRule!(TemplateArgumentList, TemplateArgument)(true);
5822     }
5823 
5824     /**
5825      * Parses TemplateArguments
5826      *
5827      * $(GRAMMAR $(RULEDEF templateArguments):
5828      *     $(LITERAL '!') ($(LITERAL '$(LPAREN)') $(RULE templateArgumentList)? $(LITERAL '$(RPAREN)')) | $(RULE templateSingleArgument)
5829      *     ;)
5830      */
5831     TemplateArguments parseTemplateArguments()
5832     {
5833         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5834         if (suppressedErrorCount > MAX_ERRORS) return null;
5835         auto node = allocate!TemplateArguments;
5836         expect(tok!"!");
5837         if (currentIs(tok!"("))
5838         {
5839             advance();
5840             if (!currentIs(tok!")"))
5841                 mixin(nullCheck!`node.templateArgumentList = parseTemplateArgumentList()`);
5842             if (expect(tok!")") is null) { deallocate(node); return null; }
5843         }
5844         else
5845             mixin(nullCheck!`node.templateSingleArgument = parseTemplateSingleArgument()`);
5846         return node;
5847     }
5848 
5849     /**
5850      * Parses a TemplateDeclaration
5851      *
5852      * $(GRAMMAR $(RULEDEF templateDeclaration):
5853      *       $(LITERAL 'template') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? $(LITERAL '{') $(RULE declaration)* $(LITERAL '}')
5854      *     ;)
5855      */
5856     TemplateDeclaration parseTemplateDeclaration()
5857     {
5858         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5859         auto node = allocate!TemplateDeclaration;
5860         node.comment = comment;
5861         comment = null;
5862         expect(tok!"template");
5863         const ident = expect(tok!"identifier");
5864         if (ident is null) { deallocate(node); return null; }
5865         node.name = *ident;
5866         mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
5867         if (currentIs(tok!"if"))
5868             mixin(nullCheck!`node.constraint = parseConstraint()`);
5869         const start = expect(tok!"{");
5870         if (start is null) { deallocate(node); return null; } else node.startLocation = start.index;
5871         Declaration[] declarations;
5872         while (moreTokens() && !currentIs(tok!"}"))
5873         {
5874             auto decl = parseDeclaration();
5875             if (decl !is null)
5876                 declarations ~= decl;
5877         }
5878         node.declarations = ownArray(declarations);
5879         const end = expect(tok!"}");
5880         if (end !is null) node.endLocation = end.index;
5881         return node;
5882     }
5883 
5884     /**
5885      * Parses a TemplateInstance
5886      *
5887      * $(GRAMMAR $(RULEDEF templateInstance):
5888      *     $(LITERAL Identifier) $(RULE templateArguments)
5889      *     ;)
5890      */
5891     TemplateInstance parseTemplateInstance()
5892     {
5893         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5894         if (suppressedErrorCount > MAX_ERRORS) return null;
5895         auto node = allocate!TemplateInstance;
5896         const ident = expect(tok!"identifier");
5897         if (ident is null) { deallocate(node); return null; }
5898         node.identifier = *ident;
5899         mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`);
5900         if (node.templateArguments is null)
5901             return null;
5902         return node;
5903     }
5904 
5905     /**
5906      * Parses a TemplateMixinExpression
5907      *
5908      * $(GRAMMAR $(RULEDEF templateMixinExpression):
5909      *     $(LITERAL 'mixin') $(RULE mixinTemplateName) $(RULE templateArguments)? $(LITERAL Identifier)?
5910      *     ;)
5911      */
5912     TemplateMixinExpression parseTemplateMixinExpression()
5913     {
5914         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5915         auto node = allocate!TemplateMixinExpression;
5916         node.comment = comment;
5917 	node.line = current.line;
5918         comment = null;
5919         if (expect(tok!"mixin") is null) { deallocate(node); return null; }
5920         mixin(nullCheck!`node.mixinTemplateName = parseMixinTemplateName()`);
5921         if (currentIs(tok!"!"))
5922             mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`);
5923         if (currentIs(tok!"identifier"))
5924             node.identifier = advance();
5925         return node;
5926     }
5927 
5928     /**
5929      * Parses a TemplateParameter
5930      *
5931      * $(GRAMMAR $(RULEDEF templateParameter):
5932      *       $(RULE templateTypeParameter)
5933      *     | $(RULE templateValueParameter)
5934      *     | $(RULE templateAliasParameter)
5935      *     | $(RULE templateTupleParameter)
5936      *     | $(RULE templateThisParameter)
5937      *     ;)
5938      */
5939     TemplateParameter parseTemplateParameter()
5940     {
5941         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5942         auto node = allocate!TemplateParameter;
5943 
5944         node.comment = current.comment;
5945 
5946         switch (current.type)
5947         {
5948         case tok!"alias":
5949             mixin(nullCheck!`node.templateAliasParameter = parseTemplateAliasParameter()`);
5950             break;
5951         case tok!"identifier":
5952             if (peekIs(tok!"..."))
5953                 mixin(nullCheck!`node.templateTupleParameter = parseTemplateTupleParameter()`);
5954             else if (peekIsOneOf(tok!":", tok!"=", tok!",", tok!")"))
5955                 mixin(nullCheck!`node.templateTypeParameter = parseTemplateTypeParameter()`);
5956             else
5957                 mixin(nullCheck!`node.templateValueParameter = parseTemplateValueParameter()`);
5958             break;
5959         case tok!"this":
5960             mixin(nullCheck!`node.templateThisParameter = parseTemplateThisParameter()`);
5961             break;
5962         default:
5963             mixin(nullCheck!`node.templateValueParameter = parseTemplateValueParameter()`);
5964             break;
5965         }
5966         return node;
5967     }
5968 
5969     /**
5970      * Parses an TemplateParameterList
5971      *
5972      * $(GRAMMAR $(RULEDEF templateParameterList):
5973      *     $(RULE templateParameter) ($(LITERAL ',') $(RULE templateParameter)?)*
5974      *     ;)
5975      */
5976     TemplateParameterList parseTemplateParameterList()
5977     {
5978         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5979         return parseCommaSeparatedRule!(TemplateParameterList, TemplateParameter)(true);
5980     }
5981 
5982     /**
5983      * Parses TemplateParameters
5984      *
5985      * $(GRAMMAR $(RULEDEF templateParameters):
5986      *     $(LITERAL '$(LPAREN)') $(RULE templateParameterList)? $(LITERAL '$(RPAREN)')
5987      *     ;)
5988      */
5989     TemplateParameters parseTemplateParameters()
5990     {
5991         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
5992         auto node = allocate!TemplateParameters;
5993         if (expect(tok!"(") is null) { deallocate(node); return null; }
5994         if (!currentIs(tok!")"))
5995             if ((node.templateParameterList = parseTemplateParameterList()) is null) { deallocate(node); return null; }
5996         if (expect(tok!")") is null) { deallocate(node); return null; }
5997         return node;
5998     }
5999 
6000     /**
6001      * Parses a TemplateSingleArgument
6002      *
6003      * $(GRAMMAR $(RULEDEF templateSingleArgument):
6004      *       $(RULE builtinType)
6005      *     | $(LITERAL Identifier)
6006      *     | $(LITERAL CharacterLiteral)
6007      *     | $(LITERAL StringLiteral)
6008      *     | $(LITERAL IntegerLiteral)
6009      *     | $(LITERAL FloatLiteral)
6010      *     | $(LITERAL '_true')
6011      *     | $(LITERAL '_false')
6012      *     | $(LITERAL '_null')
6013      *     | $(LITERAL 'this')
6014      *     | $(LITERAL '___DATE__')
6015      *     | $(LITERAL '___TIME__')
6016      *     | $(LITERAL '___TIMESTAMP__')
6017      *     | $(LITERAL '___VENDOR__')
6018      *     | $(LITERAL '___VERSION__')
6019      *     | $(LITERAL '___FILE__')
6020      *     | $(LITERAL '___LINE__')
6021      *     | $(LITERAL '___MODULE__')
6022      *     | $(LITERAL '___FUNCTION__')
6023      *     | $(LITERAL '___PRETTY_FUNCTION__')
6024      *     ;)
6025      */
6026     TemplateSingleArgument parseTemplateSingleArgument()
6027     {
6028         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6029         auto node = allocate!TemplateSingleArgument;
6030         if (!moreTokens)
6031         {
6032             error("template argument expected instead of EOF");
6033             return null;
6034         }
6035         switch (current.type)
6036         {
6037         case tok!"true":
6038         case tok!"false":
6039         case tok!"null":
6040         case tok!"this":
6041         case tok!"identifier":
6042         mixin(SPECIAL_CASES);
6043         mixin(LITERAL_CASES);
6044         mixin(BUILTIN_TYPE_CASES);
6045             node.token = advance();
6046             break;
6047         default:
6048             error(`Invalid template argument. (Try enclosing in parenthesis?)`);
6049             return null;
6050         }
6051         return node;
6052     }
6053 
6054     /**
6055      * Parses a TemplateThisParameter
6056      *
6057      * $(GRAMMAR $(RULEDEF templateThisParameter):
6058      *     $(LITERAL 'this') $(RULE templateTypeParameter)
6059      *     ;)
6060      */
6061     TemplateThisParameter parseTemplateThisParameter()
6062     {
6063         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6064         auto node = allocate!TemplateThisParameter;
6065         expect(tok!"this");
6066         mixin(nullCheck!`node.templateTypeParameter = parseTemplateTypeParameter()`);
6067         return node;
6068     }
6069 
6070     /**
6071      * Parses an TemplateTupleParameter
6072      *
6073      * $(GRAMMAR $(RULEDEF templateTupleParameter):
6074      *     $(LITERAL Identifier) $(LITERAL '...')
6075      *     ;)
6076      */
6077     TemplateTupleParameter parseTemplateTupleParameter()
6078     {
6079         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6080         auto node = allocate!TemplateTupleParameter;
6081         const i = expect(tok!"identifier");
6082         if (i is null)
6083             return null;
6084         node.identifier = *i;
6085         if (expect(tok!"...") is null) { deallocate(node); return null; }
6086         return node;
6087     }
6088 
6089     /**
6090      * Parses a TemplateTypeParameter
6091      *
6092      * $(GRAMMAR $(RULEDEF templateTypeParameter):
6093      *     $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? ($(LITERAL '=') $(RULE type))?
6094      *     ;)
6095      */
6096     TemplateTypeParameter parseTemplateTypeParameter()
6097     {
6098         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6099         auto node = allocate!TemplateTypeParameter;
6100         const ident = expect(tok!"identifier");
6101         if (ident is null) { deallocate(node); return null; }
6102         node.identifier = *ident;
6103         if (currentIs(tok!":"))
6104         {
6105             advance();
6106             mixin(nullCheck!`node.colonType = parseType()`);
6107         }
6108         if (currentIs(tok!"="))
6109         {
6110             advance();
6111             mixin(nullCheck!`node.assignType = parseType()`);
6112         }
6113         return node;
6114     }
6115 
6116     /**
6117      * Parses a TemplateValueParameter
6118      *
6119      * $(GRAMMAR $(RULEDEF templateValueParameter):
6120      *     $(RULE type) $(LITERAL Identifier) ($(LITERAL ':') $(RULE assignExpression))? $(RULE templateValueParameterDefault)?
6121      *     ;)
6122      */
6123     TemplateValueParameter parseTemplateValueParameter()
6124     {
6125         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6126         auto node = allocate!TemplateValueParameter;
6127         if ((node.type = parseType()) is null) { deallocate(node); return null; }
6128         const ident = expect(tok!"identifier");
6129         if (ident is null) { deallocate(node); return null; }
6130         node.identifier = *ident;
6131         if (currentIs(tok!":"))
6132         {
6133             advance();
6134             if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; }
6135         }
6136         if (currentIs(tok!"="))
6137         {
6138             if ((node.templateValueParameterDefault = parseTemplateValueParameterDefault()) is null)
6139                 return null;
6140         }
6141         return node;
6142     }
6143 
6144     /**
6145      * Parses a TemplateValueParameterDefault
6146      *
6147      * $(GRAMMAR $(RULEDEF templateValueParameterDefault):
6148      *     $(LITERAL '=') ($(LITERAL '___FILE__') | $(LITERAL '___MODULE__') | $(LITERAL '___LINE__') | $(LITERAL '___FUNCTION__') | $(LITERAL '___PRETTY_FUNCTION__') | $(RULE assignExpression))
6149      *     ;)
6150      */
6151     TemplateValueParameterDefault parseTemplateValueParameterDefault()
6152     {
6153         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6154         auto node = allocate!TemplateValueParameterDefault;
6155         expect(tok!"=");
6156         switch (current.type)
6157         {
6158         case tok!"__FILE__":
6159         case tok!"__MODULE__":
6160         case tok!"__LINE__":
6161         case tok!"__FUNCTION__":
6162         case tok!"__PRETTY_FUNCTION__":
6163             node.token = advance();
6164             break;
6165         default:
6166             mixin(nullCheck!`node.assignExpression = parseAssignExpression()`);
6167             break;
6168         }
6169         return node;
6170     }
6171 
6172     /**
6173      * Parses a TernaryExpression
6174      *
6175      * $(GRAMMAR $(RULEDEF ternaryExpression):
6176      *     $(RULE orOrExpression) ($(LITERAL '?') $(RULE expression) $(LITERAL ':') $(RULE ternaryExpression))?
6177      *     ;)
6178      */
6179     ExpressionNode parseTernaryExpression()
6180     {
6181         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6182 
6183         auto orOrExpression = parseOrOrExpression();
6184         if (orOrExpression is null)
6185             return null;
6186         if (currentIs(tok!"?"))
6187         {
6188             TernaryExpression node = allocate!TernaryExpression;
6189             node.orOrExpression = orOrExpression;
6190             advance();
6191             mixin(nullCheck!`node.expression = parseExpression()`);
6192             auto colon = expect(tok!":");
6193             if (colon is null) { deallocate(node); return null; }
6194             node.colon = *colon;
6195             mixin(nullCheck!`node.ternaryExpression = parseTernaryExpression()`);
6196             return node;
6197         }
6198         return orOrExpression;
6199     }
6200 
6201     /**
6202      * Parses a ThrowStatement
6203      *
6204      * $(GRAMMAR $(RULEDEF throwStatement):
6205      *     $(LITERAL 'throw') $(RULE expression) $(LITERAL ';')
6206      *     ;)
6207      */
6208     ThrowStatement parseThrowStatement()
6209     {
6210         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6211         auto node = allocate!ThrowStatement;
6212         expect(tok!"throw");
6213         mixin(nullCheck!`node.expression = parseExpression()`);
6214         expect(tok!";");
6215         return node;
6216     }
6217 
6218     /**
6219      * Parses an TraitsExpression
6220      *
6221      * $(GRAMMAR $(RULEDEF traitsExpression):
6222      *     $(LITERAL '___traits') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL ',') $(RULE TemplateArgumentList) $(LITERAL '$(RPAREN)')
6223      *     ;)
6224      */
6225     TraitsExpression parseTraitsExpression()
6226     {
6227         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6228         auto node = allocate!TraitsExpression;
6229         if (expect(tok!"__traits") is null) { deallocate(node); return null; }
6230         if (expect(tok!"(") is null) { deallocate(node); return null; }
6231         const ident = expect(tok!"identifier");
6232         if (ident is null) { deallocate(node); return null; }
6233         node.identifier = *ident;
6234         if (currentIs(tok!","))
6235         {
6236             advance();
6237             mixin(nullCheck!`(node.templateArgumentList = parseTemplateArgumentList())`);
6238         }
6239         mixin(nullCheck!`expect(tok!")")`);
6240         return node;
6241     }
6242 
6243     /**
6244      * Parses a TryStatement
6245      *
6246      * $(GRAMMAR $(RULEDEF tryStatement):
6247      *     $(LITERAL 'try') $(RULE declarationOrStatement) ($(RULE catches) | $(RULE catches) $(RULE finally) | $(RULE finally))
6248      *     ;)
6249      */
6250     TryStatement parseTryStatement()
6251     {
6252         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6253         auto node = allocate!TryStatement;
6254         expect(tok!"try");
6255         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
6256         if (currentIs(tok!"catch"))
6257             mixin(nullCheck!`node.catches = parseCatches()`);
6258         if (currentIs(tok!"finally"))
6259             mixin(nullCheck!`node.finally_ = parseFinally()`);
6260         return node;
6261     }
6262 
6263     /**
6264      * Parses a Type
6265      *
6266      * $(GRAMMAR $(RULEDEF type):
6267      *     $(RULE typeConstructors)? $(RULE type2) $(RULE typeSuffix)*
6268      *     ;)
6269      */
6270     Type parseType()
6271     {
6272         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6273         auto node = allocate!Type;
6274         if (!moreTokens)
6275         {
6276             error("type expected");
6277             return null;
6278         }
6279         switch (current.type)
6280         {
6281 	case tok!"__traits":
6282 		advance();
6283 		skipParens();
6284 		break;
6285         case tok!"const":
6286         case tok!"immutable":
6287         case tok!"inout":
6288         case tok!"shared":
6289             if (!peekIs(tok!"("))
6290                 mixin(nullCheck!`node.typeConstructors = parseTypeConstructors()`);
6291             break;
6292         default:
6293             break;
6294         }
6295         mixin(nullCheck!`node.type2 = parseType2()`);
6296         if (node.type2 is null)
6297             return null;
6298         TypeSuffix[] typeSuffixes;
6299         loop: while (moreTokens()) switch (current.type)
6300         {
6301         case tok!"[":
6302             // Allow this to fail because of the madness that is the
6303             // newExpression rule. Something starting with '[' may be arguments
6304             // to the newExpression instead of part of the type
6305             auto newBookmark = setBookmark();
6306             auto suffix = parseTypeSuffix();
6307             if (suffix !is null)
6308             {
6309                 abandonBookmark(newBookmark);
6310                 typeSuffixes ~= suffix;
6311             }
6312             else
6313             {
6314                 goToBookmark(newBookmark);
6315                 break loop;
6316             }
6317             break;
6318         case tok!"*":
6319         case tok!"delegate":
6320         case tok!"function":
6321             auto suffix = parseTypeSuffix();
6322             if (suffix !is null)
6323                 typeSuffixes ~= suffix;
6324             else
6325                 return null;
6326             break;
6327         default:
6328             break loop;
6329         }
6330         node.typeSuffixes = ownArray(typeSuffixes);
6331         return node;
6332     }
6333 
6334     /**
6335      * Parses a Type2
6336      *
6337      * $(GRAMMAR $(RULEDEF type2):
6338      *       $(RULE builtinType)
6339      *     | $(RULE symbol)
6340      *     | $(RULE typeofExpression) ($(LITERAL '.') $(RULE identifierOrTemplateChain))?
6341      *     | $(RULE typeConstructor) $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)')
6342      *     | $(RULE vector)
6343      *     ;)
6344      */
6345     Type2 parseType2()
6346     {
6347         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6348         auto node = allocate!Type2;
6349         if (!moreTokens)
6350         {
6351             error("type2 expected instead of EOF");
6352             return null;
6353         }
6354         switch (current.type)
6355         {
6356         case tok!"identifier":
6357         case tok!".":
6358             if ((node.symbol = parseSymbol()) is null)
6359                 return null;
6360             break;
6361         mixin(BUILTIN_TYPE_CASES);
6362             if ((node.builtinType = parseBuiltinType()) == tok!"")
6363                 return null;
6364             break;
6365         case tok!"typeof":
6366             if ((node.typeofExpression = parseTypeofExpression()) is null)
6367                 return null;
6368             if (currentIs(tok!"."))
6369             {
6370                 advance();
6371                 mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`);
6372                 if (node.identifierOrTemplateChain is null)
6373                     return null;
6374             }
6375             break;
6376         case tok!"const":
6377         case tok!"immutable":
6378         case tok!"inout":
6379         case tok!"shared":
6380             node.typeConstructor = advance().type;
6381             mixin(nullCheck!`expect(tok!"(")`);
6382             mixin(nullCheck!`(node.type = parseType())`);
6383             mixin(nullCheck!`expect(tok!")")`);
6384             break;
6385         case tok!"__vector":
6386             if ((node.vector = parseVector()) is null)
6387                 return null;
6388             break;
6389         default:
6390             error("Basic type, type constructor, symbol, or typeof expected");
6391             return null;
6392         }
6393         return node;
6394     }
6395 
6396     /**
6397      * Parses a TypeConstructor
6398      *
6399      * $(GRAMMAR $(RULEDEF typeConstructor):
6400      *       $(LITERAL 'const')
6401      *     | $(LITERAL 'immutable')
6402      *     | $(LITERAL 'inout')
6403      *     | $(LITERAL 'shared')
6404      *     ;)
6405      */
6406     IdType parseTypeConstructor(bool validate = true)
6407     {
6408         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6409         switch (current.type)
6410         {
6411         case tok!"const":
6412         case tok!"immutable":
6413         case tok!"inout":
6414         case tok!"shared":
6415             if (!peekIs(tok!"("))
6416                 return advance().type;
6417             goto default;
6418         default:
6419             if (validate)
6420                 error(`"const", "immutable", "inout", or "shared" expected`);
6421             return tok!"";
6422         }
6423     }
6424 
6425     /**
6426      * Parses TypeConstructors
6427      *
6428      * $(GRAMMAR $(RULEDEF typeConstructors):
6429      *     $(RULE typeConstructor)+
6430      *     ;)
6431      */
6432     IdType[] parseTypeConstructors()
6433     {
6434         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6435         IdType[] r;
6436         while (moreTokens())
6437         {
6438             IdType type = parseTypeConstructor(false);
6439             if (type == tok!"")
6440                 break;
6441             else
6442                 r ~= type;
6443         }
6444         return r;
6445     }
6446 
6447     /**
6448      * Parses a TypeSpecialization
6449      *
6450      * $(GRAMMAR $(RULEDEF typeSpecialization):
6451      *       $(RULE type)
6452      *     | $(LITERAL 'struct')
6453      *     | $(LITERAL 'union')
6454      *     | $(LITERAL 'class')
6455      *     | $(LITERAL 'interface')
6456      *     | $(LITERAL 'enum')
6457      *     | $(LITERAL 'function')
6458      *     | $(LITERAL 'delegate')
6459      *     | $(LITERAL 'super')
6460      *     | $(LITERAL 'const')
6461      *     | $(LITERAL 'immutable')
6462      *     | $(LITERAL 'inout')
6463      *     | $(LITERAL 'shared')
6464      *     | $(LITERAL 'return')
6465      *     | $(LITERAL 'typedef')
6466      *     | $(LITERAL '___parameters')
6467      *     ;)
6468      */
6469     TypeSpecialization parseTypeSpecialization()
6470     {
6471         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6472         auto node = allocate!TypeSpecialization;
6473         switch (current.type)
6474         {
6475         case tok!"struct":
6476         case tok!"union":
6477         case tok!"class":
6478         case tok!"interface":
6479         case tok!"enum":
6480         case tok!"function":
6481         case tok!"delegate":
6482         case tok!"super":
6483         case tok!"return":
6484         case tok!"typedef":
6485         case tok!"__parameters":
6486         case tok!"__vector":
6487         case tok!"const":
6488         case tok!"immutable":
6489         case tok!"inout":
6490         case tok!"shared":
6491             if (peekIsOneOf(tok!")", tok!","))
6492             {
6493                 node.token = advance();
6494                 break;
6495             }
6496             goto default;
6497         default:
6498             mixin(nullCheck!`node.type = parseType()`);
6499             break;
6500         }
6501         return node;
6502     }
6503 
6504     /**
6505      * Parses a TypeSuffix
6506      *
6507      * $(GRAMMAR $(RULEDEF typeSuffix):
6508      *       $(LITERAL '*')
6509      *     | $(LITERAL '[') $(RULE type)? $(LITERAL ']')
6510      *     | $(LITERAL '[') $(RULE assignExpression) $(LITERAL ']')
6511      *     | $(LITERAL '[') $(RULE assignExpression) $(LITERAL '..')  $(RULE assignExpression) $(LITERAL ']')
6512      *     | ($(LITERAL 'delegate') | $(LITERAL 'function')) $(RULE parameters) $(RULE memberFunctionAttribute)*
6513      *     ;)
6514      */
6515     TypeSuffix parseTypeSuffix()
6516     {
6517         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6518         auto node = allocate!TypeSuffix;
6519         switch (current.type)
6520         {
6521         case tok!"*":
6522             node.star = advance();
6523             return node;
6524         case tok!"[":
6525             node.array = true;
6526             advance();
6527             if (currentIs(tok!"]"))
6528             {
6529                 advance();
6530                 return node;
6531             }
6532             auto bookmark = setBookmark();
6533             auto type = parseType();
6534             if (type !is null && currentIs(tok!"]"))
6535             {
6536                 abandonBookmark(bookmark);
6537                 node.type = type;
6538             }
6539             else
6540             {
6541                 goToBookmark(bookmark);
6542                 mixin(nullCheck!`node.low = parseAssignExpression()`);
6543                 mixin(nullCheck!`node.low`);
6544                 if (currentIs(tok!".."))
6545                 {
6546                     advance();
6547                     mixin(nullCheck!`node.high = parseAssignExpression()`);
6548                     mixin(nullCheck!`node.high`);
6549                 }
6550             }
6551             mixin(nullCheck!`expect(tok!"]")`);
6552             return node;
6553         case tok!"delegate":
6554         case tok!"function":
6555             node.delegateOrFunction = advance();
6556             mixin(nullCheck!`node.parameters = parseParameters()`);
6557             MemberFunctionAttribute[] memberFunctionAttributes;
6558             while (currentIsMemberFunctionAttribute())
6559                 memberFunctionAttributes ~= parseMemberFunctionAttribute();
6560             node.memberFunctionAttributes = ownArray(memberFunctionAttributes);
6561             return node;
6562         default:
6563             error(`"*", "[", "delegate", or "function" expected.`);
6564             return null;
6565         }
6566     }
6567 
6568     /**
6569      * Parses a TypeidExpression
6570      *
6571      * $(GRAMMAR $(RULEDEF typeidExpression):
6572      *     $(LITERAL 'typeid') $(LITERAL '$(LPAREN)') ($(RULE type) | $(RULE expression)) $(LITERAL '$(RPAREN)')
6573      *     ;)
6574      */
6575     TypeidExpression parseTypeidExpression()
6576     {
6577         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6578         auto node = allocate!TypeidExpression;
6579         expect(tok!"typeid");
6580         expect(tok!"(");
6581         auto b = setBookmark();
6582         auto t = parseType();
6583         if (t is null || !currentIs(tok!")"))
6584         {
6585             goToBookmark(b);
6586             mixin(nullCheck!`node.expression = parseExpression()`);
6587             mixin(nullCheck!`node.expression`);
6588         }
6589         else
6590         {
6591             abandonBookmark(b);
6592             node.type = t;
6593         }
6594         expect(tok!")");
6595         return node;
6596     }
6597 
6598     /**
6599      * Parses a TypeofExpression
6600      *
6601      * $(GRAMMAR $(RULEDEF typeofExpression):
6602      *     $(LITERAL 'typeof') $(LITERAL '$(LPAREN)') ($(RULE expression) | $(LITERAL 'return')) $(LITERAL '$(RPAREN)')
6603      *     ;)
6604      */
6605     TypeofExpression parseTypeofExpression()
6606     {
6607         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6608         auto node = allocate!TypeofExpression;
6609         expect(tok!"typeof");
6610         expect(tok!"(");
6611         if (currentIs(tok!"return"))
6612             node.return_ = advance();
6613         else
6614             mixin(nullCheck!`node.expression = parseExpression()`);
6615         expect(tok!")");
6616         return node;
6617     }
6618 
6619     /**
6620      * Parses a UnaryExpression
6621      *
6622      * $(GRAMMAR $(RULEDEF unaryExpression):
6623      *       $(RULE primaryExpression)
6624      *     | $(LITERAL '&') $(RULE unaryExpression)
6625      *     | $(LITERAL '!') $(RULE unaryExpression)
6626      *     | $(LITERAL '*') $(RULE unaryExpression)
6627      *     | $(LITERAL '+') $(RULE unaryExpression)
6628      *     | $(LITERAL '-') $(RULE unaryExpression)
6629      *     | $(LITERAL '~') $(RULE unaryExpression)
6630      *     | $(LITERAL '++') $(RULE unaryExpression)
6631      *     | $(LITERAL '--') $(RULE unaryExpression)
6632      *     | $(RULE newExpression)
6633      *     | $(RULE deleteExpression)
6634      *     | $(RULE castExpression)
6635      *     | $(RULE assertExpression)
6636      *     | $(RULE functionCallExpression)
6637      *     | $(RULE indexExpression)
6638      *     | $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)') $(LITERAL '.') $(RULE identifierOrTemplateInstance)
6639      *     | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance)
6640      *     | $(RULE unaryExpression) $(LITERAL '--')
6641      *     | $(RULE unaryExpression) $(LITERAL '++')
6642      *     ;)
6643      */
6644     UnaryExpression parseUnaryExpression()
6645     {
6646         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6647         if (!moreTokens())
6648             return null;
6649         auto node = allocate!UnaryExpression;
6650         switch (current.type)
6651         {
6652         case tok!"const":
6653         case tok!"immutable":
6654         case tok!"inout":
6655         case tok!"shared":
6656             auto b = setBookmark();
6657             if (peekIs(tok!"("))
6658             {
6659                 advance();
6660                 const past = peekPastParens();
6661                 if (past !is null && past.type == tok!".")
6662                 {
6663                     goToBookmark(b);
6664                     goto default;
6665                 }
6666             }
6667             goToBookmark(b);
6668             goto case;
6669         case tok!"scope":
6670         case tok!"pure":
6671         case tok!"nothrow":
6672             mixin(nullCheck!`node.functionCallExpression = parseFunctionCallExpression()`);
6673             break;
6674         case tok!"&":
6675         case tok!"!":
6676         case tok!"*":
6677         case tok!"+":
6678         case tok!"-":
6679         case tok!"~":
6680         case tok!"++":
6681         case tok!"--":
6682             node.prefix = advance();
6683             mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`);
6684             break;
6685         case tok!"new":
6686             mixin(nullCheck!`node.newExpression = parseNewExpression()`);
6687             break;
6688         case tok!"delete":
6689             mixin(nullCheck!`node.deleteExpression = parseDeleteExpression()`);
6690             break;
6691         case tok!"cast":
6692             mixin(nullCheck!`node.castExpression = parseCastExpression()`);
6693             break;
6694         case tok!"assert":
6695             mixin(nullCheck!`node.assertExpression = parseAssertExpression()`);
6696             break;
6697         case tok!"(":
6698             // handle (type).identifier
6699             auto b = setBookmark();
6700             skipParens();
6701             if (startsWith(tok!".", tok!"identifier"))
6702             {
6703                 // go back to the (
6704                 goToBookmark(b);
6705                 b = setBookmark();
6706                 advance();
6707                 auto t = parseType();
6708                 if (t is null || !currentIs(tok!")"))
6709                 {
6710                     goToBookmark(b);
6711                     goto default;
6712                 }
6713                 abandonBookmark(b);
6714                 node.type = t;
6715                 advance(); // )
6716                 advance(); // .
6717                 mixin(nullCheck!`node.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance()`);
6718                 break;
6719             }
6720             else
6721             {
6722                 // not (type).identifier, so treat as primary expression
6723                 goToBookmark(b);
6724                 goto default;
6725             }
6726         default:
6727             mixin(nullCheck!`node.primaryExpression = parsePrimaryExpression()`);
6728             break;
6729         }
6730 
6731         loop: while (moreTokens()) switch (current.type)
6732         {
6733         case tok!"!":
6734             if (peekIs(tok!"("))
6735             {
6736                 index++;
6737                 const p = peekPastParens();
6738                 immutable bool jump =  (currentIs(tok!"(") && p !is null && p.type == tok!"(")
6739                     || peekIs(tok!"(");
6740                 index--;
6741                 if (jump)
6742                     goto case tok!"(";
6743                 else
6744                     break loop;
6745             }
6746             else
6747                 break loop;
6748         case tok!"(":
6749             auto newUnary = allocate!UnaryExpression();
6750             mixin(nullCheck!`newUnary.functionCallExpression = parseFunctionCallExpression(node)`);
6751             node = newUnary;
6752             break;
6753         case tok!"++":
6754         case tok!"--":
6755             auto n = allocate!UnaryExpression();
6756             n.unaryExpression = node;
6757             n.suffix = advance();
6758             node = n;
6759             break;
6760         case tok!"[":
6761             auto n = allocate!UnaryExpression;
6762 			n.indexExpression = parseIndexExpression(node);
6763             node = n;
6764             break;
6765         case tok!".":
6766             advance();
6767             auto n = allocate!UnaryExpression();
6768             n.unaryExpression = node;
6769             n.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance();
6770             node = n;
6771             break;
6772         default:
6773             break loop;
6774         }
6775         return node;
6776     }
6777 
6778     /**
6779      * Parses an UnionDeclaration
6780      *
6781      * $(GRAMMAR $(RULEDEF unionDeclaration):
6782      *       $(LITERAL 'union') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? $(RULE structBody)
6783      *     | $(LITERAL 'union') $(LITERAL Identifier) ($(RULE structBody) | $(LITERAL ';'))
6784      *     | $(LITERAL 'union') $(RULE structBody)
6785      *     ;)
6786      */
6787     UnionDeclaration parseUnionDeclaration()
6788     {
6789         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6790         auto node = allocate!UnionDeclaration;
6791         // grab line number even if it's anonymous
6792         const t = expect(tok!"union");
6793 	node.comment = comment;
6794         if (currentIs(tok!"identifier"))
6795         {
6796             node.name = advance();
6797             if (currentIs(tok!"("))
6798             {
6799                 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
6800                 if (currentIs(tok!"if"))
6801                     mixin(nullCheck!`node.constraint = parseConstraint()`);
6802                 mixin(nullCheck!`node.structBody = parseStructBody()`);
6803             }
6804             else
6805                 goto semiOrStructBody;
6806         }
6807         else
6808         {
6809             node.name.line = t.line;
6810             node.name.column = t.column;
6811     semiOrStructBody:
6812             if (currentIs(tok!";"))
6813                 advance();
6814             else
6815                 mixin(nullCheck!`node.structBody = parseStructBody()`);
6816         }
6817         return node;
6818     }
6819 
6820     /**
6821      * Parses a Unittest
6822      *
6823      * $(GRAMMAR $(RULEDEF unittest):
6824      *     $(LITERAL 'unittest') $(RULE blockStatement)
6825      *     ;)
6826      */
6827     Unittest parseUnittest()
6828     {
6829         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6830         mixin(simpleParse!(Unittest, tok!"unittest", "blockStatement|parseBlockStatement"));
6831     }
6832 
6833     /**
6834      * Parses a VariableDeclaration
6835      *
6836      * $(GRAMMAR $(RULEDEF variableDeclaration):
6837      *       $(RULE storageClass)* $(RULE type) $(RULE declarator) ($(LITERAL ',') $(RULE declarator))* $(LITERAL ';')
6838      *     | $(RULE storageClass)* $(RULE type) $(LITERAL identifier) $(LITERAL '=') $(RULE functionBody) $(LITERAL ';')
6839      *     | $(RULE autoDeclaration)
6840      *     ;)
6841      */
6842     VariableDeclaration parseVariableDeclaration(Type type = null, bool isAuto = false,
6843         Attribute[] attributes = null, bool isEnum = false)
6844     {
6845         mixin(traceEnterAndExit!(__FUNCTION__));
6846         auto node = allocate!VariableDeclaration;
6847         node.attributes = attributes;
6848 	node.isEnum = isEnum;
6849         if (isAuto)
6850         {
6851             mixin(nullCheck!`node.autoDeclaration = parseAutoDeclaration()`);
6852             node.comment = node.autoDeclaration.comment;
6853             return node;
6854         }
6855 
6856         StorageClass[] storageClasses;
6857         while (isStorageClass())
6858         {
6859             auto s = parseStorageClass();
6860             if (s !is null)
6861                 storageClasses ~= s;
6862             else
6863             {
6864                 deallocate(node);
6865                 return null;
6866             }
6867         }
6868         node.storageClasses = ownArray(storageClasses);
6869 
6870         node.type = type is null ? parseType() : type;
6871         node.comment = comment;
6872         comment = null;
6873 
6874         // TODO: handle function bodies correctly
6875 
6876         Declarator[] declarators;
6877         while (true)
6878         {
6879             auto declarator = parseDeclarator();
6880             mixin(nullCheck!`declarator`);
6881             declarators ~= declarator;
6882             if (moreTokens() && currentIs(tok!","))
6883             {
6884                 declarator.comment = current.trailingComment;
6885                 advance();
6886             }
6887             else
6888                 break;
6889         }
6890         node.declarators = ownArray(declarators);
6891         const semicolon = expect(tok!";");
6892         mixin(nullCheck!`semicolon`);
6893         declarators[$ - 1].comment = semicolon.trailingComment;
6894         return node;
6895     }
6896 
6897     /**
6898      * Parses a Vector
6899      *
6900      * $(GRAMMAR $(RULEDEF vector):
6901      *     $(LITERAL '___vector') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)')
6902      *     ;)
6903      */
6904     Vector parseVector()
6905     {
6906         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6907         mixin(simpleParse!(Vector, tok!"__vector", tok!"(", "type|parseType", tok!")"));
6908     }
6909 
6910     /**
6911      * Parses a VersionCondition
6912      *
6913      * $(GRAMMAR $(RULEDEF versionCondition):
6914      *     $(LITERAL 'version') $(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier) | $(LITERAL 'unittest') | $(LITERAL 'assert')) $(LITERAL '$(RPAREN)')
6915      *     ;)
6916      */
6917     VersionCondition parseVersionCondition()
6918     {
6919         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6920         auto node = allocate!VersionCondition;
6921         const v = expect(tok!"version");
6922         mixin(nullCheck!`v`);
6923         node.versionIndex = v.index;
6924         mixin(nullCheck!`expect(tok!"(")`);
6925         if (currentIsOneOf(tok!"intLiteral", tok!"identifier",
6926             tok!"unittest", tok!"assert"))
6927         {
6928             node.token = advance();
6929         }
6930         else
6931         {
6932             error(`Expected an integer literal, an identifier, "assert", or "unittest"`);
6933             return null;
6934         }
6935         expect(tok!")");
6936         return node;
6937     }
6938 
6939     /**
6940      * Parses a VersionSpecification
6941      *
6942      * $(GRAMMAR $(RULEDEF versionSpecification):
6943      *     $(LITERAL 'version') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';')
6944      *     ;)
6945      */
6946     VersionSpecification parseVersionSpecification()
6947     {
6948         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6949         auto node = allocate!VersionSpecification;
6950         mixin(expectSequence!(tok!"version", tok!"="));
6951         if (!currentIsOneOf(tok!"identifier", tok!"intLiteral"))
6952         {
6953             error("Identifier or integer literal expected");
6954             return null;
6955         }
6956         node.token = advance();
6957         expect(tok!";");
6958         return node;
6959     }
6960 
6961     /**
6962      * Parses a WhileStatement
6963      *
6964      * $(GRAMMAR $(RULEDEF whileStatement):
6965      *     $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement)
6966      *     ;)
6967      */
6968     WhileStatement parseWhileStatement()
6969     {
6970         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6971         auto node = allocate!WhileStatement;
6972         expect(tok!"while");
6973         node.startIndex = current().index;
6974         expect(tok!"(");
6975         mixin(nullCheck!`node.expression = parseExpression()`);
6976         expect(tok!")");
6977         if (currentIs(tok!"}"))
6978         {
6979             error("Statement expected", false);
6980             return node; // this line makes DCD better
6981         }
6982         mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`);
6983         return node;
6984     }
6985 
6986     /**
6987      * Parses a WithStatement
6988      *
6989      * $(GRAMMAR $(RULEDEF withStatement):
6990      *     $(LITERAL 'with') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault)
6991      *     ;)
6992      */
6993     WithStatement parseWithStatement()
6994     {
6995         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
6996         mixin(simpleParse!(WithStatement, tok!"with", tok!"(",
6997             "expression|parseExpression", tok!")",
6998             "statementNoCaseNoDefault|parseStatementNoCaseNoDefault"));
6999     }
7000 
7001     /**
7002      * Parses an XorExpression
7003      *
7004      * $(GRAMMAR $(RULEDEF xorExpression):
7005      *       $(RULE andExpression)
7006      *     | $(RULE xorExpression) $(LITERAL '^') $(RULE andExpression)
7007      *     ;)
7008      */
7009     ExpressionNode parseXorExpression()
7010     {
7011         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7012         return parseLeftAssocBinaryExpression!(XorExpression, AndExpression,
7013             tok!"^")();
7014     }
7015 
7016     /**
7017      * Current error count
7018      */
7019     uint errorCount;
7020 
7021     /**
7022      * Current warning count
7023      */
7024     uint warningCount;
7025 
7026     /**
7027      * Name used when reporting warnings and errors
7028      */
7029     string fileName;
7030 
7031     /**
7032      * Allocator used for creating AST nodes
7033      */
7034     IAllocator allocator;
7035 
7036     /**
7037      * Function that is called when a warning or error is encountered.
7038      * The parameters are the file name, line number, column number,
7039      * and the error or warning message.
7040      */
7041     void function(string, size_t, size_t, string, bool) messageFunction;
7042 
7043     void setTokens(const(Token)[] tokens)
7044     {
7045         this.tokens = tokens;
7046     }
7047 
7048     /**
7049      * Returns: true if there are more tokens
7050      */
7051     bool moreTokens() const nothrow pure @safe
7052     {
7053         return index < tokens.length;
7054     }
7055 
7056 protected:
7057 
7058     uint suppressedErrorCount;
7059 
7060     enum MAX_ERRORS = 500;
7061 
7062     T[] ownArray(T)(T[] from)
7063     {
7064         if (allocator is null)
7065             return from;
7066         T[] to = cast(T[]) allocator.allocate(T.sizeof * from.length);
7067         assert (to.length == from.length, format("from.length = %d, to.length = %d", from.length, to.length));
7068         to[] = from[];
7069         return to;
7070     }
7071 
7072     T allocate(T, Args...)(auto ref Args args)
7073     {
7074         if (allocator is null)
7075             return new T(args);
7076         enum numBytes = __traits(classInstanceSize, T);
7077         void[] mem = allocator.allocate(numBytes);
7078         assert (mem.length == numBytes, format("%d", mem.length));
7079         T t = emplace!T(mem, args);
7080         assert (cast(void*) t == mem.ptr, "%x, %x".format(cast(void*) t, mem.ptr));
7081         return t;
7082     }
7083 
7084     void deallocate(T)(T t)
7085     {
7086         if (allocator !is null)
7087             allocator.deallocate((cast (void*) t)[0 .. __traits(classInstanceSize, T)]);
7088     }
7089 
7090     bool isCastQualifier() const
7091     {
7092         switch (current.type)
7093         {
7094         case tok!"const":
7095             if (peekIs(tok!")")) return true;
7096             return startsWith(tok!"const", tok!"shared", tok!")");
7097         case tok!"immutable":
7098             return peekIs(tok!")");
7099         case tok!"inout":
7100             if (peekIs(tok!")")) return true;
7101             return startsWith(tok!"inout", tok!"shared", tok!")");
7102         case tok!"shared":
7103             if (peekIs(tok!")")) return true;
7104             if (startsWith(tok!"shared", tok!"const", tok!")")) return true;
7105             return startsWith(tok!"shared", tok!"inout", tok!")");
7106         default:
7107             return false;
7108         }
7109     }
7110 
7111     bool isAssociativeArrayLiteral()
7112     {
7113         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7114         static bool[typeof(current.index)] cached;
7115         if (auto p = current.index in cached)
7116             return *p;
7117         size_t currentIndex = current.index;
7118         auto b = setBookmark();
7119         scope(exit) goToBookmark(b);
7120         advance();
7121         bool result = !currentIs(tok!"]") && parseExpression() !is null && currentIs(tok!":");
7122         cached[currentIndex] = result;
7123         return result;
7124     }
7125 
7126     bool hasMagicDelimiter(alias L, alias T)()
7127     {
7128         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7129         immutable i = index;
7130         scope(exit) index = i;
7131         assert (currentIs(L));
7132         advance();
7133         while (moreTokens()) switch (current.type)
7134         {
7135         case tok!"{": skipBraces(); break;
7136         case tok!"(": skipParens(); break;
7137         case tok!"[": skipBrackets(); break;
7138         case tok!"]": case tok!"}": return false;
7139         case T: return true;
7140         default: advance(); break;
7141         }
7142         return false;
7143     }
7144 
7145     bool isDeclaration()
7146     {
7147         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7148         if (!moreTokens()) return false;
7149         switch (current.type)
7150         {
7151         case tok!"final":
7152             return !peekIs(tok!"switch");
7153         case tok!"debug":
7154             if (peekIs(tok!":"))
7155                 return true;
7156             goto case;
7157         case tok!"version":
7158             if (peekIs(tok!"="))
7159                 return true;
7160             if (peekIs(tok!"("))
7161             {
7162                 auto b = setBookmark();
7163                 scope (exit) goToBookmark(b);
7164                 auto dec = parseDeclaration(true);
7165                 if (dec is null)
7166                     return false;
7167                 else
7168                 {
7169                     deallocate(dec);
7170                     return true;
7171                 }
7172             }
7173             return false;
7174         case tok!"synchronized":
7175             if (peekIs(tok!"("))
7176                 return false;
7177             else
7178                 goto default;
7179         case tok!"static":
7180             if (peekIs(tok!"if"))
7181                 return false;
7182             goto case;
7183         case tok!"scope":
7184             if (peekIs(tok!"("))
7185                 return false;
7186             goto case;
7187         case tok!"const":
7188         case tok!"immutable":
7189         case tok!"inout":
7190         case tok!"shared":
7191             goto default;
7192         case tok!"@":
7193         case tok!"abstract":
7194         case tok!"alias":
7195         case tok!"align":
7196         case tok!"auto":
7197         case tok!"class":
7198         case tok!"deprecated":
7199         case tok!"enum":
7200         case tok!"export":
7201         case tok!"extern":
7202         case tok!"__gshared":
7203         case tok!"interface":
7204         case tok!"nothrow":
7205         case tok!"override":
7206         case tok!"package":
7207         case tok!"private":
7208         case tok!"protected":
7209         case tok!"public":
7210         case tok!"pure":
7211         case tok!"ref":
7212         case tok!"struct":
7213         case tok!"union":
7214         case tok!"unittest":
7215             return true;
7216         mixin(BUILTIN_TYPE_CASES);
7217             return !peekIsOneOf(tok!".", tok!"(");
7218         case tok!"asm":
7219         case tok!"break":
7220         case tok!"case":
7221         case tok!"continue":
7222         case tok!"default":
7223         case tok!"do":
7224         case tok!"for":
7225         case tok!"foreach":
7226         case tok!"foreach_reverse":
7227         case tok!"goto":
7228         case tok!"if":
7229         case tok!"return":
7230         case tok!"switch":
7231         case tok!"throw":
7232         case tok!"try":
7233         case tok!"while":
7234         case tok!"{":
7235         case tok!"assert":
7236             return false;
7237         default:
7238             auto b = setBookmark();
7239             auto p = parseDeclaration();
7240             if (p is null)
7241             {
7242                 goToBookmark(b);
7243                 return false;
7244             }
7245             else
7246             {
7247                 deallocate(p);
7248                 goToBookmark(b);
7249                 return true;
7250             }
7251         }
7252     }
7253 
7254     /// Only use this in template parameter parsing
7255     bool isType()
7256     {
7257         if (!moreTokens()) return false;
7258         auto b = setBookmark();
7259         scope (exit) goToBookmark(b);
7260         auto t = parseType();
7261         if (t is null) return false; else deallocate(t);
7262         if (currentIsOneOf(tok!",", tok!")", tok!"=")) return true;
7263         return false;
7264     }
7265 
7266     bool isStorageClass()
7267     {
7268         if (!moreTokens()) return false;
7269         switch (current.type)
7270         {
7271         case tok!"const":
7272         case tok!"immutable":
7273         case tok!"inout":
7274         case tok!"shared":
7275             return !peekIs(tok!"(");
7276         case tok!"@":
7277         case tok!"deprecated":
7278         case tok!"abstract":
7279         case tok!"align":
7280         case tok!"auto":
7281         case tok!"enum":
7282         case tok!"extern":
7283         case tok!"final":
7284         case tok!"nothrow":
7285         case tok!"override":
7286         case tok!"pure":
7287         case tok!"ref":
7288         case tok!"__gshared":
7289         case tok!"scope":
7290         case tok!"static":
7291         case tok!"synchronized":
7292             return true;
7293         default:
7294             return false;
7295         }
7296     }
7297 
7298     bool isAttribute()
7299     {
7300         if (!moreTokens()) return false;
7301         switch (current.type)
7302         {
7303         case tok!"const":
7304         case tok!"immutable":
7305         case tok!"inout":
7306         case tok!"scope":
7307             return !peekIs(tok!"(");
7308         case tok!"static":
7309             return !peekIsOneOf(tok!"assert", tok!"this", tok!"if", tok!"~");
7310         case tok!"shared":
7311             return !(startsWith(tok!"shared", tok!"static", tok!"this")
7312                 || startsWith(tok!"shared", tok!"static", tok!"~")
7313                 || peekIs(tok!"("));
7314         case tok!"pragma":
7315             auto b = setBookmark();
7316             scope(exit) goToBookmark(b);
7317             advance();
7318             const past = peekPastParens();
7319             if (past is null || *past == tok!";")
7320                 return false;
7321             return true;
7322         case tok!"deprecated":
7323         case tok!"private":
7324         case tok!"package":
7325         case tok!"protected":
7326         case tok!"public":
7327         case tok!"export":
7328         case tok!"final":
7329         case tok!"synchronized":
7330         case tok!"override":
7331         case tok!"abstract":
7332         case tok!"auto":
7333         case tok!"__gshared":
7334         case tok!"pure":
7335         case tok!"nothrow":
7336         case tok!"@":
7337         case tok!"ref":
7338         case tok!"extern":
7339         case tok!"align":
7340             return true;
7341         default:
7342             return false;
7343         }
7344     }
7345 
7346     bool currentIsMemberFunctionAttribute() const
7347     {
7348         if (!moreTokens) return false;
7349         switch (current.type)
7350         {
7351         case tok!"const":
7352         case tok!"immutable":
7353         case tok!"inout":
7354         case tok!"shared":
7355         case tok!"@":
7356         case tok!"pure":
7357         case tok!"nothrow":
7358         case tok!"return":
7359         case tok!"scope":
7360             return true;
7361         default:
7362             return false;
7363         }
7364     }
7365 
7366     ExpressionNode parseLeftAssocBinaryExpression(alias ExpressionType,
7367         alias ExpressionPartType, Operators ...)(ExpressionNode part = null)
7368     {
7369         ExpressionNode node;
7370         mixin("node = part is null ? parse" ~ ExpressionPartType.stringof ~ "() : part;");
7371         if (node is null)
7372         {
7373             deallocate(node);
7374             return null;
7375         }
7376         while (currentIsOneOf(Operators))
7377         {
7378             auto n = allocate!ExpressionType;
7379             n.line = current.line;
7380             n.column = current.column;
7381             static if (__traits(hasMember, ExpressionType, "operator"))
7382                 n.operator = advance().type;
7383             else
7384                 advance();
7385             n.left = node;
7386             mixin("n.right = parse" ~ ExpressionPartType.stringof ~ "();");
7387             node = n;
7388         }
7389         return node;
7390     }
7391 
7392     ListType parseCommaSeparatedRule(alias ListType, alias ItemType, bool setLineAndColumn = false)
7393         (bool allowTrailingComma = false)
7394     {
7395         auto node = allocate!ListType;
7396         static if (setLineAndColumn)
7397         {
7398             node.line = current.line;
7399             node.column = current.column;
7400         }
7401         static if (is(ItemType : ExpressionNode))
7402             ExpressionNode[] items;
7403         else
7404             ItemType[] items;
7405         while (moreTokens())
7406         {
7407             mixin("auto i = parse" ~ ItemType.stringof ~ "();");
7408             if (i !is null)
7409                 items ~= i;
7410             else
7411             {
7412                 deallocate(node);
7413                 return null;
7414             }
7415             if (currentIs(tok!","))
7416             {
7417                 advance();
7418                 if (allowTrailingComma && currentIsOneOf(tok!")",
7419                     tok!"}", tok!"]"))
7420                 {
7421                     break;
7422                 }
7423                 else
7424                     continue;
7425             }
7426             else
7427                 break;
7428         }
7429         node.items = ownArray(items);
7430         return node;
7431     }
7432 
7433     void warn(lazy string message)
7434     {
7435         import std.stdio : stderr;
7436         if (suppressMessages > 0)
7437             return;
7438         ++warningCount;
7439         auto column = index < tokens.length ? tokens[index].column : 0;
7440         auto line = index < tokens.length ? tokens[index].line : 0;
7441         if (messageFunction is null)
7442             stderr.writefln("%s(%d:%d)[warn]: %s", fileName, line, column, message);
7443         else
7444             messageFunction(fileName, line, column, message, false);
7445     }
7446 
7447     void error(string message, bool shouldAdvance = true)
7448     {
7449         import std.stdio : stderr;
7450         if (suppressMessages == 0)
7451         {
7452             ++errorCount;
7453             auto column = index < tokens.length ? tokens[index].column : tokens[$ - 1].column;
7454             auto line = index < tokens.length ? tokens[index].line : tokens[$ - 1].line;
7455             if (messageFunction is null)
7456                 stderr.writefln("%s(%d:%d)[error]: %s", fileName, line, column, message);
7457             else
7458                 messageFunction(fileName, line, column, message, true);
7459         }
7460         else
7461             ++suppressedErrorCount;
7462         while (shouldAdvance && moreTokens())
7463         {
7464             if (currentIsOneOf(tok!";", tok!"}",
7465                 tok!")", tok!"]"))
7466             {
7467                 advance();
7468                 break;
7469             }
7470             else
7471                 advance();
7472         }
7473     }
7474 
7475     void skip(alias O, alias C)()
7476     {
7477         assert (currentIs(O), current().text);
7478         advance();
7479         int depth = 1;
7480         while (moreTokens())
7481         {
7482             switch (tokens[index].type)
7483             {
7484                 case C:
7485                     advance();
7486                     depth--;
7487                     if (depth <= 0)
7488                         return;
7489                     break;
7490                 case O:
7491                     depth++;
7492                     advance();
7493                     break;
7494                 default:
7495                     advance();
7496                     break;
7497             }
7498         }
7499     }
7500 
7501     void skipBraces()
7502     {
7503         skip!(tok!"{", tok!"}")();
7504     }
7505 
7506     void skipParens()
7507     {
7508         version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7509         skip!(tok!"(", tok!")")();
7510     }
7511 
7512     void skipBrackets()
7513     {
7514         skip!(tok!"[", tok!"]")();
7515     }
7516 
7517     const(Token)* peek() const
7518     {
7519         return index + 1 < tokens.length ? &tokens[index + 1] : null;
7520     }
7521 
7522     const(Token)* peekPast(alias O, alias C)() const nothrow
7523     {
7524         if (index >= tokens.length)
7525             return null;
7526         int depth = 1;
7527         size_t i = index;
7528         ++i;
7529         while (i < tokens.length)
7530         {
7531             if (tokens[i] == O)
7532             {
7533                 ++depth;
7534                 ++i;
7535             }
7536             else if (tokens[i] == C)
7537             {
7538                 --depth;
7539                 ++i;
7540                 if (depth <= 0)
7541                     break;
7542             }
7543             else
7544                 ++i;
7545         }
7546         return i >= tokens.length ? null : depth == 0 ? &tokens[i] : null;
7547     }
7548 
7549     const(Token)* peekPastParens() const nothrow
7550     {
7551         return peekPast!(tok!"(", tok!")")();
7552     }
7553 
7554     const(Token)* peekPastBrackets() const nothrow
7555     {
7556         return peekPast!(tok!"[", tok!"]")();
7557     }
7558 
7559     const(Token)* peekPastBraces() const nothrow
7560     {
7561         return peekPast!(tok!"{", tok!"}")();
7562     }
7563 
7564     bool peekIs(IdType t) const nothrow
7565     {
7566         return index + 1 < tokens.length && tokens[index + 1].type == t;
7567     }
7568 
7569     bool peekIsOneOf(IdType[] types...) const nothrow
7570     {
7571         if (index + 1 >= tokens.length) return false;
7572         return canFind(types, tokens[index + 1].type);
7573     }
7574 
7575     /**
7576      * Returns a token of the specified type if it was the next token, otherwise
7577      * calls the error function and returns null. Advances the lexer by one token.
7578      */
7579     const(Token)* expect(IdType type)
7580     {
7581         if (index < tokens.length && tokens[index].type == type)
7582             return &tokens[index++];
7583         else
7584         {
7585             string tokenString = str(type) is null
7586                 ? to!string(type) : str(type);
7587             immutable bool shouldNotAdvance = index < tokens.length
7588                 && (tokens[index].type == tok!")"
7589                 || tokens[index].type == tok!";"
7590                 || tokens[index].type == tok!"}");
7591             auto token = (index < tokens.length
7592                 ? (tokens[index].text is null ? str(tokens[index].type) : tokens[index].text)
7593                 : "EOF");
7594             error("Expected " ~  tokenString ~ " instead of " ~ token,
7595                 !shouldNotAdvance);
7596             return null;
7597         }
7598     }
7599 
7600     /**
7601      * Returns: the _current token
7602      */
7603     Token current() const pure nothrow @nogc @property
7604     {
7605         return tokens[index];
7606     }
7607 
7608     /**
7609      * Advances to the next token and returns the current token
7610      */
7611     Token advance() pure nothrow @nogc
7612     {
7613         return tokens[index++];
7614     }
7615 
7616     /**
7617      * Returns: true if the current token has the given type
7618      */
7619     bool currentIs(IdType type) const pure nothrow @nogc
7620     {
7621         return index < tokens.length && tokens[index] == type;
7622     }
7623 
7624     /**
7625      * Returns: true if the current token is one of the given types
7626      */
7627     bool currentIsOneOf(IdType[] types...) const pure nothrow @nogc
7628     {
7629         if (index >= tokens.length)
7630             return false;
7631         return canFind(types, current.type);
7632     }
7633 
7634     bool startsWith(IdType[] types...) const pure nothrow @nogc
7635     {
7636         if (index + types.length >= tokens.length)
7637             return false;
7638         for (size_t i = 0; (i < types.length) && ((index + i) < tokens.length); ++i)
7639         {
7640             if (tokens[index + i].type != types[i])
7641                 return false;
7642         }
7643         return true;
7644     }
7645 
7646     alias Bookmark = size_t;
7647 
7648     Bookmark setBookmark()
7649     {
7650 //        version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__));
7651         ++suppressMessages;
7652         return index;
7653     }
7654 
7655     void abandonBookmark(Bookmark) nothrow
7656     {
7657         --suppressMessages;
7658         if (suppressMessages == 0)
7659             suppressedErrorCount = 0;
7660     }
7661 
7662     void goToBookmark(Bookmark bookmark) nothrow
7663     {
7664         --suppressMessages;
7665         if (suppressMessages == 0)
7666             suppressedErrorCount = 0;
7667         index = bookmark;
7668     }
7669 
7670     template simpleParse(NodeType, parts ...)
7671     {
7672         static if (__traits(hasMember, NodeType, "comment"))
7673             enum nodeComm = "node.comment = comment;\n"
7674                         ~ "comment = null;\n";
7675         else enum nodeComm = "";
7676 
7677         static if (__traits(hasMember, NodeType, "line"))
7678             enum nodeLine = "node.line = current().line;\n";
7679         else enum nodeLine = "";
7680 
7681         static if (__traits(hasMember, NodeType, "column"))
7682             enum nodeColumn = "node.column = current().column;\n";
7683         else enum nodeColumn = "";
7684 
7685         static if (__traits(hasMember, NodeType, "location"))
7686             enum nodeLoc = "node.location = current().index;\n";
7687         else enum nodeLoc = "";
7688 
7689         enum simpleParse = "auto node = allocate!" ~ NodeType.stringof ~ ";\n"
7690                         ~ nodeComm ~ nodeLine ~ nodeColumn ~ nodeLoc
7691                         ~ simpleParseItems!(parts)
7692                         ~ "\nreturn node;\n";
7693     }
7694 
7695     template simpleParseItems(items ...)
7696     {
7697         static if (items.length > 1)
7698             enum simpleParseItems = simpleParseItem!(items[0]) ~ "\n"
7699                 ~ simpleParseItems!(items[1 .. $]);
7700         else static if (items.length == 1)
7701             enum simpleParseItems = simpleParseItem!(items[0]);
7702         else
7703             enum simpleParseItems = "";
7704     }
7705 
7706     template simpleParseItem(alias item)
7707     {
7708         static if (is (typeof(item) == string))
7709             enum simpleParseItem = "if ((node." ~ item[0 .. item.countUntil("|")]
7710                 ~ " = " ~ item[item.countUntil("|") + 1 .. $] ~ "()) is null) { deallocate(node); return null; }";
7711         else
7712             enum simpleParseItem = "if (expect(" ~ item.stringof ~ ") is null) { deallocate(node); return null; }";
7713     }
7714 
7715     template expectSequence(sequence ...)
7716     {
7717         static if (sequence.length == 1)
7718             enum expectSequence = "if (expect(" ~ sequence[0].stringof ~ ") is null) { deallocate(node); return null; }";
7719         else
7720             enum expectSequence = "if (expect(" ~ sequence[0].stringof ~ ") is null) { deallocate(node); return null; }\n"
7721                 ~ expectSequence!(sequence[1..$]);
7722     }
7723 
7724     template traceEnterAndExit(string fun)
7725     {
7726         enum traceEnterAndExit = `version (std_parser_verbose) { _traceDepth++; trace("`
7727             ~ `\033[01;32m` ~ fun ~ `\033[0m"); }`
7728             ~ `version (std_parser_verbose) scope(exit) { trace("`
7729             ~ `\033[01;31m` ~ fun ~ `\033[0m"); _traceDepth--; }`;
7730     }
7731 
7732     version (std_parser_verbose)
7733     {
7734         import std.stdio : stderr;
7735         void trace(string message)
7736         {
7737             if (suppressMessages > 0)
7738                 return;
7739             auto depth = format("%4d ", _traceDepth);
7740             if (index < tokens.length)
7741                 stderr.writeln(depth, message, "(", current.line, ":", current.column, ")");
7742             else
7743                 stderr.writeln(depth, message, "(EOF:0)");
7744         }
7745     }
7746     else
7747     {
7748         void trace(lazy string) {}
7749     }
7750 
7751     template nullCheck(string exp)
7752     {
7753         enum nullCheck = "{if ((" ~ exp ~ ") is null) { deallocate(node); return null; }}";
7754     }
7755 
7756     template tokenCheck(string exp, string tok)
7757     {
7758         enum tokenCheck = `{auto t = expect(tok!"` ~ tok ~ `");`
7759             ~ `if (t is null) { deallocate(node); return null;}`
7760             ~ `else {` ~ exp ~ ` = *t; }}`;
7761     }
7762 
7763     // This list MUST BE MAINTAINED IN SORTED ORDER.
7764     static immutable string[] REGISTER_NAMES = [
7765         "AH", "AL", "AX", "BH", "BL", "BP", "BPL", "BX", "CH", "CL", "CR0", "CR2",
7766         "CR3", "CR4", "CS", "CX", "DH", "DI", "DIL", "DL", "DR0", "DR1", "DR2",
7767         "DR3", "DR6", "DR7", "DS", "DX", "EAX", "EBP", "EBX", "ECX", "EDI", "EDX",
7768         "ES", "ESI", "ESP", "FS", "GS", "MM0", "MM1", "MM2", "MM3", "MM4", "MM5",
7769         "MM6", "MM7", "R10", "R10B", "R10D", "R10W", "R11", "R11B", "R11D", "R11W",
7770         "R12", "R12B", "R12D", "R12W", "R13", "R13B", "R13D", "R13W", "R14", "R14B",
7771         "R14D", "R14W", "R15", "R15B", "R15D", "R15W", "R8", "R8B", "R8D", "R8W",
7772         "R9", "R9B", "R9D", "R9W", "RAX", "RBP", "RBX", "RCX", "RDI", "RDX", "RSI",
7773         "RSP", "SI", "SIL", "SP", "SPL", "SS", "ST", "TR3", "TR4", "TR5", "TR6",
7774         "TR7", "XMM0", "XMM1", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15",
7775         "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "YMM0",
7776         "YMM1", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", "YMM2",
7777         "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9"
7778     ];
7779 
7780     enum string BUILTIN_TYPE_CASES = q{
7781         case tok!"int":
7782         case tok!"uint":
7783         case tok!"double":
7784         case tok!"idouble":
7785         case tok!"float":
7786         case tok!"ifloat":
7787         case tok!"short":
7788         case tok!"ushort":
7789         case tok!"long":
7790         case tok!"ulong":
7791         case tok!"char":
7792         case tok!"wchar":
7793         case tok!"dchar":
7794         case tok!"bool":
7795         case tok!"void":
7796         case tok!"cent":
7797         case tok!"ucent":
7798         case tok!"real":
7799         case tok!"ireal":
7800         case tok!"byte":
7801         case tok!"ubyte":
7802         case tok!"cdouble":
7803         case tok!"cfloat":
7804         case tok!"creal":
7805     };
7806 
7807     enum string LITERAL_CASES = q{
7808         case tok!"doubleLiteral":
7809         case tok!"floatLiteral":
7810         case tok!"idoubleLiteral":
7811         case tok!"ifloatLiteral":
7812         case tok!"intLiteral":
7813         case tok!"longLiteral":
7814         case tok!"realLiteral":
7815         case tok!"irealLiteral":
7816         case tok!"uintLiteral":
7817         case tok!"ulongLiteral":
7818         case tok!"stringLiteral":
7819         case tok!"wstringLiteral":
7820         case tok!"dstringLiteral":
7821         case tok!"characterLiteral":
7822     };
7823 
7824     enum string SPECIAL_CASES = q{
7825         case tok!"__DATE__":
7826         case tok!"__EOF__":
7827         case tok!"__FILE__":
7828         case tok!"__FUNCTION__":
7829         case tok!"__LINE__":
7830         case tok!"__MODULE__":
7831         case tok!"__PRETTY_FUNCTION__":
7832         case tok!"__TIME__":
7833         case tok!"__TIMESTAMP__":
7834         case tok!"__VENDOR__":
7835         case tok!"__VERSION__":
7836     };
7837 
7838     enum string PARSE_INTERFACE_OR_CLASS = q{
7839         auto ident = expect(tok!"identifier");
7840         mixin(nullCheck!`ident`);
7841         node.name = *ident;
7842         node.comment = comment;
7843         comment = null;
7844         if (currentIs(tok!";"))
7845             goto emptyBody;
7846         if (currentIs(tok!"{"))
7847             goto structBody;
7848         templateStuff: if (currentIs(tok!"("))
7849         {
7850             mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`);
7851             if (currentIs(tok!";"))
7852                 goto emptyBody;
7853             constraint: if (currentIs(tok!"if"))
7854                 mixin(nullCheck!`node.constraint = parseConstraint()`);
7855             if (node.baseClassList !is null)
7856             {
7857                 if (currentIs(tok!"{"))
7858                     goto structBody;
7859                 else if (currentIs(tok!";"))
7860                     goto emptyBody;
7861                 else
7862                 {
7863                     error("Struct body or ';' expected");
7864                     return null;
7865                 }
7866             }
7867             if (currentIs(tok!":"))
7868                 goto baseClassList;
7869             if (currentIs(tok!"if"))
7870                 goto constraint;
7871             if (currentIs(tok!";"))
7872                 goto emptyBody;
7873         }
7874         if (currentIs(tok!":"))
7875         {
7876     baseClassList:
7877             advance(); // :
7878             if ((node.baseClassList = parseBaseClassList()) is null)
7879                 return null;
7880             if (currentIs(tok!"if"))
7881                 goto constraint;
7882         }
7883     structBody:
7884         mixin(nullCheck!`node.structBody = parseStructBody()`);
7885         return node;
7886     emptyBody:
7887         advance();
7888         return node;
7889     };
7890 
7891     const(Token)[] tokens;
7892     int suppressMessages;
7893     size_t index;
7894     int _traceDepth;
7895     string comment;
7896 }
7897