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 |