Chromium Code Reviews| 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 dart2js.parser; | 5 library dart2js.parser; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../tokens/keyword.dart' show Keyword; | 8 import '../tokens/keyword.dart' show Keyword; |
| 9 import '../tokens/precedence.dart' show PrecedenceInfo; | 9 import '../tokens/precedence.dart' show PrecedenceInfo; |
| 10 import '../tokens/precedence_constants.dart' | 10 import '../tokens/precedence_constants.dart' |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 period = token; | 355 period = token; |
| 356 token = parseIdentifier(token.next); | 356 token = parseIdentifier(token.next); |
| 357 } | 357 } |
| 358 token = parseArgumentsOpt(token); | 358 token = parseArgumentsOpt(token); |
| 359 listener.endMetadata(atToken, period, token); | 359 listener.endMetadata(atToken, period, token); |
| 360 return token; | 360 return token; |
| 361 } | 361 } |
| 362 | 362 |
| 363 Token parseTypedef(Token token) { | 363 Token parseTypedef(Token token) { |
| 364 Token typedefKeyword = token; | 364 Token typedefKeyword = token; |
| 365 listener.beginFunctionTypeAlias(token); | 365 listener.beginTypedef(token); |
| 366 token = parseReturnTypeOpt(token.next); | 366 Token equals; |
| 367 token = parseIdentifier(token); | 367 if (optional('=', peekAfterType(token.next))) { |
| 368 token = parseTypeVariablesOpt(token); | 368 token = parseIdentifier(token.next); |
| 369 token = parseFormalParameters(token); | 369 token = parseTypeVariablesOpt(token); |
| 370 listener.endFunctionTypeAlias(typedefKeyword, token); | 370 equals = expect('=', token); |
| 371 token = parseType(equals); | |
| 372 } else { | |
| 373 token = parseReturnTypeOpt(token.next); | |
| 374 token = parseIdentifier(token); | |
| 375 token = parseTypeVariablesOpt(token); | |
| 376 token = parseFormalParameters(token); | |
| 377 } | |
| 378 listener.endTypedef(typedefKeyword, equals, token); | |
| 371 return expect(';', token); | 379 return expect(';', token); |
| 372 } | 380 } |
| 373 | 381 |
| 374 Token parseMixinApplication(Token token) { | 382 Token parseMixinApplication(Token token) { |
| 375 listener.beginMixinApplication(token); | 383 listener.beginMixinApplication(token); |
| 376 token = parseType(token); | 384 token = parseType(token); |
| 377 token = expect('with', token); | 385 token = expect('with', token); |
| 378 token = parseTypeList(token); | 386 token = parseTypeList(token); |
| 379 listener.endMixinApplication(); | 387 listener.endMixinApplication(); |
| 380 return token; | 388 return token; |
| 381 } | 389 } |
| 382 | 390 |
| 383 Token parseReturnTypeOpt(Token token) { | 391 Token parseReturnTypeOpt(Token token, {bool allowFunctionType: true}) { |
| 384 if (identical(token.stringValue, 'void')) { | 392 if (identical(token.stringValue, 'void')) { |
| 385 listener.handleVoidKeyword(token); | 393 listener.handleVoidKeyword(token); |
| 386 return token.next; | 394 return token.next; |
| 395 } else if (!allowFunctionType && isGeneralizedFunctionType(token)) { | |
| 396 listener.handleNoType(token); | |
| 397 return token; | |
| 387 } else { | 398 } else { |
| 388 return parseTypeOpt(token); | 399 return parseTypeOpt(token); |
| 389 } | 400 } |
| 390 } | 401 } |
| 391 | 402 |
| 392 Token parseFormalParametersOpt(Token token) { | 403 Token parseFormalParametersOpt(Token token) { |
| 393 if (optional('(', token)) { | 404 if (optional('(', token)) { |
| 394 return parseFormalParameters(token); | 405 return parseFormalParameters(token); |
| 395 } else { | 406 } else { |
| 396 listener.handleNoFormalParameters(token); | 407 listener.handleNoFormalParameters(token); |
| 397 return token; | 408 return token; |
| 398 } | 409 } |
| 399 } | 410 } |
| 400 | 411 |
| 401 Token parseFormalParameters(Token token) { | 412 /// Parses the formal parameter list of a function. |
| 413 /// | |
| 414 /// If [inFunctionType] is true, then the names may be omitted (except for | |
| 415 /// named arguments). If it is false, then the types may be omitted. | |
| 416 Token parseFormalParameters(Token token, {bool inFunctionType: false}) { | |
| 402 Token begin = token; | 417 Token begin = token; |
| 403 listener.beginFormalParameters(begin); | 418 listener.beginFormalParameters(begin); |
| 404 expect('(', token); | 419 expect('(', token); |
| 405 int parameterCount = 0; | 420 int parameterCount = 0; |
| 406 do { | 421 do { |
| 407 token = token.next; | 422 token = token.next; |
| 408 if (optional(')', token)) { | 423 if (optional(')', token)) { |
| 409 break; | 424 break; |
| 410 } | 425 } |
| 411 ++parameterCount; | 426 ++parameterCount; |
| 412 String value = token.stringValue; | 427 String value = token.stringValue; |
| 413 if (identical(value, '[')) { | 428 if (identical(value, '[')) { |
| 414 token = parseOptionalFormalParameters(token, false); | 429 token = parseOptionalFormalParameters( |
| 430 token, false, inFunctionType: inFunctionType); | |
| 415 break; | 431 break; |
| 416 } else if (identical(value, '{')) { | 432 } else if (identical(value, '{')) { |
| 417 token = parseOptionalFormalParameters(token, true); | 433 token = parseOptionalFormalParameters( |
| 434 token, true, inFunctionType: inFunctionType); | |
| 418 break; | 435 break; |
| 419 } | 436 } |
| 420 token = parseFormalParameter(token, FormalParameterType.REQUIRED); | 437 token = parseFormalParameter(token, FormalParameterType.REQUIRED, |
| 438 inFunctionType: inFunctionType); | |
| 421 } while (optional(',', token)); | 439 } while (optional(',', token)); |
| 422 listener.endFormalParameters(parameterCount, begin, token); | 440 listener.endFormalParameters(parameterCount, begin, token); |
| 423 return expect(')', token); | 441 return expect(')', token); |
| 424 } | 442 } |
| 425 | 443 |
| 426 Token parseFormalParameter(Token token, FormalParameterType type) { | 444 Token parseFormalParameter(Token token, FormalParameterType type, |
| 445 {bool inFunctionType}) { | |
| 427 token = parseMetadataStar(token, forParameter: true); | 446 token = parseMetadataStar(token, forParameter: true); |
| 428 listener.beginFormalParameter(token); | 447 listener.beginFormalParameter(token); |
| 429 token = parseModifiers(token); | 448 token = parseModifiers(token); |
| 430 // TODO(ahe): Validate that there are formal parameters if void. | 449 bool isNamedParameter = type == FormalParameterType.NAMED; |
| 431 token = parseReturnTypeOpt(token); | 450 |
| 432 Token thisKeyword = null; | 451 Token thisKeyword = null; |
| 433 if (optional('this', token)) { | 452 if (inFunctionType && isNamedParameter) { |
| 434 thisKeyword = token; | 453 token = parseTypeOpt(token); |
| 435 // TODO(ahe): Validate field initializers are only used in | 454 token = parseIdentifier(token); |
| 436 // constructors, and not for function-typed arguments. | 455 } else if (inFunctionType) { |
| 437 token = expect('.', token.next); | 456 token = parseType(token); |
| 457 if (token.isIdentifier()) { | |
| 458 token = parseIdentifier(token); | |
| 459 } else { | |
| 460 listener.handleNoName(token); | |
| 461 } | |
| 462 } else { | |
| 463 // TODO(ahe): Validate that there are formal parameters if void. | |
| 464 token = parseReturnTypeOpt(token); | |
| 465 if (optional('this', token)) { | |
| 466 thisKeyword = token; | |
| 467 // TODO(ahe): Validate field initializers are only used in | |
| 468 // constructors, and not for function-typed arguments. | |
| 469 token = expect('.', token.next); | |
| 470 } | |
| 471 token = parseIdentifier(token); | |
| 438 } | 472 } |
| 439 token = parseIdentifier(token); | 473 |
| 440 if (optional('(', token)) { | 474 // Generalized function types don't allow inline function types. |
| 441 listener.handleNoTypeVariables(token); | 475 // The following isn't allowed: |
| 442 token = parseFormalParameters(token); | 476 // int Function(int bar(String x)). |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:57
should we report an error instead in that case?
(
floitsch
2016/12/30 14:55:47
In some sense that's what's happening. Just automa
| |
| 443 listener.handleFunctionTypedFormalParameter(token); | 477 if (!inFunctionType) { |
| 444 } else if (optional('<', token)) { | 478 if (optional('(', token)) { |
| 445 token = parseTypeVariablesOpt(token); | 479 listener.handleNoTypeVariables(token); |
| 446 token = parseFormalParameters(token); | 480 token = parseFormalParameters(token); |
| 447 listener.handleFunctionTypedFormalParameter(token); | 481 listener.handleFunctionTypedFormalParameter(token); |
| 482 } else if (optional('<', token)) { | |
| 483 token = parseTypeVariablesOpt(token); | |
| 484 token = parseFormalParameters(token); | |
| 485 listener.handleFunctionTypedFormalParameter(token); | |
| 486 } | |
| 448 } | 487 } |
| 449 String value = token.stringValue; | 488 String value = token.stringValue; |
| 450 if ((identical('=', value)) || (identical(':', value))) { | 489 if ((identical('=', value)) || (identical(':', value))) { |
| 451 // TODO(ahe): Validate that these are only used for optional parameters. | 490 // TODO(ahe): Validate that these are only used for optional parameters. |
| 452 Token equal = token; | 491 Token equal = token; |
| 453 token = parseExpression(token.next); | 492 token = parseExpression(token.next); |
| 454 listener.handleValuedFormalParameter(equal, token); | 493 listener.handleValuedFormalParameter(equal, token); |
| 455 if (type.isRequired) { | 494 if (type.isRequired) { |
| 456 listener.reportError( | 495 listener.reportError( |
| 457 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); | 496 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); |
| 458 } else if (type.isPositional && identical(':', value)) { | 497 } else if (type.isPositional && identical(':', value)) { |
| 459 listener.reportError( | 498 listener.reportError( |
| 460 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); | 499 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); |
| 461 } | 500 } |
| 462 } | 501 } |
| 463 listener.endFormalParameter(thisKeyword); | 502 listener.endFormalParameter(thisKeyword); |
| 464 return token; | 503 return token; |
| 465 } | 504 } |
| 466 | 505 |
| 467 Token parseOptionalFormalParameters(Token token, bool isNamed) { | 506 Token parseOptionalFormalParameters(Token token, bool isNamed, |
| 507 {bool inFunctionType}) { | |
| 468 Token begin = token; | 508 Token begin = token; |
| 469 listener.beginOptionalFormalParameters(begin); | 509 listener.beginOptionalFormalParameters(begin); |
| 470 assert((isNamed && optional('{', token)) || optional('[', token)); | 510 assert((isNamed && optional('{', token)) || optional('[', token)); |
| 471 int parameterCount = 0; | 511 int parameterCount = 0; |
| 472 do { | 512 do { |
| 473 token = token.next; | 513 token = token.next; |
| 474 if (isNamed && optional('}', token)) { | 514 if (isNamed && optional('}', token)) { |
| 475 break; | 515 break; |
| 476 } else if (!isNamed && optional(']', token)) { | 516 } else if (!isNamed && optional(']', token)) { |
| 477 break; | 517 break; |
| 478 } | 518 } |
| 479 var type = | 519 var type = |
| 480 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 520 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
| 481 token = parseFormalParameter(token, type); | 521 token = |
| 522 parseFormalParameter(token, type, inFunctionType: inFunctionType); | |
| 482 ++parameterCount; | 523 ++parameterCount; |
| 483 } while (optional(',', token)); | 524 } while (optional(',', token)); |
| 484 if (parameterCount == 0) { | 525 if (parameterCount == 0) { |
| 485 listener.reportError( | 526 listener.reportError( |
| 486 token, | 527 token, |
| 487 isNamed | 528 isNamed |
| 488 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST | 529 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST |
| 489 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST); | 530 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST); |
| 490 } | 531 } |
| 491 listener.endOptionalFormalParameters(parameterCount, begin, token); | 532 listener.endOptionalFormalParameters(parameterCount, begin, token); |
| 492 if (isNamed) { | 533 if (isNamed) { |
| 493 return expect('}', token); | 534 return expect('}', token); |
| 494 } else { | 535 } else { |
| 495 return expect(']', token); | 536 return expect(']', token); |
| 496 } | 537 } |
| 497 } | 538 } |
| 498 | 539 |
| 499 Token parseTypeOpt(Token token) { | 540 Token parseTypeOpt(Token token) { |
| 541 if (isGeneralizedFunctionType(token)) { | |
| 542 // Function type without return type. | |
| 543 return parseType(token); | |
| 544 } | |
| 500 Token peek = peekAfterIfType(token); | 545 Token peek = peekAfterIfType(token); |
| 501 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { | 546 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { |
| 502 return parseType(token); | 547 return parseType(token); |
| 503 } | 548 } |
| 504 listener.handleNoType(token); | 549 listener.handleNoType(token); |
| 505 return token; | 550 return token; |
| 506 } | 551 } |
| 507 | 552 |
| 508 bool isValidTypeReference(Token token) { | 553 bool isValidTypeReference(Token token) { |
| 509 final kind = token.kind; | 554 final kind = token.kind; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 value2 == stringValue || | 838 value2 == stringValue || |
| 794 value3 == stringValue || | 839 value3 == stringValue || |
| 795 value4 == stringValue; | 840 value4 == stringValue; |
| 796 } | 841 } |
| 797 | 842 |
| 798 bool notEofOrValue(String value, Token token) { | 843 bool notEofOrValue(String value, Token token) { |
| 799 return !identical(token.kind, EOF_TOKEN) && | 844 return !identical(token.kind, EOF_TOKEN) && |
| 800 !identical(value, token.stringValue); | 845 !identical(value, token.stringValue); |
| 801 } | 846 } |
| 802 | 847 |
| 848 bool isGeneralizedFunctionType(Token token) { | |
| 849 // TODO(floitsch): don't use string comparison, but the keyword-state | |
| 850 // table is currently not set up to deal with upper-case characters. | |
| 851 return (optional('<', token.next) || optional('(', token.next)) && | |
| 852 token.value == "Function"; | |
| 853 } | |
| 854 | |
| 803 Token parseType(Token token) { | 855 Token parseType(Token token) { |
| 804 Token begin = token; | 856 Token begin = token; |
| 805 if (isValidTypeReference(token)) { | 857 if (isGeneralizedFunctionType(token)) { |
| 806 token = parseIdentifier(token); | 858 // A function type without return type. |
| 807 token = parseQualifiedRestOpt(token); | 859 // Push the non-existing return type first. The loop below will |
| 860 // generate the full type. | |
| 861 listener.handleNoType(token); | |
| 808 } else { | 862 } else { |
| 809 token = listener.expectedType(token); | 863 if (isValidTypeReference(token)) { |
| 864 if (isGeneralizedFunctionType(token)) { | |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:58
is this branch ever executed?
floitsch
2016/12/30 14:55:47
Nope. that was old code that I didn't clean up.
Go
| |
| 865 // A function type without return type. | |
| 866 return parseFunctionType(token); | |
| 867 } else { | |
| 868 token = parseIdentifier(token); | |
| 869 token = parseQualifiedRestOpt(token); | |
| 870 } | |
| 871 } else { | |
| 872 token = listener.expectedType(token); | |
| 873 } | |
| 874 token = parseTypeArgumentsOpt(token); | |
| 875 listener.endType(begin, token); | |
| 810 } | 876 } |
| 811 token = parseTypeArgumentsOpt(token); | 877 |
| 812 listener.endType(begin, token); | 878 // While we see a `Function(` treat the pushed type as return type. |
| 879 // For example: `int Function() Function(int) Function(String x)`. | |
| 880 while (isGeneralizedFunctionType(token)) { | |
| 881 token = parseFunctionType(token); | |
| 882 } | |
| 813 return token; | 883 return token; |
| 814 } | 884 } |
| 815 | 885 |
| 886 /// Parses a generalized function type. | |
| 887 /// | |
| 888 /// The return type must already be pushed. | |
| 889 Token parseFunctionType(Token token) { | |
| 890 // TODO(floitsch): don't use string comparison, but the keyword-state | |
| 891 // table is currently not set up to deal with upper-case characters. | |
| 892 if (token.value != "Function") { | |
| 893 return listener.expected("Function", token); | |
| 894 } | |
| 895 Token functionToken = token; | |
| 896 token = token.next; | |
| 897 token = parseTypeVariablesOpt(token); | |
| 898 token = parseFormalParameters(token, inFunctionType: true); | |
| 899 listener.endFunctionType(functionToken, token); | |
| 900 return token; | |
| 901 } | |
| 902 | |
| 816 Token parseTypeArgumentsOpt(Token token) { | 903 Token parseTypeArgumentsOpt(Token token) { |
| 817 return parseStuff( | 904 return parseStuff( |
| 818 token, | 905 token, |
| 819 (t) => listener.beginTypeArguments(t), | 906 (t) => listener.beginTypeArguments(t), |
| 820 (t) => parseType(t), | 907 (t) => parseType(t), |
| 821 (c, bt, et) => listener.endTypeArguments(c, bt, et), | 908 (c, bt, et) => listener.endTypeArguments(c, bt, et), |
| 822 (t) => listener.handleNoTypeArguments(t)); | 909 (t) => listener.handleNoTypeArguments(t)); |
| 823 } | 910 } |
| 824 | 911 |
| 825 Token parseTypeVariablesOpt(Token token) { | 912 Token parseTypeVariablesOpt(Token token) { |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1139 identifiers = identifiers.prepend(token); | 1226 identifiers = identifiers.prepend(token); |
| 1140 return identifiers; | 1227 return identifiers; |
| 1141 } else if (value == '=' || value == ';' || value == ',') { | 1228 } else if (value == '=' || value == ';' || value == ',') { |
| 1142 // A field or abstract getter. | 1229 // A field or abstract getter. |
| 1143 identifiers = identifiers.prepend(token); | 1230 identifiers = identifiers.prepend(token); |
| 1144 return identifiers; | 1231 return identifiers; |
| 1145 } else if (isGetter) { | 1232 } else if (isGetter) { |
| 1146 hasName = true; | 1233 hasName = true; |
| 1147 } | 1234 } |
| 1148 identifiers = identifiers.prepend(token); | 1235 identifiers = identifiers.prepend(token); |
| 1149 if (isValidTypeReference(token)) { | 1236 |
| 1150 // type ... | 1237 if (!isGeneralizedFunctionType(token)) { |
| 1151 if (optional('.', token.next)) { | 1238 // Read a potential return type. |
| 1152 // type '.' ... | 1239 if (isValidTypeReference(token)) { |
| 1153 if (token.next.next.isIdentifier()) { | 1240 // type ... |
| 1154 // type '.' identifier | 1241 if (optional('.', token.next)) { |
| 1155 token = token.next.next; | 1242 // type '.' ... |
| 1243 if (token.next.next.isIdentifier()) { | |
| 1244 // type '.' identifier | |
| 1245 token = token.next.next; | |
| 1246 } | |
| 1247 } | |
| 1248 if (optional('<', token.next)) { | |
| 1249 if (token.next is BeginGroupToken) { | |
| 1250 BeginGroupToken beginGroup = token.next; | |
| 1251 if (beginGroup.endGroup == null) { | |
| 1252 listener.unmatched(beginGroup); | |
| 1253 } | |
| 1254 token = beginGroup.endGroup; | |
| 1255 } | |
| 1156 } | 1256 } |
| 1157 } | 1257 } |
| 1158 if (optional('<', token.next)) { | 1258 token = token.next; |
| 1159 if (token.next is BeginGroupToken) { | 1259 } |
| 1160 BeginGroupToken beginGroup = token.next; | 1260 while (isGeneralizedFunctionType(token)) { |
| 1261 token = token.next; | |
| 1262 if (optional('<', token)) { | |
| 1263 if (token is BeginGroupToken) { | |
| 1264 BeginGroupToken beginGroup = token; | |
| 1161 if (beginGroup.endGroup == null) { | 1265 if (beginGroup.endGroup == null) { |
| 1162 listener.unmatched(beginGroup); | 1266 listener.unmatched(beginGroup); |
| 1163 } | 1267 } |
| 1164 token = beginGroup.endGroup; | 1268 token = beginGroup.endGroup.next; |
| 1165 } | 1269 } |
| 1166 } | 1270 } |
| 1271 if (!optional('(', token)) { | |
| 1272 if (optional(';', token)) { | |
| 1273 listener.recoverableError(token, "expected '('"); | |
| 1274 } | |
| 1275 token = listener.unexpected(token); | |
| 1276 } | |
| 1277 if (token is BeginGroupToken) { | |
| 1278 BeginGroupToken beginGroup = token; | |
| 1279 if (beginGroup.endGroup == null) { | |
| 1280 listener.unmatched(beginGroup); | |
| 1281 } | |
| 1282 token = beginGroup.endGroup.next; | |
| 1283 } | |
| 1167 } | 1284 } |
| 1168 token = token.next; | |
| 1169 } | 1285 } |
| 1170 return const Link<Token>(); | 1286 return const Link<Token>(); |
| 1171 } | 1287 } |
| 1172 | 1288 |
| 1173 Token parseVariableInitializerOpt(Token token) { | 1289 Token parseVariableInitializerOpt(Token token) { |
| 1174 if (optional('=', token)) { | 1290 if (optional('=', token)) { |
| 1175 Token assignment = token; | 1291 Token assignment = token; |
| 1176 listener.beginInitializer(token); | 1292 listener.beginInitializer(token); |
| 1177 token = parseExpression(token.next); | 1293 token = parseExpression(token.next); |
| 1178 listener.endInitializer(assignment); | 1294 listener.endInitializer(assignment); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1261 return token; | 1377 return token; |
| 1262 } | 1378 } |
| 1263 | 1379 |
| 1264 /** | 1380 /** |
| 1265 * Returns the first token after the type starting at [token]. | 1381 * Returns the first token after the type starting at [token]. |
| 1266 * This method assumes that [token] is an identifier (or void). | 1382 * This method assumes that [token] is an identifier (or void). |
| 1267 * Use [peekAfterIfType] if [token] isn't known to be an identifier. | 1383 * Use [peekAfterIfType] if [token] isn't known to be an identifier. |
| 1268 */ | 1384 */ |
| 1269 Token peekAfterType(Token token) { | 1385 Token peekAfterType(Token token) { |
| 1270 // We are looking at "identifier ...". | 1386 // We are looking at "identifier ...". |
| 1271 Token peek = token.next; | 1387 Token peek = token; |
| 1272 if (identical(peek.kind, PERIOD_TOKEN)) { | 1388 if (!isGeneralizedFunctionType(token)) { |
| 1273 if (peek.next.isIdentifier()) { | 1389 peek = token.next; |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:58
suggestion: consider introducing 2 functions to ma
floitsch
2016/12/30 14:55:48
Done.
| |
| 1274 // Look past a library prefix. | 1390 if (identical(peek.kind, PERIOD_TOKEN)) { |
| 1275 peek = peek.next.next; | 1391 if (peek.next.isIdentifier()) { |
| 1392 // Look past a library prefix. | |
| 1393 peek = peek.next.next; | |
| 1394 } | |
| 1395 } | |
| 1396 // We are looking at "qualified ...". | |
| 1397 if (identical(peek.kind, LT_TOKEN)) { | |
| 1398 // Possibly generic type. | |
| 1399 // We are looking at "qualified '<'". | |
| 1400 BeginGroupToken beginGroupToken = peek; | |
| 1401 Token gtToken = beginGroupToken.endGroup; | |
| 1402 if (gtToken != null) { | |
| 1403 // We are looking at "qualified '<' ... '>' ...". | |
| 1404 peek = gtToken.next; | |
| 1405 } | |
| 1276 } | 1406 } |
| 1277 } | 1407 } |
| 1278 // We are looking at "qualified ...". | 1408 |
| 1279 if (identical(peek.kind, LT_TOKEN)) { | 1409 // We might have just skipped over the return value of the function type. |
| 1280 // Possibly generic type. | 1410 // Check again, if we are now at a function type position. |
| 1281 // We are looking at "qualified '<'". | 1411 if (isGeneralizedFunctionType(peek)) { |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:58
do we need a loop here, like you had in parseType?
floitsch
2016/12/30 14:55:48
I'm not sure the loop is necessary, but I don't wa
| |
| 1282 BeginGroupToken beginGroupToken = peek; | 1412 peek = peek.next; // Skip over the Function. |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:57
nit: reword "the Function" to "the `Function` toke
floitsch
2016/12/30 14:55:47
Done.
| |
| 1283 Token gtToken = beginGroupToken.endGroup; | 1413 if (identical(peek.kind, LT_TOKEN)) { |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:58
consider adding here and below comments describing
floitsch
2016/12/30 14:55:48
Done.
| |
| 1284 if (gtToken != null) { | 1414 BeginGroupToken beginGroupToken = peek; |
| 1285 // We are looking at "qualified '<' ... '>' ...". | 1415 Token closeToken = beginGroupToken.endGroup; |
| 1286 return gtToken.next; | 1416 if (closeToken != null) { |
| 1417 peek = closeToken.next; | |
| 1418 } | |
| 1419 } | |
| 1420 | |
| 1421 // There must be an open paren to be valid, but we are not checking here. | |
| 1422 if (identical(peek.kind, OPEN_PAREN_TOKEN)) { | |
| 1423 BeginGroupToken beginGroupToken = peek; | |
| 1424 Token closeToken = beginGroupToken.endGroup; | |
| 1425 if (closeToken != null) { | |
| 1426 peek = closeToken.next; | |
| 1427 } | |
| 1287 } | 1428 } |
| 1288 } | 1429 } |
| 1289 return peek; | 1430 return peek; |
| 1290 } | 1431 } |
| 1291 | 1432 |
| 1292 /** | 1433 /** |
| 1293 * If [token] is the start of a type, returns the token after that type. | 1434 * If [token] is the start of a type, returns the token after that type. |
| 1294 * If [token] is not the start of a type, null is returned. | 1435 * If [token] is not the start of a type, null is returned. |
| 1295 */ | 1436 */ |
| 1296 Token peekAfterIfType(Token token) { | 1437 Token peekAfterIfType(Token token) { |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1821 | 1962 |
| 1822 Token parseExpressionStatementOrDeclaration(Token token) { | 1963 Token parseExpressionStatementOrDeclaration(Token token) { |
| 1823 assert(token.isIdentifier() || identical(token.stringValue, 'void')); | 1964 assert(token.isIdentifier() || identical(token.stringValue, 'void')); |
| 1824 Token identifier = peekIdentifierAfterType(token); | 1965 Token identifier = peekIdentifierAfterType(token); |
| 1825 if (identifier != null) { | 1966 if (identifier != null) { |
| 1826 assert(identifier.isIdentifier()); | 1967 assert(identifier.isIdentifier()); |
| 1827 Token afterId = identifier.next; | 1968 Token afterId = identifier.next; |
| 1828 int afterIdKind = afterId.kind; | 1969 int afterIdKind = afterId.kind; |
| 1829 if (identical(afterIdKind, EQ_TOKEN) || | 1970 if (identical(afterIdKind, EQ_TOKEN) || |
| 1830 identical(afterIdKind, SEMICOLON_TOKEN) || | 1971 identical(afterIdKind, SEMICOLON_TOKEN) || |
| 1831 identical(afterIdKind, COMMA_TOKEN)) { | 1972 identical(afterIdKind, COMMA_TOKEN) || |
| 1973 isGeneralizedFunctionType(identifier)) { | |
|
Siggi Cherem (dart-lang)
2016/12/29 22:46:58
why do we need this case? could this be handled by
floitsch
2016/12/30 14:55:48
Yes. thanks for figuring this out.
I should have p
| |
| 1832 // We are looking at "type identifier" followed by '=', ';', ','. | 1974 // We are looking at "type identifier" followed by '=', ';', ','. |
| 1833 return parseVariablesDeclaration(token); | 1975 return parseVariablesDeclaration(token); |
| 1834 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { | 1976 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { |
| 1835 // We are looking at "type identifier '('". | 1977 // We are looking at "type identifier '('". |
| 1836 BeginGroupToken beginParen = afterId; | 1978 BeginGroupToken beginParen = afterId; |
| 1837 Token endParen = beginParen.endGroup; | 1979 Token endParen = beginParen.endGroup; |
| 1838 // TODO(eernst): Check for NPE as described in issue 26252. | 1980 // TODO(eernst): Check for NPE as described in issue 26252. |
| 1839 Token afterParens = endParen.next; | 1981 Token afterParens = endParen.next; |
| 1840 if (optional('{', afterParens) || | 1982 if (optional('{', afterParens) || |
| 1841 optional('=>', afterParens) || | 1983 optional('=>', afterParens) || |
| (...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2969 } | 3111 } |
| 2970 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 3112 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2971 return expectSemicolon(token); | 3113 return expectSemicolon(token); |
| 2972 } | 3114 } |
| 2973 | 3115 |
| 2974 Token parseEmptyStatement(Token token) { | 3116 Token parseEmptyStatement(Token token) { |
| 2975 listener.handleEmptyStatement(token); | 3117 listener.handleEmptyStatement(token); |
| 2976 return expectSemicolon(token); | 3118 return expectSemicolon(token); |
| 2977 } | 3119 } |
| 2978 } | 3120 } |
| OLD | NEW |