comparison trunk/src/dil/parser/Parser.d @ 798:c24be8d4f6ab

Added documentation comments.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sat, 01 Mar 2008 02:53:06 +0100
parents c1d5cfd7aa44
children cb8040538772
comparison
equal deleted inserted replaced
797:cf2ad5df025c 798:c24be8d4f6ab
31 InfoManager infoMan; 31 InfoManager infoMan;
32 ParserError[] errors; 32 ParserError[] errors;
33 33
34 ImportDeclaration[] imports; /// ImportDeclarations in the source text. 34 ImportDeclaration[] imports; /// ImportDeclarations in the source text.
35 35
36 // Attributes are evaluated in the parsing phase. 36 /// Attributes are evaluated in the parsing phase.
37 // Will probably be moved to class SemanticPass1. 37 /// TODO: will be removed. SemanticPass1 takes care of attributes.
38 LinkageType linkageType; 38 LinkageType linkageType;
39 Protection protection; 39 Protection protection; /// ditto
40 StorageClass storageClass; 40 StorageClass storageClass; /// ditto
41 uint alignSize = DEFAULT_ALIGN_SIZE; 41 uint alignSize = DEFAULT_ALIGN_SIZE; /// ditto
42 42
43 private alias TOK T; 43 private alias TOK T; /// Used often in this class.
44 private alias TypeNode Type; 44 private alias TypeNode Type;
45 45
46 /++ 46 /// Constructs a Parser object.
47 Construct a Parser object. 47 /// Params:
48 Params: 48 /// text = the UTF-8 source code.
49 text = the UTF-8 source code. 49 /// infoMan = used for collecting error messages.
50 infoMan = used for collecting error messages.
51 +/
52 this(SourceText srcText, InfoManager infoMan = null) 50 this(SourceText srcText, InfoManager infoMan = null)
53 { 51 {
54 this.infoMan = infoMan; 52 this.infoMan = infoMan;
55 lexer = new Lexer(srcText, infoMan); 53 lexer = new Lexer(srcText, infoMan);
56 } 54 }
95 93
96 // Members related to the method try_(). 94 // Members related to the method try_().
97 uint trying; /// Greater than 0 if Parser is in try_(). 95 uint trying; /// Greater than 0 if Parser is in try_().
98 uint errorCount; /// Used to track nr. of errors while being in try_(). 96 uint errorCount; /// Used to track nr. of errors while being in try_().
99 97
100 /++ 98 /// This method executes the delegate parseMethod and when an error occurred
101 This method executes the delegate parseMethod and when an error occurred 99 /// the state of the lexer and parser are restored.
102 the state of the lexer and parser are restored. 100 /// Returns: the return value of parseMethod().
103 +/
104 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success) 101 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success)
105 { 102 {
106 // Save members. 103 // Save members.
107 auto oldToken = this.token; 104 auto oldToken = this.token;
108 auto oldPrevToken = this.prevToken; 105 auto oldPrevToken = this.prevToken;
146 lexer.peek(next); 143 lexer.peek(next);
147 while (next.isWhitespace) // Skip whitespace 144 while (next.isWhitespace) // Skip whitespace
148 return next.kind; 145 return next.kind;
149 } 146 }
150 147
151 /// Returns the token kind of the token after 'next'. 148 /// Returns the token kind of the token that comes after t.
152 TOK peekAfter(ref Token* next) 149 TOK peekAfter(ref Token* t)
153 { 150 {
154 assert(next !is null); 151 assert(t !is null);
155 do 152 do
156 lexer.peek(next); 153 lexer.peek(t);
157 while (next.isWhitespace) // Skip whitespace 154 while (t.isWhitespace) // Skip whitespace
158 return next.kind; 155 return t.kind;
159 } 156 }
160 157
161 /// Consumes the current token if its kind matches k and returns true. 158 /// Consumes the current token if its kind matches k and returns true.
162 bool consumed()(TOK k) // Templatized, so it's inlined. 159 bool consumed()(TOK k) // Templatized, so it's inlined.
163 { 160 {
186 while (consumed(T.Dot)) 183 while (consumed(T.Dot))
187 require(T.Semicolon); 184 require(T.Semicolon);
188 return set(new ModuleDeclaration(moduleFQN), begin); 185 return set(new ModuleDeclaration(moduleFQN), begin);
189 } 186 }
190 187
191 /++ 188 /// Parses DeclarationDefinitions until the end of file is hit.
192 Parse DeclarationDefinitions until the end of file is hit. 189 /// $(PRE
193 DeclDefs: 190 /// DeclDefs :=
194 DeclDef 191 /// DeclDef
195 DeclDefs 192 /// DeclDefs
196 +/ 193 /// )
197 Declaration[] parseDeclarationDefinitions() 194 Declaration[] parseDeclarationDefinitions()
198 { 195 {
199 Declaration[] decls; 196 Declaration[] decls;
200 while (token.kind != T.EOF) 197 while (token.kind != T.EOF)
201 decls ~= parseDeclarationDefinition(); 198 decls ~= parseDeclarationDefinition();
202 return decls; 199 return decls;
203 } 200 }
204 201
205 /++ 202 /// Parse the body of a template, class, interface, struct or union.
206 Parse the body of a template, class, interface, struct or union. 203 /// $(PRE
207 DeclDefsBlock: 204 /// DeclDefsBlock :=
208 { } 205 /// { }
209 { DeclDefs } 206 /// { DeclDefs }
210 +/ 207 /// )
211 CompoundDeclaration parseDeclarationDefinitionsBody() 208 CompoundDeclaration parseDeclarationDefinitionsBody()
212 { 209 {
213 // Save attributes. 210 // Save attributes.
214 auto linkageType = this.linkageType; 211 auto linkageType = this.linkageType;
215 auto protection = this.protection; 212 auto protection = this.protection;
234 this.storageClass = storageClass; 231 this.storageClass = storageClass;
235 232
236 return decls; 233 return decls;
237 } 234 }
238 235
236 /// Parses a DeclarationDefinition.
239 Declaration parseDeclarationDefinition() 237 Declaration parseDeclarationDefinition()
240 out(decl) 238 out(decl)
241 { assert(isNodeSet(decl)); } 239 { assert(isNodeSet(decl)); }
242 body 240 body
243 { 241 {
392 assert(!isNodeSet(decl)); 390 assert(!isNodeSet(decl));
393 set(decl, begin); 391 set(decl, begin);
394 return decl; 392 return decl;
395 } 393 }
396 394
397 /++ 395 /// Parses a DeclarationsBlock.
398 DeclarationsBlock: 396 /// $(PRE
399 : DeclDefs 397 /// DeclarationsBlock :=
400 { } 398 /// : DeclDefs
401 { DeclDefs } 399 /// { }
402 DeclDef 400 /// { DeclDefs }
403 +/ 401 /// DeclDef
402 /// )
404 Declaration parseDeclarationsBlock(/+bool noColon = false+/) 403 Declaration parseDeclarationsBlock(/+bool noColon = false+/)
405 { 404 {
406 Declaration d; 405 Declaration d;
407 switch (token.kind) 406 switch (token.kind)
408 { 407 {
435 // Declaration parseDeclarationsBlockNoColon() 434 // Declaration parseDeclarationsBlockNoColon()
436 // { 435 // {
437 // return parseDeclarationsBlock(true); 436 // return parseDeclarationsBlock(true);
438 // } 437 // }
439 438
440 /++ 439 /// Parses either a VariableDeclaration or a FunctionDeclaration.
441 Parses either a VariableDeclaration or a FunctionDeclaration. 440 /// Params:
442 Params: 441 /// stc = previously parsed storage classes
443 stc = previously parsed storage classes 442 /// protection = previously parsed protection attribute
444 protection = previously parsed protection attribute 443 /// linkType = previously parsed linkage type
445 linkType = previously parsed linkage type 444 /// testAutoDeclaration = whether to check for an AutoDeclaration
446 testAutoDeclaration = whether to check for an AutoDeclaration 445 /// optionalParameterList = a hint for how to parse C-style function pointers
447 optionalParameterList = a hint for how to parse C-style function pointers
448 +/
449 Declaration parseVariableOrFunction(StorageClass stc = StorageClass.None, 446 Declaration parseVariableOrFunction(StorageClass stc = StorageClass.None,
450 Protection protection = Protection.None, 447 Protection protection = Protection.None,
451 LinkageType linkType = LinkageType.None, 448 LinkageType linkType = LinkageType.None,
452 bool testAutoDeclaration = false, 449 bool testAutoDeclaration = false,
453 bool optionalParameterList = true) 450 bool optionalParameterList = true)
550 d.setLinkageType(linkType); 547 d.setLinkageType(linkType);
551 d.setProtection(protection); 548 d.setProtection(protection);
552 return set(d, begin); 549 return set(d, begin);
553 } 550 }
554 551
552 /// Parses a variable initializer.
555 Expression parseInitializer() 553 Expression parseInitializer()
556 { 554 {
557 if (token.kind == T.Void) 555 if (token.kind == T.Void)
558 { 556 {
559 auto begin = token; 557 auto begin = token;
1370 require(T.RParen); 1368 require(T.RParen);
1371 set(type, begin); 1369 set(type, begin);
1372 return type; 1370 return type;
1373 } 1371 }
1374 1372
1375 /++ 1373 /// Parses a MixinDeclaration or MixinStatement.
1376 TemplateMixin: 1374 /// $(PRE
1377 mixin ( AssignExpression ) ; 1375 /// TemplateMixin :=
1378 mixin TemplateIdentifier ; 1376 /// mixin ( AssignExpression ) ;
1379 mixin TemplateIdentifier MixinIdentifier ; 1377 /// mixin TemplateIdentifier ;
1380 mixin TemplateIdentifier !( TemplateArguments ) ; 1378 /// mixin TemplateIdentifier MixinIdentifier ;
1381 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; 1379 /// mixin TemplateIdentifier !( TemplateArguments ) ;
1382 +/ 1380 /// mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
1381 /// )
1383 Class parseMixin(Class)() 1382 Class parseMixin(Class)()
1384 { 1383 {
1385 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement)); 1384 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement));
1386 skip(T.Mixin); 1385 skip(T.Mixin);
1387 1386
1427 statements ~= parseStatement(); 1426 statements ~= parseStatement();
1428 require(T.RBrace); 1427 require(T.RBrace);
1429 return set(statements, begin); 1428 return set(statements, begin);
1430 } 1429 }
1431 1430
1431 /// Parses a Statement.
1432 Statement parseStatement() 1432 Statement parseStatement()
1433 { 1433 {
1434 auto begin = token; 1434 auto begin = token;
1435 Statement s; 1435 Statement s;
1436 Declaration d; 1436 Declaration d;
1663 assert(s !is null); 1663 assert(s !is null);
1664 set(s, begin); 1664 set(s, begin);
1665 return s; 1665 return s;
1666 } 1666 }
1667 1667
1668 /++ 1668 /// $(PRE
1669 ScopeStatement: 1669 /// Parses a ScopeStatement.
1670 NoScopeStatement 1670 /// ScopeStatement :=
1671 +/ 1671 /// NoScopeStatement
1672 /// )
1672 Statement parseScopeStatement() 1673 Statement parseScopeStatement()
1673 { 1674 {
1674 return new ScopeStatement(parseNoScopeStatement()); 1675 return new ScopeStatement(parseNoScopeStatement());
1675 } 1676 }
1676 1677
1677 /++ 1678 /// $(PRE
1678 NoScopeStatement: 1679 /// NoScopeStatement :=
1679 NonEmptyStatement 1680 /// NonEmptyStatement
1680 BlockStatement 1681 /// BlockStatement
1681 BlockStatement: 1682 /// BlockStatement :=
1682 { } 1683 /// { }
1683 { StatementList } 1684 /// { StatementList }
1684 +/ 1685 /// )
1685 Statement parseNoScopeStatement() 1686 Statement parseNoScopeStatement()
1686 { 1687 {
1687 auto begin = token; 1688 auto begin = token;
1688 Statement s; 1689 Statement s;
1689 if (consumed(T.LBrace)) 1690 if (consumed(T.LBrace))
1703 else 1704 else
1704 s = parseStatement(); 1705 s = parseStatement();
1705 return s; 1706 return s;
1706 } 1707 }
1707 1708
1708 /++ 1709 /// $(PRE
1709 NoScopeOrEmptyStatement: 1710 /// NoScopeOrEmptyStatement :=
1710 ; 1711 /// ;
1711 NoScopeStatement 1712 /// NoScopeStatement
1712 +/ 1713 /// )
1713 Statement parseNoScopeOrEmptyStatement() 1714 Statement parseNoScopeOrEmptyStatement()
1714 { 1715 {
1715 if (consumed(T.Semicolon)) 1716 if (consumed(T.Semicolon))
1716 return set(new EmptyStatement(), this.prevToken); 1717 return set(new EmptyStatement(), this.prevToken);
1717 else 1718 else
2230 2231
2231 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2232 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2232 | Assembler parsing methods | 2233 | Assembler parsing methods |
2233 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 2234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2234 2235
2236 /// Parses an AsmBlockStatement.
2235 Statement parseAsmBlockStatement() 2237 Statement parseAsmBlockStatement()
2236 { 2238 {
2237 skip(T.Asm); 2239 skip(T.Asm);
2238 require(T.LBrace); 2240 require(T.LBrace);
2239 auto ss = new CompoundStatement; 2241 auto ss = new CompoundStatement;
2670 2672
2671 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2673 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2672 | Expression parsing methods | 2674 | Expression parsing methods |
2673 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 2675 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
2674 2676
2677 /// Parses an Expression.
2675 Expression parseExpression() 2678 Expression parseExpression()
2676 { 2679 {
2677 alias parseAssignExpression parseNext; 2680 alias parseAssignExpression parseNext;
2678 auto begin = token; 2681 auto begin = token;
2679 auto e = parseNext(); 2682 auto e = parseNext();
3077 assert(e !is null); 3080 assert(e !is null);
3078 set(e, begin); 3081 set(e, begin);
3079 return e; 3082 return e;
3080 } 3083 }
3081 3084
3082 /++ 3085 /// $(PRE
3083 IdentifierExpression: 3086 /// IdentifierExpression :=
3084 Identifier 3087 /// Identifier
3085 TemplateInstance 3088 /// TemplateInstance
3086 TemplateInstance: 3089 /// TemplateInstance :=
3087 Identifier !( TemplateArguments ) 3090 /// Identifier !( TemplateArguments )
3088 +/ 3091 /// )
3089 Expression parseIdentifierExpression() 3092 Expression parseIdentifierExpression()
3090 { 3093 {
3091 auto begin = token; 3094 auto begin = token;
3092 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); 3095 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
3093 Expression e; 3096 Expression e;
3404 ctorArguments = parseArguments(); 3407 ctorArguments = parseArguments();
3405 3408
3406 return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin); 3409 return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin);
3407 } 3410 }
3408 3411
3412 /// Parses a Type.
3409 Type parseType() 3413 Type parseType()
3410 { 3414 {
3411 return parseBasicType2(parseBasicType()); 3415 return parseBasicType2(parseBasicType());
3412 } 3416 }
3413 3417
3513 set(t, begin); 3517 set(t, begin);
3514 } 3518 }
3515 assert(0); 3519 assert(0);
3516 } 3520 }
3517 3521
3522 /// Returns true if the token after the closing parenthesis
3523 /// is of kind tok.
3518 bool tokenAfterParenIs(TOK tok) 3524 bool tokenAfterParenIs(TOK tok)
3519 { 3525 {
3520 // We count nested parentheses tokens because template types 3526 // We count nested parentheses tokens because template types
3521 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y) 3527 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y)
3522 assert(token.kind == T.LParen); 3528 assert(token.kind == T.LParen);
3546 } 3552 }
3547 } 3553 }
3548 return next.kind == tok; 3554 return next.kind == tok;
3549 } 3555 }
3550 3556
3551 /// Parse the C-style array types after the declarator. 3557 /// Parse the array types after the declarator (C-style.) E.g.: int a[]
3552 Type parseDeclaratorSuffix(Type lhsType) 3558 Type parseDeclaratorSuffix(Type lhsType)
3553 { 3559 {
3554 // The Type chain should be as follows: 3560 // The Type chain should be as follows:
3555 // int[3]* Identifier [][32] 3561 // int[3]* Identifier [][32]
3556 // <- <- -> -. 3562 // <- <- -> -.
3670 error(token, MSG.ExpectedDeclaratorIdentifier, token.srcText); 3676 error(token, MSG.ExpectedDeclaratorIdentifier, token.srcText);
3671 3677
3672 return t; 3678 return t;
3673 } 3679 }
3674 3680
3675 /++ 3681 /// Parses a list of AssignExpressions.
3676 Parse a list of AssignExpressions. 3682 /// $(PRE
3677 ExpressionList: 3683 /// ExpressionList :=
3678 AssignExpression 3684 /// AssignExpression
3679 AssignExpression , ExpressionList 3685 /// AssignExpression , ExpressionList
3680 +/ 3686 /// )
3681 Expression[] parseExpressionList() 3687 Expression[] parseExpressionList()
3682 { 3688 {
3683 Expression[] expressions; 3689 Expression[] expressions;
3684 do 3690 do
3685 expressions ~= parseAssignExpression(); 3691 expressions ~= parseAssignExpression();
3686 while(consumed(T.Comma)) 3692 while(consumed(T.Comma))
3687 return expressions; 3693 return expressions;
3688 } 3694 }
3689 3695
3690 /++ 3696 /// Parses a list of Arguments.
3691 Arguments: 3697 /// $(PRE
3692 ( ) 3698 /// Arguments :=
3693 ( ExpressionList ) 3699 /// ( )
3694 +/ 3700 /// ( ExpressionList )
3701 /// )
3695 Expression[] parseArguments() 3702 Expression[] parseArguments()
3696 { 3703 {
3697 skip(T.LParen); 3704 skip(T.LParen);
3698 Expression[] args; 3705 Expression[] args;
3699 if (token.kind != T.RParen) 3706 if (token.kind != T.RParen)
3700 args = parseExpressionList(); 3707 args = parseExpressionList();
3701 require(T.RParen); 3708 require(T.RParen);
3702 return args; 3709 return args;
3703 } 3710 }
3704 3711
3712 /// Parses a ParameterList.
3705 Parameters parseParameterList() 3713 Parameters parseParameterList()
3706 out(params) 3714 out(params)
3707 { 3715 {
3708 if (params.length > 1) 3716 if (params.length > 1)
3709 foreach (param; params.items[0..$-1]) 3717 foreach (param; params.items[0..$-1])
3892 error(token, MSG.ExpectedTemplateParameters); 3900 error(token, MSG.ExpectedTemplateParameters);
3893 return set(tparams, begin); 3901 return set(tparams, begin);
3894 } 3902 }
3895 } // version(D2) 3903 } // version(D2)
3896 3904
3905 /// Parses template parameters.
3897 void parseTemplateParameterList_(TemplateParameters tparams) 3906 void parseTemplateParameterList_(TemplateParameters tparams)
3898 { 3907 {
3899 do 3908 do
3900 { 3909 {
3901 auto paramBegin = token; 3910 auto paramBegin = token;
3979 tparams ~= set(tp, paramBegin); 3988 tparams ~= set(tp, paramBegin);
3980 3989
3981 } while (consumed(T.Comma)) 3990 } while (consumed(T.Comma))
3982 } 3991 }
3983 3992
3984 void expected(TOK tok) 3993 alias require expected;
3985 { 3994
3986 if (token.kind != tok) 3995 /// Requires a token of kind tok.
3987 error(MID.ExpectedButFound, Token.toString(tok), token.srcText);
3988 }
3989
3990 void require(TOK tok) 3996 void require(TOK tok)
3991 { 3997 {
3992 if (token.kind == tok) 3998 if (token.kind == tok)
3993 nT(); 3999 nT();
3994 else 4000 else
3995 error(MID.ExpectedButFound, Token.toString(tok), token.srcText); 4001 error(MID.ExpectedButFound, Token.toString(tok), token.srcText);
3996 } 4002 }
3997 4003
4004 /// Requires the next token to be of kind tok.
3998 void requireNext(TOK tok) 4005 void requireNext(TOK tok)
3999 { 4006 {
4000 nT(); 4007 nT();
4001 require(tok); 4008 require(tok);
4002 } 4009 }
4003 4010
4011 /// Optionally parses an identifier.
4012 /// Returns: null or the identifier.
4004 Identifier* optionalIdentifier() 4013 Identifier* optionalIdentifier()
4005 { 4014 {
4006 Identifier* id; 4015 Identifier* id;
4007 if (token.kind == T.Identifier) 4016 if (token.kind == T.Identifier)
4008 (id = token.ident), skip(T.Identifier); 4017 (id = token.ident), skip(T.Identifier);
4017 else 4026 else
4018 error(MID.ExpectedButFound, "Identifier", token.srcText); 4027 error(MID.ExpectedButFound, "Identifier", token.srcText);
4019 return id; 4028 return id;
4020 } 4029 }
4021 4030
4031 /// Reports an error if the current token is not an identifier.
4022 /// Params: 4032 /// Params:
4023 /// errorMsg = an error that has no message ID yet. 4033 /// errorMsg = the error message to be used.
4034 /// Returns: null or the identifier.
4024 Identifier* requireIdentifier(char[] errorMsg) 4035 Identifier* requireIdentifier(char[] errorMsg)
4025 { 4036 {
4026 Identifier* id; 4037 Identifier* id;
4027 if (token.kind == T.Identifier) 4038 if (token.kind == T.Identifier)
4028 (id = token.ident), skip(T.Identifier); 4039 (id = token.ident), skip(T.Identifier);
4029 else 4040 else
4030 error(token, errorMsg, token.srcText); 4041 error(token, errorMsg, token.srcText);
4031 return id; 4042 return id;
4032 } 4043 }
4033 4044
4045 /// Reports an error if the current token is not an identifier.
4046 /// Params:
4047 /// mid = the error message ID to be used.
4048 /// Returns: null or the identifier.
4034 Identifier* requireIdentifier(MID mid) 4049 Identifier* requireIdentifier(MID mid)
4035 { 4050 {
4036 Identifier* id; 4051 Identifier* id;
4037 if (token.kind == T.Identifier) 4052 if (token.kind == T.Identifier)
4038 (id = token.ident), skip(T.Identifier); 4053 (id = token.ident), skip(T.Identifier);
4039 else 4054 else
4040 error(mid, token.srcText); 4055 error(mid, token.srcText);
4041 return id; 4056 return id;
4042 } 4057 }
4043 4058
4059 /// Reports an error if the current token is not an identifier.
4060 /// Returns: null or the token.
4044 Token* requireId() 4061 Token* requireId()
4045 {
4046 if (token.kind == T.Identifier)
4047 {
4048 auto id = token;
4049 nT();
4050 return id;
4051 }
4052 else
4053 error(MID.ExpectedButFound, "Identifier", token.srcText);
4054 return null;
4055 }
4056
4057 Token* requireIdToken(char[] errorMsg)
4058 { 4062 {
4059 Token* idtok; 4063 Token* idtok;
4060 if (token.kind == T.Identifier) 4064 if (token.kind == T.Identifier)
4061 (idtok = token), skip(T.Identifier); 4065 (idtok = token), skip(T.Identifier);
4062 else 4066 else
4067 error(MID.ExpectedButFound, "Identifier", token.srcText);
4068 return idtok;
4069 }
4070
4071 Token* requireIdToken(char[] errorMsg)
4072 {
4073 Token* idtok;
4074 if (token.kind == T.Identifier)
4075 (idtok = token), skip(T.Identifier);
4076 else
4077 {
4063 error(token, errorMsg, token.srcText); 4078 error(token, errorMsg, token.srcText);
4079 idtok = lexer.insertEmptyTokenBefore(token);
4080 this.prevToken = idtok;
4081 }
4064 return idtok; 4082 return idtok;
4065 } 4083 }
4066 4084
4067 /// Returns true if the string str has an invalid UTF-8 sequence. 4085 /// Returns true if the string str has an invalid UTF-8 sequence.
4068 bool checkString(Token* begin, string str) 4086 bool checkString(Token* begin, string str)
4071 if (utf8Seq.length) 4089 if (utf8Seq.length)
4072 error(begin, MSG.InvalidUTF8SequenceInString, utf8Seq); 4090 error(begin, MSG.InvalidUTF8SequenceInString, utf8Seq);
4073 return utf8Seq.length != 0; 4091 return utf8Seq.length != 0;
4074 } 4092 }
4075 4093
4076 /// Reports an error that has no message ID yet. 4094 /// Forwards error parameters.
4077 void error(Token* token, char[] formatMsg, ...) 4095 void error(Token* token, char[] formatMsg, ...)
4078 { 4096 {
4079 error_(token, formatMsg, _arguments, _argptr); 4097 error_(token, formatMsg, _arguments, _argptr);
4080 } 4098 }
4081 4099
4100 /// ditto
4082 void error(MID mid, ...) 4101 void error(MID mid, ...)
4083 { 4102 {
4084 error_(this.token, GetMsg(mid), _arguments, _argptr); 4103 error_(this.token, GetMsg(mid), _arguments, _argptr);
4085 } 4104 }
4086 4105
4106 /// Creates an error report and appends it to a list.
4107 /// Params:
4108 /// token = used to get the location of where the error is.
4109 /// formatMsg = the compiler error message.
4087 void error_(Token* token, char[] formatMsg, TypeInfo[] _arguments, Arg _argptr) 4110 void error_(Token* token, char[] formatMsg, TypeInfo[] _arguments, Arg _argptr)
4088 { 4111 {
4089 if (trying) 4112 if (trying)
4090 { 4113 {
4091 ++errorCount; 4114 ++errorCount;