Mercurial > projects > dil
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; |