comparison src/dil/parser/Parser.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/dil/parser/Parser.d@9e6c6bb73e5f
children 1abffc396594
comparison
equal deleted inserted replaced
805:a3fab8b74a7d 806:bcb74c9b895c
1 /++
2 Author: Aziz Köksal
3 License: GPL3
4 +/
5 module dil.parser.Parser;
6
7 import dil.lexer.Lexer;
8 import dil.ast.Node;
9 import dil.ast.Declarations;
10 import dil.ast.Statements;
11 import dil.ast.Expressions;
12 import dil.ast.Types;
13 import dil.ast.Parameters;
14 import dil.lexer.IdTable;
15 import dil.Messages;
16 import dil.Information;
17 import dil.Enums;
18 import dil.CompilerInfo;
19 import dil.SourceText;
20 import dil.Unicode;
21 import common;
22
23 /// The Parser produces a full parse tree by examining
24 /// the list of tokens provided by the Lexer.
25 class Parser
26 {
27 Lexer lexer; /// Used to lex the source code.
28 Token* token; /// Current non-whitespace token.
29 Token* prevToken; /// Previous non-whitespace token.
30
31 InfoManager infoMan;
32 ParserError[] errors;
33
34 ImportDeclaration[] imports; /// ImportDeclarations in the source text.
35
36 /// Attributes are evaluated in the parsing phase.
37 /// TODO: will be removed. SemanticPass1 takes care of attributes.
38 LinkageType linkageType;
39 Protection protection; /// ditto
40 StorageClass storageClass; /// ditto
41 uint alignSize = DEFAULT_ALIGN_SIZE; /// ditto
42
43 private alias TOK T; /// Used often in this class.
44 private alias TypeNode Type;
45
46 /// Constructs a Parser object.
47 /// Params:
48 /// text = the UTF-8 source code.
49 /// infoMan = used for collecting error messages.
50 this(SourceText srcText, InfoManager infoMan = null)
51 {
52 this.infoMan = infoMan;
53 lexer = new Lexer(srcText, infoMan);
54 }
55
56 /// Moves to the first token.
57 protected void init()
58 {
59 nT();
60 prevToken = token;
61 }
62
63 /// Moves to the next token.
64 void nT()
65 {
66 prevToken = token;
67 do
68 {
69 lexer.nextToken();
70 token = lexer.token;
71 } while (token.isWhitespace) // Skip whitespace
72 }
73
74 /// Start the parser and return the parsed Declarations.
75 CompoundDeclaration start()
76 {
77 init();
78 auto begin = token;
79 auto decls = new CompoundDeclaration;
80 if (token.kind == T.Module)
81 decls ~= parseModuleDeclaration();
82 decls.addOptChildren(parseDeclarationDefinitions());
83 set(decls, begin);
84 return decls;
85 }
86
87 /// Start the parser and return the parsed Expression.
88 Expression start2()
89 {
90 init();
91 return parseExpression();
92 }
93
94 // Members related to the method try_().
95 uint trying; /// Greater than 0 if Parser is in try_().
96 uint errorCount; /// Used to track nr. of errors while being in try_().
97
98 /// This method executes the delegate parseMethod and when an error occurred
99 /// the state of the lexer and parser are restored.
100 /// Returns: the return value of parseMethod().
101 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success)
102 {
103 // Save members.
104 auto oldToken = this.token;
105 auto oldPrevToken = this.prevToken;
106 auto oldCount = this.errorCount;
107
108 ++trying;
109 auto result = parseMethod();
110 --trying;
111 // Check if an error occurred.
112 if (errorCount != oldCount)
113 { // Restore members.
114 token = oldToken;
115 prevToken = oldPrevToken;
116 lexer.token = oldToken;
117 errorCount = oldCount;
118 success = false;
119 }
120 else
121 success = true;
122 return result;
123 }
124
125 /// Sets the begin and end tokens of a syntax tree node.
126 Class set(Class)(Class node, Token* begin)
127 {
128 node.setTokens(begin, this.prevToken);
129 return node;
130 }
131
132 /// Sets the begin and end tokens of a syntax tree node.
133 Class set(Class)(Class node, Token* begin, Token* end)
134 {
135 node.setTokens(begin, end);
136 return node;
137 }
138
139 /// Returns true if set() has been called on a node.
140 static bool isNodeSet(Node node)
141 {
142 return node.begin !is null && node.end !is null;
143 }
144
145 /// Returns the token kind of the next token.
146 TOK peekNext()
147 {
148 Token* next = token;
149 do
150 lexer.peek(next);
151 while (next.isWhitespace) // Skip whitespace
152 return next.kind;
153 }
154
155 /// Returns the token kind of the token that comes after t.
156 TOK peekAfter(ref Token* t)
157 {
158 assert(t !is null);
159 do
160 lexer.peek(t);
161 while (t.isWhitespace) // Skip whitespace
162 return t.kind;
163 }
164
165 /// Consumes the current token if its kind matches k and returns true.
166 bool consumed()(TOK k) // Templatized, so it's inlined.
167 {
168 return token.kind == k ? (nT(), true) : false;
169 }
170
171 /// Asserts that the current token is of kind expectedKind,
172 /// and then moves to the next token.
173 void skip()(TOK expectedKind)
174 {
175 assert(token.kind == expectedKind /+|| *(int*).init+/, token.srcText());
176 nT();
177 }
178
179 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180 | Declaration parsing methods |
181 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
182
183 Declaration parseModuleDeclaration()
184 {
185 skip(T.Module);
186 auto begin = token;
187 ModuleFQN moduleFQN;
188 do
189 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
190 while (consumed(T.Dot))
191 require(T.Semicolon);
192 return set(new ModuleDeclaration(moduleFQN), begin);
193 }
194
195 /// Parses DeclarationDefinitions until the end of file is hit.
196 /// $(PRE
197 /// DeclDefs :=
198 /// DeclDef
199 /// DeclDefs
200 /// )
201 Declaration[] parseDeclarationDefinitions()
202 {
203 Declaration[] decls;
204 while (token.kind != T.EOF)
205 decls ~= parseDeclarationDefinition();
206 return decls;
207 }
208
209 /// Parse the body of a template, class, interface, struct or union.
210 /// $(PRE
211 /// DeclDefsBlock :=
212 /// { }
213 /// { DeclDefs }
214 /// )
215 CompoundDeclaration parseDeclarationDefinitionsBody()
216 {
217 // Save attributes.
218 auto linkageType = this.linkageType;
219 auto protection = this.protection;
220 auto storageClass = this.storageClass;
221 // Clear attributes.
222 this.linkageType = LinkageType.None;
223 this.protection = Protection.None;
224 this.storageClass = StorageClass.None;
225
226 // Parse body.
227 auto begin = token;
228 auto decls = new CompoundDeclaration;
229 require(T.LBrace);
230 while (token.kind != T.RBrace && token.kind != T.EOF)
231 decls ~= parseDeclarationDefinition();
232 require(T.RBrace);
233 set(decls, begin);
234
235 // Restore original values.
236 this.linkageType = linkageType;
237 this.protection = protection;
238 this.storageClass = storageClass;
239
240 return decls;
241 }
242
243 /// Parses a DeclarationDefinition.
244 Declaration parseDeclarationDefinition()
245 out(decl)
246 { assert(isNodeSet(decl)); }
247 body
248 {
249 auto begin = token;
250 Declaration decl;
251 switch (token.kind)
252 {
253 case T.Align,
254 T.Pragma,
255 // Protection attributes
256 T.Export,
257 T.Private,
258 T.Package,
259 T.Protected,
260 T.Public:
261 decl = parseAttributeSpecifier();
262 break;
263 // Storage classes
264 case T.Extern,
265 T.Deprecated,
266 T.Override,
267 T.Abstract,
268 T.Synchronized,
269 //T.Static,
270 T.Final,
271 T.Const,
272 //T.Invariant, // D 2.0
273 T.Auto,
274 T.Scope:
275 case_StaticAttribute:
276 case_InvariantAttribute: // D 2.0
277 return parseStorageAttribute();
278 case T.Alias:
279 nT();
280 decl = new AliasDeclaration(parseVariableOrFunction());
281 break;
282 case T.Typedef:
283 nT();
284 decl = new TypedefDeclaration(parseVariableOrFunction());
285 break;
286 case T.Static:
287 switch (peekNext())
288 {
289 case T.Import:
290 goto case_Import;
291 case T.This:
292 decl = parseStaticConstructorDeclaration();
293 break;
294 case T.Tilde:
295 decl = parseStaticDestructorDeclaration();
296 break;
297 case T.If:
298 decl = parseStaticIfDeclaration();
299 break;
300 case T.Assert:
301 decl = parseStaticAssertDeclaration();
302 break;
303 default:
304 goto case_StaticAttribute;
305 }
306 break;
307 case T.Import:
308 case_Import:
309 decl = parseImportDeclaration();
310 imports ~= decl.to!(ImportDeclaration);
311 // Handle specially. StorageClass mustn't be set.
312 decl.setProtection(this.protection);
313 return set(decl, begin);
314 case T.Enum:
315 decl = parseEnumDeclaration();
316 break;
317 case T.Class:
318 decl = parseClassDeclaration();
319 break;
320 case T.Interface:
321 decl = parseInterfaceDeclaration();
322 break;
323 case T.Struct, T.Union:
324 decl = parseStructOrUnionDeclaration();
325 break;
326 case T.This:
327 decl = parseConstructorDeclaration();
328 break;
329 case T.Tilde:
330 decl = parseDestructorDeclaration();
331 break;
332 case T.Invariant:
333 version(D2)
334 {
335 auto next = token;
336 if (peekAfter(next) == T.LParen)
337 {
338 if (peekAfter(next) != T.RParen)
339 goto case_Declaration;
340 }
341 else
342 goto case_InvariantAttribute;
343 }
344 decl = parseInvariantDeclaration();
345 break;
346 case T.Unittest:
347 decl = parseUnittestDeclaration();
348 break;
349 case T.Debug:
350 decl = parseDebugDeclaration();
351 break;
352 case T.Version:
353 decl = parseVersionDeclaration();
354 break;
355 case T.Template:
356 decl = parseTemplateDeclaration();
357 break;
358 case T.New:
359 decl = parseNewDeclaration();
360 break;
361 case T.Delete:
362 decl = parseDeleteDeclaration();
363 break;
364 case T.Mixin:
365 decl = parseMixin!(MixinDeclaration)();
366 break;
367 case T.Semicolon:
368 nT();
369 decl = new EmptyDeclaration();
370 break;
371 // Declaration
372 case T.Identifier, T.Dot, T.Typeof:
373 case_Declaration:
374 return parseVariableOrFunction(this.storageClass, this.protection, this.linkageType);
375 default:
376 if (token.isIntegralType)
377 goto case_Declaration;
378 else if (token.kind == T.Module)
379 {
380 decl = parseModuleDeclaration();
381 error(begin, MSG.ModuleDeclarationNotFirst);
382 return decl;
383 }
384
385 decl = new IllegalDeclaration();
386 // Skip to next valid token.
387 do
388 nT();
389 while (!token.isDeclDefStart &&
390 token.kind != T.RBrace &&
391 token.kind != T.EOF)
392 auto text = Token.textSpan(begin, this.prevToken);
393 error(begin, MSG.IllegalDeclaration, text);
394 }
395 decl.setProtection(this.protection);
396 decl.setStorageClass(this.storageClass);
397 assert(!isNodeSet(decl));
398 set(decl, begin);
399 return decl;
400 }
401
402 /// Parses a DeclarationsBlock.
403 /// $(PRE
404 /// DeclarationsBlock :=
405 /// : DeclDefs
406 /// { }
407 /// { DeclDefs }
408 /// DeclDef
409 /// )
410 Declaration parseDeclarationsBlock(/+bool noColon = false+/)
411 {
412 Declaration d;
413 switch (token.kind)
414 {
415 case T.LBrace:
416 auto begin = token;
417 nT();
418 auto decls = new CompoundDeclaration;
419 while (token.kind != T.RBrace && token.kind != T.EOF)
420 decls ~= parseDeclarationDefinition();
421 require(T.RBrace);
422 d = set(decls, begin);
423 break;
424 case T.Colon:
425 // if (noColon == true)
426 // goto default;
427 nT();
428 auto begin = token;
429 auto decls = new CompoundDeclaration;
430 while (token.kind != T.RBrace && token.kind != T.EOF)
431 decls ~= parseDeclarationDefinition();
432 d = set(decls, begin);
433 break;
434 default:
435 d = parseDeclarationDefinition();
436 }
437 assert(isNodeSet(d));
438 return d;
439 }
440
441 // Declaration parseDeclarationsBlockNoColon()
442 // {
443 // return parseDeclarationsBlock(true);
444 // }
445
446 /// Parses either a VariableDeclaration or a FunctionDeclaration.
447 /// Params:
448 /// stc = previously parsed storage classes
449 /// protection = previously parsed protection attribute
450 /// linkType = previously parsed linkage type
451 /// testAutoDeclaration = whether to check for an AutoDeclaration
452 /// optionalParameterList = a hint for how to parse C-style function pointers
453 Declaration parseVariableOrFunction(StorageClass stc = StorageClass.None,
454 Protection protection = Protection.None,
455 LinkageType linkType = LinkageType.None,
456 bool testAutoDeclaration = false,
457 bool optionalParameterList = true)
458 {
459 auto begin = token;
460 Type type;
461 Identifier* name;
462
463 // Check for AutoDeclaration: StorageClasses Identifier =
464 if (testAutoDeclaration &&
465 token.kind == T.Identifier &&
466 peekNext() == T.Assign)
467 {
468 name = token.ident;
469 skip(T.Identifier);
470 }
471 else
472 {
473 type = parseType(); // VariableType or ReturnType
474 if (token.kind == T.LParen)
475 {
476 // C-style function pointers make the grammar ambiguous.
477 // We have to treat them specially at function scope.
478 // Example:
479 // void foo() {
480 // // A pointer to a function taking an integer and returning 'some_type'.
481 // some_type (*p_func)(int);
482 // // In the following case precedence is given to a CallExpression.
483 // something(*p); // 'something' may be a function/method or an object having opCall overloaded.
484 // }
485 // // A pointer to a function taking no parameters and returning 'something'.
486 // something(*p);
487 type = parseCFunctionPointerType(type, name, optionalParameterList);
488 }
489 else if (peekNext() == T.LParen)
490 { // Type FunctionName ( ParameterList ) FunctionBody
491 name = requireIdentifier(MSG.ExpectedFunctionName);
492 name || nT(); // Skip non-identifier token.
493 assert(token.kind == T.LParen);
494 // It's a function declaration
495 TemplateParameters tparams;
496 if (tokenAfterParenIs(T.LParen))
497 // ( TemplateParameterList ) ( ParameterList )
498 tparams = parseTemplateParameterList();
499
500 auto params = parseParameterList();
501 version(D2)
502 {
503 switch (token.kind)
504 {
505 case T.Const:
506 stc |= StorageClass.Const;
507 nT();
508 break;
509 case T.Invariant:
510 stc |= StorageClass.Invariant;
511 nT();
512 break;
513 default:
514 }
515 }
516 // ReturnType FunctionName ( ParameterList )
517 auto funcBody = parseFunctionBody();
518 auto fd = new FunctionDeclaration(type, name,/+ tparams,+/ params, funcBody);
519 fd.setStorageClass(stc);
520 fd.setLinkageType(linkType);
521 fd.setProtection(protection);
522 if (tparams)
523 {
524 auto d = putInsideTemplateDeclaration(begin, name, fd, tparams);
525 d.setStorageClass(stc);
526 d.setProtection(protection);
527 return set(d, begin);
528 }
529 return set(fd, begin);
530 }
531 else
532 { // Type VariableName DeclaratorSuffix
533 name = requireIdentifier(MSG.ExpectedVariableName);
534 type = parseDeclaratorSuffix(type);
535 }
536 }
537
538 // It's a variables declaration.
539 Identifier*[] names = [name]; // One identifier has been parsed already.
540 Expression[] values;
541 goto LenterLoop; // Enter the loop and check for an initializer.
542 while (consumed(T.Comma))
543 {
544 names ~= requireIdentifier(MSG.ExpectedVariableName);
545 LenterLoop:
546 if (consumed(T.Assign))
547 values ~= parseInitializer();
548 else
549 values ~= null;
550 }
551 require(T.Semicolon);
552 auto d = new VariablesDeclaration(type, names, values);
553 d.setStorageClass(stc);
554 d.setLinkageType(linkType);
555 d.setProtection(protection);
556 return set(d, begin);
557 }
558
559 /// Parses a variable initializer.
560 Expression parseInitializer()
561 {
562 if (token.kind == T.Void)
563 {
564 auto begin = token;
565 auto next = peekNext();
566 if (next == T.Comma || next == T.Semicolon)
567 {
568 skip(T.Void);
569 return set(new VoidInitExpression(), begin);
570 }
571 }
572 return parseNonVoidInitializer();
573 }
574
575 Expression parseNonVoidInitializer()
576 {
577 auto begin = token;
578 Expression init;
579 switch (token.kind)
580 {
581 case T.LBracket:
582 // ArrayInitializer:
583 // [ ]
584 // [ ArrayMemberInitializations ]
585 Expression[] keys;
586 Expression[] values;
587
588 skip(T.LBracket);
589 while (token.kind != T.RBracket)
590 {
591 auto e = parseNonVoidInitializer();
592 if (consumed(T.Colon))
593 {
594 keys ~= e;
595 values ~= parseNonVoidInitializer();
596 }
597 else
598 {
599 keys ~= null;
600 values ~= e;
601 }
602
603 if (!consumed(T.Comma))
604 break;
605 }
606 require(T.RBracket);
607 init = new ArrayInitExpression(keys, values);
608 break;
609 case T.LBrace:
610 // StructInitializer:
611 // { }
612 // { StructMemberInitializers }
613 Expression parseStructInitializer()
614 {
615 Identifier*[] idents;
616 Expression[] values;
617
618 skip(T.LBrace);
619 while (token.kind != T.RBrace)
620 {
621 if (token.kind == T.Identifier &&
622 // Peek for colon to see if this is a member identifier.
623 peekNext() == T.Colon)
624 {
625 idents ~= token.ident;
626 skip(T.Identifier), skip(T.Colon);
627 }
628 else
629 idents ~= null;
630
631 // NonVoidInitializer
632 values ~= parseNonVoidInitializer();
633
634 if (!consumed(T.Comma))
635 break;
636 }
637 require(T.RBrace);
638 return new StructInitExpression(idents, values);
639 }
640
641 bool success;
642 auto si = try_(&parseStructInitializer, success);
643 if (success)
644 {
645 init = si;
646 break;
647 }
648 assert(token.kind == T.LBrace);
649 //goto default;
650 default:
651 init = parseAssignExpression();
652 }
653 set(init, begin);
654 return init;
655 }
656
657 FuncBodyStatement parseFunctionBody()
658 {
659 auto begin = token;
660 auto func = new FuncBodyStatement;
661 while (1)
662 {
663 switch (token.kind)
664 {
665 case T.LBrace:
666 func.funcBody = parseStatements();
667 break;
668 case T.Semicolon:
669 nT();
670 break;
671 case T.In:
672 if (func.inBody)
673 error(MID.InContract);
674 nT();
675 func.inBody = parseStatements();
676 continue;
677 case T.Out:
678 if (func.outBody)
679 error(MID.OutContract);
680 nT();
681 if (consumed(T.LParen))
682 {
683 func.outIdent = requireIdentifier(MSG.ExpectedAnIdentifier);
684 require(T.RParen);
685 }
686 func.outBody = parseStatements();
687 continue;
688 case T.Body:
689 nT();
690 goto case T.LBrace;
691 default:
692 error(token, MSG.ExpectedFunctionBody, token.srcText);
693 }
694 break; // Exit loop.
695 }
696 set(func, begin);
697 func.finishConstruction();
698 return func;
699 }
700
701 LinkageType parseLinkageType()
702 {
703 LinkageType linkageType;
704
705 if (!consumed(T.LParen))
706 return linkageType;
707
708 if (consumed(T.RParen))
709 { // extern()
710 error(MID.MissingLinkageType);
711 return linkageType;
712 }
713
714 auto identTok = requireId();
715
716 IDK idKind = identTok ? identTok.ident.idKind : IDK.Null;
717
718 switch (idKind)
719 {
720 case IDK.C:
721 if (consumed(T.PlusPlus))
722 {
723 linkageType = LinkageType.Cpp;
724 break;
725 }
726 linkageType = LinkageType.C;
727 break;
728 case IDK.D:
729 linkageType = LinkageType.D;
730 break;
731 case IDK.Windows:
732 linkageType = LinkageType.Windows;
733 break;
734 case IDK.Pascal:
735 linkageType = LinkageType.Pascal;
736 break;
737 case IDK.System:
738 linkageType = LinkageType.System;
739 break;
740 default:
741 error(MID.UnrecognizedLinkageType, token.srcText);
742 }
743 require(T.RParen);
744 return linkageType;
745 }
746
747 void checkLinkageType(ref LinkageType prev_lt, LinkageType lt, Token* begin)
748 {
749 if (prev_lt == LinkageType.None)
750 prev_lt = lt;
751 else
752 error(begin, MSG.RedundantLinkageType, Token.textSpan(begin, this.prevToken));
753 }
754
755 Declaration parseStorageAttribute()
756 {
757 StorageClass stc, stc_tmp;
758 LinkageType prev_linkageType;
759
760 auto saved_storageClass = this.storageClass; // Save.
761 // Nested function.
762 Declaration parse()
763 {
764 Declaration decl;
765 auto begin = token;
766 switch (token.kind)
767 {
768 case T.Extern:
769 if (peekNext() != T.LParen)
770 {
771 stc_tmp = StorageClass.Extern;
772 goto Lcommon;
773 }
774
775 nT();
776 auto linkageType = parseLinkageType();
777 checkLinkageType(prev_linkageType, linkageType, begin);
778
779 auto saved = this.linkageType; // Save.
780 this.linkageType = linkageType; // Set.
781 decl = new LinkageDeclaration(linkageType, parse());
782 set(decl, begin);
783 this.linkageType = saved; // Restore.
784 break;
785 case T.Override:
786 stc_tmp = StorageClass.Override;
787 goto Lcommon;
788 case T.Deprecated:
789 stc_tmp = StorageClass.Deprecated;
790 goto Lcommon;
791 case T.Abstract:
792 stc_tmp = StorageClass.Abstract;
793 goto Lcommon;
794 case T.Synchronized:
795 stc_tmp = StorageClass.Synchronized;
796 goto Lcommon;
797 case T.Static:
798 stc_tmp = StorageClass.Static;
799 goto Lcommon;
800 case T.Final:
801 stc_tmp = StorageClass.Final;
802 goto Lcommon;
803 case T.Const:
804 version(D2)
805 {
806 if (peekNext() == T.LParen)
807 goto case_Declaration;
808 }
809 stc_tmp = StorageClass.Const;
810 goto Lcommon;
811 version(D2)
812 {
813 case T.Invariant: // D 2.0
814 auto next = token;
815 if (peekAfter(next) == T.LParen)
816 {
817 if (peekAfter(next) != T.RParen)
818 goto case_Declaration; // invariant ( Type )
819 decl = parseDeclarationDefinition(); // invariant ( )
820 decl.setStorageClass(stc);
821 break;
822 }
823 // invariant as StorageClass.
824 stc_tmp = StorageClass.Invariant;
825 goto Lcommon;
826 }
827 case T.Auto:
828 stc_tmp = StorageClass.Auto;
829 goto Lcommon;
830 case T.Scope:
831 stc_tmp = StorageClass.Scope;
832 goto Lcommon;
833 Lcommon:
834 // Issue error if redundant.
835 if (stc & stc_tmp)
836 error(MID.RedundantStorageClass, token.srcText);
837 else
838 stc |= stc_tmp;
839
840 nT();
841 decl = new StorageClassDeclaration(stc_tmp, parse());
842 set(decl, begin);
843 break;
844 case T.Identifier:
845 case_Declaration:
846 // This could be a normal Declaration or an AutoDeclaration
847 decl = parseVariableOrFunction(stc, this.protection, prev_linkageType, true);
848 break;
849 default:
850 this.storageClass = stc; // Set.
851 decl = parseDeclarationsBlock();
852 this.storageClass = saved_storageClass; // Reset.
853 }
854 assert(isNodeSet(decl));
855 return decl;
856 }
857 return parse();
858 }
859
860 uint parseAlignAttribute()
861 {
862 skip(T.Align);
863 uint size = DEFAULT_ALIGN_SIZE; // Global default.
864 if (consumed(T.LParen))
865 {
866 if (token.kind == T.Int32)
867 (size = token.int_), skip(T.Int32);
868 else
869 expected(T.Int32);
870 require(T.RParen);
871 }
872 return size;
873 }
874
875 Declaration parseAttributeSpecifier()
876 {
877 Declaration decl;
878
879 switch (token.kind)
880 {
881 case T.Align:
882 uint alignSize = parseAlignAttribute();
883 auto saved = this.alignSize; // Save.
884 this.alignSize = alignSize; // Set.
885 decl = new AlignDeclaration(alignSize, parseDeclarationsBlock());
886 this.alignSize = saved; // Restore.
887 break;
888 case T.Pragma:
889 // Pragma:
890 // pragma ( Identifier )
891 // pragma ( Identifier , ExpressionList )
892 nT();
893 Identifier* ident;
894 Expression[] args;
895
896 require(T.LParen);
897 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
898
899 if (consumed(T.Comma))
900 args = parseExpressionList();
901 require(T.RParen);
902
903 decl = new PragmaDeclaration(ident, args, parseDeclarationsBlock());
904 break;
905 default:
906 // Protection attributes
907 Protection prot;
908 switch (token.kind)
909 {
910 case T.Private:
911 prot = Protection.Private; break;
912 case T.Package:
913 prot = Protection.Package; break;
914 case T.Protected:
915 prot = Protection.Protected; break;
916 case T.Public:
917 prot = Protection.Public; break;
918 case T.Export:
919 prot = Protection.Export; break;
920 default:
921 assert(0);
922 }
923 nT();
924 auto saved = this.protection; // Save.
925 this.protection = prot; // Set.
926 decl = new ProtectionDeclaration(prot, parseDeclarationsBlock());
927 this.protection = saved; // Restore.
928 }
929 return decl;
930 }
931
932 Declaration parseImportDeclaration()
933 {
934 bool isStatic = consumed(T.Static);
935 skip(T.Import);
936
937 ModuleFQN[] moduleFQNs;
938 Identifier*[] moduleAliases;
939 Identifier*[] bindNames;
940 Identifier*[] bindAliases;
941
942 do
943 {
944 ModuleFQN moduleFQN;
945 Identifier* moduleAlias;
946 // AliasName = ModuleName
947 if (peekNext() == T.Assign)
948 {
949 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName);
950 skip(T.Assign);
951 }
952 // Identifier ("." Identifier)*
953 do
954 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
955 while (consumed(T.Dot))
956 // Push identifiers.
957 moduleFQNs ~= moduleFQN;
958 moduleAliases ~= moduleAlias;
959 } while (consumed(T.Comma))
960
961 if (consumed(T.Colon))
962 { // BindAlias "=" BindName ("," BindAlias "=" BindName)*;
963 // BindName ("," BindName)*;
964 do
965 {
966 Identifier* bindAlias;
967 // BindAlias = BindName
968 if (peekNext() == T.Assign)
969 {
970 bindAlias = requireIdentifier(MSG.ExpectedAliasImportName);
971 skip(T.Assign);
972 }
973 // Push identifiers.
974 bindNames ~= requireIdentifier(MSG.ExpectedImportName);
975 bindAliases ~= bindAlias;
976 } while (consumed(T.Comma))
977 }
978 require(T.Semicolon);
979
980 return new ImportDeclaration(moduleFQNs, moduleAliases, bindNames, bindAliases, isStatic);
981 }
982
983 Declaration parseEnumDeclaration()
984 {
985 skip(T.Enum);
986
987 Identifier* enumName;
988 Type baseType;
989 EnumMemberDeclaration[] members;
990 bool hasBody;
991
992 enumName = optionalIdentifier();
993
994 if (consumed(T.Colon))
995 baseType = parseBasicType();
996
997 if (enumName && consumed(T.Semicolon))
998 {}
999 else if (consumed(T.LBrace))
1000 {
1001 hasBody = true;
1002 while (token.kind != T.RBrace)
1003 {
1004 auto begin = token;
1005 auto name = requireIdentifier(MSG.ExpectedEnumMember);
1006 Expression value;
1007
1008 if (consumed(T.Assign))
1009 value = parseAssignExpression();
1010 else
1011 value = null;
1012
1013 members ~= set(new EnumMemberDeclaration(name, value), begin);
1014
1015 if (!consumed(T.Comma))
1016 break;
1017 }
1018 require(T.RBrace);
1019 }
1020 else
1021 error(token, MSG.ExpectedEnumBody, token.srcText);
1022
1023 return new EnumDeclaration(enumName, baseType, members, hasBody);
1024 }
1025
1026 /// Wraps a declaration inside a template declaration.
1027 /// Params:
1028 /// begin = begin token of decl.
1029 /// name = name of decl.
1030 /// decl = the declaration to be wrapped.
1031 /// tparams = the template parameters.
1032 TemplateDeclaration putInsideTemplateDeclaration(Token* begin,
1033 Identifier* name,
1034 Declaration decl,
1035 TemplateParameters tparams)
1036 {
1037 set(decl, begin);
1038 auto cd = new CompoundDeclaration;
1039 cd ~= decl;
1040 set(cd, begin);
1041 return new TemplateDeclaration(name, tparams, cd);
1042 }
1043
1044 Declaration parseClassDeclaration()
1045 {
1046 auto begin = token;
1047 skip(T.Class);
1048
1049 Identifier* className;
1050 TemplateParameters tparams;
1051 BaseClassType[] bases;
1052 CompoundDeclaration decls;
1053
1054 className = requireIdentifier(MSG.ExpectedClassName);
1055
1056 if (token.kind == T.LParen)
1057 tparams = parseTemplateParameterList();
1058
1059 if (token.kind == T.Colon)
1060 bases = parseBaseClasses();
1061
1062 if (bases.length == 0 && consumed(T.Semicolon))
1063 {}
1064 else if (token.kind == T.LBrace)
1065 decls = parseDeclarationDefinitionsBody();
1066 else
1067 error(token, MSG.ExpectedClassBody, token.srcText);
1068
1069 Declaration d = new ClassDeclaration(className, /+tparams, +/bases, decls);
1070 if (tparams)
1071 d = putInsideTemplateDeclaration(begin, className, d, tparams);
1072 return d;
1073 }
1074
1075 BaseClassType[] parseBaseClasses(bool colonLeadsOff = true)
1076 {
1077 colonLeadsOff && skip(T.Colon);
1078
1079 BaseClassType[] bases;
1080 do
1081 {
1082 Protection prot = Protection.Public;
1083 switch (token.kind)
1084 {
1085 case T.Identifier, T.Dot, T.Typeof: goto LparseBasicType;
1086 case T.Private: prot = Protection.Private; break;
1087 case T.Protected: prot = Protection.Protected; break;
1088 case T.Package: prot = Protection.Package; break;
1089 case T.Public: /*prot = Protection.Public;*/ break;
1090 default:
1091 error(MID.ExpectedBaseClasses, token.srcText);
1092 return bases;
1093 }
1094 nT(); // Skip protection attribute.
1095 LparseBasicType:
1096 auto begin = token;
1097 auto type = parseBasicType();
1098 bases ~= set(new BaseClassType(prot, type), begin);
1099 } while (consumed(T.Comma))
1100 return bases;
1101 }
1102
1103 Declaration parseInterfaceDeclaration()
1104 {
1105 auto begin = token;
1106 skip(T.Interface);
1107
1108 Identifier* name;
1109 TemplateParameters tparams;
1110 BaseClassType[] bases;
1111 CompoundDeclaration decls;
1112
1113 name = requireIdentifier(MSG.ExpectedInterfaceName);
1114
1115 if (token.kind == T.LParen)
1116 tparams = parseTemplateParameterList();
1117
1118 if (token.kind == T.Colon)
1119 bases = parseBaseClasses();
1120
1121 if (bases.length == 0 && consumed(T.Semicolon))
1122 {}
1123 else if (token.kind == T.LBrace)
1124 decls = parseDeclarationDefinitionsBody();
1125 else
1126 error(token, MSG.ExpectedInterfaceBody, token.srcText);
1127
1128 Declaration d = new InterfaceDeclaration(name, /+tparams, +/bases, decls);
1129 if (tparams)
1130 d = putInsideTemplateDeclaration(begin, name, d, tparams);
1131 return d;
1132 }
1133
1134 Declaration parseStructOrUnionDeclaration()
1135 {
1136 assert(token.kind == T.Struct || token.kind == T.Union);
1137 auto begin = token;
1138 skip(token.kind);
1139
1140 Identifier* name;
1141 TemplateParameters tparams;
1142 CompoundDeclaration decls;
1143
1144 name = optionalIdentifier();
1145
1146 if (name && token.kind == T.LParen)
1147 tparams = parseTemplateParameterList();
1148
1149 if (name && consumed(T.Semicolon))
1150 {}
1151 else if (token.kind == T.LBrace)
1152 decls = parseDeclarationDefinitionsBody();
1153 else
1154 error(token, begin.kind == T.Struct ?
1155 MSG.ExpectedStructBody :
1156 MSG.ExpectedUnionBody, token.srcText);
1157
1158 Declaration d;
1159 if (begin.kind == T.Struct)
1160 {
1161 auto sd = new StructDeclaration(name, /+tparams, +/decls);
1162 sd.setAlignSize(this.alignSize);
1163 d = sd;
1164 }
1165 else
1166 d = new UnionDeclaration(name, /+tparams, +/decls);
1167
1168 if (tparams)
1169 d = putInsideTemplateDeclaration(begin, name, d, tparams);
1170 return d;
1171 }
1172
1173 Declaration parseConstructorDeclaration()
1174 {
1175 skip(T.This);
1176 auto parameters = parseParameterList();
1177 auto funcBody = parseFunctionBody();
1178 return new ConstructorDeclaration(parameters, funcBody);
1179 }
1180
1181 Declaration parseDestructorDeclaration()
1182 {
1183 skip(T.Tilde);
1184 require(T.This);
1185 require(T.LParen);
1186 require(T.RParen);
1187 auto funcBody = parseFunctionBody();
1188 return new DestructorDeclaration(funcBody);
1189 }
1190
1191 Declaration parseStaticConstructorDeclaration()
1192 {
1193 skip(T.Static);
1194 skip(T.This);
1195 require(T.LParen);
1196 require(T.RParen);
1197 auto funcBody = parseFunctionBody();
1198 return new StaticConstructorDeclaration(funcBody);
1199 }
1200
1201 Declaration parseStaticDestructorDeclaration()
1202 {
1203 skip(T.Static);
1204 skip(T.Tilde);
1205 require(T.This);
1206 require(T.LParen);
1207 require(T.RParen);
1208 auto funcBody = parseFunctionBody();
1209 return new StaticDestructorDeclaration(funcBody);
1210 }
1211
1212 Declaration parseInvariantDeclaration()
1213 {
1214 skip(T.Invariant);
1215 // Optional () for getting ready porting to D 2.0
1216 if (consumed(T.LParen))
1217 require(T.RParen);
1218 auto funcBody = parseFunctionBody();
1219 return new InvariantDeclaration(funcBody);
1220 }
1221
1222 Declaration parseUnittestDeclaration()
1223 {
1224 skip(T.Unittest);
1225 auto funcBody = parseFunctionBody();
1226 return new UnittestDeclaration(funcBody);
1227 }
1228
1229 Token* parseIdentOrInt()
1230 {
1231 if (consumed(T.Int32) || consumed(T.Identifier))
1232 return this.prevToken;
1233 error(token, MSG.ExpectedIdentOrInt, token.srcText);
1234 return null;
1235 }
1236
1237 Declaration parseDebugDeclaration()
1238 {
1239 skip(T.Debug);
1240
1241 Token* spec;
1242 Token* cond;
1243 Declaration decls, elseDecls;
1244
1245 if (consumed(T.Assign))
1246 { // debug = Integer ;
1247 // debug = Identifier ;
1248 spec = parseIdentOrInt();
1249 require(T.Semicolon);
1250 }
1251 else
1252 { // ( Condition )
1253 if (consumed(T.LParen))
1254 {
1255 cond = parseIdentOrInt();
1256 require(T.RParen);
1257 }
1258 // debug DeclarationsBlock
1259 // debug ( Condition ) DeclarationsBlock
1260 decls = parseDeclarationsBlock();
1261 // else DeclarationsBlock
1262 if (consumed(T.Else))
1263 elseDecls = parseDeclarationsBlock();
1264 }
1265
1266 return new DebugDeclaration(spec, cond, decls, elseDecls);
1267 }
1268
1269 Declaration parseVersionDeclaration()
1270 {
1271 skip(T.Version);
1272
1273 Token* spec;
1274 Token* cond;
1275 Declaration decls, elseDecls;
1276
1277 if (consumed(T.Assign))
1278 { // version = Integer ;
1279 // version = Identifier ;
1280 spec = parseIdentOrInt();
1281 require(T.Semicolon);
1282 }
1283 else
1284 { // ( Condition )
1285 require(T.LParen);
1286 cond = parseIdentOrInt();
1287 require(T.RParen);
1288 // version ( Condition ) DeclarationsBlock
1289 decls = parseDeclarationsBlock();
1290 // else DeclarationsBlock
1291 if (consumed(T.Else))
1292 elseDecls = parseDeclarationsBlock();
1293 }
1294
1295 return new VersionDeclaration(spec, cond, decls, elseDecls);
1296 }
1297
1298 Declaration parseStaticIfDeclaration()
1299 {
1300 skip(T.Static);
1301 skip(T.If);
1302
1303 Expression condition;
1304 Declaration ifDecls, elseDecls;
1305
1306 require(T.LParen);
1307 condition = parseAssignExpression();
1308 require(T.RParen);
1309
1310 ifDecls = parseDeclarationsBlock();
1311
1312 if (consumed(T.Else))
1313 elseDecls = parseDeclarationsBlock();
1314
1315 return new StaticIfDeclaration(condition, ifDecls, elseDecls);
1316 }
1317
1318 Declaration parseStaticAssertDeclaration()
1319 {
1320 skip(T.Static);
1321 skip(T.Assert);
1322 Expression condition, message;
1323 require(T.LParen);
1324 condition = parseAssignExpression();
1325 if (consumed(T.Comma))
1326 message = parseAssignExpression();
1327 require(T.RParen);
1328 require(T.Semicolon);
1329 return new StaticAssertDeclaration(condition, message);
1330 }
1331
1332 Declaration parseTemplateDeclaration()
1333 {
1334 skip(T.Template);
1335 auto templateName = requireIdentifier(MSG.ExpectedTemplateName);
1336 auto templateParams = parseTemplateParameterList();
1337 auto decls = parseDeclarationDefinitionsBody();
1338 return new TemplateDeclaration(templateName, templateParams, decls);
1339 }
1340
1341 Declaration parseNewDeclaration()
1342 {
1343 skip(T.New);
1344 auto parameters = parseParameterList();
1345 auto funcBody = parseFunctionBody();
1346 return new NewDeclaration(parameters, funcBody);
1347 }
1348
1349 Declaration parseDeleteDeclaration()
1350 {
1351 skip(T.Delete);
1352 auto parameters = parseParameterList();
1353 auto funcBody = parseFunctionBody();
1354 return new DeleteDeclaration(parameters, funcBody);
1355 }
1356
1357 Type parseTypeofType()
1358 {
1359 auto begin = token;
1360 skip(T.Typeof);
1361 require(T.LParen);
1362 Type type;
1363 switch (token.kind)
1364 {
1365 version(D2)
1366 {
1367 case T.Return:
1368 nT();
1369 type = new TypeofType();
1370 break;
1371 }
1372 default:
1373 type = new TypeofType(parseExpression());
1374 }
1375 require(T.RParen);
1376 set(type, begin);
1377 return type;
1378 }
1379
1380 /// Parses a MixinDeclaration or MixinStatement.
1381 /// $(PRE
1382 /// TemplateMixin :=
1383 /// mixin ( AssignExpression ) ;
1384 /// mixin TemplateIdentifier ;
1385 /// mixin TemplateIdentifier MixinIdentifier ;
1386 /// mixin TemplateIdentifier !( TemplateArguments ) ;
1387 /// mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
1388 /// )
1389 Class parseMixin(Class)()
1390 {
1391 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement));
1392 skip(T.Mixin);
1393
1394 static if (is(Class == MixinDeclaration))
1395 {
1396 if (consumed(T.LParen))
1397 {
1398 auto e = parseAssignExpression();
1399 require(T.RParen);
1400 require(T.Semicolon);
1401 return new MixinDeclaration(e);
1402 }
1403 }
1404
1405 auto begin = token;
1406 Expression e;
1407 Identifier* mixinIdent;
1408
1409 if (consumed(T.Dot))
1410 e = set(new ModuleScopeExpression(parseIdentifierExpression()), begin);
1411 else
1412 e = parseIdentifierExpression();
1413
1414 while (consumed(T.Dot))
1415 e = set(new DotExpression(e, parseIdentifierExpression()), begin);
1416
1417 mixinIdent = optionalIdentifier();
1418 require(T.Semicolon);
1419
1420 return new Class(e, mixinIdent);
1421 }
1422
1423 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1424 | Statement parsing methods |
1425 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1426
1427 CompoundStatement parseStatements()
1428 {
1429 auto begin = token;
1430 require(T.LBrace);
1431 auto statements = new CompoundStatement();
1432 while (token.kind != T.RBrace && token.kind != T.EOF)
1433 statements ~= parseStatement();
1434 require(T.RBrace);
1435 return set(statements, begin);
1436 }
1437
1438 /// Parses a Statement.
1439 Statement parseStatement()
1440 {
1441 auto begin = token;
1442 Statement s;
1443 Declaration d;
1444
1445 if (token.isIntegralType)
1446 {
1447 d = parseVariableOrFunction();
1448 goto LreturnDeclarationStatement;
1449 }
1450
1451 switch (token.kind)
1452 {
1453 case T.Align:
1454 uint size = parseAlignAttribute();
1455 // Restrict align attribute to structs in parsing phase.
1456 StructDeclaration structDecl;
1457 if (token.kind == T.Struct)
1458 {
1459 auto begin2 = token;
1460 structDecl = parseStructOrUnionDeclaration().to!(StructDeclaration);
1461 structDecl.setAlignSize(size);
1462 set(structDecl, begin2);
1463 }
1464 else
1465 expected(T.Struct);
1466
1467 d = new AlignDeclaration(size, structDecl ? cast(Declaration)structDecl : new CompoundDeclaration);
1468 goto LreturnDeclarationStatement;
1469 /+ Not applicable for statements.
1470 T.Private, T.Package, T.Protected, T.Public, T.Export,
1471 T.Deprecated, T.Override, T.Abstract,+/
1472 case T.Extern,
1473 T.Final,
1474 T.Const,
1475 T.Auto:
1476 //T.Scope
1477 //T.Static
1478 case_parseAttribute:
1479 s = parseAttributeStatement();
1480 return s;
1481 case T.Identifier:
1482 if (peekNext() == T.Colon)
1483 {
1484 auto ident = token.ident;
1485 skip(T.Identifier); skip(T.Colon);
1486 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement());
1487 break;
1488 }
1489 goto case T.Dot;
1490 case T.Dot, T.Typeof:
1491 bool success;
1492 d = try_(delegate {
1493 return parseVariableOrFunction(StorageClass.None,
1494 Protection.None,
1495 LinkageType.None, false, false);
1496 }, success
1497 );
1498 if (success)
1499 goto LreturnDeclarationStatement; // Declaration
1500 else
1501 goto case_parseExpressionStatement; // Expression
1502
1503 case T.If:
1504 s = parseIfStatement();
1505 break;
1506 case T.While:
1507 s = parseWhileStatement();
1508 break;
1509 case T.Do:
1510 s = parseDoWhileStatement();
1511 break;
1512 case T.For:
1513 s = parseForStatement();
1514 break;
1515 case T.Foreach, T.Foreach_reverse:
1516 s = parseForeachStatement();
1517 break;
1518 case T.Switch:
1519 s = parseSwitchStatement();
1520 break;
1521 case T.Case:
1522 s = parseCaseStatement();
1523 break;
1524 case T.Default:
1525 s = parseDefaultStatement();
1526 break;
1527 case T.Continue:
1528 s = parseContinueStatement();
1529 break;
1530 case T.Break:
1531 s = parseBreakStatement();
1532 break;
1533 case T.Return:
1534 s = parseReturnStatement();
1535 break;
1536 case T.Goto:
1537 s = parseGotoStatement();
1538 break;
1539 case T.With:
1540 s = parseWithStatement();
1541 break;
1542 case T.Synchronized:
1543 s = parseSynchronizedStatement();
1544 break;
1545 case T.Try:
1546 s = parseTryStatement();
1547 break;
1548 case T.Throw:
1549 s = parseThrowStatement();
1550 break;
1551 case T.Scope:
1552 if (peekNext() != T.LParen)
1553 goto case_parseAttribute;
1554 s = parseScopeGuardStatement();
1555 break;
1556 case T.Volatile:
1557 s = parseVolatileStatement();
1558 break;
1559 case T.Asm:
1560 s = parseAsmBlockStatement();
1561 break;
1562 case T.Pragma:
1563 s = parsePragmaStatement();
1564 break;
1565 case T.Mixin:
1566 if (peekNext() == T.LParen)
1567 goto case_parseExpressionStatement; // Parse as expression.
1568 s = parseMixin!(MixinStatement)();
1569 break;
1570 case T.Static:
1571 switch (peekNext())
1572 {
1573 case T.If:
1574 s = parseStaticIfStatement();
1575 break;
1576 case T.Assert:
1577 s = parseStaticAssertStatement();
1578 break;
1579 default:
1580 goto case_parseAttribute;
1581 }
1582 break;
1583 case T.Debug:
1584 s = parseDebugStatement();
1585 break;
1586 case T.Version:
1587 s = parseVersionStatement();
1588 break;
1589 // DeclDef
1590 case T.Alias, T.Typedef:
1591 d = parseDeclarationDefinition();
1592 goto LreturnDeclarationStatement;
1593 case T.Enum:
1594 d = parseEnumDeclaration();
1595 goto LreturnDeclarationStatement;
1596 case T.Class:
1597 d = parseClassDeclaration();
1598 goto LreturnDeclarationStatement;
1599 case T.Interface:
1600 d = parseInterfaceDeclaration();
1601 goto LreturnDeclarationStatement;
1602 case T.Struct, T.Union:
1603 d = parseStructOrUnionDeclaration();
1604 // goto LreturnDeclarationStatement;
1605 LreturnDeclarationStatement:
1606 set(d, begin);
1607 s = new DeclarationStatement(d);
1608 break;
1609 case T.LBrace:
1610 s = parseScopeStatement();
1611 break;
1612 case T.Semicolon:
1613 nT();
1614 s = new EmptyStatement();
1615 break;
1616 // Parse an ExpressionStatement:
1617 // Tokens that start a PrimaryExpression.
1618 // case T.Identifier, T.Dot, T.Typeof:
1619 case T.This:
1620 case T.Super:
1621 case T.Null:
1622 case T.True, T.False:
1623 // case T.Dollar:
1624 case T.Int32, T.Int64, T.Uint32, T.Uint64:
1625 case T.Float32, T.Float64, T.Float80,
1626 T.Imaginary32, T.Imaginary64, T.Imaginary80:
1627 case T.CharLiteral:
1628 case T.String:
1629 case T.LBracket:
1630 // case T.LBrace:
1631 case T.Function, T.Delegate:
1632 case T.Assert:
1633 // case T.Mixin:
1634 case T.Import:
1635 case T.Typeid:
1636 case T.Is:
1637 case T.LParen:
1638 case T.Traits: // D2.0
1639 // Tokens that can start a UnaryExpression:
1640 case T.AndBinary, T.PlusPlus, T.MinusMinus, T.Mul, T.Minus,
1641 T.Plus, T.Not, T.Tilde, T.New, T.Delete, T.Cast:
1642 case_parseExpressionStatement:
1643 s = new ExpressionStatement(parseExpression());
1644 require(T.Semicolon);
1645 break;
1646 default:
1647 if (token.isSpecialToken)
1648 goto case_parseExpressionStatement;
1649
1650 if (token.kind != T.Dollar)
1651 // Assert that this isn't a valid expression.
1652 assert(delegate bool(){
1653 bool success;
1654 auto expression = try_(&parseExpression, success);
1655 return success;
1656 }() == false, "Didn't expect valid expression."
1657 );
1658
1659 // Report error: it's an illegal statement.
1660 s = new IllegalStatement();
1661 // Skip to next valid token.
1662 do
1663 nT();
1664 while (!token.isStatementStart &&
1665 token.kind != T.RBrace &&
1666 token.kind != T.EOF)
1667 auto text = Token.textSpan(begin, this.prevToken);
1668 error(begin, MSG.IllegalStatement, text);
1669 }
1670 assert(s !is null);
1671 set(s, begin);
1672 return s;
1673 }
1674
1675 /// $(PRE
1676 /// Parses a ScopeStatement.
1677 /// ScopeStatement :=
1678 /// NoScopeStatement
1679 /// )
1680 Statement parseScopeStatement()
1681 {
1682 return new ScopeStatement(parseNoScopeStatement());
1683 }
1684
1685 /// $(PRE
1686 /// NoScopeStatement :=
1687 /// NonEmptyStatement
1688 /// BlockStatement
1689 /// BlockStatement :=
1690 /// { }
1691 /// { StatementList }
1692 /// )
1693 Statement parseNoScopeStatement()
1694 {
1695 auto begin = token;
1696 Statement s;
1697 if (consumed(T.LBrace))
1698 {
1699 auto ss = new CompoundStatement();
1700 while (token.kind != T.RBrace && token.kind != T.EOF)
1701 ss ~= parseStatement();
1702 require(T.RBrace);
1703 s = set(ss, begin);
1704 }
1705 else if (token.kind == T.Semicolon)
1706 {
1707 error(token, MSG.ExpectedNonEmptyStatement);
1708 nT();
1709 s = set(new EmptyStatement(), begin);
1710 }
1711 else
1712 s = parseStatement();
1713 return s;
1714 }
1715
1716 /// $(PRE
1717 /// NoScopeOrEmptyStatement :=
1718 /// ;
1719 /// NoScopeStatement
1720 /// )
1721 Statement parseNoScopeOrEmptyStatement()
1722 {
1723 if (consumed(T.Semicolon))
1724 return set(new EmptyStatement(), this.prevToken);
1725 else
1726 return parseNoScopeStatement();
1727 }
1728
1729 Statement parseAttributeStatement()
1730 {
1731 StorageClass stc, stc_tmp;
1732 LinkageType prev_linkageType;
1733
1734 Declaration parse() // Nested function.
1735 {
1736 auto begin = token;
1737 Declaration d;
1738 switch (token.kind)
1739 {
1740 case T.Extern:
1741 if (peekNext() != T.LParen)
1742 {
1743 stc_tmp = StorageClass.Extern;
1744 goto Lcommon;
1745 }
1746
1747 nT();
1748 auto linkageType = parseLinkageType();
1749 checkLinkageType(prev_linkageType, linkageType, begin);
1750
1751 d = new LinkageDeclaration(linkageType, parse());
1752 break;
1753 case T.Static:
1754 stc_tmp = StorageClass.Static;
1755 goto Lcommon;
1756 case T.Final:
1757 stc_tmp = StorageClass.Final;
1758 goto Lcommon;
1759 case T.Const:
1760 version(D2)
1761 {
1762 if (peekNext() == T.LParen)
1763 goto case_Declaration;
1764 }
1765 stc_tmp = StorageClass.Const;
1766 goto Lcommon;
1767 version(D2)
1768 {
1769 case T.Invariant: // D 2.0
1770 if (peekNext() == T.LParen)
1771 goto case_Declaration;
1772 stc_tmp = StorageClass.Invariant;
1773 goto Lcommon;
1774 }
1775 case T.Auto:
1776 stc_tmp = StorageClass.Auto;
1777 goto Lcommon;
1778 case T.Scope:
1779 stc_tmp = StorageClass.Scope;
1780 goto Lcommon;
1781 Lcommon:
1782 // Issue error if redundant.
1783 if (stc & stc_tmp)
1784 error(MID.RedundantStorageClass, token.srcText);
1785 else
1786 stc |= stc_tmp;
1787
1788 nT();
1789 d = new StorageClassDeclaration(stc_tmp, parse());
1790 break;
1791 // TODO: allow "scope class", "abstract scope class" in function bodies?
1792 //case T.Class:
1793 default:
1794 case_Declaration:
1795 return parseVariableOrFunction(stc, Protection.None, prev_linkageType, true);
1796 }
1797 return set(d, begin);
1798 }
1799 return new DeclarationStatement(parse());
1800 }
1801
1802 Statement parseIfStatement()
1803 {
1804 skip(T.If);
1805
1806 Statement variable;
1807 Expression condition;
1808 Statement ifBody, elseBody;
1809
1810 require(T.LParen);
1811
1812 Identifier* ident;
1813 auto begin = token; // For start of AutoDeclaration or normal Declaration.
1814 // auto Identifier = Expression
1815 if (consumed(T.Auto))
1816 {
1817 ident = requireIdentifier(MSG.ExpectedVariableName);
1818 require(T.Assign);
1819 auto init = parseExpression();
1820 auto v = new VariablesDeclaration(null, [ident], [init]);
1821 set(v, begin.nextNWS);
1822 auto d = new StorageClassDeclaration(StorageClass.Auto, v);
1823 set(d, begin);
1824 variable = new DeclarationStatement(d);
1825 set(variable, begin);
1826 }
1827 else
1828 { // Declarator = Expression
1829 Type parseDeclaratorAssign()
1830 {
1831 auto type = parseDeclarator(ident);
1832 require(T.Assign);
1833 return type;
1834 }
1835 bool success;
1836 auto type = try_(&parseDeclaratorAssign, success);
1837 if (success)
1838 {
1839 auto init = parseExpression();
1840 auto v = new VariablesDeclaration(type, [ident], [init]);
1841 set(v, begin);
1842 variable = new DeclarationStatement(v);
1843 set(variable, begin);
1844 }
1845 else
1846 condition = parseExpression();
1847 }
1848 require(T.RParen);
1849 ifBody = parseScopeStatement();
1850 if (consumed(T.Else))
1851 elseBody = parseScopeStatement();
1852 return new IfStatement(variable, condition, ifBody, elseBody);
1853 }
1854
1855 Statement parseWhileStatement()
1856 {
1857 skip(T.While);
1858 require(T.LParen);
1859 auto condition = parseExpression();
1860 require(T.RParen);
1861 return new WhileStatement(condition, parseScopeStatement());
1862 }
1863
1864 Statement parseDoWhileStatement()
1865 {
1866 skip(T.Do);
1867 auto doBody = parseScopeStatement();
1868 require(T.While);
1869 require(T.LParen);
1870 auto condition = parseExpression();
1871 require(T.RParen);
1872 return new DoWhileStatement(condition, doBody);
1873 }
1874
1875 Statement parseForStatement()
1876 {
1877 skip(T.For);
1878
1879 Statement init, forBody;
1880 Expression condition, increment;
1881
1882 require(T.LParen);
1883 if (!consumed(T.Semicolon))
1884 init = parseNoScopeStatement();
1885 if (token.kind != T.Semicolon)
1886 condition = parseExpression();
1887 require(T.Semicolon);
1888 if (token.kind != T.RParen)
1889 increment = parseExpression();
1890 require(T.RParen);
1891 forBody = parseScopeStatement();
1892 return new ForStatement(init, condition, increment, forBody);
1893 }
1894
1895 Statement parseForeachStatement()
1896 {
1897 assert(token.kind == T.Foreach || token.kind == T.Foreach_reverse);
1898 TOK tok = token.kind;
1899 nT();
1900
1901 auto params = new Parameters;
1902 Expression e; // Aggregate or LwrExpression
1903
1904 require(T.LParen);
1905 auto paramsBegin = token;
1906 do
1907 {
1908 auto paramBegin = token;
1909 StorageClass stc;
1910 Type type;
1911 Identifier* ident;
1912
1913 switch (token.kind)
1914 {
1915 case T.Ref, T.Inout:
1916 stc = StorageClass.Ref;
1917 nT();
1918 // fall through
1919 case T.Identifier:
1920 auto next = peekNext();
1921 if (next == T.Comma || next == T.Semicolon || next == T.RParen)
1922 {
1923 ident = requireIdentifier(MSG.ExpectedVariableName);
1924 break;
1925 }
1926 // fall through
1927 default:
1928 type = parseDeclarator(ident);
1929 }
1930
1931 params ~= set(new Parameter(stc, type, ident, null), paramBegin);
1932 } while (consumed(T.Comma))
1933 set(params, paramsBegin);
1934 require(T.Semicolon);
1935 e = parseExpression();
1936 version(D2)
1937 { //Foreach (ForeachType; LwrExpression .. UprExpression ) ScopeStatement
1938 if (consumed(T.Slice))
1939 {
1940 // if (params.length != 1)
1941 // error(MID.XYZ); // TODO: issue error msg
1942 auto upper = parseExpression();
1943 require(T.RParen);
1944 auto forBody = parseScopeStatement();
1945 return new ForeachRangeStatement(tok, params, e, upper, forBody);
1946 }
1947 }
1948 // Foreach (ForeachTypeList; Aggregate) ScopeStatement
1949 require(T.RParen);
1950 auto forBody = parseScopeStatement();
1951 return new ForeachStatement(tok, params, e, forBody);
1952 }
1953
1954 Statement parseSwitchStatement()
1955 {
1956 skip(T.Switch);
1957 require(T.LParen);
1958 auto condition = parseExpression();
1959 require(T.RParen);
1960 auto switchBody = parseScopeStatement();
1961 return new SwitchStatement(condition, switchBody);
1962 }
1963
1964 /// Helper function for parsing the body of a default or case statement.
1965 Statement parseCaseOrDefaultBody()
1966 {
1967 // This function is similar to parseNoScopeStatement()
1968 auto begin = token;
1969 auto s = new CompoundStatement();
1970 while (token.kind != T.Case &&
1971 token.kind != T.Default &&
1972 token.kind != T.RBrace &&
1973 token.kind != T.EOF)
1974 s ~= parseStatement();
1975 set(s, begin);
1976 return set(new ScopeStatement(s), begin);
1977 }
1978
1979 Statement parseCaseStatement()
1980 {
1981 skip(T.Case);
1982 auto values = parseExpressionList();
1983 require(T.Colon);
1984 auto caseBody = parseCaseOrDefaultBody();
1985 return new CaseStatement(values, caseBody);
1986 }
1987
1988 Statement parseDefaultStatement()
1989 {
1990 skip(T.Default);
1991 require(T.Colon);
1992 auto defaultBody = parseCaseOrDefaultBody();
1993 return new DefaultStatement(defaultBody);
1994 }
1995
1996 Statement parseContinueStatement()
1997 {
1998 skip(T.Continue);
1999 auto ident = optionalIdentifier();
2000 require(T.Semicolon);
2001 return new ContinueStatement(ident);
2002 }
2003
2004 Statement parseBreakStatement()
2005 {
2006 skip(T.Break);
2007 auto ident = optionalIdentifier();
2008 require(T.Semicolon);
2009 return new BreakStatement(ident);
2010 }
2011
2012 Statement parseReturnStatement()
2013 {
2014 skip(T.Return);
2015 Expression expr;
2016 if (token.kind != T.Semicolon)
2017 expr = parseExpression();
2018 require(T.Semicolon);
2019 return new ReturnStatement(expr);
2020 }
2021
2022 Statement parseGotoStatement()
2023 {
2024 skip(T.Goto);
2025 Identifier* ident;
2026 Expression caseExpr;
2027 switch (token.kind)
2028 {
2029 case T.Case:
2030 ident = token.ident;
2031 nT();
2032 if (token.kind == T.Semicolon)
2033 break;
2034 caseExpr = parseExpression();
2035 break;
2036 case T.Default:
2037 ident = token.ident;
2038 nT();
2039 break;
2040 default:
2041 ident = requireIdentifier(MSG.ExpectedAnIdentifier);
2042 }
2043 require(T.Semicolon);
2044 return new GotoStatement(ident, caseExpr);
2045 }
2046
2047 Statement parseWithStatement()
2048 {
2049 skip(T.With);
2050 require(T.LParen);
2051 auto expr = parseExpression();
2052 require(T.RParen);
2053 return new WithStatement(expr, parseScopeStatement());
2054 }
2055
2056 Statement parseSynchronizedStatement()
2057 {
2058 skip(T.Synchronized);
2059 Expression expr;
2060 if (consumed(T.LParen))
2061 {
2062 expr = parseExpression();
2063 require(T.RParen);
2064 }
2065 return new SynchronizedStatement(expr, parseScopeStatement());
2066 }
2067
2068 Statement parseTryStatement()
2069 {
2070 auto begin = token;
2071 skip(T.Try);
2072
2073 auto tryBody = parseScopeStatement();
2074 CatchStatement[] catchBodies;
2075 FinallyStatement finBody;
2076
2077 while (consumed(T.Catch))
2078 {
2079 Parameter param;
2080 if (consumed(T.LParen))
2081 {
2082 auto begin2 = token;
2083 Identifier* ident;
2084 auto type = parseDeclarator(ident, true);
2085 param = new Parameter(StorageClass.None, type, ident, null);
2086 set(param, begin2);
2087 require(T.RParen);
2088 }
2089 catchBodies ~= set(new CatchStatement(param, parseNoScopeStatement()), begin);
2090 if (param is null)
2091 break; // This is a LastCatch
2092 begin = token;
2093 }
2094
2095 if (consumed(T.Finally))
2096 finBody = set(new FinallyStatement(parseNoScopeStatement()), prevToken);
2097
2098 if (catchBodies.length == 0 && finBody is null)
2099 assert(begin.kind == T.Try), error(begin, MSG.MissingCatchOrFinally);
2100
2101 return new TryStatement(tryBody, catchBodies, finBody);
2102 }
2103
2104 Statement parseThrowStatement()
2105 {
2106 skip(T.Throw);
2107 auto expr = parseExpression();
2108 require(T.Semicolon);
2109 return new ThrowStatement(expr);
2110 }
2111
2112 Statement parseScopeGuardStatement()
2113 {
2114 skip(T.Scope);
2115 skip(T.LParen);
2116 auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier);
2117 if (condition)
2118 switch (condition.idKind)
2119 {
2120 case IDK.exit, IDK.success, IDK.failure:
2121 break;
2122 default:
2123 error(this.prevToken, MSG.InvalidScopeIdentifier, this.prevToken.srcText);
2124 }
2125 require(T.RParen);
2126 Statement scopeBody;
2127 if (token.kind == T.LBrace)
2128 scopeBody = parseScopeStatement();
2129 else
2130 scopeBody = parseNoScopeStatement();
2131 return new ScopeGuardStatement(condition, scopeBody);
2132 }
2133
2134 Statement parseVolatileStatement()
2135 {
2136 skip(T.Volatile);
2137 Statement volatileBody;
2138 if (token.kind == T.Semicolon)
2139 nT();
2140 else if (token.kind == T.LBrace)
2141 volatileBody = parseScopeStatement();
2142 else
2143 volatileBody = parseStatement();
2144 return new VolatileStatement(volatileBody);
2145 }
2146
2147 Statement parsePragmaStatement()
2148 {
2149 skip(T.Pragma);
2150
2151 Identifier* ident;
2152 Expression[] args;
2153 Statement pragmaBody;
2154
2155 require(T.LParen);
2156 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
2157
2158 if (consumed(T.Comma))
2159 args = parseExpressionList();
2160 require(T.RParen);
2161
2162 pragmaBody = parseNoScopeOrEmptyStatement();
2163
2164 return new PragmaStatement(ident, args, pragmaBody);
2165 }
2166
2167 Statement parseStaticIfStatement()
2168 {
2169 skip(T.Static);
2170 skip(T.If);
2171 Expression condition;
2172 Statement ifBody, elseBody;
2173
2174 require(T.LParen);
2175 condition = parseExpression();
2176 require(T.RParen);
2177 ifBody = parseNoScopeStatement();
2178 if (consumed(T.Else))
2179 elseBody = parseNoScopeStatement();
2180 return new StaticIfStatement(condition, ifBody, elseBody);
2181 }
2182
2183 Statement parseStaticAssertStatement()
2184 {
2185 skip(T.Static);
2186 skip(T.Assert);
2187 Expression condition, message;
2188
2189 require(T.LParen);
2190 condition = parseAssignExpression(); // Condition.
2191 if (consumed(T.Comma))
2192 message = parseAssignExpression(); // Error message.
2193 require(T.RParen);
2194 require(T.Semicolon);
2195 return new StaticAssertStatement(condition, message);
2196 }
2197
2198 Statement parseDebugStatement()
2199 {
2200 skip(T.Debug);
2201 Token* cond;
2202 Statement debugBody, elseBody;
2203
2204 // ( Condition )
2205 if (consumed(T.LParen))
2206 {
2207 cond = parseIdentOrInt();
2208 require(T.RParen);
2209 }
2210 // debug Statement
2211 // debug ( Condition ) Statement
2212 debugBody = parseNoScopeStatement();
2213 // else Statement
2214 if (consumed(T.Else))
2215 elseBody = parseNoScopeStatement();
2216
2217 return new DebugStatement(cond, debugBody, elseBody);
2218 }
2219
2220 Statement parseVersionStatement()
2221 {
2222 skip(T.Version);
2223 Token* cond;
2224 Statement versionBody, elseBody;
2225
2226 // ( Condition )
2227 require(T.LParen);
2228 cond = parseIdentOrInt();
2229 require(T.RParen);
2230 // version ( Condition ) Statement
2231 versionBody = parseNoScopeStatement();
2232 // else Statement
2233 if (consumed(T.Else))
2234 elseBody = parseNoScopeStatement();
2235
2236 return new VersionStatement(cond, versionBody, elseBody);
2237 }
2238
2239 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2240 | Assembler parsing methods |
2241 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2242
2243 /// Parses an AsmBlockStatement.
2244 Statement parseAsmBlockStatement()
2245 {
2246 skip(T.Asm);
2247 require(T.LBrace);
2248 auto ss = new CompoundStatement;
2249 while (token.kind != T.RBrace && token.kind != T.EOF)
2250 ss ~= parseAsmStatement();
2251 require(T.RBrace);
2252 return new AsmBlockStatement(ss);
2253 }
2254
2255 Statement parseAsmStatement()
2256 {
2257 auto begin = token;
2258 Statement s;
2259 Identifier* ident;
2260 switch (token.kind)
2261 {
2262 // Keywords that are valid opcodes.
2263 case T.In, T.Int, T.Out:
2264 ident = token.ident;
2265 nT();
2266 goto LOpcode;
2267 case T.Identifier:
2268 ident = token.ident;
2269 nT();
2270 if (consumed(T.Colon))
2271 { // Identifier : AsmStatement
2272 s = new LabeledStatement(ident, parseAsmStatement());
2273 break;
2274 }
2275
2276 LOpcode:
2277 // Opcode ;
2278 // Opcode Operands ;
2279 // Opcode
2280 // Identifier
2281 Expression[] es;
2282 if (token.kind != T.Semicolon)
2283 do
2284 es ~= parseAsmExpression();
2285 while (consumed(T.Comma))
2286 require(T.Semicolon);
2287 s = new AsmStatement(ident, es);
2288 break;
2289 case T.Align:
2290 // align Integer;
2291 nT();
2292 int number = -1;
2293 if (token.kind == T.Int32)
2294 (number = token.int_), skip(T.Int32);
2295 else
2296 error(token, MSG.ExpectedIntegerAfterAlign, token.srcText);
2297 require(T.Semicolon);
2298 s = new AsmAlignStatement(number);
2299 break;
2300 case T.Semicolon:
2301 s = new EmptyStatement();
2302 nT();
2303 break;
2304 default:
2305 s = new IllegalAsmStatement();
2306 // Skip to next valid token.
2307 do
2308 nT();
2309 while (!token.isAsmStatementStart &&
2310 token.kind != T.RBrace &&
2311 token.kind != T.EOF)
2312 auto text = Token.textSpan(begin, this.prevToken);
2313 error(begin, MSG.IllegalAsmStatement, text);
2314 }
2315 set(s, begin);
2316 return s;
2317 }
2318
2319 Expression parseAsmExpression()
2320 {
2321 auto begin = token;
2322 auto e = parseAsmOrOrExpression();
2323 if (consumed(T.Question))
2324 {
2325 auto tok = this.prevToken;
2326 auto iftrue = parseAsmExpression();
2327 require(T.Colon);
2328 auto iffalse = parseAsmExpression();
2329 e = new CondExpression(e, iftrue, iffalse, tok);
2330 set(e, begin);
2331 }
2332 // TODO: create AsmExpression that contains e?
2333 return e;
2334 }
2335
2336 Expression parseAsmOrOrExpression()
2337 {
2338 alias parseAsmAndAndExpression parseNext;
2339 auto begin = token;
2340 auto e = parseNext();
2341 while (token.kind == T.OrLogical)
2342 {
2343 auto tok = token;
2344 nT();
2345 e = new OrOrExpression(e, parseNext(), tok);
2346 set(e, begin);
2347 }
2348 return e;
2349 }
2350
2351 Expression parseAsmAndAndExpression()
2352 {
2353 alias parseAsmOrExpression parseNext;
2354 auto begin = token;
2355 auto e = parseNext();
2356 while (token.kind == T.AndLogical)
2357 {
2358 auto tok = token;
2359 nT();
2360 e = new AndAndExpression(e, parseNext(), tok);
2361 set(e, begin);
2362 }
2363 return e;
2364 }
2365
2366 Expression parseAsmOrExpression()
2367 {
2368 alias parseAsmXorExpression parseNext;
2369 auto begin = token;
2370 auto e = parseNext();
2371 while (token.kind == T.OrBinary)
2372 {
2373 auto tok = token;
2374 nT();
2375 e = new OrExpression(e, parseNext(), tok);
2376 set(e, begin);
2377 }
2378 return e;
2379 }
2380
2381 Expression parseAsmXorExpression()
2382 {
2383 alias parseAsmAndExpression parseNext;
2384 auto begin = token;
2385 auto e = parseNext();
2386 while (token.kind == T.Xor)
2387 {
2388 auto tok = token;
2389 nT();
2390 e = new XorExpression(e, parseNext(), tok);
2391 set(e, begin);
2392 }
2393 return e;
2394 }
2395
2396 Expression parseAsmAndExpression()
2397 {
2398 alias parseAsmCmpExpression parseNext;
2399 auto begin = token;
2400 auto e = parseNext();
2401 while (token.kind == T.AndBinary)
2402 {
2403 auto tok = token;
2404 nT();
2405 e = new AndExpression(e, parseNext(), tok);
2406 set(e, begin);
2407 }
2408 return e;
2409 }
2410
2411 Expression parseAsmCmpExpression()
2412 {
2413 alias parseAsmShiftExpression parseNext;
2414 auto begin = token;
2415 auto e = parseNext();
2416
2417 auto operator = token;
2418 switch (operator.kind)
2419 {
2420 case T.Equal, T.NotEqual:
2421 nT();
2422 e = new EqualExpression(e, parseNext(), operator);
2423 break;
2424 case T.LessEqual, T.Less, T.GreaterEqual, T.Greater:
2425 nT();
2426 e = new RelExpression(e, parseNext(), operator);
2427 break;
2428 default:
2429 return e;
2430 }
2431 set(e, begin);
2432 return e;
2433 }
2434
2435 Expression parseAsmShiftExpression()
2436 {
2437 alias parseAsmAddExpression parseNext;
2438 auto begin = token;
2439 auto e = parseNext();
2440 while (1)
2441 {
2442 auto operator = token;
2443 switch (operator.kind)
2444 {
2445 case T.LShift: nT(); e = new LShiftExpression(e, parseNext(), operator); break;
2446 case T.RShift: nT(); e = new RShiftExpression(e, parseNext(), operator); break;
2447 case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
2448 default:
2449 return e;
2450 }
2451 set(e, begin);
2452 }
2453 assert(0);
2454 }
2455
2456 Expression parseAsmAddExpression()
2457 {
2458 alias parseAsmMulExpression parseNext;
2459 auto begin = token;
2460 auto e = parseNext();
2461 while (1)
2462 {
2463 auto operator = token;
2464 switch (operator.kind)
2465 {
2466 case T.Plus: nT(); e = new PlusExpression(e, parseNext(), operator); break;
2467 case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
2468 // Not allowed in asm
2469 //case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
2470 default:
2471 return e;
2472 }
2473 set(e, begin);
2474 }
2475 assert(0);
2476 }
2477
2478 Expression parseAsmMulExpression()
2479 {
2480 alias parseAsmPostExpression parseNext;
2481 auto begin = token;
2482 auto e = parseNext();
2483 while (1)
2484 {
2485 auto operator = token;
2486 switch (operator.kind)
2487 {
2488 case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
2489 case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
2490 case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
2491 default:
2492 return e;
2493 }
2494 set(e, begin);
2495 }
2496 assert(0);
2497 }
2498
2499 Expression parseAsmPostExpression()
2500 {
2501 auto begin = token;
2502 auto e = parseAsmUnaryExpression();
2503 while (consumed(T.LBracket))
2504 {
2505 e = new AsmPostBracketExpression(e, parseAsmExpression());
2506 require(T.RBracket);
2507 set(e, begin);
2508 }
2509 return e;
2510 }
2511
2512 Expression parseAsmUnaryExpression()
2513 {
2514 auto begin = token;
2515 Expression e;
2516 switch (token.kind)
2517 {
2518 case T.Byte, T.Short, T.Int,
2519 T.Float, T.Double, T.Real:
2520 goto LAsmTypePrefix;
2521 case T.Identifier:
2522 switch (token.ident.idKind)
2523 {
2524 case IDK.near, IDK.far,/* "byte", "short", "int",*/
2525 IDK.word, IDK.dword, IDK.qword/*, "float", "double", "real"*/:
2526 LAsmTypePrefix:
2527 nT();
2528 if (token.kind == T.Identifier && token.ident is Ident.ptr)
2529 skip(T.Identifier);
2530 else
2531 error(MID.ExpectedButFound, "ptr", token.srcText);
2532 e = new AsmTypeExpression(parseAsmExpression());
2533 break;
2534 case IDK.offset:
2535 nT();
2536 e = new AsmOffsetExpression(parseAsmExpression());
2537 break;
2538 case IDK.seg:
2539 nT();
2540 e = new AsmSegExpression(parseAsmExpression());
2541 break;
2542 default:
2543 goto LparseAsmPrimaryExpression;
2544 }
2545 break;
2546 case T.Minus:
2547 case T.Plus:
2548 nT();
2549 e = new SignExpression(parseAsmUnaryExpression());
2550 break;
2551 case T.Not:
2552 nT();
2553 e = new NotExpression(parseAsmUnaryExpression());
2554 break;
2555 case T.Tilde:
2556 nT();
2557 e = new CompExpression(parseAsmUnaryExpression());
2558 break;
2559 case T.Dot:
2560 nT();
2561 e = new ModuleScopeExpression(parseIdentifierExpression());
2562 while (consumed(TOK.Dot))
2563 {
2564 e = new DotExpression(e, parseIdentifierExpression());
2565 set(e, begin);
2566 }
2567 break;
2568 default:
2569 LparseAsmPrimaryExpression:
2570 e = parseAsmPrimaryExpression();
2571 return e;
2572 }
2573 set(e, begin);
2574 return e;
2575 }
2576
2577 Expression parseAsmPrimaryExpression()
2578 {
2579 auto begin = token;
2580 Expression e;
2581 switch (token.kind)
2582 {
2583 case T.Int32, T.Int64, T.Uint32, T.Uint64:
2584 e = new IntExpression(token);
2585 nT();
2586 break;
2587 case T.Float32, T.Float64, T.Float80,
2588 T.Imaginary32, T.Imaginary64, T.Imaginary80:
2589 e = new RealExpression(token);
2590 nT();
2591 break;
2592 case T.Dollar:
2593 e = new DollarExpression();
2594 nT();
2595 break;
2596 case T.LBracket:
2597 // [ AsmExpression ]
2598 nT();
2599 e = parseAsmExpression();
2600 require(T.RBracket);
2601 e = new AsmBracketExpression(e);
2602 break;
2603 case T.Identifier:
2604 auto register = token.ident;
2605 switch (register.idKind)
2606 {
2607 // __LOCAL_SIZE
2608 case IDK.__LOCAL_SIZE:
2609 nT();
2610 e = new AsmLocalSizeExpression();
2611 break;
2612 // Register
2613 case IDK.ST:
2614 nT();
2615 // (1) - (7)
2616 int number = -1;
2617 if (consumed(T.LParen))
2618 {
2619 if (token.kind == T.Int32)
2620 (number = token.int_), skip(T.Int32);
2621 else
2622 expected(T.Int32);
2623 require(T.RParen);
2624 }
2625 e = new AsmRegisterExpression(register, number);
2626 break;
2627 case IDK.FS:
2628 nT();
2629 // TODO: is the colon-number part optional?
2630 int number = -1;
2631 if (consumed(T.Colon))
2632 {
2633 // :0, :4, :8
2634 if (token.kind == T.Int32)
2635 (number = token.int_), skip(T.Int32);
2636 if (number != 0 && number != 4 && number != 8)
2637 error(MID.ExpectedButFound, "0, 4 or 8", token.srcText);
2638 }
2639 e = new AsmRegisterExpression(register, number);
2640 break;
2641 case IDK.AL, IDK.AH, IDK.AX, IDK.EAX,
2642 IDK.BL, IDK.BH, IDK.BX, IDK.EBX,
2643 IDK.CL, IDK.CH, IDK.CX, IDK.ECX,
2644 IDK.DL, IDK.DH, IDK.DX, IDK.EDX,
2645 IDK.BP, IDK.EBP, IDK.SP, IDK.ESP,
2646 IDK.DI, IDK.EDI, IDK.SI, IDK.ESI,
2647 IDK.ES, IDK.CS, IDK.SS, IDK.DS, IDK.GS,
2648 IDK.CR0, IDK.CR2, IDK.CR3, IDK.CR4,
2649 IDK.DR0, IDK.DR1, IDK.DR2, IDK.DR3, IDK.DR6, IDK.DR7,
2650 IDK.TR3, IDK.TR4, IDK.TR5, IDK.TR6, IDK.TR7,
2651 IDK.MM0, IDK.MM1, IDK.MM2, IDK.MM3,
2652 IDK.MM4, IDK.MM5, IDK.MM6, IDK.MM7,
2653 IDK.XMM0, IDK.XMM1, IDK.XMM2, IDK.XMM3,
2654 IDK.XMM4, IDK.XMM5, IDK.XMM6, IDK.XMM7:
2655 nT();
2656 e = new AsmRegisterExpression(register);
2657 break;
2658 default:
2659 e = parseIdentifierExpression();
2660 while (consumed(TOK.Dot))
2661 {
2662 e = new DotExpression(e, parseIdentifierExpression());
2663 set(e, begin);
2664 }
2665 } // end of switch
2666 break;
2667 default:
2668 error(MID.ExpectedButFound, "Expression", token.srcText);
2669 e = new IllegalExpression();
2670 if (!trying)
2671 { // Insert a dummy token and don't consume current one.
2672 begin = lexer.insertEmptyTokenBefore(token);
2673 this.prevToken = begin;
2674 }
2675 }
2676 set(e, begin);
2677 return e;
2678 }
2679
2680 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2681 | Expression parsing methods |
2682 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2683
2684 /// Parses an Expression.
2685 Expression parseExpression()
2686 {
2687 alias parseAssignExpression parseNext;
2688 auto begin = token;
2689 auto e = parseNext();
2690 while (token.kind == T.Comma)
2691 {
2692 auto comma = token;
2693 nT();
2694 e = new CommaExpression(e, parseNext(), comma);
2695 set(e, begin);
2696 }
2697 return e;
2698 }
2699
2700 Expression parseAssignExpression()
2701 {
2702 alias parseAssignExpression parseNext;
2703 auto begin = token;
2704 auto e = parseCondExpression();
2705 switch (token.kind)
2706 {
2707 case T.Assign:
2708 nT(); e = new AssignExpression(e, parseNext()); break;
2709 case T.LShiftAssign:
2710 nT(); e = new LShiftAssignExpression(e, parseNext()); break;
2711 case T.RShiftAssign:
2712 nT(); e = new RShiftAssignExpression(e, parseNext()); break;
2713 case T.URShiftAssign:
2714 nT(); e = new URShiftAssignExpression(e, parseNext()); break;
2715 case T.OrAssign:
2716 nT(); e = new OrAssignExpression(e, parseNext()); break;
2717 case T.AndAssign:
2718 nT(); e = new AndAssignExpression(e, parseNext()); break;
2719 case T.PlusAssign:
2720 nT(); e = new PlusAssignExpression(e, parseNext()); break;
2721 case T.MinusAssign:
2722 nT(); e = new MinusAssignExpression(e, parseNext()); break;
2723 case T.DivAssign:
2724 nT(); e = new DivAssignExpression(e, parseNext()); break;
2725 case T.MulAssign:
2726 nT(); e = new MulAssignExpression(e, parseNext()); break;
2727 case T.ModAssign:
2728 nT(); e = new ModAssignExpression(e, parseNext()); break;
2729 case T.XorAssign:
2730 nT(); e = new XorAssignExpression(e, parseNext()); break;
2731 case T.CatAssign:
2732 nT(); e = new CatAssignExpression(e, parseNext()); break;
2733 default:
2734 return e;
2735 }
2736 set(e, begin);
2737 return e;
2738 }
2739
2740 Expression parseCondExpression()
2741 {
2742 auto begin = token;
2743 auto e = parseOrOrExpression();
2744 if (token.kind == T.Question)
2745 {
2746 auto tok = token;
2747 nT();
2748 auto iftrue = parseExpression();
2749 require(T.Colon);
2750 auto iffalse = parseCondExpression();
2751 e = new CondExpression(e, iftrue, iffalse, tok);
2752 set(e, begin);
2753 }
2754 return e;
2755 }
2756
2757 Expression parseOrOrExpression()
2758 {
2759 alias parseAndAndExpression parseNext;
2760 auto begin = token;
2761 auto e = parseNext();
2762 while (token.kind == T.OrLogical)
2763 {
2764 auto tok = token;
2765 nT();
2766 e = new OrOrExpression(e, parseNext(), tok);
2767 set(e, begin);
2768 }
2769 return e;
2770 }
2771
2772 Expression parseAndAndExpression()
2773 {
2774 alias parseOrExpression parseNext;
2775 auto begin = token;
2776 auto e = parseNext();
2777 while (token.kind == T.AndLogical)
2778 {
2779 auto tok = token;
2780 nT();
2781 e = new AndAndExpression(e, parseNext(), tok);
2782 set(e, begin);
2783 }
2784 return e;
2785 }
2786
2787 Expression parseOrExpression()
2788 {
2789 alias parseXorExpression parseNext;
2790 auto begin = token;
2791 auto e = parseNext();
2792 while (token.kind == T.OrBinary)
2793 {
2794 auto tok = token;
2795 nT();
2796 e = new OrExpression(e, parseNext(), tok);
2797 set(e, begin);
2798 }
2799 return e;
2800 }
2801
2802 Expression parseXorExpression()
2803 {
2804 alias parseAndExpression parseNext;
2805 auto begin = token;
2806 auto e = parseNext();
2807 while (token.kind == T.Xor)
2808 {
2809 auto tok = token;
2810 nT();
2811 e = new XorExpression(e, parseNext(), tok);
2812 set(e, begin);
2813 }
2814 return e;
2815 }
2816
2817 Expression parseAndExpression()
2818 {
2819 alias parseCmpExpression parseNext;
2820 auto begin = token;
2821 auto e = parseNext();
2822 while (token.kind == T.AndBinary)
2823 {
2824 auto tok = token;
2825 nT();
2826 e = new AndExpression(e, parseNext(), tok);
2827 set(e, begin);
2828 }
2829 return e;
2830 }
2831
2832 Expression parseCmpExpression()
2833 {
2834 alias parseShiftExpression parseNext;
2835 auto begin = token;
2836 auto e = parseShiftExpression();
2837
2838 auto operator = token;
2839 switch (operator.kind)
2840 {
2841 case T.Equal, T.NotEqual:
2842 nT();
2843 e = new EqualExpression(e, parseNext(), operator);
2844 break;
2845 case T.Not:
2846 if (peekNext() != T.Is)
2847 break;
2848 nT();
2849 // fall through
2850 case T.Is:
2851 nT();
2852 e = new IdentityExpression(e, parseNext(), operator);
2853 break;
2854 case T.LessEqual, T.Less, T.GreaterEqual, T.Greater,
2855 T.Unordered, T.UorE, T.UorG, T.UorGorE,
2856 T.UorL, T.UorLorE, T.LorEorG, T.LorG:
2857 nT();
2858 e = new RelExpression(e, parseNext(), operator);
2859 break;
2860 case T.In:
2861 nT();
2862 e = new InExpression(e, parseNext(), operator);
2863 break;
2864 default:
2865 return e;
2866 }
2867 set(e, begin);
2868 return e;
2869 }
2870
2871 Expression parseShiftExpression()
2872 {
2873 alias parseAddExpression parseNext;
2874 auto begin = token;
2875 auto e = parseNext();
2876 while (1)
2877 {
2878 auto operator = token;
2879 switch (operator.kind)
2880 {
2881 case T.LShift: nT(); e = new LShiftExpression(e, parseNext(), operator); break;
2882 case T.RShift: nT(); e = new RShiftExpression(e, parseNext(), operator); break;
2883 case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
2884 default:
2885 return e;
2886 }
2887 set(e, begin);
2888 }
2889 assert(0);
2890 }
2891
2892 Expression parseAddExpression()
2893 {
2894 alias parseMulExpression parseNext;
2895 auto begin = token;
2896 auto e = parseNext();
2897 while (1)
2898 {
2899 auto operator = token;
2900 switch (operator.kind)
2901 {
2902 case T.Plus: nT(); e = new PlusExpression(e, parseNext(), operator); break;
2903 case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
2904 case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
2905 default:
2906 return e;
2907 }
2908 set(e, begin);
2909 }
2910 assert(0);
2911 }
2912
2913 Expression parseMulExpression()
2914 {
2915 alias parsePostExpression parseNext;
2916 auto begin = token;
2917 auto e = parseNext();
2918 while (1)
2919 {
2920 auto operator = token;
2921 switch (operator.kind)
2922 {
2923 case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
2924 case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
2925 case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
2926 default:
2927 return e;
2928 }
2929 set(e, begin);
2930 }
2931 assert(0);
2932 }
2933
2934 Expression parsePostExpression()
2935 {
2936 auto begin = token;
2937 auto e = parseUnaryExpression();
2938 while (1)
2939 {
2940 while (consumed(T.Dot))
2941 {
2942 e = new DotExpression(e, parseNewOrIdentifierExpression());
2943 set(e, begin);
2944 }
2945
2946 switch (token.kind)
2947 {
2948 case T.PlusPlus:
2949 e = new PostIncrExpression(e);
2950 break;
2951 case T.MinusMinus:
2952 e = new PostDecrExpression(e);
2953 break;
2954 case T.LParen:
2955 e = new CallExpression(e, parseArguments());
2956 goto Lset;
2957 case T.LBracket:
2958 // parse Slice- and IndexExpression
2959 nT();
2960 // [] is a SliceExpression
2961 if (token.kind == T.RBracket)
2962 {
2963 e = new SliceExpression(e, null, null);
2964 break;
2965 }
2966
2967 Expression[] es = [parseAssignExpression()];
2968
2969 // [ AssignExpression .. AssignExpression ]
2970 if (consumed(T.Slice))
2971 {
2972 e = new SliceExpression(e, es[0], parseAssignExpression());
2973 require(T.RBracket);
2974 goto Lset;
2975 }
2976
2977 // [ ExpressionList ]
2978 if (consumed(T.Comma))
2979 es ~= parseExpressionList();
2980 require(T.RBracket);
2981
2982 e = new IndexExpression(e, es);
2983 goto Lset;
2984 default:
2985 return e;
2986 }
2987 nT();
2988 Lset: // Jumped here to skip nT().
2989 set(e, begin);
2990 }
2991 assert(0);
2992 }
2993
2994 Expression parseUnaryExpression()
2995 {
2996 auto begin = token;
2997 Expression e;
2998 switch (token.kind)
2999 {
3000 case T.AndBinary:
3001 nT();
3002 e = new AddressExpression(parseUnaryExpression());
3003 break;
3004 case T.PlusPlus:
3005 nT();
3006 e = new PreIncrExpression(parseUnaryExpression());
3007 break;
3008 case T.MinusMinus:
3009 nT();
3010 e = new PreDecrExpression(parseUnaryExpression());
3011 break;
3012 case T.Mul:
3013 nT();
3014 e = new DerefExpression(parseUnaryExpression());
3015 break;
3016 case T.Minus:
3017 case T.Plus:
3018 nT();
3019 e = new SignExpression(parseUnaryExpression());
3020 break;
3021 case T.Not:
3022 nT();
3023 e = new NotExpression(parseUnaryExpression());
3024 break;
3025 case T.Tilde:
3026 nT();
3027 e = new CompExpression(parseUnaryExpression());
3028 break;
3029 case T.New:
3030 e = parseNewExpression();
3031 return e;
3032 case T.Delete:
3033 nT();
3034 e = new DeleteExpression(parseUnaryExpression());
3035 break;
3036 case T.Cast:
3037 requireNext(T.LParen);
3038 Type type;
3039 switch (token.kind)
3040 {
3041 version(D2)
3042 {
3043 auto begin2 = token;
3044 case T.Const:
3045 type = new ConstType(null);
3046 goto case_break;
3047 case T.Invariant:
3048 type = new InvariantType(null);
3049 case_break:
3050 nT();
3051 set(type, begin2);
3052 break;
3053 }
3054 default:
3055 type = parseType();
3056 }
3057 require(T.RParen);
3058 e = new CastExpression(parseUnaryExpression(), type);
3059 break;
3060 case T.LParen:
3061 // ( Type ) . Identifier
3062 Type parseType_()
3063 {
3064 skip(T.LParen);
3065 auto type = parseType();
3066 require(T.RParen);
3067 require(T.Dot);
3068 return type;
3069 }
3070 bool success;
3071 auto type = try_(&parseType_, success);
3072 if (success)
3073 {
3074 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
3075 e = new TypeDotIdExpression(type, ident);
3076 break;
3077 }
3078 goto default;
3079 case T.Dot:
3080 nT();
3081 e = new ModuleScopeExpression(parseIdentifierExpression());
3082 break;
3083 default:
3084 e = parsePrimaryExpression();
3085 return e;
3086 }
3087 assert(e !is null);
3088 set(e, begin);
3089 return e;
3090 }
3091
3092 /// $(PRE
3093 /// IdentifierExpression :=
3094 /// Identifier
3095 /// TemplateInstance
3096 /// TemplateInstance :=
3097 /// Identifier !( TemplateArguments )
3098 /// )
3099 Expression parseIdentifierExpression()
3100 {
3101 auto begin = token;
3102 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
3103 Expression e;
3104 // Peek for '(' to avoid matching: id !is id
3105 if (token.kind == T.Not && peekNext() == T.LParen)
3106 { // Identifier !( TemplateArguments )
3107 skip(T.Not);
3108 auto tparams = parseTemplateArguments();
3109 e = new TemplateInstanceExpression(ident, tparams);
3110 }
3111 else // Identifier
3112 e = new IdentifierExpression(ident);
3113 return set(e, begin);
3114 }
3115
3116 Expression parseNewOrIdentifierExpression()
3117 {
3118 return token.kind == T.New ? parseNewExpression() : parseIdentifierExpression();
3119 }
3120
3121 Expression parsePrimaryExpression()
3122 {
3123 auto begin = token;
3124 Expression e;
3125 switch (token.kind)
3126 {
3127 case T.Identifier:
3128 e = parseIdentifierExpression();
3129 return e;
3130 case T.Typeof:
3131 e = new TypeofExpression(parseTypeofType());
3132 break;
3133 case T.This:
3134 nT();
3135 e = new ThisExpression();
3136 break;
3137 case T.Super:
3138 nT();
3139 e = new SuperExpression();
3140 break;
3141 case T.Null:
3142 nT();
3143 e = new NullExpression();
3144 break;
3145 case T.True, T.False:
3146 nT();
3147 e = new BoolExpression();
3148 break;
3149 case T.Dollar:
3150 nT();
3151 e = new DollarExpression();
3152 break;
3153 case T.Int32, T.Int64, T.Uint32, T.Uint64:
3154 e = new IntExpression(token);
3155 nT();
3156 break;
3157 case T.Float32, T.Float64, T.Float80,
3158 T.Imaginary32, T.Imaginary64, T.Imaginary80:
3159 e = new RealExpression(token);
3160 nT();
3161 break;
3162 case T.CharLiteral:
3163 e = new CharExpression(token.dchar_);
3164 nT();
3165 break;
3166 case T.String:
3167 char[] str = token.str;
3168 char postfix = token.pf;
3169 nT();
3170 while (token.kind == T.String)
3171 {
3172 /+if (postfix == 0)
3173 postfix = token.pf;
3174 else+/
3175 if (token.pf && token.pf != postfix)
3176 error(token, MSG.StringPostfixMismatch);
3177 str.length = str.length - 1; // Exclude '\0'.
3178 str ~= token.str;
3179 nT();
3180 }
3181 switch (postfix)
3182 {
3183 case 'w':
3184 if (checkString(begin, str))
3185 goto default;
3186 e = new StringExpression(dil.Unicode.toUTF16(str)); break;
3187 case 'd':
3188 if (checkString(begin, str))
3189 goto default;
3190 e = new StringExpression(dil.Unicode.toUTF32(str)); break;
3191 case 'c':
3192 default:
3193 // No checking done to allow for binary data.
3194 e = new StringExpression(str); break;
3195 }
3196 break;
3197 case T.LBracket:
3198 Expression[] values;
3199
3200 nT();
3201 if (!consumed(T.RBracket))
3202 {
3203 e = parseAssignExpression();
3204 if (consumed(T.Colon))
3205 goto LparseAssocArray;
3206 if (consumed(T.Comma))
3207 values = [e] ~ parseExpressionList();
3208 require(T.RBracket);
3209 }
3210
3211 e = new ArrayLiteralExpression(values);
3212 break;
3213
3214 LparseAssocArray:
3215 Expression[] keys = [e];
3216
3217 goto LenterLoop;
3218 do
3219 {
3220 keys ~= parseAssignExpression();
3221 require(T.Colon);
3222 LenterLoop:
3223 values ~= parseAssignExpression();
3224 } while (consumed(T.Comma))
3225 require(T.RBracket);
3226 e = new AArrayLiteralExpression(keys, values);
3227 break;
3228 case T.LBrace:
3229 // DelegateLiteral := { Statements }
3230 auto funcBody = parseFunctionBody();
3231 e = new FunctionLiteralExpression(funcBody);
3232 break;
3233 case T.Function, T.Delegate:
3234 // FunctionLiteral := ("function"|"delegate") Type? "(" ArgumentList ")" FunctionBody
3235 nT(); // Skip function or delegate keyword.
3236 Type returnType;
3237 Parameters parameters;
3238 if (token.kind != T.LBrace)
3239 {
3240 if (token.kind != T.LParen) // Optional return type
3241 returnType = parseType();
3242 parameters = parseParameterList();
3243 }
3244 auto funcBody = parseFunctionBody();
3245 e = new FunctionLiteralExpression(returnType, parameters, funcBody);
3246 break;
3247 case T.Assert:
3248 Expression msg;
3249 requireNext(T.LParen);
3250 e = parseAssignExpression();
3251 if (consumed(T.Comma))
3252 msg = parseAssignExpression();
3253 require(T.RParen);
3254 e = new AssertExpression(e, msg);
3255 break;
3256 case T.Mixin:
3257 requireNext(T.LParen);
3258 e = parseAssignExpression();
3259 require(T.RParen);
3260 e = new MixinExpression(e);
3261 break;
3262 case T.Import:
3263 requireNext(T.LParen);
3264 e = parseAssignExpression();
3265 require(T.RParen);
3266 e = new ImportExpression(e);
3267 break;
3268 case T.Typeid:
3269 requireNext(T.LParen);
3270 auto type = parseType();
3271 require(T.RParen);
3272 e = new TypeidExpression(type);
3273 break;
3274 case T.Is:
3275 requireNext(T.LParen);
3276
3277 Type type, specType;
3278 Identifier* ident; // optional Identifier
3279 Token* opTok, specTok;
3280
3281 type = parseDeclarator(ident, true);
3282
3283 switch (token.kind)
3284 {
3285 case T.Colon, T.Equal:
3286 opTok = token;
3287 nT();
3288 switch (token.kind)
3289 {
3290 case T.Typedef,
3291 T.Struct,
3292 T.Union,
3293 T.Class,
3294 T.Interface,
3295 T.Enum,
3296 T.Function,
3297 T.Delegate,
3298 T.Super,
3299 T.Return:
3300 case_Const_Invariant:
3301 specTok = token;
3302 nT();
3303 break;
3304 case T.Const, T.Invariant:
3305 if (peekNext() != T.LParen)
3306 goto case_Const_Invariant;
3307 // Fall through. It's a type.
3308 default:
3309 specType = parseType();
3310 }
3311 default:
3312 }
3313
3314 TemplateParameters tparams;
3315 version(D2)
3316 {
3317 // is ( Type Identifier : TypeSpecialization , TemplateParameterList )
3318 // is ( Type Identifier == TypeSpecialization , TemplateParameterList )
3319 if (ident && specType && token.kind == T.Comma)
3320 tparams = parseTemplateParameterList2();
3321 }
3322 require(T.RParen);
3323 e = new IsExpression(type, ident, opTok, specTok, specType, tparams);
3324 break;
3325 case T.LParen:
3326 if (tokenAfterParenIs(T.LBrace)) // Check for "(...) {"
3327 { // ( ParameterList ) FunctionBody
3328 auto parameters = parseParameterList();
3329 auto funcBody = parseFunctionBody();
3330 e = new FunctionLiteralExpression(null, parameters, funcBody);
3331 }
3332 else
3333 { // ( Expression )
3334 skip(T.LParen);
3335 e = parseExpression();
3336 require(T.RParen);
3337 e = new ParenExpression(e);
3338 }
3339 break;
3340 version(D2)
3341 {
3342 case T.Traits:
3343 requireNext(T.LParen);
3344 auto id = requireIdentifier(MSG.ExpectedAnIdentifier);
3345 TemplateArguments args;
3346 if (token.kind == T.Comma)
3347 args = parseTemplateArguments2();
3348 else
3349 require(T.RParen);
3350 e = new TraitsExpression(id, args);
3351 break;
3352 }
3353 default:
3354 if (token.isIntegralType)
3355 { // IntegralType . Identifier
3356 auto type = new IntegralType(token.kind);
3357 nT();
3358 set(type, begin);
3359 require(T.Dot);
3360 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
3361 e = new TypeDotIdExpression(type, ident);
3362 }
3363 else if (token.isSpecialToken)
3364 {
3365 e = new SpecialTokenExpression(token);
3366 nT();
3367 }
3368 else
3369 {
3370 error(MID.ExpectedButFound, "Expression", token.srcText);
3371 e = new IllegalExpression();
3372 if (!trying)
3373 { // Insert a dummy token and don't consume current one.
3374 begin = lexer.insertEmptyTokenBefore(token);
3375 this.prevToken = begin;
3376 }
3377 }
3378 }
3379 set(e, begin);
3380 return e;
3381 }
3382
3383 Expression parseNewExpression(/*Expression e*/)
3384 {
3385 auto begin = token;
3386 skip(T.New);
3387
3388 Expression[] newArguments;
3389 Expression[] ctorArguments;
3390
3391 if (token.kind == T.LParen)
3392 newArguments = parseArguments();
3393
3394 // NewAnonClassExpression:
3395 // new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
3396 if (consumed(T.Class))
3397 {
3398 if (token.kind == T.LParen)
3399 ctorArguments = parseArguments();
3400
3401 BaseClassType[] bases = token.kind != T.LBrace ? parseBaseClasses(false) : null ;
3402
3403 auto decls = parseDeclarationDefinitionsBody();
3404 return set(new NewAnonClassExpression(/*e, */newArguments, bases, ctorArguments, decls), begin);
3405 }
3406
3407 // NewExpression:
3408 // NewArguments Type [ AssignExpression ]
3409 // NewArguments Type ( ArgumentList )
3410 // NewArguments Type
3411 auto type = parseType();
3412
3413 if (token.kind == T.LParen)
3414 ctorArguments = parseArguments();
3415
3416 return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin);
3417 }
3418
3419 /// Parses a Type.
3420 Type parseType()
3421 {
3422 return parseBasicType2(parseBasicType());
3423 }
3424
3425 Type parseIdentifierType()
3426 {
3427 auto begin = token;
3428 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
3429 Type t;
3430 if (consumed(T.Not)) // Identifier !( TemplateArguments )
3431 t = new TemplateInstanceType(ident, parseTemplateArguments());
3432 else // Identifier
3433 t = new IdentifierType(ident);
3434 return set(t, begin);
3435 }
3436
3437 Type parseQualifiedType()
3438 {
3439 auto begin = token;
3440 Type type;
3441 if (token.kind == T.Dot)
3442 type = set(new ModuleScopeType(), begin, begin);
3443 else if (token.kind == T.Typeof)
3444 type = parseTypeofType();
3445 else
3446 type = parseIdentifierType();
3447
3448 while (consumed(T.Dot))
3449 type = set(new QualifiedType(type, parseIdentifierType()), begin);
3450 return type;
3451 }
3452
3453 Type parseBasicType()
3454 {
3455 auto begin = token;
3456 Type t;
3457
3458 if (token.isIntegralType)
3459 {
3460 t = new IntegralType(token.kind);
3461 nT();
3462 }
3463 else
3464 switch (token.kind)
3465 {
3466 case T.Identifier, T.Typeof, T.Dot:
3467 t = parseQualifiedType();
3468 return t;
3469 version(D2)
3470 {
3471 case T.Const:
3472 // const ( Type )
3473 requireNext(T.LParen);
3474 t = parseType();
3475 require(T.RParen);
3476 t = new ConstType(t);
3477 break;
3478 case T.Invariant:
3479 // invariant ( Type )
3480 requireNext(T.LParen);
3481 t = parseType();
3482 require(T.RParen);
3483 t = new InvariantType(t);
3484 break;
3485 } // version(D2)
3486 default:
3487 error(MID.ExpectedButFound, "BasicType", token.srcText);
3488 t = new IllegalType();
3489 nT();
3490 }
3491 return set(t, begin);
3492 }
3493
3494 Type parseBasicType2(Type t)
3495 {
3496 while (1)
3497 {
3498 auto begin = token;
3499 switch (token.kind)
3500 {
3501 case T.Mul:
3502 t = new PointerType(t);
3503 nT();
3504 break;
3505 case T.LBracket:
3506 t = parseArrayType(t);
3507 continue;
3508 case T.Function, T.Delegate:
3509 TOK tok = token.kind;
3510 nT();
3511 auto parameters = parseParameterList();
3512 if (tok == T.Function)
3513 t = new FunctionType(t, parameters);
3514 else
3515 t = new DelegateType(t, parameters);
3516 break;
3517 default:
3518 return t;
3519 }
3520 set(t, begin);
3521 }
3522 assert(0);
3523 }
3524
3525 /// Returns true if the token after the closing parenthesis
3526 /// is of kind tok.
3527 bool tokenAfterParenIs(TOK tok)
3528 {
3529 // We count nested parentheses tokens because template types
3530 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y)
3531 assert(token.kind == T.LParen);
3532 Token* next = token;
3533 uint level = 1;
3534 Loop:
3535 while (1)
3536 {
3537 lexer.peek(next);
3538 switch (next.kind)
3539 {
3540 case T.RParen:
3541 if (--level == 0)
3542 { // Last, closing parentheses found.
3543 do
3544 lexer.peek(next);
3545 while (next.isWhitespace)
3546 break Loop;
3547 }
3548 break;
3549 case T.LParen:
3550 ++level;
3551 break;
3552 case T.EOF:
3553 break Loop;
3554 default:
3555 }
3556 }
3557 return next.kind == tok;
3558 }
3559
3560 /// Parse the array types after the declarator (C-style.) E.g.: int a[]
3561 Type parseDeclaratorSuffix(Type lhsType)
3562 {
3563 // The Type chain should be as follows:
3564 // int[3]* Identifier [][32]
3565 // <- <- -> -.
3566 // ^-----------------´
3567 // Resulting chain: [][32]*[3]int
3568 Type parseNext() // Nested function required to accomplish this.
3569 {
3570 if (token.kind != T.LBracket)
3571 return lhsType; // Break recursion; return Type on the left hand side of the Identifier.
3572
3573 auto begin = token;
3574 Type t;
3575 skip(T.LBracket);
3576 if (consumed(T.RBracket))
3577 t = new ArrayType(parseNext()); // [ ]
3578 else
3579 {
3580 bool success;
3581 Type parseAAType()
3582 {
3583 auto type = parseType();
3584 require(T.RBracket);
3585 return type;
3586 }
3587 auto assocType = try_(&parseAAType, success);
3588 if (success)
3589 t = new ArrayType(parseNext(), assocType); // [ Type ]
3590 else
3591 {
3592 Expression e = parseExpression(), e2;
3593 if (consumed(T.Slice))
3594 e2 = parseExpression();
3595 require(T.RBracket);
3596 t = new ArrayType(parseNext(), e, e2); // [ Expression .. Expression ]
3597 }
3598 }
3599 set(t, begin);
3600 return t;
3601 }
3602 return parseNext();
3603 }
3604
3605 Type parseArrayType(Type t)
3606 {
3607 auto begin = token;
3608 skip(T.LBracket);
3609 if (consumed(T.RBracket))
3610 t = new ArrayType(t);
3611 else
3612 {
3613 bool success;
3614 Type parseAAType()
3615 {
3616 auto type = parseType();
3617 require(T.RBracket);
3618 return type;
3619 }
3620 auto assocType = try_(&parseAAType, success);
3621 if (success)
3622 t = new ArrayType(t, assocType);
3623 else
3624 {
3625 Expression e = parseExpression(), e2;
3626 if (consumed(T.Slice))
3627 e2 = parseExpression();
3628 require(T.RBracket);
3629 t = new ArrayType(t, e, e2);
3630 }
3631 }
3632 set(t, begin);
3633 return t;
3634 }
3635
3636 Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList)
3637 {
3638 assert(type !is null);
3639 auto begin = token;
3640 skip(T.LParen);
3641
3642 type = parseBasicType2(type);
3643 if (token.kind == T.LParen)
3644 { // Can be nested.
3645 type = parseCFunctionPointerType(type, ident, true);
3646 }
3647 else if (token.kind == T.Identifier)
3648 { // The identifier of the function pointer and the declaration.
3649 ident = token.ident;
3650 nT();
3651 type = parseDeclaratorSuffix(type);
3652 }
3653 require(T.RParen);
3654
3655 Parameters params;
3656 if (optionalParamList)
3657 params = token.kind == T.LParen ? parseParameterList() : null;
3658 else
3659 params = parseParameterList();
3660
3661 type = new CFuncPointerType(type, params);
3662 return set(type, begin);
3663 }
3664
3665 Type parseDeclarator(ref Identifier* ident, bool identOptional = false)
3666 {
3667 auto t = parseType();
3668
3669 if (token.kind == T.LParen)
3670 t = parseCFunctionPointerType(t, ident, true);
3671 else if (token.kind == T.Identifier)
3672 {
3673 ident = token.ident;
3674 nT();
3675 t = parseDeclaratorSuffix(t);
3676 }
3677
3678 if (ident is null && !identOptional)
3679 error(token, MSG.ExpectedDeclaratorIdentifier, token.srcText);
3680
3681 return t;
3682 }
3683
3684 /// Parses a list of AssignExpressions.
3685 /// $(PRE
3686 /// ExpressionList :=
3687 /// AssignExpression
3688 /// AssignExpression , ExpressionList
3689 /// )
3690 Expression[] parseExpressionList()
3691 {
3692 Expression[] expressions;
3693 do
3694 expressions ~= parseAssignExpression();
3695 while(consumed(T.Comma))
3696 return expressions;
3697 }
3698
3699 /// Parses a list of Arguments.
3700 /// $(PRE
3701 /// Arguments :=
3702 /// ( )
3703 /// ( ExpressionList )
3704 /// )
3705 Expression[] parseArguments()
3706 {
3707 skip(T.LParen);
3708 Expression[] args;
3709 if (token.kind != T.RParen)
3710 args = parseExpressionList();
3711 require(T.RParen);
3712 return args;
3713 }
3714
3715 /// Parses a ParameterList.
3716 Parameters parseParameterList()
3717 out(params)
3718 {
3719 if (params.length > 1)
3720 foreach (param; params.items[0..$-1])
3721 {
3722 if (param.isVariadic())
3723 assert(0, "variadic arguments can only appear at the end of the parameter list.");
3724 }
3725 }
3726 body
3727 {
3728 auto begin = token;
3729 require(T.LParen);
3730
3731 auto params = new Parameters();
3732
3733 if (consumed(T.RParen))
3734 return set(params, begin);
3735
3736 do
3737 {
3738 auto paramBegin = token;
3739 StorageClass stc, stc_;
3740 Type type;
3741 Identifier* ident;
3742 Expression defValue;
3743
3744 void pushParameter()
3745 {
3746 params ~= set(new Parameter(stc, type, ident, defValue), paramBegin);
3747 }
3748
3749 if (consumed(T.Ellipses))
3750 {
3751 stc = StorageClass.Variadic;
3752 pushParameter(); // type, ident and defValue will be null.
3753 break;
3754 }
3755
3756 while (1)
3757 { // Parse storage classes.
3758 switch (token.kind)
3759 {
3760 version(D2)
3761 {
3762 case T.Invariant: // D2.0
3763 if (peekNext() == T.LParen)
3764 break;
3765 stc_ = StorageClass.Invariant;
3766 goto Lcommon;
3767 case T.Const: // D2.0
3768 if (peekNext() == T.LParen)
3769 break;
3770 stc_ = StorageClass.Const;
3771 goto Lcommon;
3772 case T.Final: // D2.0
3773 stc_ = StorageClass.Final;
3774 goto Lcommon;
3775 case T.Scope: // D2.0
3776 stc_ = StorageClass.Scope;
3777 goto Lcommon;
3778 case T.Static: // D2.0
3779 stc_ = StorageClass.Static;
3780 goto Lcommon;
3781 }
3782 case T.In:
3783 stc_ = StorageClass.In;
3784 goto Lcommon;
3785 case T.Out:
3786 stc_ = StorageClass.Out;
3787 goto Lcommon;
3788 case T.Inout, T.Ref:
3789 stc_ = StorageClass.Ref;
3790 goto Lcommon;
3791 case T.Lazy:
3792 stc_ = StorageClass.Lazy;
3793 goto Lcommon;
3794 Lcommon:
3795 // Check for redundancy.
3796 if (stc & stc_)
3797 error(MID.RedundantStorageClass, token.srcText);
3798 else
3799 stc |= stc_;
3800 nT();
3801 version(D2)
3802 continue;
3803 else
3804 break; // In D1.0 the grammar only allows one storage class.
3805 default:
3806 }
3807 break; // Break out of inner loop.
3808 }
3809 type = parseDeclarator(ident, true);
3810
3811 if (consumed(T.Assign))
3812 defValue = parseAssignExpression();
3813
3814 if (consumed(T.Ellipses))
3815 {
3816 stc |= StorageClass.Variadic;
3817 pushParameter();
3818 break;
3819 }
3820 pushParameter();
3821
3822 } while (consumed(T.Comma))
3823 require(T.RParen);
3824 return set(params, begin);
3825 }
3826
3827 TemplateArguments parseTemplateArguments()
3828 {
3829 TemplateArguments targs;
3830 require(T.LParen);
3831 if (token.kind != T.RParen)
3832 targs = parseTemplateArguments_();
3833 require(T.RParen);
3834 return targs;
3835 }
3836
3837 version(D2)
3838 {
3839 TemplateArguments parseTemplateArguments2()
3840 {
3841 skip(T.Comma);
3842 TemplateArguments targs;
3843 if (token.kind != T.RParen)
3844 targs = parseTemplateArguments_();
3845 else
3846 error(token, MSG.ExpectedTypeOrExpression);
3847 require(T.RParen);
3848 return targs;
3849 }
3850 } // version(D2)
3851
3852 TemplateArguments parseTemplateArguments_()
3853 {
3854 auto begin = token;
3855 auto targs = new TemplateArguments;
3856 do
3857 {
3858 Type parseType_()
3859 {
3860 auto type = parseType();
3861 if (token.kind == T.Comma || token.kind == T.RParen)
3862 return type;
3863 errorCount++; // Cause try_() to fail.
3864 return null;
3865 }
3866 bool success;
3867 auto typeArgument = try_(&parseType_, success);
3868 if (success)
3869 // TemplateArgument:
3870 // Type
3871 // Symbol
3872 targs ~= typeArgument;
3873 else
3874 // TemplateArgument:
3875 // AssignExpression
3876 targs ~= parseAssignExpression();
3877 } while (consumed(T.Comma))
3878 set(targs, begin);
3879 return targs;
3880 }
3881
3882 TemplateParameters parseTemplateParameterList()
3883 {
3884 auto begin = token;
3885 auto tparams = new TemplateParameters;
3886 require(T.LParen);
3887 if (token.kind != T.RParen)
3888 parseTemplateParameterList_(tparams);
3889 require(T.RParen);
3890 return set(tparams, begin);
3891 }
3892
3893 version(D2)
3894 {
3895 TemplateParameters parseTemplateParameterList2()
3896 {
3897 skip(T.Comma);
3898 auto begin = token;
3899 auto tparams = new TemplateParameters;
3900 if (token.kind != T.RParen)
3901 parseTemplateParameterList_(tparams);
3902 else
3903 error(token, MSG.ExpectedTemplateParameters);
3904 return set(tparams, begin);
3905 }
3906 } // version(D2)
3907
3908 /// Parses template parameters.
3909 void parseTemplateParameterList_(TemplateParameters tparams)
3910 {
3911 do
3912 {
3913 auto paramBegin = token;
3914 TemplateParameter tp;
3915 Identifier* ident;
3916 Type specType, defType;
3917
3918 void parseSpecAndOrDefaultType()
3919 {
3920 // : SpecializationType
3921 if (consumed(T.Colon))
3922 specType = parseType();
3923 // = DefaultType
3924 if (consumed(T.Assign))
3925 defType = parseType();
3926 }
3927
3928 switch (token.kind)
3929 {
3930 case T.Alias:
3931 // TemplateAliasParameter:
3932 // alias Identifier
3933 skip(T.Alias);
3934 ident = requireIdentifier(MSG.ExpectedAliasTemplateParam);
3935 parseSpecAndOrDefaultType();
3936 tp = new TemplateAliasParameter(ident, specType, defType);
3937 break;
3938 case T.Identifier:
3939 ident = token.ident;
3940 switch (peekNext())
3941 {
3942 case T.Ellipses:
3943 // TemplateTupleParameter:
3944 // Identifier ...
3945 skip(T.Identifier); skip(T.Ellipses);
3946 if (token.kind == T.Comma)
3947 error(MID.TemplateTupleParameter);
3948 tp = new TemplateTupleParameter(ident);
3949 break;
3950 case T.Comma, T.RParen, T.Colon, T.Assign:
3951 // TemplateTypeParameter:
3952 // Identifier
3953 skip(T.Identifier);
3954 parseSpecAndOrDefaultType();
3955 tp = new TemplateTypeParameter(ident, specType, defType);
3956 break;
3957 default:
3958 // TemplateValueParameter:
3959 // Declarator
3960 ident = null;
3961 goto LTemplateValueParameter;
3962 }
3963 break;
3964 version(D2)
3965 {
3966 case T.This:
3967 // TemplateThisParameter
3968 // this TemplateTypeParameter
3969 skip(T.This);
3970 ident = requireIdentifier(MSG.ExpectedNameForThisTempParam);
3971 parseSpecAndOrDefaultType();
3972 tp = new TemplateThisParameter(ident, specType, defType);
3973 break;
3974 }
3975 default:
3976 LTemplateValueParameter:
3977 // TemplateValueParameter:
3978 // Declarator
3979 Expression specValue, defValue;
3980 auto valueType = parseDeclarator(ident);
3981 // : SpecializationValue
3982 if (consumed(T.Colon))
3983 specValue = parseCondExpression();
3984 // = DefaultValue
3985 if (consumed(T.Assign))
3986 defValue = parseCondExpression();
3987 tp = new TemplateValueParameter(valueType, ident, specValue, defValue);
3988 }
3989
3990 // Push template parameter.
3991 tparams ~= set(tp, paramBegin);
3992
3993 } while (consumed(T.Comma))
3994 }
3995
3996 alias require expected;
3997
3998 /// Requires a token of kind tok.
3999 void require(TOK tok)
4000 {
4001 if (token.kind == tok)
4002 nT();
4003 else
4004 error(MID.ExpectedButFound, Token.toString(tok), token.srcText);
4005 }
4006
4007 /// Requires the next token to be of kind tok.
4008 void requireNext(TOK tok)
4009 {
4010 nT();
4011 require(tok);
4012 }
4013
4014 /// Optionally parses an identifier.
4015 /// Returns: null or the identifier.
4016 Identifier* optionalIdentifier()
4017 {
4018 Identifier* id;
4019 if (token.kind == T.Identifier)
4020 (id = token.ident), skip(T.Identifier);
4021 return id;
4022 }
4023
4024 Identifier* requireIdentifier()
4025 {
4026 Identifier* id;
4027 if (token.kind == T.Identifier)
4028 (id = token.ident), skip(T.Identifier);
4029 else
4030 error(MID.ExpectedButFound, "Identifier", token.srcText);
4031 return id;
4032 }
4033
4034 /// Reports an error if the current token is not an identifier.
4035 /// Params:
4036 /// errorMsg = the error message to be used.
4037 /// Returns: null or the identifier.
4038 Identifier* requireIdentifier(char[] errorMsg)
4039 {
4040 Identifier* id;
4041 if (token.kind == T.Identifier)
4042 (id = token.ident), skip(T.Identifier);
4043 else
4044 error(token, errorMsg, token.srcText);
4045 return id;
4046 }
4047
4048 /// Reports an error if the current token is not an identifier.
4049 /// Params:
4050 /// mid = the error message ID to be used.
4051 /// Returns: null or the identifier.
4052 Identifier* requireIdentifier(MID mid)
4053 {
4054 Identifier* id;
4055 if (token.kind == T.Identifier)
4056 (id = token.ident), skip(T.Identifier);
4057 else
4058 error(mid, token.srcText);
4059 return id;
4060 }
4061
4062 /// Reports an error if the current token is not an identifier.
4063 /// Returns: null or the token.
4064 Token* requireId()
4065 {
4066 Token* idtok;
4067 if (token.kind == T.Identifier)
4068 (idtok = token), skip(T.Identifier);
4069 else
4070 error(MID.ExpectedButFound, "Identifier", token.srcText);
4071 return idtok;
4072 }
4073
4074 Token* requireIdToken(char[] errorMsg)
4075 {
4076 Token* idtok;
4077 if (token.kind == T.Identifier)
4078 (idtok = token), skip(T.Identifier);
4079 else
4080 {
4081 error(token, errorMsg, token.srcText);
4082 idtok = lexer.insertEmptyTokenBefore(token);
4083 this.prevToken = idtok;
4084 }
4085 return idtok;
4086 }
4087
4088 /// Returns true if the string str has an invalid UTF-8 sequence.
4089 bool checkString(Token* begin, string str)
4090 {
4091 auto utf8Seq = Lexer.findInvalidUTF8Sequence(str);
4092 if (utf8Seq.length)
4093 error(begin, MSG.InvalidUTF8SequenceInString, utf8Seq);
4094 return utf8Seq.length != 0;
4095 }
4096
4097 /// Forwards error parameters.
4098 void error(Token* token, char[] formatMsg, ...)
4099 {
4100 error_(token, formatMsg, _arguments, _argptr);
4101 }
4102
4103 /// ditto
4104 void error(MID mid, ...)
4105 {
4106 error_(this.token, GetMsg(mid), _arguments, _argptr);
4107 }
4108
4109 /// Creates an error report and appends it to a list.
4110 /// Params:
4111 /// token = used to get the location of where the error is.
4112 /// formatMsg = the compiler error message.
4113 void error_(Token* token, char[] formatMsg, TypeInfo[] _arguments, Arg _argptr)
4114 {
4115 if (trying)
4116 {
4117 ++errorCount;
4118 return;
4119 }
4120 auto location = token.getErrorLocation();
4121 auto msg = Format(_arguments, _argptr, formatMsg);
4122 auto error = new ParserError(location, msg);
4123 errors ~= error;
4124 if (infoMan !is null)
4125 infoMan ~= error;
4126 }
4127 }