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