| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library fasta.parser.parser; | 5 library fasta.parser.parser; |
| 6 | 6 |
| 7 import '../fasta_codes.dart' show Code, Message, Template; | 7 import '../fasta_codes.dart' show Code, Message, Template; |
| 8 | 8 |
| 9 import '../fasta_codes.dart' as fasta; | 9 import '../fasta_codes.dart' as fasta; |
| 10 | 10 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 count++; | 253 count++; |
| 254 } | 254 } |
| 255 listener.endCompilationUnit(count, token); | 255 listener.endCompilationUnit(count, token); |
| 256 // Clear fields that could lead to memory leak. | 256 // Clear fields that could lead to memory leak. |
| 257 firstToken = null; | 257 firstToken = null; |
| 258 cachedRewriter = null; | 258 cachedRewriter = null; |
| 259 return token; | 259 return token; |
| 260 } | 260 } |
| 261 | 261 |
| 262 Token parseTopLevelDeclaration(Token token) { | 262 Token parseTopLevelDeclaration(Token token) { |
| 263 token = _parseTopLevelDeclaration(token); | 263 token = parseTopLevelDeclarationImpl(token); |
| 264 listener.endTopLevelDeclaration(token); | 264 listener.endTopLevelDeclaration(token); |
| 265 return token; | 265 return token; |
| 266 } | 266 } |
| 267 | 267 |
| 268 Token _parseTopLevelDeclaration(Token token) { | 268 Token parseTopLevelDeclarationImpl(Token token) { |
| 269 if (identical(token.type, TokenType.SCRIPT_TAG)) { | 269 if (identical(token.type, TokenType.SCRIPT_TAG)) { |
| 270 return parseScript(token); | 270 return parseScript(token); |
| 271 } | 271 } |
| 272 token = parseMetadataStar(token); | 272 token = parseMetadataStar(token); |
| 273 String value = token.stringValue; | 273 if (token.isTopLevelKeyword) { |
| 274 if (identical(value, 'abstract')) { | 274 return parseTopLevelKeywordDeclaration(null, token); |
| 275 if (optional('class', token.next)) { | 275 } |
| 276 return parseClassOrNamedMixinApplication(token); | 276 Token start = token; |
| 277 // Skip modifiers to find a top level keyword or identifier |
| 278 while (token.isModifier) { |
| 279 token = token.next; |
| 280 } |
| 281 if (token.isTopLevelKeyword) { |
| 282 Token abstractToken; |
| 283 Token modifierToken = start; |
| 284 while (modifierToken != token) { |
| 285 if (optional('abstract', modifierToken) && |
| 286 optional('class', token) && |
| 287 abstractToken == null) { |
| 288 abstractToken = modifierToken; |
| 289 } else { |
| 290 // TODO(danrubel): Report more specific recoverable error message |
| 291 // for `const class` to better help the user. |
| 292 // See ParserErrorCode CONST_CLASS |
| 293 |
| 294 // Report an error for each extraneous modifier |
| 295 reportRecoverableErrorWithToken( |
| 296 modifierToken, fasta.templateExtraneousModifier); |
| 297 } |
| 298 modifierToken = modifierToken.next; |
| 277 } | 299 } |
| 278 reportRecoverableErrorWithToken(token, fasta.templateExtraneousModifier); | 300 return parseTopLevelKeywordDeclaration(abstractToken, token); |
| 279 token = token.next; | 301 } else if (token.isIdentifier || token.keyword != null) { |
| 280 value = token.stringValue; | 302 // TODO(danrubel): improve parseTopLevelMember |
| 303 // so that we don't parse modifiers twice. |
| 304 return parseTopLevelMember(start); |
| 305 } else if (start != token) { |
| 306 // Handle the edge case where a modifier is being used as an identifier |
| 307 return parseTopLevelMember(start); |
| 281 } | 308 } |
| 309 // Ignore any preceding modifiers and just report the unexpected token |
| 310 reportRecoverableErrorWithToken(token, fasta.templateExpectedDeclaration); |
| 311 listener.handleInvalidTopLevelDeclaration(token); |
| 312 return token.next; |
| 313 } |
| 314 |
| 315 Token parseTopLevelKeywordDeclaration(Token abstractToken, Token token) { |
| 316 final String value = token.stringValue; |
| 282 if (identical(value, 'class')) { | 317 if (identical(value, 'class')) { |
| 283 return parseClassOrNamedMixinApplication(token); | 318 return parseClassOrNamedMixinApplication(abstractToken, token); |
| 284 } else if (identical(value, 'enum')) { | 319 } else if (identical(value, 'enum')) { |
| 285 return parseEnum(token); | 320 return parseEnum(token); |
| 286 } else if (identical(value, 'typedef') && | 321 } else if (identical(value, 'typedef')) { |
| 287 (token.next.isIdentifier || optional("void", token.next))) { | 322 Token next = token.next; |
| 288 return parseTypedef(token); | 323 if (next.isIdentifier || optional("void", next)) { |
| 324 return parseTypedef(token); |
| 325 } else { |
| 326 return parseTopLevelMember(token); |
| 327 } |
| 289 } else if (identical(value, 'library')) { | 328 } else if (identical(value, 'library')) { |
| 290 return parseLibraryName(token); | 329 return parseLibraryName(token); |
| 291 } else if (identical(value, 'import')) { | 330 } else if (identical(value, 'import')) { |
| 292 return parseImport(token); | 331 return parseImport(token); |
| 293 } else if (identical(value, 'export')) { | 332 } else if (identical(value, 'export')) { |
| 294 return parseExport(token); | 333 return parseExport(token); |
| 295 } else if (identical(value, 'part')) { | 334 } else if (identical(value, 'part')) { |
| 296 return parsePartOrPartOf(token); | 335 return parsePartOrPartOf(token); |
| 297 } else if (token.type == TokenType.IDENTIFIER || token.keyword != null) { | |
| 298 return parseTopLevelMember(token); | |
| 299 } else { | |
| 300 reportRecoverableErrorWithToken(token, fasta.templateExpectedDeclaration); | |
| 301 listener.handleInvalidTopLevelDeclaration(token); | |
| 302 return token.next; | |
| 303 } | 336 } |
| 337 |
| 338 throw "Internal error: Unhandled top level keyword '$value'."; |
| 304 } | 339 } |
| 305 | 340 |
| 306 /// library qualified ';' | 341 /// library qualified ';' |
| 307 Token parseLibraryName(Token token) { | 342 Token parseLibraryName(Token token) { |
| 308 Token libraryKeyword = token; | 343 Token libraryKeyword = token; |
| 309 listener.beginLibraryName(libraryKeyword); | 344 listener.beginLibraryName(libraryKeyword); |
| 310 assert(optional('library', token)); | 345 assert(optional('library', token)); |
| 311 token = parseQualified(token.next, IdentifierContext.libraryName, | 346 token = parseQualified(token.next, IdentifierContext.libraryName, |
| 312 IdentifierContext.libraryNameContinuation); | 347 IdentifierContext.libraryNameContinuation); |
| 313 Token semicolon = token; | 348 Token semicolon = token; |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 token = parseIdentifier(token, IdentifierContext.enumValueDeclaration); | 855 token = parseIdentifier(token, IdentifierContext.enumValueDeclaration); |
| 821 count++; | 856 count++; |
| 822 } | 857 } |
| 823 } | 858 } |
| 824 Token endBrace = token; | 859 Token endBrace = token; |
| 825 token = expect('}', token); | 860 token = expect('}', token); |
| 826 listener.endEnum(enumKeyword, endBrace, count); | 861 listener.endEnum(enumKeyword, endBrace, count); |
| 827 return token; | 862 return token; |
| 828 } | 863 } |
| 829 | 864 |
| 830 Token parseClassOrNamedMixinApplication(Token token) { | 865 Token parseClassOrNamedMixinApplication(Token abstractToken, Token token) { |
| 831 listener.beginClassOrNamedMixinApplication(token); | 866 listener.beginClassOrNamedMixinApplication(token); |
| 832 Token begin = token; | 867 Token begin = abstractToken ?? token; |
| 833 if (optional('abstract', token)) { | 868 if (abstractToken != null) { |
| 834 token = parseModifier(token); | 869 token = parseModifier(abstractToken); |
| 835 listener.handleModifiers(1); | 870 listener.handleModifiers(1); |
| 836 } else { | 871 } else { |
| 837 listener.handleModifiers(0); | 872 listener.handleModifiers(0); |
| 838 } | 873 } |
| 839 Token classKeyword = token; | 874 Token classKeyword = token; |
| 840 token = expect("class", token); | 875 token = expect("class", token); |
| 841 Token name = token; | 876 Token name = token; |
| 842 token = | 877 token = |
| 843 parseIdentifier(name, IdentifierContext.classOrNamedMixinDeclaration); | 878 parseIdentifier(name, IdentifierContext.classOrNamedMixinDeclaration); |
| 844 token = parseTypeVariablesOpt(token); | 879 token = parseTypeVariablesOpt(token); |
| (...skipping 3303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4148 } | 4183 } |
| 4149 | 4184 |
| 4150 Token reportUnexpectedToken(Token token) { | 4185 Token reportUnexpectedToken(Token token) { |
| 4151 return reportUnrecoverableErrorWithToken( | 4186 return reportUnrecoverableErrorWithToken( |
| 4152 token, fasta.templateUnexpectedToken); | 4187 token, fasta.templateUnexpectedToken); |
| 4153 } | 4188 } |
| 4154 } | 4189 } |
| 4155 | 4190 |
| 4156 // TODO(ahe): Remove when analyzer supports generalized function syntax. | 4191 // TODO(ahe): Remove when analyzer supports generalized function syntax. |
| 4157 typedef _MessageWithArgument<T> = Message Function(T); | 4192 typedef _MessageWithArgument<T> = Message Function(T); |
| OLD | NEW |