Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.listener; | 5 library dart2js.parser.partial_elements; |
| 6 | 6 |
| 7 import '../compiler.dart' show | 7 import '../compiler.dart' show |
| 8 Compiler; | 8 Compiler; |
| 9 import '../dart_types.dart' show DynamicType; | 9 import '../dart_types.dart' show DynamicType; |
| 10 import '../diagnostics/diagnostic_listener.dart'; | 10 import '../diagnostics/diagnostic_listener.dart'; |
| 11 import '../diagnostics/invariant.dart' show | 11 import '../diagnostics/invariant.dart' show |
| 12 invariant; | 12 invariant; |
| 13 import '../diagnostics/messages.dart'; | 13 import '../diagnostics/messages.dart'; |
| 14 import '../diagnostics/spannable.dart' show | |
| 15 Spannable, | |
| 16 SpannableAssertionFailure; | |
| 17 import '../elements/elements.dart' show | 14 import '../elements/elements.dart' show |
| 18 CompilationUnitElement, | 15 CompilationUnitElement, |
| 19 ConstructorElement, | 16 ConstructorElement, |
| 20 Element, | 17 Element, |
| 21 ElementKind, | 18 ElementKind, |
| 22 GetterElement, | 19 GetterElement, |
| 23 LibraryElement, | 20 LibraryElement, |
| 24 MetadataAnnotation, | 21 MetadataAnnotation, |
| 25 MethodElement, | 22 MethodElement, |
| 26 SetterElement; | 23 SetterElement, |
| 24 STATE_NOT_STARTED, | |
| 25 STATE_DONE; | |
| 27 import '../elements/modelx.dart' show | 26 import '../elements/modelx.dart' show |
| 28 BaseFunctionElementX, | 27 BaseFunctionElementX, |
| 28 ClassElementX, | |
| 29 ConstructorElementX, | 29 ConstructorElementX, |
| 30 CompilationUnitElementX, | |
| 31 DeclarationSite, | 30 DeclarationSite, |
| 32 ElementX, | 31 ElementX, |
| 33 EnumClassElementX, | |
| 34 FieldElementX, | 32 FieldElementX, |
| 35 GetterElementX, | 33 GetterElementX, |
| 36 LibraryElementX, | |
| 37 MetadataAnnotationX, | 34 MetadataAnnotationX, |
| 38 MethodElementX, | 35 MethodElementX, |
| 39 MixinApplicationElementX, | |
| 40 SetterElementX, | 36 SetterElementX, |
| 41 TypedefElementX, | 37 TypedefElementX, |
| 42 VariableList; | 38 VariableList; |
| 43 import '../native/native.dart' as native; | 39 import '../elements/visitor.dart' show |
| 44 import '../string_validator.dart' show | 40 ElementVisitor; |
| 45 StringValidator; | |
| 46 import '../tokens/keyword.dart' show | |
| 47 Keyword; | |
| 48 import '../tokens/token.dart' show | 41 import '../tokens/token.dart' show |
| 49 BAD_INPUT_INFO, | |
| 50 BadInputToken, | 42 BadInputToken, |
| 51 BeginGroupToken, | 43 BeginGroupToken, |
| 52 EOF_INFO, | |
| 53 EOF_TOKEN, | |
| 54 ErrorToken, | 44 ErrorToken, |
| 55 IDENTIFIER_INFO, | |
| 56 INDEX_INFO, | |
| 57 KeywordToken, | 45 KeywordToken, |
| 58 StringToken, | 46 StringToken, |
| 59 Token, | 47 Token, |
| 60 UnmatchedToken, | 48 UnmatchedToken, |
| 61 UnterminatedToken; | 49 UnterminatedToken; |
| 50 import '../tokens/token_constants.dart' as Tokens show | |
| 51 EOF_TOKEN; | |
| 62 import '../tree/tree.dart'; | 52 import '../tree/tree.dart'; |
| 63 import '../util/util.dart' show | |
| 64 Link; | |
| 65 | 53 |
| 66 import 'class_element_parser.dart' show | 54 import 'class_element_parser.dart' show |
| 67 PartialClassElement; | 55 ClassElementParser; |
| 68 import 'parser.dart' show | 56 import 'parser.dart' show |
| 69 Parser; | 57 Parser; |
| 70 | 58 import 'listener.dart' show |
| 71 const bool VERBOSE = false; | 59 ParserError; |
| 72 | 60 import 'member_listener.dart' show |
| 73 /** | 61 MemberListener; |
| 74 * A parser event listener that does nothing except throw exceptions | 62 import 'node_listener.dart' show |
| 75 * on parser errors. | 63 NodeListener; |
| 76 */ | |
| 77 class Listener { | |
| 78 set suppressParseErrors(bool value) { | |
| 79 } | |
| 80 | |
| 81 void beginArguments(Token token) { | |
| 82 } | |
| 83 | |
| 84 void endArguments(int count, Token beginToken, Token endToken) { | |
| 85 } | |
| 86 | |
| 87 /// Handle async modifiers `async`, `async*`, `sync`. | |
| 88 void handleAsyncModifier(Token asyncToken, Token startToken) { | |
| 89 } | |
| 90 | |
| 91 void beginAwaitExpression(Token token) { | |
| 92 } | |
| 93 | |
| 94 void endAwaitExpression(Token beginToken, Token endToken) { | |
| 95 } | |
| 96 | |
| 97 void beginBlock(Token token) { | |
| 98 } | |
| 99 | |
| 100 void endBlock(int count, Token beginToken, Token endToken) { | |
| 101 } | |
| 102 | |
| 103 void beginCascade(Token token) { | |
| 104 } | |
| 105 | |
| 106 void endCascade() { | |
| 107 } | |
| 108 | |
| 109 void beginClassBody(Token token) { | |
| 110 } | |
| 111 | |
| 112 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
| 113 } | |
| 114 | |
| 115 void beginClassDeclaration(Token token) { | |
| 116 } | |
| 117 | |
| 118 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 119 Token extendsKeyword, Token implementsKeyword, | |
| 120 Token endToken) { | |
| 121 } | |
| 122 | |
| 123 void beginCombinators(Token token) { | |
| 124 } | |
| 125 | |
| 126 void endCombinators(int count) { | |
| 127 } | |
| 128 | |
| 129 void beginCompilationUnit(Token token) { | |
| 130 } | |
| 131 | |
| 132 void endCompilationUnit(int count, Token token) { | |
| 133 } | |
| 134 | |
| 135 void beginConstructorReference(Token start) { | |
| 136 } | |
| 137 | |
| 138 void endConstructorReference(Token start, Token periodBeforeName, | |
| 139 Token endToken) { | |
| 140 } | |
| 141 | |
| 142 void beginDoWhileStatement(Token token) { | |
| 143 } | |
| 144 | |
| 145 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
| 146 Token endToken) { | |
| 147 } | |
| 148 | |
| 149 void beginEnum(Token enumKeyword) { | |
| 150 } | |
| 151 | |
| 152 void endEnum(Token enumKeyword, Token endBrace, int count) { | |
| 153 } | |
| 154 | |
| 155 void beginExport(Token token) { | |
| 156 } | |
| 157 | |
| 158 void endExport(Token exportKeyword, Token semicolon) { | |
| 159 } | |
| 160 | |
| 161 void beginExpressionStatement(Token token) { | |
| 162 } | |
| 163 | |
| 164 void endExpressionStatement(Token token) { | |
| 165 } | |
| 166 | |
| 167 void beginFactoryMethod(Token token) { | |
| 168 } | |
| 169 | |
| 170 void endFactoryMethod(Token beginToken, Token endToken) { | |
| 171 } | |
| 172 | |
| 173 void beginFormalParameter(Token token) { | |
| 174 } | |
| 175 | |
| 176 void endFormalParameter(Token thisKeyword) { | |
| 177 } | |
| 178 | |
| 179 void handleNoFormalParameters(Token token) { | |
| 180 } | |
| 181 | |
| 182 void beginFormalParameters(Token token) { | |
| 183 } | |
| 184 | |
| 185 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
| 186 } | |
| 187 | |
| 188 void endFields(int count, Token beginToken, Token endToken) { | |
| 189 } | |
| 190 | |
| 191 void beginForStatement(Token token) { | |
| 192 } | |
| 193 | |
| 194 void endForStatement(int updateExpressionCount, | |
| 195 Token beginToken, Token endToken) { | |
| 196 } | |
| 197 | |
| 198 void endForIn(Token awaitToken, Token forToken, | |
| 199 Token inKeyword, Token endToken) { | |
| 200 } | |
| 201 | |
| 202 void beginFunction(Token token) { | |
| 203 } | |
| 204 | |
| 205 void endFunction(Token getOrSet, Token endToken) { | |
| 206 } | |
| 207 | |
| 208 void beginFunctionDeclaration(Token token) { | |
| 209 } | |
| 210 | |
| 211 void endFunctionDeclaration(Token token) { | |
| 212 } | |
| 213 | |
| 214 void beginFunctionBody(Token token) { | |
| 215 } | |
| 216 | |
| 217 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
| 218 } | |
| 219 | |
| 220 void handleNoFunctionBody(Token token) { | |
| 221 } | |
| 222 | |
| 223 void skippedFunctionBody(Token token) { | |
| 224 } | |
| 225 | |
| 226 void beginFunctionName(Token token) { | |
| 227 } | |
| 228 | |
| 229 void endFunctionName(Token token) { | |
| 230 } | |
| 231 | |
| 232 void beginFunctionTypeAlias(Token token) { | |
| 233 } | |
| 234 | |
| 235 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 236 } | |
| 237 | |
| 238 void beginMixinApplication(Token token) { | |
| 239 } | |
| 240 | |
| 241 void endMixinApplication() { | |
| 242 } | |
| 243 | |
| 244 void beginNamedMixinApplication(Token token) { | |
| 245 } | |
| 246 | |
| 247 void endNamedMixinApplication(Token classKeyword, | |
| 248 Token implementsKeyword, | |
| 249 Token endToken) { | |
| 250 } | |
| 251 | |
| 252 void beginHide(Token hideKeyword) { | |
| 253 } | |
| 254 | |
| 255 void endHide(Token hideKeyword) { | |
| 256 } | |
| 257 | |
| 258 void beginIdentifierList(Token token) { | |
| 259 } | |
| 260 | |
| 261 void endIdentifierList(int count) { | |
| 262 } | |
| 263 | |
| 264 void beginTypeList(Token token) { | |
| 265 } | |
| 266 | |
| 267 void endTypeList(int count) { | |
| 268 } | |
| 269 | |
| 270 void beginIfStatement(Token token) { | |
| 271 } | |
| 272 | |
| 273 void endIfStatement(Token ifToken, Token elseToken) { | |
| 274 } | |
| 275 | |
| 276 void beginImport(Token importKeyword) { | |
| 277 } | |
| 278 | |
| 279 void endImport(Token importKeyword, Token DeferredKeyword, | |
| 280 Token asKeyword, Token semicolon) { | |
| 281 } | |
| 282 | |
| 283 void beginInitializedIdentifier(Token token) { | |
| 284 } | |
| 285 | |
| 286 void endInitializedIdentifier() { | |
| 287 } | |
| 288 | |
| 289 void beginInitializer(Token token) { | |
| 290 } | |
| 291 | |
| 292 void endInitializer(Token assignmentOperator) { | |
| 293 } | |
| 294 | |
| 295 void beginInitializers(Token token) { | |
| 296 } | |
| 297 | |
| 298 void endInitializers(int count, Token beginToken, Token endToken) { | |
| 299 } | |
| 300 | |
| 301 void handleNoInitializers() { | |
| 302 } | |
| 303 | |
| 304 void handleLabel(Token token) { | |
| 305 } | |
| 306 | |
| 307 void beginLabeledStatement(Token token, int labelCount) { | |
| 308 } | |
| 309 | |
| 310 void endLabeledStatement(int labelCount) { | |
| 311 } | |
| 312 | |
| 313 void beginLibraryName(Token token) { | |
| 314 } | |
| 315 | |
| 316 void endLibraryName(Token libraryKeyword, Token semicolon) { | |
| 317 } | |
| 318 | |
| 319 void beginLiteralMapEntry(Token token) { | |
| 320 } | |
| 321 | |
| 322 void endLiteralMapEntry(Token colon, Token endToken) { | |
| 323 } | |
| 324 | |
| 325 void beginLiteralString(Token token) { | |
| 326 } | |
| 327 | |
| 328 void endLiteralString(int interpolationCount) { | |
| 329 } | |
| 330 | |
| 331 void handleStringJuxtaposition(int literalCount) { | |
| 332 } | |
| 333 | |
| 334 void beginMember(Token token) { | |
| 335 } | |
| 336 | |
| 337 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
| 338 } | |
| 339 | |
| 340 void beginMetadataStar(Token token) { | |
| 341 } | |
| 342 | |
| 343 void endMetadataStar(int count, bool forParameter) { | |
| 344 } | |
| 345 | |
| 346 void beginMetadata(Token token) { | |
| 347 } | |
| 348 | |
| 349 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | |
| 350 } | |
| 351 | |
| 352 void beginOptionalFormalParameters(Token token) { | |
| 353 } | |
| 354 | |
| 355 void endOptionalFormalParameters(int count, | |
| 356 Token beginToken, Token endToken) { | |
| 357 } | |
| 358 | |
| 359 void beginPart(Token token) { | |
| 360 } | |
| 361 | |
| 362 void endPart(Token partKeyword, Token semicolon) { | |
| 363 } | |
| 364 | |
| 365 void beginPartOf(Token token) { | |
| 366 } | |
| 367 | |
| 368 void endPartOf(Token partKeyword, Token semicolon) { | |
| 369 } | |
| 370 | |
| 371 void beginRedirectingFactoryBody(Token token) { | |
| 372 } | |
| 373 | |
| 374 void endRedirectingFactoryBody(Token beginToken, Token endToken) { | |
| 375 } | |
| 376 | |
| 377 void beginReturnStatement(Token token) { | |
| 378 } | |
| 379 | |
| 380 void endReturnStatement(bool hasExpression, | |
| 381 Token beginToken, Token endToken) { | |
| 382 } | |
| 383 | |
| 384 void beginSend(Token token) { | |
| 385 } | |
| 386 | |
| 387 void endSend(Token token) { | |
| 388 } | |
| 389 | |
| 390 void beginShow(Token showKeyword) { | |
| 391 } | |
| 392 | |
| 393 void endShow(Token showKeyword) { | |
| 394 } | |
| 395 | |
| 396 void beginSwitchStatement(Token token) { | |
| 397 } | |
| 398 | |
| 399 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
| 400 } | |
| 401 | |
| 402 void beginSwitchBlock(Token token) { | |
| 403 } | |
| 404 | |
| 405 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
| 406 } | |
| 407 | |
| 408 void beginLiteralSymbol(Token token) { | |
| 409 } | |
| 410 | |
| 411 void endLiteralSymbol(Token hashToken, int identifierCount) { | |
| 412 } | |
| 413 | |
| 414 void beginThrowExpression(Token token) { | |
| 415 } | |
| 416 | |
| 417 void endThrowExpression(Token throwToken, Token endToken) { | |
| 418 } | |
| 419 | |
| 420 void beginRethrowStatement(Token token) { | |
| 421 } | |
| 422 | |
| 423 void endRethrowStatement(Token throwToken, Token endToken) { | |
| 424 } | |
| 425 | |
| 426 void endTopLevelDeclaration(Token token) { | |
| 427 } | |
| 428 | |
| 429 void beginTopLevelMember(Token token) { | |
| 430 } | |
| 431 | |
| 432 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 433 } | |
| 434 | |
| 435 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 436 } | |
| 437 | |
| 438 void beginTryStatement(Token token) { | |
| 439 } | |
| 440 | |
| 441 void handleCaseMatch(Token caseKeyword, Token colon) { | |
| 442 } | |
| 443 | |
| 444 void handleCatchBlock(Token onKeyword, Token catchKeyword) { | |
| 445 } | |
| 446 | |
| 447 void handleFinallyBlock(Token finallyKeyword) { | |
| 448 } | |
| 449 | |
| 450 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
| 451 } | |
| 452 | |
| 453 void endType(Token beginToken, Token endToken) { | |
| 454 } | |
| 455 | |
| 456 void beginTypeArguments(Token token) { | |
| 457 } | |
| 458 | |
| 459 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
| 460 } | |
| 461 | |
| 462 void handleNoTypeArguments(Token token) { | |
| 463 } | |
| 464 | |
| 465 void beginTypeVariable(Token token) { | |
| 466 } | |
| 467 | |
| 468 void endTypeVariable(Token token) { | |
| 469 } | |
| 470 | |
| 471 void beginTypeVariables(Token token) { | |
| 472 } | |
| 473 | |
| 474 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
| 475 } | |
| 476 | |
| 477 void beginUnnamedFunction(Token token) { | |
| 478 } | |
| 479 | |
| 480 void endUnnamedFunction(Token token) { | |
| 481 } | |
| 482 | |
| 483 void beginVariablesDeclaration(Token token) { | |
| 484 } | |
| 485 | |
| 486 void endVariablesDeclaration(int count, Token endToken) { | |
| 487 } | |
| 488 | |
| 489 void beginWhileStatement(Token token) { | |
| 490 } | |
| 491 | |
| 492 void endWhileStatement(Token whileKeyword, Token endToken) { | |
| 493 } | |
| 494 | |
| 495 void handleAsOperator(Token operathor, Token endToken) { | |
| 496 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. | |
| 497 } | |
| 498 | |
| 499 void handleAssignmentExpression(Token token) { | |
| 500 } | |
| 501 | |
| 502 void handleBinaryExpression(Token token) { | |
| 503 } | |
| 504 | |
| 505 void handleConditionalExpression(Token question, Token colon) { | |
| 506 } | |
| 507 | |
| 508 void handleConstExpression(Token token) { | |
| 509 } | |
| 510 | |
| 511 void handleFunctionTypedFormalParameter(Token token) { | |
| 512 } | |
| 513 | |
| 514 void handleIdentifier(Token token) { | |
| 515 } | |
| 516 | |
| 517 void handleIndexedExpression(Token openCurlyBracket, | |
| 518 Token closeCurlyBracket) { | |
| 519 } | |
| 520 | |
| 521 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
| 522 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. | |
| 523 } | |
| 524 | |
| 525 void handleLiteralBool(Token token) { | |
| 526 } | |
| 527 | |
| 528 void handleBreakStatement(bool hasTarget, | |
| 529 Token breakKeyword, Token endToken) { | |
| 530 } | |
| 531 | |
| 532 void handleContinueStatement(bool hasTarget, | |
| 533 Token continueKeyword, Token endToken) { | |
| 534 } | |
| 535 | |
| 536 void handleEmptyStatement(Token token) { | |
| 537 } | |
| 538 | |
| 539 void handleAssertStatement(Token assertKeyword, Token semicolonToken) { | |
| 540 } | |
| 541 | |
| 542 /** Called with either the token containing a double literal, or | |
| 543 * an immediately preceding "unary plus" token. | |
| 544 */ | |
| 545 void handleLiteralDouble(Token token) { | |
| 546 } | |
| 547 | |
| 548 /** Called with either the token containing an integer literal, | |
| 549 * or an immediately preceding "unary plus" token. | |
| 550 */ | |
| 551 void handleLiteralInt(Token token) { | |
| 552 } | |
| 553 | |
| 554 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
| 555 Token endToken) { | |
| 556 } | |
| 557 | |
| 558 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
| 559 Token endToken) { | |
| 560 } | |
| 561 | |
| 562 void handleLiteralNull(Token token) { | |
| 563 } | |
| 564 | |
| 565 void handleModifier(Token token) { | |
| 566 } | |
| 567 | |
| 568 void handleModifiers(int count) { | |
| 569 } | |
| 570 | |
| 571 void handleNamedArgument(Token colon) { | |
| 572 } | |
| 573 | |
| 574 void handleNewExpression(Token token) { | |
| 575 } | |
| 576 | |
| 577 void handleNoArguments(Token token) { | |
| 578 } | |
| 579 | |
| 580 void handleNoExpression(Token token) { | |
| 581 } | |
| 582 | |
| 583 void handleNoType(Token token) { | |
| 584 } | |
| 585 | |
| 586 void handleNoTypeVariables(Token token) { | |
| 587 } | |
| 588 | |
| 589 void handleOperator(Token token) { | |
| 590 } | |
| 591 | |
| 592 void handleOperatorName(Token operatorKeyword, Token token) { | |
| 593 } | |
| 594 | |
| 595 void handleParenthesizedExpression(BeginGroupToken token) { | |
| 596 } | |
| 597 | |
| 598 void handleQualified(Token period) { | |
| 599 } | |
| 600 | |
| 601 void handleStringPart(Token token) { | |
| 602 } | |
| 603 | |
| 604 void handleSuperExpression(Token token) { | |
| 605 } | |
| 606 | |
| 607 void handleSwitchCase(int labelCount, int expressionCount, | |
| 608 Token defaultKeyword, int statementCount, | |
| 609 Token firstToken, Token endToken) { | |
| 610 } | |
| 611 | |
| 612 void handleThisExpression(Token token) { | |
| 613 } | |
| 614 | |
| 615 void handleUnaryPostfixAssignmentExpression(Token token) { | |
| 616 } | |
| 617 | |
| 618 void handleUnaryPrefixExpression(Token token) { | |
| 619 } | |
| 620 | |
| 621 void handleUnaryPrefixAssignmentExpression(Token token) { | |
| 622 } | |
| 623 | |
| 624 void handleValuedFormalParameter(Token equals, Token token) { | |
| 625 } | |
| 626 | |
| 627 void handleVoidKeyword(Token token) { | |
| 628 } | |
| 629 | |
| 630 void beginYieldStatement(Token token) { | |
| 631 } | |
| 632 | |
| 633 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { | |
| 634 } | |
| 635 | |
| 636 Token expected(String string, Token token) { | |
| 637 if (token is ErrorToken) { | |
| 638 reportErrorToken(token); | |
| 639 } else { | |
| 640 error("expected '$string', but got '${token.value}'", token); | |
| 641 } | |
| 642 return skipToEof(token); | |
| 643 } | |
| 644 | |
| 645 Token synthesizeIdentifier(Token token) { | |
| 646 Token synthesizedToken = | |
| 647 new StringToken.fromString(IDENTIFIER_INFO, '?', token.charOffset); | |
| 648 synthesizedToken.next = token.next; | |
| 649 return synthesizedToken; | |
| 650 } | |
| 651 | |
| 652 Token expectedIdentifier(Token token) { | |
| 653 if (token is ErrorToken) { | |
| 654 reportErrorToken(token); | |
| 655 } else { | |
| 656 error("expected identifier, but got '${token.value}'", token); | |
| 657 } | |
| 658 return skipToEof(token); | |
| 659 } | |
| 660 | |
| 661 Token expectedType(Token token) { | |
| 662 if (token is ErrorToken) { | |
| 663 reportErrorToken(token); | |
| 664 } else { | |
| 665 error("expected a type, but got '${token.value}'", token); | |
| 666 } | |
| 667 return skipToEof(token); | |
| 668 } | |
| 669 | |
| 670 Token expectedExpression(Token token) { | |
| 671 if (token is ErrorToken) { | |
| 672 reportErrorToken(token); | |
| 673 } else { | |
| 674 error("expected an expression, but got '${token.value}'", token); | |
| 675 } | |
| 676 return skipToEof(token); | |
| 677 } | |
| 678 | |
| 679 Token unexpected(Token token) { | |
| 680 if (token is ErrorToken) { | |
| 681 reportErrorToken(token); | |
| 682 } else { | |
| 683 error("unexpected token '${token.value}'", token); | |
| 684 } | |
| 685 return skipToEof(token); | |
| 686 } | |
| 687 | |
| 688 Token expectedBlockToSkip(Token token) { | |
| 689 if (token is ErrorToken) { | |
| 690 reportErrorToken(token); | |
| 691 } else { | |
| 692 error("expected a block, but got '${token.value}'", token); | |
| 693 } | |
| 694 return skipToEof(token); | |
| 695 } | |
| 696 | |
| 697 Token expectedFunctionBody(Token token) { | |
| 698 if (token is ErrorToken) { | |
| 699 reportErrorToken(token); | |
| 700 } else { | |
| 701 error("expected a function body, but got '${token.value}'", token); | |
| 702 } | |
| 703 return skipToEof(token); | |
| 704 } | |
| 705 | |
| 706 Token expectedClassBody(Token token) { | |
| 707 if (token is ErrorToken) { | |
| 708 reportErrorToken(token); | |
| 709 } else { | |
| 710 error("expected a class body, but got '${token.value}'", token); | |
| 711 } | |
| 712 return skipToEof(token); | |
| 713 } | |
| 714 | |
| 715 Token expectedClassBodyToSkip(Token token) { | |
| 716 if (token is ErrorToken) { | |
| 717 reportErrorToken(token); | |
| 718 } else { | |
| 719 error("expected a class body, but got '${token.value}'", token); | |
| 720 } | |
| 721 return skipToEof(token); | |
| 722 } | |
| 723 | |
| 724 Token expectedDeclaration(Token token) { | |
| 725 if (token is ErrorToken) { | |
| 726 reportErrorToken(token); | |
| 727 } else { | |
| 728 error("expected a declaration, but got '${token.value}'", token); | |
| 729 } | |
| 730 return skipToEof(token); | |
| 731 } | |
| 732 | |
| 733 Token unmatched(Token token) { | |
| 734 if (token is ErrorToken) { | |
| 735 reportErrorToken(token); | |
| 736 } else { | |
| 737 error("unmatched '${token.value}'", token); | |
| 738 } | |
| 739 return skipToEof(token); | |
| 740 } | |
| 741 | |
| 742 skipToEof(Token token) { | |
| 743 while (!identical(token.info, EOF_INFO)) { | |
| 744 token = token.next; | |
| 745 } | |
| 746 return token; | |
| 747 } | |
| 748 | |
| 749 void recoverableError(Token token, String message) { | |
| 750 error(message, token); | |
| 751 } | |
| 752 | |
| 753 void error(String message, Token token) { | |
| 754 throw new ParserError("$message @ ${token.charOffset}"); | |
| 755 } | |
| 756 | |
| 757 void reportError(Spannable spannable, | |
| 758 MessageKind messageKind, | |
| 759 [Map arguments = const {}]) { | |
| 760 MessageTemplate template = MessageTemplate.TEMPLATES[messageKind]; | |
| 761 String message = template.message(arguments, true).toString(); | |
| 762 Token token; | |
| 763 if (spannable is Token) { | |
| 764 token = spannable; | |
| 765 } else if (spannable is Node) { | |
| 766 token = spannable.getBeginToken(); | |
| 767 } else { | |
| 768 throw new ParserError(message); | |
| 769 } | |
| 770 recoverableError(token, message); | |
| 771 } | |
| 772 | |
| 773 void reportErrorToken(ErrorToken token) { | |
| 774 if (token is BadInputToken) { | |
| 775 String hex = token.character.toRadixString(16); | |
| 776 if (hex.length < 4) { | |
| 777 String padding = "0000".substring(hex.length); | |
| 778 hex = "$padding$hex"; | |
| 779 } | |
| 780 reportError( | |
| 781 token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex}); | |
| 782 } else if (token is UnterminatedToken) { | |
| 783 MessageKind kind; | |
| 784 var arguments = const {}; | |
| 785 switch (token.start) { | |
| 786 case '1e': | |
| 787 kind = MessageKind.EXPONENT_MISSING; | |
| 788 break; | |
| 789 case '"': | |
| 790 case "'": | |
| 791 case '"""': | |
| 792 case "'''": | |
| 793 case 'r"': | |
| 794 case "r'": | |
| 795 case 'r"""': | |
| 796 case "r'''": | |
| 797 kind = MessageKind.UNTERMINATED_STRING; | |
| 798 arguments = {'quote': token.start}; | |
| 799 break; | |
| 800 case '0x': | |
| 801 kind = MessageKind.HEX_DIGIT_EXPECTED; | |
| 802 break; | |
| 803 case r'$': | |
| 804 kind = MessageKind.MALFORMED_STRING_LITERAL; | |
| 805 break; | |
| 806 case '/*': | |
| 807 kind = MessageKind.UNTERMINATED_COMMENT; | |
| 808 break; | |
| 809 default: | |
| 810 kind = MessageKind.UNTERMINATED_TOKEN; | |
| 811 break; | |
| 812 } | |
| 813 reportError(token, kind, arguments); | |
| 814 } else if (token is UnmatchedToken) { | |
| 815 String begin = token.begin.value; | |
| 816 String end = closeBraceFor(begin); | |
| 817 reportError( | |
| 818 token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end}); | |
| 819 } else { | |
| 820 throw new SpannableAssertionFailure(token, token.assertionMessage); | |
| 821 } | |
| 822 } | |
| 823 } | |
| 824 | |
| 825 String closeBraceFor(String openBrace) { | |
| 826 return const { | |
| 827 '(': ')', | |
| 828 '[': ']', | |
| 829 '{': '}', | |
| 830 '<': '>', | |
| 831 r'${': '}', | |
| 832 }[openBrace]; | |
| 833 } | |
| 834 | |
| 835 class ParserError { | |
| 836 final String reason; | |
| 837 ParserError(this.reason); | |
| 838 toString() => reason; | |
| 839 } | |
| 840 | |
| 841 typedef int IdGenerator(); | |
| 842 | |
| 843 /** | |
| 844 * A parser event listener designed to work with [PartialParser]. It | |
| 845 * builds elements representing the top-level declarations found in | |
| 846 * the parsed compilation unit and records them in | |
| 847 * [compilationUnitElement]. | |
| 848 */ | |
| 849 class ElementListener extends Listener { | |
| 850 final IdGenerator idGenerator; | |
| 851 final DiagnosticListener listener; | |
| 852 final CompilationUnitElementX compilationUnitElement; | |
| 853 final StringValidator stringValidator; | |
| 854 Link<StringQuoting> interpolationScope; | |
| 855 | |
| 856 Link<Node> nodes = const Link<Node>(); | |
| 857 | |
| 858 Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>(); | |
| 859 | |
| 860 /// Records a stack of booleans for each member parsed (a stack is used to | |
| 861 /// support nested members which isn't currently possible, but it also serves | |
| 862 /// as a simple way to tell we're currently parsing a member). In this case, | |
| 863 /// member refers to members of a library or a class (but currently, classes | |
| 864 /// themselves are not considered members). If the top of the stack | |
| 865 /// (memberErrors.head) is true, the current member has already reported at | |
| 866 /// least one parse error. | |
| 867 Link<bool> memberErrors = const Link<bool>(); | |
| 868 | |
| 869 bool suppressParseErrors = false; | |
| 870 | |
| 871 ElementListener( | |
| 872 DiagnosticListener listener, | |
| 873 this.compilationUnitElement, | |
| 874 this.idGenerator) | |
| 875 : this.listener = listener, | |
| 876 stringValidator = new StringValidator(listener), | |
| 877 interpolationScope = const Link<StringQuoting>(); | |
| 878 | |
| 879 bool get currentMemberHasParseError { | |
| 880 return !memberErrors.isEmpty && memberErrors.head; | |
| 881 } | |
| 882 | |
| 883 void pushQuoting(StringQuoting quoting) { | |
| 884 interpolationScope = interpolationScope.prepend(quoting); | |
| 885 } | |
| 886 | |
| 887 StringQuoting popQuoting() { | |
| 888 StringQuoting result = interpolationScope.head; | |
| 889 interpolationScope = interpolationScope.tail; | |
| 890 return result; | |
| 891 } | |
| 892 | |
| 893 StringNode popLiteralString() { | |
| 894 StringNode node = popNode(); | |
| 895 // TODO(lrn): Handle interpolations in script tags. | |
| 896 if (node.isInterpolation) { | |
| 897 listener.internalError(node, | |
| 898 "String interpolation not supported in library tags."); | |
| 899 return null; | |
| 900 } | |
| 901 return node; | |
| 902 } | |
| 903 | |
| 904 bool allowLibraryTags() { | |
| 905 // Library tags are only allowed in the library file itself, not | |
| 906 // in sourced files. | |
| 907 LibraryElement library = compilationUnitElement.implementationLibrary; | |
| 908 return !compilationUnitElement.hasMembers && | |
| 909 library.entryCompilationUnit == compilationUnitElement; | |
| 910 } | |
| 911 | |
| 912 void endLibraryName(Token libraryKeyword, Token semicolon) { | |
| 913 Expression name = popNode(); | |
| 914 addLibraryTag(new LibraryName(libraryKeyword, name, | |
| 915 popMetadata(compilationUnitElement))); | |
| 916 } | |
| 917 | |
| 918 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, | |
| 919 Token semicolon) { | |
| 920 NodeList combinators = popNode(); | |
| 921 bool isDeferred = deferredKeyword != null; | |
| 922 Identifier prefix; | |
| 923 if (asKeyword != null) { | |
| 924 prefix = popNode(); | |
| 925 } | |
| 926 StringNode uri = popLiteralString(); | |
| 927 addLibraryTag(new Import(importKeyword, uri, prefix, combinators, | |
| 928 popMetadata(compilationUnitElement), | |
| 929 isDeferred: isDeferred)); | |
| 930 } | |
| 931 | |
| 932 void endEnum(Token enumKeyword, Token endBrace, int count) { | |
| 933 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ","); | |
| 934 Identifier name = popNode(); | |
| 935 | |
| 936 int id = idGenerator(); | |
| 937 Element enclosing = compilationUnitElement; | |
| 938 pushElement(new EnumClassElementX(name.source, enclosing, id, | |
| 939 new Enum(enumKeyword, name, names))); | |
| 940 rejectBuiltInIdentifier(name); | |
| 941 } | |
| 942 | |
| 943 void endExport(Token exportKeyword, Token semicolon) { | |
| 944 NodeList combinators = popNode(); | |
| 945 StringNode uri = popNode(); | |
| 946 addLibraryTag(new Export(exportKeyword, uri, combinators, | |
| 947 popMetadata(compilationUnitElement))); | |
| 948 } | |
| 949 | |
| 950 void endCombinators(int count) { | |
| 951 if (0 == count) { | |
| 952 pushNode(null); | |
| 953 } else { | |
| 954 pushNode(makeNodeList(count, null, null, " ")); | |
| 955 } | |
| 956 } | |
| 957 | |
| 958 void endHide(Token hideKeyword) => pushCombinator(hideKeyword); | |
| 959 | |
| 960 void endShow(Token showKeyword) => pushCombinator(showKeyword); | |
| 961 | |
| 962 void pushCombinator(Token keywordToken) { | |
| 963 NodeList identifiers = popNode(); | |
| 964 pushNode(new Combinator(identifiers, keywordToken)); | |
| 965 } | |
| 966 | |
| 967 void endIdentifierList(int count) { | |
| 968 pushNode(makeNodeList(count, null, null, ",")); | |
| 969 } | |
| 970 | |
| 971 void endTypeList(int count) { | |
| 972 pushNode(makeNodeList(count, null, null, ",")); | |
| 973 } | |
| 974 | |
| 975 void endPart(Token partKeyword, Token semicolon) { | |
| 976 StringNode uri = popLiteralString(); | |
| 977 addLibraryTag(new Part(partKeyword, uri, | |
| 978 popMetadata(compilationUnitElement))); | |
| 979 } | |
| 980 | |
| 981 void endPartOf(Token partKeyword, Token semicolon) { | |
| 982 Expression name = popNode(); | |
| 983 addPartOfTag(new PartOf(partKeyword, name, | |
| 984 popMetadata(compilationUnitElement))); | |
| 985 } | |
| 986 | |
| 987 void addPartOfTag(PartOf tag) { | |
| 988 compilationUnitElement.setPartOf(tag, listener); | |
| 989 } | |
| 990 | |
| 991 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | |
| 992 if (periodBeforeName != null) { | |
| 993 popNode(); // Discard name. | |
| 994 } | |
| 995 popNode(); // Discard node (Send or Identifier). | |
| 996 pushMetadata(new PartialMetadataAnnotation(beginToken, endToken)); | |
| 997 } | |
| 998 | |
| 999 void endTopLevelDeclaration(Token token) { | |
| 1000 if (!metadata.isEmpty) { | |
| 1001 recoverableError(metadata.head.beginToken, | |
| 1002 'Metadata not supported here.'); | |
| 1003 metadata = const Link<MetadataAnnotation>(); | |
| 1004 } | |
| 1005 } | |
| 1006 | |
| 1007 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 1008 Token extendsKeyword, Token implementsKeyword, | |
| 1009 Token endToken) { | |
| 1010 makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces | |
| 1011 popNode(); // superType | |
| 1012 popNode(); // typeParameters | |
| 1013 Identifier name = popNode(); | |
| 1014 int id = idGenerator(); | |
| 1015 PartialClassElement element = new PartialClassElement( | |
| 1016 name.source, beginToken, endToken, compilationUnitElement, id); | |
| 1017 pushElement(element); | |
| 1018 rejectBuiltInIdentifier(name); | |
| 1019 } | |
| 1020 | |
| 1021 void rejectBuiltInIdentifier(Identifier name) { | |
| 1022 if (name.token is KeywordToken) { | |
| 1023 Keyword keyword = (name.token as KeywordToken).keyword; | |
| 1024 if (!keyword.isPseudo) { | |
| 1025 recoverableError(name, "Illegal name '${keyword.syntax}'."); | |
| 1026 } | |
| 1027 } | |
| 1028 } | |
| 1029 | |
| 1030 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 1031 popNode(); // TODO(karlklose): do not throw away typeVariables. | |
| 1032 Identifier name = popNode(); | |
| 1033 popNode(); // returnType | |
| 1034 pushElement( | |
| 1035 new PartialTypedefElement( | |
| 1036 name.source, compilationUnitElement, typedefKeyword, endToken)); | |
| 1037 rejectBuiltInIdentifier(name); | |
| 1038 } | |
| 1039 | |
| 1040 void endNamedMixinApplication(Token classKeyword, | |
| 1041 Token implementsKeyword, | |
| 1042 Token endToken) { | |
| 1043 NodeList interfaces = (implementsKeyword != null) ? popNode() : null; | |
| 1044 MixinApplication mixinApplication = popNode(); | |
| 1045 Modifiers modifiers = popNode(); | |
| 1046 NodeList typeParameters = popNode(); | |
| 1047 Identifier name = popNode(); | |
| 1048 NamedMixinApplication namedMixinApplication = new NamedMixinApplication( | |
| 1049 name, typeParameters, modifiers, mixinApplication, interfaces, | |
| 1050 classKeyword, endToken); | |
| 1051 | |
| 1052 int id = idGenerator(); | |
| 1053 Element enclosing = compilationUnitElement; | |
| 1054 pushElement(new MixinApplicationElementX(name.source, enclosing, id, | |
| 1055 namedMixinApplication, | |
| 1056 modifiers)); | |
| 1057 rejectBuiltInIdentifier(name); | |
| 1058 } | |
| 1059 | |
| 1060 void endMixinApplication() { | |
| 1061 NodeList mixins = popNode(); | |
| 1062 TypeAnnotation superclass = popNode(); | |
| 1063 pushNode(new MixinApplication(superclass, mixins)); | |
| 1064 } | |
| 1065 | |
| 1066 void handleVoidKeyword(Token token) { | |
| 1067 pushNode(new TypeAnnotation(new Identifier(token), null)); | |
| 1068 } | |
| 1069 | |
| 1070 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 1071 bool hasParseError = currentMemberHasParseError; | |
| 1072 memberErrors = memberErrors.tail; | |
| 1073 Identifier name = popNode(); | |
| 1074 popNode(); // type | |
| 1075 Modifiers modifiers = popNode(); | |
| 1076 PartialFunctionElement element = new PartialFunctionElement( | |
| 1077 name.source, beginToken, getOrSet, endToken, | |
| 1078 modifiers, compilationUnitElement); | |
| 1079 element.hasParseError = hasParseError; | |
| 1080 pushElement(element); | |
| 1081 } | |
| 1082 | |
| 1083 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 1084 bool hasParseError = currentMemberHasParseError; | |
| 1085 memberErrors = memberErrors.tail; | |
| 1086 void buildFieldElement(Identifier name, VariableList fields) { | |
| 1087 pushElement( | |
| 1088 new FieldElementX(name, compilationUnitElement, fields)); | |
| 1089 } | |
| 1090 NodeList variables = makeNodeList(count, null, null, ","); | |
| 1091 popNode(); // type | |
| 1092 Modifiers modifiers = popNode(); | |
| 1093 buildFieldElements(modifiers, variables, compilationUnitElement, | |
| 1094 buildFieldElement, | |
| 1095 beginToken, endToken, hasParseError); | |
| 1096 } | |
| 1097 | |
| 1098 void buildFieldElements(Modifiers modifiers, | |
| 1099 NodeList variables, | |
| 1100 Element enclosingElement, | |
| 1101 void buildFieldElement(Identifier name, | |
| 1102 VariableList fields), | |
| 1103 Token beginToken, Token endToken, | |
| 1104 bool hasParseError) { | |
| 1105 VariableList fields = | |
| 1106 new PartialFieldList(beginToken, endToken, modifiers, hasParseError); | |
| 1107 for (Link<Node> variableNodes = variables.nodes; | |
| 1108 !variableNodes.isEmpty; | |
| 1109 variableNodes = variableNodes.tail) { | |
| 1110 Expression initializedIdentifier = variableNodes.head; | |
| 1111 Identifier identifier = initializedIdentifier.asIdentifier(); | |
| 1112 if (identifier == null) { | |
| 1113 identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); | |
| 1114 } | |
| 1115 buildFieldElement(identifier, fields); | |
| 1116 } | |
| 1117 } | |
| 1118 | |
| 1119 void handleIdentifier(Token token) { | |
| 1120 pushNode(new Identifier(token)); | |
| 1121 } | |
| 1122 | |
| 1123 void handleQualified(Token period) { | |
| 1124 Identifier last = popNode(); | |
| 1125 Expression first = popNode(); | |
| 1126 pushNode(new Send(first, last)); | |
| 1127 } | |
| 1128 | |
| 1129 void handleNoType(Token token) { | |
| 1130 pushNode(null); | |
| 1131 } | |
| 1132 | |
| 1133 void endTypeVariable(Token token) { | |
| 1134 TypeAnnotation bound = popNode(); | |
| 1135 Identifier name = popNode(); | |
| 1136 pushNode(new TypeVariable(name, bound)); | |
| 1137 rejectBuiltInIdentifier(name); | |
| 1138 } | |
| 1139 | |
| 1140 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
| 1141 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 1142 } | |
| 1143 | |
| 1144 void handleNoTypeVariables(token) { | |
| 1145 pushNode(null); | |
| 1146 } | |
| 1147 | |
| 1148 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
| 1149 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 1150 } | |
| 1151 | |
| 1152 void handleNoTypeArguments(Token token) { | |
| 1153 pushNode(null); | |
| 1154 } | |
| 1155 | |
| 1156 void endType(Token beginToken, Token endToken) { | |
| 1157 NodeList typeArguments = popNode(); | |
| 1158 Expression typeName = popNode(); | |
| 1159 pushNode(new TypeAnnotation(typeName, typeArguments)); | |
| 1160 } | |
| 1161 | |
| 1162 void handleParenthesizedExpression(BeginGroupToken token) { | |
| 1163 Expression expression = popNode(); | |
| 1164 pushNode(new ParenthesizedExpression(expression, token)); | |
| 1165 } | |
| 1166 | |
| 1167 void handleModifier(Token token) { | |
| 1168 pushNode(new Identifier(token)); | |
| 1169 } | |
| 1170 | |
| 1171 void handleModifiers(int count) { | |
| 1172 if (count == 0) { | |
| 1173 pushNode(Modifiers.EMPTY); | |
| 1174 } else { | |
| 1175 NodeList modifierNodes = makeNodeList(count, null, null, ' '); | |
| 1176 pushNode(new Modifiers(modifierNodes)); | |
| 1177 } | |
| 1178 } | |
| 1179 | |
| 1180 Token expected(String string, Token token) { | |
| 1181 if (token is ErrorToken) { | |
| 1182 reportErrorToken(token); | |
| 1183 } else if (identical(';', string)) { | |
| 1184 // When a semicolon is missing, it often leads to an error on the | |
| 1185 // following line. So we try to find the token preceding the semicolon | |
| 1186 // and report that something is missing *after* it. | |
| 1187 Token preceding = findPrecedingToken(token); | |
| 1188 if (preceding == token) { | |
| 1189 reportError( | |
| 1190 token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string}); | |
| 1191 } else { | |
| 1192 reportError( | |
| 1193 preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string}); | |
| 1194 } | |
| 1195 return token; | |
| 1196 } else { | |
| 1197 reportFatalError( | |
| 1198 token, | |
| 1199 MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS] | |
| 1200 .message({'token': string}, true).toString()); | |
| 1201 } | |
| 1202 return skipToEof(token); | |
| 1203 } | |
| 1204 | |
| 1205 /// Finds the preceding token via the begin token of the last AST node pushed | |
| 1206 /// on the [nodes] stack. | |
| 1207 Token findPrecedingToken(Token token) { | |
| 1208 Token result; | |
| 1209 Link<Node> nodes = this.nodes; | |
| 1210 while (!nodes.isEmpty) { | |
| 1211 result = findPrecedingTokenFromNode(nodes.head, token); | |
| 1212 if (result != null) { | |
| 1213 return result; | |
| 1214 } | |
| 1215 nodes = nodes.tail; | |
| 1216 } | |
| 1217 if (compilationUnitElement != null) { | |
| 1218 if (compilationUnitElement is CompilationUnitElementX) { | |
| 1219 CompilationUnitElementX unit = compilationUnitElement; | |
| 1220 Link<Element> members = unit.localMembers; | |
| 1221 while (!members.isEmpty) { | |
| 1222 ElementX member = members.head; | |
| 1223 DeclarationSite site = member.declarationSite; | |
| 1224 if (site is PartialElement) { | |
| 1225 result = findPrecedingTokenFromToken(site.endToken, token); | |
| 1226 if (result != null) { | |
| 1227 return result; | |
| 1228 } | |
| 1229 } | |
| 1230 members = members.tail; | |
| 1231 } | |
| 1232 result = | |
| 1233 findPrecedingTokenFromNode(compilationUnitElement.partTag, token); | |
| 1234 if (result != null) { | |
| 1235 return result; | |
| 1236 } | |
| 1237 } | |
| 1238 } | |
| 1239 return token; | |
| 1240 } | |
| 1241 | |
| 1242 Token findPrecedingTokenFromNode(Node node, Token token) { | |
| 1243 if (node != null) { | |
| 1244 return findPrecedingTokenFromToken(node.getBeginToken(), token); | |
| 1245 } | |
| 1246 return null; | |
| 1247 } | |
| 1248 | |
| 1249 Token findPrecedingTokenFromToken(Token start, Token token) { | |
| 1250 if (start != null) { | |
| 1251 Token current = start; | |
| 1252 while (current.kind != EOF_TOKEN && current.next != token) { | |
| 1253 current = current.next; | |
| 1254 } | |
| 1255 if (current.kind != EOF_TOKEN) { | |
| 1256 return current; | |
| 1257 } | |
| 1258 } | |
| 1259 return null; | |
| 1260 } | |
| 1261 | |
| 1262 Token expectedIdentifier(Token token) { | |
| 1263 if (token is KeywordToken) { | |
| 1264 reportError( | |
| 1265 token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD, | |
| 1266 {'keyword': token.value}); | |
| 1267 } else if (token is ErrorToken) { | |
| 1268 reportErrorToken(token); | |
| 1269 return synthesizeIdentifier(token); | |
| 1270 } else { | |
| 1271 reportFatalError(token, | |
| 1272 "Expected identifier, but got '${token.value}'."); | |
| 1273 } | |
| 1274 return token; | |
| 1275 } | |
| 1276 | |
| 1277 Token expectedType(Token token) { | |
| 1278 pushNode(null); | |
| 1279 if (token is ErrorToken) { | |
| 1280 reportErrorToken(token); | |
| 1281 return synthesizeIdentifier(token); | |
| 1282 } else { | |
| 1283 reportFatalError( | |
| 1284 token, "Expected a type, but got '${token.value}'."); | |
| 1285 return skipToEof(token); | |
| 1286 } | |
| 1287 } | |
| 1288 | |
| 1289 Token expectedExpression(Token token) { | |
| 1290 if (token is ErrorToken) { | |
| 1291 reportErrorToken(token); | |
| 1292 pushNode(new ErrorExpression(token)); | |
| 1293 return token.next; | |
| 1294 } else { | |
| 1295 reportFatalError(token, | |
| 1296 "Expected an expression, but got '${token.value}'."); | |
| 1297 pushNode(null); | |
| 1298 return skipToEof(token); | |
| 1299 } | |
| 1300 } | |
| 1301 | |
| 1302 Token unexpected(Token token) { | |
| 1303 if (token is ErrorToken) { | |
| 1304 reportErrorToken(token); | |
| 1305 } else { | |
| 1306 String message = "Unexpected token '${token.value}'."; | |
| 1307 if (token.info == BAD_INPUT_INFO) { | |
| 1308 message = token.value; | |
| 1309 } | |
| 1310 reportFatalError(token, message); | |
| 1311 } | |
| 1312 return skipToEof(token); | |
| 1313 } | |
| 1314 | |
| 1315 Token expectedBlockToSkip(Token token) { | |
| 1316 if (identical(token.stringValue, 'native')) { | |
| 1317 return native.handleNativeBlockToSkip(this, token); | |
| 1318 } else { | |
| 1319 return unexpected(token); | |
| 1320 } | |
| 1321 } | |
| 1322 | |
| 1323 Token expectedFunctionBody(Token token) { | |
| 1324 if (token is ErrorToken) { | |
| 1325 reportErrorToken(token); | |
| 1326 } else { | |
| 1327 String printString = token.value; | |
| 1328 reportFatalError(token, | |
| 1329 "Expected a function body, but got '$printString'."); | |
| 1330 } | |
| 1331 return skipToEof(token); | |
| 1332 } | |
| 1333 | |
| 1334 Token expectedClassBody(Token token) { | |
| 1335 if (token is ErrorToken) { | |
| 1336 reportErrorToken(token); | |
| 1337 } else { | |
| 1338 reportFatalError(token, | |
| 1339 "Expected a class body, but got '${token.value}'."); | |
| 1340 } | |
| 1341 return skipToEof(token); | |
| 1342 } | |
| 1343 | |
| 1344 Token expectedClassBodyToSkip(Token token) { | |
| 1345 return unexpected(token); | |
| 1346 } | |
| 1347 | |
| 1348 Token expectedDeclaration(Token token) { | |
| 1349 if (token is ErrorToken) { | |
| 1350 reportErrorToken(token); | |
| 1351 } else { | |
| 1352 reportFatalError(token, | |
| 1353 "Expected a declaration, but got '${token.value}'."); | |
| 1354 } | |
| 1355 return skipToEof(token); | |
| 1356 } | |
| 1357 | |
| 1358 Token unmatched(Token token) { | |
| 1359 if (token is ErrorToken) { | |
| 1360 reportErrorToken(token); | |
| 1361 } else { | |
| 1362 String begin = token.value; | |
| 1363 String end = closeBraceFor(begin); | |
| 1364 reportError( | |
| 1365 token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end}); | |
| 1366 } | |
| 1367 Token next = token.next; | |
| 1368 while (next is ErrorToken) { | |
| 1369 next = next.next; | |
| 1370 } | |
| 1371 return next; | |
| 1372 } | |
| 1373 | |
| 1374 void recoverableError(Spannable node, String message) { | |
| 1375 // TODO(johnniwinther): Make recoverable errors non-fatal. | |
| 1376 reportFatalError(node, message); | |
| 1377 } | |
| 1378 | |
| 1379 void pushElement(Element element) { | |
| 1380 popMetadata(element); | |
| 1381 compilationUnitElement.addMember(element, listener); | |
| 1382 } | |
| 1383 | |
| 1384 Link<MetadataAnnotation> popMetadata(ElementX element) { | |
| 1385 var result = const Link<MetadataAnnotation>(); | |
| 1386 for (Link link = metadata; !link.isEmpty; link = link.tail) { | |
| 1387 element.addMetadata(link.head); | |
| 1388 // Reverse the list as is implicitly done by addMetadata. | |
| 1389 result = result.prepend(link.head); | |
| 1390 } | |
| 1391 metadata = const Link<MetadataAnnotation>(); | |
| 1392 return result; | |
| 1393 } | |
| 1394 | |
| 1395 void pushMetadata(MetadataAnnotation annotation) { | |
| 1396 metadata = metadata.prepend(annotation); | |
| 1397 } | |
| 1398 | |
| 1399 void addLibraryTag(LibraryTag tag) { | |
| 1400 if (!allowLibraryTags()) { | |
| 1401 recoverableError(tag, 'Library tags not allowed here.'); | |
| 1402 } | |
| 1403 LibraryElementX implementationLibrary = | |
| 1404 compilationUnitElement.implementationLibrary; | |
| 1405 implementationLibrary.addTag(tag, listener); | |
| 1406 } | |
| 1407 | |
| 1408 void pushNode(Node node) { | |
| 1409 nodes = nodes.prepend(node); | |
| 1410 if (VERBOSE) log("push $nodes"); | |
| 1411 } | |
| 1412 | |
| 1413 Node popNode() { | |
| 1414 assert(!nodes.isEmpty); | |
| 1415 Node node = nodes.head; | |
| 1416 nodes = nodes.tail; | |
| 1417 if (VERBOSE) log("pop $nodes"); | |
| 1418 return node; | |
| 1419 } | |
| 1420 | |
| 1421 void log(message) { | |
| 1422 print(message); | |
| 1423 } | |
| 1424 | |
| 1425 NodeList makeNodeList(int count, Token beginToken, Token endToken, | |
| 1426 String delimiter) { | |
| 1427 Link<Node> poppedNodes = const Link<Node>(); | |
| 1428 for (; count > 0; --count) { | |
| 1429 // This effectively reverses the order of nodes so they end up | |
| 1430 // in correct (source) order. | |
| 1431 poppedNodes = poppedNodes.prepend(popNode()); | |
| 1432 } | |
| 1433 return new NodeList(beginToken, poppedNodes, endToken, delimiter); | |
| 1434 } | |
| 1435 | |
| 1436 void beginLiteralString(Token token) { | |
| 1437 String source = token.value; | |
| 1438 StringQuoting quoting = StringValidator.quotingFromString(source); | |
| 1439 pushQuoting(quoting); | |
| 1440 // Just wrap the token for now. At the end of the interpolation, | |
| 1441 // when we know how many there are, go back and validate the tokens. | |
| 1442 pushNode(new LiteralString(token, null)); | |
| 1443 } | |
| 1444 | |
| 1445 void handleStringPart(Token token) { | |
| 1446 // Just push an unvalidated token now, and replace it when we know the | |
| 1447 // end of the interpolation. | |
| 1448 pushNode(new LiteralString(token, null)); | |
| 1449 } | |
| 1450 | |
| 1451 void endLiteralString(int count) { | |
| 1452 StringQuoting quoting = popQuoting(); | |
| 1453 | |
| 1454 Link<StringInterpolationPart> parts = | |
| 1455 const Link<StringInterpolationPart>(); | |
| 1456 // Parts of the string interpolation are popped in reverse order, | |
| 1457 // starting with the last literal string part. | |
| 1458 bool isLast = true; | |
| 1459 for (int i = 0; i < count; i++) { | |
| 1460 LiteralString string = popNode(); | |
| 1461 DartString validation = | |
| 1462 stringValidator.validateInterpolationPart(string.token, quoting, | |
| 1463 isFirst: false, | |
| 1464 isLast: isLast); | |
| 1465 // Replace the unvalidated LiteralString with a new LiteralString | |
| 1466 // object that has the validation result included. | |
| 1467 string = new LiteralString(string.token, validation); | |
| 1468 Expression expression = popNode(); | |
| 1469 parts = parts.prepend(new StringInterpolationPart(expression, string)); | |
| 1470 isLast = false; | |
| 1471 } | |
| 1472 | |
| 1473 LiteralString string = popNode(); | |
| 1474 DartString validation = | |
| 1475 stringValidator.validateInterpolationPart(string.token, quoting, | |
| 1476 isFirst: true, | |
| 1477 isLast: isLast); | |
| 1478 string = new LiteralString(string.token, validation); | |
| 1479 if (isLast) { | |
| 1480 pushNode(string); | |
| 1481 } else { | |
| 1482 NodeList partNodes = new NodeList(null, parts, null, ""); | |
| 1483 pushNode(new StringInterpolation(string, partNodes)); | |
| 1484 } | |
| 1485 } | |
| 1486 | |
| 1487 void handleStringJuxtaposition(int stringCount) { | |
| 1488 assert(stringCount != 0); | |
| 1489 Expression accumulator = popNode(); | |
| 1490 stringCount--; | |
| 1491 while (stringCount > 0) { | |
| 1492 Expression expression = popNode(); | |
| 1493 accumulator = new StringJuxtaposition(expression, accumulator); | |
| 1494 stringCount--; | |
| 1495 } | |
| 1496 pushNode(accumulator); | |
| 1497 } | |
| 1498 | |
| 1499 void beginMember(Token token) { | |
| 1500 memberErrors = memberErrors.prepend(false); | |
| 1501 } | |
| 1502 | |
| 1503 void beginTopLevelMember(Token token) { | |
| 1504 beginMember(token); | |
| 1505 } | |
| 1506 | |
| 1507 void endFields(fieldCount, start, token) { | |
| 1508 memberErrors = memberErrors.tail; | |
| 1509 } | |
| 1510 | |
| 1511 void endMethod(getOrSet, start, token) { | |
| 1512 memberErrors = memberErrors.tail; | |
| 1513 } | |
| 1514 | |
| 1515 void beginFactoryMethod(Token token) { | |
| 1516 memberErrors = memberErrors.prepend(false); | |
| 1517 } | |
| 1518 | |
| 1519 void endFactoryMethod(Token beginToken, Token endToken) { | |
| 1520 memberErrors = memberErrors.tail; | |
| 1521 } | |
| 1522 | |
| 1523 /// Don't call this method. Should only be used as a last resort when there | |
| 1524 /// is no feasible way to recover from a parser error. | |
| 1525 void reportFatalError(Spannable spannable, String message) { | |
| 1526 reportError(spannable, MessageKind.GENERIC, {'text': message}); | |
| 1527 // Some parse errors are infeasible to recover from, so we throw an error. | |
| 1528 throw new ParserError(message); | |
| 1529 } | |
| 1530 | |
| 1531 void reportError(Spannable spannable, | |
| 1532 MessageKind errorCode, | |
| 1533 [Map arguments = const {}]) { | |
| 1534 if (currentMemberHasParseError) return; // Error already reported. | |
| 1535 if (suppressParseErrors) return; | |
| 1536 if (!memberErrors.isEmpty) { | |
| 1537 memberErrors = memberErrors.tail.prepend(true); | |
| 1538 } | |
| 1539 listener.reportError(spannable, errorCode, arguments); | |
| 1540 } | |
| 1541 } | |
| 1542 | |
| 1543 class NodeListener extends ElementListener { | |
| 1544 NodeListener( | |
| 1545 DiagnosticListener listener, | |
| 1546 CompilationUnitElement element) | |
| 1547 : super(listener, element, null); | |
| 1548 | |
| 1549 void addLibraryTag(LibraryTag tag) { | |
| 1550 pushNode(tag); | |
| 1551 } | |
| 1552 | |
| 1553 void addPartOfTag(PartOf tag) { | |
| 1554 pushNode(tag); | |
| 1555 } | |
| 1556 | |
| 1557 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 1558 Token extendsKeyword, Token implementsKeyword, | |
| 1559 Token endToken) { | |
| 1560 NodeList body = popNode(); | |
| 1561 NodeList interfaces = | |
| 1562 makeNodeList(interfacesCount, implementsKeyword, null, ","); | |
| 1563 Node supertype = popNode(); | |
| 1564 NodeList typeParameters = popNode(); | |
| 1565 Identifier name = popNode(); | |
| 1566 Modifiers modifiers = popNode(); | |
| 1567 pushNode(new ClassNode(modifiers, name, typeParameters, supertype, | |
| 1568 interfaces, beginToken, extendsKeyword, body, | |
| 1569 endToken)); | |
| 1570 } | |
| 1571 | |
| 1572 void endCompilationUnit(int count, Token token) { | |
| 1573 pushNode(makeNodeList(count, null, null, '\n')); | |
| 1574 } | |
| 1575 | |
| 1576 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 1577 NodeList formals = popNode(); | |
| 1578 NodeList typeParameters = popNode(); | |
| 1579 Identifier name = popNode(); | |
| 1580 TypeAnnotation returnType = popNode(); | |
| 1581 pushNode(new Typedef(returnType, name, typeParameters, formals, | |
| 1582 typedefKeyword, endToken)); | |
| 1583 } | |
| 1584 | |
| 1585 void endNamedMixinApplication(Token classKeyword, | |
| 1586 Token implementsKeyword, | |
| 1587 Token endToken) { | |
| 1588 NodeList interfaces = (implementsKeyword != null) ? popNode() : null; | |
| 1589 Node mixinApplication = popNode(); | |
| 1590 Modifiers modifiers = popNode(); | |
| 1591 NodeList typeParameters = popNode(); | |
| 1592 Identifier name = popNode(); | |
| 1593 pushNode(new NamedMixinApplication(name, typeParameters, | |
| 1594 modifiers, mixinApplication, | |
| 1595 interfaces, | |
| 1596 classKeyword, endToken)); | |
| 1597 } | |
| 1598 | |
| 1599 void endEnum(Token enumKeyword, Token endBrace, int count) { | |
| 1600 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ","); | |
| 1601 Identifier name = popNode(); | |
| 1602 pushNode(new Enum(enumKeyword, name, names)); | |
| 1603 } | |
| 1604 | |
| 1605 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
| 1606 pushNode(makeNodeList(memberCount, beginToken, endToken, null)); | |
| 1607 } | |
| 1608 | |
| 1609 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 1610 NodeList variables = makeNodeList(count, null, endToken, ","); | |
| 1611 TypeAnnotation type = popNode(); | |
| 1612 Modifiers modifiers = popNode(); | |
| 1613 pushNode(new VariableDefinitions(type, modifiers, variables)); | |
| 1614 } | |
| 1615 | |
| 1616 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 1617 popNode(); // body | |
| 1618 popNode(); // formalParameters | |
| 1619 Identifier name = popNode(); | |
| 1620 popNode(); // type | |
| 1621 Modifiers modifiers = popNode(); | |
| 1622 PartialFunctionElement element = new PartialFunctionElement( | |
| 1623 name.source, beginToken, getOrSet, endToken, | |
| 1624 modifiers, compilationUnitElement); | |
| 1625 pushElement(element); | |
| 1626 } | |
| 1627 | |
| 1628 void endFormalParameter(Token thisKeyword) { | |
| 1629 Expression name = popNode(); | |
| 1630 if (thisKeyword != null) { | |
| 1631 Identifier thisIdentifier = new Identifier(thisKeyword); | |
| 1632 if (name.asSend() == null) { | |
| 1633 name = new Send(thisIdentifier, name); | |
| 1634 } else { | |
| 1635 name = name.asSend().copyWithReceiver(thisIdentifier, false); | |
| 1636 } | |
| 1637 } | |
| 1638 TypeAnnotation type = popNode(); | |
| 1639 Modifiers modifiers = popNode(); | |
| 1640 NodeList metadata = popNode(); | |
| 1641 pushNode(new VariableDefinitions.forParameter( | |
| 1642 metadata, type, modifiers, new NodeList.singleton(name))); | |
| 1643 } | |
| 1644 | |
| 1645 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
| 1646 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
| 1647 } | |
| 1648 | |
| 1649 void handleNoFormalParameters(Token token) { | |
| 1650 pushNode(null); | |
| 1651 } | |
| 1652 | |
| 1653 void endArguments(int count, Token beginToken, Token endToken) { | |
| 1654 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
| 1655 } | |
| 1656 | |
| 1657 void handleNoArguments(Token token) { | |
| 1658 pushNode(null); | |
| 1659 } | |
| 1660 | |
| 1661 void endConstructorReference(Token start, Token periodBeforeName, | |
| 1662 Token endToken) { | |
| 1663 Identifier name = null; | |
| 1664 if (periodBeforeName != null) { | |
| 1665 name = popNode(); | |
| 1666 } | |
| 1667 NodeList typeArguments = popNode(); | |
| 1668 Node classReference = popNode(); | |
| 1669 if (typeArguments != null) { | |
| 1670 classReference = new TypeAnnotation(classReference, typeArguments); | |
| 1671 } else { | |
| 1672 Identifier identifier = classReference.asIdentifier(); | |
| 1673 Send send = classReference.asSend(); | |
| 1674 if (identifier != null) { | |
| 1675 // TODO(ahe): Should be: | |
| 1676 // classReference = new Send(null, identifier); | |
| 1677 classReference = identifier; | |
| 1678 } else if (send != null) { | |
| 1679 classReference = send; | |
| 1680 } else { | |
| 1681 internalError(node: classReference); | |
| 1682 } | |
| 1683 } | |
| 1684 Node constructor = classReference; | |
| 1685 if (name != null) { | |
| 1686 // Either typeName<args>.name or x.y.name. | |
| 1687 constructor = new Send(classReference, name); | |
| 1688 } | |
| 1689 pushNode(constructor); | |
| 1690 } | |
| 1691 | |
| 1692 void endRedirectingFactoryBody(Token beginToken, | |
| 1693 Token endToken) { | |
| 1694 pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode())); | |
| 1695 } | |
| 1696 | |
| 1697 void endReturnStatement(bool hasExpression, | |
| 1698 Token beginToken, Token endToken) { | |
| 1699 Expression expression = hasExpression ? popNode() : null; | |
| 1700 pushNode(new Return(beginToken, endToken, expression)); | |
| 1701 } | |
| 1702 | |
| 1703 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { | |
| 1704 Expression expression = popNode(); | |
| 1705 pushNode(new Yield(yieldToken, starToken, expression, endToken)); | |
| 1706 } | |
| 1707 | |
| 1708 void endExpressionStatement(Token token) { | |
| 1709 pushNode(new ExpressionStatement(popNode(), token)); | |
| 1710 } | |
| 1711 | |
| 1712 void handleOnError(Token token, var errorInformation) { | |
| 1713 listener.internalError(token, "'${token.value}': ${errorInformation}"); | |
| 1714 } | |
| 1715 | |
| 1716 Token expectedFunctionBody(Token token) { | |
| 1717 if (identical(token.stringValue, 'native')) { | |
| 1718 return native.handleNativeFunctionBody(this, token); | |
| 1719 } else if (token is ErrorToken) { | |
| 1720 pushNode(null); | |
| 1721 reportErrorToken(token); | |
| 1722 } else { | |
| 1723 reportFatalError(token, | |
| 1724 "Expected a function body, but got '${token.value}'."); | |
| 1725 } | |
| 1726 return skipToEof(token); | |
| 1727 } | |
| 1728 | |
| 1729 Token expectedClassBody(Token token) { | |
| 1730 if (token is ErrorToken) { | |
| 1731 reportErrorToken(token); | |
| 1732 return skipToEof(token); | |
| 1733 } else { | |
| 1734 reportFatalError(token, | |
| 1735 "Expected a class body, but got '${token.value}'."); | |
| 1736 return skipToEof(token); | |
| 1737 } | |
| 1738 } | |
| 1739 | |
| 1740 void handleLiteralInt(Token token) { | |
| 1741 pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e))); | |
| 1742 } | |
| 1743 | |
| 1744 void handleLiteralDouble(Token token) { | |
| 1745 pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e))); | |
| 1746 } | |
| 1747 | |
| 1748 void handleLiteralBool(Token token) { | |
| 1749 pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e))); | |
| 1750 } | |
| 1751 | |
| 1752 void handleLiteralNull(Token token) { | |
| 1753 pushNode(new LiteralNull(token)); | |
| 1754 } | |
| 1755 | |
| 1756 void endLiteralSymbol(Token hashToken, int identifierCount) { | |
| 1757 NodeList identifiers = makeNodeList(identifierCount, null, null, '.'); | |
| 1758 pushNode(new LiteralSymbol(hashToken, identifiers)); | |
| 1759 } | |
| 1760 | |
| 1761 void handleBinaryExpression(Token token) { | |
| 1762 Node argument = popNode(); | |
| 1763 Node receiver = popNode(); | |
| 1764 String tokenString = token.stringValue; | |
| 1765 if (identical(tokenString, '.') || | |
| 1766 identical(tokenString, '..') || | |
| 1767 identical(tokenString, '?.')) { | |
| 1768 Send argumentSend = argument.asSend(); | |
| 1769 if (argumentSend == null) { | |
| 1770 // TODO(ahe): The parser should diagnose this problem, not | |
| 1771 // this listener. | |
| 1772 reportFatalError(argument, | |
| 1773 'Expected an identifier.'); | |
| 1774 } | |
| 1775 if (argumentSend.receiver != null) internalError(node: argument); | |
| 1776 if (argument is SendSet) internalError(node: argument); | |
| 1777 pushNode(argument.asSend().copyWithReceiver(receiver, | |
| 1778 identical(tokenString, '?.'))); | |
| 1779 } else { | |
| 1780 NodeList arguments = new NodeList.singleton(argument); | |
| 1781 pushNode(new Send(receiver, new Operator(token), arguments)); | |
| 1782 } | |
| 1783 if (identical(tokenString, '===')) { | |
| 1784 listener.reportError(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ, | |
| 1785 {'lhs': receiver, 'rhs': argument}); | |
| 1786 } | |
| 1787 if (identical(tokenString, '!==')) { | |
| 1788 listener.reportError(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ, | |
| 1789 {'lhs': receiver, 'rhs': argument}); | |
| 1790 } | |
| 1791 } | |
| 1792 | |
| 1793 void beginCascade(Token token) { | |
| 1794 pushNode(new CascadeReceiver(popNode(), token)); | |
| 1795 } | |
| 1796 | |
| 1797 void endCascade() { | |
| 1798 pushNode(new Cascade(popNode())); | |
| 1799 } | |
| 1800 | |
| 1801 void handleAsOperator(Token operathor, Token endToken) { | |
| 1802 TypeAnnotation type = popNode(); | |
| 1803 Expression expression = popNode(); | |
| 1804 NodeList arguments = new NodeList.singleton(type); | |
| 1805 pushNode(new Send(expression, new Operator(operathor), arguments)); | |
| 1806 } | |
| 1807 | |
| 1808 void handleAssignmentExpression(Token token) { | |
| 1809 Node arg = popNode(); | |
| 1810 Node node = popNode(); | |
| 1811 Send send = node.asSend(); | |
| 1812 if (send == null || !(send.isPropertyAccess || send.isIndex)) { | |
| 1813 reportNotAssignable(node); | |
| 1814 } | |
| 1815 if (send.asSendSet() != null) internalError(node: send); | |
| 1816 NodeList arguments; | |
| 1817 if (send.isIndex) { | |
| 1818 Link<Node> link = const Link<Node>().prepend(arg); | |
| 1819 link = link.prepend(send.arguments.head); | |
| 1820 arguments = new NodeList(null, link); | |
| 1821 } else { | |
| 1822 arguments = new NodeList.singleton(arg); | |
| 1823 } | |
| 1824 Operator op = new Operator(token); | |
| 1825 pushNode(new SendSet(send.receiver, send.selector, op, arguments, | |
| 1826 send.isConditional)); | |
| 1827 } | |
| 1828 | |
| 1829 void reportNotAssignable(Node node) { | |
| 1830 // TODO(ahe): The parser should diagnose this problem, not this | |
| 1831 // listener. | |
| 1832 reportFatalError(node, | |
| 1833 'Not assignable.'); | |
| 1834 } | |
| 1835 | |
| 1836 void handleConditionalExpression(Token question, Token colon) { | |
| 1837 Node elseExpression = popNode(); | |
| 1838 Node thenExpression = popNode(); | |
| 1839 Node condition = popNode(); | |
| 1840 pushNode(new Conditional( | |
| 1841 condition, thenExpression, elseExpression, question, colon)); | |
| 1842 } | |
| 1843 | |
| 1844 void endSend(Token token) { | |
| 1845 NodeList arguments = popNode(); | |
| 1846 Node selector = popNode(); | |
| 1847 // TODO(ahe): Handle receiver. | |
| 1848 pushNode(new Send(null, selector, arguments)); | |
| 1849 } | |
| 1850 | |
| 1851 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
| 1852 if (count == 0 && beginToken == null) { | |
| 1853 pushNode(new EmptyStatement(endToken)); | |
| 1854 } else { | |
| 1855 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
| 1856 } | |
| 1857 } | |
| 1858 | |
| 1859 void handleAsyncModifier(Token asyncToken, Token starToken) { | |
| 1860 if (asyncToken != null) { | |
| 1861 pushNode(new AsyncModifier(asyncToken, starToken)); | |
| 1862 } else { | |
| 1863 pushNode(null); | |
| 1864 } | |
| 1865 } | |
| 1866 | |
| 1867 void skippedFunctionBody(Token token) { | |
| 1868 pushNode(new Block(new NodeList.empty())); | |
| 1869 } | |
| 1870 | |
| 1871 void handleNoFunctionBody(Token token) { | |
| 1872 pushNode(new EmptyStatement(token)); | |
| 1873 } | |
| 1874 | |
| 1875 void endFunction(Token getOrSet, Token endToken) { | |
| 1876 Statement body = popNode(); | |
| 1877 AsyncModifier asyncModifier = popNode(); | |
| 1878 NodeList initializers = popNode(); | |
| 1879 NodeList formals = popNode(); | |
| 1880 // The name can be an identifier or a send in case of named constructors. | |
| 1881 Expression name = popNode(); | |
| 1882 TypeAnnotation type = popNode(); | |
| 1883 Modifiers modifiers = popNode(); | |
| 1884 pushNode(new FunctionExpression(name, formals, body, type, | |
| 1885 modifiers, initializers, getOrSet, | |
| 1886 asyncModifier)); | |
| 1887 } | |
| 1888 | |
| 1889 void endFunctionDeclaration(Token endToken) { | |
| 1890 pushNode(new FunctionDeclaration(popNode())); | |
| 1891 } | |
| 1892 | |
| 1893 void endVariablesDeclaration(int count, Token endToken) { | |
| 1894 // TODO(ahe): Pick one name for this concept, either | |
| 1895 // VariablesDeclaration or VariableDefinitions. | |
| 1896 NodeList variables = makeNodeList(count, null, endToken, ","); | |
| 1897 TypeAnnotation type = popNode(); | |
| 1898 Modifiers modifiers = popNode(); | |
| 1899 pushNode(new VariableDefinitions(type, modifiers, variables)); | |
| 1900 } | |
| 1901 | |
| 1902 void endInitializer(Token assignmentOperator) { | |
| 1903 Expression initializer = popNode(); | |
| 1904 NodeList arguments = | |
| 1905 initializer == null ? null : new NodeList.singleton(initializer); | |
| 1906 Expression name = popNode(); | |
| 1907 Operator op = new Operator(assignmentOperator); | |
| 1908 pushNode(new SendSet(null, name, op, arguments)); | |
| 1909 } | |
| 1910 | |
| 1911 void endIfStatement(Token ifToken, Token elseToken) { | |
| 1912 Statement elsePart = (elseToken == null) ? null : popNode(); | |
| 1913 Statement thenPart = popNode(); | |
| 1914 ParenthesizedExpression condition = popNode(); | |
| 1915 pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken)); | |
| 1916 } | |
| 1917 | |
| 1918 void endForStatement(int updateExpressionCount, | |
| 1919 Token beginToken, Token endToken) { | |
| 1920 Statement body = popNode(); | |
| 1921 NodeList updates = makeNodeList(updateExpressionCount, null, null, ','); | |
| 1922 Statement condition = popNode(); | |
| 1923 Node initializer = popNode(); | |
| 1924 pushNode(new For(initializer, condition, updates, body, beginToken)); | |
| 1925 } | |
| 1926 | |
| 1927 void handleNoExpression(Token token) { | |
| 1928 pushNode(null); | |
| 1929 } | |
| 1930 | |
| 1931 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
| 1932 Token endToken) { | |
| 1933 Expression condition = popNode(); | |
| 1934 Statement body = popNode(); | |
| 1935 pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken)); | |
| 1936 } | |
| 1937 | |
| 1938 void endWhileStatement(Token whileKeyword, Token endToken) { | |
| 1939 Statement body = popNode(); | |
| 1940 Expression condition = popNode(); | |
| 1941 pushNode(new While(condition, body, whileKeyword)); | |
| 1942 } | |
| 1943 | |
| 1944 void endBlock(int count, Token beginToken, Token endToken) { | |
| 1945 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
| 1946 } | |
| 1947 | |
| 1948 void endThrowExpression(Token throwToken, Token endToken) { | |
| 1949 Expression expression = popNode(); | |
| 1950 pushNode(new Throw(expression, throwToken, endToken)); | |
| 1951 } | |
| 1952 | |
| 1953 void endAwaitExpression(Token awaitToken, Token endToken) { | |
| 1954 Expression expression = popNode(); | |
| 1955 pushNode(new Await(awaitToken, expression)); | |
| 1956 } | |
| 1957 | |
| 1958 void endRethrowStatement(Token throwToken, Token endToken) { | |
| 1959 pushNode(new Rethrow(throwToken, endToken)); | |
| 1960 if (identical(throwToken.stringValue, 'throw')) { | |
| 1961 listener.reportError(throwToken, | |
| 1962 MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP); | |
| 1963 } | |
| 1964 } | |
| 1965 | |
| 1966 void handleUnaryPrefixExpression(Token token) { | |
| 1967 pushNode(new Send.prefix(popNode(), new Operator(token))); | |
| 1968 } | |
| 1969 | |
| 1970 void handleSuperExpression(Token token) { | |
| 1971 pushNode(new Identifier(token)); | |
| 1972 } | |
| 1973 | |
| 1974 void handleThisExpression(Token token) { | |
| 1975 pushNode(new Identifier(token)); | |
| 1976 } | |
| 1977 | |
| 1978 void handleUnaryAssignmentExpression(Token token, bool isPrefix) { | |
| 1979 Node node = popNode(); | |
| 1980 Send send = node.asSend(); | |
| 1981 if (send == null) { | |
| 1982 reportNotAssignable(node); | |
| 1983 } | |
| 1984 if (!(send.isPropertyAccess || send.isIndex)) { | |
| 1985 reportNotAssignable(node); | |
| 1986 } | |
| 1987 if (send.asSendSet() != null) internalError(node: send); | |
| 1988 Node argument = null; | |
| 1989 if (send.isIndex) argument = send.arguments.head; | |
| 1990 Operator op = new Operator(token); | |
| 1991 | |
| 1992 if (isPrefix) { | |
| 1993 pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument, | |
| 1994 send.isConditional)); | |
| 1995 } else { | |
| 1996 pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument, | |
| 1997 send.isConditional)); | |
| 1998 } | |
| 1999 } | |
| 2000 | |
| 2001 void handleUnaryPostfixAssignmentExpression(Token token) { | |
| 2002 handleUnaryAssignmentExpression(token, false); | |
| 2003 } | |
| 2004 | |
| 2005 void handleUnaryPrefixAssignmentExpression(Token token) { | |
| 2006 handleUnaryAssignmentExpression(token, true); | |
| 2007 } | |
| 2008 | |
| 2009 void endInitializers(int count, Token beginToken, Token endToken) { | |
| 2010 pushNode(makeNodeList(count, beginToken, null, ',')); | |
| 2011 } | |
| 2012 | |
| 2013 void handleNoInitializers() { | |
| 2014 pushNode(null); | |
| 2015 } | |
| 2016 | |
| 2017 void endFields(int count, Token beginToken, Token endToken) { | |
| 2018 NodeList variables = makeNodeList(count, null, endToken, ","); | |
| 2019 TypeAnnotation type = popNode(); | |
| 2020 Modifiers modifiers = popNode(); | |
| 2021 pushNode(new VariableDefinitions(type, modifiers, variables)); | |
| 2022 } | |
| 2023 | |
| 2024 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
| 2025 Statement body = popNode(); | |
| 2026 AsyncModifier asyncModifier = popNode(); | |
| 2027 NodeList initializers = popNode(); | |
| 2028 NodeList formalParameters = popNode(); | |
| 2029 Expression name = popNode(); | |
| 2030 TypeAnnotation returnType = popNode(); | |
| 2031 Modifiers modifiers = popNode(); | |
| 2032 pushNode(new FunctionExpression(name, formalParameters, body, returnType, | |
| 2033 modifiers, initializers, getOrSet, | |
| 2034 asyncModifier)); | |
| 2035 } | |
| 2036 | |
| 2037 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
| 2038 Token endToken) { | |
| 2039 NodeList entries = makeNodeList(count, beginToken, endToken, ','); | |
| 2040 NodeList typeArguments = popNode(); | |
| 2041 pushNode(new LiteralMap(typeArguments, entries, constKeyword)); | |
| 2042 } | |
| 2043 | |
| 2044 void endLiteralMapEntry(Token colon, Token endToken) { | |
| 2045 Expression value = popNode(); | |
| 2046 Expression key = popNode(); | |
| 2047 pushNode(new LiteralMapEntry(key, colon, value)); | |
| 2048 } | |
| 2049 | |
| 2050 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
| 2051 Token endToken) { | |
| 2052 NodeList elements = makeNodeList(count, beginToken, endToken, ','); | |
| 2053 pushNode(new LiteralList(popNode(), elements, constKeyword)); | |
| 2054 } | |
| 2055 | |
| 2056 void handleIndexedExpression(Token openSquareBracket, | |
| 2057 Token closeSquareBracket) { | |
| 2058 NodeList arguments = | |
| 2059 makeNodeList(1, openSquareBracket, closeSquareBracket, null); | |
| 2060 Node receiver = popNode(); | |
| 2061 Token token = new StringToken.fromString(INDEX_INFO, '[]', | |
| 2062 openSquareBracket.charOffset); | |
| 2063 Node selector = new Operator(token); | |
| 2064 pushNode(new Send(receiver, selector, arguments)); | |
| 2065 } | |
| 2066 | |
| 2067 void handleNewExpression(Token token) { | |
| 2068 NodeList arguments = popNode(); | |
| 2069 Node name = popNode(); | |
| 2070 pushNode(new NewExpression(token, new Send(null, name, arguments))); | |
| 2071 } | |
| 2072 | |
| 2073 void handleConstExpression(Token token) { | |
| 2074 // [token] carries the 'const' information. | |
| 2075 handleNewExpression(token); | |
| 2076 } | |
| 2077 | |
| 2078 void handleOperator(Token token) { | |
| 2079 pushNode(new Operator(token)); | |
| 2080 } | |
| 2081 | |
| 2082 void handleOperatorName(Token operatorKeyword, Token token) { | |
| 2083 Operator op = new Operator(token); | |
| 2084 pushNode(new Send(new Identifier(operatorKeyword), op, null)); | |
| 2085 } | |
| 2086 | |
| 2087 void handleNamedArgument(Token colon) { | |
| 2088 Expression expression = popNode(); | |
| 2089 Identifier name = popNode(); | |
| 2090 pushNode(new NamedArgument(name, colon, expression)); | |
| 2091 } | |
| 2092 | |
| 2093 void endOptionalFormalParameters(int count, | |
| 2094 Token beginToken, Token endToken) { | |
| 2095 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 2096 } | |
| 2097 | |
| 2098 void handleFunctionTypedFormalParameter(Token endToken) { | |
| 2099 NodeList formals = popNode(); | |
| 2100 Identifier name = popNode(); | |
| 2101 TypeAnnotation returnType = popNode(); | |
| 2102 pushNode(null); // Signal "no type" to endFormalParameter. | |
| 2103 pushNode(new FunctionExpression(name, formals, null, returnType, | |
| 2104 Modifiers.EMPTY, null, null, null)); | |
| 2105 } | |
| 2106 | |
| 2107 void handleValuedFormalParameter(Token equals, Token token) { | |
| 2108 Expression defaultValue = popNode(); | |
| 2109 Expression parameterName = popNode(); | |
| 2110 pushNode(new SendSet(null, parameterName, new Operator(equals), | |
| 2111 new NodeList.singleton(defaultValue))); | |
| 2112 } | |
| 2113 | |
| 2114 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
| 2115 Block finallyBlock = null; | |
| 2116 if (finallyKeyword != null) { | |
| 2117 finallyBlock = popNode(); | |
| 2118 } | |
| 2119 NodeList catchBlocks = makeNodeList(catchCount, null, null, null); | |
| 2120 Block tryBlock = popNode(); | |
| 2121 pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock, | |
| 2122 tryKeyword, finallyKeyword)); | |
| 2123 } | |
| 2124 | |
| 2125 void handleCaseMatch(Token caseKeyword, Token colon) { | |
| 2126 pushNode(new CaseMatch(caseKeyword, popNode(), colon)); | |
| 2127 } | |
| 2128 | |
| 2129 void handleCatchBlock(Token onKeyword, Token catchKeyword) { | |
| 2130 Block block = popNode(); | |
| 2131 NodeList formals = catchKeyword != null? popNode(): null; | |
| 2132 TypeAnnotation type = onKeyword != null ? popNode() : null; | |
| 2133 pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword)); | |
| 2134 } | |
| 2135 | |
| 2136 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
| 2137 NodeList cases = popNode(); | |
| 2138 ParenthesizedExpression expression = popNode(); | |
| 2139 pushNode(new SwitchStatement(expression, cases, switchKeyword)); | |
| 2140 } | |
| 2141 | |
| 2142 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
| 2143 Link<Node> caseNodes = const Link<Node>(); | |
| 2144 while (caseCount > 0) { | |
| 2145 SwitchCase switchCase = popNode(); | |
| 2146 caseNodes = caseNodes.prepend(switchCase); | |
| 2147 caseCount--; | |
| 2148 } | |
| 2149 pushNode(new NodeList(beginToken, caseNodes, endToken, null)); | |
| 2150 } | |
| 2151 | |
| 2152 void handleSwitchCase(int labelCount, int caseCount, | |
| 2153 Token defaultKeyword, int statementCount, | |
| 2154 Token firstToken, Token endToken) { | |
| 2155 NodeList statements = makeNodeList(statementCount, null, null, null); | |
| 2156 NodeList labelsAndCases = | |
| 2157 makeNodeList(labelCount + caseCount, null, null, null); | |
| 2158 pushNode(new SwitchCase(labelsAndCases, defaultKeyword, statements, | |
| 2159 firstToken)); | |
| 2160 } | |
| 2161 | |
| 2162 void handleBreakStatement(bool hasTarget, | |
| 2163 Token breakKeyword, Token endToken) { | |
| 2164 Identifier target = null; | |
| 2165 if (hasTarget) { | |
| 2166 target = popNode(); | |
| 2167 } | |
| 2168 pushNode(new BreakStatement(target, breakKeyword, endToken)); | |
| 2169 } | |
| 2170 | |
| 2171 void handleContinueStatement(bool hasTarget, | |
| 2172 Token continueKeyword, Token endToken) { | |
| 2173 Identifier target = null; | |
| 2174 if (hasTarget) { | |
| 2175 target = popNode(); | |
| 2176 } | |
| 2177 pushNode(new ContinueStatement(target, continueKeyword, endToken)); | |
| 2178 } | |
| 2179 | |
| 2180 void handleEmptyStatement(Token token) { | |
| 2181 pushNode(new EmptyStatement(token)); | |
| 2182 } | |
| 2183 | |
| 2184 void endFactoryMethod(Token beginToken, Token endToken) { | |
| 2185 super.endFactoryMethod(beginToken, endToken); | |
| 2186 Statement body = popNode(); | |
| 2187 AsyncModifier asyncModifier = popNode(); | |
| 2188 NodeList formals = popNode(); | |
| 2189 Node name = popNode(); | |
| 2190 | |
| 2191 // TODO(ahe): Move this parsing to the parser. | |
| 2192 int modifierCount = 0; | |
| 2193 Token modifier = beginToken; | |
| 2194 if (modifier.stringValue == "external") { | |
| 2195 handleModifier(modifier); | |
| 2196 modifierCount++; | |
| 2197 modifier = modifier.next; | |
| 2198 } | |
| 2199 if (modifier.stringValue == "const") { | |
| 2200 handleModifier(modifier); | |
| 2201 modifierCount++; | |
| 2202 modifier = modifier.next; | |
| 2203 } | |
| 2204 assert(modifier.stringValue == "factory"); | |
| 2205 handleModifier(modifier); | |
| 2206 modifierCount++; | |
| 2207 handleModifiers(modifierCount); | |
| 2208 Modifiers modifiers = popNode(); | |
| 2209 | |
| 2210 pushNode(new FunctionExpression(name, formals, body, null, | |
| 2211 modifiers, null, null, asyncModifier)); | |
| 2212 } | |
| 2213 | |
| 2214 void endForIn(Token awaitToken, Token forToken, | |
| 2215 Token inKeyword, Token endToken) { | |
| 2216 Statement body = popNode(); | |
| 2217 Expression expression = popNode(); | |
| 2218 Node declaredIdentifier = popNode(); | |
| 2219 if (awaitToken == null) { | |
| 2220 pushNode(new SyncForIn(declaredIdentifier, expression, body, | |
| 2221 forToken, inKeyword)); | |
| 2222 } else { | |
| 2223 pushNode(new AsyncForIn(declaredIdentifier, expression, body, awaitToken, | |
| 2224 forToken, inKeyword)); | |
| 2225 } | |
| 2226 } | |
| 2227 | |
| 2228 void endMetadataStar(int count, bool forParameter) { | |
| 2229 // TODO(johnniwinther): Handle metadata for all node kinds. | |
| 2230 if (forParameter) { | |
| 2231 if (0 == count) { | |
| 2232 pushNode(null); | |
| 2233 } else { | |
| 2234 pushNode(makeNodeList(count, null, null, ' ')); | |
| 2235 } | |
| 2236 } | |
| 2237 } | |
| 2238 | |
| 2239 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | |
| 2240 NodeList arguments = popNode(); | |
| 2241 if (arguments == null) { | |
| 2242 // This is a constant expression. | |
| 2243 Identifier name; | |
| 2244 if (periodBeforeName != null) { | |
| 2245 name = popNode(); | |
| 2246 } | |
| 2247 NodeList typeArguments = popNode(); | |
| 2248 Node receiver = popNode(); | |
| 2249 if (typeArguments != null) { | |
| 2250 receiver = new TypeAnnotation(receiver, typeArguments); | |
| 2251 recoverableError(typeArguments, | |
| 2252 'Type arguments are not allowed here.'); | |
| 2253 } else { | |
| 2254 Identifier identifier = receiver.asIdentifier(); | |
| 2255 Send send = receiver.asSend(); | |
| 2256 if (identifier != null) { | |
| 2257 receiver = new Send(null, identifier); | |
| 2258 } else if (send == null) { | |
| 2259 internalError(node: receiver); | |
| 2260 } | |
| 2261 } | |
| 2262 Send send = receiver; | |
| 2263 if (name != null) { | |
| 2264 send = new Send(receiver, name); | |
| 2265 } | |
| 2266 pushNode(new Metadata(beginToken, send)); | |
| 2267 } else { | |
| 2268 // This is a const constructor call. | |
| 2269 endConstructorReference(beginToken, periodBeforeName, endToken); | |
| 2270 Node constructor = popNode(); | |
| 2271 pushNode(new Metadata(beginToken, | |
| 2272 new NewExpression(null, | |
| 2273 new Send(null, constructor, arguments)))); | |
| 2274 } | |
| 2275 } | |
| 2276 | |
| 2277 void handleAssertStatement(Token assertKeyword, Token semicolonToken) { | |
| 2278 NodeList arguments = popNode(); | |
| 2279 Node selector = new Identifier(assertKeyword); | |
| 2280 Node send = new Send(null, selector, arguments); | |
| 2281 pushNode(new ExpressionStatement(send, semicolonToken)); | |
| 2282 } | |
| 2283 | |
| 2284 void endUnnamedFunction(Token token) { | |
| 2285 Statement body = popNode(); | |
| 2286 AsyncModifier asyncModifier = popNode(); | |
| 2287 NodeList formals = popNode(); | |
| 2288 pushNode(new FunctionExpression(null, formals, body, null, | |
| 2289 Modifiers.EMPTY, null, null, | |
| 2290 asyncModifier)); | |
| 2291 } | |
| 2292 | |
| 2293 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
| 2294 TypeAnnotation type = popNode(); | |
| 2295 Expression expression = popNode(); | |
| 2296 Node argument; | |
| 2297 if (not != null) { | |
| 2298 argument = new Send.prefix(type, new Operator(not)); | |
| 2299 } else { | |
| 2300 argument = type; | |
| 2301 } | |
| 2302 | |
| 2303 NodeList arguments = new NodeList.singleton(argument); | |
| 2304 pushNode(new Send(expression, new Operator(operathor), arguments)); | |
| 2305 } | |
| 2306 | |
| 2307 void handleLabel(Token colon) { | |
| 2308 Identifier name = popNode(); | |
| 2309 pushNode(new Label(name, colon)); | |
| 2310 } | |
| 2311 | |
| 2312 void endLabeledStatement(int labelCount) { | |
| 2313 Statement statement = popNode(); | |
| 2314 NodeList labels = makeNodeList(labelCount, null, null, null); | |
| 2315 pushNode(new LabeledStatement(labels, statement)); | |
| 2316 } | |
| 2317 | |
| 2318 void log(message) { | |
| 2319 listener.log(message); | |
| 2320 } | |
| 2321 | |
| 2322 void internalError({Token token, Node node}) { | |
| 2323 // TODO(ahe): This should call listener.internalError. | |
| 2324 Spannable spannable = (token == null) ? node : token; | |
| 2325 throw new SpannableAssertionFailure(spannable, 'Internal error in parser.'); | |
| 2326 } | |
| 2327 } | |
| 2328 | 64 |
| 2329 abstract class PartialElement implements DeclarationSite { | 65 abstract class PartialElement implements DeclarationSite { |
| 2330 Token beginToken; | 66 Token beginToken; |
| 2331 Token endToken; | 67 Token endToken; |
| 2332 | 68 |
| 2333 bool hasParseError = false; | 69 bool hasParseError = false; |
| 2334 | 70 |
| 2335 bool get isErroneous => hasParseError; | 71 bool get isErroneous => hasParseError; |
| 2336 | 72 |
| 2337 DeclarationSite get declarationSite => this; | 73 DeclarationSite get declarationSite => this; |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2608 bool hasParseError = false; | 344 bool hasParseError = false; |
| 2609 | 345 |
| 2610 PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken); | 346 PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken); |
| 2611 | 347 |
| 2612 bool get isErroneous => hasParseError; | 348 bool get isErroneous => hasParseError; |
| 2613 | 349 |
| 2614 DeclarationSite get declarationSite => this; | 350 DeclarationSite get declarationSite => this; |
| 2615 | 351 |
| 2616 Token get endToken { | 352 Token get endToken { |
| 2617 Token token = beginToken; | 353 Token token = beginToken; |
| 2618 while (token.kind != EOF_TOKEN) { | 354 while (token.kind != Tokens.EOF_TOKEN) { |
| 2619 if (identical(token.next, tokenAfterEndToken)) break; | 355 if (identical(token.next, tokenAfterEndToken)) break; |
| 2620 token = token.next; | 356 token = token.next; |
| 2621 } | 357 } |
| 2622 assert(token != null); | 358 assert(token != null); |
| 2623 return token; | 359 return token; |
| 2624 } | 360 } |
| 2625 | 361 |
| 2626 void set endToken(_) { | 362 void set endToken(_) { |
| 2627 throw new UnsupportedError("endToken="); | 363 throw new UnsupportedError("endToken="); |
| 2628 } | 364 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2643 } | 379 } |
| 2644 | 380 |
| 2645 bool get hasNode => cachedNode != null; | 381 bool get hasNode => cachedNode != null; |
| 2646 | 382 |
| 2647 Node get node { | 383 Node get node { |
| 2648 assert(invariant(this, hasNode)); | 384 assert(invariant(this, hasNode)); |
| 2649 return cachedNode; | 385 return cachedNode; |
| 2650 } | 386 } |
| 2651 } | 387 } |
| 2652 | 388 |
| 389 class PartialClassElement extends ClassElementX with PartialElement { | |
|
Johnni Winther
2015/09/02 13:14:41
Moved from class_element_parser.dart
| |
| 390 ClassNode cachedNode; | |
| 391 | |
| 392 PartialClassElement(String name, | |
| 393 Token beginToken, | |
| 394 Token endToken, | |
| 395 Element enclosing, | |
| 396 int id) | |
| 397 : super(name, enclosing, id, STATE_NOT_STARTED) { | |
| 398 this.beginToken = beginToken; | |
| 399 this.endToken = endToken; | |
| 400 } | |
| 401 | |
| 402 void set supertypeLoadState(int state) { | |
| 403 assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1); | |
| 404 assert(state <= STATE_DONE); | |
| 405 super.supertypeLoadState = state; | |
| 406 } | |
| 407 | |
| 408 void set resolutionState(int state) { | |
| 409 assert(state == STATE_NOT_STARTED || state == resolutionState + 1); | |
| 410 assert(state <= STATE_DONE); | |
| 411 super.resolutionState = state; | |
| 412 } | |
| 413 | |
| 414 bool get hasNode => cachedNode != null; | |
| 415 | |
| 416 ClassNode get node { | |
| 417 assert(invariant(this, cachedNode != null, | |
| 418 message: "Node has not been computed for $this.")); | |
| 419 return cachedNode; | |
| 420 } | |
| 421 | |
| 422 ClassNode parseNode(Compiler compiler) { | |
| 423 if (cachedNode != null) return cachedNode; | |
| 424 compiler.withCurrentElement(this, () { | |
| 425 compiler.parser.measure(() { | |
| 426 MemberListener listener = new MemberListener(compiler, this); | |
| 427 Parser parser = new ClassElementParser(listener); | |
| 428 try { | |
| 429 Token token = parser.parseTopLevelDeclaration(beginToken); | |
| 430 assert(identical(token, endToken.next)); | |
| 431 cachedNode = listener.popNode(); | |
| 432 assert( | |
| 433 invariant( | |
| 434 beginToken, listener.nodes.isEmpty, | |
| 435 message: "Non-empty listener stack: ${listener.nodes}")); | |
| 436 } on ParserError { | |
| 437 // TODO(ahe): Often, a ParserError is thrown while parsing the class | |
| 438 // body. This means that the stack actually contains most of the | |
| 439 // information synthesized below. Consider rewriting the parser so | |
| 440 // endClassDeclaration is called before parsing the class body. | |
| 441 Identifier name = new Identifier(findMyName(beginToken)); | |
| 442 NodeList typeParameters = null; | |
| 443 Node supertype = null; | |
| 444 NodeList interfaces = listener.makeNodeList(0, null, null, ","); | |
| 445 Token extendsKeyword = null; | |
| 446 NodeList body = listener.makeNodeList(0, beginToken, endToken, null); | |
| 447 cachedNode = new ClassNode( | |
| 448 Modifiers.EMPTY, name, typeParameters, supertype, interfaces, | |
| 449 beginToken, extendsKeyword, body, endToken); | |
| 450 hasParseError = true; | |
| 451 } | |
| 452 }); | |
| 453 compiler.patchParser.measure(() { | |
| 454 if (isPatched) { | |
| 455 // TODO(lrn): Perhaps extract functionality so it doesn't | |
| 456 // need compiler. | |
| 457 compiler.patchParser.parsePatchClassNode(patch); | |
| 458 } | |
| 459 }); | |
| 460 }); | |
| 461 return cachedNode; | |
| 462 } | |
| 463 | |
| 464 Token get position => beginToken; | |
| 465 | |
| 466 // TODO(johnniwinther): Ensure that modifiers are always available. | |
| 467 Modifiers get modifiers => | |
| 468 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY; | |
| 469 | |
| 470 accept(ElementVisitor visitor, arg) { | |
| 471 return visitor.visitClassElement(this, arg); | |
| 472 } | |
| 473 | |
| 474 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) { | |
| 475 return new PartialClassElement(name, beginToken, endToken, enclosing, id); | |
| 476 } | |
| 477 } | |
| 478 | |
| 2653 Node parse( | 479 Node parse( |
| 2654 DiagnosticListener diagnosticListener, | 480 DiagnosticListener diagnosticListener, |
| 2655 ElementX element, | 481 ElementX element, |
| 2656 PartialElement partial, | 482 PartialElement partial, |
| 2657 doParse(Parser parser)) { | 483 doParse(Parser parser)) { |
| 2658 CompilationUnitElement unit = element.compilationUnit; | 484 CompilationUnitElement unit = element.compilationUnit; |
| 2659 NodeListener listener = new NodeListener(diagnosticListener, unit); | 485 NodeListener listener = new NodeListener(diagnosticListener, unit); |
| 2660 listener.memberErrors = listener.memberErrors.prepend(false); | 486 listener.memberErrors = listener.memberErrors.prepend(false); |
| 2661 try { | 487 try { |
| 2662 if (partial.hasParseError) { | 488 if (partial.hasParseError) { |
| 2663 listener.suppressParseErrors = true; | 489 listener.suppressParseErrors = true; |
| 2664 } | 490 } |
| 2665 doParse(new Parser(listener)); | 491 doParse(new Parser(listener)); |
| 2666 } on ParserError catch (e) { | 492 } on ParserError catch (e) { |
| 2667 partial.hasParseError = true; | 493 partial.hasParseError = true; |
| 2668 return new ErrorNode(element.position, e.reason); | 494 return new ErrorNode(element.position, e.reason); |
| 2669 } | 495 } |
| 2670 Node node = listener.popNode(); | 496 Node node = listener.popNode(); |
| 2671 assert(listener.nodes.isEmpty); | 497 assert(listener.nodes.isEmpty); |
| 2672 return node; | 498 return node; |
| 2673 } | 499 } |
| OLD | NEW |