1 /// Author: Aziz Köksal
3 /// $(Maturity very high)
4 module dil
.parser
.Parser
;
6 import dil
.lexer
.Lexer
,
15 import dil
.Diagnostics
;
17 import dil
.CompilerInfo
;
18 import dil
.SourceText
;
22 import tango
.core
.Vararg
;
24 /// The Parser produces a full parse tree by examining
25 /// the list of tokens provided by the Lexer.
28 Lexer lexer
; /// Used to lex the source code.
29 Token
* token
; /// Current non-whitespace token.
30 Token
* prevToken
; /// Previous non-whitespace token.
33 ParserError
[] errors
; /// Array of parser error messages.
35 ImportDeclaration
[] imports
; /// ImportDeclarations in the source text.
37 /// Attributes are evaluated in the parsing phase.
38 /// TODO: will be removed. SemanticPass1 takes care of attributes.
39 LinkageType linkageType
;
40 Protection protection
; /// ditto
41 StorageClass storageClass
; /// ditto
42 uint alignSize
= DEFAULT_ALIGN_SIZE
; /// ditto
44 private alias TOK T
; /// Used often in this class.
45 private alias TypeNode Type
;
47 /// Constructs a Parser object.
49 /// srcText = the UTF-8 source code.
50 /// diag = used for collecting error messages.
51 this(SourceText srcText
, Diagnostics diag
= null)
54 lexer
= new Lexer(srcText
, diag
);
57 /// Moves to the first token.
64 /// Moves to the next token.
72 } while (token
.isWhitespace
) // Skip whitespace
75 /// Start the parser and return the parsed Declarations.
76 CompoundDeclaration
start()
80 auto decls
= new CompoundDeclaration
;
81 if (token
.kind
== T
.Module
)
82 decls
~= parseModuleDeclaration();
83 decls
.addOptChildren(parseDeclarationDefinitions());
88 /// Start the parser and return the parsed Expression.
92 return parseExpression();
95 // Members related to the method try_().
96 uint trying
; /// Greater than 0 if Parser is in try_().
97 uint errorCount
; /// Used to track nr. of errors while being in try_().
99 /// This method executes the delegate parseMethod and when an error occurred
100 /// the state of the lexer and parser is restored.
101 /// Returns: the return value of parseMethod().
102 ReturnType
try_(ReturnType
)(ReturnType
delegate() parseMethod
, out bool success
)
105 auto oldToken
= this.token
;
106 auto oldPrevToken
= this.prevToken
;
107 auto oldCount
= this.errorCount
;
110 auto result
= parseMethod();
112 // Check if an error occurred.
113 if (errorCount
!= oldCount
)
114 { // Restore members.
116 prevToken
= oldPrevToken
;
117 lexer
.token
= oldToken
;
118 errorCount
= oldCount
;
126 /// Causes the current call to try_() to fail.
133 /// Sets the begin and end tokens of a syntax tree node.
134 Class
set(Class
)(Class node
, Token
* begin
)
136 node
.setTokens(begin
, this.prevToken
);
140 /// Sets the begin and end tokens of a syntax tree node.
141 Class
set(Class
)(Class node
, Token
* begin
, Token
* end
)
143 node
.setTokens(begin
, end
);
147 /// Returns true if set() has been called on a node.
148 static bool isNodeSet(Node node
)
150 return node
.begin
!is null && node
.end
!is null;
153 /// Returns the token kind of the next token.
159 while (next
.isWhitespace
) // Skip whitespace
163 /// Returns the token kind of the token that comes after t.
164 TOK
peekAfter(ref Token
* t
)
169 while (t
.isWhitespace
) // Skip whitespace
173 /// Consumes the current token if its kind matches k and returns true.
174 bool consumed()(TOK k
) // Templatized, so it's inlined.
176 return token
.kind
== k ?
(nT(), true) : false;
179 /// Asserts that the current token is of kind expectedKind,
180 /// and then moves to the next token.
181 void skip()(TOK expectedKind
)
183 assert(token
.kind
== expectedKind
/+|| *(int*).init+/, token
.srcText());
187 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188 | Declaration parsing methods |
189 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
191 Declaration
parseModuleDeclaration()
197 moduleFQN
~= requireIdentifier(MSG
.ExpectedModuleIdentifier
);
198 while (consumed(T
.Dot
))
199 require(T
.Semicolon
);
200 return set(new ModuleDeclaration(moduleFQN
), begin
);
203 /// Parses DeclarationDefinitions until the end of file is hit.
209 Declaration
[] parseDeclarationDefinitions()
212 while (token
.kind
!= T
.EOF
)
213 decls
~= parseDeclarationDefinition();
217 /// Parse the body of a template, class, interface, struct or union.
223 CompoundDeclaration
parseDeclarationDefinitionsBody()
226 auto linkageType
= this.linkageType
;
227 auto protection
= this.protection
;
228 auto storageClass
= this.storageClass
;
230 this.linkageType
= LinkageType
.None
;
231 this.protection
= Protection
.None
;
232 this.storageClass
= StorageClass
.None
;
236 auto decls
= new CompoundDeclaration
;
238 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
239 decls
~= parseDeclarationDefinition();
240 requireClosing(T
.RBrace
, begin
);
243 // Restore original values.
244 this.linkageType
= linkageType
;
245 this.protection
= protection
;
246 this.storageClass
= storageClass
;
251 /// Parses a DeclarationDefinition.
252 Declaration
parseDeclarationDefinition()
254 { assert(isNodeSet(decl
)); }
263 // Protection attributes
269 decl
= parseAttributeSpecifier();
280 //T.Invariant, // D 2.0
283 case_StaticAttribute
:
284 case_InvariantAttribute
: // D 2.0
285 case_EnumAttribute
: // D 2.0
286 return parseStorageAttribute();
289 decl
= new AliasDeclaration(parseVariableOrFunction());
293 decl
= new TypedefDeclaration(parseVariableOrFunction());
301 decl
= parseStaticConstructorDeclaration();
304 decl
= parseStaticDestructorDeclaration();
307 decl
= parseStaticIfDeclaration();
310 decl
= parseStaticAssertDeclaration();
313 goto case_StaticAttribute
;
318 decl
= parseImportDeclaration();
319 imports
~= decl
.to
!(ImportDeclaration
);
320 // Handle specially. StorageClass mustn't be set.
321 decl
.setProtection(this.protection
);
322 return set(decl
, begin
);
326 if (isEnumManifest())
327 goto case_EnumAttribute
;
329 decl
= parseEnumDeclaration();
332 decl
= parseClassDeclaration();
335 decl
= parseInterfaceDeclaration();
337 case T
.Struct
, T
.Union
:
338 decl
= parseStructOrUnionDeclaration();
341 decl
= parseConstructorDeclaration();
344 decl
= parseDestructorDeclaration();
350 if (peekAfter(next
) == T
.LParen
)
352 if (peekAfter(next
) != T
.RParen
)
353 goto case_Declaration
; // invariant ( Type )
356 goto case_InvariantAttribute
; // invariant as StorageClass.
358 decl
= parseInvariantDeclaration(); // invariant ( )
361 decl
= parseUnittestDeclaration();
364 decl
= parseDebugDeclaration();
367 decl
= parseVersionDeclaration();
370 decl
= parseTemplateDeclaration();
373 decl
= parseNewDeclaration();
376 decl
= parseDeleteDeclaration();
379 decl
= parseMixin
!(MixinDeclaration
)();
383 decl
= new EmptyDeclaration();
386 case T
.Identifier
, T
.Dot
, T
.Typeof
:
388 return parseVariableOrFunction(this.storageClass
, this.protection
, this.linkageType
);
390 if (token
.isIntegralType
)
391 goto case_Declaration
;
392 else if (token
.kind
== T
.Module
)
394 decl
= parseModuleDeclaration();
395 error(begin
, MSG
.ModuleDeclarationNotFirst
);
399 decl
= new IllegalDeclaration();
400 // Skip to next valid token.
403 while (!token
.isDeclDefStart
&&
404 token
.kind
!= T
.RBrace
&&
406 auto text
= Token
.textSpan(begin
, this.prevToken
);
407 error(begin
, MSG
.IllegalDeclaration
, text
);
409 decl
.setProtection(this.protection
);
410 decl
.setStorageClass(this.storageClass
);
411 assert(!isNodeSet(decl
));
416 /// Parses a DeclarationsBlock.
418 /// DeclarationsBlock :=
424 Declaration
parseDeclarationsBlock(/+bool noColon = false+/)
432 auto decls
= new CompoundDeclaration
;
433 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
434 decls
~= parseDeclarationDefinition();
435 requireClosing(T
.RBrace
, begin
);
436 d
= set(decls
, begin
);
439 // if (noColon == true)
443 auto decls
= new CompoundDeclaration
;
444 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
445 decls
~= parseDeclarationDefinition();
446 d
= set(decls
, begin
);
449 d
= parseDeclarationDefinition();
451 assert(isNodeSet(d
));
455 // Declaration parseDeclarationsBlockNoColon()
457 // return parseDeclarationsBlock(true);
460 /// Parses either a VariableDeclaration or a FunctionDeclaration.
462 /// stc = previously parsed storage classes
463 /// protection = previously parsed protection attribute
464 /// linkType = previously parsed linkage type
465 /// testAutoDeclaration = whether to check for an AutoDeclaration
466 /// optionalParameterList = a hint for how to parse C-style function pointers
467 Declaration
parseVariableOrFunction(StorageClass
stc = StorageClass
.None
,
468 Protection protection
= Protection
.None
,
469 LinkageType linkType
= LinkageType
.None
,
470 bool testAutoDeclaration
= false,
471 bool optionalParameterList
= true)
477 // Check for AutoDeclaration: StorageClasses Identifier =
478 if (testAutoDeclaration
&& token
.kind
== T
.Identifier
)
480 auto kind
= peekNext();
481 if (kind
== T
.Assign
)
482 { // Auto variable declaration.
485 goto LparseVariables
;
487 else version(D2
) if (kind
== T
.LParen
)
488 { // Check for auto return type template function.
489 // StorageClasses Name ( TemplateParameterList ) ( ParameterList )
493 if (tokenAfterParenIs(T
.LParen
, next
))
496 assert(token
.kind
== T
.LParen
);
497 goto LparseTPList
; // Continue with parsing a template function.
502 type
= parseType(); // VariableType or ReturnType
504 if (token
.kind
== T
.LParen
)
505 { // C-style function pointers make the grammar ambiguous.
506 // We have to treat them specially at function scope.
509 // // A pointer to a function taking an integer and returning 'some_type'.
510 // some_type (*p_func)(int);
511 // // In the following case precedence is given to a CallExpression.
512 // something(*p); // 'something' may be a function/method or an object having opCall overloaded.
514 // // A pointer to a function taking no parameters and returning 'something'.
516 type
= parseCFunctionPointerType(type
, name
, optionalParameterList
);
518 else if (peekNext() == T
.LParen
)
519 { // Type FunctionName ( ParameterList ) FunctionBody
520 name
= requireIdentifier(MSG
.ExpectedFunctionName
);
521 name ||
nT(); // Skip non-identifier token.
522 assert(token
.kind
== T
.LParen
);
523 // It's a function declaration
524 TemplateParameters tparams
;
525 Expression constraint
;
527 if (tokenAfterParenIs(T
.LParen
))
529 // ( TemplateParameterList ) ( ParameterList )
530 tparams
= parseTemplateParameterList();
532 auto params
= parseParameterList();
535 if (tparams
) // If ( ConstraintExpression )
536 constraint
= parseOptionalConstraint();
540 stc |
= StorageClass
.Const
;
544 stc |
= StorageClass
.Invariant
;
550 // ReturnType FunctionName ( ParameterList )
551 auto funcBody
= parseFunctionBody();
552 auto fd
= new FunctionDeclaration(type
, name
,/+ tparams,+/ params
, funcBody
);
553 fd
.setStorageClass(stc);
554 fd
.setLinkageType(linkType
);
555 fd
.setProtection(protection
);
558 auto d
= putInsideTemplateDeclaration(begin
, name
, fd
, tparams
, constraint
);
559 d
.setStorageClass(stc);
560 d
.setProtection(protection
);
561 return set(d
, begin
);
563 return set(fd
, begin
);
566 { // Type VariableName DeclaratorSuffix
567 name
= requireIdentifier(MSG
.ExpectedVariableName
);
568 type
= parseDeclaratorSuffix(type
);
572 // It's a variables declaration.
573 Identifier
*[] names
= [name
]; // One identifier has been parsed already.
575 goto LenterLoop
; // Enter the loop and check for an initializer.
576 while (consumed(T
.Comma
))
578 names
~= requireIdentifier(MSG
.ExpectedVariableName
);
580 if (consumed(T
.Assign
))
581 values
~= parseInitializer();
585 require(T
.Semicolon
);
586 auto d
= new VariablesDeclaration(type
, names
, values
);
587 d
.setStorageClass(stc);
588 d
.setLinkageType(linkType
);
589 d
.setProtection(protection
);
590 return set(d
, begin
);
593 /// Parses a variable initializer.
594 Expression
parseInitializer()
596 if (token
.kind
== T
.Void
)
599 auto next
= peekNext();
600 if (next
== T
.Comma || next
== T
.Semicolon
)
603 return set(new VoidInitExpression(), begin
);
606 return parseNonVoidInitializer();
609 Expression
parseNonVoidInitializer()
618 // [ ArrayMemberInitializations ]
623 while (token
.kind
!= T
.RBracket
)
625 auto e
= parseNonVoidInitializer();
626 if (consumed(T
.Colon
))
629 values
~= parseNonVoidInitializer();
637 if (!consumed(T
.Comma
))
640 requireClosing(T
.RBracket
, begin
);
641 init
= new ArrayInitExpression(keys
, values
);
644 // StructInitializer:
646 // { StructMemberInitializers }
647 Expression
parseStructInitializer()
649 Identifier
*[] idents
;
653 while (token
.kind
!= T
.RBrace
)
655 if (token
.kind
== T
.Identifier
&&
656 // Peek for colon to see if this is a member identifier.
657 peekNext() == T
.Colon
)
659 idents
~= token
.ident
;
660 skip(T
.Identifier
), skip(T
.Colon
);
665 // NonVoidInitializer
666 values
~= parseNonVoidInitializer();
668 if (!consumed(T
.Comma
))
671 requireClosing(T
.RBrace
, begin
);
672 return new StructInitExpression(idents
, values
);
676 auto si
= try_(&parseStructInitializer
, success
);
682 assert(token
.kind
== T
.LBrace
);
685 init
= parseAssignExpression();
691 FuncBodyStatement
parseFunctionBody()
694 auto func
= new FuncBodyStatement
;
700 func
.funcBody
= parseStatements();
707 error(MID
.InContract
);
709 func
.inBody
= parseStatements();
713 error(MID
.OutContract
);
715 if (consumed(T
.LParen
))
717 auto leftParen
= this.prevToken
;
718 func
.outIdent
= requireIdentifier(MSG
.ExpectedAnIdentifier
);
719 requireClosing(T
.RParen
, leftParen
);
721 func
.outBody
= parseStatements();
727 error2(MSG
.ExpectedFunctionBody
, token
);
732 func
.finishConstruction();
736 LinkageType
parseLinkageType()
738 LinkageType linkageType
;
740 if (!consumed(T
.LParen
))
743 if (consumed(T
.RParen
))
745 error(MID
.MissingLinkageType
);
749 auto identTok
= requireId();
751 IDK idKind
= identTok ? identTok
.ident
.idKind
: IDK
.Null
;
756 if (consumed(T
.PlusPlus
))
758 linkageType
= LinkageType
.Cpp
;
761 linkageType
= LinkageType
.C
;
764 linkageType
= LinkageType
.D
;
767 linkageType
= LinkageType
.Windows
;
770 linkageType
= LinkageType
.Pascal
;
773 linkageType
= LinkageType
.System
;
776 error2(MID
.UnrecognizedLinkageType
, token
);
782 void checkLinkageType(ref LinkageType prev_lt
, LinkageType lt
, Token
* begin
)
784 if (prev_lt
== LinkageType
.None
)
787 error(begin
, MSG
.RedundantLinkageType
, Token
.textSpan(begin
, this.prevToken
));
790 Declaration
parseStorageAttribute()
792 StorageClass
stc, stc_tmp
;
793 LinkageType prev_linkageType
;
795 auto saved_storageClass
= this.storageClass
; // Save.
804 if (peekNext() != T
.LParen
)
806 stc_tmp
= StorageClass
.Extern
;
811 auto linkageType
= parseLinkageType();
812 checkLinkageType(prev_linkageType
, linkageType
, begin
);
814 auto saved
= this.linkageType
; // Save.
815 this.linkageType
= linkageType
; // Set.
816 decl
= new LinkageDeclaration(linkageType
, parse());
818 this.linkageType
= saved
; // Restore.
821 stc_tmp
= StorageClass
.Override
;
824 stc_tmp
= StorageClass
.Deprecated
;
827 stc_tmp
= StorageClass
.Abstract
;
830 stc_tmp
= StorageClass
.Synchronized
;
833 stc_tmp
= StorageClass
.Static
;
836 stc_tmp
= StorageClass
.Final
;
841 if (peekNext() == T
.LParen
)
842 goto case_Declaration
;
844 stc_tmp
= StorageClass
.Const
;
848 case T
.Invariant
: // D 2.0
850 if (peekAfter(next
) == T
.LParen
)
852 if (peekAfter(next
) != T
.RParen
)
853 goto case_Declaration
; // invariant ( Type )
854 decl
= parseInvariantDeclaration(); // invariant ( )
855 // NB: this must be similar to the code at the end of
856 // parseDeclarationDefinition().
857 decl
.setProtection(this.protection
);
858 decl
.setStorageClass(stc);
862 // invariant as StorageClass.
863 stc_tmp
= StorageClass
.Invariant
;
865 case T
.Enum
: // D 2.0
866 if (!isEnumManifest())
867 { // A normal enum declaration.
868 decl
= parseEnumDeclaration();
869 // NB: this must be similar to the code at the end of
870 // parseDeclarationDefinition().
871 decl
.setProtection(this.protection
);
872 decl
.setStorageClass(stc);
876 // enum as StorageClass.
877 stc_tmp
= StorageClass
.Manifest
;
881 stc_tmp
= StorageClass
.Auto
;
884 stc_tmp
= StorageClass
.Scope
;
887 // Issue error if redundant.
889 error2(MID
.RedundantStorageClass
, token
);
894 decl
= new StorageClassDeclaration(stc_tmp
, parse());
899 // This could be a normal Declaration or an AutoDeclaration
900 decl
= parseVariableOrFunction(stc, this.protection
, prev_linkageType
, true);
903 this.storageClass
= stc; // Set.
904 decl
= parseDeclarationsBlock();
905 this.storageClass
= saved_storageClass
; // Reset.
907 assert(isNodeSet(decl
));
913 uint parseAlignAttribute()
916 uint size
= DEFAULT_ALIGN_SIZE
; // Global default.
917 if (consumed(T
.LParen
))
919 if (token
.kind
== T
.Int32
)
920 (size
= token
.int_
), skip(T
.Int32
);
928 Declaration
parseAttributeSpecifier()
935 uint alignSize
= parseAlignAttribute();
936 auto saved
= this.alignSize
; // Save.
937 this.alignSize
= alignSize
; // Set.
938 decl
= new AlignDeclaration(alignSize
, parseDeclarationsBlock());
939 this.alignSize
= saved
; // Restore.
943 // pragma ( Identifier )
944 // pragma ( Identifier , ExpressionList )
950 ident
= requireIdentifier(MSG
.ExpectedPragmaIdentifier
);
952 if (consumed(T
.Comma
))
953 args
= parseExpressionList();
956 decl
= new PragmaDeclaration(ident
, args
, parseDeclarationsBlock());
959 // Protection attributes
964 prot
= Protection
.Private
; break;
966 prot
= Protection
.Package
; break;
968 prot
= Protection
.Protected
; break;
970 prot
= Protection
.Public
; break;
972 prot
= Protection
.Export
; break;
977 auto saved
= this.protection
; // Save.
978 this.protection
= prot
; // Set.
979 decl
= new ProtectionDeclaration(prot
, parseDeclarationsBlock());
980 this.protection
= saved
; // Restore.
985 Declaration
parseImportDeclaration()
987 bool isStatic
= consumed(T
.Static
);
990 ModuleFQN
[] moduleFQNs
;
991 Identifier
*[] moduleAliases
;
992 Identifier
*[] bindNames
;
993 Identifier
*[] bindAliases
;
998 Identifier
* moduleAlias
;
999 // AliasName = ModuleName
1000 if (peekNext() == T
.Assign
)
1002 moduleAlias
= requireIdentifier(MSG
.ExpectedAliasModuleName
);
1005 // Identifier ("." Identifier)*
1007 moduleFQN
~= requireIdentifier(MSG
.ExpectedModuleIdentifier
);
1008 while (consumed(T
.Dot
))
1009 // Push identifiers.
1010 moduleFQNs
~= moduleFQN
;
1011 moduleAliases
~= moduleAlias
;
1012 } while (consumed(T
.Comma
))
1014 if (consumed(T
.Colon
))
1015 { // BindAlias "=" BindName ("," BindAlias "=" BindName)*;
1016 // BindName ("," BindName)*;
1019 Identifier
* bindAlias
;
1020 // BindAlias = BindName
1021 if (peekNext() == T
.Assign
)
1023 bindAlias
= requireIdentifier(MSG
.ExpectedAliasImportName
);
1026 // Push identifiers.
1027 bindNames
~= requireIdentifier(MSG
.ExpectedImportName
);
1028 bindAliases
~= bindAlias
;
1029 } while (consumed(T
.Comma
))
1031 require(T
.Semicolon
);
1033 return new ImportDeclaration(moduleFQNs
, moduleAliases
, bindNames
, bindAliases
, isStatic
);
1038 /// Returns true if this is an enum manifest or
1039 /// false if it's a normal enum declaration.
1040 bool isEnumManifest()
1042 assert(token
.kind
== T
.Enum
);
1044 auto kind
= peekAfter(next
);
1045 if (kind
== T
.Colon || kind
== T
.LBrace
)
1046 return false; // Anonymous enum.
1047 else if (kind
== T
.Identifier
)
1049 kind
= peekAfter(next
);
1050 if (kind
== T
.Colon || kind
== T
.LBrace || kind
== T
.Semicolon
)
1051 return false; // Named enum.
1053 return true; // Manifest enum.
1057 Declaration
parseEnumDeclaration()
1061 Identifier
* enumName
;
1063 EnumMemberDeclaration
[] members
;
1066 enumName
= optionalIdentifier();
1068 if (consumed(T
.Colon
))
1069 baseType
= parseBasicType();
1071 if (enumName
&& consumed(T
.Semicolon
))
1073 else if (consumed(T
.LBrace
))
1075 auto leftBrace
= this.prevToken
;
1077 while (token
.kind
!= T
.RBrace
)
1086 // Type Identifier = AssignExpression
1087 type
= parseType(); // Set outer type variable.
1088 if (token
.kind
!= T
.Identifier
)
1089 try_fail(), (type
= null);
1094 auto name
= requireIdentifier(MSG
.ExpectedEnumMember
);
1097 if (consumed(T
.Assign
))
1098 value
= parseAssignExpression();
1100 members
~= set(new EnumMemberDeclaration(type
, name
, value
), begin
);
1102 if (!consumed(T
.Comma
))
1105 requireClosing(T
.RBrace
, leftBrace
);
1108 error2(MSG
.ExpectedEnumBody
, token
);
1110 return new EnumDeclaration(enumName
, baseType
, members
, hasBody
);
1113 /// Wraps a declaration inside a template declaration.
1115 /// begin = begin token of decl.
1116 /// name = name of decl.
1117 /// decl = the declaration to be wrapped.
1118 /// tparams = the template parameters.
1119 /// constraint = the constraint expression.
1120 TemplateDeclaration
putInsideTemplateDeclaration(Token
* begin
,
1123 TemplateParameters tparams
,
1124 Expression constraint
)
1127 auto cd
= new CompoundDeclaration
;
1130 return new TemplateDeclaration(name
, tparams
, constraint
, cd
);
1133 Declaration
parseClassDeclaration()
1138 Identifier
* className
;
1139 TemplateParameters tparams
;
1140 Expression constraint
;
1141 BaseClassType
[] bases
;
1142 CompoundDeclaration decls
;
1144 className
= requireIdentifier(MSG
.ExpectedClassName
);
1146 if (token
.kind
== T
.LParen
)
1148 tparams
= parseTemplateParameterList();
1149 version(D2
) constraint
= parseOptionalConstraint();
1152 if (token
.kind
== T
.Colon
)
1153 bases
= parseBaseClasses();
1155 if (bases
.length
== 0 && consumed(T
.Semicolon
))
1157 else if (token
.kind
== T
.LBrace
)
1158 decls
= parseDeclarationDefinitionsBody();
1160 error2(MSG
.ExpectedClassBody
, token
);
1162 Declaration d
= new ClassDeclaration(className
, /+tparams, +/bases
, decls
);
1164 d
= putInsideTemplateDeclaration(begin
, className
, d
, tparams
, constraint
);
1168 BaseClassType
[] parseBaseClasses(bool colonLeadsOff
= true)
1170 colonLeadsOff
&& skip(T
.Colon
);
1172 BaseClassType
[] bases
;
1175 Protection prot
= Protection
.Public
;
1178 case T
.Identifier
, T
.Dot
, T
.Typeof
: goto LparseBasicType
;
1179 case T
.Private
: prot
= Protection
.Private
; break;
1180 case T
.Protected
: prot
= Protection
.Protected
; break;
1181 case T
.Package
: prot
= Protection
.Package
; break;
1182 case T
.Public
: /*prot = Protection.Public;*/ break;
1184 error2(MID
.ExpectedBaseClasses
, token
);
1187 nT(); // Skip protection attribute.
1190 auto type
= parseBasicType();
1191 bases
~= set(new BaseClassType(prot
, type
), begin
);
1192 } while (consumed(T
.Comma
))
1196 Declaration
parseInterfaceDeclaration()
1202 TemplateParameters tparams
;
1203 Expression constraint
;
1204 BaseClassType
[] bases
;
1205 CompoundDeclaration decls
;
1207 name
= requireIdentifier(MSG
.ExpectedInterfaceName
);
1209 if (token
.kind
== T
.LParen
)
1211 tparams
= parseTemplateParameterList();
1212 version(D2
) constraint
= parseOptionalConstraint();
1215 if (token
.kind
== T
.Colon
)
1216 bases
= parseBaseClasses();
1218 if (bases
.length
== 0 && consumed(T
.Semicolon
))
1220 else if (token
.kind
== T
.LBrace
)
1221 decls
= parseDeclarationDefinitionsBody();
1223 error2(MSG
.ExpectedInterfaceBody
, token
);
1225 Declaration d
= new InterfaceDeclaration(name
, /+tparams, +/bases
, decls
);
1227 d
= putInsideTemplateDeclaration(begin
, name
, d
, tparams
, constraint
);
1231 Declaration
parseStructOrUnionDeclaration()
1233 assert(token
.kind
== T
.Struct || token
.kind
== T
.Union
);
1238 TemplateParameters tparams
;
1239 Expression constraint
;
1240 CompoundDeclaration decls
;
1242 name
= optionalIdentifier();
1244 if (name
&& token
.kind
== T
.LParen
)
1246 tparams
= parseTemplateParameterList();
1247 version(D2
) constraint
= parseOptionalConstraint();
1250 if (name
&& consumed(T
.Semicolon
))
1252 else if (token
.kind
== T
.LBrace
)
1253 decls
= parseDeclarationDefinitionsBody();
1255 error2(begin
.kind
== T
.Struct ?
1256 MSG
.ExpectedStructBody
:
1257 MSG
.ExpectedUnionBody
, token
);
1260 if (begin
.kind
== T
.Struct
)
1262 auto sd
= new StructDeclaration(name
, /+tparams, +/decls
);
1263 sd
.setAlignSize(this.alignSize
);
1267 d
= new UnionDeclaration(name
, /+tparams, +/decls
);
1270 d
= putInsideTemplateDeclaration(begin
, name
, d
, tparams
, constraint
);
1274 Declaration
parseConstructorDeclaration()
1277 auto parameters
= parseParameterList();
1278 auto funcBody
= parseFunctionBody();
1279 return new ConstructorDeclaration(parameters
, funcBody
);
1282 Declaration
parseDestructorDeclaration()
1288 auto funcBody
= parseFunctionBody();
1289 return new DestructorDeclaration(funcBody
);
1292 Declaration
parseStaticConstructorDeclaration()
1298 auto funcBody
= parseFunctionBody();
1299 return new StaticConstructorDeclaration(funcBody
);
1302 Declaration
parseStaticDestructorDeclaration()
1309 auto funcBody
= parseFunctionBody();
1310 return new StaticDestructorDeclaration(funcBody
);
1313 Declaration
parseInvariantDeclaration()
1316 // Optional () for getting ready porting to D 2.0
1317 if (consumed(T
.LParen
))
1319 auto funcBody
= parseFunctionBody();
1320 return new InvariantDeclaration(funcBody
);
1323 Declaration
parseUnittestDeclaration()
1326 auto funcBody
= parseFunctionBody();
1327 return new UnittestDeclaration(funcBody
);
1330 Token
* parseIdentOrInt()
1332 if (consumed(T
.Int32
) ||
consumed(T
.Identifier
))
1333 return this.prevToken
;
1334 error2(MSG
.ExpectedIdentOrInt
, token
);
1338 Token
* parseVersionCondition()
1342 if (consumed(T
.Unittest
))
1343 return this.prevToken
;
1345 return parseIdentOrInt();
1348 Declaration
parseDebugDeclaration()
1354 Declaration decls
, elseDecls
;
1356 if (consumed(T
.Assign
))
1357 { // debug = Integer ;
1358 // debug = Identifier ;
1359 spec
= parseIdentOrInt();
1360 require(T
.Semicolon
);
1364 if (consumed(T
.LParen
))
1366 cond
= parseIdentOrInt();
1369 // debug DeclarationsBlock
1370 // debug ( Condition ) DeclarationsBlock
1371 decls
= parseDeclarationsBlock();
1372 // else DeclarationsBlock
1373 if (consumed(T
.Else
))
1374 elseDecls
= parseDeclarationsBlock();
1377 return new DebugDeclaration(spec
, cond
, decls
, elseDecls
);
1380 Declaration
parseVersionDeclaration()
1386 Declaration decls
, elseDecls
;
1388 if (consumed(T
.Assign
))
1389 { // version = Integer ;
1390 // version = Identifier ;
1391 spec
= parseIdentOrInt();
1392 require(T
.Semicolon
);
1397 cond
= parseVersionCondition();
1399 // version ( Condition ) DeclarationsBlock
1400 decls
= parseDeclarationsBlock();
1401 // else DeclarationsBlock
1402 if (consumed(T
.Else
))
1403 elseDecls
= parseDeclarationsBlock();
1406 return new VersionDeclaration(spec
, cond
, decls
, elseDecls
);
1409 Declaration
parseStaticIfDeclaration()
1414 Expression condition
;
1415 Declaration ifDecls
, elseDecls
;
1417 auto leftParen
= token
;
1419 condition
= parseAssignExpression();
1420 requireClosing(T
.RParen
, leftParen
);
1422 ifDecls
= parseDeclarationsBlock();
1424 if (consumed(T
.Else
))
1425 elseDecls
= parseDeclarationsBlock();
1427 return new StaticIfDeclaration(condition
, ifDecls
, elseDecls
);
1430 Declaration
parseStaticAssertDeclaration()
1434 Expression condition
, message
;
1435 auto leftParen
= token
;
1437 condition
= parseAssignExpression();
1438 if (consumed(T
.Comma
))
1439 message
= parseAssignExpression();
1440 requireClosing(T
.RParen
, leftParen
);
1441 require(T
.Semicolon
);
1442 return new StaticAssertDeclaration(condition
, message
);
1445 Declaration
parseTemplateDeclaration()
1448 auto name
= requireIdentifier(MSG
.ExpectedTemplateName
);
1449 auto tparams
= parseTemplateParameterList();
1450 auto constraint
= parseOptionalConstraint();
1451 auto decls
= parseDeclarationDefinitionsBody();
1452 return new TemplateDeclaration(name
, tparams
, constraint
, decls
);
1455 Declaration
parseNewDeclaration()
1458 auto parameters
= parseParameterList();
1459 auto funcBody
= parseFunctionBody();
1460 return new NewDeclaration(parameters
, funcBody
);
1463 Declaration
parseDeleteDeclaration()
1466 auto parameters
= parseParameterList();
1467 auto funcBody
= parseFunctionBody();
1468 return new DeleteDeclaration(parameters
, funcBody
);
1471 Type
parseTypeofType()
1475 auto leftParen
= token
;
1484 type
= new TypeofType();
1488 type
= new TypeofType(parseExpression());
1490 requireClosing(T
.RParen
, leftParen
);
1495 /// Parses a MixinDeclaration or MixinStatement.
1497 /// TemplateMixin :=
1498 /// mixin ( AssignExpression ) ;
1499 /// mixin TemplateIdentifier ;
1500 /// mixin TemplateIdentifier MixinIdentifier ;
1501 /// mixin TemplateIdentifier !( TemplateArguments ) ;
1502 /// mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
1504 Class
parseMixin(Class
)()
1506 static assert(is(Class
== MixinDeclaration
) ||
is(Class
== MixinStatement
));
1509 static if (is(Class
== MixinDeclaration
))
1511 if (consumed(T
.LParen
))
1513 auto leftParen
= token
;
1514 auto e
= parseAssignExpression();
1515 requireClosing(T
.RParen
, leftParen
);
1516 require(T
.Semicolon
);
1517 return new MixinDeclaration(e
);
1523 Identifier
* mixinIdent
;
1525 if (consumed(T
.Dot
))
1526 e
= set(new ModuleScopeExpression(parseIdentifierExpression()), begin
);
1528 e
= parseIdentifierExpression();
1530 while (consumed(T
.Dot
))
1531 e
= set(new DotExpression(e
, parseIdentifierExpression()), begin
);
1533 mixinIdent
= optionalIdentifier();
1534 require(T
.Semicolon
);
1536 return new Class(e
, mixinIdent
);
1539 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1540 | Statement parsing methods |
1541 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1543 CompoundStatement
parseStatements()
1547 auto statements
= new CompoundStatement();
1548 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
1549 statements
~= parseStatement();
1550 requireClosing(T
.RBrace
, begin
);
1551 return set(statements
, begin
);
1554 /// Parses a Statement.
1555 Statement
parseStatement()
1561 if (token
.isIntegralType
)
1563 d
= parseVariableOrFunction();
1564 goto LreturnDeclarationStatement
;
1570 uint size
= parseAlignAttribute();
1571 // Restrict align attribute to structs in parsing phase.
1572 StructDeclaration structDecl
;
1573 if (token
.kind
== T
.Struct
)
1575 auto begin2
= token
;
1576 structDecl
= parseStructOrUnionDeclaration().to
!(StructDeclaration
);
1577 structDecl
.setAlignSize(size
);
1578 set(structDecl
, begin2
);
1583 d
= new AlignDeclaration(size
, structDecl ?
cast(Declaration
)structDecl
: new CompoundDeclaration
);
1584 goto LreturnDeclarationStatement
;
1585 /+ Not applicable for statements.
1586 T.Private, T.Package, T.Protected, T.Public, T.Export,
1587 T.Deprecated, T.Override, T.Abstract,+/
1594 case_parseAttribute
:
1595 s
= parseAttributeStatement();
1598 if (peekNext() == T
.Colon
)
1600 auto ident
= token
.ident
;
1601 skip(T
.Identifier
); skip(T
.Colon
);
1602 s
= new LabeledStatement(ident
, parseNoScopeOrEmptyStatement());
1606 case T
.Dot
, T
.Typeof
:
1609 return parseVariableOrFunction(StorageClass
.None
,
1611 LinkageType
.None
, false, false);
1615 goto LreturnDeclarationStatement
; // Declaration
1617 goto case_parseExpressionStatement
; // Expression
1620 s
= parseIfStatement();
1623 s
= parseWhileStatement();
1626 s
= parseDoWhileStatement();
1629 s
= parseForStatement();
1631 case T
.Foreach
, T
.Foreach_reverse
:
1632 s
= parseForeachStatement();
1635 s
= parseSwitchStatement();
1638 s
= parseCaseStatement();
1641 s
= parseDefaultStatement();
1644 s
= parseContinueStatement();
1647 s
= parseBreakStatement();
1650 s
= parseReturnStatement();
1653 s
= parseGotoStatement();
1656 s
= parseWithStatement();
1658 case T
.Synchronized
:
1659 s
= parseSynchronizedStatement();
1662 s
= parseTryStatement();
1665 s
= parseThrowStatement();
1668 if (peekNext() != T
.LParen
)
1669 goto case_parseAttribute
;
1670 s
= parseScopeGuardStatement();
1673 s
= parseVolatileStatement();
1676 s
= parseAsmBlockStatement();
1679 s
= parsePragmaStatement();
1682 if (peekNext() == T
.LParen
)
1683 goto case_parseExpressionStatement
; // Parse as expression.
1684 s
= parseMixin
!(MixinStatement
)();
1690 s
= parseStaticIfStatement();
1693 s
= parseStaticAssertStatement();
1696 goto case_parseAttribute
;
1700 s
= parseDebugStatement();
1703 s
= parseVersionStatement();
1706 case T
.Alias
, T
.Typedef
:
1707 d
= parseDeclarationDefinition();
1708 goto LreturnDeclarationStatement
;
1712 if (isEnumManifest())
1713 goto case_parseAttribute
;
1715 d
= parseEnumDeclaration();
1716 goto LreturnDeclarationStatement
;
1718 d
= parseClassDeclaration();
1719 goto LreturnDeclarationStatement
;
1721 d
= parseInterfaceDeclaration();
1722 goto LreturnDeclarationStatement
;
1723 case T
.Struct
, T
.Union
:
1724 d
= parseStructOrUnionDeclaration();
1725 // goto LreturnDeclarationStatement;
1726 LreturnDeclarationStatement
:
1728 s
= new DeclarationStatement(d
);
1731 s
= parseScopeStatement();
1735 s
= new EmptyStatement();
1737 // Parse an ExpressionStatement:
1738 // Tokens that start a PrimaryExpression.
1739 // case T.Identifier, T.Dot, T.Typeof:
1743 case T
.True
, T
.False
:
1745 case T
.Int32
, T
.Int64
, T
.Uint32
, T
.Uint64
:
1746 case T
.Float32
, T
.Float64
, T
.Float80
,
1747 T
.Imaginary32
, T
.Imaginary64
, T
.Imaginary80
:
1752 case T
.Function
, T
.Delegate
:
1759 case T
.Traits
: // D2.0
1760 // Tokens that can start a UnaryExpression:
1761 case T
.AndBinary
, T
.PlusPlus
, T
.MinusMinus
, T
.Mul
, T
.Minus
,
1762 T
.Plus
, T
.Not
, T
.Tilde
, T
.New
, T
.Delete
, T
.Cast
:
1763 case_parseExpressionStatement
:
1764 s
= new ExpressionStatement(parseExpression());
1765 require(T
.Semicolon
);
1768 if (token
.isSpecialToken
)
1769 goto case_parseExpressionStatement
;
1771 if (token
.kind
!= T
.Dollar
)
1772 // Assert that this isn't a valid expression.
1773 assert(delegate bool(){
1775 auto expression
= try_(&parseExpression
, success
);
1777 }() == false, "Didn't expect valid expression."
1780 // Report error: it's an illegal statement.
1781 s
= new IllegalStatement();
1782 // Skip to next valid token.
1785 while (!token
.isStatementStart
&&
1786 token
.kind
!= T
.RBrace
&&
1787 token
.kind
!= T
.EOF
)
1788 auto text
= Token
.textSpan(begin
, this.prevToken
);
1789 error(begin
, MSG
.IllegalStatement
, text
);
1797 /// Parses a ScopeStatement.
1798 /// ScopeStatement :=
1799 /// NoScopeStatement
1801 Statement
parseScopeStatement()
1803 return new ScopeStatement(parseNoScopeStatement());
1807 /// NoScopeStatement :=
1808 /// NonEmptyStatement
1810 /// BlockStatement :=
1812 /// { StatementList }
1814 Statement
parseNoScopeStatement()
1818 if (consumed(T
.LBrace
))
1820 auto ss
= new CompoundStatement();
1821 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
1822 ss
~= parseStatement();
1823 requireClosing(T
.RBrace
, begin
);
1826 else if (token
.kind
== T
.Semicolon
)
1828 error(token
, MSG
.ExpectedNonEmptyStatement
);
1830 s
= set(new EmptyStatement(), begin
);
1833 s
= parseStatement();
1838 /// NoScopeOrEmptyStatement :=
1840 /// NoScopeStatement
1842 Statement
parseNoScopeOrEmptyStatement()
1844 if (consumed(T
.Semicolon
))
1845 return set(new EmptyStatement(), this.prevToken
);
1847 return parseNoScopeStatement();
1850 Statement
parseAttributeStatement()
1852 StorageClass
stc, stc_tmp
;
1853 LinkageType prev_linkageType
;
1855 Declaration
parse() // Nested function.
1862 if (peekNext() != T
.LParen
)
1864 stc_tmp
= StorageClass
.Extern
;
1869 auto linkageType
= parseLinkageType();
1870 checkLinkageType(prev_linkageType
, linkageType
, begin
);
1872 decl
= new LinkageDeclaration(linkageType
, parse());
1875 stc_tmp
= StorageClass
.Static
;
1878 stc_tmp
= StorageClass
.Final
;
1883 if (peekNext() == T
.LParen
)
1884 goto case_Declaration
;
1886 stc_tmp
= StorageClass
.Const
;
1890 case T
.Invariant
: // D 2.0
1891 if (peekNext() == T
.LParen
)
1892 goto case_Declaration
;
1893 stc_tmp
= StorageClass
.Invariant
;
1895 case T
.Enum
: // D 2.0
1896 if (!isEnumManifest())
1897 { // A normal enum declaration.
1898 decl
= parseEnumDeclaration();
1899 // NB: this must be similar to the code at the end of
1900 // parseDeclarationDefinition().
1901 decl
.setProtection(this.protection
);
1902 decl
.setStorageClass(stc);
1906 // enum as StorageClass.
1907 stc_tmp
= StorageClass
.Manifest
;
1911 stc_tmp
= StorageClass
.Auto
;
1914 stc_tmp
= StorageClass
.Scope
;
1917 // Issue error if redundant.
1919 error2(MID
.RedundantStorageClass
, token
);
1924 decl
= new StorageClassDeclaration(stc_tmp
, parse());
1926 case T
.Class
, T
.Interface
, T
.Struct
, T
.Union
, T
.Alias
, T
.Typedef
:
1927 decl
= parseDeclarationDefinition();
1928 decl
.setProtection(Protection
.None
);
1929 decl
.setStorageClass(StorageClass
.None
);
1933 return parseVariableOrFunction(stc, Protection
.None
, prev_linkageType
, true);
1935 return set(decl
, begin
);
1937 return new DeclarationStatement(parse());
1940 Statement
parseIfStatement()
1945 Expression condition
;
1946 Statement ifBody
, elseBody
;
1948 auto leftParen
= token
;
1952 auto begin
= token
; // For start of AutoDeclaration or normal Declaration.
1953 // auto Identifier = Expression
1954 if (consumed(T
.Auto
))
1956 ident
= requireIdentifier(MSG
.ExpectedVariableName
);
1958 auto init
= parseExpression();
1959 auto v
= new VariablesDeclaration(null, [ident
], [init
]);
1960 set(v
, begin
.nextNWS
);
1961 auto d
= new StorageClassDeclaration(StorageClass
.Auto
, v
);
1963 variable
= new DeclarationStatement(d
);
1964 set(variable
, begin
);
1967 { // Declarator = Expression
1968 Type
parseDeclaratorAssign()
1970 auto type
= parseDeclarator(ident
);
1975 auto type
= try_(&parseDeclaratorAssign
, success
);
1978 auto init
= parseExpression();
1979 auto v
= new VariablesDeclaration(type
, [ident
], [init
]);
1981 variable
= new DeclarationStatement(v
);
1982 set(variable
, begin
);
1985 condition
= parseExpression();
1987 requireClosing(T
.RParen
, leftParen
);
1988 ifBody
= parseScopeStatement();
1989 if (consumed(T
.Else
))
1990 elseBody
= parseScopeStatement();
1991 return new IfStatement(variable
, condition
, ifBody
, elseBody
);
1994 Statement
parseWhileStatement()
1997 auto leftParen
= token
;
1999 auto condition
= parseExpression();
2000 requireClosing(T
.RParen
, leftParen
);
2001 return new WhileStatement(condition
, parseScopeStatement());
2004 Statement
parseDoWhileStatement()
2007 auto doBody
= parseScopeStatement();
2009 auto leftParen
= token
;
2011 auto condition
= parseExpression();
2012 requireClosing(T
.RParen
, leftParen
);
2013 return new DoWhileStatement(condition
, doBody
);
2016 Statement
parseForStatement()
2020 Statement init
, forBody
;
2021 Expression condition
, increment
;
2023 auto leftParen
= token
;
2025 if (!consumed(T
.Semicolon
))
2026 init
= parseNoScopeStatement();
2027 if (token
.kind
!= T
.Semicolon
)
2028 condition
= parseExpression();
2029 require(T
.Semicolon
);
2030 if (token
.kind
!= T
.RParen
)
2031 increment
= parseExpression();
2032 requireClosing(T
.RParen
, leftParen
);
2033 forBody
= parseScopeStatement();
2034 return new ForStatement(init
, condition
, increment
, forBody
);
2037 Statement
parseForeachStatement()
2039 assert(token
.kind
== T
.Foreach || token
.kind
== T
.Foreach_reverse
);
2040 TOK tok
= token
.kind
;
2043 auto params
= new Parameters
;
2044 Expression e
; // Aggregate or LwrExpression
2046 auto leftParen
= token
;
2048 auto paramsBegin
= token
;
2051 auto paramBegin
= token
;
2058 case T
.Ref
, T
.Inout
:
2059 stc = StorageClass
.Ref
;
2063 auto next
= peekNext();
2064 if (next
== T
.Comma || next
== T
.Semicolon || next
== T
.RParen
)
2066 ident
= requireIdentifier(MSG
.ExpectedVariableName
);
2071 type
= parseDeclarator(ident
);
2074 params
~= set(new Parameter(stc, type
, ident
, null), paramBegin
);
2075 } while (consumed(T
.Comma
))
2076 set(params
, paramsBegin
);
2077 require(T
.Semicolon
);
2078 e
= parseExpression();
2080 { //Foreach (ForeachType; LwrExpression .. UprExpression ) ScopeStatement
2081 if (consumed(T
.Slice
))
2083 // if (params.length != 1)
2084 // error(MID.XYZ); // TODO: issue error msg
2085 auto upper
= parseExpression();
2086 requireClosing(T
.RParen
, leftParen
);
2087 auto forBody
= parseScopeStatement();
2088 return new ForeachRangeStatement(tok
, params
, e
, upper
, forBody
);
2091 // Foreach (ForeachTypeList; Aggregate) ScopeStatement
2092 requireClosing(T
.RParen
, leftParen
);
2093 auto forBody
= parseScopeStatement();
2094 return new ForeachStatement(tok
, params
, e
, forBody
);
2097 Statement
parseSwitchStatement()
2100 auto leftParen
= token
;
2102 auto condition
= parseExpression();
2103 requireClosing(T
.RParen
, leftParen
);
2104 auto switchBody
= parseScopeStatement();
2105 return new SwitchStatement(condition
, switchBody
);
2108 /// Helper function for parsing the body of a default or case statement.
2109 Statement
parseCaseOrDefaultBody()
2111 // This function is similar to parseNoScopeStatement()
2113 auto s
= new CompoundStatement();
2114 while (token
.kind
!= T
.Case
&&
2115 token
.kind
!= T
.Default
&&
2116 token
.kind
!= T
.RBrace
&&
2117 token
.kind
!= T
.EOF
)
2118 s
~= parseStatement();
2120 return set(new ScopeStatement(s
), begin
);
2123 Statement
parseCaseStatement()
2126 auto values
= parseExpressionList();
2128 auto caseBody
= parseCaseOrDefaultBody();
2129 return new CaseStatement(values
, caseBody
);
2132 Statement
parseDefaultStatement()
2136 auto defaultBody
= parseCaseOrDefaultBody();
2137 return new DefaultStatement(defaultBody
);
2140 Statement
parseContinueStatement()
2143 auto ident
= optionalIdentifier();
2144 require(T
.Semicolon
);
2145 return new ContinueStatement(ident
);
2148 Statement
parseBreakStatement()
2151 auto ident
= optionalIdentifier();
2152 require(T
.Semicolon
);
2153 return new BreakStatement(ident
);
2156 Statement
parseReturnStatement()
2160 if (token
.kind
!= T
.Semicolon
)
2161 expr
= parseExpression();
2162 require(T
.Semicolon
);
2163 return new ReturnStatement(expr
);
2166 Statement
parseGotoStatement()
2170 Expression caseExpr
;
2174 ident
= token
.ident
;
2176 if (token
.kind
== T
.Semicolon
)
2178 caseExpr
= parseExpression();
2181 ident
= token
.ident
;
2185 ident
= requireIdentifier(MSG
.ExpectedAnIdentifier
);
2187 require(T
.Semicolon
);
2188 return new GotoStatement(ident
, caseExpr
);
2191 Statement
parseWithStatement()
2194 auto leftParen
= token
;
2196 auto expr
= parseExpression();
2197 requireClosing(T
.RParen
, leftParen
);
2198 return new WithStatement(expr
, parseScopeStatement());
2201 Statement
parseSynchronizedStatement()
2203 skip(T
.Synchronized
);
2205 if (consumed(T
.LParen
))
2207 auto leftParen
= this.prevToken
;
2208 expr
= parseExpression();
2209 requireClosing(T
.RParen
, leftParen
);
2211 return new SynchronizedStatement(expr
, parseScopeStatement());
2214 Statement
parseTryStatement()
2219 auto tryBody
= parseScopeStatement();
2220 CatchStatement
[] catchBodies
;
2221 FinallyStatement finBody
;
2223 while (consumed(T
.Catch
))
2226 if (consumed(T
.LParen
))
2228 auto begin2
= token
;
2230 auto type
= parseDeclarator(ident
, true);
2231 param
= new Parameter(StorageClass
.None
, type
, ident
, null);
2235 catchBodies
~= set(new CatchStatement(param
, parseNoScopeStatement()), begin
);
2237 break; // This is a LastCatch
2241 if (consumed(T
.Finally
))
2242 finBody
= set(new FinallyStatement(parseNoScopeStatement()), prevToken
);
2244 if (catchBodies
.length
== 0 && finBody
is null)
2245 assert(begin
.kind
== T
.Try
), error(begin
, MSG
.MissingCatchOrFinally
);
2247 return new TryStatement(tryBody
, catchBodies
, finBody
);
2250 Statement
parseThrowStatement()
2253 auto expr
= parseExpression();
2254 require(T
.Semicolon
);
2255 return new ThrowStatement(expr
);
2258 Statement
parseScopeGuardStatement()
2262 auto condition
= requireIdentifier(MSG
.ExpectedScopeIdentifier
);
2264 switch (condition
.idKind
)
2266 case IDK
.exit
, IDK
.success
, IDK
.failure
:
2269 error2(MSG
.InvalidScopeIdentifier
, this.prevToken
);
2272 Statement scopeBody
;
2273 if (token
.kind
== T
.LBrace
)
2274 scopeBody
= parseScopeStatement();
2276 scopeBody
= parseNoScopeStatement();
2277 return new ScopeGuardStatement(condition
, scopeBody
);
2280 Statement
parseVolatileStatement()
2283 Statement volatileBody
;
2284 if (token
.kind
== T
.Semicolon
)
2286 else if (token
.kind
== T
.LBrace
)
2287 volatileBody
= parseScopeStatement();
2289 volatileBody
= parseStatement();
2290 return new VolatileStatement(volatileBody
);
2293 Statement
parsePragmaStatement()
2299 Statement pragmaBody
;
2301 auto leftParen
= token
;
2303 ident
= requireIdentifier(MSG
.ExpectedPragmaIdentifier
);
2305 if (consumed(T
.Comma
))
2306 args
= parseExpressionList();
2307 requireClosing(T
.RParen
, leftParen
);
2309 pragmaBody
= parseNoScopeOrEmptyStatement();
2311 return new PragmaStatement(ident
, args
, pragmaBody
);
2314 Statement
parseStaticIfStatement()
2318 Expression condition
;
2319 Statement ifBody
, elseBody
;
2321 auto leftParen
= token
;
2323 condition
= parseExpression();
2324 requireClosing(T
.RParen
, leftParen
);
2325 ifBody
= parseNoScopeStatement();
2326 if (consumed(T
.Else
))
2327 elseBody
= parseNoScopeStatement();
2328 return new StaticIfStatement(condition
, ifBody
, elseBody
);
2331 Statement
parseStaticAssertStatement()
2335 Expression condition
, message
;
2338 condition
= parseAssignExpression(); // Condition.
2339 if (consumed(T
.Comma
))
2340 message
= parseAssignExpression(); // Error message.
2342 require(T
.Semicolon
);
2343 return new StaticAssertStatement(condition
, message
);
2346 Statement
parseDebugStatement()
2350 Statement debugBody
, elseBody
;
2353 if (consumed(T
.LParen
))
2355 cond
= parseIdentOrInt();
2359 // debug ( Condition ) Statement
2360 debugBody
= parseNoScopeStatement();
2362 if (consumed(T
.Else
))
2363 elseBody
= parseNoScopeStatement();
2365 return new DebugStatement(cond
, debugBody
, elseBody
);
2368 Statement
parseVersionStatement()
2372 Statement versionBody
, elseBody
;
2376 cond
= parseVersionCondition();
2378 // version ( Condition ) Statement
2379 versionBody
= parseNoScopeStatement();
2381 if (consumed(T
.Else
))
2382 elseBody
= parseNoScopeStatement();
2384 return new VersionStatement(cond
, versionBody
, elseBody
);
2387 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2388 | Assembler parsing methods |
2389 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2391 /// Parses an AsmBlockStatement.
2392 Statement
parseAsmBlockStatement()
2395 auto leftBrace
= token
;
2397 auto ss
= new CompoundStatement
;
2398 while (token
.kind
!= T
.RBrace
&& token
.kind
!= T
.EOF
)
2399 ss
~= parseAsmStatement();
2400 requireClosing(T
.RBrace
, leftBrace
);
2401 return new AsmBlockStatement(ss
);
2404 Statement
parseAsmStatement()
2411 // Keywords that are valid opcodes.
2412 case T
.In
, T
.Int
, T
.Out
:
2413 ident
= token
.ident
;
2417 ident
= token
.ident
;
2419 if (consumed(T
.Colon
))
2420 { // Identifier : AsmStatement
2421 s
= new LabeledStatement(ident
, parseAsmStatement());
2427 // Opcode Operands ;
2431 if (token
.kind
!= T
.Semicolon
)
2433 es
~= parseAsmExpression();
2434 while (consumed(T
.Comma
))
2435 require(T
.Semicolon
);
2436 s
= new AsmStatement(ident
, es
);
2442 if (token
.kind
== T
.Int32
)
2443 (number
= token
.int_
), skip(T
.Int32
);
2445 error2(MSG
.ExpectedIntegerAfterAlign
, token
);
2446 require(T
.Semicolon
);
2447 s
= new AsmAlignStatement(number
);
2450 s
= new EmptyStatement();
2454 s
= new IllegalAsmStatement();
2455 // Skip to next valid token.
2458 while (!token
.isAsmStatementStart
&&
2459 token
.kind
!= T
.RBrace
&&
2460 token
.kind
!= T
.EOF
)
2461 auto text
= Token
.textSpan(begin
, this.prevToken
);
2462 error(begin
, MSG
.IllegalAsmStatement
, text
);
2468 Expression
parseAsmExpression()
2471 auto e
= parseAsmOrOrExpression();
2472 if (consumed(T
.Question
))
2474 auto tok
= this.prevToken
;
2475 auto iftrue
= parseAsmExpression();
2477 auto iffalse
= parseAsmExpression();
2478 e
= new CondExpression(e
, iftrue
, iffalse
, tok
);
2481 // TODO: create AsmExpression that contains e?
2485 Expression
parseAsmOrOrExpression()
2487 alias parseAsmAndAndExpression parseNext
;
2489 auto e
= parseNext();
2490 while (token
.kind
== T
.OrLogical
)
2494 e
= new OrOrExpression(e
, parseNext(), tok
);
2500 Expression
parseAsmAndAndExpression()
2502 alias parseAsmOrExpression parseNext
;
2504 auto e
= parseNext();
2505 while (token
.kind
== T
.AndLogical
)
2509 e
= new AndAndExpression(e
, parseNext(), tok
);
2515 Expression
parseAsmOrExpression()
2517 alias parseAsmXorExpression parseNext
;
2519 auto e
= parseNext();
2520 while (token
.kind
== T
.OrBinary
)
2524 e
= new OrExpression(e
, parseNext(), tok
);
2530 Expression
parseAsmXorExpression()
2532 alias parseAsmAndExpression parseNext
;
2534 auto e
= parseNext();
2535 while (token
.kind
== T
.Xor
)
2539 e
= new XorExpression(e
, parseNext(), tok
);
2545 Expression
parseAsmAndExpression()
2547 alias parseAsmCmpExpression parseNext
;
2549 auto e
= parseNext();
2550 while (token
.kind
== T
.AndBinary
)
2554 e
= new AndExpression(e
, parseNext(), tok
);
2560 Expression
parseAsmCmpExpression()
2562 alias parseAsmShiftExpression parseNext
;
2564 auto e
= parseNext();
2566 auto operator
= token
;
2567 switch (operator
.kind
)
2569 case T
.Equal
, T
.NotEqual
:
2571 e
= new EqualExpression(e
, parseNext(), operator
);
2573 case T
.LessEqual
, T
.Less
, T
.GreaterEqual
, T
.Greater
:
2575 e
= new RelExpression(e
, parseNext(), operator
);
2584 Expression
parseAsmShiftExpression()
2586 alias parseAsmAddExpression parseNext
;
2588 auto e
= parseNext();
2591 auto operator
= token
;
2592 switch (operator
.kind
)
2594 case T
.LShift
: nT(); e
= new LShiftExpression(e
, parseNext(), operator
); break;
2595 case T
.RShift
: nT(); e
= new RShiftExpression(e
, parseNext(), operator
); break;
2596 case T
.URShift
: nT(); e
= new URShiftExpression(e
, parseNext(), operator
); break;
2605 Expression
parseAsmAddExpression()
2607 alias parseAsmMulExpression parseNext
;
2609 auto e
= parseNext();
2612 auto operator
= token
;
2613 switch (operator
.kind
)
2615 case T
.Plus
: nT(); e
= new PlusExpression(e
, parseNext(), operator
); break;
2616 case T
.Minus
: nT(); e
= new MinusExpression(e
, parseNext(), operator
); break;
2617 // Not allowed in asm
2618 //case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
2627 Expression
parseAsmMulExpression()
2629 alias parseAsmPostExpression parseNext
;
2631 auto e
= parseNext();
2634 auto operator
= token
;
2635 switch (operator
.kind
)
2637 case T
.Mul
: nT(); e
= new MulExpression(e
, parseNext(), operator
); break;
2638 case T
.Div
: nT(); e
= new DivExpression(e
, parseNext(), operator
); break;
2639 case T
.Mod
: nT(); e
= new ModExpression(e
, parseNext(), operator
); break;
2648 Expression
parseAsmPostExpression()
2651 auto e
= parseAsmUnaryExpression();
2652 while (consumed(T
.LBracket
))
2654 auto leftBracket
= this.prevToken
;
2655 e
= new AsmPostBracketExpression(e
, parseAsmExpression());
2656 requireClosing(T
.RBracket
, leftBracket
);
2662 Expression
parseAsmUnaryExpression()
2668 case T
.Byte
, T
.Short
, T
.Int
,
2669 T
.Float
, T
.Double
, T
.Real
:
2670 goto LAsmTypePrefix
;
2672 switch (token
.ident
.idKind
)
2674 case IDK
.near
, IDK
.far
,/* "byte", "short", "int",*/
2675 IDK
.word
, IDK
.dword
, IDK
.qword
/*, "float", "double", "real"*/:
2678 if (token
.kind
== T
.Identifier
&& token
.ident
is Ident
.ptr
)
2681 error2(MID
.ExpectedButFound
, "ptr", token
);
2682 e
= new AsmTypeExpression(parseAsmExpression());
2686 e
= new AsmOffsetExpression(parseAsmExpression());
2690 e
= new AsmSegExpression(parseAsmExpression());
2693 goto LparseAsmPrimaryExpression
;
2699 e
= new SignExpression(parseAsmUnaryExpression());
2703 e
= new NotExpression(parseAsmUnaryExpression());
2707 e
= new CompExpression(parseAsmUnaryExpression());
2711 e
= new ModuleScopeExpression(parseIdentifierExpression());
2712 while (consumed(TOK
.Dot
))
2714 e
= new DotExpression(e
, parseIdentifierExpression());
2719 LparseAsmPrimaryExpression
:
2720 e
= parseAsmPrimaryExpression();
2727 Expression
parseAsmPrimaryExpression()
2733 case T
.Int32
, T
.Int64
, T
.Uint32
, T
.Uint64
:
2734 e
= new IntExpression(token
);
2737 case T
.Float32
, T
.Float64
, T
.Float80
,
2738 T
.Imaginary32
, T
.Imaginary64
, T
.Imaginary80
:
2739 e
= new RealExpression(token
);
2743 e
= new DollarExpression();
2747 // [ AsmExpression ]
2748 auto leftBracket
= token
;
2750 e
= parseAsmExpression();
2751 requireClosing(T
.RBracket
, leftBracket
);
2752 e
= new AsmBracketExpression(e
);
2755 auto register
= token
.ident
;
2756 switch (register
.idKind
)
2759 case IDK
.__LOCAL_SIZE
:
2761 e
= new AsmLocalSizeExpression();
2768 if (consumed(T
.LParen
))
2770 if (token
.kind
== T
.Int32
)
2771 (number
= token
.int_
), skip(T
.Int32
);
2776 e
= new AsmRegisterExpression(register
, number
);
2780 // TODO: is the colon-number part optional?
2782 if (consumed(T
.Colon
))
2785 if (token
.kind
== T
.Int32
)
2786 (number
= token
.int_
), skip(T
.Int32
);
2787 if (number
!= 0 && number
!= 4 && number
!= 8)
2788 error2(MID
.ExpectedButFound
, "0, 4 or 8", token
);
2790 e
= new AsmRegisterExpression(register
, number
);
2792 case IDK
.AL
, IDK
.AH
, IDK
.AX
, IDK
.EAX
,
2793 IDK
.BL
, IDK
.BH
, IDK
.BX
, IDK
.EBX
,
2794 IDK
.CL
, IDK
.CH
, IDK
.CX
, IDK
.ECX
,
2795 IDK
.DL
, IDK
.DH
, IDK
.DX
, IDK
.EDX
,
2796 IDK
.BP
, IDK
.EBP
, IDK
.SP
, IDK
.ESP
,
2797 IDK
.DI
, IDK
.EDI
, IDK
.SI
, IDK
.ESI
,
2798 IDK
.ES
, IDK
.CS
, IDK
.SS
, IDK
.DS
, IDK
.GS
,
2799 IDK
.CR0
, IDK
.CR2
, IDK
.CR3
, IDK
.CR4
,
2800 IDK
.DR0
, IDK
.DR1
, IDK
.DR2
, IDK
.DR3
, IDK
.DR6
, IDK
.DR7
,
2801 IDK
.TR3
, IDK
.TR4
, IDK
.TR5
, IDK
.TR6
, IDK
.TR7
,
2802 IDK
.MM0
, IDK
.MM1
, IDK
.MM2
, IDK
.MM3
,
2803 IDK
.MM4
, IDK
.MM5
, IDK
.MM6
, IDK
.MM7
,
2804 IDK
.XMM0
, IDK
.XMM1
, IDK
.XMM2
, IDK
.XMM3
,
2805 IDK
.XMM4
, IDK
.XMM5
, IDK
.XMM6
, IDK
.XMM7
:
2807 e
= new AsmRegisterExpression(register
);
2810 e
= parseIdentifierExpression();
2811 while (consumed(TOK
.Dot
))
2813 e
= new DotExpression(e
, parseIdentifierExpression());
2819 error2(MID
.ExpectedButFound
, "Expression", token
);
2820 e
= new IllegalExpression();
2822 { // Insert a dummy token and don't consume current one.
2823 begin
= lexer
.insertEmptyTokenBefore(token
);
2824 this.prevToken
= begin
;
2831 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2832 | Expression parsing methods |
2833 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2835 /// Parses an Expression.
2836 Expression
parseExpression()
2838 alias parseAssignExpression parseNext
;
2840 auto e
= parseNext();
2841 while (token
.kind
== T
.Comma
)
2845 e
= new CommaExpression(e
, parseNext(), comma
);
2851 Expression
parseAssignExpression()
2853 alias parseAssignExpression parseNext
;
2855 auto e
= parseCondExpression();
2859 nT(); e
= new AssignExpression(e
, parseNext()); break;
2860 case T
.LShiftAssign
:
2861 nT(); e
= new LShiftAssignExpression(e
, parseNext()); break;
2862 case T
.RShiftAssign
:
2863 nT(); e
= new RShiftAssignExpression(e
, parseNext()); break;
2864 case T
.URShiftAssign
:
2865 nT(); e
= new URShiftAssignExpression(e
, parseNext()); break;
2867 nT(); e
= new OrAssignExpression(e
, parseNext()); break;
2869 nT(); e
= new AndAssignExpression(e
, parseNext()); break;
2871 nT(); e
= new PlusAssignExpression(e
, parseNext()); break;
2873 nT(); e
= new MinusAssignExpression(e
, parseNext()); break;
2875 nT(); e
= new DivAssignExpression(e
, parseNext()); break;
2877 nT(); e
= new MulAssignExpression(e
, parseNext()); break;
2879 nT(); e
= new ModAssignExpression(e
, parseNext()); break;
2881 nT(); e
= new XorAssignExpression(e
, parseNext()); break;
2883 nT(); e
= new CatAssignExpression(e
, parseNext()); break;
2891 Expression
parseCondExpression()
2894 auto e
= parseOrOrExpression();
2895 if (token
.kind
== T
.Question
)
2899 auto iftrue
= parseExpression();
2901 auto iffalse
= parseCondExpression();
2902 e
= new CondExpression(e
, iftrue
, iffalse
, tok
);
2908 Expression
parseOrOrExpression()
2910 alias parseAndAndExpression parseNext
;
2912 auto e
= parseNext();
2913 while (token
.kind
== T
.OrLogical
)
2917 e
= new OrOrExpression(e
, parseNext(), tok
);
2923 Expression
parseAndAndExpression()
2925 alias parseOrExpression parseNext
;
2927 auto e
= parseNext();
2928 while (token
.kind
== T
.AndLogical
)
2932 e
= new AndAndExpression(e
, parseNext(), tok
);
2938 Expression
parseOrExpression()
2940 alias parseXorExpression parseNext
;
2942 auto e
= parseNext();
2943 while (token
.kind
== T
.OrBinary
)
2947 e
= new OrExpression(e
, parseNext(), tok
);
2953 Expression
parseXorExpression()
2955 alias parseAndExpression parseNext
;
2957 auto e
= parseNext();
2958 while (token
.kind
== T
.Xor
)
2962 e
= new XorExpression(e
, parseNext(), tok
);
2968 Expression
parseAndExpression()
2970 alias parseCmpExpression parseNext
;
2972 auto e
= parseNext();
2973 while (token
.kind
== T
.AndBinary
)
2977 e
= new AndExpression(e
, parseNext(), tok
);
2983 Expression
parseCmpExpression()
2985 alias parseShiftExpression parseNext
;
2987 auto e
= parseShiftExpression();
2989 auto operator
= token
;
2990 switch (operator
.kind
)
2992 case T
.Equal
, T
.NotEqual
:
2994 e
= new EqualExpression(e
, parseNext(), operator
);
2997 if (peekNext() != T
.Is
)
3003 e
= new IdentityExpression(e
, parseNext(), operator
);
3005 case T
.LessEqual
, T
.Less
, T
.GreaterEqual
, T
.Greater
,
3006 T
.Unordered
, T
.UorE
, T
.UorG
, T
.UorGorE
,
3007 T
.UorL
, T
.UorLorE
, T
.LorEorG
, T
.LorG
:
3009 e
= new RelExpression(e
, parseNext(), operator
);
3013 e
= new InExpression(e
, parseNext(), operator
);
3022 Expression
parseShiftExpression()
3024 alias parseAddExpression parseNext
;
3026 auto e
= parseNext();
3029 auto operator
= token
;
3030 switch (operator
.kind
)
3032 case T
.LShift
: nT(); e
= new LShiftExpression(e
, parseNext(), operator
); break;
3033 case T
.RShift
: nT(); e
= new RShiftExpression(e
, parseNext(), operator
); break;
3034 case T
.URShift
: nT(); e
= new URShiftExpression(e
, parseNext(), operator
); break;
3043 Expression
parseAddExpression()
3045 alias parseMulExpression parseNext
;
3047 auto e
= parseNext();
3050 auto operator
= token
;
3051 switch (operator
.kind
)
3053 case T
.Plus
: nT(); e
= new PlusExpression(e
, parseNext(), operator
); break;
3054 case T
.Minus
: nT(); e
= new MinusExpression(e
, parseNext(), operator
); break;
3055 case T
.Tilde
: nT(); e
= new CatExpression(e
, parseNext(), operator
); break;
3064 Expression
parseMulExpression()
3066 alias parsePostExpression parseNext
;
3068 auto e
= parseNext();
3071 auto operator
= token
;
3072 switch (operator
.kind
)
3074 case T
.Mul
: nT(); e
= new MulExpression(e
, parseNext(), operator
); break;
3075 case T
.Div
: nT(); e
= new DivExpression(e
, parseNext(), operator
); break;
3076 case T
.Mod
: nT(); e
= new ModExpression(e
, parseNext(), operator
); break;
3085 Expression
parsePostExpression()
3088 auto e
= parseUnaryExpression();
3091 while (consumed(T
.Dot
))
3093 e
= new DotExpression(e
, parseNewOrIdentifierExpression());
3100 e
= new PostIncrExpression(e
);
3103 e
= new PostDecrExpression(e
);
3106 e
= new CallExpression(e
, parseArguments());
3109 // parse Slice- and IndexExpression
3110 auto leftBracket
= token
;
3112 // [] is a SliceExpression
3113 if (token
.kind
== T
.RBracket
)
3115 e
= new SliceExpression(e
, null, null);
3119 Expression
[] es
= [parseAssignExpression()];
3121 // [ AssignExpression .. AssignExpression ]
3122 if (consumed(T
.Slice
))
3124 e
= new SliceExpression(e
, es
[0], parseAssignExpression());
3125 requireClosing(T
.RBracket
, leftBracket
);
3129 // [ ExpressionList ]
3130 if (consumed(T
.Comma
))
3131 es
~= parseExpressionList();
3132 requireClosing(T
.RBracket
, leftBracket
);
3134 e
= new IndexExpression(e
, es
);
3140 Lset
: // Jumped here to skip nT().
3146 Expression
parseUnaryExpression()
3154 e
= new AddressExpression(parseUnaryExpression());
3158 e
= new PreIncrExpression(parseUnaryExpression());
3162 e
= new PreDecrExpression(parseUnaryExpression());
3166 e
= new DerefExpression(parseUnaryExpression());
3171 e
= new SignExpression(parseUnaryExpression());
3175 e
= new NotExpression(parseUnaryExpression());
3179 e
= new CompExpression(parseUnaryExpression());
3182 e
= parseNewExpression();
3186 e
= new DeleteExpression(parseUnaryExpression());
3189 requireNext(T
.LParen
);
3195 auto begin2
= token
;
3197 type
= new ConstType(null);
3200 type
= new InvariantType(null);
3210 e
= new CastExpression(parseUnaryExpression(), type
);
3213 // ( Type ) . Identifier
3217 auto type
= parseType();
3223 auto type
= try_(&parseType_
, success
);
3226 auto ident
= requireIdentifier(MSG
.ExpectedIdAfterTypeDot
);
3227 e
= new TypeDotIdExpression(type
, ident
);
3233 e
= new ModuleScopeExpression(parseIdentifierExpression());
3236 e
= parsePrimaryExpression();
3245 /// IdentifierExpression :=
3247 /// TemplateInstance
3248 /// TemplateInstance :=
3249 /// Identifier !( TemplateArguments )
3251 Expression
parseIdentifierExpression()
3254 auto ident
= requireIdentifier(MSG
.ExpectedAnIdentifier
);
3256 // Peek for '(' to avoid matching: id !is id
3257 if (token
.kind
== T
.Not
&& peekNext() == T
.LParen
)
3258 { // Identifier !( TemplateArguments )
3260 auto tparams
= parseTemplateArguments();
3261 e
= new TemplateInstanceExpression(ident
, tparams
);
3264 e
= new IdentifierExpression(ident
);
3265 return set(e
, begin
);
3268 Expression
parseNewOrIdentifierExpression()
3270 return token
.kind
== T
.New ?
parseNewExpression() : parseIdentifierExpression();
3273 Expression
parsePrimaryExpression()
3280 e
= parseIdentifierExpression();
3283 e
= new TypeofExpression(parseTypeofType());
3287 e
= new ThisExpression();
3291 e
= new SuperExpression();
3295 e
= new NullExpression();
3297 case T
.True
, T
.False
:
3299 e
= new BoolExpression(token
.kind
== T
.True
);
3303 e
= new DollarExpression();
3305 case T
.Int32
, T
.Int64
, T
.Uint32
, T
.Uint64
:
3306 e
= new IntExpression(token
);
3309 case T
.Float32
, T
.Float64
, T
.Float80
,
3310 T
.Imaginary32
, T
.Imaginary64
, T
.Imaginary80
:
3311 e
= new RealExpression(token
);
3315 e
= new CharExpression(token
.dchar_
);
3319 char[] str = token
.str;
3320 char postfix
= token
.pf
;
3322 while (token
.kind
== T
.String
)
3327 if (token
.pf
&& token
.pf
!= postfix
)
3328 error(token
, MSG
.StringPostfixMismatch
);
3329 str.length
= str.length
- 1; // Exclude '\0'.
3336 if (hasInvalidUTF8(str, begin
))
3338 e
= new StringExpression(dil
.Unicode
.toUTF16(str)); break;
3340 if (hasInvalidUTF8(str, begin
))
3342 e
= new StringExpression(dil
.Unicode
.toUTF32(str)); break;
3345 // No checking done to allow for binary data.
3346 e
= new StringExpression(str); break;
3350 Expression
[] values
;
3353 if (!consumed(T
.RBracket
))
3355 e
= parseAssignExpression();
3356 if (consumed(T
.Colon
))
3357 goto LparseAssocArray
;
3358 if (consumed(T
.Comma
))
3359 values
= [e
] ~ parseExpressionList();
3360 requireClosing(T
.RBracket
, begin
);
3363 e
= new ArrayLiteralExpression(values
);
3367 Expression
[] keys
= [e
];
3372 keys
~= parseAssignExpression();
3375 values
~= parseAssignExpression();
3376 } while (consumed(T
.Comma
))
3377 requireClosing(T
.RBracket
, begin
);
3378 e
= new AArrayLiteralExpression(keys
, values
);
3381 // DelegateLiteral := { Statements }
3382 auto funcBody
= parseFunctionBody();
3383 e
= new FunctionLiteralExpression(funcBody
);
3385 case T
.Function
, T
.Delegate
:
3386 // FunctionLiteral := ("function"|"delegate") Type? "(" ArgumentList ")" FunctionBody
3387 nT(); // Skip function or delegate keyword.
3389 Parameters parameters
;
3390 if (token
.kind
!= T
.LBrace
)
3392 if (token
.kind
!= T
.LParen
) // Optional return type
3393 returnType
= parseType();
3394 parameters
= parseParameterList();
3396 auto funcBody
= parseFunctionBody();
3397 e
= new FunctionLiteralExpression(returnType
, parameters
, funcBody
);
3401 requireNext(T
.LParen
);
3402 e
= parseAssignExpression();
3403 if (consumed(T
.Comma
))
3404 msg
= parseAssignExpression();
3406 e
= new AssertExpression(e
, msg
);
3409 requireNext(T
.LParen
);
3410 e
= parseAssignExpression();
3412 e
= new MixinExpression(e
);
3415 requireNext(T
.LParen
);
3416 e
= parseAssignExpression();
3418 e
= new ImportExpression(e
);
3421 requireNext(T
.LParen
);
3422 auto type
= parseType();
3424 e
= new TypeidExpression(type
);
3428 auto leftParen
= token
;
3431 Type type
, specType
;
3432 Identifier
* ident
; // optional Identifier
3433 Token
* opTok
, specTok
;
3435 type
= parseDeclarator(ident
, true);
3439 case T
.Colon
, T
.Equal
:
3454 case_Const_Invariant
:
3458 case T
.Const
, T
.Invariant
:
3459 if (peekNext() != T
.LParen
)
3460 goto case_Const_Invariant
;
3461 // Fall through. It's a type.
3463 specType
= parseType();
3468 TemplateParameters tparams
;
3471 // is ( Type Identifier : TypeSpecialization , TemplateParameterList )
3472 // is ( Type Identifier == TypeSpecialization , TemplateParameterList )
3473 if (ident
&& specType
&& token
.kind
== T
.Comma
)
3474 tparams
= parseTemplateParameterList2();
3476 requireClosing(T
.RParen
, leftParen
);
3477 e
= new IsExpression(type
, ident
, opTok
, specTok
, specType
, tparams
);
3480 if (tokenAfterParenIs(T
.LBrace
)) // Check for "(...) {"
3481 { // ( ParameterList ) FunctionBody
3482 auto parameters
= parseParameterList();
3483 auto funcBody
= parseFunctionBody();
3484 e
= new FunctionLiteralExpression(null, parameters
, funcBody
);
3488 auto leftParen
= token
;
3490 e
= parseExpression();
3491 requireClosing(T
.RParen
, leftParen
);
3492 e
= new ParenExpression(e
);
3498 requireNext(T
.LParen
);
3499 auto id
= requireIdentifier(MSG
.ExpectedAnIdentifier
);
3500 TemplateArguments args
;
3501 if (token
.kind
== T
.Comma
)
3502 args
= parseTemplateArguments2();
3505 e
= new TraitsExpression(id
, args
);
3509 if (token
.isIntegralType
)
3510 { // IntegralType . Identifier
3511 auto type
= new IntegralType(token
.kind
);
3515 auto ident
= requireIdentifier(MSG
.ExpectedIdAfterTypeDot
);
3516 e
= new TypeDotIdExpression(type
, ident
);
3518 else if (token
.isSpecialToken
)
3520 e
= new SpecialTokenExpression(token
);
3525 error2(MID
.ExpectedButFound
, "Expression", token
);
3526 e
= new IllegalExpression();
3528 { // Insert a dummy token and don't consume current one.
3529 begin
= lexer
.insertEmptyTokenBefore(token
);
3530 this.prevToken
= begin
;
3538 Expression
parseNewExpression(/*Expression e*/)
3543 Expression
[] newArguments
;
3544 Expression
[] ctorArguments
;
3546 if (token
.kind
== T
.LParen
)
3547 newArguments
= parseArguments();
3549 // NewAnonClassExpression:
3550 // new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
3551 if (consumed(T
.Class
))
3553 if (token
.kind
== T
.LParen
)
3554 ctorArguments
= parseArguments();
3556 BaseClassType
[] bases
= token
.kind
!= T
.LBrace ?
parseBaseClasses(false) : null ;
3558 auto decls
= parseDeclarationDefinitionsBody();
3559 return set(new NewAnonClassExpression(/*e, */newArguments
, bases
, ctorArguments
, decls
), begin
);
3563 // NewArguments Type [ AssignExpression ]
3564 // NewArguments Type ( ArgumentList )
3565 // NewArguments Type
3566 auto type
= parseType();
3568 if (token
.kind
== T
.LParen
)
3569 ctorArguments
= parseArguments();
3571 return set(new NewExpression(/*e, */newArguments
, type
, ctorArguments
), begin
);
3577 return parseBasicType2(parseBasicType());
3580 Type
parseIdentifierType()
3583 auto ident
= requireIdentifier(MSG
.ExpectedAnIdentifier
);
3585 if (consumed(T
.Not
)) // Identifier !( TemplateArguments )
3586 t
= new TemplateInstanceType(ident
, parseTemplateArguments());
3588 t
= new IdentifierType(ident
);
3589 return set(t
, begin
);
3592 Type
parseQualifiedType()
3596 if (token
.kind
== T
.Dot
)
3597 type
= set(new ModuleScopeType(), begin
, begin
);
3598 else if (token
.kind
== T
.Typeof
)
3599 type
= parseTypeofType();
3601 type
= parseIdentifierType();
3603 while (consumed(T
.Dot
))
3604 type
= set(new QualifiedType(type
, parseIdentifierType()), begin
);
3608 Type
parseBasicType()
3613 if (token
.isIntegralType
)
3615 t
= new IntegralType(token
.kind
);
3621 case T
.Identifier
, T
.Typeof
, T
.Dot
:
3622 t
= parseQualifiedType();
3628 requireNext(T
.LParen
);
3631 t
= new ConstType(t
);
3634 // invariant ( Type )
3635 requireNext(T
.LParen
);
3638 t
= new InvariantType(t
);
3642 error2(MID
.ExpectedButFound
, "BasicType", token
);
3643 t
= new IllegalType();
3646 return set(t
, begin
);
3649 Type
parseBasicType2(Type t
)
3657 t
= new PointerType(t
);
3661 t
= parseArrayType(t
);
3663 case T
.Function
, T
.Delegate
:
3664 TOK tok
= token
.kind
;
3666 auto parameters
= parseParameterList();
3667 if (tok
== T
.Function
)
3668 t
= new FunctionType(t
, parameters
);
3670 t
= new DelegateType(t
, parameters
);
3680 /// Returns true if the token after the closing parenthesis
3681 /// matches the searched kind.
3682 bool tokenAfterParenIs(TOK kind
)
3684 assert(token
.kind
== T
.LParen
);
3686 return skipParens(next
) == kind
;
3690 bool tokenAfterParenIs(TOK kind
, ref Token
* next
)
3692 assert(next
!is null && next
.kind
== T
.LParen
);
3693 return skipParens(next
) == kind
;
3696 /// Skips to the token behind the closing parenthesis.
3697 /// Takes nested parentheses into account.
3698 TOK
skipParens(ref Token
* next
)
3700 assert(next
!is null && next
.kind
== T
.LParen
);
3701 // We count nested parentheses tokens because template types, typeof etc.
3702 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y)
3706 switch (peekAfter(next
))
3713 return peekAfter(next
); // Closing parenthesis found.
3719 assert(0, "should be unreachable");
3722 /// Parse the array types after the declarator (C-style.) E.g.: int a[]
3723 Type
parseDeclaratorSuffix(Type lhsType
)
3725 // The Type chain should be as follows:
3726 // int[3]* Identifier [][32]
3728 // ^-----------------´
3729 // Resulting chain: [][32]*[3]int
3730 Type
parseNext() // Nested function required to accomplish this.
3732 if (token
.kind
!= T
.LBracket
)
3733 return lhsType
; // Break recursion; return Type on the left hand side of the Identifier.
3738 if (consumed(T
.RBracket
))
3739 t
= new ArrayType(parseNext()); // [ ]
3745 auto type
= parseType();
3746 require(T
.RBracket
);
3749 auto assocType
= try_(&parseAAType
, success
);
3751 t
= new ArrayType(parseNext(), assocType
); // [ Type ]
3754 Expression e
= parseExpression(), e2
;
3755 if (consumed(T
.Slice
))
3756 e2
= parseExpression();
3757 requireClosing(T
.RBracket
, begin
);
3758 t
= new ArrayType(parseNext(), e
, e2
); // [ Expression .. Expression ]
3767 Type
parseArrayType(Type t
)
3771 if (consumed(T
.RBracket
))
3772 t
= new ArrayType(t
);
3778 auto type
= parseType();
3779 require(T
.RBracket
);
3782 auto assocType
= try_(&parseAAType
, success
);
3784 t
= new ArrayType(t
, assocType
);
3787 Expression e
= parseExpression(), e2
;
3788 if (consumed(T
.Slice
))
3789 e2
= parseExpression();
3790 requireClosing(T
.RBracket
, begin
);
3791 t
= new ArrayType(t
, e
, e2
);
3798 Type
parseCFunctionPointerType(Type type
, ref Identifier
* ident
, bool optionalParamList
)
3800 assert(type
!is null);
3804 type
= parseBasicType2(type
);
3805 if (token
.kind
== T
.LParen
)
3807 type
= parseCFunctionPointerType(type
, ident
, true);
3809 else if (token
.kind
== T
.Identifier
)
3810 { // The identifier of the function pointer and the declaration.
3811 ident
= token
.ident
;
3813 type
= parseDeclaratorSuffix(type
);
3815 requireClosing(T
.RParen
, begin
);
3818 if (optionalParamList
)
3819 params
= token
.kind
== T
.LParen ?
parseParameterList() : null;
3821 params
= parseParameterList();
3823 type
= new CFuncPointerType(type
, params
);
3824 return set(type
, begin
);
3827 Type
parseDeclarator(ref Identifier
* ident
, bool identOptional
= false)
3829 auto t
= parseType();
3831 if (token
.kind
== T
.LParen
)
3832 t
= parseCFunctionPointerType(t
, ident
, true);
3833 else if (token
.kind
== T
.Identifier
)
3835 ident
= token
.ident
;
3837 t
= parseDeclaratorSuffix(t
);
3840 if (ident
is null && !identOptional
)
3841 error2(MSG
.ExpectedDeclaratorIdentifier
, token
);
3846 /// Parses a list of AssignExpressions.
3848 /// ExpressionList :=
3849 /// AssignExpression
3850 /// AssignExpression , ExpressionList
3852 Expression
[] parseExpressionList()
3854 Expression
[] expressions
;
3856 expressions
~= parseAssignExpression();
3857 while(consumed(T
.Comma
))
3861 /// Parses a list of Arguments.
3865 /// ( ExpressionList )
3867 Expression
[] parseArguments()
3869 auto leftParen
= token
;
3872 if (token
.kind
!= T
.RParen
)
3873 args
= parseExpressionList();
3874 requireClosing(T
.RParen
, leftParen
);
3878 /// Parses a ParameterList.
3879 Parameters
parseParameterList()
3882 if (params
.length
> 1)
3883 foreach (param
; params
.items
[0..$-1])
3885 if (param
.isVariadic())
3886 assert(0, "variadic arguments can only appear at the end of the parameter list.");
3894 auto params
= new Parameters();
3896 if (consumed(T
.RParen
))
3897 return set(params
, begin
);
3901 auto paramBegin
= token
;
3902 StorageClass
stc, stc_
;
3905 Expression defValue
;
3907 void pushParameter()
3909 params
~= set(new Parameter(stc, type
, ident
, defValue
), paramBegin
);
3912 if (consumed(T
.Ellipses
))
3914 stc = StorageClass
.Variadic
;
3915 pushParameter(); // type, ident and defValue will be null.
3920 { // Parse storage classes.
3925 case T
.Invariant
: // D2.0
3926 if (peekNext() == T
.LParen
)
3928 stc_
= StorageClass
.Invariant
;
3930 case T
.Const
: // D2.0
3931 if (peekNext() == T
.LParen
)
3933 stc_
= StorageClass
.Const
;
3935 case T
.Final
: // D2.0
3936 stc_
= StorageClass
.Final
;
3938 case T
.Scope
: // D2.0
3939 stc_
= StorageClass
.Scope
;
3941 case T
.Static
: // D2.0
3942 stc_
= StorageClass
.Static
;
3946 stc_
= StorageClass
.In
;
3949 stc_
= StorageClass
.Out
;
3951 case T
.Inout
, T
.Ref
:
3952 stc_
= StorageClass
.Ref
;
3955 stc_
= StorageClass
.Lazy
;
3958 // Check for redundancy.
3960 error2(MID
.RedundantStorageClass
, token
);
3967 break; // In D1.0 the grammar only allows one storage class.
3970 break; // Break out of inner loop.
3972 type
= parseDeclarator(ident
, true);
3974 if (consumed(T
.Assign
))
3975 defValue
= parseAssignExpression();
3977 if (consumed(T
.Ellipses
))
3979 stc |
= StorageClass
.Variadic
;
3985 } while (consumed(T
.Comma
))
3986 requireClosing(T
.RParen
, begin
);
3987 return set(params
, begin
);
3990 TemplateArguments
parseTemplateArguments()
3992 TemplateArguments targs
;
3993 auto leftParen
= token
;
3995 if (token
.kind
!= T
.RParen
)
3996 targs
= parseTemplateArguments_();
3997 requireClosing(T
.RParen
, leftParen
);
4003 TemplateArguments
parseTemplateArguments2()
4006 TemplateArguments targs
;
4007 if (token
.kind
!= T
.RParen
)
4008 targs
= parseTemplateArguments_();
4010 error(token
, MSG
.ExpectedTypeOrExpression
);
4016 TemplateArguments
parseTemplateArguments_()
4019 auto targs
= new TemplateArguments
;
4024 auto type
= parseType();
4025 if (token
.kind
== T
.Comma || token
.kind
== T
.RParen
)
4031 auto typeArgument
= try_(&parseType_
, success
);
4033 // TemplateArgument:
4036 targs
~= typeArgument
;
4038 // TemplateArgument:
4040 targs
~= parseAssignExpression();
4041 } while (consumed(T
.Comma
))
4046 /// if ( ConstraintExpression )
4047 Expression
parseOptionalConstraint()
4049 if (!consumed(T
.If
))
4052 auto e
= parseExpression();
4057 TemplateParameters
parseTemplateParameterList()
4060 auto tparams
= new TemplateParameters
;
4062 if (token
.kind
!= T
.RParen
)
4063 parseTemplateParameterList_(tparams
);
4064 requireClosing(T
.RParen
, begin
);
4065 return set(tparams
, begin
);
4070 TemplateParameters
parseTemplateParameterList2()
4074 auto tparams
= new TemplateParameters
;
4075 if (token
.kind
!= T
.RParen
)
4076 parseTemplateParameterList_(tparams
);
4078 error(token
, MSG
.ExpectedTemplateParameters
);
4079 return set(tparams
, begin
);
4083 /// Parses template parameters.
4084 void parseTemplateParameterList_(TemplateParameters tparams
)
4088 auto paramBegin
= token
;
4089 TemplateParameter tp
;
4091 Type specType
, defType
;
4093 void parseSpecAndOrDefaultType()
4095 // : SpecializationType
4096 if (consumed(T
.Colon
))
4097 specType
= parseType();
4099 if (consumed(T
.Assign
))
4100 defType
= parseType();
4106 // TemplateAliasParameter:
4109 ident
= requireIdentifier(MSG
.ExpectedAliasTemplateParam
);
4110 parseSpecAndOrDefaultType();
4111 tp
= new TemplateAliasParameter(ident
, specType
, defType
);
4114 ident
= token
.ident
;
4118 // TemplateTupleParameter:
4120 skip(T
.Identifier
); skip(T
.Ellipses
);
4121 if (token
.kind
== T
.Comma
)
4122 error(MID
.TemplateTupleParameter
);
4123 tp
= new TemplateTupleParameter(ident
);
4125 case T
.Comma
, T
.RParen
, T
.Colon
, T
.Assign
:
4126 // TemplateTypeParameter:
4129 parseSpecAndOrDefaultType();
4130 tp
= new TemplateTypeParameter(ident
, specType
, defType
);
4133 // TemplateValueParameter:
4136 goto LTemplateValueParameter
;
4142 // TemplateThisParameter
4143 // this TemplateTypeParameter
4145 ident
= requireIdentifier(MSG
.ExpectedNameForThisTempParam
);
4146 parseSpecAndOrDefaultType();
4147 tp
= new TemplateThisParameter(ident
, specType
, defType
);
4151 LTemplateValueParameter
:
4152 // TemplateValueParameter:
4154 Expression specValue
, defValue
;
4155 auto valueType
= parseDeclarator(ident
);
4156 // : SpecializationValue
4157 if (consumed(T
.Colon
))
4158 specValue
= parseCondExpression();
4160 if (consumed(T
.Assign
))
4161 defValue
= parseCondExpression();
4162 tp
= new TemplateValueParameter(valueType
, ident
, specValue
, defValue
);
4165 // Push template parameter.
4166 tparams
~= set(tp
, paramBegin
);
4168 } while (consumed(T
.Comma
))
4171 /// Returns the string of a token printable to the client.
4172 char[] getPrintable(Token
* token
)
4173 { // TODO: there are some other tokens that have to be handled, e.g. strings.
4174 return token
.kind
== T
.EOF ?
"EOF" : token
.srcText
;
4177 alias require expected
;
4179 /// Requires a token of kind tok.
4180 void require(TOK tok
)
4182 if (token
.kind
== tok
)
4185 error2(MID
.ExpectedButFound
, Token
.toString(tok
), token
);
4188 /// Requires the next token to be of kind tok.
4189 void requireNext(TOK tok
)
4195 /// Optionally parses an identifier.
4196 /// Returns: null or the identifier.
4197 Identifier
* optionalIdentifier()
4200 if (token
.kind
== T
.Identifier
)
4201 (id
= token
.ident
), skip(T
.Identifier
);
4205 Identifier
* requireIdentifier()
4208 if (token
.kind
== T
.Identifier
)
4209 (id
= token
.ident
), skip(T
.Identifier
);
4211 error(MID
.ExpectedButFound
, "Identifier", token
.srcText
);
4215 /// Reports an error if the current token is not an identifier.
4217 /// errorMsg = the error message to be used.
4218 /// Returns: null or the identifier.
4219 Identifier
* requireIdentifier(char[] errorMsg
)
4222 if (token
.kind
== T
.Identifier
)
4223 (id
= token
.ident
), skip(T
.Identifier
);
4225 error(token
, errorMsg
, token
.srcText
);
4229 /// Reports an error if the current token is not an identifier.
4231 /// mid = the error message ID to be used.
4232 /// Returns: null or the identifier.
4233 Identifier
* requireIdentifier(MID mid
)
4236 if (token
.kind
== T
.Identifier
)
4237 (id
= token
.ident
), skip(T
.Identifier
);
4239 error(mid
, token
.srcText
);
4243 /// Reports an error if the current token is not an identifier.
4244 /// Returns: null or the token.
4248 if (token
.kind
== T
.Identifier
)
4249 (idtok
= token
), skip(T
.Identifier
);
4251 error(MID
.ExpectedButFound
, "Identifier", token
.srcText
);
4255 Token
* requireIdToken(char[] errorMsg
)
4258 if (token
.kind
== T
.Identifier
)
4259 (idtok
= token
), skip(T
.Identifier
);
4262 error(token
, errorMsg
, token
.srcText
);
4263 idtok
= lexer
.insertEmptyTokenBefore(token
);
4264 this.prevToken
= idtok
;
4269 /// Reports an error if the closing counterpart of a token is not found.
4270 void requireClosing(TOK closing
, Token
* opening
)
4272 assert(closing
== T
.RBrace || closing
== T
.RParen || closing
== T
.RBracket
);
4273 assert(opening
!is null);
4274 if (!consumed(closing
))
4276 auto loc
= opening
.getRealLocation();
4277 auto openingLoc
= Format("(opening @{},{})", loc
.lineNum
, loc
.colNum
);
4278 error(token
, MSG
.ExpectedClosing
,
4279 Token
.toString(closing
), openingLoc
, getPrintable(token
));
4283 /// Returns true if the string str has an invalid UTF-8 sequence.
4284 bool hasInvalidUTF8(string
str, Token
* begin
)
4286 auto invalidUTF8Seq
= Lexer
.findInvalidUTF8Sequence(str);
4287 if (invalidUTF8Seq
.length
)
4288 error(begin
, MSG
.InvalidUTF8SequenceInString
, invalidUTF8Seq
);
4289 return invalidUTF8Seq
.length
!= 0;
4292 /// Forwards error parameters.
4293 void error(Token
* token
, char[] formatMsg
, ...)
4295 error_(token
, formatMsg
, _arguments
, _argptr
);
4298 void error(MID mid
, ...)
4300 error_(this.token
, GetMsg(mid
), _arguments
, _argptr
);
4304 void error2(char[] formatMsg
, Token
* token
)
4306 error(token
, formatMsg
, getPrintable(token
));
4309 void error2(MID mid
, Token
* token
)
4311 error(mid
, getPrintable(token
));
4314 void error2(MID mid
, char[] arg
, Token
* token
)
4316 error(mid
, arg
, getPrintable(token
));
4319 /// Creates an error report and appends it to a list.
4321 /// token = used to get the location of where the error is.
4322 /// formatMsg = the compiler error message.
4323 void error_(Token
* token
, char[] formatMsg
, TypeInfo
[] _arguments
, va_list _argptr
)
4330 auto location
= token
.getErrorLocation();
4331 auto msg
= Format(_arguments
, _argptr
, formatMsg
);
4332 auto error
= new ParserError(location
, msg
);