| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 final bool VERBOSE = false; | |
| 6 | |
| 7 class Listener { | |
| 8 void beginArguments(Token token) { | |
| 9 } | |
| 10 | |
| 11 void endArguments(int count, Token beginToken, Token endToken) { | |
| 12 } | |
| 13 | |
| 14 void beginBlock(Token token) { | |
| 15 } | |
| 16 | |
| 17 void endBlock(int count, Token beginToken, Token endToken) { | |
| 18 } | |
| 19 | |
| 20 void beginClassBody(Token token) { | |
| 21 } | |
| 22 | |
| 23 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
| 24 } | |
| 25 | |
| 26 void beginClassDeclaration(Token token) { | |
| 27 } | |
| 28 | |
| 29 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 30 Token extendsKeyword, Token implementsKeyword, | |
| 31 Token endToken) { | |
| 32 } | |
| 33 | |
| 34 void beginDoWhileStatement(Token token) { | |
| 35 } | |
| 36 | |
| 37 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
| 38 Token endToken) { | |
| 39 } | |
| 40 | |
| 41 void beginExpressionStatement(Token token) { | |
| 42 } | |
| 43 | |
| 44 void endExpressionStatement(Token token) { | |
| 45 } | |
| 46 | |
| 47 void beginDefaultClause(Token token) { | |
| 48 } | |
| 49 | |
| 50 void handleNoDefaultClause(Token token) { | |
| 51 } | |
| 52 | |
| 53 void endDefaultClause(Token defaultKeyword) { | |
| 54 } | |
| 55 | |
| 56 void beginFactoryMethod(Token token) { | |
| 57 } | |
| 58 | |
| 59 void endFactoryMethod(Token factoryKeyword, Token periodBeforeName, | |
| 60 Token endToken) { | |
| 61 } | |
| 62 | |
| 63 void beginFormalParameter(Token token) { | |
| 64 } | |
| 65 | |
| 66 void endFormalParameter(Token token, Token thisKeyword) { | |
| 67 } | |
| 68 | |
| 69 void beginFormalParameters(Token token) { | |
| 70 } | |
| 71 | |
| 72 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
| 73 } | |
| 74 | |
| 75 void endFields(int count, Token beginToken, Token endToken) { | |
| 76 } | |
| 77 | |
| 78 void beginForStatement(Token token) { | |
| 79 } | |
| 80 | |
| 81 void endForStatement(int updateExpressionCount, | |
| 82 Token beginToken, Token endToken) { | |
| 83 } | |
| 84 | |
| 85 void endForInStatement(Token beginToken, Token inKeyword, Token endToken) { | |
| 86 } | |
| 87 | |
| 88 void beginFunction(Token token) { | |
| 89 } | |
| 90 | |
| 91 void endFunction(Token getOrSet, Token endToken) { | |
| 92 } | |
| 93 | |
| 94 void beginFunctionDeclaration(Token token) { | |
| 95 } | |
| 96 | |
| 97 void endFunctionDeclaration(Token token) { | |
| 98 } | |
| 99 | |
| 100 void beginFunctionBody(Token token) { | |
| 101 } | |
| 102 | |
| 103 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
| 104 } | |
| 105 | |
| 106 void handleNoFunctionBody(Token token) { | |
| 107 } | |
| 108 | |
| 109 void beginFunctionName(Token token) { | |
| 110 } | |
| 111 | |
| 112 void endFunctionName(Token token) { | |
| 113 } | |
| 114 | |
| 115 void beginFunctionTypeAlias(Token token) { | |
| 116 } | |
| 117 | |
| 118 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 119 } | |
| 120 | |
| 121 void beginIfStatement(Token token) { | |
| 122 } | |
| 123 | |
| 124 void endIfStatement(Token ifToken, Token elseToken) { | |
| 125 } | |
| 126 | |
| 127 void beginInitializedIdentifier(Token token) { | |
| 128 } | |
| 129 | |
| 130 void endInitializedIdentifier() { | |
| 131 } | |
| 132 | |
| 133 void beginInitializer(Token token) { | |
| 134 } | |
| 135 | |
| 136 void endInitializer(Token assignmentOperator) { | |
| 137 } | |
| 138 | |
| 139 void beginInitializers(Token token) { | |
| 140 } | |
| 141 | |
| 142 void endInitializers(int count, Token beginToken, Token endToken) { | |
| 143 } | |
| 144 | |
| 145 void handleNoInitializers() { | |
| 146 } | |
| 147 | |
| 148 void beginInterface(Token token) { | |
| 149 } | |
| 150 | |
| 151 void endInterface(int supertypeCount, Token interfaceKeyword, | |
| 152 Token extendsKeyword, Token endToken) { | |
| 153 } | |
| 154 | |
| 155 void beginLabeledStatement(Token token) { | |
| 156 } | |
| 157 | |
| 158 void endLabeledStatement(Token colon) { | |
| 159 } | |
| 160 | |
| 161 void beginLiteralMapEntry(Token token) { | |
| 162 } | |
| 163 | |
| 164 void endLiteralMapEntry(Token colon, Token endToken) { | |
| 165 } | |
| 166 | |
| 167 void beginLiteralString(Token token) { | |
| 168 } | |
| 169 | |
| 170 void endLiteralString(int interpolationCount) { | |
| 171 } | |
| 172 | |
| 173 void handleStringJuxtaposition(int literalCount) { | |
| 174 } | |
| 175 | |
| 176 void beginMember(Token token) { | |
| 177 } | |
| 178 | |
| 179 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
| 180 } | |
| 181 | |
| 182 void beginOptionalFormalParameters(Token token) { | |
| 183 } | |
| 184 | |
| 185 void endOptionalFormalParameters(int count, | |
| 186 Token beginToken, Token endToken) { | |
| 187 } | |
| 188 | |
| 189 void beginReturnStatement(Token token) { | |
| 190 } | |
| 191 | |
| 192 void endReturnStatement(bool hasExpression, | |
| 193 Token beginToken, Token endToken) { | |
| 194 } | |
| 195 | |
| 196 void beginScriptTag(Token token) { | |
| 197 } | |
| 198 | |
| 199 void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { | |
| 200 } | |
| 201 | |
| 202 void beginSend(Token token) { | |
| 203 } | |
| 204 | |
| 205 void endSend(Token token) { | |
| 206 } | |
| 207 | |
| 208 void beginSwitchStatement(Token token) { | |
| 209 } | |
| 210 | |
| 211 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
| 212 } | |
| 213 | |
| 214 void beginSwitchBlock(Token token) { | |
| 215 } | |
| 216 | |
| 217 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
| 218 } | |
| 219 | |
| 220 void beginThrowStatement(Token token) { | |
| 221 } | |
| 222 | |
| 223 void endThrowStatement(Token throwToken, Token endToken) { | |
| 224 } | |
| 225 | |
| 226 void endRethrowStatement(Token throwToken, Token endToken) { | |
| 227 } | |
| 228 | |
| 229 void beginTopLevelMember(Token token) { | |
| 230 } | |
| 231 | |
| 232 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 233 } | |
| 234 | |
| 235 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 236 } | |
| 237 | |
| 238 void beginTryStatement(Token token) { | |
| 239 } | |
| 240 | |
| 241 void handleCatchBlock(Token catchKeyword) { | |
| 242 } | |
| 243 | |
| 244 void handleFinallyBlock(Token finallyKeyword) { | |
| 245 } | |
| 246 | |
| 247 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
| 248 } | |
| 249 | |
| 250 void endType(Token beginToken, Token endToken) { | |
| 251 } | |
| 252 | |
| 253 void beginTypeArguments(Token token) { | |
| 254 } | |
| 255 | |
| 256 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
| 257 } | |
| 258 | |
| 259 void handleNoTypeArguments(Token token) { | |
| 260 } | |
| 261 | |
| 262 void beginTypeVariable(Token token) { | |
| 263 } | |
| 264 | |
| 265 void endTypeVariable(Token token) { | |
| 266 } | |
| 267 | |
| 268 void beginTypeVariables(Token token) { | |
| 269 } | |
| 270 | |
| 271 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
| 272 } | |
| 273 | |
| 274 void beginUnamedFunction(Token token) { | |
| 275 } | |
| 276 | |
| 277 void endUnamedFunction(Token token) { | |
| 278 } | |
| 279 | |
| 280 void beginVariablesDeclaration(Token token) { | |
| 281 } | |
| 282 | |
| 283 void endVariablesDeclaration(int count, Token endToken) { | |
| 284 } | |
| 285 | |
| 286 void beginWhileStatement(Token token) { | |
| 287 } | |
| 288 | |
| 289 void endWhileStatement(Token whileKeyword, Token endToken) { | |
| 290 } | |
| 291 | |
| 292 void handleAssignmentExpression(Token token) { | |
| 293 } | |
| 294 | |
| 295 void handleBinaryExpression(Token token) { | |
| 296 } | |
| 297 | |
| 298 void handleConditionalExpression(Token question, Token colon) { | |
| 299 } | |
| 300 | |
| 301 void handleConstExpression(Token token, bool named) { | |
| 302 } | |
| 303 | |
| 304 void handleFunctionTypedFormalParameter(Token token) { | |
| 305 } | |
| 306 | |
| 307 void handleIdentifier(Token token) { | |
| 308 } | |
| 309 | |
| 310 void handleIndexedExpression(Token openCurlyBracket, | |
| 311 Token closeCurlyBracket) { | |
| 312 } | |
| 313 | |
| 314 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
| 315 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. | |
| 316 } | |
| 317 | |
| 318 void handleLiteralBool(Token token) { | |
| 319 } | |
| 320 | |
| 321 void handleBreakStatement(bool hasTarget, | |
| 322 Token breakKeyword, Token endToken) { | |
| 323 } | |
| 324 | |
| 325 void handleContinueStatement(bool hasTarget, | |
| 326 Token continueKeyword, Token endToken) { | |
| 327 } | |
| 328 | |
| 329 void handleEmptyStatement(Token token) { | |
| 330 } | |
| 331 | |
| 332 /** Called with either the token containing a double literal, or | |
| 333 * an immediately preceding "unary plus" token. | |
| 334 */ | |
| 335 void handleLiteralDouble(Token token) { | |
| 336 } | |
| 337 | |
| 338 /** Called with either the token containing an integer literal, | |
| 339 * or an immediately preceding "unary plus" token. | |
| 340 */ | |
| 341 void handleLiteralInt(Token token) { | |
| 342 } | |
| 343 | |
| 344 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
| 345 Token endToken) { | |
| 346 } | |
| 347 | |
| 348 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
| 349 Token endToken) { | |
| 350 } | |
| 351 | |
| 352 void handleLiteralNull(Token token) { | |
| 353 } | |
| 354 | |
| 355 void handleModifier(Token token) { | |
| 356 } | |
| 357 | |
| 358 void handleModifiers(int count) { | |
| 359 } | |
| 360 | |
| 361 void handleNamedArgument(Token colon) { | |
| 362 } | |
| 363 | |
| 364 void handleNewExpression(Token token, bool named) { | |
| 365 } | |
| 366 | |
| 367 void handleNoArguments(Token token) { | |
| 368 } | |
| 369 | |
| 370 void handleNoExpression(Token token) { | |
| 371 } | |
| 372 | |
| 373 void handleNoType(Token token) { | |
| 374 } | |
| 375 | |
| 376 void handleNoTypeVariables(Token token) { | |
| 377 } | |
| 378 | |
| 379 void handleOperatorName(Token operatorKeyword, Token token) { | |
| 380 } | |
| 381 | |
| 382 void handleParenthesizedExpression(BeginGroupToken token) { | |
| 383 } | |
| 384 | |
| 385 void handleQualified(Token period) { | |
| 386 } | |
| 387 | |
| 388 void handleStringPart(Token token) { | |
| 389 } | |
| 390 | |
| 391 void handleSuperExpression(Token token) { | |
| 392 } | |
| 393 | |
| 394 void handleSwitchCase(Token labelToken, int expressionCount, | |
| 395 Token defaultKeyword, int statementCount, | |
| 396 Token firstToken, Token endToken) { | |
| 397 } | |
| 398 | |
| 399 void handleThisExpression(Token token) { | |
| 400 } | |
| 401 | |
| 402 void handleUnaryPostfixAssignmentExpression(Token token) { | |
| 403 } | |
| 404 | |
| 405 void handleUnaryPrefixExpression(Token token) { | |
| 406 } | |
| 407 | |
| 408 void handleUnaryPrefixAssignmentExpression(Token token) { | |
| 409 } | |
| 410 | |
| 411 void handleValuedFormalParameter(Token equals, Token token) { | |
| 412 } | |
| 413 | |
| 414 void handleVoidKeyword(Token token) { | |
| 415 } | |
| 416 | |
| 417 Token expected(String string, Token token) { | |
| 418 error("expected '$string', but got '${token.slowToString()}'", token); | |
| 419 return skipToEof(token); | |
| 420 } | |
| 421 | |
| 422 void expectedIdentifier(Token token) { | |
| 423 error("expected identifier, but got '${token.slowToString()}'", token); | |
| 424 } | |
| 425 | |
| 426 Token expectedType(Token token) { | |
| 427 error("expected a type, but got '${token.slowToString()}'", token); | |
| 428 return skipToEof(token); | |
| 429 } | |
| 430 | |
| 431 Token expectedExpression(Token token) { | |
| 432 error("expected an expression, but got '${token.slowToString()}'", token); | |
| 433 return skipToEof(token); | |
| 434 } | |
| 435 | |
| 436 Token unexpected(Token token) { | |
| 437 error("unexpected token '${token.slowToString()}'", token); | |
| 438 return skipToEof(token); | |
| 439 } | |
| 440 | |
| 441 Token expectedBlockToSkip(Token token) { | |
| 442 error("expected a block, but got '${token.slowToString()}'", token); | |
| 443 return skipToEof(token); | |
| 444 } | |
| 445 | |
| 446 Token expectedFunctionBody(Token token) { | |
| 447 error("expected a function body, but got '${token.slowToString()}'", token); | |
| 448 return skipToEof(token); | |
| 449 } | |
| 450 | |
| 451 Token expectedClassBody(Token token) { | |
| 452 error("expected a class body, but got '${token.slowToString()}'", token); | |
| 453 return skipToEof(token); | |
| 454 } | |
| 455 | |
| 456 Token expectedClassBodyToSkip(Token token) { | |
| 457 error("expected a class body, but got '${token.slowToString()}'", token); | |
| 458 return skipToEof(token); | |
| 459 } | |
| 460 | |
| 461 skipToEof(Token token) { | |
| 462 while (token.info !== EOF_INFO) { | |
| 463 token = token.next; | |
| 464 } | |
| 465 return token; | |
| 466 } | |
| 467 | |
| 468 void recoverableError(String message, [Token token, Node node]) { | |
| 469 if (token === null && node !== null) { | |
| 470 token = node.getBeginToken(); | |
| 471 } | |
| 472 error(message, token); | |
| 473 } | |
| 474 | |
| 475 void error(String message, Token token) { | |
| 476 throw new ParserError("$message @ ${token.charOffset}"); | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 class ParserError { | |
| 481 final String reason; | |
| 482 ParserError(this.reason); | |
| 483 toString() => reason; | |
| 484 } | |
| 485 | |
| 486 /** | |
| 487 * A listener for parser events. | |
| 488 */ | |
| 489 class ElementListener extends Listener { | |
| 490 final DiagnosticListener listener; | |
| 491 final CompilationUnitElement compilationUnitElement; | |
| 492 final StringValidator stringValidator; | |
| 493 Link<StringQuoting> interpolationScope; | |
| 494 | |
| 495 Link<Node> nodes = const EmptyLink<Node>(); | |
| 496 | |
| 497 ElementListener(DiagnosticListener listener, | |
| 498 CompilationUnitElement this.compilationUnitElement) | |
| 499 : this.listener = listener, | |
| 500 stringValidator = new StringValidator(listener), | |
| 501 interpolationScope = const EmptyLink<StringQuoting>(); | |
| 502 | |
| 503 void pushQuoting(StringQuoting quoting) { | |
| 504 interpolationScope = interpolationScope.prepend(quoting); | |
| 505 } | |
| 506 | |
| 507 StringQuoting popQuoting() { | |
| 508 StringQuoting result = interpolationScope.head; | |
| 509 interpolationScope = interpolationScope.tail; | |
| 510 return result; | |
| 511 } | |
| 512 | |
| 513 LiteralString popLiteralString() { | |
| 514 StringNode node = popNode(); | |
| 515 // TODO(lrn): Handle interpolations in script tags. | |
| 516 if (node.isInterpolation) { | |
| 517 listener.cancel("String interpolation not supported in library tags", | |
| 518 node: node); | |
| 519 return null; | |
| 520 } | |
| 521 return node; | |
| 522 } | |
| 523 | |
| 524 void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { | |
| 525 StringNode prefix = null; | |
| 526 Identifier argumentName = null; | |
| 527 if (hasPrefix) { | |
| 528 prefix = popLiteralString(); | |
| 529 argumentName = popNode(); | |
| 530 } | |
| 531 StringNode firstArgument = popLiteralString(); | |
| 532 Identifier tag = popNode(); | |
| 533 compilationUnitElement.addTag(new ScriptTag(tag, firstArgument, | |
| 534 argumentName, prefix, | |
| 535 beginToken, endToken), | |
| 536 listener); | |
| 537 } | |
| 538 | |
| 539 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 540 Token extendsKeyword, Token implementsKeyword, | |
| 541 Token endToken) { | |
| 542 SourceString nativeName = native.checkForNativeClass(this); | |
| 543 NodeList interfaces = | |
| 544 makeNodeList(interfacesCount, implementsKeyword, null, ","); | |
| 545 TypeAnnotation supertype = popNode(); | |
| 546 NodeList typeParameters = popNode(); | |
| 547 Identifier name = popNode(); | |
| 548 ClassElement element = new PartialClassElement( | |
| 549 name.source, beginToken, endToken, compilationUnitElement); | |
| 550 element.nativeName = nativeName; | |
| 551 pushElement(element); | |
| 552 } | |
| 553 | |
| 554 void endDefaultClause(Token defaultKeyword) { | |
| 555 NodeList typeParameters = popNode(); | |
| 556 Node name = popNode(); | |
| 557 pushNode(new TypeAnnotation(name, typeParameters)); | |
| 558 } | |
| 559 | |
| 560 void handleNoDefaultClause(Token token) { | |
| 561 pushNode(null); | |
| 562 } | |
| 563 | |
| 564 void endInterface(int supertypeCount, Token interfaceKeyword, | |
| 565 Token extendsKeyword, Token endToken) { | |
| 566 // TODO(ahe): Record the defaultClause. | |
| 567 Node defaultClause = popNode(); | |
| 568 NodeList supertypes = | |
| 569 makeNodeList(supertypeCount, extendsKeyword, null, ","); | |
| 570 NodeList typeParameters = popNode(); | |
| 571 Identifier name = popNode(); | |
| 572 pushElement(new PartialClassElement(name.source, interfaceKeyword, | |
| 573 endToken, | |
| 574 compilationUnitElement)); | |
| 575 } | |
| 576 | |
| 577 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 578 NodeList typeVariables = popNode(); // TOOD(karlklose): do not throw away. | |
| 579 Identifier name = popNode(); | |
| 580 TypeAnnotation returnType = popNode(); | |
| 581 pushElement(new TypedefElement(name.source, compilationUnitElement, | |
| 582 typedefKeyword)); | |
| 583 } | |
| 584 | |
| 585 void handleVoidKeyword(Token token) { | |
| 586 pushNode(new TypeAnnotation(new Identifier(token), null)); | |
| 587 } | |
| 588 | |
| 589 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 590 Identifier name = popNode(); | |
| 591 Modifiers modifiers = popNode(); | |
| 592 ElementKind kind; | |
| 593 if (getOrSet === null) { | |
| 594 kind = ElementKind.FUNCTION; | |
| 595 } else if (getOrSet.stringValue === 'get') { | |
| 596 kind = ElementKind.GETTER; | |
| 597 } else if (getOrSet.stringValue === 'set') { | |
| 598 kind = ElementKind.SETTER; | |
| 599 } | |
| 600 pushElement(new PartialFunctionElement(name.source, beginToken, getOrSet, | |
| 601 endToken, kind, | |
| 602 modifiers, compilationUnitElement)); | |
| 603 } | |
| 604 | |
| 605 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 606 void buildFieldElement(SourceString name, Element fields) { | |
| 607 pushElement(new VariableElement( | |
| 608 name, fields, ElementKind.FIELD, compilationUnitElement)); | |
| 609 } | |
| 610 NodeList variables = makeNodeList(count, null, null, ","); | |
| 611 Modifiers modifiers = popNode(); | |
| 612 buildFieldElements(modifiers, variables, compilationUnitElement, | |
| 613 buildFieldElement, | |
| 614 beginToken, endToken); | |
| 615 } | |
| 616 | |
| 617 void buildFieldElements(Modifiers modifiers, | |
| 618 NodeList variables, | |
| 619 ContainerElement enclosingElement, | |
| 620 void buildFieldElement(SourceString name, | |
| 621 Element fields), | |
| 622 Token beginToken, Token endToken) { | |
| 623 Element fields = new PartialFieldListElement(beginToken, | |
| 624 endToken, | |
| 625 modifiers, | |
| 626 enclosingElement); | |
| 627 for (Link<Node> nodes = variables.nodes; !nodes.isEmpty(); | |
| 628 nodes = nodes.tail) { | |
| 629 Expression initializedIdentifier = nodes.head; | |
| 630 Identifier identifier = initializedIdentifier.asIdentifier(); | |
| 631 if (identifier === null) { | |
| 632 identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); | |
| 633 } | |
| 634 SourceString name = identifier.source; | |
| 635 buildFieldElement(name, fields); | |
| 636 } | |
| 637 } | |
| 638 | |
| 639 void handleIdentifier(Token token) { | |
| 640 pushNode(new Identifier(token)); | |
| 641 } | |
| 642 | |
| 643 void handleQualified(Token period) { | |
| 644 Identifier last = popNode(); | |
| 645 Identifier first = popNode(); | |
| 646 pushNode(new Send(first, last)); | |
| 647 } | |
| 648 | |
| 649 void handleNoType(Token token) { | |
| 650 pushNode(null); | |
| 651 } | |
| 652 | |
| 653 void endTypeVariable(Token token) { | |
| 654 TypeAnnotation bound = popNode(); | |
| 655 Identifier name = popNode(); | |
| 656 pushNode(new TypeVariable(name, bound)); | |
| 657 } | |
| 658 | |
| 659 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
| 660 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 661 } | |
| 662 | |
| 663 void handleNoTypeVariables(token) { | |
| 664 pushNode(null); | |
| 665 } | |
| 666 | |
| 667 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
| 668 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 669 } | |
| 670 | |
| 671 void handleNoTypeArguments(Token token) { | |
| 672 pushNode(null); | |
| 673 } | |
| 674 | |
| 675 void endType(Token beginToken, Token endToken) { | |
| 676 NodeList typeArguments = popNode(); | |
| 677 Expression typeName = popNode(); | |
| 678 pushNode(new TypeAnnotation(typeName, typeArguments)); | |
| 679 } | |
| 680 | |
| 681 void handleParenthesizedExpression(BeginGroupToken token) { | |
| 682 Expression expression = popNode(); | |
| 683 pushNode(new ParenthesizedExpression(expression, token)); | |
| 684 } | |
| 685 | |
| 686 void handleModifier(Token token) { | |
| 687 pushNode(new Identifier(token)); | |
| 688 } | |
| 689 | |
| 690 void handleModifiers(int count) { | |
| 691 NodeList nodes = makeNodeList(count, null, null, null); | |
| 692 pushNode(new Modifiers(nodes)); | |
| 693 } | |
| 694 | |
| 695 Token expected(String string, Token token) { | |
| 696 listener.cancel("expected '$string', but got '${token.slowToString()}'", | |
| 697 token: token); | |
| 698 return skipToEof(token); | |
| 699 } | |
| 700 | |
| 701 void expectedIdentifier(Token token) { | |
| 702 listener.cancel("expected identifier, but got '${token.slowToString()}'", | |
| 703 token: token); | |
| 704 pushNode(null); | |
| 705 } | |
| 706 | |
| 707 Token expectedType(Token token) { | |
| 708 listener.cancel("expected a type, but got '${token.slowToString()}'", | |
| 709 token: token); | |
| 710 pushNode(null); | |
| 711 return skipToEof(token); | |
| 712 } | |
| 713 | |
| 714 Token expectedExpression(Token token) { | |
| 715 listener.cancel("expected an expression, but got '${token.slowToString()}'", | |
| 716 token: token); | |
| 717 pushNode(null); | |
| 718 return skipToEof(token); | |
| 719 } | |
| 720 | |
| 721 Token unexpected(Token token) { | |
| 722 listener.cancel("unexpected token '${token.slowToString()}'", token: token); | |
| 723 return skipToEof(token); | |
| 724 } | |
| 725 | |
| 726 Token expectedBlockToSkip(Token token) { | |
| 727 if (token.stringValue === 'native') { | |
| 728 return native.handleNativeBlockToSkip(this, token); | |
| 729 } else { | |
| 730 return unexpected(token); | |
| 731 } | |
| 732 } | |
| 733 | |
| 734 Token expectedFunctionBody(Token token) { | |
| 735 String printString = token.slowToString(); | |
| 736 listener.cancel("expected a function body, but got '$printString'", | |
| 737 token: token); | |
| 738 return skipToEof(token); | |
| 739 } | |
| 740 | |
| 741 Token expectedClassBody(Token token) { | |
| 742 listener.cancel("expected a class body, but got '${token.slowToString()}'", | |
| 743 token: token); | |
| 744 return skipToEof(token); | |
| 745 } | |
| 746 | |
| 747 Token expectedClassBodyToSkip(Token token) { | |
| 748 if (token.stringValue === 'native') { | |
| 749 return native.handleNativeClassBodyToSkip(this, token); | |
| 750 } else { | |
| 751 return unexpected(token); | |
| 752 } | |
| 753 } | |
| 754 | |
| 755 void recoverableError(String message, [Token token, Node node]) { | |
| 756 listener.cancel(message, token: token, node: node); | |
| 757 } | |
| 758 | |
| 759 void pushElement(Element element) { | |
| 760 compilationUnitElement.addMember(element, listener); | |
| 761 } | |
| 762 | |
| 763 void pushNode(Node node) { | |
| 764 nodes = nodes.prepend(node); | |
| 765 if (VERBOSE) log("push $nodes"); | |
| 766 } | |
| 767 | |
| 768 Node popNode() { | |
| 769 assert(!nodes.isEmpty()); | |
| 770 Node node = nodes.head; | |
| 771 nodes = nodes.tail; | |
| 772 if (VERBOSE) log("pop $nodes"); | |
| 773 return node; | |
| 774 } | |
| 775 | |
| 776 Node peekNode() { | |
| 777 assert(!nodes.isEmpty()); | |
| 778 Node node = nodes.head; | |
| 779 if (VERBOSE) log("peek $node"); | |
| 780 return node; | |
| 781 } | |
| 782 | |
| 783 void log(message) { | |
| 784 print(message); | |
| 785 } | |
| 786 | |
| 787 NodeList makeNodeList(int count, Token beginToken, Token endToken, | |
| 788 String delimiter) { | |
| 789 Link<Node> nodes = const EmptyLink<Node>(); | |
| 790 for (; count > 0; --count) { | |
| 791 // This effectively reverses the order of nodes so they end up | |
| 792 // in correct (source) order. | |
| 793 nodes = nodes.prepend(popNode()); | |
| 794 } | |
| 795 SourceString sourceDelimiter = | |
| 796 (delimiter === null) ? null : new SourceString(delimiter); | |
| 797 return new NodeList(beginToken, nodes, endToken, sourceDelimiter); | |
| 798 } | |
| 799 | |
| 800 void beginLiteralString(Token token) { | |
| 801 SourceString source = token.value; | |
| 802 StringQuoting quoting = StringValidator.quotingFromString(source); | |
| 803 pushQuoting(quoting); | |
| 804 // Just wrap the token for now. At the end of the interpolation, | |
| 805 // when we know how many there are, go back and validate the tokens. | |
| 806 pushNode(new LiteralString(token, null)); | |
| 807 } | |
| 808 | |
| 809 void handleStringPart(Token token) { | |
| 810 // Just push an unvalidated token now, and replace it when we know the | |
| 811 // end of the interpolation. | |
| 812 pushNode(new LiteralString(token, null)); | |
| 813 } | |
| 814 | |
| 815 void endLiteralString(int count) { | |
| 816 StringQuoting quoting = popQuoting(); | |
| 817 | |
| 818 Link<StringInterpolationPart> parts = | |
| 819 const EmptyLink<StringInterpolationPart>(); | |
| 820 // Parts of the string interpolation are popped in reverse order, | |
| 821 // starting with the last literal string part. | |
| 822 bool isLast = true; | |
| 823 for (int i = 0; i < count; i++) { | |
| 824 LiteralString string = popNode(); | |
| 825 DartString validation = | |
| 826 stringValidator.validateInterpolationPart(string.token, quoting, | |
| 827 isFirst: false, | |
| 828 isLast: isLast); | |
| 829 // Replace the unvalidated LiteralString with a new LiteralString | |
| 830 // object that has the validation result included. | |
| 831 string = new LiteralString(string.token, validation); | |
| 832 Expression expression = popNode(); | |
| 833 parts = parts.prepend(new StringInterpolationPart(expression, string)); | |
| 834 isLast = false; | |
| 835 } | |
| 836 | |
| 837 LiteralString string = popNode(); | |
| 838 DartString validation = | |
| 839 stringValidator.validateInterpolationPart(string.token, quoting, | |
| 840 isFirst: true, | |
| 841 isLast: isLast); | |
| 842 string = new LiteralString(string.token, validation); | |
| 843 if (isLast) { | |
| 844 pushNode(string); | |
| 845 } else { | |
| 846 NodeList nodes = new NodeList(null, parts, null, null); | |
| 847 pushNode(new StringInterpolation(string, nodes)); | |
| 848 } | |
| 849 } | |
| 850 | |
| 851 void handleStringJuxtaposition(int stringCount) { | |
| 852 assert(stringCount != 0); | |
| 853 Expression accumulator = popNode(); | |
| 854 stringCount--; | |
| 855 while (stringCount > 0) { | |
| 856 Expression expression = popNode(); | |
| 857 accumulator = new StringJuxtaposition(expression, accumulator); | |
| 858 stringCount--; | |
| 859 } | |
| 860 pushNode(accumulator); | |
| 861 } | |
| 862 } | |
| 863 | |
| 864 class NodeListener extends ElementListener { | |
| 865 NodeListener(DiagnosticListener listener, CompilationUnitElement element) | |
| 866 : super(listener, element); | |
| 867 | |
| 868 void endClassDeclaration(int interfacesCount, Token beginToken, | |
| 869 Token extendsKeyword, Token implementsKeyword, | |
| 870 Token endToken) { | |
| 871 NodeList body = popNode(); | |
| 872 NodeList interfaces = | |
| 873 makeNodeList(interfacesCount, implementsKeyword, null, ","); | |
| 874 TypeAnnotation supertype = popNode(); | |
| 875 NodeList typeParameters = popNode(); | |
| 876 Identifier name = popNode(); | |
| 877 pushNode(new ClassNode(name, typeParameters, supertype, interfaces, null, | |
| 878 beginToken, extendsKeyword, endToken)); | |
| 879 } | |
| 880 | |
| 881 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
| 882 NodeList formals = popNode(); | |
| 883 NodeList typeParameters = null; // TODO(ahe): Don't discard these. | |
| 884 Identifier name = popNode(); | |
| 885 TypeAnnotation returnType = popNode(); | |
| 886 pushNode(new Typedef(returnType, name, typeParameters, formals, | |
| 887 typedefKeyword, endToken)); | |
| 888 } | |
| 889 | |
| 890 void endInterface(int supertypeCount, Token interfaceKeyword, | |
| 891 Token extendsKeyword, Token endToken) { | |
| 892 NodeList body = popNode(); | |
| 893 TypeAnnotation defaultClause = popNode(); | |
| 894 NodeList supertypes = makeNodeList(supertypeCount, extendsKeyword, | |
| 895 null, ','); | |
| 896 NodeList typeParameters = popNode(); | |
| 897 Identifier name = popNode(); | |
| 898 pushNode(new ClassNode(name, typeParameters, null, supertypes, | |
| 899 defaultClause, interfaceKeyword, null, endToken)); | |
| 900 } | |
| 901 | |
| 902 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
| 903 pushNode(makeNodeList(memberCount, beginToken, endToken, null)); | |
| 904 } | |
| 905 | |
| 906 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 907 NodeList variables = makeNodeList(count, null, null, ","); | |
| 908 Modifiers modifiers = popNode(); | |
| 909 pushNode(new VariableDefinitions(null, modifiers, variables, endToken)); | |
| 910 } | |
| 911 | |
| 912 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
| 913 Statement body = popNode(); | |
| 914 NodeList formalParameters = popNode(); | |
| 915 Identifier name = popNode(); | |
| 916 Modifiers modifiers = popNode(); | |
| 917 ElementKind kind; | |
| 918 if (getOrSet === null) { | |
| 919 kind = ElementKind.FUNCTION; | |
| 920 } else if (getOrSet.stringValue === 'get') { | |
| 921 kind = ElementKind.GETTER; | |
| 922 } else if (getOrSet.stringValue === 'set') { | |
| 923 kind = ElementKind.SETTER; | |
| 924 } | |
| 925 pushElement(new PartialFunctionElement(name.source, beginToken, getOrSet, | |
| 926 endToken, kind, | |
| 927 modifiers, compilationUnitElement)); | |
| 928 } | |
| 929 | |
| 930 void endFormalParameter(Token token, Token thisKeyword) { | |
| 931 Expression name = popNode(); | |
| 932 if (thisKeyword !== null) { | |
| 933 Identifier thisIdentifier = new Identifier(thisKeyword); | |
| 934 if (name.asSend() === null) { | |
| 935 name = new Send(thisIdentifier, name); | |
| 936 } else { | |
| 937 name = name.asSend().copyWithReceiver(thisIdentifier); | |
| 938 } | |
| 939 } | |
| 940 TypeAnnotation type = popNode(); | |
| 941 Modifiers modifiers = popNode(); | |
| 942 pushNode(new VariableDefinitions(type, modifiers, | |
| 943 new NodeList.singleton(name), token)); | |
| 944 } | |
| 945 | |
| 946 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
| 947 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
| 948 } | |
| 949 | |
| 950 void endArguments(int count, Token beginToken, Token endToken) { | |
| 951 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
| 952 } | |
| 953 | |
| 954 void handleNoArguments(Token token) { | |
| 955 pushNode(null); | |
| 956 } | |
| 957 | |
| 958 void endReturnStatement(bool hasExpression, | |
| 959 Token beginToken, Token endToken) { | |
| 960 Expression expression = hasExpression ? popNode() : null; | |
| 961 pushNode(new Return(beginToken, endToken, expression)); | |
| 962 } | |
| 963 | |
| 964 void endExpressionStatement(Token token) { | |
| 965 pushNode(new ExpressionStatement(popNode(), token)); | |
| 966 } | |
| 967 | |
| 968 void handleOnError(Token token, var error) { | |
| 969 listener.cancel("internal error: '${token.value}': ${error}", token: token); | |
| 970 } | |
| 971 | |
| 972 Token expectedFunctionBody(Token token) { | |
| 973 if (token.stringValue === 'native') { | |
| 974 return native.handleNativeFunctionBody(this, token); | |
| 975 } else { | |
| 976 listener.cancel( | |
| 977 "expected a function body, but got '${token.slowToString()}'", | |
| 978 token: token); | |
| 979 return skipToEof(token); | |
| 980 } | |
| 981 } | |
| 982 | |
| 983 Token expectedClassBody(Token token) { | |
| 984 if (token.stringValue === 'native') { | |
| 985 return native.handleNativeClassBody(this, token); | |
| 986 } else { | |
| 987 listener.cancel( | |
| 988 "expected a class body, but got '${token.slowToString()}'", | |
| 989 token: token); | |
| 990 return skipToEof(token); | |
| 991 } | |
| 992 } | |
| 993 | |
| 994 void handleLiteralInt(Token token) { | |
| 995 pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e))); | |
| 996 } | |
| 997 | |
| 998 void handleLiteralDouble(Token token) { | |
| 999 pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e))); | |
| 1000 } | |
| 1001 | |
| 1002 void handleLiteralBool(Token token) { | |
| 1003 pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e))); | |
| 1004 } | |
| 1005 | |
| 1006 void handleLiteralNull(Token token) { | |
| 1007 pushNode(new LiteralNull(token)); | |
| 1008 } | |
| 1009 | |
| 1010 void handleBinaryExpression(Token token) { | |
| 1011 Node argument = popNode(); | |
| 1012 Node receiver = popNode(); | |
| 1013 if (token.stringValue === '.') { | |
| 1014 if (argument is !Send) internalError(node: argument); | |
| 1015 if (argument.asSend().receiver !== null) internalError(node: argument); | |
| 1016 if (argument is SendSet) internalError(node: argument); | |
| 1017 pushNode(argument.asSend().copyWithReceiver(receiver)); | |
| 1018 } else { | |
| 1019 NodeList arguments = new NodeList.singleton(argument); | |
| 1020 pushNode(new Send(receiver, new Operator(token), arguments)); | |
| 1021 } | |
| 1022 } | |
| 1023 | |
| 1024 void handleAssignmentExpression(Token token) { | |
| 1025 Node arg = popNode(); | |
| 1026 Node node = popNode(); | |
| 1027 Send send = node.asSend(); | |
| 1028 if (send === null) internalError(node: node); | |
| 1029 if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send); | |
| 1030 if (send.asSendSet() !== null) internalError(node: send); | |
| 1031 NodeList arguments; | |
| 1032 if (send.isIndex) { | |
| 1033 Link<Node> link = new Link<Node>(arg); | |
| 1034 link = link.prepend(send.arguments.head); | |
| 1035 arguments = new NodeList(null, link); | |
| 1036 } else { | |
| 1037 arguments = new NodeList.singleton(arg); | |
| 1038 } | |
| 1039 Operator op = new Operator(token); | |
| 1040 pushNode(new SendSet(send.receiver, send.selector, op, arguments)); | |
| 1041 } | |
| 1042 | |
| 1043 void handleConditionalExpression(Token question, Token colon) { | |
| 1044 Node elseExpression = popNode(); | |
| 1045 Node thenExpression = popNode(); | |
| 1046 Node condition = popNode(); | |
| 1047 pushNode(new Conditional( | |
| 1048 condition, thenExpression, elseExpression, question, colon)); | |
| 1049 } | |
| 1050 | |
| 1051 void endSend(Token token) { | |
| 1052 NodeList arguments = popNode(); | |
| 1053 Node selector = popNode(); | |
| 1054 // TODO(ahe): Handle receiver. | |
| 1055 pushNode(new Send(null, selector, arguments)); | |
| 1056 } | |
| 1057 | |
| 1058 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
| 1059 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
| 1060 } | |
| 1061 | |
| 1062 void handleNoFunctionBody(Token token) { | |
| 1063 pushNode(null); | |
| 1064 } | |
| 1065 | |
| 1066 void endFunction(Token getOrSet, Token endToken) { | |
| 1067 Statement body = popNode(); | |
| 1068 NodeList initializers = popNode(); | |
| 1069 NodeList formals = popNode(); | |
| 1070 // The name can be an identifier or a send in case of named constructors. | |
| 1071 Expression name = popNode(); | |
| 1072 TypeAnnotation type = popNode(); | |
| 1073 Modifiers modifiers = popNode(); | |
| 1074 pushNode(new FunctionExpression(name, formals, body, type, | |
| 1075 modifiers, initializers, getOrSet)); | |
| 1076 } | |
| 1077 | |
| 1078 void endFunctionDeclaration(Token endToken) { | |
| 1079 pushNode(new FunctionDeclaration(popNode())); | |
| 1080 } | |
| 1081 | |
| 1082 void endVariablesDeclaration(int count, Token endToken) { | |
| 1083 // TODO(ahe): Pick one name for this concept, either | |
| 1084 // VariablesDeclaration or VariableDefinitions. | |
| 1085 NodeList variables = makeNodeList(count, null, null, ","); | |
| 1086 TypeAnnotation type = popNode(); | |
| 1087 Modifiers modifiers = popNode(); | |
| 1088 pushNode(new VariableDefinitions(type, modifiers, variables, endToken)); | |
| 1089 } | |
| 1090 | |
| 1091 void endInitializer(Token assignmentOperator) { | |
| 1092 Expression initializer = popNode(); | |
| 1093 NodeList arguments = new NodeList.singleton(initializer); | |
| 1094 Expression name = popNode(); | |
| 1095 Operator op = new Operator(assignmentOperator); | |
| 1096 pushNode(new SendSet(null, name, op, arguments)); | |
| 1097 } | |
| 1098 | |
| 1099 void endIfStatement(Token ifToken, Token elseToken) { | |
| 1100 Statement elsePart = (elseToken === null) ? null : popNode(); | |
| 1101 Statement thenPart = popNode(); | |
| 1102 ParenthesizedExpression condition = popNode(); | |
| 1103 pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken)); | |
| 1104 } | |
| 1105 | |
| 1106 void endForStatement(int updateExpressionCount, | |
| 1107 Token beginToken, Token endToken) { | |
| 1108 Statement body = popNode(); | |
| 1109 NodeList updates = makeNodeList(updateExpressionCount, null, null, ','); | |
| 1110 Statement condition = popNode(); | |
| 1111 Node initializer = popNode(); | |
| 1112 pushNode(new For(initializer, condition, updates, body, beginToken)); | |
| 1113 } | |
| 1114 | |
| 1115 void handleNoExpression(Token token) { | |
| 1116 pushNode(null); | |
| 1117 } | |
| 1118 | |
| 1119 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
| 1120 Token endToken) { | |
| 1121 Expression condition = popNode(); | |
| 1122 Statement body = popNode(); | |
| 1123 pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken)); | |
| 1124 } | |
| 1125 | |
| 1126 void endWhileStatement(Token whileKeyword, Token endToken) { | |
| 1127 Statement body = popNode(); | |
| 1128 Expression condition = popNode(); | |
| 1129 pushNode(new While(condition, body, whileKeyword)); | |
| 1130 } | |
| 1131 | |
| 1132 void endBlock(int count, Token beginToken, Token endToken) { | |
| 1133 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
| 1134 } | |
| 1135 | |
| 1136 void endThrowStatement(Token throwToken, Token endToken) { | |
| 1137 Expression expression = popNode(); | |
| 1138 pushNode(new Throw(expression, throwToken, endToken)); | |
| 1139 } | |
| 1140 | |
| 1141 void endRethrowStatement(Token throwToken, Token endToken) { | |
| 1142 pushNode(new Throw(null, throwToken, endToken)); | |
| 1143 } | |
| 1144 | |
| 1145 void handleUnaryPrefixExpression(Token token) { | |
| 1146 pushNode(new Send.prefix(popNode(), new Operator(token))); | |
| 1147 } | |
| 1148 | |
| 1149 void handleSuperExpression(Token token) { | |
| 1150 pushNode(new Identifier(token)); | |
| 1151 } | |
| 1152 | |
| 1153 void handleThisExpression(Token token) { | |
| 1154 pushNode(new Identifier(token)); | |
| 1155 } | |
| 1156 | |
| 1157 void handleUnaryAssignmentExpression(Token token, bool isPrefix) { | |
| 1158 Node node = popNode(); | |
| 1159 Send send = node.asSend(); | |
| 1160 if (send === null) internalError(node: node); | |
| 1161 if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send); | |
| 1162 if (send.asSendSet() !== null) internalError(node: send); | |
| 1163 Node argument = null; | |
| 1164 if (send.isIndex) argument = send.arguments.head; | |
| 1165 Operator op = new Operator(token); | |
| 1166 | |
| 1167 if (isPrefix) { | |
| 1168 pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument)); | |
| 1169 } else { | |
| 1170 pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument)); | |
| 1171 } | |
| 1172 } | |
| 1173 | |
| 1174 void handleUnaryPostfixAssignmentExpression(Token token) { | |
| 1175 handleUnaryAssignmentExpression(token, false); | |
| 1176 } | |
| 1177 | |
| 1178 void handleUnaryPrefixAssignmentExpression(Token token) { | |
| 1179 handleUnaryAssignmentExpression(token, true); | |
| 1180 } | |
| 1181 | |
| 1182 void endInitializers(int count, Token beginToken, Token endToken) { | |
| 1183 pushNode(makeNodeList(count, beginToken, null, ',')); | |
| 1184 } | |
| 1185 | |
| 1186 void handleNoInitializers() { | |
| 1187 pushNode(null); | |
| 1188 } | |
| 1189 | |
| 1190 void endFields(int count, Token beginToken, Token endToken) { | |
| 1191 NodeList variables = makeNodeList(count, null, null, ","); | |
| 1192 Modifiers modifiers = popNode(); | |
| 1193 pushNode(new VariableDefinitions(null, modifiers, variables, endToken)); | |
| 1194 } | |
| 1195 | |
| 1196 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
| 1197 Statement body = popNode(); | |
| 1198 NodeList initializers = popNode(); | |
| 1199 NodeList formalParameters = popNode(); | |
| 1200 Expression name = popNode(); | |
| 1201 Modifiers modifiers = popNode(); | |
| 1202 pushNode(new FunctionExpression(name, formalParameters, body, null, | |
| 1203 modifiers, initializers, getOrSet)); | |
| 1204 } | |
| 1205 | |
| 1206 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
| 1207 Token endToken) { | |
| 1208 NodeList entries = makeNodeList(count, beginToken, endToken, ','); | |
| 1209 NodeList typeArguments = popNode(); | |
| 1210 pushNode(new LiteralMap(typeArguments, entries)); | |
| 1211 } | |
| 1212 | |
| 1213 void endLiteralMapEntry(Token colon, Token endToken) { | |
| 1214 Expression value = popNode(); | |
| 1215 Expression key = popNode(); | |
| 1216 if (key.asLiteralString() === null) { | |
| 1217 recoverableError('expected a constant string', node: key); | |
| 1218 } | |
| 1219 pushNode(new LiteralMapEntry(key, colon, value)); | |
| 1220 } | |
| 1221 | |
| 1222 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
| 1223 Token endToken) { | |
| 1224 NodeList elements = makeNodeList(count, beginToken, endToken, ','); | |
| 1225 NodeList typeArguments = popNode(); | |
| 1226 // TODO(ahe): Type arguments are discarded. | |
| 1227 pushNode(new LiteralList(null, elements, constKeyword)); | |
| 1228 } | |
| 1229 | |
| 1230 void handleIndexedExpression(Token openSquareBracket, | |
| 1231 Token closeSquareBracket) { | |
| 1232 NodeList arguments = | |
| 1233 makeNodeList(1, openSquareBracket, closeSquareBracket, null); | |
| 1234 Node receiver = popNode(); | |
| 1235 Token token = | |
| 1236 new StringToken(INDEX_INFO, '[]', openSquareBracket.charOffset); | |
| 1237 Node selector = new Operator(token); | |
| 1238 pushNode(new Send(receiver, selector, arguments)); | |
| 1239 } | |
| 1240 | |
| 1241 void handleNewExpression(Token token, bool named) { | |
| 1242 NodeList arguments = popNode(); | |
| 1243 Node name = popNode(); | |
| 1244 if (named) { | |
| 1245 TypeAnnotation type = popNode(); | |
| 1246 name = new Send(type, name); | |
| 1247 } | |
| 1248 pushNode(new NewExpression(token, new Send(null, name, arguments))); | |
| 1249 } | |
| 1250 | |
| 1251 void handleConstExpression(Token token, bool named) { | |
| 1252 NodeList arguments = popNode(); | |
| 1253 if (named) { | |
| 1254 Identifier name = popNode(); | |
| 1255 } | |
| 1256 TypeAnnotation type = popNode(); | |
| 1257 pushNode(new NewExpression(token, new Send(null, type, arguments))); | |
| 1258 } | |
| 1259 | |
| 1260 void handleOperatorName(Token operatorKeyword, Token token) { | |
| 1261 Operator op = new Operator(token); | |
| 1262 pushNode(new Send(new Identifier(operatorKeyword), op, null)); | |
| 1263 } | |
| 1264 | |
| 1265 void handleNamedArgument(Token colon) { | |
| 1266 Expression expression = popNode(); | |
| 1267 Identifier name = popNode(); | |
| 1268 pushNode(new NamedArgument(name, colon, expression)); | |
| 1269 } | |
| 1270 | |
| 1271 void endOptionalFormalParameters(int count, | |
| 1272 Token beginToken, Token endToken) { | |
| 1273 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
| 1274 } | |
| 1275 | |
| 1276 void handleFunctionTypedFormalParameter(Token endToken) { | |
| 1277 NodeList formals = popNode(); | |
| 1278 Identifier name = popNode(); | |
| 1279 TypeAnnotation returnType = popNode(); | |
| 1280 pushNode(null); // Signal "no type" to endFormalParameter. | |
| 1281 pushNode(new FunctionExpression(name, formals, null, returnType, | |
| 1282 null, null, null)); | |
| 1283 } | |
| 1284 | |
| 1285 void handleValuedFormalParameter(Token equals, Token token) { | |
| 1286 Expression defaultValue = popNode(); | |
| 1287 Expression parameterName = popNode(); | |
| 1288 pushNode(new SendSet(null, parameterName, new Operator(equals), | |
| 1289 new NodeList.singleton(defaultValue))); | |
| 1290 } | |
| 1291 | |
| 1292 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
| 1293 Block finallyBlock = null; | |
| 1294 if (finallyKeyword !== null) { | |
| 1295 finallyBlock = popNode(); | |
| 1296 } | |
| 1297 NodeList catchBlocks = makeNodeList(catchCount, null, null, null); | |
| 1298 Block tryBlock = popNode(); | |
| 1299 pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock, | |
| 1300 tryKeyword, finallyKeyword)); | |
| 1301 } | |
| 1302 | |
| 1303 void handleCatchBlock(Token catchKeyword) { | |
| 1304 Block block = popNode(); | |
| 1305 NodeList formals = popNode(); | |
| 1306 pushNode(new CatchBlock(formals, block, catchKeyword)); | |
| 1307 } | |
| 1308 | |
| 1309 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
| 1310 NodeList cases = popNode(); | |
| 1311 ParenthesizedExpression expression = popNode(); | |
| 1312 pushNode(new SwitchStatement(expression, cases, switchKeyword)); | |
| 1313 } | |
| 1314 | |
| 1315 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
| 1316 Link<Node> nodes = const EmptyLink<Node>(); | |
| 1317 while (caseCount > 0) { | |
| 1318 SwitchCase switchCase = popNode(); | |
| 1319 nodes = nodes.prepend(switchCase); | |
| 1320 caseCount--; | |
| 1321 } | |
| 1322 pushNode(new NodeList(beginToken, nodes, endToken, null)); | |
| 1323 } | |
| 1324 | |
| 1325 void handleSwitchCase(Token labelToken, int expressionCount, | |
| 1326 Token defaultKeyword, int statementCount, | |
| 1327 Token firstToken, Token endToken) { | |
| 1328 NodeList statements = makeNodeList(statementCount, null, null, null); | |
| 1329 NodeList expressions = makeNodeList(expressionCount, null, null, null); | |
| 1330 Identifier label = null; | |
| 1331 if (labelToken !== null) { | |
| 1332 label = popNode(); | |
| 1333 } | |
| 1334 pushNode(new SwitchCase(label, expressions, defaultKeyword, statements, | |
| 1335 firstToken)); | |
| 1336 } | |
| 1337 | |
| 1338 void handleBreakStatement(bool hasTarget, | |
| 1339 Token breakKeyword, Token endToken) { | |
| 1340 Identifier target = null; | |
| 1341 if (hasTarget) { | |
| 1342 target = popNode(); | |
| 1343 } | |
| 1344 pushNode(new BreakStatement(target, breakKeyword, endToken)); | |
| 1345 } | |
| 1346 | |
| 1347 void handleContinueStatement(bool hasTarget, | |
| 1348 Token continueKeyword, Token endToken) { | |
| 1349 Identifier target = null; | |
| 1350 if (hasTarget) { | |
| 1351 target = popNode(); | |
| 1352 } | |
| 1353 pushNode(new ContinueStatement(target, continueKeyword, endToken)); | |
| 1354 } | |
| 1355 | |
| 1356 void handleEmptyStatement(Token token) { | |
| 1357 pushNode(new EmptyStatement(token)); | |
| 1358 } | |
| 1359 | |
| 1360 void endFactoryMethod(Token factoryKeyword, Token periodBeforeName, | |
| 1361 Token endToken) { | |
| 1362 Statement body = popNode(); | |
| 1363 NodeList formals = popNode(); | |
| 1364 NodeList typeParameters = popNode(); // TODO(karlklose): don't throw away. | |
| 1365 Node name = popNode(); | |
| 1366 if (periodBeforeName !== null) { | |
| 1367 // A library prefix was handled in [handleQualified]. | |
| 1368 name = new Send(popNode(), name); | |
| 1369 } | |
| 1370 handleModifier(factoryKeyword); | |
| 1371 handleModifiers(1); | |
| 1372 Modifiers modifiers = popNode(); | |
| 1373 pushNode(new FunctionExpression(name, formals, body, null, | |
| 1374 modifiers, null, null)); | |
| 1375 } | |
| 1376 | |
| 1377 void endForInStatement(Token beginToken, Token inKeyword, Token endToken) { | |
| 1378 Statement body = popNode(); | |
| 1379 Expression expression = popNode(); | |
| 1380 Node declaredIdentifier = popNode(); | |
| 1381 pushNode(new ForInStatement(declaredIdentifier, expression, body, | |
| 1382 beginToken, inKeyword)); | |
| 1383 } | |
| 1384 | |
| 1385 void endUnamedFunction(Token token) { | |
| 1386 Statement body = popNode(); | |
| 1387 NodeList formals = popNode(); | |
| 1388 pushNode(new FunctionExpression(null, formals, body, null, | |
| 1389 null, null, null)); | |
| 1390 } | |
| 1391 | |
| 1392 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
| 1393 TypeAnnotation type = popNode(); | |
| 1394 Expression expression = popNode(); | |
| 1395 Node argument; | |
| 1396 if (not != null) { | |
| 1397 argument = new Send.prefix(type, new Operator(not)); | |
| 1398 } else { | |
| 1399 argument = type; | |
| 1400 } | |
| 1401 | |
| 1402 NodeList arguments = new NodeList.singleton(argument); | |
| 1403 pushNode(new Send(expression, new Operator(operathor), arguments)); | |
| 1404 } | |
| 1405 | |
| 1406 void endLabeledStatement(Token colon) { | |
| 1407 Statement statement = popNode(); | |
| 1408 Identifier label = popNode(); | |
| 1409 pushNode(new LabeledStatement(label, colon, statement)); | |
| 1410 } | |
| 1411 | |
| 1412 void log(message) { | |
| 1413 listener.log(message); | |
| 1414 } | |
| 1415 | |
| 1416 void internalError([Token token, Node node]) { | |
| 1417 listener.cancel('internal error', token: token, node: node); | |
| 1418 throw 'internal error'; | |
| 1419 } | |
| 1420 } | |
| 1421 | |
| 1422 class PartialFunctionElement extends FunctionElement { | |
| 1423 final Token beginToken; | |
| 1424 final Token getOrSet; | |
| 1425 final Token endToken; | |
| 1426 | |
| 1427 PartialFunctionElement(SourceString name, | |
| 1428 Token this.beginToken, | |
| 1429 Token this.getOrSet, | |
| 1430 Token this.endToken, | |
| 1431 ElementKind kind, | |
| 1432 Modifiers modifiers, | |
| 1433 Element enclosing) | |
| 1434 : super(name, kind, modifiers, enclosing); | |
| 1435 | |
| 1436 FunctionExpression parseNode(DiagnosticListener listener) { | |
| 1437 if (cachedNode != null) return cachedNode; | |
| 1438 cachedNode = parse(listener, | |
| 1439 getCompilationUnit(), | |
| 1440 (p) => p.parseFunction(beginToken, getOrSet)); | |
| 1441 return cachedNode; | |
| 1442 } | |
| 1443 | |
| 1444 Token position() => findMyName(beginToken); | |
| 1445 } | |
| 1446 | |
| 1447 class PartialFieldListElement extends VariableListElement { | |
| 1448 final Token beginToken; | |
| 1449 final Token endToken; | |
| 1450 | |
| 1451 PartialFieldListElement(Token this.beginToken, | |
| 1452 Token this.endToken, | |
| 1453 Modifiers modifiers, | |
| 1454 Element enclosing) | |
| 1455 : super(ElementKind.VARIABLE_LIST, modifiers, enclosing); | |
| 1456 | |
| 1457 VariableDefinitions parseNode(DiagnosticListener listener) { | |
| 1458 if (cachedNode != null) return cachedNode; | |
| 1459 cachedNode = parse(listener, | |
| 1460 getCompilationUnit(), | |
| 1461 (p) => p.parseVariablesDeclaration(beginToken)); | |
| 1462 return cachedNode; | |
| 1463 } | |
| 1464 | |
| 1465 Token position() => beginToken; // findMyName doesn't work. I'm nameless. | |
| 1466 } | |
| 1467 | |
| 1468 Node parse(DiagnosticListener diagnosticListener, | |
| 1469 CompilationUnitElement element, | |
| 1470 doParse(Parser parser)) { | |
| 1471 NodeListener listener = new NodeListener(diagnosticListener, element); | |
| 1472 doParse(new Parser(listener)); | |
| 1473 Node node = listener.popNode(); | |
| 1474 assert(listener.nodes.isEmpty()); | |
| 1475 return node; | |
| 1476 } | |
| OLD | NEW |