Parser: issue better error msgs for missing closing tokens.
[dil.git] / src / dil / parser / Parser.d
blob25e2fa66a9e191e060d8708035cdcd7c53cf97f6
1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity very high)
4 module dil.parser.Parser;
6 import dil.lexer.Lexer,
7 dil.lexer.IdTable;
8 import dil.ast.Node,
9 dil.ast.Declarations,
10 dil.ast.Statements,
11 dil.ast.Expressions,
12 dil.ast.Types,
13 dil.ast.Parameters;
14 import dil.Messages;
15 import dil.Diagnostics;
16 import dil.Enums;
17 import dil.CompilerInfo;
18 import dil.SourceText;
19 import dil.Unicode;
20 import common;
22 import tango.core.Vararg;
24 /// The Parser produces a full parse tree by examining
25 /// the list of tokens provided by the Lexer.
26 class Parser
28 Lexer lexer; /// Used to lex the source code.
29 Token* token; /// Current non-whitespace token.
30 Token* prevToken; /// Previous non-whitespace token.
32 Diagnostics diag;
33 ParserError[] errors; /// Array of parser error messages.
35 ImportDeclaration[] imports; /// ImportDeclarations in the source text.
37 /// Attributes are evaluated in the parsing phase.
38 /// TODO: will be removed. SemanticPass1 takes care of attributes.
39 LinkageType linkageType;
40 Protection protection; /// ditto
41 StorageClass storageClass; /// ditto
42 uint alignSize = DEFAULT_ALIGN_SIZE; /// ditto
44 private alias TOK T; /// Used often in this class.
45 private alias TypeNode Type;
47 /// Constructs a Parser object.
48 /// Params:
49 /// srcText = the UTF-8 source code.
50 /// diag = used for collecting error messages.
51 this(SourceText srcText, Diagnostics diag = null)
53 this.diag = diag;
54 lexer = new Lexer(srcText, diag);
57 /// Moves to the first token.
58 protected void init()
60 nT();
61 prevToken = token;
64 /// Moves to the next token.
65 void nT()
67 prevToken = token;
70 lexer.nextToken();
71 token = lexer.token;
72 } while (token.isWhitespace) // Skip whitespace
75 /// Start the parser and return the parsed Declarations.
76 CompoundDeclaration start()
78 init();
79 auto begin = token;
80 auto decls = new CompoundDeclaration;
81 if (token.kind == T.Module)
82 decls ~= parseModuleDeclaration();
83 decls.addOptChildren(parseDeclarationDefinitions());
84 set(decls, begin);
85 return decls;
88 /// Start the parser and return the parsed Expression.
89 Expression start2()
91 init();
92 return parseExpression();
95 // Members related to the method try_().
96 uint trying; /// Greater than 0 if Parser is in try_().
97 uint errorCount; /// Used to track nr. of errors while being in try_().
99 /// This method executes the delegate parseMethod and when an error occurred
100 /// the state of the lexer and parser is restored.
101 /// Returns: the return value of parseMethod().
102 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success)
104 // Save members.
105 auto oldToken = this.token;
106 auto oldPrevToken = this.prevToken;
107 auto oldCount = this.errorCount;
109 ++trying;
110 auto result = parseMethod();
111 --trying;
112 // Check if an error occurred.
113 if (errorCount != oldCount)
114 { // Restore members.
115 token = oldToken;
116 prevToken = oldPrevToken;
117 lexer.token = oldToken;
118 errorCount = oldCount;
119 success = false;
121 else
122 success = true;
123 return result;
126 /// Causes the current call to try_() to fail.
127 void try_fail()
129 assert(trying);
130 errorCount++;
133 /// Sets the begin and end tokens of a syntax tree node.
134 Class set(Class)(Class node, Token* begin)
136 node.setTokens(begin, this.prevToken);
137 return node;
140 /// Sets the begin and end tokens of a syntax tree node.
141 Class set(Class)(Class node, Token* begin, Token* end)
143 node.setTokens(begin, end);
144 return node;
147 /// Returns true if set() has been called on a node.
148 static bool isNodeSet(Node node)
150 return node.begin !is null && node.end !is null;
153 /// Returns the token kind of the next token.
154 TOK peekNext()
156 Token* next = token;
158 lexer.peek(next);
159 while (next.isWhitespace) // Skip whitespace
160 return next.kind;
163 /// Returns the token kind of the token that comes after t.
164 TOK peekAfter(ref Token* t)
166 assert(t !is null);
168 lexer.peek(t);
169 while (t.isWhitespace) // Skip whitespace
170 return t.kind;
173 /// Consumes the current token if its kind matches k and returns true.
174 bool consumed()(TOK k) // Templatized, so it's inlined.
176 return token.kind == k ? (nT(), true) : false;
179 /// Asserts that the current token is of kind expectedKind,
180 /// and then moves to the next token.
181 void skip()(TOK expectedKind)
183 assert(token.kind == expectedKind /+|| *(int*).init+/, token.srcText());
184 nT();
187 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188 | Declaration parsing methods |
189 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
191 Declaration parseModuleDeclaration()
193 auto begin = token;
194 skip(T.Module);
195 ModuleFQN moduleFQN;
197 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
198 while (consumed(T.Dot))
199 require(T.Semicolon);
200 return set(new ModuleDeclaration(moduleFQN), begin);
203 /// Parses DeclarationDefinitions until the end of file is hit.
204 /// $(PRE
205 /// DeclDefs :=
206 /// DeclDef
207 /// DeclDefs
208 /// )
209 Declaration[] parseDeclarationDefinitions()
211 Declaration[] decls;
212 while (token.kind != T.EOF)
213 decls ~= parseDeclarationDefinition();
214 return decls;
217 /// Parse the body of a template, class, interface, struct or union.
218 /// $(PRE
219 /// DeclDefsBlock :=
220 /// { }
221 /// { DeclDefs }
222 /// )
223 CompoundDeclaration parseDeclarationDefinitionsBody()
225 // Save attributes.
226 auto linkageType = this.linkageType;
227 auto protection = this.protection;
228 auto storageClass = this.storageClass;
229 // Clear attributes.
230 this.linkageType = LinkageType.None;
231 this.protection = Protection.None;
232 this.storageClass = StorageClass.None;
234 // Parse body.
235 auto begin = token;
236 auto decls = new CompoundDeclaration;
237 require(T.LBrace);
238 while (token.kind != T.RBrace && token.kind != T.EOF)
239 decls ~= parseDeclarationDefinition();
240 requireClosing(T.RBrace, begin);
241 set(decls, begin);
243 // Restore original values.
244 this.linkageType = linkageType;
245 this.protection = protection;
246 this.storageClass = storageClass;
248 return decls;
251 /// Parses a DeclarationDefinition.
252 Declaration parseDeclarationDefinition()
253 out(decl)
254 { assert(isNodeSet(decl)); }
255 body
257 auto begin = token;
258 Declaration decl;
259 switch (token.kind)
261 case T.Align,
262 T.Pragma,
263 // Protection attributes
264 T.Export,
265 T.Private,
266 T.Package,
267 T.Protected,
268 T.Public:
269 decl = parseAttributeSpecifier();
270 break;
271 // Storage classes
272 case T.Extern,
273 T.Deprecated,
274 T.Override,
275 T.Abstract,
276 T.Synchronized,
277 //T.Static,
278 T.Final,
279 T.Const,
280 //T.Invariant, // D 2.0
281 T.Auto,
282 T.Scope:
283 case_StaticAttribute:
284 case_InvariantAttribute: // D 2.0
285 case_EnumAttribute: // D 2.0
286 return parseStorageAttribute();
287 case T.Alias:
288 nT();
289 decl = new AliasDeclaration(parseVariableOrFunction());
290 break;
291 case T.Typedef:
292 nT();
293 decl = new TypedefDeclaration(parseVariableOrFunction());
294 break;
295 case T.Static:
296 switch (peekNext())
298 case T.Import:
299 goto case_Import;
300 case T.This:
301 decl = parseStaticConstructorDeclaration();
302 break;
303 case T.Tilde:
304 decl = parseStaticDestructorDeclaration();
305 break;
306 case T.If:
307 decl = parseStaticIfDeclaration();
308 break;
309 case T.Assert:
310 decl = parseStaticAssertDeclaration();
311 break;
312 default:
313 goto case_StaticAttribute;
315 break;
316 case T.Import:
317 case_Import:
318 decl = parseImportDeclaration();
319 imports ~= decl.to!(ImportDeclaration);
320 // Handle specially. StorageClass mustn't be set.
321 decl.setProtection(this.protection);
322 return set(decl, begin);
323 case T.Enum:
324 version(D2)
326 if (isEnumManifest())
327 goto case_EnumAttribute;
329 decl = parseEnumDeclaration();
330 break;
331 case T.Class:
332 decl = parseClassDeclaration();
333 break;
334 case T.Interface:
335 decl = parseInterfaceDeclaration();
336 break;
337 case T.Struct, T.Union:
338 decl = parseStructOrUnionDeclaration();
339 break;
340 case T.This:
341 decl = parseConstructorDeclaration();
342 break;
343 case T.Tilde:
344 decl = parseDestructorDeclaration();
345 break;
346 case T.Invariant:
347 version(D2)
349 auto next = token;
350 if (peekAfter(next) == T.LParen)
352 if (peekAfter(next) != T.RParen)
353 goto case_Declaration; // invariant ( Type )
355 else
356 goto case_InvariantAttribute; // invariant as StorageClass.
358 decl = parseInvariantDeclaration(); // invariant ( )
359 break;
360 case T.Unittest:
361 decl = parseUnittestDeclaration();
362 break;
363 case T.Debug:
364 decl = parseDebugDeclaration();
365 break;
366 case T.Version:
367 decl = parseVersionDeclaration();
368 break;
369 case T.Template:
370 decl = parseTemplateDeclaration();
371 break;
372 case T.New:
373 decl = parseNewDeclaration();
374 break;
375 case T.Delete:
376 decl = parseDeleteDeclaration();
377 break;
378 case T.Mixin:
379 decl = parseMixin!(MixinDeclaration)();
380 break;
381 case T.Semicolon:
382 nT();
383 decl = new EmptyDeclaration();
384 break;
385 // Declaration
386 case T.Identifier, T.Dot, T.Typeof:
387 case_Declaration:
388 return parseVariableOrFunction(this.storageClass, this.protection, this.linkageType);
389 default:
390 if (token.isIntegralType)
391 goto case_Declaration;
392 else if (token.kind == T.Module)
394 decl = parseModuleDeclaration();
395 error(begin, MSG.ModuleDeclarationNotFirst);
396 return decl;
399 decl = new IllegalDeclaration();
400 // Skip to next valid token.
402 nT();
403 while (!token.isDeclDefStart &&
404 token.kind != T.RBrace &&
405 token.kind != T.EOF)
406 auto text = Token.textSpan(begin, this.prevToken);
407 error(begin, MSG.IllegalDeclaration, text);
409 decl.setProtection(this.protection);
410 decl.setStorageClass(this.storageClass);
411 assert(!isNodeSet(decl));
412 set(decl, begin);
413 return decl;
416 /// Parses a DeclarationsBlock.
417 /// $(PRE
418 /// DeclarationsBlock :=
419 /// : DeclDefs
420 /// { }
421 /// { DeclDefs }
422 /// DeclDef
423 /// )
424 Declaration parseDeclarationsBlock(/+bool noColon = false+/)
426 Declaration d;
427 switch (token.kind)
429 case T.LBrace:
430 auto begin = token;
431 nT();
432 auto decls = new CompoundDeclaration;
433 while (token.kind != T.RBrace && token.kind != T.EOF)
434 decls ~= parseDeclarationDefinition();
435 requireClosing(T.RBrace, begin);
436 d = set(decls, begin);
437 break;
438 case T.Colon:
439 // if (noColon == true)
440 // goto default;
441 nT();
442 auto begin = token;
443 auto decls = new CompoundDeclaration;
444 while (token.kind != T.RBrace && token.kind != T.EOF)
445 decls ~= parseDeclarationDefinition();
446 d = set(decls, begin);
447 break;
448 default:
449 d = parseDeclarationDefinition();
451 assert(isNodeSet(d));
452 return d;
455 // Declaration parseDeclarationsBlockNoColon()
456 // {
457 // return parseDeclarationsBlock(true);
458 // }
460 /// Parses either a VariableDeclaration or a FunctionDeclaration.
461 /// Params:
462 /// stc = previously parsed storage classes
463 /// protection = previously parsed protection attribute
464 /// linkType = previously parsed linkage type
465 /// testAutoDeclaration = whether to check for an AutoDeclaration
466 /// optionalParameterList = a hint for how to parse C-style function pointers
467 Declaration parseVariableOrFunction(StorageClass stc = StorageClass.None,
468 Protection protection = Protection.None,
469 LinkageType linkType = LinkageType.None,
470 bool testAutoDeclaration = false,
471 bool optionalParameterList = true)
473 auto begin = token;
474 Type type;
475 Identifier* name;
477 // Check for AutoDeclaration: StorageClasses Identifier =
478 if (testAutoDeclaration && token.kind == T.Identifier)
480 auto kind = peekNext();
481 if (kind == T.Assign)
482 { // Auto variable declaration.
483 name = token.ident;
484 skip(T.Identifier);
485 goto LparseVariables;
487 else version(D2) if (kind == T.LParen)
488 { // Check for auto return type template function.
489 // StorageClasses Name ( TemplateParameterList ) ( ParameterList )
490 name = token.ident;
491 auto next = token;
492 peekAfter(next);
493 if (tokenAfterParenIs(T.LParen, next))
495 skip(T.Identifier);
496 assert(token.kind == T.LParen);
497 goto LparseTPList; // Continue with parsing a template function.
502 type = parseType(); // VariableType or ReturnType
504 if (token.kind == T.LParen)
505 { // C-style function pointers make the grammar ambiguous.
506 // We have to treat them specially at function scope.
507 // Example:
508 // void foo() {
509 // // A pointer to a function taking an integer and returning 'some_type'.
510 // some_type (*p_func)(int);
511 // // In the following case precedence is given to a CallExpression.
512 // something(*p); // 'something' may be a function/method or an object having opCall overloaded.
513 // }
514 // // A pointer to a function taking no parameters and returning 'something'.
515 // something(*p);
516 type = parseCFunctionPointerType(type, name, optionalParameterList);
518 else if (peekNext() == T.LParen)
519 { // Type FunctionName ( ParameterList ) FunctionBody
520 name = requireIdentifier(MSG.ExpectedFunctionName);
521 name || nT(); // Skip non-identifier token.
522 assert(token.kind == T.LParen);
523 // It's a function declaration
524 TemplateParameters tparams;
525 Expression constraint;
527 if (tokenAfterParenIs(T.LParen))
528 LparseTPList:
529 // ( TemplateParameterList ) ( ParameterList )
530 tparams = parseTemplateParameterList();
532 auto params = parseParameterList();
533 version(D2)
535 if (tparams) // If ( ConstraintExpression )
536 constraint = parseOptionalConstraint();
537 switch (token.kind)
539 case T.Const:
540 stc |= StorageClass.Const;
541 nT();
542 break;
543 case T.Invariant:
544 stc |= StorageClass.Invariant;
545 nT();
546 break;
547 default:
550 // ReturnType FunctionName ( ParameterList )
551 auto funcBody = parseFunctionBody();
552 auto fd = new FunctionDeclaration(type, name,/+ tparams,+/ params, funcBody);
553 fd.setStorageClass(stc);
554 fd.setLinkageType(linkType);
555 fd.setProtection(protection);
556 if (tparams)
558 auto d = putInsideTemplateDeclaration(begin, name, fd, tparams, constraint);
559 d.setStorageClass(stc);
560 d.setProtection(protection);
561 return set(d, begin);
563 return set(fd, begin);
565 else
566 { // Type VariableName DeclaratorSuffix
567 name = requireIdentifier(MSG.ExpectedVariableName);
568 type = parseDeclaratorSuffix(type);
571 LparseVariables:
572 // It's a variables declaration.
573 Identifier*[] names = [name]; // One identifier has been parsed already.
574 Expression[] values;
575 goto LenterLoop; // Enter the loop and check for an initializer.
576 while (consumed(T.Comma))
578 names ~= requireIdentifier(MSG.ExpectedVariableName);
579 LenterLoop:
580 if (consumed(T.Assign))
581 values ~= parseInitializer();
582 else
583 values ~= null;
585 require(T.Semicolon);
586 auto d = new VariablesDeclaration(type, names, values);
587 d.setStorageClass(stc);
588 d.setLinkageType(linkType);
589 d.setProtection(protection);
590 return set(d, begin);
593 /// Parses a variable initializer.
594 Expression parseInitializer()
596 if (token.kind == T.Void)
598 auto begin = token;
599 auto next = peekNext();
600 if (next == T.Comma || next == T.Semicolon)
602 skip(T.Void);
603 return set(new VoidInitExpression(), begin);
606 return parseNonVoidInitializer();
609 Expression parseNonVoidInitializer()
611 auto begin = token;
612 Expression init;
613 switch (token.kind)
615 case T.LBracket:
616 // ArrayInitializer:
617 // [ ]
618 // [ ArrayMemberInitializations ]
619 Expression[] keys;
620 Expression[] values;
622 skip(T.LBracket);
623 while (token.kind != T.RBracket)
625 auto e = parseNonVoidInitializer();
626 if (consumed(T.Colon))
628 keys ~= e;
629 values ~= parseNonVoidInitializer();
631 else
633 keys ~= null;
634 values ~= e;
637 if (!consumed(T.Comma))
638 break;
640 requireClosing(T.RBracket, begin);
641 init = new ArrayInitExpression(keys, values);
642 break;
643 case T.LBrace:
644 // StructInitializer:
645 // { }
646 // { StructMemberInitializers }
647 Expression parseStructInitializer()
649 Identifier*[] idents;
650 Expression[] values;
652 skip(T.LBrace);
653 while (token.kind != T.RBrace)
655 if (token.kind == T.Identifier &&
656 // Peek for colon to see if this is a member identifier.
657 peekNext() == T.Colon)
659 idents ~= token.ident;
660 skip(T.Identifier), skip(T.Colon);
662 else
663 idents ~= null;
665 // NonVoidInitializer
666 values ~= parseNonVoidInitializer();
668 if (!consumed(T.Comma))
669 break;
671 requireClosing(T.RBrace, begin);
672 return new StructInitExpression(idents, values);
675 bool success;
676 auto si = try_(&parseStructInitializer, success);
677 if (success)
679 init = si;
680 break;
682 assert(token.kind == T.LBrace);
683 //goto default;
684 default:
685 init = parseAssignExpression();
687 set(init, begin);
688 return init;
691 FuncBodyStatement parseFunctionBody()
693 auto begin = token;
694 auto func = new FuncBodyStatement;
695 while (1)
697 switch (token.kind)
699 case T.LBrace:
700 func.funcBody = parseStatements();
701 break;
702 case T.Semicolon:
703 nT();
704 break;
705 case T.In:
706 if (func.inBody)
707 error(MID.InContract);
708 nT();
709 func.inBody = parseStatements();
710 continue;
711 case T.Out:
712 if (func.outBody)
713 error(MID.OutContract);
714 nT();
715 if (consumed(T.LParen))
717 auto leftParen = this.prevToken;
718 func.outIdent = requireIdentifier(MSG.ExpectedAnIdentifier);
719 requireClosing(T.RParen, leftParen);
721 func.outBody = parseStatements();
722 continue;
723 case T.Body:
724 nT();
725 goto case T.LBrace;
726 default:
727 error2(MSG.ExpectedFunctionBody, token);
729 break; // Exit loop.
731 set(func, begin);
732 func.finishConstruction();
733 return func;
736 LinkageType parseLinkageType()
738 LinkageType linkageType;
740 if (!consumed(T.LParen))
741 return linkageType;
743 if (consumed(T.RParen))
744 { // extern()
745 error(MID.MissingLinkageType);
746 return linkageType;
749 auto identTok = requireId();
751 IDK idKind = identTok ? identTok.ident.idKind : IDK.Null;
753 switch (idKind)
755 case IDK.C:
756 if (consumed(T.PlusPlus))
758 linkageType = LinkageType.Cpp;
759 break;
761 linkageType = LinkageType.C;
762 break;
763 case IDK.D:
764 linkageType = LinkageType.D;
765 break;
766 case IDK.Windows:
767 linkageType = LinkageType.Windows;
768 break;
769 case IDK.Pascal:
770 linkageType = LinkageType.Pascal;
771 break;
772 case IDK.System:
773 linkageType = LinkageType.System;
774 break;
775 default:
776 error2(MID.UnrecognizedLinkageType, token);
778 require(T.RParen);
779 return linkageType;
782 void checkLinkageType(ref LinkageType prev_lt, LinkageType lt, Token* begin)
784 if (prev_lt == LinkageType.None)
785 prev_lt = lt;
786 else
787 error(begin, MSG.RedundantLinkageType, Token.textSpan(begin, this.prevToken));
790 Declaration parseStorageAttribute()
792 StorageClass stc, stc_tmp;
793 LinkageType prev_linkageType;
795 auto saved_storageClass = this.storageClass; // Save.
796 // Nested function.
797 Declaration parse()
799 Declaration decl;
800 auto begin = token;
801 switch (token.kind)
803 case T.Extern:
804 if (peekNext() != T.LParen)
806 stc_tmp = StorageClass.Extern;
807 goto Lcommon;
810 nT();
811 auto linkageType = parseLinkageType();
812 checkLinkageType(prev_linkageType, linkageType, begin);
814 auto saved = this.linkageType; // Save.
815 this.linkageType = linkageType; // Set.
816 decl = new LinkageDeclaration(linkageType, parse());
817 set(decl, begin);
818 this.linkageType = saved; // Restore.
819 break;
820 case T.Override:
821 stc_tmp = StorageClass.Override;
822 goto Lcommon;
823 case T.Deprecated:
824 stc_tmp = StorageClass.Deprecated;
825 goto Lcommon;
826 case T.Abstract:
827 stc_tmp = StorageClass.Abstract;
828 goto Lcommon;
829 case T.Synchronized:
830 stc_tmp = StorageClass.Synchronized;
831 goto Lcommon;
832 case T.Static:
833 stc_tmp = StorageClass.Static;
834 goto Lcommon;
835 case T.Final:
836 stc_tmp = StorageClass.Final;
837 goto Lcommon;
838 case T.Const:
839 version(D2)
841 if (peekNext() == T.LParen)
842 goto case_Declaration;
844 stc_tmp = StorageClass.Const;
845 goto Lcommon;
846 version(D2)
848 case T.Invariant: // D 2.0
849 auto next = token;
850 if (peekAfter(next) == T.LParen)
852 if (peekAfter(next) != T.RParen)
853 goto case_Declaration; // invariant ( Type )
854 decl = parseInvariantDeclaration(); // invariant ( )
855 // NB: this must be similar to the code at the end of
856 // parseDeclarationDefinition().
857 decl.setProtection(this.protection);
858 decl.setStorageClass(stc);
859 set(decl, begin);
860 break;
862 // invariant as StorageClass.
863 stc_tmp = StorageClass.Invariant;
864 goto Lcommon;
865 case T.Enum: // D 2.0
866 if (!isEnumManifest())
867 { // A normal enum declaration.
868 decl = parseEnumDeclaration();
869 // NB: this must be similar to the code at the end of
870 // parseDeclarationDefinition().
871 decl.setProtection(this.protection);
872 decl.setStorageClass(stc);
873 set(decl, begin);
874 break;
876 // enum as StorageClass.
877 stc_tmp = StorageClass.Manifest;
878 goto Lcommon;
879 } // version(D2)
880 case T.Auto:
881 stc_tmp = StorageClass.Auto;
882 goto Lcommon;
883 case T.Scope:
884 stc_tmp = StorageClass.Scope;
885 goto Lcommon;
886 Lcommon:
887 // Issue error if redundant.
888 if (stc & stc_tmp)
889 error2(MID.RedundantStorageClass, token);
890 else
891 stc |= stc_tmp;
893 nT();
894 decl = new StorageClassDeclaration(stc_tmp, parse());
895 set(decl, begin);
896 break;
897 case T.Identifier:
898 case_Declaration:
899 // This could be a normal Declaration or an AutoDeclaration
900 decl = parseVariableOrFunction(stc, this.protection, prev_linkageType, true);
901 break;
902 default:
903 this.storageClass = stc; // Set.
904 decl = parseDeclarationsBlock();
905 this.storageClass = saved_storageClass; // Reset.
907 assert(isNodeSet(decl));
908 return decl;
910 return parse();
913 uint parseAlignAttribute()
915 skip(T.Align);
916 uint size = DEFAULT_ALIGN_SIZE; // Global default.
917 if (consumed(T.LParen))
919 if (token.kind == T.Int32)
920 (size = token.int_), skip(T.Int32);
921 else
922 expected(T.Int32);
923 require(T.RParen);
925 return size;
928 Declaration parseAttributeSpecifier()
930 Declaration decl;
932 switch (token.kind)
934 case T.Align:
935 uint alignSize = parseAlignAttribute();
936 auto saved = this.alignSize; // Save.
937 this.alignSize = alignSize; // Set.
938 decl = new AlignDeclaration(alignSize, parseDeclarationsBlock());
939 this.alignSize = saved; // Restore.
940 break;
941 case T.Pragma:
942 // Pragma:
943 // pragma ( Identifier )
944 // pragma ( Identifier , ExpressionList )
945 nT();
946 Identifier* ident;
947 Expression[] args;
949 require(T.LParen);
950 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
952 if (consumed(T.Comma))
953 args = parseExpressionList();
954 require(T.RParen);
956 decl = new PragmaDeclaration(ident, args, parseDeclarationsBlock());
957 break;
958 default:
959 // Protection attributes
960 Protection prot;
961 switch (token.kind)
963 case T.Private:
964 prot = Protection.Private; break;
965 case T.Package:
966 prot = Protection.Package; break;
967 case T.Protected:
968 prot = Protection.Protected; break;
969 case T.Public:
970 prot = Protection.Public; break;
971 case T.Export:
972 prot = Protection.Export; break;
973 default:
974 assert(0);
976 nT();
977 auto saved = this.protection; // Save.
978 this.protection = prot; // Set.
979 decl = new ProtectionDeclaration(prot, parseDeclarationsBlock());
980 this.protection = saved; // Restore.
982 return decl;
985 Declaration parseImportDeclaration()
987 bool isStatic = consumed(T.Static);
988 skip(T.Import);
990 ModuleFQN[] moduleFQNs;
991 Identifier*[] moduleAliases;
992 Identifier*[] bindNames;
993 Identifier*[] bindAliases;
997 ModuleFQN moduleFQN;
998 Identifier* moduleAlias;
999 // AliasName = ModuleName
1000 if (peekNext() == T.Assign)
1002 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName);
1003 skip(T.Assign);
1005 // Identifier ("." Identifier)*
1007 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
1008 while (consumed(T.Dot))
1009 // Push identifiers.
1010 moduleFQNs ~= moduleFQN;
1011 moduleAliases ~= moduleAlias;
1012 } while (consumed(T.Comma))
1014 if (consumed(T.Colon))
1015 { // BindAlias "=" BindName ("," BindAlias "=" BindName)*;
1016 // BindName ("," BindName)*;
1019 Identifier* bindAlias;
1020 // BindAlias = BindName
1021 if (peekNext() == T.Assign)
1023 bindAlias = requireIdentifier(MSG.ExpectedAliasImportName);
1024 skip(T.Assign);
1026 // Push identifiers.
1027 bindNames ~= requireIdentifier(MSG.ExpectedImportName);
1028 bindAliases ~= bindAlias;
1029 } while (consumed(T.Comma))
1031 require(T.Semicolon);
1033 return new ImportDeclaration(moduleFQNs, moduleAliases, bindNames, bindAliases, isStatic);
1036 version(D2)
1038 /// Returns true if this is an enum manifest or
1039 /// false if it's a normal enum declaration.
1040 bool isEnumManifest()
1042 assert(token.kind == T.Enum);
1043 auto next = token;
1044 auto kind = peekAfter(next);
1045 if (kind == T.Colon || kind == T.LBrace)
1046 return false; // Anonymous enum.
1047 else if (kind == T.Identifier)
1049 kind = peekAfter(next);
1050 if (kind == T.Colon || kind == T.LBrace || kind == T.Semicolon)
1051 return false; // Named enum.
1053 return true; // Manifest enum.
1057 Declaration parseEnumDeclaration()
1059 skip(T.Enum);
1061 Identifier* enumName;
1062 Type baseType;
1063 EnumMemberDeclaration[] members;
1064 bool hasBody;
1066 enumName = optionalIdentifier();
1068 if (consumed(T.Colon))
1069 baseType = parseBasicType();
1071 if (enumName && consumed(T.Semicolon))
1073 else if (consumed(T.LBrace))
1075 auto leftBrace = this.prevToken;
1076 hasBody = true;
1077 while (token.kind != T.RBrace)
1079 auto begin = token;
1081 Type type;
1082 version(D2)
1084 bool success;
1085 try_({
1086 // Type Identifier = AssignExpression
1087 type = parseType(); // Set outer type variable.
1088 if (token.kind != T.Identifier)
1089 try_fail(), (type = null);
1090 return null;
1091 }, success);
1094 auto name = requireIdentifier(MSG.ExpectedEnumMember);
1095 Expression value;
1097 if (consumed(T.Assign))
1098 value = parseAssignExpression();
1100 members ~= set(new EnumMemberDeclaration(type, name, value), begin);
1102 if (!consumed(T.Comma))
1103 break;
1105 requireClosing(T.RBrace, leftBrace);
1107 else
1108 error2(MSG.ExpectedEnumBody, token);
1110 return new EnumDeclaration(enumName, baseType, members, hasBody);
1113 /// Wraps a declaration inside a template declaration.
1114 /// Params:
1115 /// begin = begin token of decl.
1116 /// name = name of decl.
1117 /// decl = the declaration to be wrapped.
1118 /// tparams = the template parameters.
1119 /// constraint = the constraint expression.
1120 TemplateDeclaration putInsideTemplateDeclaration(Token* begin,
1121 Identifier* name,
1122 Declaration decl,
1123 TemplateParameters tparams,
1124 Expression constraint)
1126 set(decl, begin);
1127 auto cd = new CompoundDeclaration;
1128 cd ~= decl;
1129 set(cd, begin);
1130 return new TemplateDeclaration(name, tparams, constraint, cd);
1133 Declaration parseClassDeclaration()
1135 auto begin = token;
1136 skip(T.Class);
1138 Identifier* className;
1139 TemplateParameters tparams;
1140 Expression constraint;
1141 BaseClassType[] bases;
1142 CompoundDeclaration decls;
1144 className = requireIdentifier(MSG.ExpectedClassName);
1146 if (token.kind == T.LParen)
1148 tparams = parseTemplateParameterList();
1149 version(D2) constraint = parseOptionalConstraint();
1152 if (token.kind == T.Colon)
1153 bases = parseBaseClasses();
1155 if (bases.length == 0 && consumed(T.Semicolon))
1157 else if (token.kind == T.LBrace)
1158 decls = parseDeclarationDefinitionsBody();
1159 else
1160 error2(MSG.ExpectedClassBody, token);
1162 Declaration d = new ClassDeclaration(className, /+tparams, +/bases, decls);
1163 if (tparams)
1164 d = putInsideTemplateDeclaration(begin, className, d, tparams, constraint);
1165 return d;
1168 BaseClassType[] parseBaseClasses(bool colonLeadsOff = true)
1170 colonLeadsOff && skip(T.Colon);
1172 BaseClassType[] bases;
1175 Protection prot = Protection.Public;
1176 switch (token.kind)
1178 case T.Identifier, T.Dot, T.Typeof: goto LparseBasicType;
1179 case T.Private: prot = Protection.Private; break;
1180 case T.Protected: prot = Protection.Protected; break;
1181 case T.Package: prot = Protection.Package; break;
1182 case T.Public: /*prot = Protection.Public;*/ break;
1183 default:
1184 error2(MID.ExpectedBaseClasses, token);
1185 return bases;
1187 nT(); // Skip protection attribute.
1188 LparseBasicType:
1189 auto begin = token;
1190 auto type = parseBasicType();
1191 bases ~= set(new BaseClassType(prot, type), begin);
1192 } while (consumed(T.Comma))
1193 return bases;
1196 Declaration parseInterfaceDeclaration()
1198 auto begin = token;
1199 skip(T.Interface);
1201 Identifier* name;
1202 TemplateParameters tparams;
1203 Expression constraint;
1204 BaseClassType[] bases;
1205 CompoundDeclaration decls;
1207 name = requireIdentifier(MSG.ExpectedInterfaceName);
1209 if (token.kind == T.LParen)
1211 tparams = parseTemplateParameterList();
1212 version(D2) constraint = parseOptionalConstraint();
1215 if (token.kind == T.Colon)
1216 bases = parseBaseClasses();
1218 if (bases.length == 0 && consumed(T.Semicolon))
1220 else if (token.kind == T.LBrace)
1221 decls = parseDeclarationDefinitionsBody();
1222 else
1223 error2(MSG.ExpectedInterfaceBody, token);
1225 Declaration d = new InterfaceDeclaration(name, /+tparams, +/bases, decls);
1226 if (tparams)
1227 d = putInsideTemplateDeclaration(begin, name, d, tparams, constraint);
1228 return d;
1231 Declaration parseStructOrUnionDeclaration()
1233 assert(token.kind == T.Struct || token.kind == T.Union);
1234 auto begin = token;
1235 skip(token.kind);
1237 Identifier* name;
1238 TemplateParameters tparams;
1239 Expression constraint;
1240 CompoundDeclaration decls;
1242 name = optionalIdentifier();
1244 if (name && token.kind == T.LParen)
1246 tparams = parseTemplateParameterList();
1247 version(D2) constraint = parseOptionalConstraint();
1250 if (name && consumed(T.Semicolon))
1252 else if (token.kind == T.LBrace)
1253 decls = parseDeclarationDefinitionsBody();
1254 else
1255 error2(begin.kind == T.Struct ?
1256 MSG.ExpectedStructBody :
1257 MSG.ExpectedUnionBody, token);
1259 Declaration d;
1260 if (begin.kind == T.Struct)
1262 auto sd = new StructDeclaration(name, /+tparams, +/decls);
1263 sd.setAlignSize(this.alignSize);
1264 d = sd;
1266 else
1267 d = new UnionDeclaration(name, /+tparams, +/decls);
1269 if (tparams)
1270 d = putInsideTemplateDeclaration(begin, name, d, tparams, constraint);
1271 return d;
1274 Declaration parseConstructorDeclaration()
1276 skip(T.This);
1277 auto parameters = parseParameterList();
1278 auto funcBody = parseFunctionBody();
1279 return new ConstructorDeclaration(parameters, funcBody);
1282 Declaration parseDestructorDeclaration()
1284 skip(T.Tilde);
1285 require(T.This);
1286 require(T.LParen);
1287 require(T.RParen);
1288 auto funcBody = parseFunctionBody();
1289 return new DestructorDeclaration(funcBody);
1292 Declaration parseStaticConstructorDeclaration()
1294 skip(T.Static);
1295 skip(T.This);
1296 require(T.LParen);
1297 require(T.RParen);
1298 auto funcBody = parseFunctionBody();
1299 return new StaticConstructorDeclaration(funcBody);
1302 Declaration parseStaticDestructorDeclaration()
1304 skip(T.Static);
1305 skip(T.Tilde);
1306 require(T.This);
1307 require(T.LParen);
1308 require(T.RParen);
1309 auto funcBody = parseFunctionBody();
1310 return new StaticDestructorDeclaration(funcBody);
1313 Declaration parseInvariantDeclaration()
1315 skip(T.Invariant);
1316 // Optional () for getting ready porting to D 2.0
1317 if (consumed(T.LParen))
1318 require(T.RParen);
1319 auto funcBody = parseFunctionBody();
1320 return new InvariantDeclaration(funcBody);
1323 Declaration parseUnittestDeclaration()
1325 skip(T.Unittest);
1326 auto funcBody = parseFunctionBody();
1327 return new UnittestDeclaration(funcBody);
1330 Token* parseIdentOrInt()
1332 if (consumed(T.Int32) || consumed(T.Identifier))
1333 return this.prevToken;
1334 error2(MSG.ExpectedIdentOrInt, token);
1335 return null;
1338 Token* parseVersionCondition()
1340 version(D2)
1342 if (consumed(T.Unittest))
1343 return this.prevToken;
1345 return parseIdentOrInt();
1348 Declaration parseDebugDeclaration()
1350 skip(T.Debug);
1352 Token* spec;
1353 Token* cond;
1354 Declaration decls, elseDecls;
1356 if (consumed(T.Assign))
1357 { // debug = Integer ;
1358 // debug = Identifier ;
1359 spec = parseIdentOrInt();
1360 require(T.Semicolon);
1362 else
1363 { // ( Condition )
1364 if (consumed(T.LParen))
1366 cond = parseIdentOrInt();
1367 require(T.RParen);
1369 // debug DeclarationsBlock
1370 // debug ( Condition ) DeclarationsBlock
1371 decls = parseDeclarationsBlock();
1372 // else DeclarationsBlock
1373 if (consumed(T.Else))
1374 elseDecls = parseDeclarationsBlock();
1377 return new DebugDeclaration(spec, cond, decls, elseDecls);
1380 Declaration parseVersionDeclaration()
1382 skip(T.Version);
1384 Token* spec;
1385 Token* cond;
1386 Declaration decls, elseDecls;
1388 if (consumed(T.Assign))
1389 { // version = Integer ;
1390 // version = Identifier ;
1391 spec = parseIdentOrInt();
1392 require(T.Semicolon);
1394 else
1395 { // ( Condition )
1396 require(T.LParen);
1397 cond = parseVersionCondition();
1398 require(T.RParen);
1399 // version ( Condition ) DeclarationsBlock
1400 decls = parseDeclarationsBlock();
1401 // else DeclarationsBlock
1402 if (consumed(T.Else))
1403 elseDecls = parseDeclarationsBlock();
1406 return new VersionDeclaration(spec, cond, decls, elseDecls);
1409 Declaration parseStaticIfDeclaration()
1411 skip(T.Static);
1412 skip(T.If);
1414 Expression condition;
1415 Declaration ifDecls, elseDecls;
1417 auto leftParen = token;
1418 require(T.LParen);
1419 condition = parseAssignExpression();
1420 requireClosing(T.RParen, leftParen);
1422 ifDecls = parseDeclarationsBlock();
1424 if (consumed(T.Else))
1425 elseDecls = parseDeclarationsBlock();
1427 return new StaticIfDeclaration(condition, ifDecls, elseDecls);
1430 Declaration parseStaticAssertDeclaration()
1432 skip(T.Static);
1433 skip(T.Assert);
1434 Expression condition, message;
1435 auto leftParen = token;
1436 require(T.LParen);
1437 condition = parseAssignExpression();
1438 if (consumed(T.Comma))
1439 message = parseAssignExpression();
1440 requireClosing(T.RParen, leftParen);
1441 require(T.Semicolon);
1442 return new StaticAssertDeclaration(condition, message);
1445 Declaration parseTemplateDeclaration()
1447 skip(T.Template);
1448 auto name = requireIdentifier(MSG.ExpectedTemplateName);
1449 auto tparams = parseTemplateParameterList();
1450 auto constraint = parseOptionalConstraint();
1451 auto decls = parseDeclarationDefinitionsBody();
1452 return new TemplateDeclaration(name, tparams, constraint, decls);
1455 Declaration parseNewDeclaration()
1457 skip(T.New);
1458 auto parameters = parseParameterList();
1459 auto funcBody = parseFunctionBody();
1460 return new NewDeclaration(parameters, funcBody);
1463 Declaration parseDeleteDeclaration()
1465 skip(T.Delete);
1466 auto parameters = parseParameterList();
1467 auto funcBody = parseFunctionBody();
1468 return new DeleteDeclaration(parameters, funcBody);
1471 Type parseTypeofType()
1473 auto begin = token;
1474 skip(T.Typeof);
1475 auto leftParen = token;
1476 require(T.LParen);
1477 Type type;
1478 switch (token.kind)
1480 version(D2)
1482 case T.Return:
1483 nT();
1484 type = new TypeofType();
1485 break;
1487 default:
1488 type = new TypeofType(parseExpression());
1490 requireClosing(T.RParen, leftParen);
1491 set(type, begin);
1492 return type;
1495 /// Parses a MixinDeclaration or MixinStatement.
1496 /// $(PRE
1497 /// TemplateMixin :=
1498 /// mixin ( AssignExpression ) ;
1499 /// mixin TemplateIdentifier ;
1500 /// mixin TemplateIdentifier MixinIdentifier ;
1501 /// mixin TemplateIdentifier !( TemplateArguments ) ;
1502 /// mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
1503 /// )
1504 Class parseMixin(Class)()
1506 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement));
1507 skip(T.Mixin);
1509 static if (is(Class == MixinDeclaration))
1511 if (consumed(T.LParen))
1513 auto leftParen = token;
1514 auto e = parseAssignExpression();
1515 requireClosing(T.RParen, leftParen);
1516 require(T.Semicolon);
1517 return new MixinDeclaration(e);
1521 auto begin = token;
1522 Expression e;
1523 Identifier* mixinIdent;
1525 if (consumed(T.Dot))
1526 e = set(new ModuleScopeExpression(parseIdentifierExpression()), begin);
1527 else
1528 e = parseIdentifierExpression();
1530 while (consumed(T.Dot))
1531 e = set(new DotExpression(e, parseIdentifierExpression()), begin);
1533 mixinIdent = optionalIdentifier();
1534 require(T.Semicolon);
1536 return new Class(e, mixinIdent);
1539 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1540 | Statement parsing methods |
1541 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1543 CompoundStatement parseStatements()
1545 auto begin = token;
1546 require(T.LBrace);
1547 auto statements = new CompoundStatement();
1548 while (token.kind != T.RBrace && token.kind != T.EOF)
1549 statements ~= parseStatement();
1550 requireClosing(T.RBrace, begin);
1551 return set(statements, begin);
1554 /// Parses a Statement.
1555 Statement parseStatement()
1557 auto begin = token;
1558 Statement s;
1559 Declaration d;
1561 if (token.isIntegralType)
1563 d = parseVariableOrFunction();
1564 goto LreturnDeclarationStatement;
1567 switch (token.kind)
1569 case T.Align:
1570 uint size = parseAlignAttribute();
1571 // Restrict align attribute to structs in parsing phase.
1572 StructDeclaration structDecl;
1573 if (token.kind == T.Struct)
1575 auto begin2 = token;
1576 structDecl = parseStructOrUnionDeclaration().to!(StructDeclaration);
1577 structDecl.setAlignSize(size);
1578 set(structDecl, begin2);
1580 else
1581 expected(T.Struct);
1583 d = new AlignDeclaration(size, structDecl ? cast(Declaration)structDecl : new CompoundDeclaration);
1584 goto LreturnDeclarationStatement;
1585 /+ Not applicable for statements.
1586 T.Private, T.Package, T.Protected, T.Public, T.Export,
1587 T.Deprecated, T.Override, T.Abstract,+/
1588 case T.Extern,
1589 T.Final,
1590 T.Const,
1591 T.Auto:
1592 //T.Scope
1593 //T.Static
1594 case_parseAttribute:
1595 s = parseAttributeStatement();
1596 return s;
1597 case T.Identifier:
1598 if (peekNext() == T.Colon)
1600 auto ident = token.ident;
1601 skip(T.Identifier); skip(T.Colon);
1602 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement());
1603 break;
1605 goto case T.Dot;
1606 case T.Dot, T.Typeof:
1607 bool success;
1608 d = try_(delegate {
1609 return parseVariableOrFunction(StorageClass.None,
1610 Protection.None,
1611 LinkageType.None, false, false);
1612 }, success
1614 if (success)
1615 goto LreturnDeclarationStatement; // Declaration
1616 else
1617 goto case_parseExpressionStatement; // Expression
1619 case T.If:
1620 s = parseIfStatement();
1621 break;
1622 case T.While:
1623 s = parseWhileStatement();
1624 break;
1625 case T.Do:
1626 s = parseDoWhileStatement();
1627 break;
1628 case T.For:
1629 s = parseForStatement();
1630 break;
1631 case T.Foreach, T.Foreach_reverse:
1632 s = parseForeachStatement();
1633 break;
1634 case T.Switch:
1635 s = parseSwitchStatement();
1636 break;
1637 case T.Case:
1638 s = parseCaseStatement();
1639 break;
1640 case T.Default:
1641 s = parseDefaultStatement();
1642 break;
1643 case T.Continue:
1644 s = parseContinueStatement();
1645 break;
1646 case T.Break:
1647 s = parseBreakStatement();
1648 break;
1649 case T.Return:
1650 s = parseReturnStatement();
1651 break;
1652 case T.Goto:
1653 s = parseGotoStatement();
1654 break;
1655 case T.With:
1656 s = parseWithStatement();
1657 break;
1658 case T.Synchronized:
1659 s = parseSynchronizedStatement();
1660 break;
1661 case T.Try:
1662 s = parseTryStatement();
1663 break;
1664 case T.Throw:
1665 s = parseThrowStatement();
1666 break;
1667 case T.Scope:
1668 if (peekNext() != T.LParen)
1669 goto case_parseAttribute;
1670 s = parseScopeGuardStatement();
1671 break;
1672 case T.Volatile:
1673 s = parseVolatileStatement();
1674 break;
1675 case T.Asm:
1676 s = parseAsmBlockStatement();
1677 break;
1678 case T.Pragma:
1679 s = parsePragmaStatement();
1680 break;
1681 case T.Mixin:
1682 if (peekNext() == T.LParen)
1683 goto case_parseExpressionStatement; // Parse as expression.
1684 s = parseMixin!(MixinStatement)();
1685 break;
1686 case T.Static:
1687 switch (peekNext())
1689 case T.If:
1690 s = parseStaticIfStatement();
1691 break;
1692 case T.Assert:
1693 s = parseStaticAssertStatement();
1694 break;
1695 default:
1696 goto case_parseAttribute;
1698 break;
1699 case T.Debug:
1700 s = parseDebugStatement();
1701 break;
1702 case T.Version:
1703 s = parseVersionStatement();
1704 break;
1705 // DeclDef
1706 case T.Alias, T.Typedef:
1707 d = parseDeclarationDefinition();
1708 goto LreturnDeclarationStatement;
1709 case T.Enum:
1710 version(D2)
1712 if (isEnumManifest())
1713 goto case_parseAttribute;
1715 d = parseEnumDeclaration();
1716 goto LreturnDeclarationStatement;
1717 case T.Class:
1718 d = parseClassDeclaration();
1719 goto LreturnDeclarationStatement;
1720 case T.Interface:
1721 d = parseInterfaceDeclaration();
1722 goto LreturnDeclarationStatement;
1723 case T.Struct, T.Union:
1724 d = parseStructOrUnionDeclaration();
1725 // goto LreturnDeclarationStatement;
1726 LreturnDeclarationStatement:
1727 set(d, begin);
1728 s = new DeclarationStatement(d);
1729 break;
1730 case T.LBrace:
1731 s = parseScopeStatement();
1732 break;
1733 case T.Semicolon:
1734 nT();
1735 s = new EmptyStatement();
1736 break;
1737 // Parse an ExpressionStatement:
1738 // Tokens that start a PrimaryExpression.
1739 // case T.Identifier, T.Dot, T.Typeof:
1740 case T.This:
1741 case T.Super:
1742 case T.Null:
1743 case T.True, T.False:
1744 // case T.Dollar:
1745 case T.Int32, T.Int64, T.Uint32, T.Uint64:
1746 case T.Float32, T.Float64, T.Float80,
1747 T.Imaginary32, T.Imaginary64, T.Imaginary80:
1748 case T.CharLiteral:
1749 case T.String:
1750 case T.LBracket:
1751 // case T.LBrace:
1752 case T.Function, T.Delegate:
1753 case T.Assert:
1754 // case T.Mixin:
1755 case T.Import:
1756 case T.Typeid:
1757 case T.Is:
1758 case T.LParen:
1759 case T.Traits: // D2.0
1760 // Tokens that can start a UnaryExpression:
1761 case T.AndBinary, T.PlusPlus, T.MinusMinus, T.Mul, T.Minus,
1762 T.Plus, T.Not, T.Tilde, T.New, T.Delete, T.Cast:
1763 case_parseExpressionStatement:
1764 s = new ExpressionStatement(parseExpression());
1765 require(T.Semicolon);
1766 break;
1767 default:
1768 if (token.isSpecialToken)
1769 goto case_parseExpressionStatement;
1771 if (token.kind != T.Dollar)
1772 // Assert that this isn't a valid expression.
1773 assert(delegate bool(){
1774 bool success;
1775 auto expression = try_(&parseExpression, success);
1776 return success;
1777 }() == false, "Didn't expect valid expression."
1780 // Report error: it's an illegal statement.
1781 s = new IllegalStatement();
1782 // Skip to next valid token.
1784 nT();
1785 while (!token.isStatementStart &&
1786 token.kind != T.RBrace &&
1787 token.kind != T.EOF)
1788 auto text = Token.textSpan(begin, this.prevToken);
1789 error(begin, MSG.IllegalStatement, text);
1791 assert(s !is null);
1792 set(s, begin);
1793 return s;
1796 /// $(PRE
1797 /// Parses a ScopeStatement.
1798 /// ScopeStatement :=
1799 /// NoScopeStatement
1800 /// )
1801 Statement parseScopeStatement()
1803 return new ScopeStatement(parseNoScopeStatement());
1806 /// $(PRE
1807 /// NoScopeStatement :=
1808 /// NonEmptyStatement
1809 /// BlockStatement
1810 /// BlockStatement :=
1811 /// { }
1812 /// { StatementList }
1813 /// )
1814 Statement parseNoScopeStatement()
1816 auto begin = token;
1817 Statement s;
1818 if (consumed(T.LBrace))
1820 auto ss = new CompoundStatement();
1821 while (token.kind != T.RBrace && token.kind != T.EOF)
1822 ss ~= parseStatement();
1823 requireClosing(T.RBrace, begin);
1824 s = set(ss, begin);
1826 else if (token.kind == T.Semicolon)
1828 error(token, MSG.ExpectedNonEmptyStatement);
1829 nT();
1830 s = set(new EmptyStatement(), begin);
1832 else
1833 s = parseStatement();
1834 return s;
1837 /// $(PRE
1838 /// NoScopeOrEmptyStatement :=
1839 /// ;
1840 /// NoScopeStatement
1841 /// )
1842 Statement parseNoScopeOrEmptyStatement()
1844 if (consumed(T.Semicolon))
1845 return set(new EmptyStatement(), this.prevToken);
1846 else
1847 return parseNoScopeStatement();
1850 Statement parseAttributeStatement()
1852 StorageClass stc, stc_tmp;
1853 LinkageType prev_linkageType;
1855 Declaration parse() // Nested function.
1857 auto begin = token;
1858 Declaration decl;
1859 switch (token.kind)
1861 case T.Extern:
1862 if (peekNext() != T.LParen)
1864 stc_tmp = StorageClass.Extern;
1865 goto Lcommon;
1868 nT();
1869 auto linkageType = parseLinkageType();
1870 checkLinkageType(prev_linkageType, linkageType, begin);
1872 decl = new LinkageDeclaration(linkageType, parse());
1873 break;
1874 case T.Static:
1875 stc_tmp = StorageClass.Static;
1876 goto Lcommon;
1877 case T.Final:
1878 stc_tmp = StorageClass.Final;
1879 goto Lcommon;
1880 case T.Const:
1881 version(D2)
1883 if (peekNext() == T.LParen)
1884 goto case_Declaration;
1886 stc_tmp = StorageClass.Const;
1887 goto Lcommon;
1888 version(D2)
1890 case T.Invariant: // D 2.0
1891 if (peekNext() == T.LParen)
1892 goto case_Declaration;
1893 stc_tmp = StorageClass.Invariant;
1894 goto Lcommon;
1895 case T.Enum: // D 2.0
1896 if (!isEnumManifest())
1897 { // A normal enum declaration.
1898 decl = parseEnumDeclaration();
1899 // NB: this must be similar to the code at the end of
1900 // parseDeclarationDefinition().
1901 decl.setProtection(this.protection);
1902 decl.setStorageClass(stc);
1903 set(decl, begin);
1904 return decl;
1906 // enum as StorageClass.
1907 stc_tmp = StorageClass.Manifest;
1908 goto Lcommon;
1910 case T.Auto:
1911 stc_tmp = StorageClass.Auto;
1912 goto Lcommon;
1913 case T.Scope:
1914 stc_tmp = StorageClass.Scope;
1915 goto Lcommon;
1916 Lcommon:
1917 // Issue error if redundant.
1918 if (stc & stc_tmp)
1919 error2(MID.RedundantStorageClass, token);
1920 else
1921 stc |= stc_tmp;
1923 nT();
1924 decl = new StorageClassDeclaration(stc_tmp, parse());
1925 break;
1926 case T.Class, T.Interface, T.Struct, T.Union, T.Alias, T.Typedef:
1927 decl = parseDeclarationDefinition();
1928 decl.setProtection(Protection.None);
1929 decl.setStorageClass(StorageClass.None);
1930 return decl;
1931 default:
1932 case_Declaration:
1933 return parseVariableOrFunction(stc, Protection.None, prev_linkageType, true);
1935 return set(decl, begin);
1937 return new DeclarationStatement(parse());
1940 Statement parseIfStatement()
1942 skip(T.If);
1944 Statement variable;
1945 Expression condition;
1946 Statement ifBody, elseBody;
1948 auto leftParen = token;
1949 require(T.LParen);
1951 Identifier* ident;
1952 auto begin = token; // For start of AutoDeclaration or normal Declaration.
1953 // auto Identifier = Expression
1954 if (consumed(T.Auto))
1956 ident = requireIdentifier(MSG.ExpectedVariableName);
1957 require(T.Assign);
1958 auto init = parseExpression();
1959 auto v = new VariablesDeclaration(null, [ident], [init]);
1960 set(v, begin.nextNWS);
1961 auto d = new StorageClassDeclaration(StorageClass.Auto, v);
1962 set(d, begin);
1963 variable = new DeclarationStatement(d);
1964 set(variable, begin);
1966 else
1967 { // Declarator = Expression
1968 Type parseDeclaratorAssign()
1970 auto type = parseDeclarator(ident);
1971 require(T.Assign);
1972 return type;
1974 bool success;
1975 auto type = try_(&parseDeclaratorAssign, success);
1976 if (success)
1978 auto init = parseExpression();
1979 auto v = new VariablesDeclaration(type, [ident], [init]);
1980 set(v, begin);
1981 variable = new DeclarationStatement(v);
1982 set(variable, begin);
1984 else
1985 condition = parseExpression();
1987 requireClosing(T.RParen, leftParen);
1988 ifBody = parseScopeStatement();
1989 if (consumed(T.Else))
1990 elseBody = parseScopeStatement();
1991 return new IfStatement(variable, condition, ifBody, elseBody);
1994 Statement parseWhileStatement()
1996 skip(T.While);
1997 auto leftParen = token;
1998 require(T.LParen);
1999 auto condition = parseExpression();
2000 requireClosing(T.RParen, leftParen);
2001 return new WhileStatement(condition, parseScopeStatement());
2004 Statement parseDoWhileStatement()
2006 skip(T.Do);
2007 auto doBody = parseScopeStatement();
2008 require(T.While);
2009 auto leftParen = token;
2010 require(T.LParen);
2011 auto condition = parseExpression();
2012 requireClosing(T.RParen, leftParen);
2013 return new DoWhileStatement(condition, doBody);
2016 Statement parseForStatement()
2018 skip(T.For);
2020 Statement init, forBody;
2021 Expression condition, increment;
2023 auto leftParen = token;
2024 require(T.LParen);
2025 if (!consumed(T.Semicolon))
2026 init = parseNoScopeStatement();
2027 if (token.kind != T.Semicolon)
2028 condition = parseExpression();
2029 require(T.Semicolon);
2030 if (token.kind != T.RParen)
2031 increment = parseExpression();
2032 requireClosing(T.RParen, leftParen);
2033 forBody = parseScopeStatement();
2034 return new ForStatement(init, condition, increment, forBody);
2037 Statement parseForeachStatement()
2039 assert(token.kind == T.Foreach || token.kind == T.Foreach_reverse);
2040 TOK tok = token.kind;
2041 nT();
2043 auto params = new Parameters;
2044 Expression e; // Aggregate or LwrExpression
2046 auto leftParen = token;
2047 require(T.LParen);
2048 auto paramsBegin = token;
2051 auto paramBegin = token;
2052 StorageClass stc;
2053 Type type;
2054 Identifier* ident;
2056 switch (token.kind)
2058 case T.Ref, T.Inout:
2059 stc = StorageClass.Ref;
2060 nT();
2061 // fall through
2062 case T.Identifier:
2063 auto next = peekNext();
2064 if (next == T.Comma || next == T.Semicolon || next == T.RParen)
2066 ident = requireIdentifier(MSG.ExpectedVariableName);
2067 break;
2069 // fall through
2070 default:
2071 type = parseDeclarator(ident);
2074 params ~= set(new Parameter(stc, type, ident, null), paramBegin);
2075 } while (consumed(T.Comma))
2076 set(params, paramsBegin);
2077 require(T.Semicolon);
2078 e = parseExpression();
2079 version(D2)
2080 { //Foreach (ForeachType; LwrExpression .. UprExpression ) ScopeStatement
2081 if (consumed(T.Slice))
2083 // if (params.length != 1)
2084 // error(MID.XYZ); // TODO: issue error msg
2085 auto upper = parseExpression();
2086 requireClosing(T.RParen, leftParen);
2087 auto forBody = parseScopeStatement();
2088 return new ForeachRangeStatement(tok, params, e, upper, forBody);
2091 // Foreach (ForeachTypeList; Aggregate) ScopeStatement
2092 requireClosing(T.RParen, leftParen);
2093 auto forBody = parseScopeStatement();
2094 return new ForeachStatement(tok, params, e, forBody);
2097 Statement parseSwitchStatement()
2099 skip(T.Switch);
2100 auto leftParen = token;
2101 require(T.LParen);
2102 auto condition = parseExpression();
2103 requireClosing(T.RParen, leftParen);
2104 auto switchBody = parseScopeStatement();
2105 return new SwitchStatement(condition, switchBody);
2108 /// Helper function for parsing the body of a default or case statement.
2109 Statement parseCaseOrDefaultBody()
2111 // This function is similar to parseNoScopeStatement()
2112 auto begin = token;
2113 auto s = new CompoundStatement();
2114 while (token.kind != T.Case &&
2115 token.kind != T.Default &&
2116 token.kind != T.RBrace &&
2117 token.kind != T.EOF)
2118 s ~= parseStatement();
2119 set(s, begin);
2120 return set(new ScopeStatement(s), begin);
2123 Statement parseCaseStatement()
2125 skip(T.Case);
2126 auto values = parseExpressionList();
2127 require(T.Colon);
2128 auto caseBody = parseCaseOrDefaultBody();
2129 return new CaseStatement(values, caseBody);
2132 Statement parseDefaultStatement()
2134 skip(T.Default);
2135 require(T.Colon);
2136 auto defaultBody = parseCaseOrDefaultBody();
2137 return new DefaultStatement(defaultBody);
2140 Statement parseContinueStatement()
2142 skip(T.Continue);
2143 auto ident = optionalIdentifier();
2144 require(T.Semicolon);
2145 return new ContinueStatement(ident);
2148 Statement parseBreakStatement()
2150 skip(T.Break);
2151 auto ident = optionalIdentifier();
2152 require(T.Semicolon);
2153 return new BreakStatement(ident);
2156 Statement parseReturnStatement()
2158 skip(T.Return);
2159 Expression expr;
2160 if (token.kind != T.Semicolon)
2161 expr = parseExpression();
2162 require(T.Semicolon);
2163 return new ReturnStatement(expr);
2166 Statement parseGotoStatement()
2168 skip(T.Goto);
2169 Identifier* ident;
2170 Expression caseExpr;
2171 switch (token.kind)
2173 case T.Case:
2174 ident = token.ident;
2175 nT();
2176 if (token.kind == T.Semicolon)
2177 break;
2178 caseExpr = parseExpression();
2179 break;
2180 case T.Default:
2181 ident = token.ident;
2182 nT();
2183 break;
2184 default:
2185 ident = requireIdentifier(MSG.ExpectedAnIdentifier);
2187 require(T.Semicolon);
2188 return new GotoStatement(ident, caseExpr);
2191 Statement parseWithStatement()
2193 skip(T.With);
2194 auto leftParen = token;
2195 require(T.LParen);
2196 auto expr = parseExpression();
2197 requireClosing(T.RParen, leftParen);
2198 return new WithStatement(expr, parseScopeStatement());
2201 Statement parseSynchronizedStatement()
2203 skip(T.Synchronized);
2204 Expression expr;
2205 if (consumed(T.LParen))
2207 auto leftParen = this.prevToken;
2208 expr = parseExpression();
2209 requireClosing(T.RParen, leftParen);
2211 return new SynchronizedStatement(expr, parseScopeStatement());
2214 Statement parseTryStatement()
2216 auto begin = token;
2217 skip(T.Try);
2219 auto tryBody = parseScopeStatement();
2220 CatchStatement[] catchBodies;
2221 FinallyStatement finBody;
2223 while (consumed(T.Catch))
2225 Parameter param;
2226 if (consumed(T.LParen))
2228 auto begin2 = token;
2229 Identifier* ident;
2230 auto type = parseDeclarator(ident, true);
2231 param = new Parameter(StorageClass.None, type, ident, null);
2232 set(param, begin2);
2233 require(T.RParen);
2235 catchBodies ~= set(new CatchStatement(param, parseNoScopeStatement()), begin);
2236 if (param is null)
2237 break; // This is a LastCatch
2238 begin = token;
2241 if (consumed(T.Finally))
2242 finBody = set(new FinallyStatement(parseNoScopeStatement()), prevToken);
2244 if (catchBodies.length == 0 && finBody is null)
2245 assert(begin.kind == T.Try), error(begin, MSG.MissingCatchOrFinally);
2247 return new TryStatement(tryBody, catchBodies, finBody);
2250 Statement parseThrowStatement()
2252 skip(T.Throw);
2253 auto expr = parseExpression();
2254 require(T.Semicolon);
2255 return new ThrowStatement(expr);
2258 Statement parseScopeGuardStatement()
2260 skip(T.Scope);
2261 skip(T.LParen);
2262 auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier);
2263 if (condition)
2264 switch (condition.idKind)
2266 case IDK.exit, IDK.success, IDK.failure:
2267 break;
2268 default:
2269 error2(MSG.InvalidScopeIdentifier, this.prevToken);
2271 require(T.RParen);
2272 Statement scopeBody;
2273 if (token.kind == T.LBrace)
2274 scopeBody = parseScopeStatement();
2275 else
2276 scopeBody = parseNoScopeStatement();
2277 return new ScopeGuardStatement(condition, scopeBody);
2280 Statement parseVolatileStatement()
2282 skip(T.Volatile);
2283 Statement volatileBody;
2284 if (token.kind == T.Semicolon)
2285 nT();
2286 else if (token.kind == T.LBrace)
2287 volatileBody = parseScopeStatement();
2288 else
2289 volatileBody = parseStatement();
2290 return new VolatileStatement(volatileBody);
2293 Statement parsePragmaStatement()
2295 skip(T.Pragma);
2297 Identifier* ident;
2298 Expression[] args;
2299 Statement pragmaBody;
2301 auto leftParen = token;
2302 require(T.LParen);
2303 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
2305 if (consumed(T.Comma))
2306 args = parseExpressionList();
2307 requireClosing(T.RParen, leftParen);
2309 pragmaBody = parseNoScopeOrEmptyStatement();
2311 return new PragmaStatement(ident, args, pragmaBody);
2314 Statement parseStaticIfStatement()
2316 skip(T.Static);
2317 skip(T.If);
2318 Expression condition;
2319 Statement ifBody, elseBody;
2321 auto leftParen = token;
2322 require(T.LParen);
2323 condition = parseExpression();
2324 requireClosing(T.RParen, leftParen);
2325 ifBody = parseNoScopeStatement();
2326 if (consumed(T.Else))
2327 elseBody = parseNoScopeStatement();
2328 return new StaticIfStatement(condition, ifBody, elseBody);
2331 Statement parseStaticAssertStatement()
2333 skip(T.Static);
2334 skip(T.Assert);
2335 Expression condition, message;
2337 require(T.LParen);
2338 condition = parseAssignExpression(); // Condition.
2339 if (consumed(T.Comma))
2340 message = parseAssignExpression(); // Error message.
2341 require(T.RParen);
2342 require(T.Semicolon);
2343 return new StaticAssertStatement(condition, message);
2346 Statement parseDebugStatement()
2348 skip(T.Debug);
2349 Token* cond;
2350 Statement debugBody, elseBody;
2352 // ( Condition )
2353 if (consumed(T.LParen))
2355 cond = parseIdentOrInt();
2356 require(T.RParen);
2358 // debug Statement
2359 // debug ( Condition ) Statement
2360 debugBody = parseNoScopeStatement();
2361 // else Statement
2362 if (consumed(T.Else))
2363 elseBody = parseNoScopeStatement();
2365 return new DebugStatement(cond, debugBody, elseBody);
2368 Statement parseVersionStatement()
2370 skip(T.Version);
2371 Token* cond;
2372 Statement versionBody, elseBody;
2374 // ( Condition )
2375 require(T.LParen);
2376 cond = parseVersionCondition();
2377 require(T.RParen);
2378 // version ( Condition ) Statement
2379 versionBody = parseNoScopeStatement();
2380 // else Statement
2381 if (consumed(T.Else))
2382 elseBody = parseNoScopeStatement();
2384 return new VersionStatement(cond, versionBody, elseBody);
2387 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2388 | Assembler parsing methods |
2389 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2391 /// Parses an AsmBlockStatement.
2392 Statement parseAsmBlockStatement()
2394 skip(T.Asm);
2395 auto leftBrace = token;
2396 require(T.LBrace);
2397 auto ss = new CompoundStatement;
2398 while (token.kind != T.RBrace && token.kind != T.EOF)
2399 ss ~= parseAsmStatement();
2400 requireClosing(T.RBrace, leftBrace);
2401 return new AsmBlockStatement(ss);
2404 Statement parseAsmStatement()
2406 auto begin = token;
2407 Statement s;
2408 Identifier* ident;
2409 switch (token.kind)
2411 // Keywords that are valid opcodes.
2412 case T.In, T.Int, T.Out:
2413 ident = token.ident;
2414 nT();
2415 goto LOpcode;
2416 case T.Identifier:
2417 ident = token.ident;
2418 nT();
2419 if (consumed(T.Colon))
2420 { // Identifier : AsmStatement
2421 s = new LabeledStatement(ident, parseAsmStatement());
2422 break;
2425 LOpcode:
2426 // Opcode ;
2427 // Opcode Operands ;
2428 // Opcode
2429 // Identifier
2430 Expression[] es;
2431 if (token.kind != T.Semicolon)
2433 es ~= parseAsmExpression();
2434 while (consumed(T.Comma))
2435 require(T.Semicolon);
2436 s = new AsmStatement(ident, es);
2437 break;
2438 case T.Align:
2439 // align Integer;
2440 nT();
2441 int number = -1;
2442 if (token.kind == T.Int32)
2443 (number = token.int_), skip(T.Int32);
2444 else
2445 error2(MSG.ExpectedIntegerAfterAlign, token);
2446 require(T.Semicolon);
2447 s = new AsmAlignStatement(number);
2448 break;
2449 case T.Semicolon:
2450 s = new EmptyStatement();
2451 nT();
2452 break;
2453 default:
2454 s = new IllegalAsmStatement();
2455 // Skip to next valid token.
2457 nT();
2458 while (!token.isAsmStatementStart &&
2459 token.kind != T.RBrace &&
2460 token.kind != T.EOF)
2461 auto text = Token.textSpan(begin, this.prevToken);
2462 error(begin, MSG.IllegalAsmStatement, text);
2464 set(s, begin);
2465 return s;
2468 Expression parseAsmExpression()
2470 auto begin = token;
2471 auto e = parseAsmOrOrExpression();
2472 if (consumed(T.Question))
2474 auto tok = this.prevToken;
2475 auto iftrue = parseAsmExpression();
2476 require(T.Colon);
2477 auto iffalse = parseAsmExpression();
2478 e = new CondExpression(e, iftrue, iffalse, tok);
2479 set(e, begin);
2481 // TODO: create AsmExpression that contains e?
2482 return e;
2485 Expression parseAsmOrOrExpression()
2487 alias parseAsmAndAndExpression parseNext;
2488 auto begin = token;
2489 auto e = parseNext();
2490 while (token.kind == T.OrLogical)
2492 auto tok = token;
2493 nT();
2494 e = new OrOrExpression(e, parseNext(), tok);
2495 set(e, begin);
2497 return e;
2500 Expression parseAsmAndAndExpression()
2502 alias parseAsmOrExpression parseNext;
2503 auto begin = token;
2504 auto e = parseNext();
2505 while (token.kind == T.AndLogical)
2507 auto tok = token;
2508 nT();
2509 e = new AndAndExpression(e, parseNext(), tok);
2510 set(e, begin);
2512 return e;
2515 Expression parseAsmOrExpression()
2517 alias parseAsmXorExpression parseNext;
2518 auto begin = token;
2519 auto e = parseNext();
2520 while (token.kind == T.OrBinary)
2522 auto tok = token;
2523 nT();
2524 e = new OrExpression(e, parseNext(), tok);
2525 set(e, begin);
2527 return e;
2530 Expression parseAsmXorExpression()
2532 alias parseAsmAndExpression parseNext;
2533 auto begin = token;
2534 auto e = parseNext();
2535 while (token.kind == T.Xor)
2537 auto tok = token;
2538 nT();
2539 e = new XorExpression(e, parseNext(), tok);
2540 set(e, begin);
2542 return e;
2545 Expression parseAsmAndExpression()
2547 alias parseAsmCmpExpression parseNext;
2548 auto begin = token;
2549 auto e = parseNext();
2550 while (token.kind == T.AndBinary)
2552 auto tok = token;
2553 nT();
2554 e = new AndExpression(e, parseNext(), tok);
2555 set(e, begin);
2557 return e;
2560 Expression parseAsmCmpExpression()
2562 alias parseAsmShiftExpression parseNext;
2563 auto begin = token;
2564 auto e = parseNext();
2566 auto operator = token;
2567 switch (operator.kind)
2569 case T.Equal, T.NotEqual:
2570 nT();
2571 e = new EqualExpression(e, parseNext(), operator);
2572 break;
2573 case T.LessEqual, T.Less, T.GreaterEqual, T.Greater:
2574 nT();
2575 e = new RelExpression(e, parseNext(), operator);
2576 break;
2577 default:
2578 return e;
2580 set(e, begin);
2581 return e;
2584 Expression parseAsmShiftExpression()
2586 alias parseAsmAddExpression parseNext;
2587 auto begin = token;
2588 auto e = parseNext();
2589 while (1)
2591 auto operator = token;
2592 switch (operator.kind)
2594 case T.LShift: nT(); e = new LShiftExpression(e, parseNext(), operator); break;
2595 case T.RShift: nT(); e = new RShiftExpression(e, parseNext(), operator); break;
2596 case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
2597 default:
2598 return e;
2600 set(e, begin);
2602 assert(0);
2605 Expression parseAsmAddExpression()
2607 alias parseAsmMulExpression parseNext;
2608 auto begin = token;
2609 auto e = parseNext();
2610 while (1)
2612 auto operator = token;
2613 switch (operator.kind)
2615 case T.Plus: nT(); e = new PlusExpression(e, parseNext(), operator); break;
2616 case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
2617 // Not allowed in asm
2618 //case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
2619 default:
2620 return e;
2622 set(e, begin);
2624 assert(0);
2627 Expression parseAsmMulExpression()
2629 alias parseAsmPostExpression parseNext;
2630 auto begin = token;
2631 auto e = parseNext();
2632 while (1)
2634 auto operator = token;
2635 switch (operator.kind)
2637 case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
2638 case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
2639 case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
2640 default:
2641 return e;
2643 set(e, begin);
2645 assert(0);
2648 Expression parseAsmPostExpression()
2650 auto begin = token;
2651 auto e = parseAsmUnaryExpression();
2652 while (consumed(T.LBracket))
2654 auto leftBracket = this.prevToken;
2655 e = new AsmPostBracketExpression(e, parseAsmExpression());
2656 requireClosing(T.RBracket, leftBracket);
2657 set(e, begin);
2659 return e;
2662 Expression parseAsmUnaryExpression()
2664 auto begin = token;
2665 Expression e;
2666 switch (token.kind)
2668 case T.Byte, T.Short, T.Int,
2669 T.Float, T.Double, T.Real:
2670 goto LAsmTypePrefix;
2671 case T.Identifier:
2672 switch (token.ident.idKind)
2674 case IDK.near, IDK.far,/* "byte", "short", "int",*/
2675 IDK.word, IDK.dword, IDK.qword/*, "float", "double", "real"*/:
2676 LAsmTypePrefix:
2677 nT();
2678 if (token.kind == T.Identifier && token.ident is Ident.ptr)
2679 skip(T.Identifier);
2680 else
2681 error2(MID.ExpectedButFound, "ptr", token);
2682 e = new AsmTypeExpression(parseAsmExpression());
2683 break;
2684 case IDK.offset:
2685 nT();
2686 e = new AsmOffsetExpression(parseAsmExpression());
2687 break;
2688 case IDK.seg:
2689 nT();
2690 e = new AsmSegExpression(parseAsmExpression());
2691 break;
2692 default:
2693 goto LparseAsmPrimaryExpression;
2695 break;
2696 case T.Minus:
2697 case T.Plus:
2698 nT();
2699 e = new SignExpression(parseAsmUnaryExpression());
2700 break;
2701 case T.Not:
2702 nT();
2703 e = new NotExpression(parseAsmUnaryExpression());
2704 break;
2705 case T.Tilde:
2706 nT();
2707 e = new CompExpression(parseAsmUnaryExpression());
2708 break;
2709 case T.Dot:
2710 nT();
2711 e = new ModuleScopeExpression(parseIdentifierExpression());
2712 while (consumed(TOK.Dot))
2714 e = new DotExpression(e, parseIdentifierExpression());
2715 set(e, begin);
2717 break;
2718 default:
2719 LparseAsmPrimaryExpression:
2720 e = parseAsmPrimaryExpression();
2721 return e;
2723 set(e, begin);
2724 return e;
2727 Expression parseAsmPrimaryExpression()
2729 auto begin = token;
2730 Expression e;
2731 switch (token.kind)
2733 case T.Int32, T.Int64, T.Uint32, T.Uint64:
2734 e = new IntExpression(token);
2735 nT();
2736 break;
2737 case T.Float32, T.Float64, T.Float80,
2738 T.Imaginary32, T.Imaginary64, T.Imaginary80:
2739 e = new RealExpression(token);
2740 nT();
2741 break;
2742 case T.Dollar:
2743 e = new DollarExpression();
2744 nT();
2745 break;
2746 case T.LBracket:
2747 // [ AsmExpression ]
2748 auto leftBracket = token;
2749 nT();
2750 e = parseAsmExpression();
2751 requireClosing(T.RBracket, leftBracket);
2752 e = new AsmBracketExpression(e);
2753 break;
2754 case T.Identifier:
2755 auto register = token.ident;
2756 switch (register.idKind)
2758 // __LOCAL_SIZE
2759 case IDK.__LOCAL_SIZE:
2760 nT();
2761 e = new AsmLocalSizeExpression();
2762 break;
2763 // Register
2764 case IDK.ST:
2765 nT();
2766 // (1) - (7)
2767 int number = -1;
2768 if (consumed(T.LParen))
2770 if (token.kind == T.Int32)
2771 (number = token.int_), skip(T.Int32);
2772 else
2773 expected(T.Int32);
2774 require(T.RParen);
2776 e = new AsmRegisterExpression(register, number);
2777 break;
2778 case IDK.FS:
2779 nT();
2780 // TODO: is the colon-number part optional?
2781 int number = -1;
2782 if (consumed(T.Colon))
2784 // :0, :4, :8
2785 if (token.kind == T.Int32)
2786 (number = token.int_), skip(T.Int32);
2787 if (number != 0 && number != 4 && number != 8)
2788 error2(MID.ExpectedButFound, "0, 4 or 8", token);
2790 e = new AsmRegisterExpression(register, number);
2791 break;
2792 case IDK.AL, IDK.AH, IDK.AX, IDK.EAX,
2793 IDK.BL, IDK.BH, IDK.BX, IDK.EBX,
2794 IDK.CL, IDK.CH, IDK.CX, IDK.ECX,
2795 IDK.DL, IDK.DH, IDK.DX, IDK.EDX,
2796 IDK.BP, IDK.EBP, IDK.SP, IDK.ESP,
2797 IDK.DI, IDK.EDI, IDK.SI, IDK.ESI,
2798 IDK.ES, IDK.CS, IDK.SS, IDK.DS, IDK.GS,
2799 IDK.CR0, IDK.CR2, IDK.CR3, IDK.CR4,
2800 IDK.DR0, IDK.DR1, IDK.DR2, IDK.DR3, IDK.DR6, IDK.DR7,
2801 IDK.TR3, IDK.TR4, IDK.TR5, IDK.TR6, IDK.TR7,
2802 IDK.MM0, IDK.MM1, IDK.MM2, IDK.MM3,
2803 IDK.MM4, IDK.MM5, IDK.MM6, IDK.MM7,
2804 IDK.XMM0, IDK.XMM1, IDK.XMM2, IDK.XMM3,
2805 IDK.XMM4, IDK.XMM5, IDK.XMM6, IDK.XMM7:
2806 nT();
2807 e = new AsmRegisterExpression(register);
2808 break;
2809 default:
2810 e = parseIdentifierExpression();
2811 while (consumed(TOK.Dot))
2813 e = new DotExpression(e, parseIdentifierExpression());
2814 set(e, begin);
2816 } // end of switch
2817 break;
2818 default:
2819 error2(MID.ExpectedButFound, "Expression", token);
2820 e = new IllegalExpression();
2821 if (!trying)
2822 { // Insert a dummy token and don't consume current one.
2823 begin = lexer.insertEmptyTokenBefore(token);
2824 this.prevToken = begin;
2827 set(e, begin);
2828 return e;
2831 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2832 | Expression parsing methods |
2833 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2835 /// Parses an Expression.
2836 Expression parseExpression()
2838 alias parseAssignExpression parseNext;
2839 auto begin = token;
2840 auto e = parseNext();
2841 while (token.kind == T.Comma)
2843 auto comma = token;
2844 nT();
2845 e = new CommaExpression(e, parseNext(), comma);
2846 set(e, begin);
2848 return e;
2851 Expression parseAssignExpression()
2853 alias parseAssignExpression parseNext;
2854 auto begin = token;
2855 auto e = parseCondExpression();
2856 switch (token.kind)
2858 case T.Assign:
2859 nT(); e = new AssignExpression(e, parseNext()); break;
2860 case T.LShiftAssign:
2861 nT(); e = new LShiftAssignExpression(e, parseNext()); break;
2862 case T.RShiftAssign:
2863 nT(); e = new RShiftAssignExpression(e, parseNext()); break;
2864 case T.URShiftAssign:
2865 nT(); e = new URShiftAssignExpression(e, parseNext()); break;
2866 case T.OrAssign:
2867 nT(); e = new OrAssignExpression(e, parseNext()); break;
2868 case T.AndAssign:
2869 nT(); e = new AndAssignExpression(e, parseNext()); break;
2870 case T.PlusAssign:
2871 nT(); e = new PlusAssignExpression(e, parseNext()); break;
2872 case T.MinusAssign:
2873 nT(); e = new MinusAssignExpression(e, parseNext()); break;
2874 case T.DivAssign:
2875 nT(); e = new DivAssignExpression(e, parseNext()); break;
2876 case T.MulAssign:
2877 nT(); e = new MulAssignExpression(e, parseNext()); break;
2878 case T.ModAssign:
2879 nT(); e = new ModAssignExpression(e, parseNext()); break;
2880 case T.XorAssign:
2881 nT(); e = new XorAssignExpression(e, parseNext()); break;
2882 case T.CatAssign:
2883 nT(); e = new CatAssignExpression(e, parseNext()); break;
2884 default:
2885 return e;
2887 set(e, begin);
2888 return e;
2891 Expression parseCondExpression()
2893 auto begin = token;
2894 auto e = parseOrOrExpression();
2895 if (token.kind == T.Question)
2897 auto tok = token;
2898 nT();
2899 auto iftrue = parseExpression();
2900 require(T.Colon);
2901 auto iffalse = parseCondExpression();
2902 e = new CondExpression(e, iftrue, iffalse, tok);
2903 set(e, begin);
2905 return e;
2908 Expression parseOrOrExpression()
2910 alias parseAndAndExpression parseNext;
2911 auto begin = token;
2912 auto e = parseNext();
2913 while (token.kind == T.OrLogical)
2915 auto tok = token;
2916 nT();
2917 e = new OrOrExpression(e, parseNext(), tok);
2918 set(e, begin);
2920 return e;
2923 Expression parseAndAndExpression()
2925 alias parseOrExpression parseNext;
2926 auto begin = token;
2927 auto e = parseNext();
2928 while (token.kind == T.AndLogical)
2930 auto tok = token;
2931 nT();
2932 e = new AndAndExpression(e, parseNext(), tok);
2933 set(e, begin);
2935 return e;
2938 Expression parseOrExpression()
2940 alias parseXorExpression parseNext;
2941 auto begin = token;
2942 auto e = parseNext();
2943 while (token.kind == T.OrBinary)
2945 auto tok = token;
2946 nT();
2947 e = new OrExpression(e, parseNext(), tok);
2948 set(e, begin);
2950 return e;
2953 Expression parseXorExpression()
2955 alias parseAndExpression parseNext;
2956 auto begin = token;
2957 auto e = parseNext();
2958 while (token.kind == T.Xor)
2960 auto tok = token;
2961 nT();
2962 e = new XorExpression(e, parseNext(), tok);
2963 set(e, begin);
2965 return e;
2968 Expression parseAndExpression()
2970 alias parseCmpExpression parseNext;
2971 auto begin = token;
2972 auto e = parseNext();
2973 while (token.kind == T.AndBinary)
2975 auto tok = token;
2976 nT();
2977 e = new AndExpression(e, parseNext(), tok);
2978 set(e, begin);
2980 return e;
2983 Expression parseCmpExpression()
2985 alias parseShiftExpression parseNext;
2986 auto begin = token;
2987 auto e = parseShiftExpression();
2989 auto operator = token;
2990 switch (operator.kind)
2992 case T.Equal, T.NotEqual:
2993 nT();
2994 e = new EqualExpression(e, parseNext(), operator);
2995 break;
2996 case T.Not:
2997 if (peekNext() != T.Is)
2998 break;
2999 nT();
3000 // fall through
3001 case T.Is:
3002 nT();
3003 e = new IdentityExpression(e, parseNext(), operator);
3004 break;
3005 case T.LessEqual, T.Less, T.GreaterEqual, T.Greater,
3006 T.Unordered, T.UorE, T.UorG, T.UorGorE,
3007 T.UorL, T.UorLorE, T.LorEorG, T.LorG:
3008 nT();
3009 e = new RelExpression(e, parseNext(), operator);
3010 break;
3011 case T.In:
3012 nT();
3013 e = new InExpression(e, parseNext(), operator);
3014 break;
3015 default:
3016 return e;
3018 set(e, begin);
3019 return e;
3022 Expression parseShiftExpression()
3024 alias parseAddExpression parseNext;
3025 auto begin = token;
3026 auto e = parseNext();
3027 while (1)
3029 auto operator = token;
3030 switch (operator.kind)
3032 case T.LShift: nT(); e = new LShiftExpression(e, parseNext(), operator); break;
3033 case T.RShift: nT(); e = new RShiftExpression(e, parseNext(), operator); break;
3034 case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
3035 default:
3036 return e;
3038 set(e, begin);
3040 assert(0);
3043 Expression parseAddExpression()
3045 alias parseMulExpression parseNext;
3046 auto begin = token;
3047 auto e = parseNext();
3048 while (1)
3050 auto operator = token;
3051 switch (operator.kind)
3053 case T.Plus: nT(); e = new PlusExpression(e, parseNext(), operator); break;
3054 case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
3055 case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
3056 default:
3057 return e;
3059 set(e, begin);
3061 assert(0);
3064 Expression parseMulExpression()
3066 alias parsePostExpression parseNext;
3067 auto begin = token;
3068 auto e = parseNext();
3069 while (1)
3071 auto operator = token;
3072 switch (operator.kind)
3074 case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
3075 case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
3076 case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
3077 default:
3078 return e;
3080 set(e, begin);
3082 assert(0);
3085 Expression parsePostExpression()
3087 auto begin = token;
3088 auto e = parseUnaryExpression();
3089 while (1)
3091 while (consumed(T.Dot))
3093 e = new DotExpression(e, parseNewOrIdentifierExpression());
3094 set(e, begin);
3097 switch (token.kind)
3099 case T.PlusPlus:
3100 e = new PostIncrExpression(e);
3101 break;
3102 case T.MinusMinus:
3103 e = new PostDecrExpression(e);
3104 break;
3105 case T.LParen:
3106 e = new CallExpression(e, parseArguments());
3107 goto Lset;
3108 case T.LBracket:
3109 // parse Slice- and IndexExpression
3110 auto leftBracket = token;
3111 nT();
3112 // [] is a SliceExpression
3113 if (token.kind == T.RBracket)
3115 e = new SliceExpression(e, null, null);
3116 break;
3119 Expression[] es = [parseAssignExpression()];
3121 // [ AssignExpression .. AssignExpression ]
3122 if (consumed(T.Slice))
3124 e = new SliceExpression(e, es[0], parseAssignExpression());
3125 requireClosing(T.RBracket, leftBracket);
3126 goto Lset;
3129 // [ ExpressionList ]
3130 if (consumed(T.Comma))
3131 es ~= parseExpressionList();
3132 requireClosing(T.RBracket, leftBracket);
3134 e = new IndexExpression(e, es);
3135 goto Lset;
3136 default:
3137 return e;
3139 nT();
3140 Lset: // Jumped here to skip nT().
3141 set(e, begin);
3143 assert(0);
3146 Expression parseUnaryExpression()
3148 auto begin = token;
3149 Expression e;
3150 switch (token.kind)
3152 case T.AndBinary:
3153 nT();
3154 e = new AddressExpression(parseUnaryExpression());
3155 break;
3156 case T.PlusPlus:
3157 nT();
3158 e = new PreIncrExpression(parseUnaryExpression());
3159 break;
3160 case T.MinusMinus:
3161 nT();
3162 e = new PreDecrExpression(parseUnaryExpression());
3163 break;
3164 case T.Mul:
3165 nT();
3166 e = new DerefExpression(parseUnaryExpression());
3167 break;
3168 case T.Minus:
3169 case T.Plus:
3170 nT();
3171 e = new SignExpression(parseUnaryExpression());
3172 break;
3173 case T.Not:
3174 nT();
3175 e = new NotExpression(parseUnaryExpression());
3176 break;
3177 case T.Tilde:
3178 nT();
3179 e = new CompExpression(parseUnaryExpression());
3180 break;
3181 case T.New:
3182 e = parseNewExpression();
3183 return e;
3184 case T.Delete:
3185 nT();
3186 e = new DeleteExpression(parseUnaryExpression());
3187 break;
3188 case T.Cast:
3189 requireNext(T.LParen);
3190 Type type;
3191 switch (token.kind)
3193 version(D2)
3195 auto begin2 = token;
3196 case T.Const:
3197 type = new ConstType(null);
3198 goto case_break;
3199 case T.Invariant:
3200 type = new InvariantType(null);
3201 case_break:
3202 nT();
3203 set(type, begin2);
3204 break;
3206 default:
3207 type = parseType();
3209 require(T.RParen);
3210 e = new CastExpression(parseUnaryExpression(), type);
3211 break;
3212 case T.LParen:
3213 // ( Type ) . Identifier
3214 Type parseType_()
3216 skip(T.LParen);
3217 auto type = parseType();
3218 require(T.RParen);
3219 require(T.Dot);
3220 return type;
3222 bool success;
3223 auto type = try_(&parseType_, success);
3224 if (success)
3226 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
3227 e = new TypeDotIdExpression(type, ident);
3228 break;
3230 goto default;
3231 case T.Dot:
3232 nT();
3233 e = new ModuleScopeExpression(parseIdentifierExpression());
3234 break;
3235 default:
3236 e = parsePrimaryExpression();
3237 return e;
3239 assert(e !is null);
3240 set(e, begin);
3241 return e;
3244 /// $(PRE
3245 /// IdentifierExpression :=
3246 /// Identifier
3247 /// TemplateInstance
3248 /// TemplateInstance :=
3249 /// Identifier !( TemplateArguments )
3250 /// )
3251 Expression parseIdentifierExpression()
3253 auto begin = token;
3254 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
3255 Expression e;
3256 // Peek for '(' to avoid matching: id !is id
3257 if (token.kind == T.Not && peekNext() == T.LParen)
3258 { // Identifier !( TemplateArguments )
3259 skip(T.Not);
3260 auto tparams = parseTemplateArguments();
3261 e = new TemplateInstanceExpression(ident, tparams);
3263 else // Identifier
3264 e = new IdentifierExpression(ident);
3265 return set(e, begin);
3268 Expression parseNewOrIdentifierExpression()
3270 return token.kind == T.New ? parseNewExpression() : parseIdentifierExpression();
3273 Expression parsePrimaryExpression()
3275 auto begin = token;
3276 Expression e;
3277 switch (token.kind)
3279 case T.Identifier:
3280 e = parseIdentifierExpression();
3281 return e;
3282 case T.Typeof:
3283 e = new TypeofExpression(parseTypeofType());
3284 break;
3285 case T.This:
3286 nT();
3287 e = new ThisExpression();
3288 break;
3289 case T.Super:
3290 nT();
3291 e = new SuperExpression();
3292 break;
3293 case T.Null:
3294 nT();
3295 e = new NullExpression();
3296 break;
3297 case T.True, T.False:
3298 nT();
3299 e = new BoolExpression(token.kind == T.True);
3300 break;
3301 case T.Dollar:
3302 nT();
3303 e = new DollarExpression();
3304 break;
3305 case T.Int32, T.Int64, T.Uint32, T.Uint64:
3306 e = new IntExpression(token);
3307 nT();
3308 break;
3309 case T.Float32, T.Float64, T.Float80,
3310 T.Imaginary32, T.Imaginary64, T.Imaginary80:
3311 e = new RealExpression(token);
3312 nT();
3313 break;
3314 case T.CharLiteral:
3315 e = new CharExpression(token.dchar_);
3316 nT();
3317 break;
3318 case T.String:
3319 char[] str = token.str;
3320 char postfix = token.pf;
3321 nT();
3322 while (token.kind == T.String)
3324 /+if (postfix == 0)
3325 postfix = token.pf;
3326 else+/
3327 if (token.pf && token.pf != postfix)
3328 error(token, MSG.StringPostfixMismatch);
3329 str.length = str.length - 1; // Exclude '\0'.
3330 str ~= token.str;
3331 nT();
3333 switch (postfix)
3335 case 'w':
3336 if (hasInvalidUTF8(str, begin))
3337 goto default;
3338 e = new StringExpression(dil.Unicode.toUTF16(str)); break;
3339 case 'd':
3340 if (hasInvalidUTF8(str, begin))
3341 goto default;
3342 e = new StringExpression(dil.Unicode.toUTF32(str)); break;
3343 case 'c':
3344 default:
3345 // No checking done to allow for binary data.
3346 e = new StringExpression(str); break;
3348 break;
3349 case T.LBracket:
3350 Expression[] values;
3352 nT();
3353 if (!consumed(T.RBracket))
3355 e = parseAssignExpression();
3356 if (consumed(T.Colon))
3357 goto LparseAssocArray;
3358 if (consumed(T.Comma))
3359 values = [e] ~ parseExpressionList();
3360 requireClosing(T.RBracket, begin);
3363 e = new ArrayLiteralExpression(values);
3364 break;
3366 LparseAssocArray:
3367 Expression[] keys = [e];
3369 goto LenterLoop;
3372 keys ~= parseAssignExpression();
3373 require(T.Colon);
3374 LenterLoop:
3375 values ~= parseAssignExpression();
3376 } while (consumed(T.Comma))
3377 requireClosing(T.RBracket, begin);
3378 e = new AArrayLiteralExpression(keys, values);
3379 break;
3380 case T.LBrace:
3381 // DelegateLiteral := { Statements }
3382 auto funcBody = parseFunctionBody();
3383 e = new FunctionLiteralExpression(funcBody);
3384 break;
3385 case T.Function, T.Delegate:
3386 // FunctionLiteral := ("function"|"delegate") Type? "(" ArgumentList ")" FunctionBody
3387 nT(); // Skip function or delegate keyword.
3388 Type returnType;
3389 Parameters parameters;
3390 if (token.kind != T.LBrace)
3392 if (token.kind != T.LParen) // Optional return type
3393 returnType = parseType();
3394 parameters = parseParameterList();
3396 auto funcBody = parseFunctionBody();
3397 e = new FunctionLiteralExpression(returnType, parameters, funcBody);
3398 break;
3399 case T.Assert:
3400 Expression msg;
3401 requireNext(T.LParen);
3402 e = parseAssignExpression();
3403 if (consumed(T.Comma))
3404 msg = parseAssignExpression();
3405 require(T.RParen);
3406 e = new AssertExpression(e, msg);
3407 break;
3408 case T.Mixin:
3409 requireNext(T.LParen);
3410 e = parseAssignExpression();
3411 require(T.RParen);
3412 e = new MixinExpression(e);
3413 break;
3414 case T.Import:
3415 requireNext(T.LParen);
3416 e = parseAssignExpression();
3417 require(T.RParen);
3418 e = new ImportExpression(e);
3419 break;
3420 case T.Typeid:
3421 requireNext(T.LParen);
3422 auto type = parseType();
3423 require(T.RParen);
3424 e = new TypeidExpression(type);
3425 break;
3426 case T.Is:
3427 nT();
3428 auto leftParen = token;
3429 require(T.LParen);
3431 Type type, specType;
3432 Identifier* ident; // optional Identifier
3433 Token* opTok, specTok;
3435 type = parseDeclarator(ident, true);
3437 switch (token.kind)
3439 case T.Colon, T.Equal:
3440 opTok = token;
3441 nT();
3442 switch (token.kind)
3444 case T.Typedef,
3445 T.Struct,
3446 T.Union,
3447 T.Class,
3448 T.Interface,
3449 T.Enum,
3450 T.Function,
3451 T.Delegate,
3452 T.Super,
3453 T.Return:
3454 case_Const_Invariant:
3455 specTok = token;
3456 nT();
3457 break;
3458 case T.Const, T.Invariant:
3459 if (peekNext() != T.LParen)
3460 goto case_Const_Invariant;
3461 // Fall through. It's a type.
3462 default:
3463 specType = parseType();
3465 default:
3468 TemplateParameters tparams;
3469 version(D2)
3471 // is ( Type Identifier : TypeSpecialization , TemplateParameterList )
3472 // is ( Type Identifier == TypeSpecialization , TemplateParameterList )
3473 if (ident && specType && token.kind == T.Comma)
3474 tparams = parseTemplateParameterList2();
3476 requireClosing(T.RParen, leftParen);
3477 e = new IsExpression(type, ident, opTok, specTok, specType, tparams);
3478 break;
3479 case T.LParen:
3480 if (tokenAfterParenIs(T.LBrace)) // Check for "(...) {"
3481 { // ( ParameterList ) FunctionBody
3482 auto parameters = parseParameterList();
3483 auto funcBody = parseFunctionBody();
3484 e = new FunctionLiteralExpression(null, parameters, funcBody);
3486 else
3487 { // ( Expression )
3488 auto leftParen = token;
3489 skip(T.LParen);
3490 e = parseExpression();
3491 requireClosing(T.RParen, leftParen);
3492 e = new ParenExpression(e);
3494 break;
3495 version(D2)
3497 case T.Traits:
3498 requireNext(T.LParen);
3499 auto id = requireIdentifier(MSG.ExpectedAnIdentifier);
3500 TemplateArguments args;
3501 if (token.kind == T.Comma)
3502 args = parseTemplateArguments2();
3503 else
3504 require(T.RParen);
3505 e = new TraitsExpression(id, args);
3506 break;
3508 default:
3509 if (token.isIntegralType)
3510 { // IntegralType . Identifier
3511 auto type = new IntegralType(token.kind);
3512 nT();
3513 set(type, begin);
3514 require(T.Dot);
3515 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
3516 e = new TypeDotIdExpression(type, ident);
3518 else if (token.isSpecialToken)
3520 e = new SpecialTokenExpression(token);
3521 nT();
3523 else
3525 error2(MID.ExpectedButFound, "Expression", token);
3526 e = new IllegalExpression();
3527 if (!trying)
3528 { // Insert a dummy token and don't consume current one.
3529 begin = lexer.insertEmptyTokenBefore(token);
3530 this.prevToken = begin;
3534 set(e, begin);
3535 return e;
3538 Expression parseNewExpression(/*Expression e*/)
3540 auto begin = token;
3541 skip(T.New);
3543 Expression[] newArguments;
3544 Expression[] ctorArguments;
3546 if (token.kind == T.LParen)
3547 newArguments = parseArguments();
3549 // NewAnonClassExpression:
3550 // new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
3551 if (consumed(T.Class))
3553 if (token.kind == T.LParen)
3554 ctorArguments = parseArguments();
3556 BaseClassType[] bases = token.kind != T.LBrace ? parseBaseClasses(false) : null ;
3558 auto decls = parseDeclarationDefinitionsBody();
3559 return set(new NewAnonClassExpression(/*e, */newArguments, bases, ctorArguments, decls), begin);
3562 // NewExpression:
3563 // NewArguments Type [ AssignExpression ]
3564 // NewArguments Type ( ArgumentList )
3565 // NewArguments Type
3566 auto type = parseType();
3568 if (token.kind == T.LParen)
3569 ctorArguments = parseArguments();
3571 return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin);
3574 /// Parses a Type.
3575 Type parseType()
3577 return parseBasicType2(parseBasicType());
3580 Type parseIdentifierType()
3582 auto begin = token;
3583 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
3584 Type t;
3585 if (consumed(T.Not)) // Identifier !( TemplateArguments )
3586 t = new TemplateInstanceType(ident, parseTemplateArguments());
3587 else // Identifier
3588 t = new IdentifierType(ident);
3589 return set(t, begin);
3592 Type parseQualifiedType()
3594 auto begin = token;
3595 Type type;
3596 if (token.kind == T.Dot)
3597 type = set(new ModuleScopeType(), begin, begin);
3598 else if (token.kind == T.Typeof)
3599 type = parseTypeofType();
3600 else
3601 type = parseIdentifierType();
3603 while (consumed(T.Dot))
3604 type = set(new QualifiedType(type, parseIdentifierType()), begin);
3605 return type;
3608 Type parseBasicType()
3610 auto begin = token;
3611 Type t;
3613 if (token.isIntegralType)
3615 t = new IntegralType(token.kind);
3616 nT();
3618 else
3619 switch (token.kind)
3621 case T.Identifier, T.Typeof, T.Dot:
3622 t = parseQualifiedType();
3623 return t;
3624 version(D2)
3626 case T.Const:
3627 // const ( Type )
3628 requireNext(T.LParen);
3629 t = parseType();
3630 require(T.RParen);
3631 t = new ConstType(t);
3632 break;
3633 case T.Invariant:
3634 // invariant ( Type )
3635 requireNext(T.LParen);
3636 t = parseType();
3637 require(T.RParen);
3638 t = new InvariantType(t);
3639 break;
3640 } // version(D2)
3641 default:
3642 error2(MID.ExpectedButFound, "BasicType", token);
3643 t = new IllegalType();
3644 nT();
3646 return set(t, begin);
3649 Type parseBasicType2(Type t)
3651 while (1)
3653 auto begin = token;
3654 switch (token.kind)
3656 case T.Mul:
3657 t = new PointerType(t);
3658 nT();
3659 break;
3660 case T.LBracket:
3661 t = parseArrayType(t);
3662 continue;
3663 case T.Function, T.Delegate:
3664 TOK tok = token.kind;
3665 nT();
3666 auto parameters = parseParameterList();
3667 if (tok == T.Function)
3668 t = new FunctionType(t, parameters);
3669 else
3670 t = new DelegateType(t, parameters);
3671 break;
3672 default:
3673 return t;
3675 set(t, begin);
3677 assert(0);
3680 /// Returns true if the token after the closing parenthesis
3681 /// matches the searched kind.
3682 bool tokenAfterParenIs(TOK kind)
3684 assert(token.kind == T.LParen);
3685 auto next = token;
3686 return skipParens(next) == kind;
3689 /// ditto
3690 bool tokenAfterParenIs(TOK kind, ref Token* next)
3692 assert(next !is null && next.kind == T.LParen);
3693 return skipParens(next) == kind;
3696 /// Skips to the token behind the closing parenthesis.
3697 /// Takes nested parentheses into account.
3698 TOK skipParens(ref Token* next)
3700 assert(next !is null && next.kind == T.LParen);
3701 // We count nested parentheses tokens because template types, typeof etc.
3702 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y)
3703 uint level = 1;
3704 Loop:
3705 while (1)
3706 switch (peekAfter(next))
3708 case T.LParen:
3709 ++level;
3710 break;
3711 case T.RParen:
3712 if (--level == 0)
3713 return peekAfter(next); // Closing parenthesis found.
3714 break;
3715 case T.EOF:
3716 return T.EOF;
3717 default:
3719 assert(0, "should be unreachable");
3722 /// Parse the array types after the declarator (C-style.) E.g.: int a[]
3723 Type parseDeclaratorSuffix(Type lhsType)
3725 // The Type chain should be as follows:
3726 // int[3]* Identifier [][32]
3727 // <- <- -> -.
3728 // ^-----------------´
3729 // Resulting chain: [][32]*[3]int
3730 Type parseNext() // Nested function required to accomplish this.
3732 if (token.kind != T.LBracket)
3733 return lhsType; // Break recursion; return Type on the left hand side of the Identifier.
3735 auto begin = token;
3736 Type t;
3737 skip(T.LBracket);
3738 if (consumed(T.RBracket))
3739 t = new ArrayType(parseNext()); // [ ]
3740 else
3742 bool success;
3743 Type parseAAType()
3745 auto type = parseType();
3746 require(T.RBracket);
3747 return type;
3749 auto assocType = try_(&parseAAType, success);
3750 if (success)
3751 t = new ArrayType(parseNext(), assocType); // [ Type ]
3752 else
3754 Expression e = parseExpression(), e2;
3755 if (consumed(T.Slice))
3756 e2 = parseExpression();
3757 requireClosing(T.RBracket, begin);
3758 t = new ArrayType(parseNext(), e, e2); // [ Expression .. Expression ]
3761 set(t, begin);
3762 return t;
3764 return parseNext();
3767 Type parseArrayType(Type t)
3769 auto begin = token;
3770 skip(T.LBracket);
3771 if (consumed(T.RBracket))
3772 t = new ArrayType(t);
3773 else
3775 bool success;
3776 Type parseAAType()
3778 auto type = parseType();
3779 require(T.RBracket);
3780 return type;
3782 auto assocType = try_(&parseAAType, success);
3783 if (success)
3784 t = new ArrayType(t, assocType);
3785 else
3787 Expression e = parseExpression(), e2;
3788 if (consumed(T.Slice))
3789 e2 = parseExpression();
3790 requireClosing(T.RBracket, begin);
3791 t = new ArrayType(t, e, e2);
3794 set(t, begin);
3795 return t;
3798 Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList)
3800 assert(type !is null);
3801 auto begin = token;
3802 skip(T.LParen);
3804 type = parseBasicType2(type);
3805 if (token.kind == T.LParen)
3806 { // Can be nested.
3807 type = parseCFunctionPointerType(type, ident, true);
3809 else if (token.kind == T.Identifier)
3810 { // The identifier of the function pointer and the declaration.
3811 ident = token.ident;
3812 nT();
3813 type = parseDeclaratorSuffix(type);
3815 requireClosing(T.RParen, begin);
3817 Parameters params;
3818 if (optionalParamList)
3819 params = token.kind == T.LParen ? parseParameterList() : null;
3820 else
3821 params = parseParameterList();
3823 type = new CFuncPointerType(type, params);
3824 return set(type, begin);
3827 Type parseDeclarator(ref Identifier* ident, bool identOptional = false)
3829 auto t = parseType();
3831 if (token.kind == T.LParen)
3832 t = parseCFunctionPointerType(t, ident, true);
3833 else if (token.kind == T.Identifier)
3835 ident = token.ident;
3836 nT();
3837 t = parseDeclaratorSuffix(t);
3840 if (ident is null && !identOptional)
3841 error2(MSG.ExpectedDeclaratorIdentifier, token);
3843 return t;
3846 /// Parses a list of AssignExpressions.
3847 /// $(PRE
3848 /// ExpressionList :=
3849 /// AssignExpression
3850 /// AssignExpression , ExpressionList
3851 /// )
3852 Expression[] parseExpressionList()
3854 Expression[] expressions;
3856 expressions ~= parseAssignExpression();
3857 while(consumed(T.Comma))
3858 return expressions;
3861 /// Parses a list of Arguments.
3862 /// $(PRE
3863 /// Arguments :=
3864 /// ( )
3865 /// ( ExpressionList )
3866 /// )
3867 Expression[] parseArguments()
3869 auto leftParen = token;
3870 skip(T.LParen);
3871 Expression[] args;
3872 if (token.kind != T.RParen)
3873 args = parseExpressionList();
3874 requireClosing(T.RParen, leftParen);
3875 return args;
3878 /// Parses a ParameterList.
3879 Parameters parseParameterList()
3880 out(params)
3882 if (params.length > 1)
3883 foreach (param; params.items[0..$-1])
3885 if (param.isVariadic())
3886 assert(0, "variadic arguments can only appear at the end of the parameter list.");
3889 body
3891 auto begin = token;
3892 require(T.LParen);
3894 auto params = new Parameters();
3896 if (consumed(T.RParen))
3897 return set(params, begin);
3901 auto paramBegin = token;
3902 StorageClass stc, stc_;
3903 Type type;
3904 Identifier* ident;
3905 Expression defValue;
3907 void pushParameter()
3909 params ~= set(new Parameter(stc, type, ident, defValue), paramBegin);
3912 if (consumed(T.Ellipses))
3914 stc = StorageClass.Variadic;
3915 pushParameter(); // type, ident and defValue will be null.
3916 break;
3919 while (1)
3920 { // Parse storage classes.
3921 switch (token.kind)
3923 version(D2)
3925 case T.Invariant: // D2.0
3926 if (peekNext() == T.LParen)
3927 break;
3928 stc_ = StorageClass.Invariant;
3929 goto Lcommon;
3930 case T.Const: // D2.0
3931 if (peekNext() == T.LParen)
3932 break;
3933 stc_ = StorageClass.Const;
3934 goto Lcommon;
3935 case T.Final: // D2.0
3936 stc_ = StorageClass.Final;
3937 goto Lcommon;
3938 case T.Scope: // D2.0
3939 stc_ = StorageClass.Scope;
3940 goto Lcommon;
3941 case T.Static: // D2.0
3942 stc_ = StorageClass.Static;
3943 goto Lcommon;
3945 case T.In:
3946 stc_ = StorageClass.In;
3947 goto Lcommon;
3948 case T.Out:
3949 stc_ = StorageClass.Out;
3950 goto Lcommon;
3951 case T.Inout, T.Ref:
3952 stc_ = StorageClass.Ref;
3953 goto Lcommon;
3954 case T.Lazy:
3955 stc_ = StorageClass.Lazy;
3956 goto Lcommon;
3957 Lcommon:
3958 // Check for redundancy.
3959 if (stc & stc_)
3960 error2(MID.RedundantStorageClass, token);
3961 else
3962 stc |= stc_;
3963 nT();
3964 version(D2)
3965 continue;
3966 else
3967 break; // In D1.0 the grammar only allows one storage class.
3968 default:
3970 break; // Break out of inner loop.
3972 type = parseDeclarator(ident, true);
3974 if (consumed(T.Assign))
3975 defValue = parseAssignExpression();
3977 if (consumed(T.Ellipses))
3979 stc |= StorageClass.Variadic;
3980 pushParameter();
3981 break;
3983 pushParameter();
3985 } while (consumed(T.Comma))
3986 requireClosing(T.RParen, begin);
3987 return set(params, begin);
3990 TemplateArguments parseTemplateArguments()
3992 TemplateArguments targs;
3993 auto leftParen = token;
3994 require(T.LParen);
3995 if (token.kind != T.RParen)
3996 targs = parseTemplateArguments_();
3997 requireClosing(T.RParen, leftParen);
3998 return targs;
4001 version(D2)
4003 TemplateArguments parseTemplateArguments2()
4005 skip(T.Comma);
4006 TemplateArguments targs;
4007 if (token.kind != T.RParen)
4008 targs = parseTemplateArguments_();
4009 else
4010 error(token, MSG.ExpectedTypeOrExpression);
4011 require(T.RParen);
4012 return targs;
4014 } // version(D2)
4016 TemplateArguments parseTemplateArguments_()
4018 auto begin = token;
4019 auto targs = new TemplateArguments;
4022 Type parseType_()
4024 auto type = parseType();
4025 if (token.kind == T.Comma || token.kind == T.RParen)
4026 return type;
4027 try_fail();
4028 return null;
4030 bool success;
4031 auto typeArgument = try_(&parseType_, success);
4032 if (success)
4033 // TemplateArgument:
4034 // Type
4035 // Symbol
4036 targs ~= typeArgument;
4037 else
4038 // TemplateArgument:
4039 // AssignExpression
4040 targs ~= parseAssignExpression();
4041 } while (consumed(T.Comma))
4042 set(targs, begin);
4043 return targs;
4046 /// if ( ConstraintExpression )
4047 Expression parseOptionalConstraint()
4049 if (!consumed(T.If))
4050 return null;
4051 require(T.LParen);
4052 auto e = parseExpression();
4053 require(T.RParen);
4054 return e;
4057 TemplateParameters parseTemplateParameterList()
4059 auto begin = token;
4060 auto tparams = new TemplateParameters;
4061 require(T.LParen);
4062 if (token.kind != T.RParen)
4063 parseTemplateParameterList_(tparams);
4064 requireClosing(T.RParen, begin);
4065 return set(tparams, begin);
4068 version(D2)
4070 TemplateParameters parseTemplateParameterList2()
4072 skip(T.Comma);
4073 auto begin = token;
4074 auto tparams = new TemplateParameters;
4075 if (token.kind != T.RParen)
4076 parseTemplateParameterList_(tparams);
4077 else
4078 error(token, MSG.ExpectedTemplateParameters);
4079 return set(tparams, begin);
4081 } // version(D2)
4083 /// Parses template parameters.
4084 void parseTemplateParameterList_(TemplateParameters tparams)
4088 auto paramBegin = token;
4089 TemplateParameter tp;
4090 Identifier* ident;
4091 Type specType, defType;
4093 void parseSpecAndOrDefaultType()
4095 // : SpecializationType
4096 if (consumed(T.Colon))
4097 specType = parseType();
4098 // = DefaultType
4099 if (consumed(T.Assign))
4100 defType = parseType();
4103 switch (token.kind)
4105 case T.Alias:
4106 // TemplateAliasParameter:
4107 // alias Identifier
4108 skip(T.Alias);
4109 ident = requireIdentifier(MSG.ExpectedAliasTemplateParam);
4110 parseSpecAndOrDefaultType();
4111 tp = new TemplateAliasParameter(ident, specType, defType);
4112 break;
4113 case T.Identifier:
4114 ident = token.ident;
4115 switch (peekNext())
4117 case T.Ellipses:
4118 // TemplateTupleParameter:
4119 // Identifier ...
4120 skip(T.Identifier); skip(T.Ellipses);
4121 if (token.kind == T.Comma)
4122 error(MID.TemplateTupleParameter);
4123 tp = new TemplateTupleParameter(ident);
4124 break;
4125 case T.Comma, T.RParen, T.Colon, T.Assign:
4126 // TemplateTypeParameter:
4127 // Identifier
4128 skip(T.Identifier);
4129 parseSpecAndOrDefaultType();
4130 tp = new TemplateTypeParameter(ident, specType, defType);
4131 break;
4132 default:
4133 // TemplateValueParameter:
4134 // Declarator
4135 ident = null;
4136 goto LTemplateValueParameter;
4138 break;
4139 version(D2)
4141 case T.This:
4142 // TemplateThisParameter
4143 // this TemplateTypeParameter
4144 skip(T.This);
4145 ident = requireIdentifier(MSG.ExpectedNameForThisTempParam);
4146 parseSpecAndOrDefaultType();
4147 tp = new TemplateThisParameter(ident, specType, defType);
4148 break;
4150 default:
4151 LTemplateValueParameter:
4152 // TemplateValueParameter:
4153 // Declarator
4154 Expression specValue, defValue;
4155 auto valueType = parseDeclarator(ident);
4156 // : SpecializationValue
4157 if (consumed(T.Colon))
4158 specValue = parseCondExpression();
4159 // = DefaultValue
4160 if (consumed(T.Assign))
4161 defValue = parseCondExpression();
4162 tp = new TemplateValueParameter(valueType, ident, specValue, defValue);
4165 // Push template parameter.
4166 tparams ~= set(tp, paramBegin);
4168 } while (consumed(T.Comma))
4171 /// Returns the string of a token printable to the client.
4172 char[] getPrintable(Token* token)
4173 { // TODO: there are some other tokens that have to be handled, e.g. strings.
4174 return token.kind == T.EOF ? "EOF" : token.srcText;
4177 alias require expected;
4179 /// Requires a token of kind tok.
4180 void require(TOK tok)
4182 if (token.kind == tok)
4183 nT();
4184 else
4185 error2(MID.ExpectedButFound, Token.toString(tok), token);
4188 /// Requires the next token to be of kind tok.
4189 void requireNext(TOK tok)
4191 nT();
4192 require(tok);
4195 /// Optionally parses an identifier.
4196 /// Returns: null or the identifier.
4197 Identifier* optionalIdentifier()
4199 Identifier* id;
4200 if (token.kind == T.Identifier)
4201 (id = token.ident), skip(T.Identifier);
4202 return id;
4205 Identifier* requireIdentifier()
4207 Identifier* id;
4208 if (token.kind == T.Identifier)
4209 (id = token.ident), skip(T.Identifier);
4210 else
4211 error(MID.ExpectedButFound, "Identifier", token.srcText);
4212 return id;
4215 /// Reports an error if the current token is not an identifier.
4216 /// Params:
4217 /// errorMsg = the error message to be used.
4218 /// Returns: null or the identifier.
4219 Identifier* requireIdentifier(char[] errorMsg)
4221 Identifier* id;
4222 if (token.kind == T.Identifier)
4223 (id = token.ident), skip(T.Identifier);
4224 else
4225 error(token, errorMsg, token.srcText);
4226 return id;
4229 /// Reports an error if the current token is not an identifier.
4230 /// Params:
4231 /// mid = the error message ID to be used.
4232 /// Returns: null or the identifier.
4233 Identifier* requireIdentifier(MID mid)
4235 Identifier* id;
4236 if (token.kind == T.Identifier)
4237 (id = token.ident), skip(T.Identifier);
4238 else
4239 error(mid, token.srcText);
4240 return id;
4243 /// Reports an error if the current token is not an identifier.
4244 /// Returns: null or the token.
4245 Token* requireId()
4247 Token* idtok;
4248 if (token.kind == T.Identifier)
4249 (idtok = token), skip(T.Identifier);
4250 else
4251 error(MID.ExpectedButFound, "Identifier", token.srcText);
4252 return idtok;
4255 Token* requireIdToken(char[] errorMsg)
4257 Token* idtok;
4258 if (token.kind == T.Identifier)
4259 (idtok = token), skip(T.Identifier);
4260 else
4262 error(token, errorMsg, token.srcText);
4263 idtok = lexer.insertEmptyTokenBefore(token);
4264 this.prevToken = idtok;
4266 return idtok;
4269 /// Reports an error if the closing counterpart of a token is not found.
4270 void requireClosing(TOK closing, Token* opening)
4272 assert(closing == T.RBrace || closing == T.RParen || closing == T.RBracket);
4273 assert(opening !is null);
4274 if (!consumed(closing))
4276 auto loc = opening.getRealLocation();
4277 auto openingLoc = Format("(opening @{},{})", loc.lineNum, loc.colNum);
4278 error(token, MSG.ExpectedClosing,
4279 Token.toString(closing), openingLoc, getPrintable(token));
4283 /// Returns true if the string str has an invalid UTF-8 sequence.
4284 bool hasInvalidUTF8(string str, Token* begin)
4286 auto invalidUTF8Seq = Lexer.findInvalidUTF8Sequence(str);
4287 if (invalidUTF8Seq.length)
4288 error(begin, MSG.InvalidUTF8SequenceInString, invalidUTF8Seq);
4289 return invalidUTF8Seq.length != 0;
4292 /// Forwards error parameters.
4293 void error(Token* token, char[] formatMsg, ...)
4295 error_(token, formatMsg, _arguments, _argptr);
4297 /// ditto
4298 void error(MID mid, ...)
4300 error_(this.token, GetMsg(mid), _arguments, _argptr);
4303 /// ditto
4304 void error2(char[] formatMsg, Token* token)
4306 error(token, formatMsg, getPrintable(token));
4308 /// ditto
4309 void error2(MID mid, Token* token)
4311 error(mid, getPrintable(token));
4313 /// ditto
4314 void error2(MID mid, char[] arg, Token* token)
4316 error(mid, arg, getPrintable(token));
4319 /// Creates an error report and appends it to a list.
4320 /// Params:
4321 /// token = used to get the location of where the error is.
4322 /// formatMsg = the compiler error message.
4323 void error_(Token* token, char[] formatMsg, TypeInfo[] _arguments, va_list _argptr)
4325 if (trying)
4327 errorCount++;
4328 return;
4330 auto location = token.getErrorLocation();
4331 auto msg = Format(_arguments, _argptr, formatMsg);
4332 auto error = new ParserError(location, msg);
4333 errors ~= error;
4334 if (diag !is null)
4335 diag ~= error;