OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. |
| 7 |
| 8 library engine.parser; |
| 9 |
| 10 import 'dart:collection'; |
| 11 import 'java_core.dart'; |
| 12 import 'java_engine.dart'; |
| 13 import 'instrumentation.dart'; |
| 14 import 'error.dart'; |
| 15 import 'source.dart'; |
| 16 import 'scanner.dart'; |
| 17 import 'ast.dart'; |
| 18 import 'utilities_dart.dart'; |
| 19 import 'engine.dart' show AnalysisEngine, AnalysisOptionsImpl; |
| 20 import 'utilities_collection.dart' show TokenMap; |
| 21 |
| 22 /** |
| 23 * Instances of the class `CommentAndMetadata` implement a simple data-holder fo
r a method |
| 24 * that needs to return multiple values. |
| 25 */ |
| 26 class CommentAndMetadata { |
| 27 /** |
| 28 * The documentation comment that was parsed, or `null` if none was given. |
| 29 */ |
| 30 final Comment comment; |
| 31 |
| 32 /** |
| 33 * The metadata that was parsed. |
| 34 */ |
| 35 final List<Annotation> metadata; |
| 36 |
| 37 /** |
| 38 * Initialize a newly created holder with the given data. |
| 39 * |
| 40 * @param comment the documentation comment that was parsed |
| 41 * @param metadata the metadata that was parsed |
| 42 */ |
| 43 CommentAndMetadata(this.comment, this.metadata); |
| 44 } |
| 45 |
| 46 /** |
| 47 * Instances of the class `FinalConstVarOrType` implement a simple data-holder f
or a method |
| 48 * that needs to return multiple values. |
| 49 */ |
| 50 class FinalConstVarOrType { |
| 51 /** |
| 52 * The 'final', 'const' or 'var' keyword, or `null` if none was given. |
| 53 */ |
| 54 final Token keyword; |
| 55 |
| 56 /** |
| 57 * The type, of `null` if no type was specified. |
| 58 */ |
| 59 final TypeName type; |
| 60 |
| 61 /** |
| 62 * Initialize a newly created holder with the given data. |
| 63 * |
| 64 * @param keyword the 'final', 'const' or 'var' keyword |
| 65 * @param type the type |
| 66 */ |
| 67 FinalConstVarOrType(this.keyword, this.type); |
| 68 } |
| 69 |
| 70 /** |
| 71 * Instances of the class `IncrementalParseDispatcher` implement a dispatcher th
at will invoke |
| 72 * the right parse method when re-parsing a specified child of the visited node.
All of the methods |
| 73 * in this class assume that the parser is positioned to parse the replacement f
or the node. All of |
| 74 * the methods will throw an [IncrementalParseException] if the node could not b
e parsed for |
| 75 * some reason. |
| 76 */ |
| 77 class IncrementalParseDispatcher implements AstVisitor<AstNode> { |
| 78 /** |
| 79 * The parser used to parse the replacement for the node. |
| 80 */ |
| 81 final Parser _parser; |
| 82 |
| 83 /** |
| 84 * The node that is to be replaced. |
| 85 */ |
| 86 final AstNode _oldNode; |
| 87 |
| 88 /** |
| 89 * Initialize a newly created dispatcher to parse a single node that will repl
ace the given node. |
| 90 * |
| 91 * @param parser the parser used to parse the replacement for the node |
| 92 * @param oldNode the node that is to be replaced |
| 93 */ |
| 94 IncrementalParseDispatcher(this._parser, this._oldNode); |
| 95 |
| 96 @override |
| 97 AstNode visitAdjacentStrings(AdjacentStrings node) { |
| 98 if (node.strings.contains(_oldNode)) { |
| 99 return _parser.parseStringLiteral(); |
| 100 } |
| 101 return _notAChild(node); |
| 102 } |
| 103 |
| 104 @override |
| 105 AstNode visitAnnotation(Annotation node) { |
| 106 if (identical(_oldNode, node.name)) { |
| 107 throw new InsufficientContextException(); |
| 108 } else if (identical(_oldNode, node.constructorName)) { |
| 109 throw new InsufficientContextException(); |
| 110 } else if (identical(_oldNode, node.arguments)) { |
| 111 return _parser.parseArgumentList(); |
| 112 } |
| 113 return _notAChild(node); |
| 114 } |
| 115 |
| 116 @override |
| 117 AstNode visitArgumentList(ArgumentList node) { |
| 118 if (node.arguments.contains(_oldNode)) { |
| 119 return _parser.parseArgument(); |
| 120 } |
| 121 return _notAChild(node); |
| 122 } |
| 123 |
| 124 @override |
| 125 AstNode visitAsExpression(AsExpression node) { |
| 126 if (identical(_oldNode, node.expression)) { |
| 127 return _parser.parseBitwiseOrExpression(); |
| 128 } else if (identical(_oldNode, node.type)) { |
| 129 return _parser.parseTypeName(); |
| 130 } |
| 131 return _notAChild(node); |
| 132 } |
| 133 |
| 134 @override |
| 135 AstNode visitAssertStatement(AssertStatement node) { |
| 136 if (identical(_oldNode, node.condition)) { |
| 137 return _parser.parseExpression2(); |
| 138 } |
| 139 return _notAChild(node); |
| 140 } |
| 141 |
| 142 @override |
| 143 AstNode visitAssignmentExpression(AssignmentExpression node) { |
| 144 if (identical(_oldNode, node.leftHandSide)) { |
| 145 // TODO(brianwilkerson) If the assignment is part of a cascade section, th
en we don't have a |
| 146 // single parse method that will work. Otherwise, we can parse a condition
al expression, but |
| 147 // need to ensure that the resulting expression is assignable. |
| 148 // return parser.parseConditionalExpression(); |
| 149 throw new InsufficientContextException(); |
| 150 } else if (identical(_oldNode, node.rightHandSide)) { |
| 151 if (_isCascadeAllowedInAssignment(node)) { |
| 152 return _parser.parseExpression2(); |
| 153 } |
| 154 return _parser.parseExpressionWithoutCascade(); |
| 155 } |
| 156 return _notAChild(node); |
| 157 } |
| 158 |
| 159 @override |
| 160 AstNode visitAwaitExpression(AwaitExpression node) { |
| 161 if (identical(_oldNode, node.expression)) { |
| 162 // TODO(brianwilkerson) Depending on precedence, this might not be suffici
ent. |
| 163 return _parser.parseExpression2(); |
| 164 } |
| 165 return _notAChild(node); |
| 166 } |
| 167 |
| 168 @override |
| 169 AstNode visitBinaryExpression(BinaryExpression node) { |
| 170 if (identical(_oldNode, node.leftOperand)) { |
| 171 throw new InsufficientContextException(); |
| 172 } else if (identical(_oldNode, node.rightOperand)) { |
| 173 throw new InsufficientContextException(); |
| 174 } |
| 175 return _notAChild(node); |
| 176 } |
| 177 |
| 178 @override |
| 179 AstNode visitBlock(Block node) { |
| 180 if (node.statements.contains(_oldNode)) { |
| 181 return _parser.parseStatement2(); |
| 182 } |
| 183 return _notAChild(node); |
| 184 } |
| 185 |
| 186 @override |
| 187 AstNode visitBlockFunctionBody(BlockFunctionBody node) { |
| 188 if (identical(_oldNode, node.block)) { |
| 189 return _parser.parseBlock(); |
| 190 } |
| 191 return _notAChild(node); |
| 192 } |
| 193 |
| 194 @override |
| 195 AstNode visitBooleanLiteral(BooleanLiteral node) => _notAChild(node); |
| 196 |
| 197 @override |
| 198 AstNode visitBreakStatement(BreakStatement node) { |
| 199 if (identical(_oldNode, node.label)) { |
| 200 return _parser.parseSimpleIdentifier(); |
| 201 } |
| 202 return _notAChild(node); |
| 203 } |
| 204 |
| 205 @override |
| 206 AstNode visitCascadeExpression(CascadeExpression node) { |
| 207 if (identical(_oldNode, node.target)) { |
| 208 return _parser.parseConditionalExpression(); |
| 209 } else if (node.cascadeSections.contains(_oldNode)) { |
| 210 throw new InsufficientContextException(); |
| 211 } |
| 212 return _notAChild(node); |
| 213 } |
| 214 |
| 215 @override |
| 216 AstNode visitCatchClause(CatchClause node) { |
| 217 if (identical(_oldNode, node.exceptionType)) { |
| 218 return _parser.parseTypeName(); |
| 219 } else if (identical(_oldNode, node.exceptionParameter)) { |
| 220 return _parser.parseSimpleIdentifier(); |
| 221 } else if (identical(_oldNode, node.stackTraceParameter)) { |
| 222 return _parser.parseSimpleIdentifier(); |
| 223 } else if (identical(_oldNode, node.body)) { |
| 224 return _parser.parseBlock(); |
| 225 } |
| 226 return _notAChild(node); |
| 227 } |
| 228 |
| 229 @override |
| 230 AstNode visitClassDeclaration(ClassDeclaration node) { |
| 231 if (identical(_oldNode, node.documentationComment)) { |
| 232 throw new InsufficientContextException(); |
| 233 } else if (node.metadata.contains(_oldNode)) { |
| 234 return _parser.parseAnnotation(); |
| 235 } else if (identical(_oldNode, node.name)) { |
| 236 return _parser.parseSimpleIdentifier(); |
| 237 } else if (identical(_oldNode, node.typeParameters)) { |
| 238 return _parser.parseTypeParameterList(); |
| 239 } else if (identical(_oldNode, node.extendsClause)) { |
| 240 return _parser.parseExtendsClause(); |
| 241 } else if (identical(_oldNode, node.withClause)) { |
| 242 return _parser.parseWithClause(); |
| 243 } else if (identical(_oldNode, node.implementsClause)) { |
| 244 return _parser.parseImplementsClause(); |
| 245 } else if (node.members.contains(_oldNode)) { |
| 246 ClassMember member = _parser.parseClassMember(node.name.name); |
| 247 if (member == null) { |
| 248 throw new InsufficientContextException(); |
| 249 } |
| 250 return member; |
| 251 } |
| 252 return _notAChild(node); |
| 253 } |
| 254 |
| 255 @override |
| 256 AstNode visitClassTypeAlias(ClassTypeAlias node) { |
| 257 if (identical(_oldNode, node.documentationComment)) { |
| 258 throw new InsufficientContextException(); |
| 259 } else if (node.metadata.contains(_oldNode)) { |
| 260 return _parser.parseAnnotation(); |
| 261 } else if (identical(_oldNode, node.name)) { |
| 262 return _parser.parseSimpleIdentifier(); |
| 263 } else if (identical(_oldNode, node.typeParameters)) { |
| 264 return _parser.parseTypeParameterList(); |
| 265 } else if (identical(_oldNode, node.superclass)) { |
| 266 return _parser.parseTypeName(); |
| 267 } else if (identical(_oldNode, node.withClause)) { |
| 268 return _parser.parseWithClause(); |
| 269 } else if (identical(_oldNode, node.implementsClause)) { |
| 270 return _parser.parseImplementsClause(); |
| 271 } |
| 272 return _notAChild(node); |
| 273 } |
| 274 |
| 275 @override |
| 276 AstNode visitComment(Comment node) { |
| 277 throw new InsufficientContextException(); |
| 278 } |
| 279 |
| 280 @override |
| 281 AstNode visitCommentReference(CommentReference node) { |
| 282 if (identical(_oldNode, node.identifier)) { |
| 283 return _parser.parsePrefixedIdentifier(); |
| 284 } |
| 285 return _notAChild(node); |
| 286 } |
| 287 |
| 288 @override |
| 289 AstNode visitCompilationUnit(CompilationUnit node) { |
| 290 throw new InsufficientContextException(); |
| 291 } |
| 292 |
| 293 @override |
| 294 AstNode visitConditionalExpression(ConditionalExpression node) { |
| 295 if (identical(_oldNode, node.condition)) { |
| 296 return _parser.parseLogicalOrExpression(); |
| 297 } else if (identical(_oldNode, node.thenExpression)) { |
| 298 return _parser.parseExpressionWithoutCascade(); |
| 299 } else if (identical(_oldNode, node.elseExpression)) { |
| 300 return _parser.parseExpressionWithoutCascade(); |
| 301 } |
| 302 return _notAChild(node); |
| 303 } |
| 304 |
| 305 @override |
| 306 AstNode visitConstructorDeclaration(ConstructorDeclaration node) { |
| 307 if (identical(_oldNode, node.documentationComment)) { |
| 308 throw new InsufficientContextException(); |
| 309 } else if (node.metadata.contains(_oldNode)) { |
| 310 return _parser.parseAnnotation(); |
| 311 } else if (identical(_oldNode, node.returnType)) { |
| 312 throw new InsufficientContextException(); |
| 313 } else if (identical(_oldNode, node.name)) { |
| 314 throw new InsufficientContextException(); |
| 315 } else if (identical(_oldNode, node.parameters)) { |
| 316 return _parser.parseFormalParameterList(); |
| 317 } else if (identical(_oldNode, node.redirectedConstructor)) { |
| 318 throw new InsufficientContextException(); |
| 319 } else if (node.initializers.contains(_oldNode)) { |
| 320 throw new InsufficientContextException(); |
| 321 } else if (identical(_oldNode, node.body)) { |
| 322 throw new InsufficientContextException(); |
| 323 } |
| 324 return _notAChild(node); |
| 325 } |
| 326 |
| 327 @override |
| 328 AstNode visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 329 if (identical(_oldNode, node.fieldName)) { |
| 330 return _parser.parseSimpleIdentifier(); |
| 331 } else if (identical(_oldNode, node.expression)) { |
| 332 throw new InsufficientContextException(); |
| 333 } |
| 334 return _notAChild(node); |
| 335 } |
| 336 |
| 337 @override |
| 338 AstNode visitConstructorName(ConstructorName node) { |
| 339 if (identical(_oldNode, node.type)) { |
| 340 return _parser.parseTypeName(); |
| 341 } else if (identical(_oldNode, node.name)) { |
| 342 return _parser.parseSimpleIdentifier(); |
| 343 } |
| 344 return _notAChild(node); |
| 345 } |
| 346 |
| 347 @override |
| 348 AstNode visitContinueStatement(ContinueStatement node) { |
| 349 if (identical(_oldNode, node.label)) { |
| 350 return _parser.parseSimpleIdentifier(); |
| 351 } |
| 352 return _notAChild(node); |
| 353 } |
| 354 |
| 355 @override |
| 356 AstNode visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 357 if (identical(_oldNode, node.documentationComment)) { |
| 358 throw new InsufficientContextException(); |
| 359 } else if (node.metadata.contains(_oldNode)) { |
| 360 return _parser.parseAnnotation(); |
| 361 } else if (identical(_oldNode, node.type)) { |
| 362 throw new InsufficientContextException(); |
| 363 } else if (identical(_oldNode, node.identifier)) { |
| 364 return _parser.parseSimpleIdentifier(); |
| 365 } |
| 366 return _notAChild(node); |
| 367 } |
| 368 |
| 369 @override |
| 370 AstNode visitDefaultFormalParameter(DefaultFormalParameter node) { |
| 371 if (identical(_oldNode, node.parameter)) { |
| 372 return _parser.parseNormalFormalParameter(); |
| 373 } else if (identical(_oldNode, node.defaultValue)) { |
| 374 return _parser.parseExpression2(); |
| 375 } |
| 376 return _notAChild(node); |
| 377 } |
| 378 |
| 379 @override |
| 380 AstNode visitDoStatement(DoStatement node) { |
| 381 if (identical(_oldNode, node.body)) { |
| 382 return _parser.parseStatement2(); |
| 383 } else if (identical(_oldNode, node.condition)) { |
| 384 return _parser.parseExpression2(); |
| 385 } |
| 386 return _notAChild(node); |
| 387 } |
| 388 |
| 389 @override |
| 390 AstNode visitDoubleLiteral(DoubleLiteral node) => _notAChild(node); |
| 391 |
| 392 @override |
| 393 AstNode visitEmptyFunctionBody(EmptyFunctionBody node) => _notAChild(node); |
| 394 |
| 395 @override |
| 396 AstNode visitEmptyStatement(EmptyStatement node) => _notAChild(node); |
| 397 |
| 398 @override |
| 399 AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) { |
| 400 if (identical(_oldNode, node.documentationComment)) { |
| 401 throw new InsufficientContextException(); |
| 402 } else if (node.metadata.contains(_oldNode)) { |
| 403 return _parser.parseAnnotation(); |
| 404 } else if (identical(_oldNode, node.name)) { |
| 405 return _parser.parseSimpleIdentifier(); |
| 406 } |
| 407 return _notAChild(node); |
| 408 } |
| 409 |
| 410 @override |
| 411 AstNode visitEnumDeclaration(EnumDeclaration node) { |
| 412 if (identical(_oldNode, node.documentationComment)) { |
| 413 throw new InsufficientContextException(); |
| 414 } else if (node.metadata.contains(_oldNode)) { |
| 415 return _parser.parseAnnotation(); |
| 416 } else if (identical(_oldNode, node.name)) { |
| 417 return _parser.parseSimpleIdentifier(); |
| 418 } else if (node.constants.contains(_oldNode)) { |
| 419 throw new InsufficientContextException(); |
| 420 } |
| 421 return _notAChild(node); |
| 422 } |
| 423 |
| 424 @override |
| 425 AstNode visitExportDirective(ExportDirective node) { |
| 426 if (identical(_oldNode, node.documentationComment)) { |
| 427 throw new InsufficientContextException(); |
| 428 } else if (node.metadata.contains(_oldNode)) { |
| 429 return _parser.parseAnnotation(); |
| 430 } else if (identical(_oldNode, node.uri)) { |
| 431 return _parser.parseStringLiteral(); |
| 432 } else if (node.combinators.contains(_oldNode)) { |
| 433 throw new IncrementalParseException(); |
| 434 } |
| 435 return _notAChild(node); |
| 436 } |
| 437 |
| 438 @override |
| 439 AstNode visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 440 if (identical(_oldNode, node.expression)) { |
| 441 return _parser.parseExpression2(); |
| 442 } |
| 443 return _notAChild(node); |
| 444 } |
| 445 |
| 446 @override |
| 447 AstNode visitExpressionStatement(ExpressionStatement node) { |
| 448 if (identical(_oldNode, node.expression)) { |
| 449 return _parser.parseExpression2(); |
| 450 } |
| 451 return _notAChild(node); |
| 452 } |
| 453 |
| 454 @override |
| 455 AstNode visitExtendsClause(ExtendsClause node) { |
| 456 if (identical(_oldNode, node.superclass)) { |
| 457 return _parser.parseTypeName(); |
| 458 } |
| 459 return _notAChild(node); |
| 460 } |
| 461 |
| 462 @override |
| 463 AstNode visitFieldDeclaration(FieldDeclaration node) { |
| 464 if (identical(_oldNode, node.documentationComment)) { |
| 465 throw new InsufficientContextException(); |
| 466 } else if (node.metadata.contains(_oldNode)) { |
| 467 return _parser.parseAnnotation(); |
| 468 } else if (identical(_oldNode, node.fields)) { |
| 469 throw new InsufficientContextException(); |
| 470 } |
| 471 return _notAChild(node); |
| 472 } |
| 473 |
| 474 @override |
| 475 AstNode visitFieldFormalParameter(FieldFormalParameter node) { |
| 476 if (identical(_oldNode, node.documentationComment)) { |
| 477 throw new InsufficientContextException(); |
| 478 } else if (node.metadata.contains(_oldNode)) { |
| 479 return _parser.parseAnnotation(); |
| 480 } else if (identical(_oldNode, node.type)) { |
| 481 return _parser.parseTypeName(); |
| 482 } else if (identical(_oldNode, node.identifier)) { |
| 483 return _parser.parseSimpleIdentifier(); |
| 484 } else if (identical(_oldNode, node.parameters)) { |
| 485 return _parser.parseFormalParameterList(); |
| 486 } |
| 487 return _notAChild(node); |
| 488 } |
| 489 |
| 490 @override |
| 491 AstNode visitForEachStatement(ForEachStatement node) { |
| 492 if (identical(_oldNode, node.loopVariable)) { |
| 493 throw new InsufficientContextException(); |
| 494 } else if (identical(_oldNode, node.identifier)) { |
| 495 return _parser.parseSimpleIdentifier(); |
| 496 } else if (identical(_oldNode, node.body)) { |
| 497 return _parser.parseStatement2(); |
| 498 } |
| 499 return _notAChild(node); |
| 500 } |
| 501 |
| 502 @override |
| 503 AstNode visitFormalParameterList(FormalParameterList node) { |
| 504 // We don't know which kind of parameter to parse. |
| 505 throw new InsufficientContextException(); |
| 506 } |
| 507 |
| 508 @override |
| 509 AstNode visitForStatement(ForStatement node) { |
| 510 if (identical(_oldNode, node.variables)) { |
| 511 throw new InsufficientContextException(); |
| 512 } else if (identical(_oldNode, node.initialization)) { |
| 513 throw new InsufficientContextException(); |
| 514 } else if (identical(_oldNode, node.condition)) { |
| 515 return _parser.parseExpression2(); |
| 516 } else if (node.updaters.contains(_oldNode)) { |
| 517 return _parser.parseExpression2(); |
| 518 } else if (identical(_oldNode, node.body)) { |
| 519 return _parser.parseStatement2(); |
| 520 } |
| 521 return _notAChild(node); |
| 522 } |
| 523 |
| 524 @override |
| 525 AstNode visitFunctionDeclaration(FunctionDeclaration node) { |
| 526 if (identical(_oldNode, node.documentationComment)) { |
| 527 throw new InsufficientContextException(); |
| 528 } else if (node.metadata.contains(_oldNode)) { |
| 529 return _parser.parseAnnotation(); |
| 530 } else if (identical(_oldNode, node.returnType)) { |
| 531 return _parser.parseReturnType(); |
| 532 } else if (identical(_oldNode, node.name)) { |
| 533 return _parser.parseSimpleIdentifier(); |
| 534 } else if (identical(_oldNode, node.functionExpression)) { |
| 535 throw new InsufficientContextException(); |
| 536 } |
| 537 return _notAChild(node); |
| 538 } |
| 539 |
| 540 @override |
| 541 AstNode visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { |
| 542 if (identical(_oldNode, node.functionDeclaration)) { |
| 543 throw new InsufficientContextException(); |
| 544 } |
| 545 return _notAChild(node); |
| 546 } |
| 547 |
| 548 @override |
| 549 AstNode visitFunctionExpression(FunctionExpression node) { |
| 550 if (identical(_oldNode, node.parameters)) { |
| 551 return _parser.parseFormalParameterList(); |
| 552 } else if (identical(_oldNode, node.body)) { |
| 553 throw new InsufficientContextException(); |
| 554 } |
| 555 return _notAChild(node); |
| 556 } |
| 557 |
| 558 @override |
| 559 AstNode visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 560 if (identical(_oldNode, node.function)) { |
| 561 throw new InsufficientContextException(); |
| 562 } else if (identical(_oldNode, node.argumentList)) { |
| 563 return _parser.parseArgumentList(); |
| 564 } |
| 565 return _notAChild(node); |
| 566 } |
| 567 |
| 568 @override |
| 569 AstNode visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 570 if (identical(_oldNode, node.documentationComment)) { |
| 571 throw new InsufficientContextException(); |
| 572 } else if (node.metadata.contains(_oldNode)) { |
| 573 return _parser.parseAnnotation(); |
| 574 } else if (identical(_oldNode, node.returnType)) { |
| 575 return _parser.parseReturnType(); |
| 576 } else if (identical(_oldNode, node.name)) { |
| 577 return _parser.parseSimpleIdentifier(); |
| 578 } else if (identical(_oldNode, node.typeParameters)) { |
| 579 return _parser.parseTypeParameterList(); |
| 580 } else if (identical(_oldNode, node.parameters)) { |
| 581 return _parser.parseFormalParameterList(); |
| 582 } |
| 583 return _notAChild(node); |
| 584 } |
| 585 |
| 586 @override |
| 587 AstNode visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| 588 if (identical(_oldNode, node.documentationComment)) { |
| 589 throw new InsufficientContextException(); |
| 590 } else if (node.metadata.contains(_oldNode)) { |
| 591 return _parser.parseAnnotation(); |
| 592 } else if (identical(_oldNode, node.returnType)) { |
| 593 return _parser.parseReturnType(); |
| 594 } else if (identical(_oldNode, node.identifier)) { |
| 595 return _parser.parseSimpleIdentifier(); |
| 596 } else if (identical(_oldNode, node.parameters)) { |
| 597 return _parser.parseFormalParameterList(); |
| 598 } |
| 599 return _notAChild(node); |
| 600 } |
| 601 |
| 602 @override |
| 603 AstNode visitHideCombinator(HideCombinator node) { |
| 604 if (node.hiddenNames.contains(_oldNode)) { |
| 605 return _parser.parseSimpleIdentifier(); |
| 606 } |
| 607 return _notAChild(node); |
| 608 } |
| 609 |
| 610 @override |
| 611 AstNode visitIfStatement(IfStatement node) { |
| 612 if (identical(_oldNode, node.condition)) { |
| 613 return _parser.parseExpression2(); |
| 614 } else if (identical(_oldNode, node.thenStatement)) { |
| 615 return _parser.parseStatement2(); |
| 616 } else if (identical(_oldNode, node.elseStatement)) { |
| 617 return _parser.parseStatement2(); |
| 618 } |
| 619 return _notAChild(node); |
| 620 } |
| 621 |
| 622 @override |
| 623 AstNode visitImplementsClause(ImplementsClause node) { |
| 624 if (node.interfaces.contains(node)) { |
| 625 return _parser.parseTypeName(); |
| 626 } |
| 627 return _notAChild(node); |
| 628 } |
| 629 |
| 630 @override |
| 631 AstNode visitImportDirective(ImportDirective node) { |
| 632 if (identical(_oldNode, node.documentationComment)) { |
| 633 throw new InsufficientContextException(); |
| 634 } else if (node.metadata.contains(_oldNode)) { |
| 635 return _parser.parseAnnotation(); |
| 636 } else if (identical(_oldNode, node.uri)) { |
| 637 return _parser.parseStringLiteral(); |
| 638 } else if (identical(_oldNode, node.prefix)) { |
| 639 return _parser.parseSimpleIdentifier(); |
| 640 } else if (node.combinators.contains(_oldNode)) { |
| 641 throw new IncrementalParseException(); |
| 642 } |
| 643 return _notAChild(node); |
| 644 } |
| 645 |
| 646 @override |
| 647 AstNode visitIndexExpression(IndexExpression node) { |
| 648 if (identical(_oldNode, node.target)) { |
| 649 throw new InsufficientContextException(); |
| 650 } else if (identical(_oldNode, node.index)) { |
| 651 return _parser.parseExpression2(); |
| 652 } |
| 653 return _notAChild(node); |
| 654 } |
| 655 |
| 656 @override |
| 657 AstNode visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 658 if (identical(_oldNode, node.constructorName)) { |
| 659 return _parser.parseConstructorName(); |
| 660 } else if (identical(_oldNode, node.argumentList)) { |
| 661 return _parser.parseArgumentList(); |
| 662 } |
| 663 return _notAChild(node); |
| 664 } |
| 665 |
| 666 @override |
| 667 AstNode visitIntegerLiteral(IntegerLiteral node) => _notAChild(node); |
| 668 |
| 669 @override |
| 670 AstNode visitInterpolationExpression(InterpolationExpression node) { |
| 671 if (identical(_oldNode, node.expression)) { |
| 672 if (node.leftBracket == null) { |
| 673 throw new InsufficientContextException(); |
| 674 } |
| 675 return _parser.parseExpression2(); |
| 676 } |
| 677 return _notAChild(node); |
| 678 } |
| 679 |
| 680 @override |
| 681 AstNode visitInterpolationString(InterpolationString node) { |
| 682 throw new InsufficientContextException(); |
| 683 } |
| 684 |
| 685 @override |
| 686 AstNode visitIsExpression(IsExpression node) { |
| 687 if (identical(_oldNode, node.expression)) { |
| 688 return _parser.parseBitwiseOrExpression(); |
| 689 } else if (identical(_oldNode, node.type)) { |
| 690 return _parser.parseTypeName(); |
| 691 } |
| 692 return _notAChild(node); |
| 693 } |
| 694 |
| 695 @override |
| 696 AstNode visitLabel(Label node) { |
| 697 if (identical(_oldNode, node.label)) { |
| 698 return _parser.parseSimpleIdentifier(); |
| 699 } |
| 700 return _notAChild(node); |
| 701 } |
| 702 |
| 703 @override |
| 704 AstNode visitLabeledStatement(LabeledStatement node) { |
| 705 if (node.labels.contains(_oldNode)) { |
| 706 return _parser.parseLabel(); |
| 707 } else if (identical(_oldNode, node.statement)) { |
| 708 return _parser.parseStatement2(); |
| 709 } |
| 710 return _notAChild(node); |
| 711 } |
| 712 |
| 713 @override |
| 714 AstNode visitLibraryDirective(LibraryDirective node) { |
| 715 if (identical(_oldNode, node.documentationComment)) { |
| 716 throw new InsufficientContextException(); |
| 717 } else if (node.metadata.contains(_oldNode)) { |
| 718 return _parser.parseAnnotation(); |
| 719 } else if (identical(_oldNode, node.name)) { |
| 720 return _parser.parseLibraryIdentifier(); |
| 721 } |
| 722 return _notAChild(node); |
| 723 } |
| 724 |
| 725 @override |
| 726 AstNode visitLibraryIdentifier(LibraryIdentifier node) { |
| 727 if (node.components.contains(_oldNode)) { |
| 728 return _parser.parseSimpleIdentifier(); |
| 729 } |
| 730 return _notAChild(node); |
| 731 } |
| 732 |
| 733 @override |
| 734 AstNode visitListLiteral(ListLiteral node) { |
| 735 if (identical(_oldNode, node.typeArguments)) { |
| 736 return _parser.parseTypeArgumentList(); |
| 737 } else if (node.elements.contains(_oldNode)) { |
| 738 return _parser.parseExpression2(); |
| 739 } |
| 740 return _notAChild(node); |
| 741 } |
| 742 |
| 743 @override |
| 744 AstNode visitMapLiteral(MapLiteral node) { |
| 745 if (identical(_oldNode, node.typeArguments)) { |
| 746 return _parser.parseTypeArgumentList(); |
| 747 } else if (node.entries.contains(_oldNode)) { |
| 748 return _parser.parseMapLiteralEntry(); |
| 749 } |
| 750 return _notAChild(node); |
| 751 } |
| 752 |
| 753 @override |
| 754 AstNode visitMapLiteralEntry(MapLiteralEntry node) { |
| 755 if (identical(_oldNode, node.key)) { |
| 756 return _parser.parseExpression2(); |
| 757 } else if (identical(_oldNode, node.value)) { |
| 758 return _parser.parseExpression2(); |
| 759 } |
| 760 return _notAChild(node); |
| 761 } |
| 762 |
| 763 @override |
| 764 AstNode visitMethodDeclaration(MethodDeclaration node) { |
| 765 if (identical(_oldNode, node.documentationComment)) { |
| 766 throw new InsufficientContextException(); |
| 767 } else if (node.metadata.contains(_oldNode)) { |
| 768 return _parser.parseAnnotation(); |
| 769 } else if (identical(_oldNode, node.returnType)) { |
| 770 throw new InsufficientContextException(); |
| 771 } else if (identical(_oldNode, node.name)) { |
| 772 if (node.operatorKeyword != null) { |
| 773 throw new InsufficientContextException(); |
| 774 } |
| 775 return _parser.parseSimpleIdentifier(); |
| 776 } else if (identical(_oldNode, node.body)) { |
| 777 //return parser.parseFunctionBody(); |
| 778 throw new InsufficientContextException(); |
| 779 } |
| 780 return _notAChild(node); |
| 781 } |
| 782 |
| 783 @override |
| 784 AstNode visitMethodInvocation(MethodInvocation node) { |
| 785 if (identical(_oldNode, node.target)) { |
| 786 throw new IncrementalParseException(); |
| 787 } else if (identical(_oldNode, node.methodName)) { |
| 788 return _parser.parseSimpleIdentifier(); |
| 789 } else if (identical(_oldNode, node.argumentList)) { |
| 790 return _parser.parseArgumentList(); |
| 791 } |
| 792 return _notAChild(node); |
| 793 } |
| 794 |
| 795 @override |
| 796 AstNode visitNamedExpression(NamedExpression node) { |
| 797 if (identical(_oldNode, node.name)) { |
| 798 return _parser.parseLabel(); |
| 799 } else if (identical(_oldNode, node.expression)) { |
| 800 return _parser.parseExpression2(); |
| 801 } |
| 802 return _notAChild(node); |
| 803 } |
| 804 |
| 805 @override |
| 806 AstNode visitNativeClause(NativeClause node) { |
| 807 if (identical(_oldNode, node.name)) { |
| 808 return _parser.parseStringLiteral(); |
| 809 } |
| 810 return _notAChild(node); |
| 811 } |
| 812 |
| 813 @override |
| 814 AstNode visitNativeFunctionBody(NativeFunctionBody node) { |
| 815 if (identical(_oldNode, node.stringLiteral)) { |
| 816 return _parser.parseStringLiteral(); |
| 817 } |
| 818 return _notAChild(node); |
| 819 } |
| 820 |
| 821 @override |
| 822 AstNode visitNullLiteral(NullLiteral node) => _notAChild(node); |
| 823 |
| 824 @override |
| 825 AstNode visitParenthesizedExpression(ParenthesizedExpression node) { |
| 826 if (identical(_oldNode, node.expression)) { |
| 827 return _parser.parseExpression2(); |
| 828 } |
| 829 return _notAChild(node); |
| 830 } |
| 831 |
| 832 @override |
| 833 AstNode visitPartDirective(PartDirective node) { |
| 834 if (identical(_oldNode, node.documentationComment)) { |
| 835 throw new InsufficientContextException(); |
| 836 } else if (node.metadata.contains(_oldNode)) { |
| 837 return _parser.parseAnnotation(); |
| 838 } else if (identical(_oldNode, node.uri)) { |
| 839 return _parser.parseStringLiteral(); |
| 840 } |
| 841 return _notAChild(node); |
| 842 } |
| 843 |
| 844 @override |
| 845 AstNode visitPartOfDirective(PartOfDirective node) { |
| 846 if (identical(_oldNode, node.documentationComment)) { |
| 847 throw new InsufficientContextException(); |
| 848 } else if (node.metadata.contains(_oldNode)) { |
| 849 return _parser.parseAnnotation(); |
| 850 } else if (identical(_oldNode, node.libraryName)) { |
| 851 return _parser.parseLibraryIdentifier(); |
| 852 } |
| 853 return _notAChild(node); |
| 854 } |
| 855 |
| 856 @override |
| 857 AstNode visitPostfixExpression(PostfixExpression node) { |
| 858 if (identical(_oldNode, node.operand)) { |
| 859 throw new InsufficientContextException(); |
| 860 } |
| 861 return _notAChild(node); |
| 862 } |
| 863 |
| 864 @override |
| 865 AstNode visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 866 if (identical(_oldNode, node.prefix)) { |
| 867 return _parser.parseSimpleIdentifier(); |
| 868 } else if (identical(_oldNode, node.identifier)) { |
| 869 return _parser.parseSimpleIdentifier(); |
| 870 } |
| 871 return _notAChild(node); |
| 872 } |
| 873 |
| 874 @override |
| 875 AstNode visitPrefixExpression(PrefixExpression node) { |
| 876 if (identical(_oldNode, node.operand)) { |
| 877 throw new InsufficientContextException(); |
| 878 } |
| 879 return _notAChild(node); |
| 880 } |
| 881 |
| 882 @override |
| 883 AstNode visitPropertyAccess(PropertyAccess node) { |
| 884 if (identical(_oldNode, node.target)) { |
| 885 throw new InsufficientContextException(); |
| 886 } else if (identical(_oldNode, node.propertyName)) { |
| 887 return _parser.parseSimpleIdentifier(); |
| 888 } |
| 889 return _notAChild(node); |
| 890 } |
| 891 |
| 892 @override |
| 893 AstNode visitRedirectingConstructorInvocation(RedirectingConstructorInvocation
node) { |
| 894 if (identical(_oldNode, node.constructorName)) { |
| 895 return _parser.parseSimpleIdentifier(); |
| 896 } else if (identical(_oldNode, node.argumentList)) { |
| 897 return _parser.parseArgumentList(); |
| 898 } |
| 899 return _notAChild(node); |
| 900 } |
| 901 |
| 902 @override |
| 903 AstNode visitRethrowExpression(RethrowExpression node) => _notAChild(node); |
| 904 |
| 905 @override |
| 906 AstNode visitReturnStatement(ReturnStatement node) { |
| 907 if (identical(_oldNode, node.expression)) { |
| 908 return _parser.parseExpression2(); |
| 909 } |
| 910 return _notAChild(node); |
| 911 } |
| 912 |
| 913 @override |
| 914 AstNode visitScriptTag(ScriptTag node) => _notAChild(node); |
| 915 |
| 916 @override |
| 917 AstNode visitShowCombinator(ShowCombinator node) { |
| 918 if (node.shownNames.contains(_oldNode)) { |
| 919 return _parser.parseSimpleIdentifier(); |
| 920 } |
| 921 return _notAChild(node); |
| 922 } |
| 923 |
| 924 @override |
| 925 AstNode visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 926 if (identical(_oldNode, node.documentationComment)) { |
| 927 throw new InsufficientContextException(); |
| 928 } else if (node.metadata.contains(_oldNode)) { |
| 929 return _parser.parseAnnotation(); |
| 930 } else if (identical(_oldNode, node.type)) { |
| 931 throw new InsufficientContextException(); |
| 932 } else if (identical(_oldNode, node.identifier)) { |
| 933 throw new InsufficientContextException(); |
| 934 } |
| 935 return _notAChild(node); |
| 936 } |
| 937 |
| 938 @override |
| 939 AstNode visitSimpleIdentifier(SimpleIdentifier node) => _notAChild(node); |
| 940 |
| 941 @override |
| 942 AstNode visitSimpleStringLiteral(SimpleStringLiteral node) => _notAChild(node)
; |
| 943 |
| 944 @override |
| 945 AstNode visitStringInterpolation(StringInterpolation node) { |
| 946 if (node.elements.contains(_oldNode)) { |
| 947 throw new InsufficientContextException(); |
| 948 } |
| 949 return _notAChild(node); |
| 950 } |
| 951 |
| 952 @override |
| 953 AstNode visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 954 if (identical(_oldNode, node.constructorName)) { |
| 955 return _parser.parseSimpleIdentifier(); |
| 956 } else if (identical(_oldNode, node.argumentList)) { |
| 957 return _parser.parseArgumentList(); |
| 958 } |
| 959 return _notAChild(node); |
| 960 } |
| 961 |
| 962 @override |
| 963 AstNode visitSuperExpression(SuperExpression node) => _notAChild(node); |
| 964 |
| 965 @override |
| 966 AstNode visitSwitchCase(SwitchCase node) { |
| 967 if (node.labels.contains(_oldNode)) { |
| 968 return _parser.parseLabel(); |
| 969 } else if (identical(_oldNode, node.expression)) { |
| 970 return _parser.parseExpression2(); |
| 971 } else if (node.statements.contains(_oldNode)) { |
| 972 return _parser.parseStatement2(); |
| 973 } |
| 974 return _notAChild(node); |
| 975 } |
| 976 |
| 977 @override |
| 978 AstNode visitSwitchDefault(SwitchDefault node) { |
| 979 if (node.labels.contains(_oldNode)) { |
| 980 return _parser.parseLabel(); |
| 981 } else if (node.statements.contains(_oldNode)) { |
| 982 return _parser.parseStatement2(); |
| 983 } |
| 984 return _notAChild(node); |
| 985 } |
| 986 |
| 987 @override |
| 988 AstNode visitSwitchStatement(SwitchStatement node) { |
| 989 if (identical(_oldNode, node.expression)) { |
| 990 return _parser.parseExpression2(); |
| 991 } else if (node.members.contains(_oldNode)) { |
| 992 throw new InsufficientContextException(); |
| 993 } |
| 994 return _notAChild(node); |
| 995 } |
| 996 |
| 997 @override |
| 998 AstNode visitSymbolLiteral(SymbolLiteral node) => _notAChild(node); |
| 999 |
| 1000 @override |
| 1001 AstNode visitThisExpression(ThisExpression node) => _notAChild(node); |
| 1002 |
| 1003 @override |
| 1004 AstNode visitThrowExpression(ThrowExpression node) { |
| 1005 if (identical(_oldNode, node.expression)) { |
| 1006 if (_isCascadeAllowedInThrow(node)) { |
| 1007 return _parser.parseExpression2(); |
| 1008 } |
| 1009 return _parser.parseExpressionWithoutCascade(); |
| 1010 } |
| 1011 return _notAChild(node); |
| 1012 } |
| 1013 |
| 1014 @override |
| 1015 AstNode visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 1016 if (identical(_oldNode, node.documentationComment)) { |
| 1017 throw new InsufficientContextException(); |
| 1018 } else if (node.metadata.contains(_oldNode)) { |
| 1019 return _parser.parseAnnotation(); |
| 1020 } else if (identical(_oldNode, node.variables)) { |
| 1021 throw new InsufficientContextException(); |
| 1022 } |
| 1023 return _notAChild(node); |
| 1024 } |
| 1025 |
| 1026 @override |
| 1027 AstNode visitTryStatement(TryStatement node) { |
| 1028 if (identical(_oldNode, node.body)) { |
| 1029 return _parser.parseBlock(); |
| 1030 } else if (node.catchClauses.contains(_oldNode)) { |
| 1031 throw new InsufficientContextException(); |
| 1032 } else if (identical(_oldNode, node.finallyBlock)) { |
| 1033 throw new InsufficientContextException(); |
| 1034 } |
| 1035 return _notAChild(node); |
| 1036 } |
| 1037 |
| 1038 @override |
| 1039 AstNode visitTypeArgumentList(TypeArgumentList node) { |
| 1040 if (node.arguments.contains(_oldNode)) { |
| 1041 return _parser.parseTypeName(); |
| 1042 } |
| 1043 return _notAChild(node); |
| 1044 } |
| 1045 |
| 1046 @override |
| 1047 AstNode visitTypeName(TypeName node) { |
| 1048 if (identical(_oldNode, node.name)) { |
| 1049 return _parser.parsePrefixedIdentifier(); |
| 1050 } else if (identical(_oldNode, node.typeArguments)) { |
| 1051 return _parser.parseTypeArgumentList(); |
| 1052 } |
| 1053 return _notAChild(node); |
| 1054 } |
| 1055 |
| 1056 @override |
| 1057 AstNode visitTypeParameter(TypeParameter node) { |
| 1058 if (identical(_oldNode, node.documentationComment)) { |
| 1059 throw new InsufficientContextException(); |
| 1060 } else if (node.metadata.contains(_oldNode)) { |
| 1061 return _parser.parseAnnotation(); |
| 1062 } else if (identical(_oldNode, node.name)) { |
| 1063 return _parser.parseSimpleIdentifier(); |
| 1064 } else if (identical(_oldNode, node.bound)) { |
| 1065 return _parser.parseTypeName(); |
| 1066 } |
| 1067 return _notAChild(node); |
| 1068 } |
| 1069 |
| 1070 @override |
| 1071 AstNode visitTypeParameterList(TypeParameterList node) { |
| 1072 if (node.typeParameters.contains(node)) { |
| 1073 return _parser.parseTypeParameter(); |
| 1074 } |
| 1075 return _notAChild(node); |
| 1076 } |
| 1077 |
| 1078 @override |
| 1079 AstNode visitVariableDeclaration(VariableDeclaration node) { |
| 1080 if (identical(_oldNode, node.documentationComment)) { |
| 1081 throw new InsufficientContextException(); |
| 1082 } else if (node.metadata.contains(_oldNode)) { |
| 1083 return _parser.parseAnnotation(); |
| 1084 } else if (identical(_oldNode, node.name)) { |
| 1085 throw new InsufficientContextException(); |
| 1086 } else if (identical(_oldNode, node.initializer)) { |
| 1087 throw new InsufficientContextException(); |
| 1088 } |
| 1089 return _notAChild(node); |
| 1090 } |
| 1091 |
| 1092 @override |
| 1093 AstNode visitVariableDeclarationList(VariableDeclarationList node) { |
| 1094 if (identical(_oldNode, node.documentationComment)) { |
| 1095 throw new InsufficientContextException(); |
| 1096 } else if (node.metadata.contains(_oldNode)) { |
| 1097 return _parser.parseAnnotation(); |
| 1098 } else if (node.variables.contains(_oldNode)) { |
| 1099 throw new InsufficientContextException(); |
| 1100 } |
| 1101 return _notAChild(node); |
| 1102 } |
| 1103 |
| 1104 @override |
| 1105 AstNode visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 1106 if (identical(_oldNode, node.variables)) { |
| 1107 throw new InsufficientContextException(); |
| 1108 } |
| 1109 return _notAChild(node); |
| 1110 } |
| 1111 |
| 1112 @override |
| 1113 AstNode visitWhileStatement(WhileStatement node) { |
| 1114 if (identical(_oldNode, node.condition)) { |
| 1115 return _parser.parseExpression2(); |
| 1116 } else if (identical(_oldNode, node.body)) { |
| 1117 return _parser.parseStatement2(); |
| 1118 } |
| 1119 return _notAChild(node); |
| 1120 } |
| 1121 |
| 1122 @override |
| 1123 AstNode visitWithClause(WithClause node) { |
| 1124 if (node.mixinTypes.contains(node)) { |
| 1125 return _parser.parseTypeName(); |
| 1126 } |
| 1127 return _notAChild(node); |
| 1128 } |
| 1129 |
| 1130 @override |
| 1131 AstNode visitYieldStatement(YieldStatement node) { |
| 1132 if (identical(_oldNode, node.expression)) { |
| 1133 return _parser.parseExpression2(); |
| 1134 } |
| 1135 return _notAChild(node); |
| 1136 } |
| 1137 |
| 1138 /** |
| 1139 * Return `true` if the given assignment expression can have a cascade express
ion on the |
| 1140 * right-hand side. |
| 1141 * |
| 1142 * @param node the assignment expression being tested |
| 1143 * @return `true` if the right-hand side can be a cascade expression |
| 1144 */ |
| 1145 bool _isCascadeAllowedInAssignment(AssignmentExpression node) { |
| 1146 // TODO(brianwilkerson) Implement this method. |
| 1147 throw new InsufficientContextException(); |
| 1148 } |
| 1149 |
| 1150 /** |
| 1151 * Return `true` if the given throw expression can have a cascade expression. |
| 1152 * |
| 1153 * @param node the throw expression being tested |
| 1154 * @return `true` if the expression can be a cascade expression |
| 1155 */ |
| 1156 bool _isCascadeAllowedInThrow(ThrowExpression node) { |
| 1157 // TODO(brianwilkerson) Implement this method. |
| 1158 throw new InsufficientContextException(); |
| 1159 } |
| 1160 |
| 1161 /** |
| 1162 * Throw an exception indicating that the visited node was not the parent of t
he node to be |
| 1163 * replaced. |
| 1164 * |
| 1165 * @param visitedNode the visited node that should have been the parent of the
node to be replaced |
| 1166 */ |
| 1167 AstNode _notAChild(AstNode visitedNode) { |
| 1168 throw new IncrementalParseException.con1("Internal error: the visited node (
a ${visitedNode.runtimeType.toString()}) was not the parent of the node to be re
placed (a ${_oldNode.runtimeType.toString()})"); |
| 1169 } |
| 1170 } |
| 1171 |
| 1172 /** |
| 1173 * Instances of the class `IncrementalParseException` represent an exception tha
t occurred |
| 1174 * while attempting to parse a replacement for a specified node in an existing A
ST structure. |
| 1175 */ |
| 1176 class IncrementalParseException extends RuntimeException { |
| 1177 /** |
| 1178 * Initialize a newly created exception to have no message and to be its own c
ause. |
| 1179 */ |
| 1180 IncrementalParseException() : super(); |
| 1181 |
| 1182 /** |
| 1183 * Initialize a newly created exception to have the given message and to be it
s own cause. |
| 1184 * |
| 1185 * @param message the message describing the reason for the exception |
| 1186 */ |
| 1187 IncrementalParseException.con1(String message) : super(message: message); |
| 1188 |
| 1189 /** |
| 1190 * Initialize a newly created exception to have no message and to have the giv
en cause. |
| 1191 * |
| 1192 * @param cause the exception that caused this exception |
| 1193 */ |
| 1194 IncrementalParseException.con2(Exception cause) : super(cause: cause); |
| 1195 } |
| 1196 |
| 1197 /** |
| 1198 * Instances of the class `IncrementalParser` re-parse a single AST structure wi
thin a larger |
| 1199 * AST structure. |
| 1200 */ |
| 1201 class IncrementalParser { |
| 1202 /** |
| 1203 * The source being parsed. |
| 1204 */ |
| 1205 final Source _source; |
| 1206 |
| 1207 /** |
| 1208 * A map from old tokens to new tokens used during the cloning process. |
| 1209 */ |
| 1210 final TokenMap _tokenMap; |
| 1211 |
| 1212 /** |
| 1213 * The error listener that will be informed of any errors that are found durin
g the parse. |
| 1214 */ |
| 1215 final AnalysisErrorListener _errorListener; |
| 1216 |
| 1217 /** |
| 1218 * The node in the AST structure that contains the revised content. |
| 1219 */ |
| 1220 AstNode _updatedNode; |
| 1221 |
| 1222 /** |
| 1223 * Initialize a newly created incremental parser to parse a portion of the con
tent of the given |
| 1224 * source. |
| 1225 * |
| 1226 * @param source the source being parsed |
| 1227 * @param tokenMap a map from old tokens to new tokens used during the cloning
process |
| 1228 * @param errorListener the error listener that will be informed of any errors
that are found |
| 1229 * during the parse |
| 1230 */ |
| 1231 IncrementalParser(this._source, this._tokenMap, this._errorListener); |
| 1232 |
| 1233 /** |
| 1234 * Return the node in the AST structure that contains the revised content. |
| 1235 * |
| 1236 * @return the updated node |
| 1237 */ |
| 1238 AstNode get updatedNode => _updatedNode; |
| 1239 |
| 1240 /** |
| 1241 * Given a range of tokens that were re-scanned, re-parse the minimum number o
f tokens to produce |
| 1242 * a consistent AST structure. The range is represented by the first and last
tokens in the range. |
| 1243 * The tokens are assumed to be contained in the same token stream. |
| 1244 * |
| 1245 * @param leftToken the token in the new token stream immediately to the left
of the range of |
| 1246 * tokens that were inserted |
| 1247 * @param rightToken the token in the new token stream immediately to the righ
t of the range of |
| 1248 * tokens that were inserted |
| 1249 * @param originalStart the offset in the original source of the first charact
er that was modified |
| 1250 * @param originalEnd the offset in the original source of the last character
that was modified |
| 1251 */ |
| 1252 AstNode reparse(AstNode originalStructure, Token leftToken, Token rightToken,
int originalStart, int originalEnd) { |
| 1253 AstNode oldNode = null; |
| 1254 AstNode newNode = null; |
| 1255 // |
| 1256 // Find the first token that needs to be re-parsed. |
| 1257 // |
| 1258 Token firstToken = leftToken.next; |
| 1259 if (identical(firstToken, rightToken)) { |
| 1260 // If there are no new tokens, then we need to include at least one copied
node in the range. |
| 1261 firstToken = leftToken; |
| 1262 } |
| 1263 // |
| 1264 // Find the smallest AST node that encompasses the range of re-scanned token
s. |
| 1265 // |
| 1266 if (originalEnd < originalStart) { |
| 1267 oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructu
re); |
| 1268 } else { |
| 1269 oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(or
iginalStructure); |
| 1270 } |
| 1271 // |
| 1272 // Find the token at which parsing is to begin. |
| 1273 // |
| 1274 int originalOffset = oldNode.offset; |
| 1275 Token parseToken = _findTokenAt(firstToken, originalOffset); |
| 1276 if (parseToken == null) { |
| 1277 return null; |
| 1278 } |
| 1279 // |
| 1280 // Parse the appropriate AST structure starting at the appropriate place. |
| 1281 // |
| 1282 Parser parser = new Parser(_source, _errorListener); |
| 1283 parser.currentToken = parseToken; |
| 1284 while (newNode == null) { |
| 1285 AstNode parent = oldNode.parent; |
| 1286 if (parent == null) { |
| 1287 parseToken = _findFirstToken(parseToken); |
| 1288 parser.currentToken = parseToken; |
| 1289 return parser.parseCompilationUnit2(); |
| 1290 } |
| 1291 bool advanceToParent = false; |
| 1292 try { |
| 1293 IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(p
arser, oldNode); |
| 1294 newNode = parent.accept(dispatcher); |
| 1295 // |
| 1296 // Validate that the new node can replace the old node. |
| 1297 // |
| 1298 Token mappedToken = _tokenMap.get(oldNode.endToken.next); |
| 1299 if (mappedToken == null || mappedToken.offset != newNode.endToken.next.o
ffset || newNode.offset != oldNode.offset) { |
| 1300 advanceToParent = true; |
| 1301 } |
| 1302 } on InsufficientContextException catch (exception) { |
| 1303 advanceToParent = true; |
| 1304 } catch (exception) { |
| 1305 return null; |
| 1306 } |
| 1307 if (advanceToParent) { |
| 1308 newNode = null; |
| 1309 oldNode = parent; |
| 1310 originalOffset = oldNode.offset; |
| 1311 parseToken = _findTokenAt(parseToken, originalOffset); |
| 1312 parser.currentToken = parseToken; |
| 1313 } |
| 1314 } |
| 1315 _updatedNode = newNode; |
| 1316 // |
| 1317 // Replace the old node with the new node in a copy of the original AST stru
cture. |
| 1318 // |
| 1319 if (identical(oldNode, originalStructure)) { |
| 1320 // We ended up re-parsing the whole structure, so there's no need for a co
py. |
| 1321 ResolutionCopier.copyResolutionData(oldNode, newNode); |
| 1322 return newNode; |
| 1323 } |
| 1324 ResolutionCopier.copyResolutionData(oldNode, newNode); |
| 1325 IncrementalAstCloner cloner = new IncrementalAstCloner(oldNode, newNode, _to
kenMap); |
| 1326 return originalStructure.accept(cloner) as AstNode; |
| 1327 } |
| 1328 |
| 1329 /** |
| 1330 * Return the first (non-EOF) token in the token stream containing the given t
oken. |
| 1331 * |
| 1332 * @param firstToken the token from which the search is to begin |
| 1333 * @return the first token in the token stream containing the given token |
| 1334 */ |
| 1335 Token _findFirstToken(Token firstToken) { |
| 1336 while (firstToken.type != TokenType.EOF) { |
| 1337 firstToken = firstToken.previous; |
| 1338 } |
| 1339 return firstToken.next; |
| 1340 } |
| 1341 |
| 1342 /** |
| 1343 * Find the token at or before the given token with the given offset, or `null
` if there is |
| 1344 * no such token. |
| 1345 * |
| 1346 * @param firstToken the token from which the search is to begin |
| 1347 * @param offset the offset of the token to be returned |
| 1348 * @return the token with the given offset |
| 1349 */ |
| 1350 Token _findTokenAt(Token firstToken, int offset) { |
| 1351 while (firstToken.offset > offset && firstToken.type != TokenType.EOF) { |
| 1352 firstToken = firstToken.previous; |
| 1353 } |
| 1354 return firstToken; |
| 1355 } |
| 1356 } |
| 1357 |
| 1358 /** |
| 1359 * Instances of the class `InsufficientContextException` represent a situation i
n which an AST |
| 1360 * node cannot be re-parsed because there is not enough context to know how to r
e-parse the node. |
| 1361 * Clients can attempt to re-parse the parent of the node. |
| 1362 */ |
| 1363 class InsufficientContextException extends IncrementalParseException { |
| 1364 /** |
| 1365 * Initialize a newly created exception to have no message and to be its own c
ause. |
| 1366 */ |
| 1367 InsufficientContextException() : super(); |
| 1368 |
| 1369 /** |
| 1370 * Initialize a newly created exception to have the given message and to be it
s own cause. |
| 1371 * |
| 1372 * @param message the message describing the reason for the exception |
| 1373 */ |
| 1374 InsufficientContextException.con1(String message) : super.con1(message); |
| 1375 |
| 1376 /** |
| 1377 * Initialize a newly created exception to have no message and to have the giv
en cause. |
| 1378 * |
| 1379 * @param cause the exception that caused this exception |
| 1380 */ |
| 1381 InsufficientContextException.con2(Exception cause) : super.con2(cause); |
| 1382 } |
| 1383 |
| 1384 /** |
| 1385 * Instances of the class `Modifiers` implement a simple data-holder for a metho
d that needs |
| 1386 * to return multiple values. |
| 1387 */ |
| 1388 class Modifiers { |
| 1389 /** |
| 1390 * The token representing the keyword 'abstract', or `null` if the keyword was
not found. |
| 1391 */ |
| 1392 Token abstractKeyword; |
| 1393 |
| 1394 /** |
| 1395 * The token representing the keyword 'const', or `null` if the keyword was no
t found. |
| 1396 */ |
| 1397 Token constKeyword; |
| 1398 |
| 1399 /** |
| 1400 * The token representing the keyword 'external', or `null` if the keyword was
not found. |
| 1401 */ |
| 1402 Token externalKeyword; |
| 1403 |
| 1404 /** |
| 1405 * The token representing the keyword 'factory', or `null` if the keyword was
not found. |
| 1406 */ |
| 1407 Token factoryKeyword; |
| 1408 |
| 1409 /** |
| 1410 * The token representing the keyword 'final', or `null` if the keyword was no
t found. |
| 1411 */ |
| 1412 Token finalKeyword; |
| 1413 |
| 1414 /** |
| 1415 * The token representing the keyword 'static', or `null` if the keyword was n
ot found. |
| 1416 */ |
| 1417 Token staticKeyword; |
| 1418 |
| 1419 /** |
| 1420 * The token representing the keyword 'var', or `null` if the keyword was not
found. |
| 1421 */ |
| 1422 Token varKeyword; |
| 1423 |
| 1424 @override |
| 1425 String toString() { |
| 1426 JavaStringBuilder builder = new JavaStringBuilder(); |
| 1427 bool needsSpace = _appendKeyword(builder, false, abstractKeyword); |
| 1428 needsSpace = _appendKeyword(builder, needsSpace, constKeyword); |
| 1429 needsSpace = _appendKeyword(builder, needsSpace, externalKeyword); |
| 1430 needsSpace = _appendKeyword(builder, needsSpace, factoryKeyword); |
| 1431 needsSpace = _appendKeyword(builder, needsSpace, finalKeyword); |
| 1432 needsSpace = _appendKeyword(builder, needsSpace, staticKeyword); |
| 1433 _appendKeyword(builder, needsSpace, varKeyword); |
| 1434 return builder.toString(); |
| 1435 } |
| 1436 |
| 1437 /** |
| 1438 * If the given keyword is not `null`, append it to the given builder, prefixi
ng it with a |
| 1439 * space if needed. |
| 1440 * |
| 1441 * @param builder the builder to which the keyword will be appended |
| 1442 * @param needsSpace `true` if the keyword needs to be prefixed with a space |
| 1443 * @param keyword the keyword to be appended |
| 1444 * @return `true` if subsequent keywords need to be prefixed with a space |
| 1445 */ |
| 1446 bool _appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword)
{ |
| 1447 if (keyword != null) { |
| 1448 if (needsSpace) { |
| 1449 builder.appendChar(0x20); |
| 1450 } |
| 1451 builder.append(keyword.lexeme); |
| 1452 return true; |
| 1453 } |
| 1454 return needsSpace; |
| 1455 } |
| 1456 } |
| 1457 |
| 1458 /** |
| 1459 * Instances of the class `Parser` are used to parse tokens into an AST structur
e. |
| 1460 */ |
| 1461 class Parser { |
| 1462 /** |
| 1463 * The source being parsed. |
| 1464 */ |
| 1465 final Source _source; |
| 1466 |
| 1467 /** |
| 1468 * The error listener that will be informed of any errors that are found durin
g the parse. |
| 1469 */ |
| 1470 final AnalysisErrorListener _errorListener; |
| 1471 |
| 1472 /** |
| 1473 * An [errorListener] lock, if more than `0`, then errors are not reported. |
| 1474 */ |
| 1475 int _errorListenerLock = 0; |
| 1476 |
| 1477 /** |
| 1478 * A flag indicating whether parser is to parse function bodies. |
| 1479 */ |
| 1480 bool _parseFunctionBodies = true; |
| 1481 |
| 1482 /** |
| 1483 * A flag indicating whether the parser is to parse the async support. |
| 1484 */ |
| 1485 bool _parseAsync = AnalysisOptionsImpl.DEFAULT_ENABLE_ASYNC; |
| 1486 |
| 1487 /** |
| 1488 * A flag indicating whether the parser is to parse deferred libraries. |
| 1489 */ |
| 1490 bool _parseDeferredLibraries = AnalysisOptionsImpl.DEFAULT_ENABLE_DEFERRED_LOA
DING; |
| 1491 |
| 1492 /** |
| 1493 * A flag indicating whether the parser is to parse enum declarations. |
| 1494 */ |
| 1495 bool _parseEnum = AnalysisOptionsImpl.DEFAULT_ENABLE_ENUM; |
| 1496 |
| 1497 /** |
| 1498 * The next token to be parsed. |
| 1499 */ |
| 1500 Token _currentToken; |
| 1501 |
| 1502 /** |
| 1503 * A flag indicating whether the parser is currently in a function body marked
as being 'async'. |
| 1504 */ |
| 1505 bool _inAsync = false; |
| 1506 |
| 1507 /** |
| 1508 * A flag indicating whether the parser is currently in the body of a loop. |
| 1509 */ |
| 1510 bool _inLoop = false; |
| 1511 |
| 1512 /** |
| 1513 * A flag indicating whether the parser is currently in a switch statement. |
| 1514 */ |
| 1515 bool _inSwitch = false; |
| 1516 |
| 1517 /** |
| 1518 * A flag indicating whether the parser is currently in a constructor field in
itializer, with no |
| 1519 * intervening parens, braces, or brackets. |
| 1520 */ |
| 1521 bool _inInitializer = false; |
| 1522 |
| 1523 static String ASYNC = "async"; |
| 1524 |
| 1525 static String _AWAIT = "await"; |
| 1526 |
| 1527 static String _HIDE = "hide"; |
| 1528 |
| 1529 static String _OF = "of"; |
| 1530 |
| 1531 static String _ON = "on"; |
| 1532 |
| 1533 static String _NATIVE = "native"; |
| 1534 |
| 1535 static String _SHOW = "show"; |
| 1536 |
| 1537 static String SYNC = "sync"; |
| 1538 |
| 1539 static String _YIELD = "yield"; |
| 1540 |
| 1541 /** |
| 1542 * Initialize a newly created parser. |
| 1543 * |
| 1544 * @param source the source being parsed |
| 1545 * @param errorListener the error listener that will be informed of any errors
that are found |
| 1546 * during the parse |
| 1547 */ |
| 1548 Parser(this._source, this._errorListener); |
| 1549 |
| 1550 /** |
| 1551 * Parse a compilation unit, starting with the given token. |
| 1552 * |
| 1553 * @param token the first token of the compilation unit |
| 1554 * @return the compilation unit that was parsed |
| 1555 */ |
| 1556 CompilationUnit parseCompilationUnit(Token token) { |
| 1557 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi
ne.Parser.parseCompilationUnit"); |
| 1558 try { |
| 1559 _currentToken = token; |
| 1560 return parseCompilationUnit2(); |
| 1561 } finally { |
| 1562 instrumentation.log2(2); |
| 1563 } |
| 1564 } |
| 1565 |
| 1566 /** |
| 1567 * Parse the script tag and directives in a compilation unit, starting with th
e given token, until |
| 1568 * the first non-directive is encountered. The remainder of the compilation un
it will not be |
| 1569 * parsed. Specifically, if there are directives later in the file, they will
not be parsed. |
| 1570 * |
| 1571 * @param token the first token of the compilation unit |
| 1572 * @return the compilation unit that was parsed |
| 1573 */ |
| 1574 CompilationUnit parseDirectives(Token token) { |
| 1575 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi
ne.Parser.parseDirectives"); |
| 1576 try { |
| 1577 _currentToken = token; |
| 1578 return _parseDirectives(); |
| 1579 } finally { |
| 1580 instrumentation.log2(2); |
| 1581 } |
| 1582 } |
| 1583 |
| 1584 /** |
| 1585 * Parse an expression, starting with the given token. |
| 1586 * |
| 1587 * @param token the first token of the expression |
| 1588 * @return the expression that was parsed, or `null` if the tokens do not repr
esent a |
| 1589 * recognizable expression |
| 1590 */ |
| 1591 Expression parseExpression(Token token) { |
| 1592 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi
ne.Parser.parseExpression"); |
| 1593 try { |
| 1594 _currentToken = token; |
| 1595 return parseExpression2(); |
| 1596 } finally { |
| 1597 instrumentation.log(); |
| 1598 } |
| 1599 } |
| 1600 |
| 1601 /** |
| 1602 * Parse a statement, starting with the given token. |
| 1603 * |
| 1604 * @param token the first token of the statement |
| 1605 * @return the statement that was parsed, or `null` if the tokens do not repre
sent a |
| 1606 * recognizable statement |
| 1607 */ |
| 1608 Statement parseStatement(Token token) { |
| 1609 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi
ne.Parser.parseStatement"); |
| 1610 try { |
| 1611 _currentToken = token; |
| 1612 return parseStatement2(); |
| 1613 } finally { |
| 1614 instrumentation.log(); |
| 1615 } |
| 1616 } |
| 1617 |
| 1618 /** |
| 1619 * Parse a sequence of statements, starting with the given token. |
| 1620 * |
| 1621 * @param token the first token of the sequence of statement |
| 1622 * @return the statements that were parsed, or `null` if the tokens do not rep
resent a |
| 1623 * recognizable sequence of statements |
| 1624 */ |
| 1625 List<Statement> parseStatements(Token token) { |
| 1626 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi
ne.Parser.parseStatements"); |
| 1627 try { |
| 1628 _currentToken = token; |
| 1629 return _parseStatementList(); |
| 1630 } finally { |
| 1631 instrumentation.log(); |
| 1632 } |
| 1633 } |
| 1634 |
| 1635 /** |
| 1636 * Set whether the parser is to parse the async support. |
| 1637 * |
| 1638 * @param parseAsync `true` if the parser is to parse the async support |
| 1639 */ |
| 1640 void set parseAsync(bool parseAsync) { |
| 1641 this._parseAsync = parseAsync; |
| 1642 } |
| 1643 |
| 1644 /** |
| 1645 * Set whether the parser is to parse deferred libraries. |
| 1646 * |
| 1647 * @param parseDeferredLibraries `true` if the parser is to parse deferred lib
raries |
| 1648 */ |
| 1649 void set parseDeferredLibraries(bool parseDeferredLibraries) { |
| 1650 this._parseDeferredLibraries = parseDeferredLibraries; |
| 1651 } |
| 1652 |
| 1653 /** |
| 1654 * Set whether the parser is to parse enum declarations. |
| 1655 * |
| 1656 * @param parseEnum `true` if the parser is to parse enum declarations |
| 1657 */ |
| 1658 void set parseEnum(bool parseEnum) { |
| 1659 this._parseEnum = parseEnum; |
| 1660 } |
| 1661 |
| 1662 /** |
| 1663 * Set whether parser is to parse function bodies. |
| 1664 * |
| 1665 * @param parseFunctionBodies `true` if parser is to parse function bodies |
| 1666 */ |
| 1667 void set parseFunctionBodies(bool parseFunctionBodies) { |
| 1668 this._parseFunctionBodies = parseFunctionBodies; |
| 1669 } |
| 1670 |
| 1671 /** |
| 1672 * Parse an annotation. |
| 1673 * |
| 1674 * <pre> |
| 1675 * annotation ::= |
| 1676 * '@' qualified ('.' identifier)? arguments? |
| 1677 * </pre> |
| 1678 * |
| 1679 * @return the annotation that was parsed |
| 1680 */ |
| 1681 Annotation parseAnnotation() { |
| 1682 Token atSign = _expect(TokenType.AT); |
| 1683 Identifier name = parsePrefixedIdentifier(); |
| 1684 Token period = null; |
| 1685 SimpleIdentifier constructorName = null; |
| 1686 if (_matches(TokenType.PERIOD)) { |
| 1687 period = andAdvance; |
| 1688 constructorName = parseSimpleIdentifier(); |
| 1689 } |
| 1690 ArgumentList arguments = null; |
| 1691 if (_matches(TokenType.OPEN_PAREN)) { |
| 1692 arguments = parseArgumentList(); |
| 1693 } |
| 1694 return new Annotation(atSign, name, period, constructorName, arguments); |
| 1695 } |
| 1696 |
| 1697 /** |
| 1698 * Parse an argument. |
| 1699 * |
| 1700 * <pre> |
| 1701 * argument ::= |
| 1702 * namedArgument |
| 1703 * | expression |
| 1704 * |
| 1705 * namedArgument ::= |
| 1706 * label expression |
| 1707 * </pre> |
| 1708 * |
| 1709 * @return the argument that was parsed |
| 1710 */ |
| 1711 Expression parseArgument() { |
| 1712 // |
| 1713 // Both namedArgument and expression can start with an identifier, but only
namedArgument can |
| 1714 // have an identifier followed by a colon. |
| 1715 // |
| 1716 if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) { |
| 1717 return new NamedExpression(parseLabel(), parseExpression2()); |
| 1718 } else { |
| 1719 return parseExpression2(); |
| 1720 } |
| 1721 } |
| 1722 |
| 1723 /** |
| 1724 * Parse a list of arguments. |
| 1725 * |
| 1726 * <pre> |
| 1727 * arguments ::= |
| 1728 * '(' argumentList? ')' |
| 1729 * |
| 1730 * argumentList ::= |
| 1731 * namedArgument (',' namedArgument)* |
| 1732 * | expressionList (',' namedArgument)* |
| 1733 * </pre> |
| 1734 * |
| 1735 * @return the argument list that was parsed |
| 1736 */ |
| 1737 ArgumentList parseArgumentList() { |
| 1738 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 1739 List<Expression> arguments = new List<Expression>(); |
| 1740 if (_matches(TokenType.CLOSE_PAREN)) { |
| 1741 return new ArgumentList(leftParenthesis, arguments, andAdvance); |
| 1742 } |
| 1743 // |
| 1744 // Even though unnamed arguments must all appear before any named arguments,
we allow them to |
| 1745 // appear in any order so that we can recover faster. |
| 1746 // |
| 1747 bool wasInInitializer = _inInitializer; |
| 1748 _inInitializer = false; |
| 1749 try { |
| 1750 Expression argument = parseArgument(); |
| 1751 arguments.add(argument); |
| 1752 bool foundNamedArgument = argument is NamedExpression; |
| 1753 bool generatedError = false; |
| 1754 while (_optional(TokenType.COMMA)) { |
| 1755 argument = parseArgument(); |
| 1756 arguments.add(argument); |
| 1757 if (foundNamedArgument) { |
| 1758 if (!generatedError && argument is! NamedExpression) { |
| 1759 // Report the error, once, but allow the arguments to be in any orde
r in the AST. |
| 1760 _reportErrorForCurrentToken(ParserErrorCode.POSITIONAL_AFTER_NAMED_A
RGUMENT, []); |
| 1761 generatedError = true; |
| 1762 } |
| 1763 } else if (argument is NamedExpression) { |
| 1764 foundNamedArgument = true; |
| 1765 } |
| 1766 } |
| 1767 // TODO(brianwilkerson) Recovery: Look at the left parenthesis to see whet
her there is a |
| 1768 // matching right parenthesis. If there is, then we're more likely missing
a comma and should |
| 1769 // go back to parsing arguments. |
| 1770 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 1771 return new ArgumentList(leftParenthesis, arguments, rightParenthesis); |
| 1772 } finally { |
| 1773 _inInitializer = wasInInitializer; |
| 1774 } |
| 1775 } |
| 1776 |
| 1777 /** |
| 1778 * Parse a bitwise or expression. |
| 1779 * |
| 1780 * <pre> |
| 1781 * bitwiseOrExpression ::= |
| 1782 * bitwiseXorExpression ('|' bitwiseXorExpression)* |
| 1783 * | 'super' ('|' bitwiseXorExpression)+ |
| 1784 * </pre> |
| 1785 * |
| 1786 * @return the bitwise or expression that was parsed |
| 1787 */ |
| 1788 Expression parseBitwiseOrExpression() { |
| 1789 Expression expression; |
| 1790 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.BAR))
{ |
| 1791 expression = new SuperExpression(andAdvance); |
| 1792 } else { |
| 1793 expression = _parseBitwiseXorExpression(); |
| 1794 } |
| 1795 while (_matches(TokenType.BAR)) { |
| 1796 Token operator = andAdvance; |
| 1797 expression = new BinaryExpression(expression, operator, _parseBitwiseXorEx
pression()); |
| 1798 } |
| 1799 return expression; |
| 1800 } |
| 1801 |
| 1802 /** |
| 1803 * Parse a block. |
| 1804 * |
| 1805 * <pre> |
| 1806 * block ::= |
| 1807 * '{' statements '}' |
| 1808 * </pre> |
| 1809 * |
| 1810 * @return the block that was parsed |
| 1811 */ |
| 1812 Block parseBlock() { |
| 1813 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); |
| 1814 List<Statement> statements = new List<Statement>(); |
| 1815 Token statementStart = _currentToken; |
| 1816 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET))
{ |
| 1817 Statement statement = parseStatement2(); |
| 1818 if (statement != null) { |
| 1819 statements.add(statement); |
| 1820 } |
| 1821 if (identical(_currentToken, statementStart)) { |
| 1822 // Ensure that we are making progress and report an error if we're not. |
| 1823 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 1824 _advance(); |
| 1825 } |
| 1826 statementStart = _currentToken; |
| 1827 } |
| 1828 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 1829 return new Block(leftBracket, statements, rightBracket); |
| 1830 } |
| 1831 |
| 1832 /** |
| 1833 * Parse a class member. |
| 1834 * |
| 1835 * <pre> |
| 1836 * classMemberDefinition ::= |
| 1837 * declaration ';' |
| 1838 * | methodSignature functionBody |
| 1839 * </pre> |
| 1840 * |
| 1841 * @param className the name of the class containing the member being parsed |
| 1842 * @return the class member that was parsed, or `null` if what was found was n
ot a valid |
| 1843 * class member |
| 1844 */ |
| 1845 ClassMember parseClassMember(String className) { |
| 1846 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 1847 Modifiers modifiers = _parseModifiers(); |
| 1848 if (_matchesKeyword(Keyword.VOID)) { |
| 1849 TypeName returnType = parseReturnType(); |
| 1850 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) { |
| 1851 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1852 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modif
iers.staticKeyword, returnType); |
| 1853 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek()
)) { |
| 1854 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1855 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modif
iers.staticKeyword, returnType); |
| 1856 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 1857 _validateModifiersForOperator(modifiers); |
| 1858 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, ret
urnType); |
| 1859 } else if (_matchesIdentifier() && _peek().matchesAny([ |
| 1860 TokenType.OPEN_PAREN, |
| 1861 TokenType.OPEN_CURLY_BRACKET, |
| 1862 TokenType.FUNCTION])) { |
| 1863 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1864 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, modifi
ers.externalKeyword, modifiers.staticKeyword, returnType); |
| 1865 } else { |
| 1866 // |
| 1867 // We have found an error of some kind. Try to recover. |
| 1868 // |
| 1869 if (_matchesIdentifier()) { |
| 1870 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMIC
OLON])) { |
| 1871 // |
| 1872 // We appear to have a variable declaration with a type of "void". |
| 1873 // |
| 1874 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, []); |
| 1875 return _parseInitializedIdentifierList(commentAndMetadata, modifiers
.staticKeyword, _validateModifiersForField(modifiers), returnType); |
| 1876 } |
| 1877 } |
| 1878 if (_isOperator(_currentToken)) { |
| 1879 // |
| 1880 // We appear to have found an operator declaration without the 'operat
or' keyword. |
| 1881 // |
| 1882 _validateModifiersForOperator(modifiers); |
| 1883 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, r
eturnType); |
| 1884 } |
| 1885 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken,
[]); |
| 1886 return null; |
| 1887 } |
| 1888 } else if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek()))
{ |
| 1889 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1890 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie
rs.staticKeyword, null); |
| 1891 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek()))
{ |
| 1892 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1893 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modifie
rs.staticKeyword, null); |
| 1894 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 1895 _validateModifiersForOperator(modifiers); |
| 1896 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, null)
; |
| 1897 } else if (!_matchesIdentifier()) { |
| 1898 if (_isOperator(_currentToken)) { |
| 1899 // |
| 1900 // We appear to have found an operator declaration without the 'operator
' keyword. |
| 1901 // |
| 1902 _validateModifiersForOperator(modifiers); |
| 1903 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, nul
l); |
| 1904 } |
| 1905 Token keyword = modifiers.varKeyword; |
| 1906 if (keyword == null) { |
| 1907 keyword = modifiers.finalKeyword; |
| 1908 } |
| 1909 if (keyword == null) { |
| 1910 keyword = modifiers.constKeyword; |
| 1911 } |
| 1912 if (keyword != null) { |
| 1913 // |
| 1914 // We appear to have found an incomplete field declaration. |
| 1915 // |
| 1916 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 1917 List<VariableDeclaration> variables = new List<VariableDeclaration>(); |
| 1918 variables.add(new VariableDeclaration(null, null, _createSyntheticIdenti
fier(), null, null)); |
| 1919 return new FieldDeclaration(commentAndMetadata.comment, commentAndMetada
ta.metadata, null, new VariableDeclarationList(null, null, keyword, null, variab
les), _expectSemicolon()); |
| 1920 } |
| 1921 _reportErrorForToken(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken,
[]); |
| 1922 if (commentAndMetadata.comment != null || !commentAndMetadata.metadata.isE
mpty) { |
| 1923 // |
| 1924 // We appear to have found an incomplete declaration at the end of the c
lass. At this point |
| 1925 // it consists of a metadata, which we don't want to loose, so we'll tre
at it as a method |
| 1926 // declaration with a missing name, parameters and empty body. |
| 1927 // |
| 1928 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetad
ata.metadata, null, null, null, null, null, _createSyntheticIdentifier(), new Fo
rmalParameterList(null, new List<FormalParameter>(), null, null, null), new Empt
yFunctionBody(_createSyntheticToken(TokenType.SEMICOLON))); |
| 1929 } |
| 1930 return null; |
| 1931 } else if (_tokenMatches(_peek(), TokenType.PERIOD) && _tokenMatchesIdentifi
er(_peekAt(2)) && _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) { |
| 1932 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword, _v
alidateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimple
Identifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList()); |
| 1933 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 1934 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 1935 FormalParameterList parameters = parseFormalParameterList(); |
| 1936 if (_matches(TokenType.COLON) || modifiers.factoryKeyword != null || metho
dName.name == className) { |
| 1937 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
_validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodNam
e, null, null, parameters); |
| 1938 } |
| 1939 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1940 _validateFormalParameterList(parameters); |
| 1941 return _parseMethodDeclarationAfterParameters(commentAndMetadata, modifier
s.externalKeyword, modifiers.staticKeyword, null, methodName, parameters); |
| 1942 } else if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMI
COLON])) { |
| 1943 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo
difiers.varKeyword == null) { |
| 1944 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T
YPE, []); |
| 1945 } |
| 1946 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.stati
cKeyword, _validateModifiersForField(modifiers), null); |
| 1947 } |
| 1948 TypeName type = parseTypeName(); |
| 1949 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) { |
| 1950 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1951 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie
rs.staticKeyword, type); |
| 1952 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek()))
{ |
| 1953 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1954 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modifie
rs.staticKeyword, type); |
| 1955 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 1956 _validateModifiersForOperator(modifiers); |
| 1957 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, type)
; |
| 1958 } else if (!_matchesIdentifier()) { |
| 1959 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 1960 // |
| 1961 // We appear to have found an incomplete declaration at the end of the c
lass. At this point |
| 1962 // it consists of a type name, so we'll treat it as a field declaration
with a missing |
| 1963 // field name and semicolon. |
| 1964 // |
| 1965 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.sta
ticKeyword, _validateModifiersForField(modifiers), type); |
| 1966 } |
| 1967 if (_isOperator(_currentToken)) { |
| 1968 // |
| 1969 // We appear to have found an operator declaration without the 'operator
' keyword. |
| 1970 // |
| 1971 _validateModifiersForOperator(modifiers); |
| 1972 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, typ
e); |
| 1973 } |
| 1974 // |
| 1975 // We appear to have found an incomplete declaration before another declar
ation. |
| 1976 // At this point it consists of a type name, so we'll treat it as a field
declaration |
| 1977 // with a missing field name and semicolon. |
| 1978 // |
| 1979 _reportErrorForToken(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken,
[]); |
| 1980 try { |
| 1981 _lockErrorListener(); |
| 1982 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.sta
ticKeyword, _validateModifiersForField(modifiers), type); |
| 1983 } finally { |
| 1984 _unlockErrorListener(); |
| 1985 } |
| 1986 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 1987 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 1988 FormalParameterList parameters = parseFormalParameterList(); |
| 1989 if (methodName.name == className) { |
| 1990 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type,
[]); |
| 1991 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
_validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodNam
e, null, null, parameters); |
| 1992 } |
| 1993 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 1994 _validateFormalParameterList(parameters); |
| 1995 return _parseMethodDeclarationAfterParameters(commentAndMetadata, modifier
s.externalKeyword, modifiers.staticKeyword, type, methodName, parameters); |
| 1996 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { |
| 1997 // We have found "TypeName identifier {", and are guessing that this is a
getter without the |
| 1998 // keyword 'get'. |
| 1999 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2000 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET, []); |
| 2001 _currentToken = _injectToken(new Parser_SyntheticKeywordToken(Keyword.GET,
_currentToken.offset)); |
| 2002 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie
rs.staticKeyword, type); |
| 2003 } |
| 2004 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.staticK
eyword, _validateModifiersForField(modifiers), type); |
| 2005 } |
| 2006 |
| 2007 /** |
| 2008 * Parse a compilation unit. |
| 2009 * |
| 2010 * Specified: |
| 2011 * |
| 2012 * <pre> |
| 2013 * compilationUnit ::= |
| 2014 * scriptTag? directive* topLevelDeclaration* |
| 2015 * </pre> |
| 2016 * Actual: |
| 2017 * |
| 2018 * <pre> |
| 2019 * compilationUnit ::= |
| 2020 * scriptTag? topLevelElement* |
| 2021 * |
| 2022 * topLevelElement ::= |
| 2023 * directive |
| 2024 * | topLevelDeclaration |
| 2025 * </pre> |
| 2026 * |
| 2027 * @return the compilation unit that was parsed |
| 2028 */ |
| 2029 CompilationUnit parseCompilationUnit2() { |
| 2030 Token firstToken = _currentToken; |
| 2031 ScriptTag scriptTag = null; |
| 2032 if (_matches(TokenType.SCRIPT_TAG)) { |
| 2033 scriptTag = new ScriptTag(andAdvance); |
| 2034 } |
| 2035 // |
| 2036 // Even though all directives must appear before declarations and must occur
in a given order, |
| 2037 // we allow directives and declarations to occur in any order so that we can
recover better. |
| 2038 // |
| 2039 bool libraryDirectiveFound = false; |
| 2040 bool partOfDirectiveFound = false; |
| 2041 bool partDirectiveFound = false; |
| 2042 bool directiveFoundAfterDeclaration = false; |
| 2043 List<Directive> directives = new List<Directive>(); |
| 2044 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>()
; |
| 2045 Token memberStart = _currentToken; |
| 2046 while (!_matches(TokenType.EOF)) { |
| 2047 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 2048 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) ||
_matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMa
tches(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_t
okenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 2049 Directive directive = _parseDirective(commentAndMetadata); |
| 2050 if (declarations.length > 0 && !directiveFoundAfterDeclaration) { |
| 2051 _reportErrorForCurrentToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATIO
N, []); |
| 2052 directiveFoundAfterDeclaration = true; |
| 2053 } |
| 2054 if (directive is LibraryDirective) { |
| 2055 if (libraryDirectiveFound) { |
| 2056 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTI
VES, []); |
| 2057 } else { |
| 2058 if (directives.length > 0) { |
| 2059 _reportErrorForToken(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST,
directive.libraryToken, []); |
| 2060 } |
| 2061 libraryDirectiveFound = true; |
| 2062 } |
| 2063 } else if (directive is PartDirective) { |
| 2064 partDirectiveFound = true; |
| 2065 } else if (partDirectiveFound) { |
| 2066 if (directive is ExportDirective) { |
| 2067 _reportErrorForToken(ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIR
ECTIVE, directive.keyword, []); |
| 2068 } else if (directive is ImportDirective) { |
| 2069 _reportErrorForToken(ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIR
ECTIVE, directive.keyword, []); |
| 2070 } |
| 2071 } |
| 2072 if (directive is PartOfDirective) { |
| 2073 if (partOfDirectiveFound) { |
| 2074 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_PART_OF_DIRECTI
VES, []); |
| 2075 } else { |
| 2076 int directiveCount = directives.length; |
| 2077 for (int i = 0; i < directiveCount; i++) { |
| 2078 _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART
, directives[i].keyword, []); |
| 2079 } |
| 2080 partOfDirectiveFound = true; |
| 2081 } |
| 2082 } else { |
| 2083 if (partOfDirectiveFound) { |
| 2084 _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
directive.keyword, []); |
| 2085 } |
| 2086 } |
| 2087 directives.add(directive); |
| 2088 } else if (_matches(TokenType.SEMICOLON)) { |
| 2089 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 2090 _advance(); |
| 2091 } else { |
| 2092 CompilationUnitMember member = _parseCompilationUnitMember(commentAndMet
adata); |
| 2093 if (member != null) { |
| 2094 declarations.add(member); |
| 2095 } |
| 2096 } |
| 2097 if (identical(_currentToken, memberStart)) { |
| 2098 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 2099 _advance(); |
| 2100 while (!_matches(TokenType.EOF) && !_couldBeStartOfCompilationUnitMember
()) { |
| 2101 _advance(); |
| 2102 } |
| 2103 } |
| 2104 memberStart = _currentToken; |
| 2105 } |
| 2106 return new CompilationUnit(firstToken, scriptTag, directives, declarations,
_currentToken); |
| 2107 } |
| 2108 |
| 2109 /** |
| 2110 * Parse a conditional expression. |
| 2111 * |
| 2112 * <pre> |
| 2113 * conditionalExpression ::= |
| 2114 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithout
Cascade)? |
| 2115 * </pre> |
| 2116 * |
| 2117 * @return the conditional expression that was parsed |
| 2118 */ |
| 2119 Expression parseConditionalExpression() { |
| 2120 Expression condition = parseLogicalOrExpression(); |
| 2121 if (!_matches(TokenType.QUESTION)) { |
| 2122 return condition; |
| 2123 } |
| 2124 Token question = andAdvance; |
| 2125 Expression thenExpression = parseExpressionWithoutCascade(); |
| 2126 Token colon = _expect(TokenType.COLON); |
| 2127 Expression elseExpression = parseExpressionWithoutCascade(); |
| 2128 return new ConditionalExpression(condition, question, thenExpression, colon,
elseExpression); |
| 2129 } |
| 2130 |
| 2131 /** |
| 2132 * Parse the name of a constructor. |
| 2133 * |
| 2134 * <pre> |
| 2135 * constructorName: |
| 2136 * type ('.' identifier)? |
| 2137 * </pre> |
| 2138 * |
| 2139 * @return the constructor name that was parsed |
| 2140 */ |
| 2141 ConstructorName parseConstructorName() { |
| 2142 TypeName type = parseTypeName(); |
| 2143 Token period = null; |
| 2144 SimpleIdentifier name = null; |
| 2145 if (_matches(TokenType.PERIOD)) { |
| 2146 period = andAdvance; |
| 2147 name = parseSimpleIdentifier(); |
| 2148 } |
| 2149 return new ConstructorName(type, period, name); |
| 2150 } |
| 2151 |
| 2152 /** |
| 2153 * Parse an expression that might contain a cascade. |
| 2154 * |
| 2155 * <pre> |
| 2156 * expression ::= |
| 2157 * assignableExpression assignmentOperator expression |
| 2158 * | conditionalExpression cascadeSection* |
| 2159 * | throwExpression |
| 2160 * </pre> |
| 2161 * |
| 2162 * @return the expression that was parsed |
| 2163 */ |
| 2164 Expression parseExpression2() { |
| 2165 if (_matchesKeyword(Keyword.THROW)) { |
| 2166 return _parseThrowExpression(); |
| 2167 } else if (_matchesKeyword(Keyword.RETHROW)) { |
| 2168 // TODO(brianwilkerson) Rethrow is a statement again. |
| 2169 return _parseRethrowExpression(); |
| 2170 } |
| 2171 // |
| 2172 // assignableExpression is a subset of conditionalExpression, so we can pars
e a conditional |
| 2173 // expression and then determine whether it is followed by an assignmentOper
ator, checking for |
| 2174 // conformance to the restricted grammar after making that determination. |
| 2175 // |
| 2176 Expression expression = parseConditionalExpression(); |
| 2177 TokenType tokenType = _currentToken.type; |
| 2178 if (tokenType == TokenType.PERIOD_PERIOD) { |
| 2179 List<Expression> cascadeSections = new List<Expression>(); |
| 2180 while (tokenType == TokenType.PERIOD_PERIOD) { |
| 2181 Expression section = _parseCascadeSection(); |
| 2182 if (section != null) { |
| 2183 cascadeSections.add(section); |
| 2184 } |
| 2185 tokenType = _currentToken.type; |
| 2186 } |
| 2187 return new CascadeExpression(expression, cascadeSections); |
| 2188 } else if (tokenType.isAssignmentOperator) { |
| 2189 Token operator = andAdvance; |
| 2190 _ensureAssignable(expression); |
| 2191 return new AssignmentExpression(expression, operator, parseExpression2()); |
| 2192 } |
| 2193 return expression; |
| 2194 } |
| 2195 |
| 2196 /** |
| 2197 * Parse an expression that does not contain any cascades. |
| 2198 * |
| 2199 * <pre> |
| 2200 * expressionWithoutCascade ::= |
| 2201 * assignableExpression assignmentOperator expressionWithoutCascade |
| 2202 * | conditionalExpression |
| 2203 * | throwExpressionWithoutCascade |
| 2204 * </pre> |
| 2205 * |
| 2206 * @return the expression that was parsed |
| 2207 */ |
| 2208 Expression parseExpressionWithoutCascade() { |
| 2209 if (_matchesKeyword(Keyword.THROW)) { |
| 2210 return _parseThrowExpressionWithoutCascade(); |
| 2211 } else if (_matchesKeyword(Keyword.RETHROW)) { |
| 2212 return _parseRethrowExpression(); |
| 2213 } |
| 2214 // |
| 2215 // assignableExpression is a subset of conditionalExpression, so we can pars
e a conditional |
| 2216 // expression and then determine whether it is followed by an assignmentOper
ator, checking for |
| 2217 // conformance to the restricted grammar after making that determination. |
| 2218 // |
| 2219 Expression expression = parseConditionalExpression(); |
| 2220 if (_currentToken.type.isAssignmentOperator) { |
| 2221 Token operator = andAdvance; |
| 2222 _ensureAssignable(expression); |
| 2223 expression = new AssignmentExpression(expression, operator, parseExpressio
nWithoutCascade()); |
| 2224 } |
| 2225 return expression; |
| 2226 } |
| 2227 |
| 2228 /** |
| 2229 * Parse a class extends clause. |
| 2230 * |
| 2231 * <pre> |
| 2232 * classExtendsClause ::= |
| 2233 * 'extends' type |
| 2234 * </pre> |
| 2235 * |
| 2236 * @return the class extends clause that was parsed |
| 2237 */ |
| 2238 ExtendsClause parseExtendsClause() { |
| 2239 Token keyword = _expectKeyword(Keyword.EXTENDS); |
| 2240 TypeName superclass = parseTypeName(); |
| 2241 return new ExtendsClause(keyword, superclass); |
| 2242 } |
| 2243 |
| 2244 /** |
| 2245 * Parse a list of formal parameters. |
| 2246 * |
| 2247 * <pre> |
| 2248 * formalParameterList ::= |
| 2249 * '(' ')' |
| 2250 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' |
| 2251 * | '(' optionalFormalParameters ')' |
| 2252 * |
| 2253 * normalFormalParameters ::= |
| 2254 * normalFormalParameter (',' normalFormalParameter)* |
| 2255 * |
| 2256 * optionalFormalParameters ::= |
| 2257 * optionalPositionalFormalParameters |
| 2258 * | namedFormalParameters |
| 2259 * |
| 2260 * optionalPositionalFormalParameters ::= |
| 2261 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' |
| 2262 * |
| 2263 * namedFormalParameters ::= |
| 2264 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' |
| 2265 * </pre> |
| 2266 * |
| 2267 * @return the formal parameters that were parsed |
| 2268 */ |
| 2269 FormalParameterList parseFormalParameterList() { |
| 2270 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 2271 if (_matches(TokenType.CLOSE_PAREN)) { |
| 2272 return new FormalParameterList(leftParenthesis, null, null, null, andAdvan
ce); |
| 2273 } |
| 2274 // |
| 2275 // Even though it is invalid to have default parameters outside of brackets,
required parameters |
| 2276 // inside of brackets, or multiple groups of default and named parameters, w
e allow all of these |
| 2277 // cases so that we can recover better. |
| 2278 // |
| 2279 List<FormalParameter> parameters = new List<FormalParameter>(); |
| 2280 List<FormalParameter> normalParameters = new List<FormalParameter>(); |
| 2281 List<FormalParameter> positionalParameters = new List<FormalParameter>(); |
| 2282 List<FormalParameter> namedParameters = new List<FormalParameter>(); |
| 2283 List<FormalParameter> currentParameters = normalParameters; |
| 2284 Token leftSquareBracket = null; |
| 2285 Token rightSquareBracket = null; |
| 2286 Token leftCurlyBracket = null; |
| 2287 Token rightCurlyBracket = null; |
| 2288 ParameterKind kind = ParameterKind.REQUIRED; |
| 2289 bool firstParameter = true; |
| 2290 bool reportedMuliplePositionalGroups = false; |
| 2291 bool reportedMulipleNamedGroups = false; |
| 2292 bool reportedMixedGroups = false; |
| 2293 bool wasOptionalParameter = false; |
| 2294 Token initialToken = null; |
| 2295 do { |
| 2296 if (firstParameter) { |
| 2297 firstParameter = false; |
| 2298 } else if (!_optional(TokenType.COMMA)) { |
| 2299 // TODO(brianwilkerson) The token is wrong, we need to recover from this
case. |
| 2300 if (_getEndToken(leftParenthesis) != null) { |
| 2301 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType
.COMMA.lexeme]); |
| 2302 } else { |
| 2303 _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _cur
rentToken.previous, []); |
| 2304 break; |
| 2305 } |
| 2306 } |
| 2307 initialToken = _currentToken; |
| 2308 // |
| 2309 // Handle the beginning of parameter groups. |
| 2310 // |
| 2311 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) { |
| 2312 wasOptionalParameter = true; |
| 2313 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) { |
| 2314 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_POSITIONAL_PARAME
TER_GROUPS, []); |
| 2315 reportedMuliplePositionalGroups = true; |
| 2316 } |
| 2317 if (leftCurlyBracket != null && !reportedMixedGroups) { |
| 2318 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS, []
); |
| 2319 reportedMixedGroups = true; |
| 2320 } |
| 2321 leftSquareBracket = andAdvance; |
| 2322 currentParameters = positionalParameters; |
| 2323 kind = ParameterKind.POSITIONAL; |
| 2324 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 2325 wasOptionalParameter = true; |
| 2326 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) { |
| 2327 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_G
ROUPS, []); |
| 2328 reportedMulipleNamedGroups = true; |
| 2329 } |
| 2330 if (leftSquareBracket != null && !reportedMixedGroups) { |
| 2331 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS, []
); |
| 2332 reportedMixedGroups = true; |
| 2333 } |
| 2334 leftCurlyBracket = andAdvance; |
| 2335 currentParameters = namedParameters; |
| 2336 kind = ParameterKind.NAMED; |
| 2337 } |
| 2338 // |
| 2339 // Parse and record the parameter. |
| 2340 // |
| 2341 FormalParameter parameter = _parseFormalParameter(kind); |
| 2342 parameters.add(parameter); |
| 2343 currentParameters.add(parameter); |
| 2344 if (kind == ParameterKind.REQUIRED && wasOptionalParameter) { |
| 2345 _reportErrorForNode(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, p
arameter, []); |
| 2346 } |
| 2347 // |
| 2348 // Handle the end of parameter groups. |
| 2349 // |
| 2350 // TODO(brianwilkerson) Improve the detection and reporting of missing and
mismatched delimiters. |
| 2351 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) { |
| 2352 rightSquareBracket = andAdvance; |
| 2353 currentParameters = normalParameters; |
| 2354 if (leftSquareBracket == null) { |
| 2355 if (leftCurlyBracket != null) { |
| 2356 _reportErrorForCurrentToken(ParserErrorCode.WRONG_TERMINATOR_FOR_PAR
AMETER_GROUP, ["}"]); |
| 2357 rightCurlyBracket = rightSquareBracket; |
| 2358 rightSquareBracket = null; |
| 2359 } else { |
| 2360 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TERMINATOR_FO
R_PARAMETER_GROUP, ["["]); |
| 2361 } |
| 2362 } |
| 2363 kind = ParameterKind.REQUIRED; |
| 2364 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 2365 rightCurlyBracket = andAdvance; |
| 2366 currentParameters = normalParameters; |
| 2367 if (leftCurlyBracket == null) { |
| 2368 if (leftSquareBracket != null) { |
| 2369 _reportErrorForCurrentToken(ParserErrorCode.WRONG_TERMINATOR_FOR_PAR
AMETER_GROUP, ["]"]); |
| 2370 rightSquareBracket = rightCurlyBracket; |
| 2371 rightCurlyBracket = null; |
| 2372 } else { |
| 2373 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TERMINATOR_FO
R_PARAMETER_GROUP, ["{"]); |
| 2374 } |
| 2375 } |
| 2376 kind = ParameterKind.REQUIRED; |
| 2377 } |
| 2378 } while (!_matches(TokenType.CLOSE_PAREN) && !identical(initialToken, _curre
ntToken)); |
| 2379 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 2380 // |
| 2381 // Check that the groups were closed correctly. |
| 2382 // |
| 2383 if (leftSquareBracket != null && rightSquareBracket == null) { |
| 2384 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMET
ER_GROUP, ["]"]); |
| 2385 } |
| 2386 if (leftCurlyBracket != null && rightCurlyBracket == null) { |
| 2387 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMET
ER_GROUP, ["}"]); |
| 2388 } |
| 2389 // |
| 2390 // Build the parameter list. |
| 2391 // |
| 2392 if (leftSquareBracket == null) { |
| 2393 leftSquareBracket = leftCurlyBracket; |
| 2394 } |
| 2395 if (rightSquareBracket == null) { |
| 2396 rightSquareBracket = rightCurlyBracket; |
| 2397 } |
| 2398 return new FormalParameterList(leftParenthesis, parameters, leftSquareBracke
t, rightSquareBracket, rightParenthesis); |
| 2399 } |
| 2400 |
| 2401 /** |
| 2402 * Parse a function expression. |
| 2403 * |
| 2404 * <pre> |
| 2405 * functionExpression ::= |
| 2406 * formalParameterList functionExpressionBody |
| 2407 * </pre> |
| 2408 * |
| 2409 * @return the function expression that was parsed |
| 2410 */ |
| 2411 FunctionExpression parseFunctionExpression() { |
| 2412 FormalParameterList parameters = parseFormalParameterList(); |
| 2413 _validateFormalParameterList(parameters); |
| 2414 FunctionBody body = _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTI
ON_BODY, true); |
| 2415 return new FunctionExpression(parameters, body); |
| 2416 } |
| 2417 |
| 2418 /** |
| 2419 * Parse an implements clause. |
| 2420 * |
| 2421 * <pre> |
| 2422 * implementsClause ::= |
| 2423 * 'implements' type (',' type)* |
| 2424 * </pre> |
| 2425 * |
| 2426 * @return the implements clause that was parsed |
| 2427 */ |
| 2428 ImplementsClause parseImplementsClause() { |
| 2429 Token keyword = _expectKeyword(Keyword.IMPLEMENTS); |
| 2430 List<TypeName> interfaces = new List<TypeName>(); |
| 2431 interfaces.add(parseTypeName()); |
| 2432 while (_optional(TokenType.COMMA)) { |
| 2433 interfaces.add(parseTypeName()); |
| 2434 } |
| 2435 return new ImplementsClause(keyword, interfaces); |
| 2436 } |
| 2437 |
| 2438 /** |
| 2439 * Parse a label. |
| 2440 * |
| 2441 * <pre> |
| 2442 * label ::= |
| 2443 * identifier ':' |
| 2444 * </pre> |
| 2445 * |
| 2446 * @return the label that was parsed |
| 2447 */ |
| 2448 Label parseLabel() { |
| 2449 SimpleIdentifier label = parseSimpleIdentifier(); |
| 2450 Token colon = _expect(TokenType.COLON); |
| 2451 return new Label(label, colon); |
| 2452 } |
| 2453 |
| 2454 /** |
| 2455 * Parse a library identifier. |
| 2456 * |
| 2457 * <pre> |
| 2458 * libraryIdentifier ::= |
| 2459 * identifier ('.' identifier)* |
| 2460 * </pre> |
| 2461 * |
| 2462 * @return the library identifier that was parsed |
| 2463 */ |
| 2464 LibraryIdentifier parseLibraryIdentifier() { |
| 2465 List<SimpleIdentifier> components = new List<SimpleIdentifier>(); |
| 2466 components.add(parseSimpleIdentifier()); |
| 2467 while (_matches(TokenType.PERIOD)) { |
| 2468 _advance(); |
| 2469 components.add(parseSimpleIdentifier()); |
| 2470 } |
| 2471 return new LibraryIdentifier(components); |
| 2472 } |
| 2473 |
| 2474 /** |
| 2475 * Parse a logical or expression. |
| 2476 * |
| 2477 * <pre> |
| 2478 * logicalOrExpression ::= |
| 2479 * logicalAndExpression ('||' logicalAndExpression)* |
| 2480 * </pre> |
| 2481 * |
| 2482 * @return the logical or expression that was parsed |
| 2483 */ |
| 2484 Expression parseLogicalOrExpression() { |
| 2485 Expression expression = _parseLogicalAndExpression(); |
| 2486 while (_matches(TokenType.BAR_BAR)) { |
| 2487 Token operator = andAdvance; |
| 2488 expression = new BinaryExpression(expression, operator, _parseLogicalAndEx
pression()); |
| 2489 } |
| 2490 return expression; |
| 2491 } |
| 2492 |
| 2493 /** |
| 2494 * Parse a map literal entry. |
| 2495 * |
| 2496 * <pre> |
| 2497 * mapLiteralEntry ::= |
| 2498 * expression ':' expression |
| 2499 * </pre> |
| 2500 * |
| 2501 * @return the map literal entry that was parsed |
| 2502 */ |
| 2503 MapLiteralEntry parseMapLiteralEntry() { |
| 2504 Expression key = parseExpression2(); |
| 2505 Token separator = _expect(TokenType.COLON); |
| 2506 Expression value = parseExpression2(); |
| 2507 return new MapLiteralEntry(key, separator, value); |
| 2508 } |
| 2509 |
| 2510 /** |
| 2511 * Parse a normal formal parameter. |
| 2512 * |
| 2513 * <pre> |
| 2514 * normalFormalParameter ::= |
| 2515 * functionSignature |
| 2516 * | fieldFormalParameter |
| 2517 * | simpleFormalParameter |
| 2518 * |
| 2519 * functionSignature: |
| 2520 * metadata returnType? identifier formalParameterList |
| 2521 * |
| 2522 * fieldFormalParameter ::= |
| 2523 * metadata finalConstVarOrType? 'this' '.' identifier |
| 2524 * |
| 2525 * simpleFormalParameter ::= |
| 2526 * declaredIdentifier |
| 2527 * | metadata identifier |
| 2528 * </pre> |
| 2529 * |
| 2530 * @return the normal formal parameter that was parsed |
| 2531 */ |
| 2532 NormalFormalParameter parseNormalFormalParameter() { |
| 2533 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 2534 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); |
| 2535 Token thisKeyword = null; |
| 2536 Token period = null; |
| 2537 if (_matchesKeyword(Keyword.THIS)) { |
| 2538 thisKeyword = andAdvance; |
| 2539 period = _expect(TokenType.PERIOD); |
| 2540 } |
| 2541 SimpleIdentifier identifier = parseSimpleIdentifier(); |
| 2542 if (_matches(TokenType.OPEN_PAREN)) { |
| 2543 FormalParameterList parameters = parseFormalParameterList(); |
| 2544 if (thisKeyword == null) { |
| 2545 if (holder.keyword != null) { |
| 2546 _reportErrorForToken(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, hol
der.keyword, []); |
| 2547 } |
| 2548 return new FunctionTypedFormalParameter(commentAndMetadata.comment, comm
entAndMetadata.metadata, holder.type, identifier, parameters); |
| 2549 } else { |
| 2550 return new FieldFormalParameter(commentAndMetadata.comment, commentAndMe
tadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, p
arameters); |
| 2551 } |
| 2552 } |
| 2553 TypeName type = holder.type; |
| 2554 if (type != null) { |
| 2555 if (_tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) { |
| 2556 _reportErrorForToken(ParserErrorCode.VOID_PARAMETER, type.name.beginToke
n, []); |
| 2557 } else if (holder.keyword != null && _tokenMatchesKeyword(holder.keyword,
Keyword.VAR)) { |
| 2558 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword, []); |
| 2559 } |
| 2560 } |
| 2561 if (thisKeyword != null) { |
| 2562 return new FieldFormalParameter(commentAndMetadata.comment, commentAndMeta
data.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, nul
l); |
| 2563 } |
| 2564 return new SimpleFormalParameter(commentAndMetadata.comment, commentAndMetad
ata.metadata, holder.keyword, holder.type, identifier); |
| 2565 } |
| 2566 |
| 2567 /** |
| 2568 * Parse a prefixed identifier. |
| 2569 * |
| 2570 * <pre> |
| 2571 * prefixedIdentifier ::= |
| 2572 * identifier ('.' identifier)? |
| 2573 * </pre> |
| 2574 * |
| 2575 * @return the prefixed identifier that was parsed |
| 2576 */ |
| 2577 Identifier parsePrefixedIdentifier() { |
| 2578 SimpleIdentifier qualifier = parseSimpleIdentifier(); |
| 2579 if (!_matches(TokenType.PERIOD)) { |
| 2580 return qualifier; |
| 2581 } |
| 2582 Token period = andAdvance; |
| 2583 SimpleIdentifier qualified = parseSimpleIdentifier(); |
| 2584 return new PrefixedIdentifier(qualifier, period, qualified); |
| 2585 } |
| 2586 |
| 2587 /** |
| 2588 * Parse a return type. |
| 2589 * |
| 2590 * <pre> |
| 2591 * returnType ::= |
| 2592 * 'void' |
| 2593 * | type |
| 2594 * </pre> |
| 2595 * |
| 2596 * @return the return type that was parsed |
| 2597 */ |
| 2598 TypeName parseReturnType() { |
| 2599 if (_matchesKeyword(Keyword.VOID)) { |
| 2600 return new TypeName(new SimpleIdentifier(andAdvance), null); |
| 2601 } else { |
| 2602 return parseTypeName(); |
| 2603 } |
| 2604 } |
| 2605 |
| 2606 /** |
| 2607 * Parse a simple identifier. |
| 2608 * |
| 2609 * <pre> |
| 2610 * identifier ::= |
| 2611 * IDENTIFIER |
| 2612 * </pre> |
| 2613 * |
| 2614 * @return the simple identifier that was parsed |
| 2615 */ |
| 2616 SimpleIdentifier parseSimpleIdentifier() { |
| 2617 if (_matchesIdentifier()) { |
| 2618 return new SimpleIdentifier(andAdvance); |
| 2619 } |
| 2620 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 2621 return _createSyntheticIdentifier(); |
| 2622 } |
| 2623 |
| 2624 /** |
| 2625 * Parse a statement. |
| 2626 * |
| 2627 * <pre> |
| 2628 * statement ::= |
| 2629 * label* nonLabeledStatement |
| 2630 * </pre> |
| 2631 * |
| 2632 * @return the statement that was parsed |
| 2633 */ |
| 2634 Statement parseStatement2() { |
| 2635 List<Label> labels = new List<Label>(); |
| 2636 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) { |
| 2637 labels.add(parseLabel()); |
| 2638 } |
| 2639 Statement statement = _parseNonLabeledStatement(); |
| 2640 if (labels.isEmpty) { |
| 2641 return statement; |
| 2642 } |
| 2643 return new LabeledStatement(labels, statement); |
| 2644 } |
| 2645 |
| 2646 /** |
| 2647 * Parse a string literal. |
| 2648 * |
| 2649 * <pre> |
| 2650 * stringLiteral ::= |
| 2651 * MULTI_LINE_STRING+ |
| 2652 * | SINGLE_LINE_STRING+ |
| 2653 * </pre> |
| 2654 * |
| 2655 * @return the string literal that was parsed |
| 2656 */ |
| 2657 StringLiteral parseStringLiteral() { |
| 2658 List<StringLiteral> strings = new List<StringLiteral>(); |
| 2659 while (_matches(TokenType.STRING)) { |
| 2660 Token string = andAdvance; |
| 2661 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _matches(TokenT
ype.STRING_INTERPOLATION_IDENTIFIER)) { |
| 2662 strings.add(_parseStringInterpolation(string)); |
| 2663 } else { |
| 2664 strings.add(new SimpleStringLiteral(string, _computeStringValue(string.l
exeme, true, true))); |
| 2665 } |
| 2666 } |
| 2667 if (strings.length < 1) { |
| 2668 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL, []); |
| 2669 return _createSyntheticStringLiteral(); |
| 2670 } else if (strings.length == 1) { |
| 2671 return strings[0]; |
| 2672 } else { |
| 2673 return new AdjacentStrings(strings); |
| 2674 } |
| 2675 } |
| 2676 |
| 2677 /** |
| 2678 * Parse a list of type arguments. |
| 2679 * |
| 2680 * <pre> |
| 2681 * typeArguments ::= |
| 2682 * '<' typeList '>' |
| 2683 * |
| 2684 * typeList ::= |
| 2685 * type (',' type)* |
| 2686 * </pre> |
| 2687 * |
| 2688 * @return the type argument list that was parsed |
| 2689 */ |
| 2690 TypeArgumentList parseTypeArgumentList() { |
| 2691 Token leftBracket = _expect(TokenType.LT); |
| 2692 List<TypeName> arguments = new List<TypeName>(); |
| 2693 arguments.add(parseTypeName()); |
| 2694 while (_optional(TokenType.COMMA)) { |
| 2695 arguments.add(parseTypeName()); |
| 2696 } |
| 2697 Token rightBracket = _expectGt(); |
| 2698 return new TypeArgumentList(leftBracket, arguments, rightBracket); |
| 2699 } |
| 2700 |
| 2701 /** |
| 2702 * Parse a type name. |
| 2703 * |
| 2704 * <pre> |
| 2705 * type ::= |
| 2706 * qualified typeArguments? |
| 2707 * </pre> |
| 2708 * |
| 2709 * @return the type name that was parsed |
| 2710 */ |
| 2711 TypeName parseTypeName() { |
| 2712 Identifier typeName; |
| 2713 if (_matchesKeyword(Keyword.VAR)) { |
| 2714 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME, []); |
| 2715 typeName = new SimpleIdentifier(andAdvance); |
| 2716 } else if (_matchesIdentifier()) { |
| 2717 typeName = parsePrefixedIdentifier(); |
| 2718 } else { |
| 2719 typeName = _createSyntheticIdentifier(); |
| 2720 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME, []); |
| 2721 } |
| 2722 TypeArgumentList typeArguments = null; |
| 2723 if (_matches(TokenType.LT)) { |
| 2724 typeArguments = parseTypeArgumentList(); |
| 2725 } |
| 2726 return new TypeName(typeName, typeArguments); |
| 2727 } |
| 2728 |
| 2729 /** |
| 2730 * Parse a type parameter. |
| 2731 * |
| 2732 * <pre> |
| 2733 * typeParameter ::= |
| 2734 * metadata name ('extends' bound)? |
| 2735 * </pre> |
| 2736 * |
| 2737 * @return the type parameter that was parsed |
| 2738 */ |
| 2739 TypeParameter parseTypeParameter() { |
| 2740 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 2741 SimpleIdentifier name = parseSimpleIdentifier(); |
| 2742 if (_matchesKeyword(Keyword.EXTENDS)) { |
| 2743 Token keyword = andAdvance; |
| 2744 TypeName bound = parseTypeName(); |
| 2745 return new TypeParameter(commentAndMetadata.comment, commentAndMetadata.me
tadata, name, keyword, bound); |
| 2746 } |
| 2747 return new TypeParameter(commentAndMetadata.comment, commentAndMetadata.meta
data, name, null, null); |
| 2748 } |
| 2749 |
| 2750 /** |
| 2751 * Parse a list of type parameters. |
| 2752 * |
| 2753 * <pre> |
| 2754 * typeParameterList ::= |
| 2755 * '<' typeParameter (',' typeParameter)* '>' |
| 2756 * </pre> |
| 2757 * |
| 2758 * @return the list of type parameters that were parsed |
| 2759 */ |
| 2760 TypeParameterList parseTypeParameterList() { |
| 2761 Token leftBracket = _expect(TokenType.LT); |
| 2762 List<TypeParameter> typeParameters = new List<TypeParameter>(); |
| 2763 typeParameters.add(parseTypeParameter()); |
| 2764 while (_optional(TokenType.COMMA)) { |
| 2765 typeParameters.add(parseTypeParameter()); |
| 2766 } |
| 2767 Token rightBracket = _expectGt(); |
| 2768 return new TypeParameterList(leftBracket, typeParameters, rightBracket); |
| 2769 } |
| 2770 |
| 2771 /** |
| 2772 * Parse a with clause. |
| 2773 * |
| 2774 * <pre> |
| 2775 * withClause ::= |
| 2776 * 'with' typeName (',' typeName)* |
| 2777 * </pre> |
| 2778 * |
| 2779 * @return the with clause that was parsed |
| 2780 */ |
| 2781 WithClause parseWithClause() { |
| 2782 Token with2 = _expectKeyword(Keyword.WITH); |
| 2783 List<TypeName> types = new List<TypeName>(); |
| 2784 types.add(parseTypeName()); |
| 2785 while (_optional(TokenType.COMMA)) { |
| 2786 types.add(parseTypeName()); |
| 2787 } |
| 2788 return new WithClause(with2, types); |
| 2789 } |
| 2790 |
| 2791 void set currentToken(Token currentToken) { |
| 2792 this._currentToken = currentToken; |
| 2793 } |
| 2794 |
| 2795 /** |
| 2796 * Advance to the next token in the token stream. |
| 2797 */ |
| 2798 void _advance() { |
| 2799 _currentToken = _currentToken.next; |
| 2800 } |
| 2801 |
| 2802 /** |
| 2803 * Append the character equivalent of the given scalar value to the given buil
der. Use the start |
| 2804 * and end indices to report an error, and don't append anything to the builde
r, if the scalar |
| 2805 * value is invalid. |
| 2806 * |
| 2807 * @param builder the builder to which the scalar value is to be appended |
| 2808 * @param escapeSequence the escape sequence that was parsed to produce the sc
alar value |
| 2809 * @param scalarValue the value to be appended |
| 2810 * @param startIndex the index of the first character representing the scalar
value |
| 2811 * @param endIndex the index of the last character representing the scalar val
ue |
| 2812 */ |
| 2813 void _appendScalarValue(JavaStringBuilder builder, String escapeSequence, int
scalarValue, int startIndex, int endIndex) { |
| 2814 if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT || (scalarValu
e >= 0xD800 && scalarValue <= 0xDFFF)) { |
| 2815 _reportErrorForCurrentToken(ParserErrorCode.INVALID_CODE_POINT, [escapeSeq
uence]); |
| 2816 return; |
| 2817 } |
| 2818 if (scalarValue < Character.MAX_VALUE) { |
| 2819 builder.appendChar(scalarValue); |
| 2820 } else { |
| 2821 builder.append(Character.toChars(scalarValue)); |
| 2822 } |
| 2823 } |
| 2824 |
| 2825 /** |
| 2826 * Compute the content of a string with the given literal representation. |
| 2827 * |
| 2828 * @param lexeme the literal representation of the string |
| 2829 * @param first `true` if this is the first token in a string literal |
| 2830 * @param last `true` if this is the last token in a string literal |
| 2831 * @return the actual value of the string |
| 2832 */ |
| 2833 String _computeStringValue(String lexeme, bool first, bool last) { |
| 2834 bool isRaw = false; |
| 2835 int start = 0; |
| 2836 if (first) { |
| 2837 if (StringUtilities.startsWith4(lexeme, 0, 0x72, 0x22, 0x22, 0x22) || Stri
ngUtilities.startsWith4(lexeme, 0, 0x72, 0x27, 0x27, 0x27)) { |
| 2838 isRaw = true; |
| 2839 start += 4; |
| 2840 } else if (StringUtilities.startsWith2(lexeme, 0, 0x72, 0x22) || StringUti
lities.startsWith2(lexeme, 0, 0x72, 0x27)) { |
| 2841 isRaw = true; |
| 2842 start += 2; |
| 2843 } else if (StringUtilities.startsWith3(lexeme, 0, 0x22, 0x22, 0x22) || Str
ingUtilities.startsWith3(lexeme, 0, 0x27, 0x27, 0x27)) { |
| 2844 start += 3; |
| 2845 } else if (StringUtilities.startsWithChar(lexeme, 0x22) || StringUtilities
.startsWithChar(lexeme, 0x27)) { |
| 2846 start += 1; |
| 2847 } |
| 2848 } |
| 2849 int end = lexeme.length; |
| 2850 if (last) { |
| 2851 if (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) || StringUtilities
.endsWith3(lexeme, 0x27, 0x27, 0x27)) { |
| 2852 end -= 3; |
| 2853 } else if (StringUtilities.endsWithChar(lexeme, 0x22) || StringUtilities.e
ndsWithChar(lexeme, 0x27)) { |
| 2854 end -= 1; |
| 2855 } |
| 2856 } |
| 2857 if (end - start + 1 < 0) { |
| 2858 AnalysisEngine.instance.logger.logError("Internal error: computeStringValu
e(${lexeme}, ${first}, ${last})"); |
| 2859 return ""; |
| 2860 } |
| 2861 if (isRaw) { |
| 2862 return lexeme.substring(start, end); |
| 2863 } |
| 2864 JavaStringBuilder builder = new JavaStringBuilder(); |
| 2865 int index = start; |
| 2866 while (index < end) { |
| 2867 index = _translateCharacter(builder, lexeme, index); |
| 2868 } |
| 2869 return builder.toString(); |
| 2870 } |
| 2871 |
| 2872 /** |
| 2873 * Convert the given method declaration into the nearest valid top-level funct
ion declaration. |
| 2874 * |
| 2875 * @param method the method to be converted |
| 2876 * @return the function declaration that most closely captures the components
of the given method |
| 2877 * declaration |
| 2878 */ |
| 2879 FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
new FunctionDeclaration(method.documentationComment, method.metadata, method.ex
ternalKeyword, method.returnType, method.propertyKeyword, method.name, new Funct
ionExpression(method.parameters, method.body)); |
| 2880 |
| 2881 /** |
| 2882 * Return `true` if the current token could be the start of a compilation unit
member. This |
| 2883 * method is used for recovery purposes to decide when to stop skipping tokens
after finding an |
| 2884 * error while parsing a compilation unit member. |
| 2885 * |
| 2886 * @return `true` if the current token could be the start of a compilation uni
t member |
| 2887 */ |
| 2888 bool _couldBeStartOfCompilationUnitMember() { |
| 2889 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) || _
matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMatc
hes(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) { |
| 2890 // This looks like the start of a directive |
| 2891 return true; |
| 2892 } else if (_matchesKeyword(Keyword.CLASS)) { |
| 2893 // This looks like the start of a class definition |
| 2894 return true; |
| 2895 } else if (_matchesKeyword(Keyword.TYPEDEF) && !_tokenMatches(_peek(), Token
Type.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) { |
| 2896 // This looks like the start of a typedef |
| 2897 return true; |
| 2898 } else if (_matchesKeyword(Keyword.VOID) || ((_matchesKeyword(Keyword.GET) |
| _matchesKeyword(Keyword.SET)) && _tokenMatchesIdentifier(_peek())) || (_matche
sKeyword(Keyword.OPERATOR) && _isOperator(_peek()))) { |
| 2899 // This looks like the start of a function |
| 2900 return true; |
| 2901 } else if (_matchesIdentifier()) { |
| 2902 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 2903 // This looks like the start of a function |
| 2904 return true; |
| 2905 } |
| 2906 Token token = _skipReturnType(_currentToken); |
| 2907 if (token == null) { |
| 2908 return false; |
| 2909 } |
| 2910 if (_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET) || (_matc
hesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) || _matchesIdentifier()) { |
| 2911 return true; |
| 2912 } |
| 2913 } |
| 2914 return false; |
| 2915 } |
| 2916 |
| 2917 /** |
| 2918 * Create a synthetic identifier. |
| 2919 * |
| 2920 * @return the synthetic identifier that was created |
| 2921 */ |
| 2922 SimpleIdentifier _createSyntheticIdentifier() { |
| 2923 Token syntheticToken; |
| 2924 if (_currentToken.type == TokenType.KEYWORD) { |
| 2925 // Consider current keyword token as an identifier. |
| 2926 // It is not always true, e.g. "^is T" where "^" is place the place for sy
nthetic identifier. |
| 2927 // By creating SyntheticStringToken we can distinguish a real identifier f
rom synthetic. |
| 2928 // In the code completion behavior will depend on a cursor position - befo
re or on "is". |
| 2929 syntheticToken = _injectToken(new SyntheticStringToken(TokenType.IDENTIFIE
R, _currentToken.lexeme, _currentToken.offset)); |
| 2930 } else { |
| 2931 syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER); |
| 2932 } |
| 2933 return new SimpleIdentifier(syntheticToken); |
| 2934 } |
| 2935 |
| 2936 /** |
| 2937 * Create a synthetic token representing the given keyword. |
| 2938 * |
| 2939 * @return the synthetic token that was created |
| 2940 */ |
| 2941 Token _createSyntheticKeyword(Keyword keyword) => _injectToken(new Parser_Synt
heticKeywordToken(keyword, _currentToken.offset)); |
| 2942 |
| 2943 /** |
| 2944 * Create a synthetic string literal. |
| 2945 * |
| 2946 * @return the synthetic string literal that was created |
| 2947 */ |
| 2948 SimpleStringLiteral _createSyntheticStringLiteral() => new SimpleStringLiteral
(_createSyntheticToken(TokenType.STRING), ""); |
| 2949 |
| 2950 /** |
| 2951 * Create a synthetic token with the given type. |
| 2952 * |
| 2953 * @return the synthetic token that was created |
| 2954 */ |
| 2955 Token _createSyntheticToken(TokenType type) => _injectToken(new StringToken(ty
pe, "", _currentToken.offset)); |
| 2956 |
| 2957 /** |
| 2958 * Check that the given expression is assignable and report an error if it isn
't. |
| 2959 * |
| 2960 * <pre> |
| 2961 * assignableExpression ::= |
| 2962 * primary (arguments* assignableSelector)+ |
| 2963 * | 'super' assignableSelector |
| 2964 * | identifier |
| 2965 * |
| 2966 * assignableSelector ::= |
| 2967 * '[' expression ']' |
| 2968 * | '.' identifier |
| 2969 * </pre> |
| 2970 * |
| 2971 * @param expression the expression being checked |
| 2972 */ |
| 2973 void _ensureAssignable(Expression expression) { |
| 2974 if (expression != null && !expression.isAssignable) { |
| 2975 _reportErrorForCurrentToken(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSI
GNABLE, []); |
| 2976 } |
| 2977 } |
| 2978 |
| 2979 /** |
| 2980 * If the current token has the expected type, return it after advancing to th
e next token. |
| 2981 * Otherwise report an error and return the current token without advancing. N
ote that the method |
| 2982 * [expectGt] should be used if the argument to this method would be [TokenTyp
e#GT] |
| 2983 * . |
| 2984 * |
| 2985 * @param type the type of token that is expected |
| 2986 * @return the token that matched the given type |
| 2987 */ |
| 2988 Token _expect(TokenType type) { |
| 2989 if (_matches(type)) { |
| 2990 return andAdvance; |
| 2991 } |
| 2992 // Remove uses of this method in favor of matches? |
| 2993 // Pass in the error code to use to report the error? |
| 2994 if (type == TokenType.SEMICOLON) { |
| 2995 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou
s, [type.lexeme]); |
| 2996 } else { |
| 2997 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme])
; |
| 2998 } |
| 2999 return _currentToken; |
| 3000 } |
| 3001 |
| 3002 /** |
| 3003 * If the current token has the type [TokenType#GT], return it after advancing
to the next |
| 3004 * token. Otherwise report an error and return the current token without advan
cing. |
| 3005 * |
| 3006 * @return the token that matched the given type |
| 3007 */ |
| 3008 Token _expectGt() { |
| 3009 if (_matchesGt()) { |
| 3010 return andAdvance; |
| 3011 } |
| 3012 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.le
xeme]); |
| 3013 return _currentToken; |
| 3014 } |
| 3015 |
| 3016 /** |
| 3017 * If the current token is a keyword matching the given string, return it afte
r advancing to the |
| 3018 * next token. Otherwise report an error and return the current token without
advancing. |
| 3019 * |
| 3020 * @param keyword the keyword that is expected |
| 3021 * @return the token that matched the given type |
| 3022 */ |
| 3023 Token _expectKeyword(Keyword keyword) { |
| 3024 if (_matchesKeyword(keyword)) { |
| 3025 return andAdvance; |
| 3026 } |
| 3027 // Remove uses of this method in favor of matches? |
| 3028 // Pass in the error code to use to report the error? |
| 3029 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]
); |
| 3030 return _currentToken; |
| 3031 } |
| 3032 |
| 3033 /** |
| 3034 * If [currentToken] is a semicolon, returns it; otherwise reports error and c
reates a |
| 3035 * synthetic one. |
| 3036 * |
| 3037 * TODO(scheglov) consider pushing this into [expect] |
| 3038 */ |
| 3039 Token _expectSemicolon() { |
| 3040 if (_matches(TokenType.SEMICOLON)) { |
| 3041 return andAdvance; |
| 3042 } else { |
| 3043 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou
s, [";"]); |
| 3044 return _createSyntheticToken(TokenType.SEMICOLON); |
| 3045 } |
| 3046 } |
| 3047 |
| 3048 /** |
| 3049 * Search the given list of ranges for a range that contains the given index.
Return the range |
| 3050 * that was found, or `null` if none of the ranges contain the index. |
| 3051 * |
| 3052 * @param ranges the ranges to be searched |
| 3053 * @param index the index contained in the returned range |
| 3054 * @return the range that was found |
| 3055 */ |
| 3056 List<int> _findRange(List<List<int>> ranges, int index) { |
| 3057 int rangeCount = ranges.length; |
| 3058 for (int i = 0; i < rangeCount; i++) { |
| 3059 List<int> range = ranges[i]; |
| 3060 if (range[0] <= index && index <= range[1]) { |
| 3061 return range; |
| 3062 } else if (index < range[0]) { |
| 3063 return null; |
| 3064 } |
| 3065 } |
| 3066 return null; |
| 3067 } |
| 3068 |
| 3069 /** |
| 3070 * Advance to the next token in the token stream, making it the new current to
ken. |
| 3071 * |
| 3072 * @return the token that was current before this method was invoked |
| 3073 */ |
| 3074 Token get andAdvance { |
| 3075 Token token = _currentToken; |
| 3076 _advance(); |
| 3077 return token; |
| 3078 } |
| 3079 |
| 3080 /** |
| 3081 * Return a list of the ranges of characters in the given comment string that
should be treated as |
| 3082 * code blocks. |
| 3083 * |
| 3084 * @param comment the comment being processed |
| 3085 * @return the ranges of characters that should be treated as code blocks |
| 3086 */ |
| 3087 List<List<int>> _getCodeBlockRanges(String comment) { |
| 3088 List<List<int>> ranges = new List<List<int>>(); |
| 3089 int length = comment.length; |
| 3090 if (length < 3) { |
| 3091 return ranges; |
| 3092 } |
| 3093 int index = 0; |
| 3094 int firstChar = comment.codeUnitAt(0); |
| 3095 if (firstChar == 0x2F) { |
| 3096 int secondChar = comment.codeUnitAt(1); |
| 3097 int thirdChar = comment.codeUnitAt(2); |
| 3098 if ((secondChar == 0x2A && thirdChar == 0x2A) || (secondChar == 0x2F && th
irdChar == 0x2F)) { |
| 3099 index = 3; |
| 3100 } |
| 3101 } |
| 3102 while (index < length) { |
| 3103 int currentChar = comment.codeUnitAt(index); |
| 3104 if (currentChar == 0xD || currentChar == 0xA) { |
| 3105 index = index + 1; |
| 3106 while (index < length && Character.isWhitespace(comment.codeUnitAt(index
))) { |
| 3107 index = index + 1; |
| 3108 } |
| 3109 if (StringUtilities.startsWith6(comment, index, 0x2A, 0x20, 0x20, 0x20,
0x20, 0x20)) { |
| 3110 int end = index + 6; |
| 3111 while (end < length && comment.codeUnitAt(end) != 0xD && comment.codeU
nitAt(end) != 0xA) { |
| 3112 end = end + 1; |
| 3113 } |
| 3114 ranges.add(<int> [index, end]); |
| 3115 index = end; |
| 3116 } |
| 3117 } else if (index + 1 < length && currentChar == 0x5B && comment.codeUnitAt
(index + 1) == 0x3A) { |
| 3118 int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D); |
| 3119 if (end < 0) { |
| 3120 end = length; |
| 3121 } |
| 3122 ranges.add(<int> [index, end]); |
| 3123 index = end + 1; |
| 3124 } else { |
| 3125 index = index + 1; |
| 3126 } |
| 3127 } |
| 3128 return ranges; |
| 3129 } |
| 3130 |
| 3131 /** |
| 3132 * Return the end token associated with the given begin token, or `null` if ei
ther the given |
| 3133 * token is not a begin token or it does not have an end token associated with
it. |
| 3134 * |
| 3135 * @param beginToken the token that is expected to have an end token associate
d with it |
| 3136 * @return the end token associated with the begin token |
| 3137 */ |
| 3138 Token _getEndToken(Token beginToken) { |
| 3139 if (beginToken is BeginToken) { |
| 3140 return beginToken.endToken; |
| 3141 } |
| 3142 return null; |
| 3143 } |
| 3144 |
| 3145 /** |
| 3146 * Return `true` if the current token is the first token of a return type that
is followed |
| 3147 * by an identifier, possibly followed by a list of type parameters, followed
by a |
| 3148 * left-parenthesis. This is used by parseTypeAlias to determine whether or no
t to parse a return |
| 3149 * type. |
| 3150 * |
| 3151 * @return `true` if we can successfully parse the rest of a type alias if we
first parse a |
| 3152 * return type. |
| 3153 */ |
| 3154 bool get hasReturnTypeInTypeAlias { |
| 3155 Token next = _skipReturnType(_currentToken); |
| 3156 if (next == null) { |
| 3157 return false; |
| 3158 } |
| 3159 return _tokenMatchesIdentifier(next); |
| 3160 } |
| 3161 |
| 3162 /** |
| 3163 * Inject the given token into the token stream immediately before the current
token. |
| 3164 * |
| 3165 * @param token the token to be added to the token stream |
| 3166 * @return the token that was just added to the token stream |
| 3167 */ |
| 3168 Token _injectToken(Token token) { |
| 3169 Token previous = _currentToken.previous; |
| 3170 token.setNext(_currentToken); |
| 3171 previous.setNext(token); |
| 3172 return token; |
| 3173 } |
| 3174 |
| 3175 /** |
| 3176 * Return `true` if the current token appears to be the beginning of a functio
n declaration. |
| 3177 * |
| 3178 * @return `true` if the current token appears to be the beginning of a functi
on declaration |
| 3179 */ |
| 3180 bool _isFunctionDeclaration() { |
| 3181 if (_matchesKeyword(Keyword.VOID)) { |
| 3182 return true; |
| 3183 } |
| 3184 Token afterReturnType = _skipTypeName(_currentToken); |
| 3185 if (afterReturnType == null) { |
| 3186 // There was no return type, but it is optional, so go back to where we st
arted. |
| 3187 afterReturnType = _currentToken; |
| 3188 } |
| 3189 Token afterIdentifier = _skipSimpleIdentifier(afterReturnType); |
| 3190 if (afterIdentifier == null) { |
| 3191 // It's possible that we parsed the function name as if it were a type nam
e, so see whether |
| 3192 // it makes sense if we assume that there is no type. |
| 3193 afterIdentifier = _skipSimpleIdentifier(_currentToken); |
| 3194 } |
| 3195 if (afterIdentifier == null) { |
| 3196 return false; |
| 3197 } |
| 3198 if (_isFunctionExpression(afterIdentifier)) { |
| 3199 return true; |
| 3200 } |
| 3201 // It's possible that we have found a getter. While this isn't valid at this
point we test for |
| 3202 // it in order to recover better. |
| 3203 if (_matchesKeyword(Keyword.GET)) { |
| 3204 Token afterName = _skipSimpleIdentifier(_currentToken.next); |
| 3205 if (afterName == null) { |
| 3206 return false; |
| 3207 } |
| 3208 return _tokenMatches(afterName, TokenType.FUNCTION) || _tokenMatches(after
Name, TokenType.OPEN_CURLY_BRACKET); |
| 3209 } |
| 3210 return false; |
| 3211 } |
| 3212 |
| 3213 /** |
| 3214 * Return `true` if the given token appears to be the beginning of a function
expression. |
| 3215 * |
| 3216 * @param startToken the token that might be the start of a function expressio
n |
| 3217 * @return `true` if the given token appears to be the beginning of a function
expression |
| 3218 */ |
| 3219 bool _isFunctionExpression(Token startToken) { |
| 3220 // Function expressions aren't allowed in initializer lists. |
| 3221 if (_inInitializer) { |
| 3222 return false; |
| 3223 } |
| 3224 Token afterParameters = _skipFormalParameterList(startToken); |
| 3225 if (afterParameters == null) { |
| 3226 return false; |
| 3227 } |
| 3228 if (afterParameters.matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNC
TION])) { |
| 3229 return true; |
| 3230 } |
| 3231 if (_parseAsync) { |
| 3232 String lexeme = afterParameters.lexeme; |
| 3233 return lexeme == ASYNC || lexeme == SYNC; |
| 3234 } |
| 3235 return false; |
| 3236 } |
| 3237 |
| 3238 /** |
| 3239 * Return `true` if the given character is a valid hexadecimal digit. |
| 3240 * |
| 3241 * @param character the character being tested |
| 3242 * @return `true` if the character is a valid hexadecimal digit |
| 3243 */ |
| 3244 bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) ||
(0x41 <= character && character <= 0x46) || (0x61 <= character && character <=
0x66); |
| 3245 |
| 3246 /** |
| 3247 * Return `true` if the current token is the first token in an initialized var
iable |
| 3248 * declaration rather than an expression. This method assumes that we have alr
eady skipped past |
| 3249 * any metadata that might be associated with the declaration. |
| 3250 * |
| 3251 * <pre> |
| 3252 * initializedVariableDeclaration ::= |
| 3253 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)* |
| 3254 * |
| 3255 * declaredIdentifier ::= |
| 3256 * metadata finalConstVarOrType identifier |
| 3257 * |
| 3258 * finalConstVarOrType ::= |
| 3259 * 'final' type? |
| 3260 * | 'const' type? |
| 3261 * | 'var' |
| 3262 * | type |
| 3263 * |
| 3264 * type ::= |
| 3265 * qualified typeArguments? |
| 3266 * |
| 3267 * initializedIdentifier ::= |
| 3268 * identifier ('=' expression)? |
| 3269 * </pre> |
| 3270 * |
| 3271 * @return `true` if the current token is the first token in an initialized va
riable |
| 3272 * declaration |
| 3273 */ |
| 3274 bool _isInitializedVariableDeclaration() { |
| 3275 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.VAR)) { |
| 3276 // An expression cannot start with a keyword other than 'const', 'rethrow'
, or 'throw'. |
| 3277 return true; |
| 3278 } |
| 3279 if (_matchesKeyword(Keyword.CONST)) { |
| 3280 // Look to see whether we might be at the start of a list or map literal,
otherwise this |
| 3281 // should be the start of a variable declaration. |
| 3282 return !_peek().matchesAny([ |
| 3283 TokenType.LT, |
| 3284 TokenType.OPEN_CURLY_BRACKET, |
| 3285 TokenType.OPEN_SQUARE_BRACKET, |
| 3286 TokenType.INDEX]); |
| 3287 } |
| 3288 // We know that we have an identifier, and need to see whether it might be a
type name. |
| 3289 Token token = _skipTypeName(_currentToken); |
| 3290 if (token == null) { |
| 3291 // There was no type name, so this can't be a declaration. |
| 3292 return false; |
| 3293 } |
| 3294 token = _skipSimpleIdentifier(token); |
| 3295 if (token == null) { |
| 3296 return false; |
| 3297 } |
| 3298 TokenType type = token.type; |
| 3299 return type == TokenType.EQ || type == TokenType.COMMA || type == TokenType.
SEMICOLON || _tokenMatchesKeyword(token, Keyword.IN); |
| 3300 } |
| 3301 |
| 3302 /** |
| 3303 * Given that we have just found bracketed text within a comment, look to see
whether that text is |
| 3304 * (a) followed by a parenthesized link address, (b) followed by a colon, or (
c) followed by |
| 3305 * optional whitespace and another square bracket. |
| 3306 * |
| 3307 * This method uses the syntax described by the <a |
| 3308 * href="http://daringfireball.net/projects/markdown/syntax">markdown</a> proj
ect. |
| 3309 * |
| 3310 * @param comment the comment text in which the bracketed text was found |
| 3311 * @param rightIndex the index of the right bracket |
| 3312 * @return `true` if the bracketed text is followed by a link address |
| 3313 */ |
| 3314 bool _isLinkText(String comment, int rightIndex) { |
| 3315 int length = comment.length; |
| 3316 int index = rightIndex + 1; |
| 3317 if (index >= length) { |
| 3318 return false; |
| 3319 } |
| 3320 int nextChar = comment.codeUnitAt(index); |
| 3321 if (nextChar == 0x28 || nextChar == 0x3A) { |
| 3322 return true; |
| 3323 } |
| 3324 while (Character.isWhitespace(nextChar)) { |
| 3325 index = index + 1; |
| 3326 if (index >= length) { |
| 3327 return false; |
| 3328 } |
| 3329 nextChar = comment.codeUnitAt(index); |
| 3330 } |
| 3331 return nextChar == 0x5B; |
| 3332 } |
| 3333 |
| 3334 /** |
| 3335 * Return `true` if the given token appears to be the beginning of an operator
declaration. |
| 3336 * |
| 3337 * @param startToken the token that might be the start of an operator declarat
ion |
| 3338 * @return `true` if the given token appears to be the beginning of an operato
r declaration |
| 3339 */ |
| 3340 bool _isOperator(Token startToken) { |
| 3341 // Accept any operator here, even if it is not user definable. |
| 3342 if (!startToken.isOperator) { |
| 3343 return false; |
| 3344 } |
| 3345 // Token "=" means that it is actually field initializer. |
| 3346 if (startToken.type == TokenType.EQ) { |
| 3347 return false; |
| 3348 } |
| 3349 // Consume all operator tokens. |
| 3350 Token token = startToken.next; |
| 3351 while (token.isOperator) { |
| 3352 token = token.next; |
| 3353 } |
| 3354 // Formal parameter list is expect now. |
| 3355 return _tokenMatches(token, TokenType.OPEN_PAREN); |
| 3356 } |
| 3357 |
| 3358 /** |
| 3359 * Return `true` if the current token appears to be the beginning of a switch
member. |
| 3360 * |
| 3361 * @return `true` if the current token appears to be the beginning of a switch
member |
| 3362 */ |
| 3363 bool _isSwitchMember() { |
| 3364 Token token = _currentToken; |
| 3365 while (_tokenMatches(token, TokenType.IDENTIFIER) && _tokenMatches(token.nex
t, TokenType.COLON)) { |
| 3366 token = token.next.next; |
| 3367 } |
| 3368 if (token.type == TokenType.KEYWORD) { |
| 3369 Keyword keyword = (token as KeywordToken).keyword; |
| 3370 return keyword == Keyword.CASE || keyword == Keyword.DEFAULT; |
| 3371 } |
| 3372 return false; |
| 3373 } |
| 3374 |
| 3375 /** |
| 3376 * Return `true` if the given token appears to be the first token of a type na
me that is |
| 3377 * followed by a variable or field formal parameter. |
| 3378 * |
| 3379 * @param startToken the first token of the sequence being checked |
| 3380 * @return `true` if there is a type name and variable starting at the given t
oken |
| 3381 */ |
| 3382 bool _isTypedIdentifier(Token startToken) { |
| 3383 Token token = _skipReturnType(startToken); |
| 3384 if (token == null) { |
| 3385 return false; |
| 3386 } else if (_tokenMatchesIdentifier(token)) { |
| 3387 return true; |
| 3388 } else if (_tokenMatchesKeyword(token, Keyword.THIS) && _tokenMatches(token.
next, TokenType.PERIOD) && _tokenMatchesIdentifier(token.next.next)) { |
| 3389 return true; |
| 3390 } |
| 3391 return false; |
| 3392 } |
| 3393 |
| 3394 /** |
| 3395 * Compare the given tokens to find the token that appears first in the source
being parsed. That |
| 3396 * is, return the left-most of all of the tokens. The arguments are allowed to
be `null`. |
| 3397 * Return the token with the smallest offset, or `null` if there are no argume
nts or if all |
| 3398 * of the arguments are `null`. |
| 3399 * |
| 3400 * @param tokens the tokens being compared |
| 3401 * @return the token with the smallest offset |
| 3402 */ |
| 3403 Token _lexicallyFirst(List<Token> tokens) { |
| 3404 Token first = null; |
| 3405 int firstOffset = 2147483647; |
| 3406 for (Token token in tokens) { |
| 3407 if (token != null) { |
| 3408 int offset = token.offset; |
| 3409 if (offset < firstOffset) { |
| 3410 first = token; |
| 3411 firstOffset = offset; |
| 3412 } |
| 3413 } |
| 3414 } |
| 3415 return first; |
| 3416 } |
| 3417 |
| 3418 /** |
| 3419 * Increments the error reporting lock level. If level is more than `0`, then |
| 3420 * [reportError] wont report any error. |
| 3421 */ |
| 3422 void _lockErrorListener() { |
| 3423 _errorListenerLock++; |
| 3424 } |
| 3425 |
| 3426 /** |
| 3427 * Return `true` if the current token has the given type. Note that the method |
| 3428 * [matchesGt] should be used if the argument to this method would be |
| 3429 * [TokenType#GT]. |
| 3430 * |
| 3431 * @param type the type of token that can optionally appear in the current loc
ation |
| 3432 * @return `true` if the current token has the given type |
| 3433 */ |
| 3434 bool _matches(TokenType type) => _currentToken.type == type; |
| 3435 |
| 3436 /** |
| 3437 * Return `true` if the current token has a type of [TokenType#GT]. Note that
this |
| 3438 * method, unlike other variants, will modify the token stream if possible to
match desired type. |
| 3439 * In particular, if the next token is either a '>>' or '>>>', the token strea
m will be re-written |
| 3440 * and `true` will be returned. |
| 3441 * |
| 3442 * @return `true` if the current token has a type of [TokenType#GT] |
| 3443 */ |
| 3444 bool _matchesGt() { |
| 3445 TokenType currentType = _currentToken.type; |
| 3446 if (currentType == TokenType.GT) { |
| 3447 return true; |
| 3448 } else if (currentType == TokenType.GT_GT) { |
| 3449 int offset = _currentToken.offset; |
| 3450 Token first = new Token(TokenType.GT, offset); |
| 3451 Token second = new Token(TokenType.GT, offset + 1); |
| 3452 second.setNext(_currentToken.next); |
| 3453 first.setNext(second); |
| 3454 _currentToken.previous.setNext(first); |
| 3455 _currentToken = first; |
| 3456 return true; |
| 3457 } else if (currentType == TokenType.GT_EQ) { |
| 3458 int offset = _currentToken.offset; |
| 3459 Token first = new Token(TokenType.GT, offset); |
| 3460 Token second = new Token(TokenType.EQ, offset + 1); |
| 3461 second.setNext(_currentToken.next); |
| 3462 first.setNext(second); |
| 3463 _currentToken.previous.setNext(first); |
| 3464 _currentToken = first; |
| 3465 return true; |
| 3466 } else if (currentType == TokenType.GT_GT_EQ) { |
| 3467 int offset = _currentToken.offset; |
| 3468 Token first = new Token(TokenType.GT, offset); |
| 3469 Token second = new Token(TokenType.GT, offset + 1); |
| 3470 Token third = new Token(TokenType.EQ, offset + 2); |
| 3471 third.setNext(_currentToken.next); |
| 3472 second.setNext(third); |
| 3473 first.setNext(second); |
| 3474 _currentToken.previous.setNext(first); |
| 3475 _currentToken = first; |
| 3476 return true; |
| 3477 } |
| 3478 return false; |
| 3479 } |
| 3480 |
| 3481 /** |
| 3482 * Return `true` if the current token is a valid identifier. Valid identifiers
include |
| 3483 * built-in identifiers (pseudo-keywords). |
| 3484 * |
| 3485 * @return `true` if the current token is a valid identifier |
| 3486 */ |
| 3487 bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken); |
| 3488 |
| 3489 /** |
| 3490 * Return `true` if the current token matches the given keyword. |
| 3491 * |
| 3492 * @param keyword the keyword that can optionally appear in the current locati
on |
| 3493 * @return `true` if the current token matches the given keyword |
| 3494 */ |
| 3495 bool _matchesKeyword(Keyword keyword) => _tokenMatchesKeyword(_currentToken, k
eyword); |
| 3496 |
| 3497 /** |
| 3498 * Return `true` if the current token matches the given identifier. |
| 3499 * |
| 3500 * @param identifier the identifier that can optionally appear in the current
location |
| 3501 * @return `true` if the current token matches the given identifier |
| 3502 */ |
| 3503 bool _matchesString(String identifier) => _currentToken.type == TokenType.IDEN
TIFIER && _currentToken.lexeme == identifier; |
| 3504 |
| 3505 /** |
| 3506 * If the current token has the given type, then advance to the next token and
return `true` |
| 3507 * . Otherwise, return `false` without advancing. This method should not be in
voked with an |
| 3508 * argument value of [TokenType#GT]. |
| 3509 * |
| 3510 * @param type the type of token that can optionally appear in the current loc
ation |
| 3511 * @return `true` if the current token has the given type |
| 3512 */ |
| 3513 bool _optional(TokenType type) { |
| 3514 if (_matches(type)) { |
| 3515 _advance(); |
| 3516 return true; |
| 3517 } |
| 3518 return false; |
| 3519 } |
| 3520 |
| 3521 /** |
| 3522 * Parse an additive expression. |
| 3523 * |
| 3524 * <pre> |
| 3525 * additiveExpression ::= |
| 3526 * multiplicativeExpression (additiveOperator multiplicativeExpression)* |
| 3527 * | 'super' (additiveOperator multiplicativeExpression)+ |
| 3528 * </pre> |
| 3529 * |
| 3530 * @return the additive expression that was parsed |
| 3531 */ |
| 3532 Expression _parseAdditiveExpression() { |
| 3533 Expression expression; |
| 3534 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isAdditiveOper
ator) { |
| 3535 expression = new SuperExpression(andAdvance); |
| 3536 } else { |
| 3537 expression = _parseMultiplicativeExpression(); |
| 3538 } |
| 3539 while (_currentToken.type.isAdditiveOperator) { |
| 3540 Token operator = andAdvance; |
| 3541 expression = new BinaryExpression(expression, operator, _parseMultiplicati
veExpression()); |
| 3542 } |
| 3543 return expression; |
| 3544 } |
| 3545 |
| 3546 /** |
| 3547 * Parse an assert statement. |
| 3548 * |
| 3549 * <pre> |
| 3550 * assertStatement ::= |
| 3551 * 'assert' '(' conditionalExpression ')' ';' |
| 3552 * </pre> |
| 3553 * |
| 3554 * @return the assert statement |
| 3555 */ |
| 3556 AssertStatement _parseAssertStatement() { |
| 3557 Token keyword = _expectKeyword(Keyword.ASSERT); |
| 3558 Token leftParen = _expect(TokenType.OPEN_PAREN); |
| 3559 Expression expression = parseExpression2(); |
| 3560 if (expression is AssignmentExpression) { |
| 3561 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expre
ssion, []); |
| 3562 } else if (expression is CascadeExpression) { |
| 3563 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expressi
on, []); |
| 3564 } else if (expression is ThrowExpression) { |
| 3565 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression
, []); |
| 3566 } else if (expression is RethrowExpression) { |
| 3567 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expressi
on, []); |
| 3568 } |
| 3569 Token rightParen = _expect(TokenType.CLOSE_PAREN); |
| 3570 Token semicolon = _expect(TokenType.SEMICOLON); |
| 3571 return new AssertStatement(keyword, leftParen, expression, rightParen, semic
olon); |
| 3572 } |
| 3573 |
| 3574 /** |
| 3575 * Parse an assignable expression. |
| 3576 * |
| 3577 * <pre> |
| 3578 * assignableExpression ::= |
| 3579 * primary (arguments* assignableSelector)+ |
| 3580 * | 'super' assignableSelector |
| 3581 * | identifier |
| 3582 * </pre> |
| 3583 * |
| 3584 * @param primaryAllowed `true` if the expression is allowed to be a primary w
ithout any |
| 3585 * assignable selector |
| 3586 * @return the assignable expression that was parsed |
| 3587 */ |
| 3588 Expression _parseAssignableExpression(bool primaryAllowed) { |
| 3589 if (_matchesKeyword(Keyword.SUPER)) { |
| 3590 return _parseAssignableSelector(new SuperExpression(andAdvance), false); |
| 3591 } |
| 3592 // |
| 3593 // A primary expression can start with an identifier. We resolve the ambigui
ty by determining |
| 3594 // whether the primary consists of anything other than an identifier and/or
is followed by an |
| 3595 // assignableSelector. |
| 3596 // |
| 3597 Expression expression = _parsePrimaryExpression(); |
| 3598 bool isOptional = primaryAllowed || expression is SimpleIdentifier; |
| 3599 while (true) { |
| 3600 while (_matches(TokenType.OPEN_PAREN)) { |
| 3601 ArgumentList argumentList = parseArgumentList(); |
| 3602 if (expression is SimpleIdentifier) { |
| 3603 expression = new MethodInvocation(null, null, expression as SimpleIden
tifier, argumentList); |
| 3604 } else if (expression is PrefixedIdentifier) { |
| 3605 PrefixedIdentifier identifier = expression as PrefixedIdentifier; |
| 3606 expression = new MethodInvocation(identifier.prefix, identifier.period
, identifier.identifier, argumentList); |
| 3607 } else if (expression is PropertyAccess) { |
| 3608 PropertyAccess access = expression as PropertyAccess; |
| 3609 expression = new MethodInvocation(access.target, access.operator, acce
ss.propertyName, argumentList); |
| 3610 } else { |
| 3611 expression = new FunctionExpressionInvocation(expression, argumentList
); |
| 3612 } |
| 3613 if (!primaryAllowed) { |
| 3614 isOptional = false; |
| 3615 } |
| 3616 } |
| 3617 Expression selectorExpression = _parseAssignableSelector(expression, isOpt
ional || (expression is PrefixedIdentifier)); |
| 3618 if (identical(selectorExpression, expression)) { |
| 3619 if (!isOptional && (expression is PrefixedIdentifier)) { |
| 3620 PrefixedIdentifier identifier = expression as PrefixedIdentifier; |
| 3621 expression = new PropertyAccess(identifier.prefix, identifier.period,
identifier.identifier); |
| 3622 } |
| 3623 return expression; |
| 3624 } |
| 3625 expression = selectorExpression; |
| 3626 isOptional = true; |
| 3627 } |
| 3628 } |
| 3629 |
| 3630 /** |
| 3631 * Parse an assignable selector. |
| 3632 * |
| 3633 * <pre> |
| 3634 * assignableSelector ::= |
| 3635 * '[' expression ']' |
| 3636 * | '.' identifier |
| 3637 * </pre> |
| 3638 * |
| 3639 * @param prefix the expression preceding the selector |
| 3640 * @param optional `true` if the selector is optional |
| 3641 * @return the assignable selector that was parsed, or the original prefix if
there was no |
| 3642 * assignable selector |
| 3643 */ |
| 3644 Expression _parseAssignableSelector(Expression prefix, bool optional) { |
| 3645 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) { |
| 3646 Token leftBracket = andAdvance; |
| 3647 bool wasInInitializer = _inInitializer; |
| 3648 _inInitializer = false; |
| 3649 try { |
| 3650 Expression index = parseExpression2(); |
| 3651 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET); |
| 3652 return new IndexExpression.forTarget(prefix, leftBracket, index, rightBr
acket); |
| 3653 } finally { |
| 3654 _inInitializer = wasInInitializer; |
| 3655 } |
| 3656 } else if (_matches(TokenType.PERIOD)) { |
| 3657 Token period = andAdvance; |
| 3658 return new PropertyAccess(prefix, period, parseSimpleIdentifier()); |
| 3659 } else { |
| 3660 if (!optional) { |
| 3661 // Report the missing selector. |
| 3662 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR,
[]); |
| 3663 } |
| 3664 return prefix; |
| 3665 } |
| 3666 } |
| 3667 |
| 3668 /** |
| 3669 * Parse a await expression. |
| 3670 * |
| 3671 * <pre> |
| 3672 * awaitExpression ::= |
| 3673 * 'await' unaryExpression |
| 3674 * </pre> |
| 3675 * |
| 3676 * @return the await expression that was parsed |
| 3677 */ |
| 3678 AwaitExpression _parseAwaitExpression() { |
| 3679 Token awaitToken = andAdvance; |
| 3680 Expression expression = _parseUnaryExpression(); |
| 3681 return new AwaitExpression(awaitToken, expression); |
| 3682 } |
| 3683 |
| 3684 /** |
| 3685 * Parse a bitwise and expression. |
| 3686 * |
| 3687 * <pre> |
| 3688 * bitwiseAndExpression ::= |
| 3689 * shiftExpression ('&' shiftExpression)* |
| 3690 * | 'super' ('&' shiftExpression)+ |
| 3691 * </pre> |
| 3692 * |
| 3693 * @return the bitwise and expression that was parsed |
| 3694 */ |
| 3695 Expression _parseBitwiseAndExpression() { |
| 3696 Expression expression; |
| 3697 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.AMPER
SAND)) { |
| 3698 expression = new SuperExpression(andAdvance); |
| 3699 } else { |
| 3700 expression = _parseShiftExpression(); |
| 3701 } |
| 3702 while (_matches(TokenType.AMPERSAND)) { |
| 3703 Token operator = andAdvance; |
| 3704 expression = new BinaryExpression(expression, operator, _parseShiftExpress
ion()); |
| 3705 } |
| 3706 return expression; |
| 3707 } |
| 3708 |
| 3709 /** |
| 3710 * Parse a bitwise exclusive-or expression. |
| 3711 * |
| 3712 * <pre> |
| 3713 * bitwiseXorExpression ::= |
| 3714 * bitwiseAndExpression ('^' bitwiseAndExpression)* |
| 3715 * | 'super' ('^' bitwiseAndExpression)+ |
| 3716 * </pre> |
| 3717 * |
| 3718 * @return the bitwise exclusive-or expression that was parsed |
| 3719 */ |
| 3720 Expression _parseBitwiseXorExpression() { |
| 3721 Expression expression; |
| 3722 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.CARET
)) { |
| 3723 expression = new SuperExpression(andAdvance); |
| 3724 } else { |
| 3725 expression = _parseBitwiseAndExpression(); |
| 3726 } |
| 3727 while (_matches(TokenType.CARET)) { |
| 3728 Token operator = andAdvance; |
| 3729 expression = new BinaryExpression(expression, operator, _parseBitwiseAndEx
pression()); |
| 3730 } |
| 3731 return expression; |
| 3732 } |
| 3733 |
| 3734 /** |
| 3735 * Parse a break statement. |
| 3736 * |
| 3737 * <pre> |
| 3738 * breakStatement ::= |
| 3739 * 'break' identifier? ';' |
| 3740 * </pre> |
| 3741 * |
| 3742 * @return the break statement that was parsed |
| 3743 */ |
| 3744 Statement _parseBreakStatement() { |
| 3745 Token breakKeyword = _expectKeyword(Keyword.BREAK); |
| 3746 SimpleIdentifier label = null; |
| 3747 if (_matchesIdentifier()) { |
| 3748 label = parseSimpleIdentifier(); |
| 3749 } |
| 3750 if (!_inLoop && !_inSwitch && label == null) { |
| 3751 _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword,
[]); |
| 3752 } |
| 3753 Token semicolon = _expect(TokenType.SEMICOLON); |
| 3754 return new BreakStatement(breakKeyword, label, semicolon); |
| 3755 } |
| 3756 |
| 3757 /** |
| 3758 * Parse a cascade section. |
| 3759 * |
| 3760 * <pre> |
| 3761 * cascadeSection ::= |
| 3762 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* casc
adeAssignment? |
| 3763 * |
| 3764 * cascadeSelector ::= |
| 3765 * '[' expression ']' |
| 3766 * | identifier |
| 3767 * |
| 3768 * cascadeAssignment ::= |
| 3769 * assignmentOperator expressionWithoutCascade |
| 3770 * </pre> |
| 3771 * |
| 3772 * @return the expression representing the cascaded method invocation |
| 3773 */ |
| 3774 Expression _parseCascadeSection() { |
| 3775 Token period = _expect(TokenType.PERIOD_PERIOD); |
| 3776 Expression expression = null; |
| 3777 SimpleIdentifier functionName = null; |
| 3778 if (_matchesIdentifier()) { |
| 3779 functionName = parseSimpleIdentifier(); |
| 3780 } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) { |
| 3781 Token leftBracket = andAdvance; |
| 3782 bool wasInInitializer = _inInitializer; |
| 3783 _inInitializer = false; |
| 3784 try { |
| 3785 Expression index = parseExpression2(); |
| 3786 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET); |
| 3787 expression = new IndexExpression.forCascade(period, leftBracket, index,
rightBracket); |
| 3788 period = null; |
| 3789 } finally { |
| 3790 _inInitializer = wasInInitializer; |
| 3791 } |
| 3792 } else { |
| 3793 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_
currentToken.lexeme]); |
| 3794 functionName = _createSyntheticIdentifier(); |
| 3795 } |
| 3796 assert((expression == null && functionName != null) || (expression != null &
& functionName == null)); |
| 3797 if (_currentToken.type == TokenType.OPEN_PAREN) { |
| 3798 while (_currentToken.type == TokenType.OPEN_PAREN) { |
| 3799 if (functionName != null) { |
| 3800 expression = new MethodInvocation(expression, period, functionName, pa
rseArgumentList()); |
| 3801 period = null; |
| 3802 functionName = null; |
| 3803 } else if (expression == null) { |
| 3804 // It should not be possible to get here. |
| 3805 expression = new MethodInvocation(expression, period, _createSynthetic
Identifier(), parseArgumentList()); |
| 3806 } else { |
| 3807 expression = new FunctionExpressionInvocation(expression, parseArgumen
tList()); |
| 3808 } |
| 3809 } |
| 3810 } else if (functionName != null) { |
| 3811 expression = new PropertyAccess(expression, period, functionName); |
| 3812 period = null; |
| 3813 } |
| 3814 assert(expression != null); |
| 3815 bool progress = true; |
| 3816 while (progress) { |
| 3817 progress = false; |
| 3818 Expression selector = _parseAssignableSelector(expression, true); |
| 3819 if (!identical(selector, expression)) { |
| 3820 expression = selector; |
| 3821 progress = true; |
| 3822 while (_currentToken.type == TokenType.OPEN_PAREN) { |
| 3823 if (expression is PropertyAccess) { |
| 3824 PropertyAccess propertyAccess = expression as PropertyAccess; |
| 3825 expression = new MethodInvocation(propertyAccess.target, propertyAcc
ess.operator, propertyAccess.propertyName, parseArgumentList()); |
| 3826 } else { |
| 3827 expression = new FunctionExpressionInvocation(expression, parseArgum
entList()); |
| 3828 } |
| 3829 } |
| 3830 } |
| 3831 } |
| 3832 if (_currentToken.type.isAssignmentOperator) { |
| 3833 Token operator = andAdvance; |
| 3834 _ensureAssignable(expression); |
| 3835 expression = new AssignmentExpression(expression, operator, parseExpressio
nWithoutCascade()); |
| 3836 } |
| 3837 return expression; |
| 3838 } |
| 3839 |
| 3840 /** |
| 3841 * Parse a class declaration. |
| 3842 * |
| 3843 * <pre> |
| 3844 * classDeclaration ::= |
| 3845 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause wit
hClause?)? implementsClause? '{' classMembers '}' | |
| 3846 * metadata 'abstract'? 'class' mixinApplicationClass |
| 3847 * </pre> |
| 3848 * |
| 3849 * @param commentAndMetadata the metadata to be associated with the member |
| 3850 * @param abstractKeyword the token for the keyword 'abstract', or `null` if t
he keyword was |
| 3851 * not given |
| 3852 * @return the class declaration that was parsed |
| 3853 */ |
| 3854 CompilationUnitMember _parseClassDeclaration(CommentAndMetadata commentAndMeta
data, Token abstractKeyword) { |
| 3855 Token keyword = _expectKeyword(Keyword.CLASS); |
| 3856 if (_matchesIdentifier()) { |
| 3857 Token next = _peek(); |
| 3858 if (_tokenMatches(next, TokenType.LT)) { |
| 3859 next = _skipTypeParameterList(next); |
| 3860 if (next != null && _tokenMatches(next, TokenType.EQ)) { |
| 3861 return _parseClassTypeAlias(commentAndMetadata, abstractKeyword, keywo
rd); |
| 3862 } |
| 3863 } else if (_tokenMatches(next, TokenType.EQ)) { |
| 3864 return _parseClassTypeAlias(commentAndMetadata, abstractKeyword, keyword
); |
| 3865 } |
| 3866 } |
| 3867 SimpleIdentifier name = parseSimpleIdentifier(); |
| 3868 String className = name.name; |
| 3869 TypeParameterList typeParameters = null; |
| 3870 if (_matches(TokenType.LT)) { |
| 3871 typeParameters = parseTypeParameterList(); |
| 3872 } |
| 3873 // |
| 3874 // Parse the clauses. The parser accepts clauses in any order, but will gene
rate errors if they |
| 3875 // are not in the order required by the specification. |
| 3876 // |
| 3877 ExtendsClause extendsClause = null; |
| 3878 WithClause withClause = null; |
| 3879 ImplementsClause implementsClause = null; |
| 3880 bool foundClause = true; |
| 3881 while (foundClause) { |
| 3882 if (_matchesKeyword(Keyword.EXTENDS)) { |
| 3883 if (extendsClause == null) { |
| 3884 extendsClause = parseExtendsClause(); |
| 3885 if (withClause != null) { |
| 3886 _reportErrorForToken(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause
.withKeyword, []); |
| 3887 } else if (implementsClause != null) { |
| 3888 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, impl
ementsClause.keyword, []); |
| 3889 } |
| 3890 } else { |
| 3891 _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, extends
Clause.keyword, []); |
| 3892 parseExtendsClause(); |
| 3893 } |
| 3894 } else if (_matchesKeyword(Keyword.WITH)) { |
| 3895 if (withClause == null) { |
| 3896 withClause = parseWithClause(); |
| 3897 if (implementsClause != null) { |
| 3898 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, impleme
ntsClause.keyword, []); |
| 3899 } |
| 3900 } else { |
| 3901 _reportErrorForToken(ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause
.withKeyword, []); |
| 3902 parseWithClause(); |
| 3903 } |
| 3904 } else if (_matchesKeyword(Keyword.IMPLEMENTS)) { |
| 3905 if (implementsClause == null) { |
| 3906 implementsClause = parseImplementsClause(); |
| 3907 } else { |
| 3908 _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, impl
ementsClause.keyword, []); |
| 3909 parseImplementsClause(); |
| 3910 } |
| 3911 } else { |
| 3912 foundClause = false; |
| 3913 } |
| 3914 } |
| 3915 if (withClause != null && extendsClause == null) { |
| 3916 _reportErrorForToken(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.with
Keyword, []); |
| 3917 } |
| 3918 // |
| 3919 // Look for and skip over the extra-lingual 'native' specification. |
| 3920 // |
| 3921 NativeClause nativeClause = null; |
| 3922 if (_matchesString(_NATIVE) && _tokenMatches(_peek(), TokenType.STRING)) { |
| 3923 nativeClause = _parseNativeClause(); |
| 3924 } |
| 3925 // |
| 3926 // Parse the body of the class. |
| 3927 // |
| 3928 Token leftBracket = null; |
| 3929 List<ClassMember> members = null; |
| 3930 Token rightBracket = null; |
| 3931 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 3932 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); |
| 3933 members = _parseClassMembers(className, _getEndToken(leftBracket)); |
| 3934 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 3935 } else { |
| 3936 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET); |
| 3937 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET); |
| 3938 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CLASS_BODY, []); |
| 3939 } |
| 3940 ClassDeclaration classDeclaration = new ClassDeclaration(commentAndMetadata.
comment, commentAndMetadata.metadata, abstractKeyword, keyword, name, typeParame
ters, extendsClause, withClause, implementsClause, leftBracket, members, rightBr
acket); |
| 3941 classDeclaration.nativeClause = nativeClause; |
| 3942 return classDeclaration; |
| 3943 } |
| 3944 |
| 3945 /** |
| 3946 * Parse a list of class members. |
| 3947 * |
| 3948 * <pre> |
| 3949 * classMembers ::= |
| 3950 * (metadata memberDefinition)* |
| 3951 * </pre> |
| 3952 * |
| 3953 * @param className the name of the class whose members are being parsed |
| 3954 * @param closingBracket the closing bracket for the class, or `null` if the c
losing bracket |
| 3955 * is missing |
| 3956 * @return the list of class members that were parsed |
| 3957 */ |
| 3958 List<ClassMember> _parseClassMembers(String className, Token closingBracket) { |
| 3959 List<ClassMember> members = new List<ClassMember>(); |
| 3960 Token memberStart = _currentToken; |
| 3961 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)
&& (closingBracket != null || (!_matchesKeyword(Keyword.CLASS) && !_matchesKeywo
rd(Keyword.TYPEDEF)))) { |
| 3962 if (_matches(TokenType.SEMICOLON)) { |
| 3963 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 3964 _advance(); |
| 3965 } else { |
| 3966 ClassMember member = parseClassMember(className); |
| 3967 if (member != null) { |
| 3968 members.add(member); |
| 3969 } |
| 3970 } |
| 3971 if (identical(_currentToken, memberStart)) { |
| 3972 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 3973 _advance(); |
| 3974 } |
| 3975 memberStart = _currentToken; |
| 3976 } |
| 3977 return members; |
| 3978 } |
| 3979 |
| 3980 /** |
| 3981 * Parse a class type alias. |
| 3982 * |
| 3983 * <pre> |
| 3984 * classTypeAlias ::= |
| 3985 * identifier typeParameters? '=' 'abstract'? mixinApplication |
| 3986 * |
| 3987 * mixinApplication ::= |
| 3988 * type withClause implementsClause? ';' |
| 3989 * </pre> |
| 3990 * |
| 3991 * @param commentAndMetadata the metadata to be associated with the member |
| 3992 * @param abstractKeyword the token representing the 'abstract' keyword |
| 3993 * @param classKeyword the token representing the 'class' keyword |
| 3994 * @return the class type alias that was parsed |
| 3995 */ |
| 3996 ClassTypeAlias _parseClassTypeAlias(CommentAndMetadata commentAndMetadata, Tok
en abstractKeyword, Token classKeyword) { |
| 3997 SimpleIdentifier className = parseSimpleIdentifier(); |
| 3998 TypeParameterList typeParameters = null; |
| 3999 if (_matches(TokenType.LT)) { |
| 4000 typeParameters = parseTypeParameterList(); |
| 4001 } |
| 4002 Token equals = _expect(TokenType.EQ); |
| 4003 TypeName superclass = parseTypeName(); |
| 4004 WithClause withClause = null; |
| 4005 if (_matchesKeyword(Keyword.WITH)) { |
| 4006 withClause = parseWithClause(); |
| 4007 } else { |
| 4008 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.
syntax]); |
| 4009 } |
| 4010 ImplementsClause implementsClause = null; |
| 4011 if (_matchesKeyword(Keyword.IMPLEMENTS)) { |
| 4012 implementsClause = parseImplementsClause(); |
| 4013 } |
| 4014 Token semicolon; |
| 4015 if (_matches(TokenType.SEMICOLON)) { |
| 4016 semicolon = andAdvance; |
| 4017 } else { |
| 4018 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 4019 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType.S
EMICOLON.lexeme]); |
| 4020 Token leftBracket = andAdvance; |
| 4021 _parseClassMembers(className.name, _getEndToken(leftBracket)); |
| 4022 _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 4023 } else { |
| 4024 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previ
ous, [TokenType.SEMICOLON.lexeme]); |
| 4025 } |
| 4026 semicolon = _createSyntheticToken(TokenType.SEMICOLON); |
| 4027 } |
| 4028 return new ClassTypeAlias(commentAndMetadata.comment, commentAndMetadata.met
adata, classKeyword, className, typeParameters, equals, abstractKeyword, supercl
ass, withClause, implementsClause, semicolon); |
| 4029 } |
| 4030 |
| 4031 /** |
| 4032 * Parse a list of combinators in a directive. |
| 4033 * |
| 4034 * <pre> |
| 4035 * combinator ::= |
| 4036 * 'show' identifier (',' identifier)* |
| 4037 * | 'hide' identifier (',' identifier)* |
| 4038 * </pre> |
| 4039 * |
| 4040 * @return the combinators that were parsed |
| 4041 */ |
| 4042 List<Combinator> _parseCombinators() { |
| 4043 List<Combinator> combinators = new List<Combinator>(); |
| 4044 while (_matchesString(_SHOW) || _matchesString(_HIDE)) { |
| 4045 Token keyword = _expect(TokenType.IDENTIFIER); |
| 4046 if (keyword.lexeme == _SHOW) { |
| 4047 List<SimpleIdentifier> shownNames = _parseIdentifierList(); |
| 4048 combinators.add(new ShowCombinator(keyword, shownNames)); |
| 4049 } else { |
| 4050 List<SimpleIdentifier> hiddenNames = _parseIdentifierList(); |
| 4051 combinators.add(new HideCombinator(keyword, hiddenNames)); |
| 4052 } |
| 4053 } |
| 4054 return combinators; |
| 4055 } |
| 4056 |
| 4057 /** |
| 4058 * Parse the documentation comment and metadata preceding a declaration. This
method allows any |
| 4059 * number of documentation comments to occur before, after or between the meta
data, but only |
| 4060 * returns the last (right-most) documentation comment that is found. |
| 4061 * |
| 4062 * <pre> |
| 4063 * metadata ::= |
| 4064 * annotation* |
| 4065 * </pre> |
| 4066 * |
| 4067 * @return the documentation comment and metadata that were parsed |
| 4068 */ |
| 4069 CommentAndMetadata _parseCommentAndMetadata() { |
| 4070 Comment comment = _parseDocumentationComment(); |
| 4071 List<Annotation> metadata = new List<Annotation>(); |
| 4072 while (_matches(TokenType.AT)) { |
| 4073 metadata.add(parseAnnotation()); |
| 4074 Comment optionalComment = _parseDocumentationComment(); |
| 4075 if (optionalComment != null) { |
| 4076 comment = optionalComment; |
| 4077 } |
| 4078 } |
| 4079 return new CommentAndMetadata(comment, metadata); |
| 4080 } |
| 4081 |
| 4082 /** |
| 4083 * Parse a comment reference from the source between square brackets. |
| 4084 * |
| 4085 * <pre> |
| 4086 * commentReference ::= |
| 4087 * 'new'? prefixedIdentifier |
| 4088 * </pre> |
| 4089 * |
| 4090 * @param referenceSource the source occurring between the square brackets wit
hin a documentation |
| 4091 * comment |
| 4092 * @param sourceOffset the offset of the first character of the reference sour
ce |
| 4093 * @return the comment reference that was parsed, or `null` if no reference co
uld be found |
| 4094 */ |
| 4095 CommentReference _parseCommentReference(String referenceSource, int sourceOffs
et) { |
| 4096 // TODO(brianwilkerson) The errors are not getting the right offset/length a
nd are being duplicated. |
| 4097 if (referenceSource.length == 0) { |
| 4098 Token syntheticToken = new SyntheticStringToken(TokenType.IDENTIFIER, "",
sourceOffset); |
| 4099 return new CommentReference(null, new SimpleIdentifier(syntheticToken)); |
| 4100 } |
| 4101 try { |
| 4102 BooleanErrorListener listener = new BooleanErrorListener(); |
| 4103 Scanner scanner = new Scanner(null, new SubSequenceReader(referenceSource,
sourceOffset), listener); |
| 4104 scanner.setSourceStart(1, 1); |
| 4105 Token firstToken = scanner.tokenize(); |
| 4106 if (listener.errorReported) { |
| 4107 return null; |
| 4108 } |
| 4109 Token newKeyword = null; |
| 4110 if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) { |
| 4111 newKeyword = firstToken; |
| 4112 firstToken = firstToken.next; |
| 4113 } |
| 4114 if (_tokenMatchesIdentifier(firstToken)) { |
| 4115 Token secondToken = firstToken.next; |
| 4116 Token thirdToken = secondToken.next; |
| 4117 Token nextToken; |
| 4118 Identifier identifier; |
| 4119 if (_tokenMatches(secondToken, TokenType.PERIOD) && _tokenMatchesIdentif
ier(thirdToken)) { |
| 4120 identifier = new PrefixedIdentifier(new SimpleIdentifier(firstToken),
secondToken, new SimpleIdentifier(thirdToken)); |
| 4121 nextToken = thirdToken.next; |
| 4122 } else { |
| 4123 identifier = new SimpleIdentifier(firstToken); |
| 4124 nextToken = firstToken.next; |
| 4125 } |
| 4126 if (nextToken.type != TokenType.EOF) { |
| 4127 return null; |
| 4128 } |
| 4129 return new CommentReference(newKeyword, identifier); |
| 4130 } else if (_tokenMatchesKeyword(firstToken, Keyword.THIS) || _tokenMatches
Keyword(firstToken, Keyword.NULL) || _tokenMatchesKeyword(firstToken, Keyword.TR
UE) || _tokenMatchesKeyword(firstToken, Keyword.FALSE)) { |
| 4131 // TODO(brianwilkerson) If we want to support this we will need to exten
d the definition |
| 4132 // of CommentReference to take an expression rather than an identifier.
For now we just |
| 4133 // ignore it to reduce the number of errors produced, but that's probabl
y not a valid |
| 4134 // long term approach. |
| 4135 return null; |
| 4136 } |
| 4137 } catch (exception) { |
| 4138 } |
| 4139 return null; |
| 4140 } |
| 4141 |
| 4142 /** |
| 4143 * Parse all of the comment references occurring in the given array of documen
tation comments. |
| 4144 * |
| 4145 * <pre> |
| 4146 * commentReference ::= |
| 4147 * '[' 'new'? qualified ']' libraryReference? |
| 4148 * |
| 4149 * libraryReference ::= |
| 4150 * '(' stringLiteral ')' |
| 4151 * </pre> |
| 4152 * |
| 4153 * @param tokens the comment tokens representing the documentation comments to
be parsed |
| 4154 * @return the comment references that were parsed |
| 4155 */ |
| 4156 List<CommentReference> _parseCommentReferences(List<Token> tokens) { |
| 4157 List<CommentReference> references = new List<CommentReference>(); |
| 4158 for (Token token in tokens) { |
| 4159 String comment = token.lexeme; |
| 4160 int length = comment.length; |
| 4161 List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment); |
| 4162 int leftIndex = comment.indexOf('['); |
| 4163 while (leftIndex >= 0 && leftIndex + 1 < length) { |
| 4164 List<int> range = _findRange(codeBlockRanges, leftIndex); |
| 4165 if (range == null) { |
| 4166 int nameOffset = token.offset + leftIndex + 1; |
| 4167 int rightIndex = JavaString.indexOf(comment, ']', leftIndex); |
| 4168 if (rightIndex >= 0) { |
| 4169 int firstChar = comment.codeUnitAt(leftIndex + 1); |
| 4170 if (firstChar != 0x27 && firstChar != 0x22) { |
| 4171 if (_isLinkText(comment, rightIndex)) { |
| 4172 } else { |
| 4173 CommentReference reference = _parseCommentReference(comment.subs
tring(leftIndex + 1, rightIndex), nameOffset); |
| 4174 if (reference != null) { |
| 4175 references.add(reference); |
| 4176 } |
| 4177 } |
| 4178 } |
| 4179 } else { |
| 4180 // terminating ']' is not typed yet |
| 4181 int charAfterLeft = comment.codeUnitAt(leftIndex + 1); |
| 4182 if (Character.isLetterOrDigit(charAfterLeft)) { |
| 4183 int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(comment,
leftIndex + 1); |
| 4184 String name = comment.substring(leftIndex + 1, nameEnd); |
| 4185 Token nameToken = new StringToken(TokenType.IDENTIFIER, name, name
Offset); |
| 4186 references.add(new CommentReference(null, new SimpleIdentifier(nam
eToken))); |
| 4187 } else { |
| 4188 Token nameToken = new SyntheticStringToken(TokenType.IDENTIFIER, "
", nameOffset); |
| 4189 references.add(new CommentReference(null, new SimpleIdentifier(nam
eToken))); |
| 4190 } |
| 4191 // next character |
| 4192 rightIndex = leftIndex + 1; |
| 4193 } |
| 4194 leftIndex = JavaString.indexOf(comment, '[', rightIndex); |
| 4195 } else { |
| 4196 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1); |
| 4197 } |
| 4198 } |
| 4199 } |
| 4200 return references; |
| 4201 } |
| 4202 |
| 4203 /** |
| 4204 * Parse a compilation unit member. |
| 4205 * |
| 4206 * <pre> |
| 4207 * compilationUnitMember ::= |
| 4208 * classDefinition |
| 4209 * | functionTypeAlias |
| 4210 * | external functionSignature |
| 4211 * | external getterSignature |
| 4212 * | external setterSignature |
| 4213 * | functionSignature functionBody |
| 4214 * | returnType? getOrSet identifier formalParameterList functionBody |
| 4215 * | (final | const) type? staticFinalDeclarationList ';' |
| 4216 * | variableDeclaration ';' |
| 4217 * </pre> |
| 4218 * |
| 4219 * @param commentAndMetadata the metadata to be associated with the member |
| 4220 * @return the compilation unit member that was parsed, or `null` if what was
parsed could |
| 4221 * not be represented as a compilation unit member |
| 4222 */ |
| 4223 CompilationUnitMember _parseCompilationUnitMember(CommentAndMetadata commentAn
dMetadata) { |
| 4224 Modifiers modifiers = _parseModifiers(); |
| 4225 if (_matchesKeyword(Keyword.CLASS)) { |
| 4226 return _parseClassDeclaration(commentAndMetadata, _validateModifiersForCla
ss(modifiers)); |
| 4227 } else if (_matchesKeyword(Keyword.TYPEDEF) && !_tokenMatches(_peek(), Token
Type.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_tokenMatches(_peek(),
TokenType.OPEN_PAREN)) { |
| 4228 _validateModifiersForTypedef(modifiers); |
| 4229 return _parseTypeAlias(commentAndMetadata); |
| 4230 } else if (_parseEnum && _matchesKeyword(Keyword.ENUM)) { |
| 4231 _validateModifiersForEnum(modifiers); |
| 4232 return _parseEnumDeclaration(commentAndMetadata); |
| 4233 } |
| 4234 if (_matchesKeyword(Keyword.VOID)) { |
| 4235 TypeName returnType = parseReturnType(); |
| 4236 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) && _tok
enMatchesIdentifier(_peek())) { |
| 4237 _validateModifiersForTopLevelFunction(modifiers); |
| 4238 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalK
eyword, returnType); |
| 4239 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 4240 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken,
[]); |
| 4241 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata,
modifiers.externalKeyword, returnType)); |
| 4242 } else if (_matchesIdentifier() && _peek().matchesAny([ |
| 4243 TokenType.OPEN_PAREN, |
| 4244 TokenType.OPEN_CURLY_BRACKET, |
| 4245 TokenType.FUNCTION])) { |
| 4246 _validateModifiersForTopLevelFunction(modifiers); |
| 4247 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalK
eyword, returnType); |
| 4248 } else { |
| 4249 // |
| 4250 // We have found an error of some kind. Try to recover. |
| 4251 // |
| 4252 if (_matchesIdentifier()) { |
| 4253 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMIC
OLON])) { |
| 4254 // |
| 4255 // We appear to have a variable declaration with a type of "void". |
| 4256 // |
| 4257 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, []); |
| 4258 return new TopLevelVariableDeclaration(commentAndMetadata.comment, c
ommentAndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _valida
teModifiersForTopLevelVariable(modifiers), null), _expect(TokenType.SEMICOLON)); |
| 4259 } |
| 4260 } |
| 4261 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken,
[]); |
| 4262 return null; |
| 4263 } |
| 4264 } else if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) &&
_tokenMatchesIdentifier(_peek())) { |
| 4265 _validateModifiersForTopLevelFunction(modifiers); |
| 4266 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey
word, null); |
| 4267 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 4268 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []
); |
| 4269 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata, mo
difiers.externalKeyword, null)); |
| 4270 } else if (!_matchesIdentifier()) { |
| 4271 Token keyword = modifiers.varKeyword; |
| 4272 if (keyword == null) { |
| 4273 keyword = modifiers.finalKeyword; |
| 4274 } |
| 4275 if (keyword == null) { |
| 4276 keyword = modifiers.constKeyword; |
| 4277 } |
| 4278 if (keyword != null) { |
| 4279 // |
| 4280 // We appear to have found an incomplete top-level variable declaration. |
| 4281 // |
| 4282 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 4283 List<VariableDeclaration> variables = new List<VariableDeclaration>(); |
| 4284 variables.add(new VariableDeclaration(null, null, _createSyntheticIdenti
fier(), null, null)); |
| 4285 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comme
ntAndMetadata.metadata, new VariableDeclarationList(null, null, keyword, null, v
ariables), _expectSemicolon()); |
| 4286 } |
| 4287 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, [
]); |
| 4288 return null; |
| 4289 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 4290 _validateModifiersForTopLevelFunction(modifiers); |
| 4291 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey
word, null); |
| 4292 } else if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMI
COLON])) { |
| 4293 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo
difiers.varKeyword == null) { |
| 4294 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T
YPE, []); |
| 4295 } |
| 4296 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment
AndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModi
fiersForTopLevelVariable(modifiers), null), _expect(TokenType.SEMICOLON)); |
| 4297 } |
| 4298 TypeName returnType = parseReturnType(); |
| 4299 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) && _token
MatchesIdentifier(_peek())) { |
| 4300 _validateModifiersForTopLevelFunction(modifiers); |
| 4301 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey
word, returnType); |
| 4302 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) { |
| 4303 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []
); |
| 4304 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata, mo
difiers.externalKeyword, returnType)); |
| 4305 } else if (_matches(TokenType.AT)) { |
| 4306 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment
AndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModi
fiersForTopLevelVariable(modifiers), returnType), _expect(TokenType.SEMICOLON)); |
| 4307 } else if (!_matchesIdentifier()) { |
| 4308 // TODO(brianwilkerson) Generalize this error. We could also be parsing a
top-level variable at this point. |
| 4309 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, [
]); |
| 4310 Token semicolon; |
| 4311 if (_matches(TokenType.SEMICOLON)) { |
| 4312 semicolon = andAdvance; |
| 4313 } else { |
| 4314 semicolon = _createSyntheticToken(TokenType.SEMICOLON); |
| 4315 } |
| 4316 List<VariableDeclaration> variables = new List<VariableDeclaration>(); |
| 4317 variables.add(new VariableDeclaration(null, null, _createSyntheticIdentifi
er(), null, null)); |
| 4318 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment
AndMetadata.metadata, new VariableDeclarationList(null, null, null, returnType,
variables), semicolon); |
| 4319 } |
| 4320 if (_peek().matchesAny([ |
| 4321 TokenType.OPEN_PAREN, |
| 4322 TokenType.FUNCTION, |
| 4323 TokenType.OPEN_CURLY_BRACKET])) { |
| 4324 _validateModifiersForTopLevelFunction(modifiers); |
| 4325 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey
word, returnType); |
| 4326 } |
| 4327 return new TopLevelVariableDeclaration(commentAndMetadata.comment, commentAn
dMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModifi
ersForTopLevelVariable(modifiers), returnType), _expect(TokenType.SEMICOLON)); |
| 4328 } |
| 4329 |
| 4330 /** |
| 4331 * Parse a const expression. |
| 4332 * |
| 4333 * <pre> |
| 4334 * constExpression ::= |
| 4335 * instanceCreationExpression |
| 4336 * | listLiteral |
| 4337 * | mapLiteral |
| 4338 * </pre> |
| 4339 * |
| 4340 * @return the const expression that was parsed |
| 4341 */ |
| 4342 Expression _parseConstExpression() { |
| 4343 Token keyword = _expectKeyword(Keyword.CONST); |
| 4344 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) { |
| 4345 return _parseListLiteral(keyword, null); |
| 4346 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 4347 return _parseMapLiteral(keyword, null); |
| 4348 } else if (_matches(TokenType.LT)) { |
| 4349 return _parseListOrMapLiteral(keyword); |
| 4350 } |
| 4351 return _parseInstanceCreationExpression(keyword); |
| 4352 } |
| 4353 |
| 4354 ConstructorDeclaration _parseConstructor(CommentAndMetadata commentAndMetadata
, Token externalKeyword, Token constKeyword, Token factoryKeyword, SimpleIdentif
ier returnType, Token period, SimpleIdentifier name, FormalParameterList paramet
ers) { |
| 4355 bool bodyAllowed = externalKeyword == null; |
| 4356 Token separator = null; |
| 4357 List<ConstructorInitializer> initializers = null; |
| 4358 if (_matches(TokenType.COLON)) { |
| 4359 separator = andAdvance; |
| 4360 initializers = new List<ConstructorInitializer>(); |
| 4361 do { |
| 4362 if (_matchesKeyword(Keyword.THIS)) { |
| 4363 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 4364 bodyAllowed = false; |
| 4365 initializers.add(_parseRedirectingConstructorInvocation()); |
| 4366 } else if (_tokenMatches(_peek(), TokenType.PERIOD) && _tokenMatches(_
peekAt(3), TokenType.OPEN_PAREN)) { |
| 4367 bodyAllowed = false; |
| 4368 initializers.add(_parseRedirectingConstructorInvocation()); |
| 4369 } else { |
| 4370 initializers.add(_parseConstructorFieldInitializer()); |
| 4371 } |
| 4372 } else if (_matchesKeyword(Keyword.SUPER)) { |
| 4373 initializers.add(_parseSuperConstructorInvocation()); |
| 4374 } else { |
| 4375 initializers.add(_parseConstructorFieldInitializer()); |
| 4376 } |
| 4377 } while (_optional(TokenType.COMMA)); |
| 4378 } |
| 4379 ConstructorName redirectedConstructor = null; |
| 4380 FunctionBody body; |
| 4381 if (_matches(TokenType.EQ)) { |
| 4382 separator = andAdvance; |
| 4383 redirectedConstructor = parseConstructorName(); |
| 4384 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON)); |
| 4385 if (factoryKeyword == null) { |
| 4386 _reportErrorForNode(ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCT
OR, redirectedConstructor, []); |
| 4387 } |
| 4388 } else { |
| 4389 body = _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, fal
se); |
| 4390 if (constKeyword != null && factoryKeyword != null && externalKeyword == n
ull) { |
| 4391 _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword, []); |
| 4392 } else if (body is EmptyFunctionBody) { |
| 4393 if (factoryKeyword != null && externalKeyword == null) { |
| 4394 _reportErrorForToken(ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyw
ord, []); |
| 4395 } |
| 4396 } else { |
| 4397 if (constKeyword != null) { |
| 4398 _reportErrorForNode(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body,
[]); |
| 4399 } else if (!bodyAllowed) { |
| 4400 _reportErrorForNode(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, bo
dy, []); |
| 4401 } |
| 4402 } |
| 4403 } |
| 4404 return new ConstructorDeclaration(commentAndMetadata.comment, commentAndMeta
data.metadata, externalKeyword, constKeyword, factoryKeyword, returnType, period
, name, parameters, separator, initializers, redirectedConstructor, body); |
| 4405 } |
| 4406 |
| 4407 /** |
| 4408 * Parse a field initializer within a constructor. |
| 4409 * |
| 4410 * <pre> |
| 4411 * fieldInitializer: |
| 4412 * ('this' '.')? identifier '=' conditionalExpression cascadeSection* |
| 4413 * </pre> |
| 4414 * |
| 4415 * @return the field initializer that was parsed |
| 4416 */ |
| 4417 ConstructorFieldInitializer _parseConstructorFieldInitializer() { |
| 4418 Token keyword = null; |
| 4419 Token period = null; |
| 4420 if (_matchesKeyword(Keyword.THIS)) { |
| 4421 keyword = andAdvance; |
| 4422 period = _expect(TokenType.PERIOD); |
| 4423 } |
| 4424 SimpleIdentifier fieldName = parseSimpleIdentifier(); |
| 4425 Token equals = _expect(TokenType.EQ); |
| 4426 bool wasInInitializer = _inInitializer; |
| 4427 _inInitializer = true; |
| 4428 try { |
| 4429 Expression expression = parseConditionalExpression(); |
| 4430 TokenType tokenType = _currentToken.type; |
| 4431 if (tokenType == TokenType.PERIOD_PERIOD) { |
| 4432 List<Expression> cascadeSections = new List<Expression>(); |
| 4433 while (tokenType == TokenType.PERIOD_PERIOD) { |
| 4434 Expression section = _parseCascadeSection(); |
| 4435 if (section != null) { |
| 4436 cascadeSections.add(section); |
| 4437 } |
| 4438 tokenType = _currentToken.type; |
| 4439 } |
| 4440 expression = new CascadeExpression(expression, cascadeSections); |
| 4441 } |
| 4442 return new ConstructorFieldInitializer(keyword, period, fieldName, equals,
expression); |
| 4443 } finally { |
| 4444 _inInitializer = wasInInitializer; |
| 4445 } |
| 4446 } |
| 4447 |
| 4448 /** |
| 4449 * Parse a continue statement. |
| 4450 * |
| 4451 * <pre> |
| 4452 * continueStatement ::= |
| 4453 * 'continue' identifier? ';' |
| 4454 * </pre> |
| 4455 * |
| 4456 * @return the continue statement that was parsed |
| 4457 */ |
| 4458 Statement _parseContinueStatement() { |
| 4459 Token continueKeyword = _expectKeyword(Keyword.CONTINUE); |
| 4460 if (!_inLoop && !_inSwitch) { |
| 4461 _reportErrorForToken(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKey
word, []); |
| 4462 } |
| 4463 SimpleIdentifier label = null; |
| 4464 if (_matchesIdentifier()) { |
| 4465 label = parseSimpleIdentifier(); |
| 4466 } |
| 4467 if (_inSwitch && !_inLoop && label == null) { |
| 4468 _reportErrorForToken(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, conti
nueKeyword, []); |
| 4469 } |
| 4470 Token semicolon = _expect(TokenType.SEMICOLON); |
| 4471 return new ContinueStatement(continueKeyword, label, semicolon); |
| 4472 } |
| 4473 |
| 4474 /** |
| 4475 * Parse a directive. |
| 4476 * |
| 4477 * <pre> |
| 4478 * directive ::= |
| 4479 * exportDirective |
| 4480 * | libraryDirective |
| 4481 * | importDirective |
| 4482 * | partDirective |
| 4483 * </pre> |
| 4484 * |
| 4485 * @param commentAndMetadata the metadata to be associated with the directive |
| 4486 * @return the directive that was parsed |
| 4487 */ |
| 4488 Directive _parseDirective(CommentAndMetadata commentAndMetadata) { |
| 4489 if (_matchesKeyword(Keyword.IMPORT)) { |
| 4490 return _parseImportDirective(commentAndMetadata); |
| 4491 } else if (_matchesKeyword(Keyword.EXPORT)) { |
| 4492 return _parseExportDirective(commentAndMetadata); |
| 4493 } else if (_matchesKeyword(Keyword.LIBRARY)) { |
| 4494 return _parseLibraryDirective(commentAndMetadata); |
| 4495 } else if (_matchesKeyword(Keyword.PART)) { |
| 4496 return _parsePartDirective(commentAndMetadata); |
| 4497 } else { |
| 4498 // Internal error: this method should not have been invoked if the current
token was something |
| 4499 // other than one of the above. |
| 4500 throw new IllegalStateException("parseDirective invoked in an invalid stat
e; currentToken = ${_currentToken}"); |
| 4501 } |
| 4502 } |
| 4503 |
| 4504 /** |
| 4505 * Parse the script tag and directives in a compilation unit until the first n
on-directive is |
| 4506 * encountered. |
| 4507 * |
| 4508 * |
| 4509 * <pre> |
| 4510 * compilationUnit ::= |
| 4511 * scriptTag? directive* |
| 4512 * </pre> |
| 4513 * |
| 4514 * @return the compilation unit that was parsed |
| 4515 */ |
| 4516 CompilationUnit _parseDirectives() { |
| 4517 Token firstToken = _currentToken; |
| 4518 ScriptTag scriptTag = null; |
| 4519 if (_matches(TokenType.SCRIPT_TAG)) { |
| 4520 scriptTag = new ScriptTag(andAdvance); |
| 4521 } |
| 4522 List<Directive> directives = new List<Directive>(); |
| 4523 while (!_matches(TokenType.EOF)) { |
| 4524 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 4525 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) ||
_matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMa
tches(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_t
okenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 4526 directives.add(_parseDirective(commentAndMetadata)); |
| 4527 } else if (_matches(TokenType.SEMICOLON)) { |
| 4528 _advance(); |
| 4529 } else { |
| 4530 while (!_matches(TokenType.EOF)) { |
| 4531 _advance(); |
| 4532 } |
| 4533 return new CompilationUnit(firstToken, scriptTag, directives, new List<C
ompilationUnitMember>(), _currentToken); |
| 4534 } |
| 4535 } |
| 4536 return new CompilationUnit(firstToken, scriptTag, directives, new List<Compi
lationUnitMember>(), _currentToken); |
| 4537 } |
| 4538 |
| 4539 /** |
| 4540 * Parse a documentation comment. |
| 4541 * |
| 4542 * <pre> |
| 4543 * documentationComment ::= |
| 4544 * multiLineComment? |
| 4545 * | singleLineComment* |
| 4546 * </pre> |
| 4547 * |
| 4548 * @return the documentation comment that was parsed, or `null` if there was n
o comment |
| 4549 */ |
| 4550 Comment _parseDocumentationComment() { |
| 4551 List<Token> commentTokens = new List<Token>(); |
| 4552 Token commentToken = _currentToken.precedingComments; |
| 4553 while (commentToken != null) { |
| 4554 if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) { |
| 4555 if (StringUtilities.startsWith3(commentToken.lexeme, 0, 0x2F, 0x2F, 0x2F
)) { |
| 4556 if (commentTokens.length == 1 && StringUtilities.startsWith3(commentTo
kens[0].lexeme, 0, 0x2F, 0x2A, 0x2A)) { |
| 4557 commentTokens.clear(); |
| 4558 } |
| 4559 commentTokens.add(commentToken); |
| 4560 } |
| 4561 } else { |
| 4562 if (StringUtilities.startsWith3(commentToken.lexeme, 0, 0x2F, 0x2A, 0x2A
)) { |
| 4563 commentTokens.clear(); |
| 4564 commentTokens.add(commentToken); |
| 4565 } |
| 4566 } |
| 4567 commentToken = commentToken.next; |
| 4568 } |
| 4569 if (commentTokens.isEmpty) { |
| 4570 return null; |
| 4571 } |
| 4572 List<Token> tokens = new List.from(commentTokens); |
| 4573 List<CommentReference> references = _parseCommentReferences(tokens); |
| 4574 return Comment.createDocumentationCommentWithReferences(tokens, references); |
| 4575 } |
| 4576 |
| 4577 /** |
| 4578 * Parse a do statement. |
| 4579 * |
| 4580 * <pre> |
| 4581 * doStatement ::= |
| 4582 * 'do' statement 'while' '(' expression ')' ';' |
| 4583 * </pre> |
| 4584 * |
| 4585 * @return the do statement that was parsed |
| 4586 */ |
| 4587 Statement _parseDoStatement() { |
| 4588 bool wasInLoop = _inLoop; |
| 4589 _inLoop = true; |
| 4590 try { |
| 4591 Token doKeyword = _expectKeyword(Keyword.DO); |
| 4592 Statement body = parseStatement2(); |
| 4593 Token whileKeyword = _expectKeyword(Keyword.WHILE); |
| 4594 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 4595 Expression condition = parseExpression2(); |
| 4596 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 4597 Token semicolon = _expect(TokenType.SEMICOLON); |
| 4598 return new DoStatement(doKeyword, body, whileKeyword, leftParenthesis, con
dition, rightParenthesis, semicolon); |
| 4599 } finally { |
| 4600 _inLoop = wasInLoop; |
| 4601 } |
| 4602 } |
| 4603 |
| 4604 /** |
| 4605 * Parse an empty statement. |
| 4606 * |
| 4607 * <pre> |
| 4608 * emptyStatement ::= |
| 4609 * ';' |
| 4610 * </pre> |
| 4611 * |
| 4612 * @return the empty statement that was parsed |
| 4613 */ |
| 4614 Statement _parseEmptyStatement() => new EmptyStatement(andAdvance); |
| 4615 |
| 4616 EnumConstantDeclaration _parseEnumConstantDeclaration() { |
| 4617 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 4618 SimpleIdentifier name; |
| 4619 if (_matchesIdentifier()) { |
| 4620 name = parseSimpleIdentifier(); |
| 4621 } else { |
| 4622 name = _createSyntheticIdentifier(); |
| 4623 } |
| 4624 return new EnumConstantDeclaration(commentAndMetadata.comment, commentAndMet
adata.metadata, name); |
| 4625 } |
| 4626 |
| 4627 /** |
| 4628 * Parse an enum declaration. |
| 4629 * |
| 4630 * <pre> |
| 4631 * enumType ::= |
| 4632 * metadata 'enum' id '{' id (',' id)* (',')? '}' |
| 4633 * </pre> |
| 4634 * |
| 4635 * @param commentAndMetadata the metadata to be associated with the member |
| 4636 * @return the enum declaration that was parsed |
| 4637 */ |
| 4638 EnumDeclaration _parseEnumDeclaration(CommentAndMetadata commentAndMetadata) { |
| 4639 Token keyword = _expectKeyword(Keyword.ENUM); |
| 4640 SimpleIdentifier name = parseSimpleIdentifier(); |
| 4641 Token leftBracket = null; |
| 4642 List<EnumConstantDeclaration> constants = new List<EnumConstantDeclaration>(
); |
| 4643 Token rightBracket = null; |
| 4644 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 4645 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); |
| 4646 if (_matchesIdentifier()) { |
| 4647 constants.add(_parseEnumConstantDeclaration()); |
| 4648 } else if (_matches(TokenType.COMMA) && _tokenMatchesIdentifier(_peek()))
{ |
| 4649 constants.add(_parseEnumConstantDeclaration()); |
| 4650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 4651 } else { |
| 4652 constants.add(_parseEnumConstantDeclaration()); |
| 4653 _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY, []); |
| 4654 } |
| 4655 while (_optional(TokenType.COMMA)) { |
| 4656 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 4657 break; |
| 4658 } |
| 4659 constants.add(_parseEnumConstantDeclaration()); |
| 4660 } |
| 4661 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 4662 } else { |
| 4663 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET); |
| 4664 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET); |
| 4665 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY, []); |
| 4666 } |
| 4667 return new EnumDeclaration(commentAndMetadata.comment, commentAndMetadata.me
tadata, keyword, name, leftBracket, constants, rightBracket); |
| 4668 } |
| 4669 |
| 4670 /** |
| 4671 * Parse an equality expression. |
| 4672 * |
| 4673 * <pre> |
| 4674 * equalityExpression ::= |
| 4675 * relationalExpression (equalityOperator relationalExpression)? |
| 4676 * | 'super' equalityOperator relationalExpression |
| 4677 * </pre> |
| 4678 * |
| 4679 * @return the equality expression that was parsed |
| 4680 */ |
| 4681 Expression _parseEqualityExpression() { |
| 4682 Expression expression; |
| 4683 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isEqualityOper
ator) { |
| 4684 expression = new SuperExpression(andAdvance); |
| 4685 } else { |
| 4686 expression = _parseRelationalExpression(); |
| 4687 } |
| 4688 bool leftEqualityExpression = false; |
| 4689 while (_currentToken.type.isEqualityOperator) { |
| 4690 Token operator = andAdvance; |
| 4691 if (leftEqualityExpression) { |
| 4692 _reportErrorForNode(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
expression, []); |
| 4693 } |
| 4694 expression = new BinaryExpression(expression, operator, _parseRelationalEx
pression()); |
| 4695 leftEqualityExpression = true; |
| 4696 } |
| 4697 return expression; |
| 4698 } |
| 4699 |
| 4700 /** |
| 4701 * Parse an export directive. |
| 4702 * |
| 4703 * <pre> |
| 4704 * exportDirective ::= |
| 4705 * metadata 'export' stringLiteral combinator*';' |
| 4706 * </pre> |
| 4707 * |
| 4708 * @param commentAndMetadata the metadata to be associated with the directive |
| 4709 * @return the export directive that was parsed |
| 4710 */ |
| 4711 ExportDirective _parseExportDirective(CommentAndMetadata commentAndMetadata) { |
| 4712 Token exportKeyword = _expectKeyword(Keyword.EXPORT); |
| 4713 StringLiteral libraryUri = parseStringLiteral(); |
| 4714 List<Combinator> combinators = _parseCombinators(); |
| 4715 Token semicolon = _expectSemicolon(); |
| 4716 return new ExportDirective(commentAndMetadata.comment, commentAndMetadata.me
tadata, exportKeyword, libraryUri, combinators, semicolon); |
| 4717 } |
| 4718 |
| 4719 /** |
| 4720 * Parse a list of expressions. |
| 4721 * |
| 4722 * <pre> |
| 4723 * expressionList ::= |
| 4724 * expression (',' expression)* |
| 4725 * </pre> |
| 4726 * |
| 4727 * @return the expression that was parsed |
| 4728 */ |
| 4729 List<Expression> _parseExpressionList() { |
| 4730 List<Expression> expressions = new List<Expression>(); |
| 4731 expressions.add(parseExpression2()); |
| 4732 while (_optional(TokenType.COMMA)) { |
| 4733 expressions.add(parseExpression2()); |
| 4734 } |
| 4735 return expressions; |
| 4736 } |
| 4737 |
| 4738 /** |
| 4739 * Parse the 'final', 'const', 'var' or type preceding a variable declaration. |
| 4740 * |
| 4741 * <pre> |
| 4742 * finalConstVarOrType ::= |
| 4743 * | 'final' type? |
| 4744 * | 'const' type? |
| 4745 * | 'var' |
| 4746 * | type |
| 4747 * </pre> |
| 4748 * |
| 4749 * @param optional `true` if the keyword and type are optional |
| 4750 * @return the 'final', 'const', 'var' or type that was parsed |
| 4751 */ |
| 4752 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { |
| 4753 Token keyword = null; |
| 4754 TypeName type = null; |
| 4755 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) { |
| 4756 keyword = andAdvance; |
| 4757 if (_isTypedIdentifier(_currentToken)) { |
| 4758 type = parseTypeName(); |
| 4759 } |
| 4760 } else if (_matchesKeyword(Keyword.VAR)) { |
| 4761 keyword = andAdvance; |
| 4762 } else { |
| 4763 if (_isTypedIdentifier(_currentToken)) { |
| 4764 type = parseReturnType(); |
| 4765 } else if (!optional) { |
| 4766 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T
YPE, []); |
| 4767 } |
| 4768 } |
| 4769 return new FinalConstVarOrType(keyword, type); |
| 4770 } |
| 4771 |
| 4772 /** |
| 4773 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be |
| 4774 * `true`. |
| 4775 * |
| 4776 * <pre> |
| 4777 * defaultFormalParameter ::= |
| 4778 * normalFormalParameter ('=' expression)? |
| 4779 * |
| 4780 * defaultNamedParameter ::= |
| 4781 * normalFormalParameter (':' expression)? |
| 4782 * </pre> |
| 4783 * |
| 4784 * @param kind the kind of parameter being expected based on the presence or a
bsence of group |
| 4785 * delimiters |
| 4786 * @return the formal parameter that was parsed |
| 4787 */ |
| 4788 FormalParameter _parseFormalParameter(ParameterKind kind) { |
| 4789 NormalFormalParameter parameter = parseNormalFormalParameter(); |
| 4790 if (_matches(TokenType.EQ)) { |
| 4791 Token seperator = andAdvance; |
| 4792 Expression defaultValue = parseExpression2(); |
| 4793 if (kind == ParameterKind.NAMED) { |
| 4794 _reportErrorForToken(ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER
, seperator, []); |
| 4795 } else if (kind == ParameterKind.REQUIRED) { |
| 4796 _reportErrorForNode(ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP,
parameter, []); |
| 4797 } |
| 4798 return new DefaultFormalParameter(parameter, kind, seperator, defaultValue
); |
| 4799 } else if (_matches(TokenType.COLON)) { |
| 4800 Token seperator = andAdvance; |
| 4801 Expression defaultValue = parseExpression2(); |
| 4802 if (kind == ParameterKind.POSITIONAL) { |
| 4803 _reportErrorForToken(ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARA
METER, seperator, []); |
| 4804 } else if (kind == ParameterKind.REQUIRED) { |
| 4805 _reportErrorForNode(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, param
eter, []); |
| 4806 } |
| 4807 return new DefaultFormalParameter(parameter, kind, seperator, defaultValue
); |
| 4808 } else if (kind != ParameterKind.REQUIRED) { |
| 4809 return new DefaultFormalParameter(parameter, kind, null, null); |
| 4810 } |
| 4811 return parameter; |
| 4812 } |
| 4813 |
| 4814 /** |
| 4815 * Parse a for statement. |
| 4816 * |
| 4817 * <pre> |
| 4818 * forStatement ::= |
| 4819 * 'for' '(' forLoopParts ')' statement |
| 4820 * |
| 4821 * forLoopParts ::= |
| 4822 * forInitializerStatement expression? ';' expressionList? |
| 4823 * | declaredIdentifier 'in' expression |
| 4824 * | identifier 'in' expression |
| 4825 * |
| 4826 * forInitializerStatement ::= |
| 4827 * localVariableDeclaration ';' |
| 4828 * | expression? ';' |
| 4829 * </pre> |
| 4830 * |
| 4831 * @return the for statement that was parsed |
| 4832 */ |
| 4833 Statement _parseForStatement() { |
| 4834 bool wasInLoop = _inLoop; |
| 4835 _inLoop = true; |
| 4836 try { |
| 4837 Token awaitKeyword = null; |
| 4838 if (_matchesString(_AWAIT)) { |
| 4839 awaitKeyword = andAdvance; |
| 4840 } |
| 4841 Token forKeyword = _expectKeyword(Keyword.FOR); |
| 4842 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 4843 VariableDeclarationList variableList = null; |
| 4844 Expression initialization = null; |
| 4845 if (!_matches(TokenType.SEMICOLON)) { |
| 4846 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 4847 if (_matchesIdentifier() && _tokenMatchesKeyword(_peek(), Keyword.IN)) { |
| 4848 List<VariableDeclaration> variables = new List<VariableDeclaration>(); |
| 4849 SimpleIdentifier variableName = parseSimpleIdentifier(); |
| 4850 variables.add(new VariableDeclaration(null, null, variableName, null,
null)); |
| 4851 variableList = new VariableDeclarationList(commentAndMetadata.comment,
commentAndMetadata.metadata, null, null, variables); |
| 4852 } else if (_isInitializedVariableDeclaration()) { |
| 4853 variableList = _parseVariableDeclarationListAfterMetadata(commentAndMe
tadata); |
| 4854 } else { |
| 4855 initialization = parseExpression2(); |
| 4856 } |
| 4857 if (_matchesKeyword(Keyword.IN)) { |
| 4858 DeclaredIdentifier loopVariable = null; |
| 4859 SimpleIdentifier identifier = null; |
| 4860 if (variableList == null) { |
| 4861 // We found: <expression> 'in' |
| 4862 _reportErrorForCurrentToken(ParserErrorCode.MISSING_VARIABLE_IN_FOR_
EACH, []); |
| 4863 } else { |
| 4864 NodeList<VariableDeclaration> variables = variableList.variables; |
| 4865 if (variables.length > 1) { |
| 4866 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_VARIABLES_IN_
FOR_EACH, [variables.length.toString()]); |
| 4867 } |
| 4868 VariableDeclaration variable = variables[0]; |
| 4869 if (variable.initializer != null) { |
| 4870 _reportErrorForCurrentToken(ParserErrorCode.INITIALIZED_VARIABLE_I
N_FOR_EACH, []); |
| 4871 } |
| 4872 Token keyword = variableList.keyword; |
| 4873 TypeName type = variableList.type; |
| 4874 if (keyword != null || type != null) { |
| 4875 loopVariable = new DeclaredIdentifier(commentAndMetadata.comment,
commentAndMetadata.metadata, keyword, type, variable.name); |
| 4876 } else { |
| 4877 if (!commentAndMetadata.metadata.isEmpty) { |
| 4878 } |
| 4879 identifier = variable.name; |
| 4880 } |
| 4881 } |
| 4882 Token inKeyword = _expectKeyword(Keyword.IN); |
| 4883 Expression iterator = parseExpression2(); |
| 4884 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 4885 Statement body = parseStatement2(); |
| 4886 if (loopVariable == null) { |
| 4887 return new ForEachStatement.con2(awaitKeyword, forKeyword, leftParen
thesis, identifier, inKeyword, iterator, rightParenthesis, body); |
| 4888 } |
| 4889 return new ForEachStatement.con1(awaitKeyword, forKeyword, leftParenth
esis, loopVariable, inKeyword, iterator, rightParenthesis, body); |
| 4890 } |
| 4891 } |
| 4892 if (awaitKeyword != null) { |
| 4893 _reportErrorForToken(ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword,
[]); |
| 4894 } |
| 4895 Token leftSeparator = _expect(TokenType.SEMICOLON); |
| 4896 Expression condition = null; |
| 4897 if (!_matches(TokenType.SEMICOLON)) { |
| 4898 condition = parseExpression2(); |
| 4899 } |
| 4900 Token rightSeparator = _expect(TokenType.SEMICOLON); |
| 4901 List<Expression> updaters = null; |
| 4902 if (!_matches(TokenType.CLOSE_PAREN)) { |
| 4903 updaters = _parseExpressionList(); |
| 4904 } |
| 4905 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 4906 Statement body = parseStatement2(); |
| 4907 return new ForStatement(forKeyword, leftParenthesis, variableList, initial
ization, leftSeparator, condition, rightSeparator, updaters, rightParenthesis, b
ody); |
| 4908 } finally { |
| 4909 _inLoop = wasInLoop; |
| 4910 } |
| 4911 } |
| 4912 |
| 4913 /** |
| 4914 * Parse a function body. |
| 4915 * |
| 4916 * <pre> |
| 4917 * functionBody ::= |
| 4918 * '=>' expression ';' |
| 4919 * | block |
| 4920 * |
| 4921 * functionExpressionBody ::= |
| 4922 * '=>' expression |
| 4923 * | block |
| 4924 * </pre> |
| 4925 * |
| 4926 * @param mayBeEmpty `true` if the function body is allowed to be empty |
| 4927 * @param emptyErrorCode the error code to report if function body expected, b
ut not found |
| 4928 * @param inExpression `true` if the function body is being parsed as part of
an expression |
| 4929 * and therefore does not have a terminating semicolon |
| 4930 * @return the function body that was parsed |
| 4931 */ |
| 4932 FunctionBody _parseFunctionBody(bool mayBeEmpty, ParserErrorCode emptyErrorCod
e, bool inExpression) { |
| 4933 bool wasInAsync = _inAsync; |
| 4934 bool wasInLoop = _inLoop; |
| 4935 bool wasInSwitch = _inSwitch; |
| 4936 _inAsync = false; |
| 4937 _inLoop = false; |
| 4938 _inSwitch = false; |
| 4939 try { |
| 4940 if (_matches(TokenType.SEMICOLON)) { |
| 4941 if (!mayBeEmpty) { |
| 4942 _reportErrorForCurrentToken(emptyErrorCode, []); |
| 4943 } |
| 4944 return new EmptyFunctionBody(andAdvance); |
| 4945 } else if (_matchesString(_NATIVE)) { |
| 4946 Token nativeToken = andAdvance; |
| 4947 StringLiteral stringLiteral = null; |
| 4948 if (_matches(TokenType.STRING)) { |
| 4949 stringLiteral = parseStringLiteral(); |
| 4950 } |
| 4951 return new NativeFunctionBody(nativeToken, stringLiteral, _expect(TokenT
ype.SEMICOLON)); |
| 4952 } |
| 4953 Token keyword = null; |
| 4954 Token star = null; |
| 4955 if (_parseAsync) { |
| 4956 if (_matchesString(ASYNC)) { |
| 4957 keyword = andAdvance; |
| 4958 if (_matches(TokenType.STAR)) { |
| 4959 star = andAdvance; |
| 4960 } |
| 4961 _inAsync = true; |
| 4962 } else if (_matchesString(SYNC)) { |
| 4963 keyword = andAdvance; |
| 4964 if (_matches(TokenType.STAR)) { |
| 4965 star = andAdvance; |
| 4966 } |
| 4967 } |
| 4968 } |
| 4969 if (_matches(TokenType.FUNCTION)) { |
| 4970 if (keyword != null) { |
| 4971 if (!_tokenMatchesString(keyword, ASYNC)) { |
| 4972 _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword, []); |
| 4973 keyword = null; |
| 4974 } else if (star != null) { |
| 4975 _reportErrorForToken(ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star,
[]); |
| 4976 } |
| 4977 } |
| 4978 Token functionDefinition = andAdvance; |
| 4979 Expression expression = parseExpression2(); |
| 4980 Token semicolon = null; |
| 4981 if (!inExpression) { |
| 4982 semicolon = _expect(TokenType.SEMICOLON); |
| 4983 } |
| 4984 if (!_parseFunctionBodies) { |
| 4985 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON
)); |
| 4986 } |
| 4987 return new ExpressionFunctionBody(keyword, functionDefinition, expressio
n, semicolon); |
| 4988 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 4989 if (keyword != null) { |
| 4990 if (_tokenMatchesString(keyword, SYNC) && star == null) { |
| 4991 _reportErrorForToken(ParserErrorCode.MISSING_STAR_AFTER_SYNC, keywor
d, []); |
| 4992 } |
| 4993 } |
| 4994 if (!_parseFunctionBodies) { |
| 4995 _skipBlock(); |
| 4996 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON
)); |
| 4997 } |
| 4998 return new BlockFunctionBody(keyword, star, parseBlock()); |
| 4999 } else { |
| 5000 // Invalid function body |
| 5001 _reportErrorForCurrentToken(emptyErrorCode, []); |
| 5002 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON))
; |
| 5003 } |
| 5004 } finally { |
| 5005 _inAsync = wasInAsync; |
| 5006 _inLoop = wasInLoop; |
| 5007 _inSwitch = wasInSwitch; |
| 5008 } |
| 5009 } |
| 5010 |
| 5011 /** |
| 5012 * Parse a function declaration. |
| 5013 * |
| 5014 * <pre> |
| 5015 * functionDeclaration ::= |
| 5016 * functionSignature functionBody |
| 5017 * | returnType? getOrSet identifier formalParameterList functionBody |
| 5018 * </pre> |
| 5019 * |
| 5020 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5021 * declaration |
| 5022 * @param externalKeyword the 'external' keyword, or `null` if the function is
not external |
| 5023 * @param returnType the return type, or `null` if there is no return type |
| 5024 * @param isStatement `true` if the function declaration is being parsed as a
statement |
| 5025 * @return the function declaration that was parsed |
| 5026 */ |
| 5027 FunctionDeclaration _parseFunctionDeclaration(CommentAndMetadata commentAndMet
adata, Token externalKeyword, TypeName returnType) { |
| 5028 Token keyword = null; |
| 5029 bool isGetter = false; |
| 5030 if (_matchesKeyword(Keyword.GET) && !_tokenMatches(_peek(), TokenType.OPEN_P
AREN)) { |
| 5031 keyword = andAdvance; |
| 5032 isGetter = true; |
| 5033 } else if (_matchesKeyword(Keyword.SET) && !_tokenMatches(_peek(), TokenType
.OPEN_PAREN)) { |
| 5034 keyword = andAdvance; |
| 5035 } |
| 5036 SimpleIdentifier name = parseSimpleIdentifier(); |
| 5037 FormalParameterList parameters = null; |
| 5038 if (!isGetter) { |
| 5039 if (_matches(TokenType.OPEN_PAREN)) { |
| 5040 parameters = parseFormalParameterList(); |
| 5041 _validateFormalParameterList(parameters); |
| 5042 } else { |
| 5043 _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
[]); |
| 5044 } |
| 5045 } else if (_matches(TokenType.OPEN_PAREN)) { |
| 5046 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS, []); |
| 5047 parseFormalParameterList(); |
| 5048 } |
| 5049 FunctionBody body; |
| 5050 if (externalKeyword == null) { |
| 5051 body = _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, fa
lse); |
| 5052 } else { |
| 5053 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON)); |
| 5054 } |
| 5055 // if (!isStatement && matches(TokenType.SEMICOLON)) { |
| 5056 // // TODO(brianwilkerson) Improve this error message. |
| 5057 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme
()); |
| 5058 // advance(); |
| 5059 // } |
| 5060 return new FunctionDeclaration(commentAndMetadata.comment, commentAndMetadat
a.metadata, externalKeyword, returnType, keyword, name, new FunctionExpression(p
arameters, body)); |
| 5061 } |
| 5062 |
| 5063 /** |
| 5064 * Parse a function declaration statement. |
| 5065 * |
| 5066 * <pre> |
| 5067 * functionDeclarationStatement ::= |
| 5068 * functionSignature functionBody |
| 5069 * </pre> |
| 5070 * |
| 5071 * @return the function declaration statement that was parsed |
| 5072 */ |
| 5073 Statement _parseFunctionDeclarationStatement() { |
| 5074 Modifiers modifiers = _parseModifiers(); |
| 5075 _validateModifiersForFunctionDeclarationStatement(modifiers); |
| 5076 return _parseFunctionDeclarationStatementAfterReturnType(_parseCommentAndMet
adata(), _parseOptionalReturnType()); |
| 5077 } |
| 5078 |
| 5079 /** |
| 5080 * Parse a function declaration statement. |
| 5081 * |
| 5082 * <pre> |
| 5083 * functionDeclarationStatement ::= |
| 5084 * functionSignature functionBody |
| 5085 * </pre> |
| 5086 * |
| 5087 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5088 * declaration |
| 5089 * @param returnType the return type, or `null` if there is no return type |
| 5090 * @return the function declaration statement that was parsed |
| 5091 */ |
| 5092 Statement _parseFunctionDeclarationStatementAfterReturnType(CommentAndMetadata
commentAndMetadata, TypeName returnType) { |
| 5093 FunctionDeclaration declaration = _parseFunctionDeclaration(commentAndMetada
ta, null, returnType); |
| 5094 Token propertyKeyword = declaration.propertyKeyword; |
| 5095 if (propertyKeyword != null) { |
| 5096 if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) { |
| 5097 _reportErrorForToken(ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword
, []); |
| 5098 } else { |
| 5099 _reportErrorForToken(ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword
, []); |
| 5100 } |
| 5101 } |
| 5102 return new FunctionDeclarationStatement(declaration); |
| 5103 } |
| 5104 |
| 5105 /** |
| 5106 * Parse a function type alias. |
| 5107 * |
| 5108 * <pre> |
| 5109 * functionTypeAlias ::= |
| 5110 * functionPrefix typeParameterList? formalParameterList ';' |
| 5111 * |
| 5112 * functionPrefix ::= |
| 5113 * returnType? name |
| 5114 * </pre> |
| 5115 * |
| 5116 * @param commentAndMetadata the metadata to be associated with the member |
| 5117 * @param keyword the token representing the 'typedef' keyword |
| 5118 * @return the function type alias that was parsed |
| 5119 */ |
| 5120 FunctionTypeAlias _parseFunctionTypeAlias(CommentAndMetadata commentAndMetadat
a, Token keyword) { |
| 5121 TypeName returnType = null; |
| 5122 if (hasReturnTypeInTypeAlias) { |
| 5123 returnType = parseReturnType(); |
| 5124 } |
| 5125 SimpleIdentifier name = parseSimpleIdentifier(); |
| 5126 TypeParameterList typeParameters = null; |
| 5127 if (_matches(TokenType.LT)) { |
| 5128 typeParameters = parseTypeParameterList(); |
| 5129 } |
| 5130 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.EOF)) { |
| 5131 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []
); |
| 5132 FormalParameterList parameters = new FormalParameterList(_createSyntheticT
oken(TokenType.OPEN_PAREN), null, null, null, _createSyntheticToken(TokenType.CL
OSE_PAREN)); |
| 5133 Token semicolon = _expect(TokenType.SEMICOLON); |
| 5134 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat
a.metadata, keyword, returnType, name, typeParameters, parameters, semicolon); |
| 5135 } else if (!_matches(TokenType.OPEN_PAREN)) { |
| 5136 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []
); |
| 5137 // TODO(brianwilkerson) Recover from this error. At the very least we shou
ld skip to the start |
| 5138 // of the next valid compilation unit member, allowing for the possibility
of finding the |
| 5139 // typedef parameters before that point. |
| 5140 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat
a.metadata, keyword, returnType, name, typeParameters, new FormalParameterList(_
createSyntheticToken(TokenType.OPEN_PAREN), null, null, null, _createSyntheticTo
ken(TokenType.CLOSE_PAREN)), _createSyntheticToken(TokenType.SEMICOLON)); |
| 5141 } |
| 5142 FormalParameterList parameters = parseFormalParameterList(); |
| 5143 _validateFormalParameterList(parameters); |
| 5144 Token semicolon = _expect(TokenType.SEMICOLON); |
| 5145 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadata.
metadata, keyword, returnType, name, typeParameters, parameters, semicolon); |
| 5146 } |
| 5147 |
| 5148 /** |
| 5149 * Parse a getter. |
| 5150 * |
| 5151 * <pre> |
| 5152 * getter ::= |
| 5153 * getterSignature functionBody? |
| 5154 * |
| 5155 * getterSignature ::= |
| 5156 * 'external'? 'static'? returnType? 'get' identifier |
| 5157 * </pre> |
| 5158 * |
| 5159 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5160 * declaration |
| 5161 * @param externalKeyword the 'external' token |
| 5162 * @param staticKeyword the static keyword, or `null` if the getter is not sta
tic |
| 5163 * @param the return type that has already been parsed, or `null` if there was
no return |
| 5164 * type |
| 5165 * @return the getter that was parsed |
| 5166 */ |
| 5167 MethodDeclaration _parseGetter(CommentAndMetadata commentAndMetadata, Token ex
ternalKeyword, Token staticKeyword, TypeName returnType) { |
| 5168 Token propertyKeyword = _expectKeyword(Keyword.GET); |
| 5169 SimpleIdentifier name = parseSimpleIdentifier(); |
| 5170 if (_matches(TokenType.OPEN_PAREN) && _tokenMatches(_peek(), TokenType.CLOSE
_PAREN)) { |
| 5171 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS, []); |
| 5172 _advance(); |
| 5173 _advance(); |
| 5174 } |
| 5175 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw
ord == null, ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false); |
| 5176 if (externalKeyword != null && body is! EmptyFunctionBody) { |
| 5177 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY, [])
; |
| 5178 } |
| 5179 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata.
metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, nam
e, null, body); |
| 5180 } |
| 5181 |
| 5182 /** |
| 5183 * Parse a list of identifiers. |
| 5184 * |
| 5185 * <pre> |
| 5186 * identifierList ::= |
| 5187 * identifier (',' identifier)* |
| 5188 * </pre> |
| 5189 * |
| 5190 * @return the list of identifiers that were parsed |
| 5191 */ |
| 5192 List<SimpleIdentifier> _parseIdentifierList() { |
| 5193 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>(); |
| 5194 identifiers.add(parseSimpleIdentifier()); |
| 5195 while (_matches(TokenType.COMMA)) { |
| 5196 _advance(); |
| 5197 identifiers.add(parseSimpleIdentifier()); |
| 5198 } |
| 5199 return identifiers; |
| 5200 } |
| 5201 |
| 5202 /** |
| 5203 * Parse an if statement. |
| 5204 * |
| 5205 * <pre> |
| 5206 * ifStatement ::= |
| 5207 * 'if' '(' expression ')' statement ('else' statement)? |
| 5208 * </pre> |
| 5209 * |
| 5210 * @return the if statement that was parsed |
| 5211 */ |
| 5212 Statement _parseIfStatement() { |
| 5213 Token ifKeyword = _expectKeyword(Keyword.IF); |
| 5214 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 5215 Expression condition = parseExpression2(); |
| 5216 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 5217 Statement thenStatement = parseStatement2(); |
| 5218 Token elseKeyword = null; |
| 5219 Statement elseStatement = null; |
| 5220 if (_matchesKeyword(Keyword.ELSE)) { |
| 5221 elseKeyword = andAdvance; |
| 5222 elseStatement = parseStatement2(); |
| 5223 } |
| 5224 return new IfStatement(ifKeyword, leftParenthesis, condition, rightParenthes
is, thenStatement, elseKeyword, elseStatement); |
| 5225 } |
| 5226 |
| 5227 /** |
| 5228 * Parse an import directive. |
| 5229 * |
| 5230 * <pre> |
| 5231 * importDirective ::= |
| 5232 * metadata 'import' stringLiteral ('as' identifier)? combinator*';' |
| 5233 * </pre> |
| 5234 * |
| 5235 * @param commentAndMetadata the metadata to be associated with the directive |
| 5236 * @return the import directive that was parsed |
| 5237 */ |
| 5238 ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) { |
| 5239 Token importKeyword = _expectKeyword(Keyword.IMPORT); |
| 5240 StringLiteral libraryUri = parseStringLiteral(); |
| 5241 Token deferredToken = null; |
| 5242 Token asToken = null; |
| 5243 SimpleIdentifier prefix = null; |
| 5244 if (_matchesKeyword(Keyword.DEFERRED)) { |
| 5245 if (_parseDeferredLibraries) { |
| 5246 deferredToken = andAdvance; |
| 5247 } else { |
| 5248 _reportErrorForCurrentToken(ParserErrorCode.DEFERRED_IMPORTS_NOT_SUPPORT
ED, []); |
| 5249 _advance(); |
| 5250 } |
| 5251 } |
| 5252 if (_matchesKeyword(Keyword.AS)) { |
| 5253 asToken = andAdvance; |
| 5254 prefix = parseSimpleIdentifier(); |
| 5255 } else if (deferredToken != null) { |
| 5256 _reportErrorForCurrentToken(ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMP
ORT, []); |
| 5257 } |
| 5258 List<Combinator> combinators = _parseCombinators(); |
| 5259 Token semicolon = _expectSemicolon(); |
| 5260 return new ImportDirective(commentAndMetadata.comment, commentAndMetadata.me
tadata, importKeyword, libraryUri, deferredToken, asToken, prefix, combinators,
semicolon); |
| 5261 } |
| 5262 |
| 5263 /** |
| 5264 * Parse a list of initialized identifiers. |
| 5265 * |
| 5266 * <pre> |
| 5267 * ?? ::= |
| 5268 * 'static'? ('var' | type) initializedIdentifierList ';' |
| 5269 * | 'final' type? initializedIdentifierList ';' |
| 5270 * |
| 5271 * initializedIdentifierList ::= |
| 5272 * initializedIdentifier (',' initializedIdentifier)* |
| 5273 * |
| 5274 * initializedIdentifier ::= |
| 5275 * identifier ('=' expression)? |
| 5276 * </pre> |
| 5277 * |
| 5278 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5279 * declaration |
| 5280 * @param staticKeyword the static keyword, or `null` if the getter is not sta
tic |
| 5281 * @param keyword the token representing the 'final', 'const' or 'var' keyword
, or `null` if |
| 5282 * there is no keyword |
| 5283 * @param type the type that has already been parsed, or `null` if 'var' was p
rovided |
| 5284 * @return the getter that was parsed |
| 5285 */ |
| 5286 FieldDeclaration _parseInitializedIdentifierList(CommentAndMetadata commentAnd
Metadata, Token staticKeyword, Token keyword, TypeName type) { |
| 5287 VariableDeclarationList fieldList = _parseVariableDeclarationListAfterType(n
ull, keyword, type); |
| 5288 return new FieldDeclaration(commentAndMetadata.comment, commentAndMetadata.m
etadata, staticKeyword, fieldList, _expect(TokenType.SEMICOLON)); |
| 5289 } |
| 5290 |
| 5291 /** |
| 5292 * Parse an instance creation expression. |
| 5293 * |
| 5294 * <pre> |
| 5295 * instanceCreationExpression ::= |
| 5296 * ('new' | 'const') type ('.' identifier)? argumentList |
| 5297 * </pre> |
| 5298 * |
| 5299 * @param keyword the 'new' or 'const' keyword that introduces the expression |
| 5300 * @return the instance creation expression that was parsed |
| 5301 */ |
| 5302 InstanceCreationExpression _parseInstanceCreationExpression(Token keyword) { |
| 5303 ConstructorName constructorName = parseConstructorName(); |
| 5304 ArgumentList argumentList = parseArgumentList(); |
| 5305 return new InstanceCreationExpression(keyword, constructorName, argumentList
); |
| 5306 } |
| 5307 |
| 5308 /** |
| 5309 * Parse a library directive. |
| 5310 * |
| 5311 * <pre> |
| 5312 * libraryDirective ::= |
| 5313 * metadata 'library' identifier ';' |
| 5314 * </pre> |
| 5315 * |
| 5316 * @param commentAndMetadata the metadata to be associated with the directive |
| 5317 * @return the library directive that was parsed |
| 5318 */ |
| 5319 LibraryDirective _parseLibraryDirective(CommentAndMetadata commentAndMetadata)
{ |
| 5320 Token keyword = _expectKeyword(Keyword.LIBRARY); |
| 5321 LibraryIdentifier libraryName = _parseLibraryName(ParserErrorCode.MISSING_NA
ME_IN_LIBRARY_DIRECTIVE, keyword); |
| 5322 Token semicolon = _expect(TokenType.SEMICOLON); |
| 5323 return new LibraryDirective(commentAndMetadata.comment, commentAndMetadata.m
etadata, keyword, libraryName, semicolon); |
| 5324 } |
| 5325 |
| 5326 /** |
| 5327 * Parse a library name. |
| 5328 * |
| 5329 * <pre> |
| 5330 * libraryName ::= |
| 5331 * libraryIdentifier |
| 5332 * </pre> |
| 5333 * |
| 5334 * @param missingNameError the error code to be used if the library name is mi
ssing |
| 5335 * @param missingNameToken the token associated with the error produced if the
library name is |
| 5336 * missing |
| 5337 * @return the library name that was parsed |
| 5338 */ |
| 5339 LibraryIdentifier _parseLibraryName(ParserErrorCode missingNameError, Token mi
ssingNameToken) { |
| 5340 if (_matchesIdentifier()) { |
| 5341 return parseLibraryIdentifier(); |
| 5342 } else if (_matches(TokenType.STRING)) { |
| 5343 // TODO(brianwilkerson) Recovery: This should be extended to handle arbitr
ary tokens until we |
| 5344 // can find a token that can start a compilation unit member. |
| 5345 StringLiteral string = parseStringLiteral(); |
| 5346 _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, [
]); |
| 5347 } else { |
| 5348 _reportErrorForToken(missingNameError, missingNameToken, []); |
| 5349 } |
| 5350 List<SimpleIdentifier> components = new List<SimpleIdentifier>(); |
| 5351 components.add(_createSyntheticIdentifier()); |
| 5352 return new LibraryIdentifier(components); |
| 5353 } |
| 5354 |
| 5355 /** |
| 5356 * Parse a list literal. |
| 5357 * |
| 5358 * <pre> |
| 5359 * listLiteral ::= |
| 5360 * 'const'? typeArguments? '[' (expressionList ','?)? ']' |
| 5361 * </pre> |
| 5362 * |
| 5363 * @param modifier the 'const' modifier appearing before the literal, or `null
` if there is |
| 5364 * no modifier |
| 5365 * @param typeArguments the type arguments appearing before the literal, or `n
ull` if there |
| 5366 * are no type arguments |
| 5367 * @return the list literal that was parsed |
| 5368 */ |
| 5369 ListLiteral _parseListLiteral(Token modifier, TypeArgumentList typeArguments)
{ |
| 5370 // may be empty list literal |
| 5371 if (_matches(TokenType.INDEX)) { |
| 5372 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu
rrentToken.offset); |
| 5373 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok
en.offset + 1); |
| 5374 leftBracket.endToken = rightBracket; |
| 5375 rightBracket.setNext(_currentToken.next); |
| 5376 leftBracket.setNext(rightBracket); |
| 5377 _currentToken.previous.setNext(leftBracket); |
| 5378 _currentToken = _currentToken.next; |
| 5379 return new ListLiteral(modifier, typeArguments, leftBracket, null, rightBr
acket); |
| 5380 } |
| 5381 // open |
| 5382 Token leftBracket = _expect(TokenType.OPEN_SQUARE_BRACKET); |
| 5383 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) { |
| 5384 return new ListLiteral(modifier, typeArguments, leftBracket, null, andAdva
nce); |
| 5385 } |
| 5386 bool wasInInitializer = _inInitializer; |
| 5387 _inInitializer = false; |
| 5388 try { |
| 5389 List<Expression> elements = new List<Expression>(); |
| 5390 elements.add(parseExpression2()); |
| 5391 while (_optional(TokenType.COMMA)) { |
| 5392 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) { |
| 5393 return new ListLiteral(modifier, typeArguments, leftBracket, elements,
andAdvance); |
| 5394 } |
| 5395 elements.add(parseExpression2()); |
| 5396 } |
| 5397 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET); |
| 5398 return new ListLiteral(modifier, typeArguments, leftBracket, elements, rig
htBracket); |
| 5399 } finally { |
| 5400 _inInitializer = wasInInitializer; |
| 5401 } |
| 5402 } |
| 5403 |
| 5404 /** |
| 5405 * Parse a list or map literal. |
| 5406 * |
| 5407 * <pre> |
| 5408 * listOrMapLiteral ::= |
| 5409 * listLiteral |
| 5410 * | mapLiteral |
| 5411 * </pre> |
| 5412 * |
| 5413 * @param modifier the 'const' modifier appearing before the literal, or `null
` if there is |
| 5414 * no modifier |
| 5415 * @return the list or map literal that was parsed |
| 5416 */ |
| 5417 TypedLiteral _parseListOrMapLiteral(Token modifier) { |
| 5418 TypeArgumentList typeArguments = null; |
| 5419 if (_matches(TokenType.LT)) { |
| 5420 typeArguments = parseTypeArgumentList(); |
| 5421 } |
| 5422 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 5423 return _parseMapLiteral(modifier, typeArguments); |
| 5424 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.IND
EX)) { |
| 5425 return _parseListLiteral(modifier, typeArguments); |
| 5426 } |
| 5427 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, []
); |
| 5428 return new ListLiteral(modifier, typeArguments, _createSyntheticToken(TokenT
ype.OPEN_SQUARE_BRACKET), null, _createSyntheticToken(TokenType.CLOSE_SQUARE_BRA
CKET)); |
| 5429 } |
| 5430 |
| 5431 /** |
| 5432 * Parse a logical and expression. |
| 5433 * |
| 5434 * <pre> |
| 5435 * logicalAndExpression ::= |
| 5436 * equalityExpression ('&&' equalityExpression)* |
| 5437 * </pre> |
| 5438 * |
| 5439 * @return the logical and expression that was parsed |
| 5440 */ |
| 5441 Expression _parseLogicalAndExpression() { |
| 5442 Expression expression = _parseEqualityExpression(); |
| 5443 while (_matches(TokenType.AMPERSAND_AMPERSAND)) { |
| 5444 Token operator = andAdvance; |
| 5445 expression = new BinaryExpression(expression, operator, _parseEqualityExpr
ession()); |
| 5446 } |
| 5447 return expression; |
| 5448 } |
| 5449 |
| 5450 /** |
| 5451 * Parse a map literal. |
| 5452 * |
| 5453 * <pre> |
| 5454 * mapLiteral ::= |
| 5455 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','
?)? '}' |
| 5456 * </pre> |
| 5457 * |
| 5458 * @param modifier the 'const' modifier appearing before the literal, or `null
` if there is |
| 5459 * no modifier |
| 5460 * @param typeArguments the type arguments that were declared, or `null` if th
ere are no |
| 5461 * type arguments |
| 5462 * @return the map literal that was parsed |
| 5463 */ |
| 5464 MapLiteral _parseMapLiteral(Token modifier, TypeArgumentList typeArguments) { |
| 5465 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); |
| 5466 List<MapLiteralEntry> entries = new List<MapLiteralEntry>(); |
| 5467 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 5468 return new MapLiteral(modifier, typeArguments, leftBracket, entries, andAd
vance); |
| 5469 } |
| 5470 bool wasInInitializer = _inInitializer; |
| 5471 _inInitializer = false; |
| 5472 try { |
| 5473 entries.add(parseMapLiteralEntry()); |
| 5474 while (_optional(TokenType.COMMA)) { |
| 5475 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 5476 return new MapLiteral(modifier, typeArguments, leftBracket, entries, a
ndAdvance); |
| 5477 } |
| 5478 entries.add(parseMapLiteralEntry()); |
| 5479 } |
| 5480 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 5481 return new MapLiteral(modifier, typeArguments, leftBracket, entries, right
Bracket); |
| 5482 } finally { |
| 5483 _inInitializer = wasInInitializer; |
| 5484 } |
| 5485 } |
| 5486 |
| 5487 /** |
| 5488 * Parse a method declaration. |
| 5489 * |
| 5490 * <pre> |
| 5491 * functionDeclaration ::= |
| 5492 * ('external' 'static'?)? functionSignature functionBody |
| 5493 * | 'external'? functionSignature ';' |
| 5494 * </pre> |
| 5495 * |
| 5496 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5497 * declaration |
| 5498 * @param externalKeyword the 'external' token |
| 5499 * @param staticKeyword the static keyword, or `null` if the getter is not sta
tic |
| 5500 * @param returnType the return type of the method |
| 5501 * @param name the name of the method |
| 5502 * @param parameters the parameters to the method |
| 5503 * @return the method declaration that was parsed |
| 5504 */ |
| 5505 MethodDeclaration _parseMethodDeclarationAfterParameters(CommentAndMetadata co
mmentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnTyp
e, SimpleIdentifier name, FormalParameterList parameters) { |
| 5506 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw
ord == null, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| 5507 if (externalKeyword != null) { |
| 5508 if (body is! EmptyFunctionBody) { |
| 5509 _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body, [])
; |
| 5510 } |
| 5511 } else if (staticKeyword != null) { |
| 5512 if (body is EmptyFunctionBody) { |
| 5513 _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body, []); |
| 5514 } |
| 5515 } |
| 5516 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata.
metadata, externalKeyword, staticKeyword, returnType, null, null, name, paramete
rs, body); |
| 5517 } |
| 5518 |
| 5519 /** |
| 5520 * Parse a method declaration. |
| 5521 * |
| 5522 * <pre> |
| 5523 * functionDeclaration ::= |
| 5524 * 'external'? 'static'? functionSignature functionBody |
| 5525 * | 'external'? functionSignature ';' |
| 5526 * </pre> |
| 5527 * |
| 5528 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5529 * declaration |
| 5530 * @param externalKeyword the 'external' token |
| 5531 * @param staticKeyword the static keyword, or `null` if the getter is not sta
tic |
| 5532 * @param returnType the return type of the method |
| 5533 * @return the method declaration that was parsed |
| 5534 */ |
| 5535 MethodDeclaration _parseMethodDeclarationAfterReturnType(CommentAndMetadata co
mmentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnTyp
e) { |
| 5536 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 5537 FormalParameterList parameters = parseFormalParameterList(); |
| 5538 _validateFormalParameterList(parameters); |
| 5539 return _parseMethodDeclarationAfterParameters(commentAndMetadata, externalKe
yword, staticKeyword, returnType, methodName, parameters); |
| 5540 } |
| 5541 |
| 5542 /** |
| 5543 * Parse the modifiers preceding a declaration. This method allows the modifie
rs to appear in any |
| 5544 * order but does generate errors for duplicated modifiers. Checks for other p
roblems, such as |
| 5545 * having the modifiers appear in the wrong order or specifying both 'const' a
nd 'final', are |
| 5546 * reported in one of the methods whose name is prefixed with `validateModifie
rsFor`. |
| 5547 * |
| 5548 * <pre> |
| 5549 * modifiers ::= |
| 5550 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | '
var')* |
| 5551 * </pre> |
| 5552 * |
| 5553 * @return the modifiers that were parsed |
| 5554 */ |
| 5555 Modifiers _parseModifiers() { |
| 5556 Modifiers modifiers = new Modifiers(); |
| 5557 bool progress = true; |
| 5558 while (progress) { |
| 5559 if (_tokenMatches(_peek(), TokenType.PERIOD) || _tokenMatches(_peek(), Tok
enType.LT) || _tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 5560 return modifiers; |
| 5561 } |
| 5562 if (_matchesKeyword(Keyword.ABSTRACT)) { |
| 5563 if (modifiers.abstractKeyword != null) { |
| 5564 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5565 _advance(); |
| 5566 } else { |
| 5567 modifiers.abstractKeyword = andAdvance; |
| 5568 } |
| 5569 } else if (_matchesKeyword(Keyword.CONST)) { |
| 5570 if (modifiers.constKeyword != null) { |
| 5571 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5572 _advance(); |
| 5573 } else { |
| 5574 modifiers.constKeyword = andAdvance; |
| 5575 } |
| 5576 } else if (_matchesKeyword(Keyword.EXTERNAL) && !_tokenMatches(_peek(), To
kenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) { |
| 5577 if (modifiers.externalKeyword != null) { |
| 5578 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5579 _advance(); |
| 5580 } else { |
| 5581 modifiers.externalKeyword = andAdvance; |
| 5582 } |
| 5583 } else if (_matchesKeyword(Keyword.FACTORY) && !_tokenMatches(_peek(), Tok
enType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) { |
| 5584 if (modifiers.factoryKeyword != null) { |
| 5585 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5586 _advance(); |
| 5587 } else { |
| 5588 modifiers.factoryKeyword = andAdvance; |
| 5589 } |
| 5590 } else if (_matchesKeyword(Keyword.FINAL)) { |
| 5591 if (modifiers.finalKeyword != null) { |
| 5592 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5593 _advance(); |
| 5594 } else { |
| 5595 modifiers.finalKeyword = andAdvance; |
| 5596 } |
| 5597 } else if (_matchesKeyword(Keyword.STATIC) && !_tokenMatches(_peek(), Toke
nType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) { |
| 5598 if (modifiers.staticKeyword != null) { |
| 5599 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5600 _advance(); |
| 5601 } else { |
| 5602 modifiers.staticKeyword = andAdvance; |
| 5603 } |
| 5604 } else if (_matchesKeyword(Keyword.VAR)) { |
| 5605 if (modifiers.varKeyword != null) { |
| 5606 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur
rentToken.lexeme]); |
| 5607 _advance(); |
| 5608 } else { |
| 5609 modifiers.varKeyword = andAdvance; |
| 5610 } |
| 5611 } else { |
| 5612 progress = false; |
| 5613 } |
| 5614 } |
| 5615 return modifiers; |
| 5616 } |
| 5617 |
| 5618 /** |
| 5619 * Parse a multiplicative expression. |
| 5620 * |
| 5621 * <pre> |
| 5622 * multiplicativeExpression ::= |
| 5623 * unaryExpression (multiplicativeOperator unaryExpression)* |
| 5624 * | 'super' (multiplicativeOperator unaryExpression)+ |
| 5625 * </pre> |
| 5626 * |
| 5627 * @return the multiplicative expression that was parsed |
| 5628 */ |
| 5629 Expression _parseMultiplicativeExpression() { |
| 5630 Expression expression; |
| 5631 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isMultiplicati
veOperator) { |
| 5632 expression = new SuperExpression(andAdvance); |
| 5633 } else { |
| 5634 expression = _parseUnaryExpression(); |
| 5635 } |
| 5636 while (_currentToken.type.isMultiplicativeOperator) { |
| 5637 Token operator = andAdvance; |
| 5638 expression = new BinaryExpression(expression, operator, _parseUnaryExpress
ion()); |
| 5639 } |
| 5640 return expression; |
| 5641 } |
| 5642 |
| 5643 /** |
| 5644 * Parse a class native clause. |
| 5645 * |
| 5646 * <pre> |
| 5647 * classNativeClause ::= |
| 5648 * 'native' name |
| 5649 * </pre> |
| 5650 * |
| 5651 * @return the class native clause that was parsed |
| 5652 */ |
| 5653 NativeClause _parseNativeClause() { |
| 5654 Token keyword = andAdvance; |
| 5655 StringLiteral name = parseStringLiteral(); |
| 5656 return new NativeClause(keyword, name); |
| 5657 } |
| 5658 |
| 5659 /** |
| 5660 * Parse a new expression. |
| 5661 * |
| 5662 * <pre> |
| 5663 * newExpression ::= |
| 5664 * instanceCreationExpression |
| 5665 * </pre> |
| 5666 * |
| 5667 * @return the new expression that was parsed |
| 5668 */ |
| 5669 InstanceCreationExpression _parseNewExpression() => _parseInstanceCreationExpr
ession(_expectKeyword(Keyword.NEW)); |
| 5670 |
| 5671 /** |
| 5672 * Parse a non-labeled statement. |
| 5673 * |
| 5674 * <pre> |
| 5675 * nonLabeledStatement ::= |
| 5676 * block |
| 5677 * | assertStatement |
| 5678 * | breakStatement |
| 5679 * | continueStatement |
| 5680 * | doStatement |
| 5681 * | forStatement |
| 5682 * | ifStatement |
| 5683 * | returnStatement |
| 5684 * | switchStatement |
| 5685 * | tryStatement |
| 5686 * | whileStatement |
| 5687 * | variableDeclarationList ';' |
| 5688 * | expressionStatement |
| 5689 * | functionSignature functionBody |
| 5690 * </pre> |
| 5691 * |
| 5692 * @return the non-labeled statement that was parsed |
| 5693 */ |
| 5694 Statement _parseNonLabeledStatement() { |
| 5695 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate. |
| 5696 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 5697 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 5698 if (_tokenMatches(_peek(), TokenType.STRING)) { |
| 5699 Token afterString = _skipStringLiteral(_currentToken.next); |
| 5700 if (afterString != null && afterString.type == TokenType.COLON) { |
| 5701 return new ExpressionStatement(parseExpression2(), _expect(TokenType.S
EMICOLON)); |
| 5702 } |
| 5703 } |
| 5704 return parseBlock(); |
| 5705 } else if (_matches(TokenType.KEYWORD) && !(_currentToken as KeywordToken).k
eyword.isPseudoKeyword) { |
| 5706 Keyword keyword = (_currentToken as KeywordToken).keyword; |
| 5707 // TODO(jwren) compute some metrics to figure out a better order for this
if-then sequence to optimize performance |
| 5708 if (keyword == Keyword.ASSERT) { |
| 5709 return _parseAssertStatement(); |
| 5710 } else if (keyword == Keyword.BREAK) { |
| 5711 return _parseBreakStatement(); |
| 5712 } else if (keyword == Keyword.CONTINUE) { |
| 5713 return _parseContinueStatement(); |
| 5714 } else if (keyword == Keyword.DO) { |
| 5715 return _parseDoStatement(); |
| 5716 } else if (keyword == Keyword.FOR) { |
| 5717 return _parseForStatement(); |
| 5718 } else if (keyword == Keyword.IF) { |
| 5719 return _parseIfStatement(); |
| 5720 } else if (keyword == Keyword.RETHROW) { |
| 5721 return new ExpressionStatement(_parseRethrowExpression(), _expect(TokenT
ype.SEMICOLON)); |
| 5722 } else if (keyword == Keyword.RETURN) { |
| 5723 return _parseReturnStatement(); |
| 5724 } else if (keyword == Keyword.SWITCH) { |
| 5725 return _parseSwitchStatement(); |
| 5726 } else if (keyword == Keyword.THROW) { |
| 5727 return new ExpressionStatement(_parseThrowExpression(), _expect(TokenTyp
e.SEMICOLON)); |
| 5728 } else if (keyword == Keyword.TRY) { |
| 5729 return _parseTryStatement(); |
| 5730 } else if (keyword == Keyword.WHILE) { |
| 5731 return _parseWhileStatement(); |
| 5732 } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) { |
| 5733 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadat
a); |
| 5734 } else if (keyword == Keyword.VOID) { |
| 5735 TypeName returnType = parseReturnType(); |
| 5736 if (_matchesIdentifier() && _peek().matchesAny([ |
| 5737 TokenType.OPEN_PAREN, |
| 5738 TokenType.OPEN_CURLY_BRACKET, |
| 5739 TokenType.FUNCTION])) { |
| 5740 return _parseFunctionDeclarationStatementAfterReturnType(commentAndMet
adata, returnType); |
| 5741 } else { |
| 5742 // |
| 5743 // We have found an error of some kind. Try to recover. |
| 5744 // |
| 5745 if (_matchesIdentifier()) { |
| 5746 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEM
ICOLON])) { |
| 5747 // |
| 5748 // We appear to have a variable declaration with a type of "void". |
| 5749 // |
| 5750 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, [])
; |
| 5751 return _parseVariableDeclarationStatementAfterMetadata(commentAndM
etadata); |
| 5752 } |
| 5753 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 5754 // |
| 5755 // We appear to have found an incomplete statement at the end of a b
lock. Parse it as a |
| 5756 // variable declaration. |
| 5757 // |
| 5758 return _parseVariableDeclarationStatementAfterType(commentAndMetadat
a, null, returnType); |
| 5759 } |
| 5760 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []); |
| 5761 // TODO(brianwilkerson) Recover from this error. |
| 5762 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON)); |
| 5763 } |
| 5764 } else if (keyword == Keyword.CONST) { |
| 5765 if (_peek().matchesAny([ |
| 5766 TokenType.LT, |
| 5767 TokenType.OPEN_CURLY_BRACKET, |
| 5768 TokenType.OPEN_SQUARE_BRACKET, |
| 5769 TokenType.INDEX])) { |
| 5770 return new ExpressionStatement(parseExpression2(), _expect(TokenType.S
EMICOLON)); |
| 5771 } else if (_tokenMatches(_peek(), TokenType.IDENTIFIER)) { |
| 5772 Token afterType = _skipTypeName(_peek()); |
| 5773 if (afterType != null) { |
| 5774 if (_tokenMatches(afterType, TokenType.OPEN_PAREN) || (_tokenMatches
(afterType, TokenType.PERIOD) && _tokenMatches(afterType.next, TokenType.IDENTIF
IER) && _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) { |
| 5775 return new ExpressionStatement(parseExpression2(), _expect(TokenTy
pe.SEMICOLON)); |
| 5776 } |
| 5777 } |
| 5778 } |
| 5779 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadat
a); |
| 5780 } else if (keyword == Keyword.NEW || keyword == Keyword.TRUE || keyword ==
Keyword.FALSE || keyword == Keyword.NULL || keyword == Keyword.SUPER || keyword
== Keyword.THIS) { |
| 5781 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEM
ICOLON)); |
| 5782 } else { |
| 5783 // |
| 5784 // We have found an error of some kind. Try to recover. |
| 5785 // |
| 5786 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []); |
| 5787 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON)); |
| 5788 } |
| 5789 } else if (_inAsync && _matchesString(_YIELD)) { |
| 5790 return _parseYieldStatement(); |
| 5791 } else if (_inAsync && _matchesString(_AWAIT)) { |
| 5792 if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) { |
| 5793 return _parseForStatement(); |
| 5794 } |
| 5795 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEMIC
OLON)); |
| 5796 } else if (_matches(TokenType.SEMICOLON)) { |
| 5797 return _parseEmptyStatement(); |
| 5798 } else if (_isInitializedVariableDeclaration()) { |
| 5799 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadata)
; |
| 5800 } else if (_isFunctionDeclaration()) { |
| 5801 return _parseFunctionDeclarationStatement(); |
| 5802 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
| 5803 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []); |
| 5804 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON)); |
| 5805 } else { |
| 5806 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEMIC
OLON)); |
| 5807 } |
| 5808 } |
| 5809 |
| 5810 /** |
| 5811 * Parse an operator declaration. |
| 5812 * |
| 5813 * <pre> |
| 5814 * operatorDeclaration ::= |
| 5815 * operatorSignature (';' | functionBody) |
| 5816 * |
| 5817 * operatorSignature ::= |
| 5818 * 'external'? returnType? 'operator' operator formalParameterList |
| 5819 * </pre> |
| 5820 * |
| 5821 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 5822 * declaration |
| 5823 * @param externalKeyword the 'external' token |
| 5824 * @param the return type that has already been parsed, or `null` if there was
no return |
| 5825 * type |
| 5826 * @return the operator declaration that was parsed |
| 5827 */ |
| 5828 MethodDeclaration _parseOperator(CommentAndMetadata commentAndMetadata, Token
externalKeyword, TypeName returnType) { |
| 5829 Token operatorKeyword; |
| 5830 if (_matchesKeyword(Keyword.OPERATOR)) { |
| 5831 operatorKeyword = andAdvance; |
| 5832 } else { |
| 5833 _reportErrorForToken(ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentTok
en, []); |
| 5834 operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR); |
| 5835 } |
| 5836 if (!_currentToken.isUserDefinableOperator) { |
| 5837 _reportErrorForCurrentToken(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [
_currentToken.lexeme]); |
| 5838 } |
| 5839 SimpleIdentifier name = new SimpleIdentifier(andAdvance); |
| 5840 if (_matches(TokenType.EQ)) { |
| 5841 Token previous = _currentToken.previous; |
| 5842 if ((_tokenMatches(previous, TokenType.EQ_EQ) || _tokenMatches(previous, T
okenType.BANG_EQ)) && _currentToken.offset == previous.offset + 2) { |
| 5843 _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR, ["${previo
us.lexeme}${_currentToken.lexeme}"]); |
| 5844 _advance(); |
| 5845 } |
| 5846 } |
| 5847 FormalParameterList parameters = parseFormalParameterList(); |
| 5848 _validateFormalParameterList(parameters); |
| 5849 FunctionBody body = _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTIO
N_BODY, false); |
| 5850 if (externalKeyword != null && body is! EmptyFunctionBody) { |
| 5851 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY, [
]); |
| 5852 } |
| 5853 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata.
metadata, externalKeyword, null, returnType, null, operatorKeyword, name, parame
ters, body); |
| 5854 } |
| 5855 |
| 5856 /** |
| 5857 * Parse a return type if one is given, otherwise return `null` without advanc
ing. |
| 5858 * |
| 5859 * @return the return type that was parsed |
| 5860 */ |
| 5861 TypeName _parseOptionalReturnType() { |
| 5862 if (_matchesKeyword(Keyword.VOID)) { |
| 5863 return parseReturnType(); |
| 5864 } else if (_matchesIdentifier() && !_matchesKeyword(Keyword.GET) && !_matche
sKeyword(Keyword.SET) && !_matchesKeyword(Keyword.OPERATOR) && (_tokenMatchesIde
ntifier(_peek()) || _tokenMatches(_peek(), TokenType.LT))) { |
| 5865 return parseReturnType(); |
| 5866 } else if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.PERIOD)
&& _tokenMatchesIdentifier(_peekAt(2)) && (_tokenMatchesIdentifier(_peekAt(3)) |
| _tokenMatches(_peekAt(3), TokenType.LT))) { |
| 5867 return parseReturnType(); |
| 5868 } |
| 5869 return null; |
| 5870 } |
| 5871 |
| 5872 /** |
| 5873 * Parse a part or part-of directive. |
| 5874 * |
| 5875 * <pre> |
| 5876 * partDirective ::= |
| 5877 * metadata 'part' stringLiteral ';' |
| 5878 * |
| 5879 * partOfDirective ::= |
| 5880 * metadata 'part' 'of' identifier ';' |
| 5881 * </pre> |
| 5882 * |
| 5883 * @param commentAndMetadata the metadata to be associated with the directive |
| 5884 * @return the part or part-of directive that was parsed |
| 5885 */ |
| 5886 Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) { |
| 5887 Token partKeyword = _expectKeyword(Keyword.PART); |
| 5888 if (_matchesString(_OF)) { |
| 5889 Token ofKeyword = andAdvance; |
| 5890 LibraryIdentifier libraryName = _parseLibraryName(ParserErrorCode.MISSING_
NAME_IN_PART_OF_DIRECTIVE, ofKeyword); |
| 5891 Token semicolon = _expect(TokenType.SEMICOLON); |
| 5892 return new PartOfDirective(commentAndMetadata.comment, commentAndMetadata.
metadata, partKeyword, ofKeyword, libraryName, semicolon); |
| 5893 } |
| 5894 StringLiteral partUri = parseStringLiteral(); |
| 5895 Token semicolon = _expect(TokenType.SEMICOLON); |
| 5896 return new PartDirective(commentAndMetadata.comment, commentAndMetadata.meta
data, partKeyword, partUri, semicolon); |
| 5897 } |
| 5898 |
| 5899 /** |
| 5900 * Parse a postfix expression. |
| 5901 * |
| 5902 * <pre> |
| 5903 * postfixExpression ::= |
| 5904 * assignableExpression postfixOperator |
| 5905 * | primary selector* |
| 5906 * |
| 5907 * selector ::= |
| 5908 * assignableSelector |
| 5909 * | argumentList |
| 5910 * </pre> |
| 5911 * |
| 5912 * @return the postfix expression that was parsed |
| 5913 */ |
| 5914 Expression _parsePostfixExpression() { |
| 5915 Expression operand = _parseAssignableExpression(true); |
| 5916 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.PERIOD) ||
_matches(TokenType.OPEN_PAREN)) { |
| 5917 do { |
| 5918 if (_matches(TokenType.OPEN_PAREN)) { |
| 5919 ArgumentList argumentList = parseArgumentList(); |
| 5920 if (operand is PropertyAccess) { |
| 5921 PropertyAccess access = operand as PropertyAccess; |
| 5922 operand = new MethodInvocation(access.target, access.operator, acces
s.propertyName, argumentList); |
| 5923 } else { |
| 5924 operand = new FunctionExpressionInvocation(operand, argumentList); |
| 5925 } |
| 5926 } else { |
| 5927 operand = _parseAssignableSelector(operand, true); |
| 5928 } |
| 5929 } while (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.PER
IOD) || _matches(TokenType.OPEN_PAREN)); |
| 5930 return operand; |
| 5931 } |
| 5932 if (!_currentToken.type.isIncrementOperator) { |
| 5933 return operand; |
| 5934 } |
| 5935 _ensureAssignable(operand); |
| 5936 Token operator = andAdvance; |
| 5937 return new PostfixExpression(operand, operator); |
| 5938 } |
| 5939 |
| 5940 /** |
| 5941 * Parse a primary expression. |
| 5942 * |
| 5943 * <pre> |
| 5944 * primary ::= |
| 5945 * thisExpression |
| 5946 * | 'super' assignableSelector |
| 5947 * | functionExpression |
| 5948 * | literal |
| 5949 * | identifier |
| 5950 * | newExpression |
| 5951 * | constObjectExpression |
| 5952 * | '(' expression ')' |
| 5953 * | argumentDefinitionTest |
| 5954 * |
| 5955 * literal ::= |
| 5956 * nullLiteral |
| 5957 * | booleanLiteral |
| 5958 * | numericLiteral |
| 5959 * | stringLiteral |
| 5960 * | symbolLiteral |
| 5961 * | mapLiteral |
| 5962 * | listLiteral |
| 5963 * </pre> |
| 5964 * |
| 5965 * @return the primary expression that was parsed |
| 5966 */ |
| 5967 Expression _parsePrimaryExpression() { |
| 5968 if (_matchesKeyword(Keyword.THIS)) { |
| 5969 return new ThisExpression(andAdvance); |
| 5970 } else if (_matchesKeyword(Keyword.SUPER)) { |
| 5971 return _parseAssignableSelector(new SuperExpression(andAdvance), false); |
| 5972 } else if (_matchesKeyword(Keyword.NULL)) { |
| 5973 return new NullLiteral(andAdvance); |
| 5974 } else if (_matchesKeyword(Keyword.FALSE)) { |
| 5975 return new BooleanLiteral(andAdvance, false); |
| 5976 } else if (_matchesKeyword(Keyword.TRUE)) { |
| 5977 return new BooleanLiteral(andAdvance, true); |
| 5978 } else if (_matches(TokenType.DOUBLE)) { |
| 5979 Token token = andAdvance; |
| 5980 double value = 0.0; |
| 5981 try { |
| 5982 value = double.parse(token.lexeme); |
| 5983 } on FormatException catch (exception) { |
| 5984 } |
| 5985 return new DoubleLiteral(token, value); |
| 5986 } else if (_matches(TokenType.HEXADECIMAL)) { |
| 5987 Token token = andAdvance; |
| 5988 int value = null; |
| 5989 try { |
| 5990 value = int.parse(token.lexeme.substring(2), radix: 16); |
| 5991 } on FormatException catch (exception) { |
| 5992 } |
| 5993 return new IntegerLiteral(token, value); |
| 5994 } else if (_matches(TokenType.INT)) { |
| 5995 Token token = andAdvance; |
| 5996 int value = null; |
| 5997 try { |
| 5998 value = int.parse(token.lexeme); |
| 5999 } on FormatException catch (exception) { |
| 6000 } |
| 6001 return new IntegerLiteral(token, value); |
| 6002 } else if (_matches(TokenType.STRING)) { |
| 6003 return parseStringLiteral(); |
| 6004 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 6005 return _parseMapLiteral(null, null); |
| 6006 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.IND
EX)) { |
| 6007 return _parseListLiteral(null, null); |
| 6008 } else if (_matchesIdentifier()) { |
| 6009 // TODO(brianwilkerson) The code below was an attempt to recover from an e
rror case, but it |
| 6010 // needs to be applied as a recovery only after we know that parsing it as
an identifier |
| 6011 // doesn't work. Leaving the code as a reminder of how to recover. |
| 6012 // if (isFunctionExpression(peek())) { |
| 6013 // // |
| 6014 // // Function expressions were allowed to have names at one point,
but this is now illegal. |
| 6015 // // |
| 6016 // reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdv
ance()); |
| 6017 // return parseFunctionExpression(); |
| 6018 // } |
| 6019 return parsePrefixedIdentifier(); |
| 6020 } else if (_matchesKeyword(Keyword.NEW)) { |
| 6021 return _parseNewExpression(); |
| 6022 } else if (_matchesKeyword(Keyword.CONST)) { |
| 6023 return _parseConstExpression(); |
| 6024 } else if (_matches(TokenType.OPEN_PAREN)) { |
| 6025 if (_isFunctionExpression(_currentToken)) { |
| 6026 return parseFunctionExpression(); |
| 6027 } |
| 6028 Token leftParenthesis = andAdvance; |
| 6029 bool wasInInitializer = _inInitializer; |
| 6030 _inInitializer = false; |
| 6031 try { |
| 6032 Expression expression = parseExpression2(); |
| 6033 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 6034 return new ParenthesizedExpression(leftParenthesis, expression, rightPar
enthesis); |
| 6035 } finally { |
| 6036 _inInitializer = wasInInitializer; |
| 6037 } |
| 6038 } else if (_matches(TokenType.LT)) { |
| 6039 return _parseListOrMapLiteral(null); |
| 6040 } else if (_matches(TokenType.QUESTION) && _tokenMatches(_peek(), TokenType.
IDENTIFIER)) { |
| 6041 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TOKEN, [_currentTok
en.lexeme]); |
| 6042 _advance(); |
| 6043 return _parsePrimaryExpression(); |
| 6044 } else if (_matchesKeyword(Keyword.VOID)) { |
| 6045 // |
| 6046 // Recover from having a return type of "void" where a return type is not
expected. |
| 6047 // |
| 6048 // TODO(brianwilkerson) Improve this error message. |
| 6049 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TOKEN, [_currentTok
en.lexeme]); |
| 6050 _advance(); |
| 6051 return _parsePrimaryExpression(); |
| 6052 } else if (_matches(TokenType.HASH)) { |
| 6053 return _parseSymbolLiteral(); |
| 6054 } else { |
| 6055 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 6056 return _createSyntheticIdentifier(); |
| 6057 } |
| 6058 } |
| 6059 |
| 6060 /** |
| 6061 * Parse a redirecting constructor invocation. |
| 6062 * |
| 6063 * <pre> |
| 6064 * redirectingConstructorInvocation ::= |
| 6065 * 'this' ('.' identifier)? arguments |
| 6066 * </pre> |
| 6067 * |
| 6068 * @return the redirecting constructor invocation that was parsed |
| 6069 */ |
| 6070 RedirectingConstructorInvocation _parseRedirectingConstructorInvocation() { |
| 6071 Token keyword = _expectKeyword(Keyword.THIS); |
| 6072 Token period = null; |
| 6073 SimpleIdentifier constructorName = null; |
| 6074 if (_matches(TokenType.PERIOD)) { |
| 6075 period = andAdvance; |
| 6076 constructorName = parseSimpleIdentifier(); |
| 6077 } |
| 6078 ArgumentList argumentList = parseArgumentList(); |
| 6079 return new RedirectingConstructorInvocation(keyword, period, constructorName
, argumentList); |
| 6080 } |
| 6081 |
| 6082 /** |
| 6083 * Parse a relational expression. |
| 6084 * |
| 6085 * <pre> |
| 6086 * relationalExpression ::= |
| 6087 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bi
twiseOrExpression)? |
| 6088 * | 'super' relationalOperator bitwiseOrExpression |
| 6089 * </pre> |
| 6090 * |
| 6091 * @return the relational expression that was parsed |
| 6092 */ |
| 6093 Expression _parseRelationalExpression() { |
| 6094 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isRelationalOp
erator) { |
| 6095 Expression expression = new SuperExpression(andAdvance); |
| 6096 Token operator = andAdvance; |
| 6097 expression = new BinaryExpression(expression, operator, parseBitwiseOrExpr
ession()); |
| 6098 return expression; |
| 6099 } |
| 6100 Expression expression = parseBitwiseOrExpression(); |
| 6101 if (_matchesKeyword(Keyword.AS)) { |
| 6102 Token asOperator = andAdvance; |
| 6103 expression = new AsExpression(expression, asOperator, parseTypeName()); |
| 6104 } else if (_matchesKeyword(Keyword.IS)) { |
| 6105 Token isOperator = andAdvance; |
| 6106 Token notOperator = null; |
| 6107 if (_matches(TokenType.BANG)) { |
| 6108 notOperator = andAdvance; |
| 6109 } |
| 6110 expression = new IsExpression(expression, isOperator, notOperator, parseTy
peName()); |
| 6111 } else if (_currentToken.type.isRelationalOperator) { |
| 6112 Token operator = andAdvance; |
| 6113 expression = new BinaryExpression(expression, operator, parseBitwiseOrExpr
ession()); |
| 6114 } |
| 6115 return expression; |
| 6116 } |
| 6117 |
| 6118 /** |
| 6119 * Parse a rethrow expression. |
| 6120 * |
| 6121 * <pre> |
| 6122 * rethrowExpression ::= |
| 6123 * 'rethrow' |
| 6124 * </pre> |
| 6125 * |
| 6126 * @return the rethrow expression that was parsed |
| 6127 */ |
| 6128 Expression _parseRethrowExpression() => new RethrowExpression(_expectKeyword(K
eyword.RETHROW)); |
| 6129 |
| 6130 /** |
| 6131 * Parse a return statement. |
| 6132 * |
| 6133 * <pre> |
| 6134 * returnStatement ::= |
| 6135 * 'return' expression? ';' |
| 6136 * </pre> |
| 6137 * |
| 6138 * @return the return statement that was parsed |
| 6139 */ |
| 6140 Statement _parseReturnStatement() { |
| 6141 Token returnKeyword = _expectKeyword(Keyword.RETURN); |
| 6142 if (_matches(TokenType.SEMICOLON)) { |
| 6143 return new ReturnStatement(returnKeyword, null, andAdvance); |
| 6144 } |
| 6145 Expression expression = parseExpression2(); |
| 6146 Token semicolon = _expect(TokenType.SEMICOLON); |
| 6147 return new ReturnStatement(returnKeyword, expression, semicolon); |
| 6148 } |
| 6149 |
| 6150 /** |
| 6151 * Parse a setter. |
| 6152 * |
| 6153 * <pre> |
| 6154 * setter ::= |
| 6155 * setterSignature functionBody? |
| 6156 * |
| 6157 * setterSignature ::= |
| 6158 * 'external'? 'static'? returnType? 'set' identifier formalParameterList |
| 6159 * </pre> |
| 6160 * |
| 6161 * @param commentAndMetadata the documentation comment and metadata to be asso
ciated with the |
| 6162 * declaration |
| 6163 * @param externalKeyword the 'external' token |
| 6164 * @param staticKeyword the static keyword, or `null` if the setter is not sta
tic |
| 6165 * @param the return type that has already been parsed, or `null` if there was
no return |
| 6166 * type |
| 6167 * @return the setter that was parsed |
| 6168 */ |
| 6169 MethodDeclaration _parseSetter(CommentAndMetadata commentAndMetadata, Token ex
ternalKeyword, Token staticKeyword, TypeName returnType) { |
| 6170 Token propertyKeyword = _expectKeyword(Keyword.SET); |
| 6171 SimpleIdentifier name = parseSimpleIdentifier(); |
| 6172 FormalParameterList parameters = parseFormalParameterList(); |
| 6173 _validateFormalParameterList(parameters); |
| 6174 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw
ord == null, ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false); |
| 6175 if (externalKeyword != null && body is! EmptyFunctionBody) { |
| 6176 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY, [])
; |
| 6177 } |
| 6178 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata.
metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, nam
e, parameters, body); |
| 6179 } |
| 6180 |
| 6181 /** |
| 6182 * Parse a shift expression. |
| 6183 * |
| 6184 * <pre> |
| 6185 * shiftExpression ::= |
| 6186 * additiveExpression (shiftOperator additiveExpression)* |
| 6187 * | 'super' (shiftOperator additiveExpression)+ |
| 6188 * </pre> |
| 6189 * |
| 6190 * @return the shift expression that was parsed |
| 6191 */ |
| 6192 Expression _parseShiftExpression() { |
| 6193 Expression expression; |
| 6194 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isShiftOperato
r) { |
| 6195 expression = new SuperExpression(andAdvance); |
| 6196 } else { |
| 6197 expression = _parseAdditiveExpression(); |
| 6198 } |
| 6199 while (_currentToken.type.isShiftOperator) { |
| 6200 Token operator = andAdvance; |
| 6201 expression = new BinaryExpression(expression, operator, _parseAdditiveExpr
ession()); |
| 6202 } |
| 6203 return expression; |
| 6204 } |
| 6205 |
| 6206 /** |
| 6207 * Parse a list of statements within a switch statement. |
| 6208 * |
| 6209 * <pre> |
| 6210 * statements ::= |
| 6211 * statement* |
| 6212 * </pre> |
| 6213 * |
| 6214 * @return the statements that were parsed |
| 6215 */ |
| 6216 List<Statement> _parseStatementList() { |
| 6217 List<Statement> statements = new List<Statement>(); |
| 6218 Token statementStart = _currentToken; |
| 6219 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)
&& !_isSwitchMember()) { |
| 6220 statements.add(parseStatement2()); |
| 6221 if (identical(_currentToken, statementStart)) { |
| 6222 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_
currentToken.lexeme]); |
| 6223 _advance(); |
| 6224 } |
| 6225 statementStart = _currentToken; |
| 6226 } |
| 6227 return statements; |
| 6228 } |
| 6229 |
| 6230 /** |
| 6231 * Parse a string literal that contains interpolations. |
| 6232 * |
| 6233 * @return the string literal that was parsed |
| 6234 */ |
| 6235 StringInterpolation _parseStringInterpolation(Token string) { |
| 6236 List<InterpolationElement> elements = new List<InterpolationElement>(); |
| 6237 bool hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _match
es(TokenType.STRING_INTERPOLATION_IDENTIFIER); |
| 6238 elements.add(new InterpolationString(string, _computeStringValue(string.lexe
me, true, !hasMore))); |
| 6239 while (hasMore) { |
| 6240 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION)) { |
| 6241 Token openToken = andAdvance; |
| 6242 bool wasInInitializer = _inInitializer; |
| 6243 _inInitializer = false; |
| 6244 try { |
| 6245 Expression expression = parseExpression2(); |
| 6246 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 6247 elements.add(new InterpolationExpression(openToken, expression, rightB
racket)); |
| 6248 } finally { |
| 6249 _inInitializer = wasInInitializer; |
| 6250 } |
| 6251 } else { |
| 6252 Token openToken = andAdvance; |
| 6253 Expression expression = null; |
| 6254 if (_matchesKeyword(Keyword.THIS)) { |
| 6255 expression = new ThisExpression(andAdvance); |
| 6256 } else { |
| 6257 expression = parseSimpleIdentifier(); |
| 6258 } |
| 6259 elements.add(new InterpolationExpression(openToken, expression, null)); |
| 6260 } |
| 6261 if (_matches(TokenType.STRING)) { |
| 6262 string = andAdvance; |
| 6263 hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _matche
s(TokenType.STRING_INTERPOLATION_IDENTIFIER); |
| 6264 elements.add(new InterpolationString(string, _computeStringValue(string.
lexeme, false, !hasMore))); |
| 6265 } else { |
| 6266 hasMore = false; |
| 6267 } |
| 6268 } |
| 6269 return new StringInterpolation(elements); |
| 6270 } |
| 6271 |
| 6272 /** |
| 6273 * Parse a super constructor invocation. |
| 6274 * |
| 6275 * <pre> |
| 6276 * superConstructorInvocation ::= |
| 6277 * 'super' ('.' identifier)? arguments |
| 6278 * </pre> |
| 6279 * |
| 6280 * @return the super constructor invocation that was parsed |
| 6281 */ |
| 6282 SuperConstructorInvocation _parseSuperConstructorInvocation() { |
| 6283 Token keyword = _expectKeyword(Keyword.SUPER); |
| 6284 Token period = null; |
| 6285 SimpleIdentifier constructorName = null; |
| 6286 if (_matches(TokenType.PERIOD)) { |
| 6287 period = andAdvance; |
| 6288 constructorName = parseSimpleIdentifier(); |
| 6289 } |
| 6290 ArgumentList argumentList = parseArgumentList(); |
| 6291 return new SuperConstructorInvocation(keyword, period, constructorName, argu
mentList); |
| 6292 } |
| 6293 |
| 6294 /** |
| 6295 * Parse a switch statement. |
| 6296 * |
| 6297 * <pre> |
| 6298 * switchStatement ::= |
| 6299 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}' |
| 6300 * |
| 6301 * switchCase ::= |
| 6302 * label* ('case' expression ':') statements |
| 6303 * |
| 6304 * defaultCase ::= |
| 6305 * label* 'default' ':' statements |
| 6306 * </pre> |
| 6307 * |
| 6308 * @return the switch statement that was parsed |
| 6309 */ |
| 6310 SwitchStatement _parseSwitchStatement() { |
| 6311 bool wasInSwitch = _inSwitch; |
| 6312 _inSwitch = true; |
| 6313 try { |
| 6314 HashSet<String> definedLabels = new HashSet<String>(); |
| 6315 Token keyword = _expectKeyword(Keyword.SWITCH); |
| 6316 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 6317 Expression expression = parseExpression2(); |
| 6318 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 6319 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); |
| 6320 Token defaultKeyword = null; |
| 6321 List<SwitchMember> members = new List<SwitchMember>(); |
| 6322 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET
)) { |
| 6323 List<Label> labels = new List<Label>(); |
| 6324 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON))
{ |
| 6325 SimpleIdentifier identifier = parseSimpleIdentifier(); |
| 6326 String label = identifier.token.lexeme; |
| 6327 if (definedLabels.contains(label)) { |
| 6328 _reportErrorForToken(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATE
MENT, identifier.token, [label]); |
| 6329 } else { |
| 6330 definedLabels.add(label); |
| 6331 } |
| 6332 Token colon = _expect(TokenType.COLON); |
| 6333 labels.add(new Label(identifier, colon)); |
| 6334 } |
| 6335 if (_matchesKeyword(Keyword.CASE)) { |
| 6336 Token caseKeyword = andAdvance; |
| 6337 Expression caseExpression = parseExpression2(); |
| 6338 Token colon = _expect(TokenType.COLON); |
| 6339 members.add(new SwitchCase(labels, caseKeyword, caseExpression, colon,
_parseStatementList())); |
| 6340 if (defaultKeyword != null) { |
| 6341 _reportErrorForToken(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_C
ASE, caseKeyword, []); |
| 6342 } |
| 6343 } else if (_matchesKeyword(Keyword.DEFAULT)) { |
| 6344 if (defaultKeyword != null) { |
| 6345 _reportErrorForToken(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CAS
ES, _peek(), []); |
| 6346 } |
| 6347 defaultKeyword = andAdvance; |
| 6348 Token colon = _expect(TokenType.COLON); |
| 6349 members.add(new SwitchDefault(labels, defaultKeyword, colon, _parseSta
tementList())); |
| 6350 } else { |
| 6351 // We need to advance, otherwise we could end up in an infinite loop,
but this could be a |
| 6352 // lot smarter about recovering from the error. |
| 6353 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
[]); |
| 6354 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRA
CKET) && !_matchesKeyword(Keyword.CASE) && !_matchesKeyword(Keyword.DEFAULT)) { |
| 6355 _advance(); |
| 6356 } |
| 6357 } |
| 6358 } |
| 6359 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); |
| 6360 return new SwitchStatement(keyword, leftParenthesis, expression, rightPare
nthesis, leftBracket, members, rightBracket); |
| 6361 } finally { |
| 6362 _inSwitch = wasInSwitch; |
| 6363 } |
| 6364 } |
| 6365 |
| 6366 /** |
| 6367 * Parse a symbol literal. |
| 6368 * |
| 6369 * <pre> |
| 6370 * symbolLiteral ::= |
| 6371 * '#' identifier ('.' identifier)* |
| 6372 * </pre> |
| 6373 * |
| 6374 * @return the symbol literal that was parsed |
| 6375 */ |
| 6376 SymbolLiteral _parseSymbolLiteral() { |
| 6377 Token poundSign = andAdvance; |
| 6378 List<Token> components = new List<Token>(); |
| 6379 if (_matchesIdentifier()) { |
| 6380 components.add(andAdvance); |
| 6381 while (_matches(TokenType.PERIOD)) { |
| 6382 _advance(); |
| 6383 if (_matchesIdentifier()) { |
| 6384 components.add(andAdvance); |
| 6385 } else { |
| 6386 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 6387 components.add(_createSyntheticToken(TokenType.IDENTIFIER)); |
| 6388 break; |
| 6389 } |
| 6390 } |
| 6391 } else if (_currentToken.isOperator) { |
| 6392 components.add(andAdvance); |
| 6393 } else if (_tokenMatchesKeyword(_currentToken, Keyword.VOID)) { |
| 6394 components.add(andAdvance); |
| 6395 } else { |
| 6396 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 6397 components.add(_createSyntheticToken(TokenType.IDENTIFIER)); |
| 6398 } |
| 6399 return new SymbolLiteral(poundSign, new List.from(components)); |
| 6400 } |
| 6401 |
| 6402 /** |
| 6403 * Parse a throw expression. |
| 6404 * |
| 6405 * <pre> |
| 6406 * throwExpression ::= |
| 6407 * 'throw' expression |
| 6408 * </pre> |
| 6409 * |
| 6410 * @return the throw expression that was parsed |
| 6411 */ |
| 6412 Expression _parseThrowExpression() { |
| 6413 Token keyword = _expectKeyword(Keyword.THROW); |
| 6414 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) { |
| 6415 _reportErrorForToken(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _current
Token, []); |
| 6416 return new ThrowExpression(keyword, _createSyntheticIdentifier()); |
| 6417 } |
| 6418 Expression expression = parseExpression2(); |
| 6419 return new ThrowExpression(keyword, expression); |
| 6420 } |
| 6421 |
| 6422 /** |
| 6423 * Parse a throw expression. |
| 6424 * |
| 6425 * <pre> |
| 6426 * throwExpressionWithoutCascade ::= |
| 6427 * 'throw' expressionWithoutCascade |
| 6428 * </pre> |
| 6429 * |
| 6430 * @return the throw expression that was parsed |
| 6431 */ |
| 6432 Expression _parseThrowExpressionWithoutCascade() { |
| 6433 Token keyword = _expectKeyword(Keyword.THROW); |
| 6434 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) { |
| 6435 _reportErrorForToken(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _current
Token, []); |
| 6436 return new ThrowExpression(keyword, _createSyntheticIdentifier()); |
| 6437 } |
| 6438 Expression expression = parseExpressionWithoutCascade(); |
| 6439 return new ThrowExpression(keyword, expression); |
| 6440 } |
| 6441 |
| 6442 /** |
| 6443 * Parse a try statement. |
| 6444 * |
| 6445 * <pre> |
| 6446 * tryStatement ::= |
| 6447 * 'try' block (onPart+ finallyPart? | finallyPart) |
| 6448 * |
| 6449 * onPart ::= |
| 6450 * catchPart block |
| 6451 * | 'on' type catchPart? block |
| 6452 * |
| 6453 * catchPart ::= |
| 6454 * 'catch' '(' identifier (',' identifier)? ')' |
| 6455 * |
| 6456 * finallyPart ::= |
| 6457 * 'finally' block |
| 6458 * </pre> |
| 6459 * |
| 6460 * @return the try statement that was parsed |
| 6461 */ |
| 6462 Statement _parseTryStatement() { |
| 6463 Token tryKeyword = _expectKeyword(Keyword.TRY); |
| 6464 Block body = parseBlock(); |
| 6465 List<CatchClause> catchClauses = new List<CatchClause>(); |
| 6466 Block finallyClause = null; |
| 6467 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) { |
| 6468 Token onKeyword = null; |
| 6469 TypeName exceptionType = null; |
| 6470 if (_matchesString(_ON)) { |
| 6471 onKeyword = andAdvance; |
| 6472 exceptionType = parseTypeName(); |
| 6473 } |
| 6474 Token catchKeyword = null; |
| 6475 Token leftParenthesis = null; |
| 6476 SimpleIdentifier exceptionParameter = null; |
| 6477 Token comma = null; |
| 6478 SimpleIdentifier stackTraceParameter = null; |
| 6479 Token rightParenthesis = null; |
| 6480 if (_matchesKeyword(Keyword.CATCH)) { |
| 6481 catchKeyword = andAdvance; |
| 6482 leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 6483 exceptionParameter = parseSimpleIdentifier(); |
| 6484 if (_matches(TokenType.COMMA)) { |
| 6485 comma = andAdvance; |
| 6486 stackTraceParameter = parseSimpleIdentifier(); |
| 6487 } |
| 6488 rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 6489 } |
| 6490 Block catchBody = parseBlock(); |
| 6491 catchClauses.add(new CatchClause(onKeyword, exceptionType, catchKeyword, l
eftParenthesis, exceptionParameter, comma, stackTraceParameter, rightParenthesis
, catchBody)); |
| 6492 } |
| 6493 Token finallyKeyword = null; |
| 6494 if (_matchesKeyword(Keyword.FINALLY)) { |
| 6495 finallyKeyword = andAdvance; |
| 6496 finallyClause = parseBlock(); |
| 6497 } else { |
| 6498 if (catchClauses.isEmpty) { |
| 6499 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY, []
); |
| 6500 } |
| 6501 } |
| 6502 return new TryStatement(tryKeyword, body, catchClauses, finallyKeyword, fina
llyClause); |
| 6503 } |
| 6504 |
| 6505 /** |
| 6506 * Parse a type alias. |
| 6507 * |
| 6508 * <pre> |
| 6509 * typeAlias ::= |
| 6510 * 'typedef' typeAliasBody |
| 6511 * |
| 6512 * typeAliasBody ::= |
| 6513 * classTypeAlias |
| 6514 * | functionTypeAlias |
| 6515 * |
| 6516 * classTypeAlias ::= |
| 6517 * identifier typeParameters? '=' 'abstract'? mixinApplication |
| 6518 * |
| 6519 * mixinApplication ::= |
| 6520 * qualified withClause implementsClause? ';' |
| 6521 * |
| 6522 * functionTypeAlias ::= |
| 6523 * functionPrefix typeParameterList? formalParameterList ';' |
| 6524 * |
| 6525 * functionPrefix ::= |
| 6526 * returnType? name |
| 6527 * </pre> |
| 6528 * |
| 6529 * @param commentAndMetadata the metadata to be associated with the member |
| 6530 * @return the type alias that was parsed |
| 6531 */ |
| 6532 TypeAlias _parseTypeAlias(CommentAndMetadata commentAndMetadata) { |
| 6533 Token keyword = _expectKeyword(Keyword.TYPEDEF); |
| 6534 if (_matchesIdentifier()) { |
| 6535 Token next = _peek(); |
| 6536 if (_tokenMatches(next, TokenType.LT)) { |
| 6537 next = _skipTypeParameterList(next); |
| 6538 if (next != null && _tokenMatches(next, TokenType.EQ)) { |
| 6539 TypeAlias typeAlias = _parseClassTypeAlias(commentAndMetadata, null, k
eyword); |
| 6540 _reportErrorForToken(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyw
ord, []); |
| 6541 return typeAlias; |
| 6542 } |
| 6543 } else if (_tokenMatches(next, TokenType.EQ)) { |
| 6544 TypeAlias typeAlias = _parseClassTypeAlias(commentAndMetadata, null, key
word); |
| 6545 _reportErrorForToken(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keywor
d, []); |
| 6546 return typeAlias; |
| 6547 } |
| 6548 } |
| 6549 return _parseFunctionTypeAlias(commentAndMetadata, keyword); |
| 6550 } |
| 6551 |
| 6552 /** |
| 6553 * Parse a unary expression. |
| 6554 * |
| 6555 * <pre> |
| 6556 * unaryExpression ::= |
| 6557 * prefixOperator unaryExpression |
| 6558 * | awaitExpression |
| 6559 * | postfixExpression |
| 6560 * | unaryOperator 'super' |
| 6561 * | '-' 'super' |
| 6562 * | incrementOperator assignableExpression |
| 6563 * </pre> |
| 6564 * |
| 6565 * @return the unary expression that was parsed |
| 6566 */ |
| 6567 Expression _parseUnaryExpression() { |
| 6568 if (_matches(TokenType.MINUS) || _matches(TokenType.BANG) || _matches(TokenT
ype.TILDE)) { |
| 6569 Token operator = andAdvance; |
| 6570 if (_matchesKeyword(Keyword.SUPER)) { |
| 6571 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) || _tokenMatch
es(_peek(), TokenType.PERIOD)) { |
| 6572 // "prefixOperator unaryExpression" |
| 6573 // --> "prefixOperator postfixExpression" |
| 6574 // --> "prefixOperator primary selector*" |
| 6575 // --> "prefixOperator 'super' assignableSelector selector*" |
| 6576 return new PrefixExpression(operator, _parseUnaryExpression()); |
| 6577 } |
| 6578 return new PrefixExpression(operator, new SuperExpression(andAdvance)); |
| 6579 } |
| 6580 return new PrefixExpression(operator, _parseUnaryExpression()); |
| 6581 } else if (_currentToken.type.isIncrementOperator) { |
| 6582 Token operator = andAdvance; |
| 6583 if (_matchesKeyword(Keyword.SUPER)) { |
| 6584 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) || _tokenMatch
es(_peek(), TokenType.PERIOD)) { |
| 6585 // --> "prefixOperator 'super' assignableSelector selector*" |
| 6586 return new PrefixExpression(operator, _parseUnaryExpression()); |
| 6587 } |
| 6588 // |
| 6589 // Even though it is not valid to use an incrementing operator ('++' or
'--') before 'super', |
| 6590 // we can (and therefore must) interpret "--super" as semantically equiv
alent to "-(-super)". |
| 6591 // Unfortunately, we cannot do the same for "++super" because "+super" i
s also not valid. |
| 6592 // |
| 6593 if (operator.type == TokenType.MINUS_MINUS) { |
| 6594 int offset = operator.offset; |
| 6595 Token firstOperator = new Token(TokenType.MINUS, offset); |
| 6596 Token secondOperator = new Token(TokenType.MINUS, offset + 1); |
| 6597 secondOperator.setNext(_currentToken); |
| 6598 firstOperator.setNext(secondOperator); |
| 6599 operator.previous.setNext(firstOperator); |
| 6600 return new PrefixExpression(firstOperator, new PrefixExpression(second
Operator, new SuperExpression(andAdvance))); |
| 6601 } else { |
| 6602 // Invalid operator before 'super' |
| 6603 _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER
, [operator.lexeme]); |
| 6604 return new PrefixExpression(operator, new SuperExpression(andAdvance))
; |
| 6605 } |
| 6606 } |
| 6607 return new PrefixExpression(operator, _parseAssignableExpression(false)); |
| 6608 } else if (_matches(TokenType.PLUS)) { |
| 6609 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []); |
| 6610 return _createSyntheticIdentifier(); |
| 6611 } else if (_inAsync && _matchesString(_AWAIT)) { |
| 6612 return _parseAwaitExpression(); |
| 6613 } |
| 6614 return _parsePostfixExpression(); |
| 6615 } |
| 6616 |
| 6617 /** |
| 6618 * Parse a variable declaration. |
| 6619 * |
| 6620 * <pre> |
| 6621 * variableDeclaration ::= |
| 6622 * identifier ('=' expression)? |
| 6623 * </pre> |
| 6624 * |
| 6625 * @return the variable declaration that was parsed |
| 6626 */ |
| 6627 VariableDeclaration _parseVariableDeclaration() { |
| 6628 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 6629 SimpleIdentifier name = parseSimpleIdentifier(); |
| 6630 Token equals = null; |
| 6631 Expression initializer = null; |
| 6632 if (_matches(TokenType.EQ)) { |
| 6633 equals = andAdvance; |
| 6634 initializer = parseExpression2(); |
| 6635 } |
| 6636 return new VariableDeclaration(commentAndMetadata.comment, commentAndMetadat
a.metadata, name, equals, initializer); |
| 6637 } |
| 6638 |
| 6639 /** |
| 6640 * Parse a variable declaration list. |
| 6641 * |
| 6642 * <pre> |
| 6643 * variableDeclarationList ::= |
| 6644 * finalConstVarOrType variableDeclaration (',' variableDeclaration)* |
| 6645 * </pre> |
| 6646 * |
| 6647 * @param commentAndMetadata the metadata to be associated with the variable d
eclaration list |
| 6648 * @return the variable declaration list that was parsed |
| 6649 */ |
| 6650 VariableDeclarationList _parseVariableDeclarationListAfterMetadata(CommentAndM
etadata commentAndMetadata) { |
| 6651 FinalConstVarOrType holder = _parseFinalConstVarOrType(false); |
| 6652 return _parseVariableDeclarationListAfterType(commentAndMetadata, holder.key
word, holder.type); |
| 6653 } |
| 6654 |
| 6655 /** |
| 6656 * Parse a variable declaration list. |
| 6657 * |
| 6658 * <pre> |
| 6659 * variableDeclarationList ::= |
| 6660 * finalConstVarOrType variableDeclaration (',' variableDeclaration)* |
| 6661 * </pre> |
| 6662 * |
| 6663 * @param commentAndMetadata the metadata to be associated with the variable d
eclaration list, or |
| 6664 * `null` if there is no attempt at parsing the comment and metadata |
| 6665 * @param keyword the token representing the 'final', 'const' or 'var' keyword
, or `null` if |
| 6666 * there is no keyword |
| 6667 * @param type the type of the variables in the list |
| 6668 * @return the variable declaration list that was parsed |
| 6669 */ |
| 6670 VariableDeclarationList _parseVariableDeclarationListAfterType(CommentAndMetad
ata commentAndMetadata, Token keyword, TypeName type) { |
| 6671 if (type != null && keyword != null && _tokenMatchesKeyword(keyword, Keyword
.VAR)) { |
| 6672 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword, []); |
| 6673 } |
| 6674 List<VariableDeclaration> variables = new List<VariableDeclaration>(); |
| 6675 variables.add(_parseVariableDeclaration()); |
| 6676 while (_matches(TokenType.COMMA)) { |
| 6677 _advance(); |
| 6678 variables.add(_parseVariableDeclaration()); |
| 6679 } |
| 6680 return new VariableDeclarationList(commentAndMetadata != null ? commentAndMe
tadata.comment : null, commentAndMetadata != null ? commentAndMetadata.metadata
: null, keyword, type, variables); |
| 6681 } |
| 6682 |
| 6683 /** |
| 6684 * Parse a variable declaration statement. |
| 6685 * |
| 6686 * <pre> |
| 6687 * variableDeclarationStatement ::= |
| 6688 * variableDeclarationList ';' |
| 6689 * </pre> |
| 6690 * |
| 6691 * @param commentAndMetadata the metadata to be associated with the variable d
eclaration |
| 6692 * statement, or `null` if there is no attempt at parsing the comment
and metadata |
| 6693 * @return the variable declaration statement that was parsed |
| 6694 */ |
| 6695 VariableDeclarationStatement _parseVariableDeclarationStatementAfterMetadata(C
ommentAndMetadata commentAndMetadata) { |
| 6696 // Token startToken = currentToken; |
| 6697 VariableDeclarationList variableList = _parseVariableDeclarationListAfterMet
adata(commentAndMetadata); |
| 6698 // if (!matches(TokenType.SEMICOLON)) { |
| 6699 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken
.getNext())) { |
| 6700 // // TODO(brianwilkerson) This appears to be of the form "var type v
ariable". We should do |
| 6701 // // a better job of recovering in this case. |
| 6702 // } |
| 6703 // } |
| 6704 Token semicolon = _expect(TokenType.SEMICOLON); |
| 6705 return new VariableDeclarationStatement(variableList, semicolon); |
| 6706 } |
| 6707 |
| 6708 /** |
| 6709 * Parse a variable declaration statement. |
| 6710 * |
| 6711 * <pre> |
| 6712 * variableDeclarationStatement ::= |
| 6713 * variableDeclarationList ';' |
| 6714 * </pre> |
| 6715 * |
| 6716 * @param commentAndMetadata the metadata to be associated with the variable d
eclaration |
| 6717 * statement, or `null` if there is no attempt at parsing the comment
and metadata |
| 6718 * @param keyword the token representing the 'final', 'const' or 'var' keyword
, or `null` if |
| 6719 * there is no keyword |
| 6720 * @param type the type of the variables in the list |
| 6721 * @return the variable declaration statement that was parsed |
| 6722 */ |
| 6723 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(Comme
ntAndMetadata commentAndMetadata, Token keyword, TypeName type) { |
| 6724 VariableDeclarationList variableList = _parseVariableDeclarationListAfterTyp
e(commentAndMetadata, keyword, type); |
| 6725 Token semicolon = _expect(TokenType.SEMICOLON); |
| 6726 return new VariableDeclarationStatement(variableList, semicolon); |
| 6727 } |
| 6728 |
| 6729 /** |
| 6730 * Parse a while statement. |
| 6731 * |
| 6732 * <pre> |
| 6733 * whileStatement ::= |
| 6734 * 'while' '(' expression ')' statement |
| 6735 * </pre> |
| 6736 * |
| 6737 * @return the while statement that was parsed |
| 6738 */ |
| 6739 Statement _parseWhileStatement() { |
| 6740 bool wasInLoop = _inLoop; |
| 6741 _inLoop = true; |
| 6742 try { |
| 6743 Token keyword = _expectKeyword(Keyword.WHILE); |
| 6744 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); |
| 6745 Expression condition = parseExpression2(); |
| 6746 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); |
| 6747 Statement body = parseStatement2(); |
| 6748 return new WhileStatement(keyword, leftParenthesis, condition, rightParent
hesis, body); |
| 6749 } finally { |
| 6750 _inLoop = wasInLoop; |
| 6751 } |
| 6752 } |
| 6753 |
| 6754 /** |
| 6755 * Parse a yield statement. |
| 6756 * |
| 6757 * <pre> |
| 6758 * yieldStatement ::= |
| 6759 * 'yield' '*'? expression ';' |
| 6760 * </pre> |
| 6761 * |
| 6762 * @return the yield statement that was parsed |
| 6763 */ |
| 6764 YieldStatement _parseYieldStatement() { |
| 6765 Token yieldToken = andAdvance; |
| 6766 Token star = null; |
| 6767 if (_matches(TokenType.STAR)) { |
| 6768 star = andAdvance; |
| 6769 } |
| 6770 Expression expression = parseExpression2(); |
| 6771 Token semicolon = _expect(TokenType.SEMICOLON); |
| 6772 return new YieldStatement(yieldToken, star, expression, semicolon); |
| 6773 } |
| 6774 |
| 6775 /** |
| 6776 * Return the token that is immediately after the current token. This is equiv
alent to |
| 6777 * [peekAt]. |
| 6778 * |
| 6779 * @return the token that is immediately after the current token |
| 6780 */ |
| 6781 Token _peek() => _currentToken.next; |
| 6782 |
| 6783 /** |
| 6784 * Return the token that is the given distance after the current token. |
| 6785 * |
| 6786 * @param distance the number of tokens to look ahead, where `0` is the curren
t token, |
| 6787 * `1` is the next token, etc. |
| 6788 * @return the token that is the given distance after the current token |
| 6789 */ |
| 6790 Token _peekAt(int distance) { |
| 6791 Token token = _currentToken; |
| 6792 for (int i = 0; i < distance; i++) { |
| 6793 token = token.next; |
| 6794 } |
| 6795 return token; |
| 6796 } |
| 6797 |
| 6798 /** |
| 6799 * Report the given [AnalysisError]. |
| 6800 * |
| 6801 * @param error the error to be reported |
| 6802 */ |
| 6803 void _reportError(AnalysisError error) { |
| 6804 if (_errorListenerLock != 0) { |
| 6805 return; |
| 6806 } |
| 6807 _errorListener.onError(error); |
| 6808 } |
| 6809 |
| 6810 /** |
| 6811 * Report an error with the given error code and arguments. |
| 6812 * |
| 6813 * @param errorCode the error code of the error to be reported |
| 6814 * @param arguments the arguments to the error, used to compose the error mess
age |
| 6815 */ |
| 6816 void _reportErrorForCurrentToken(ParserErrorCode errorCode, List<Object> argum
ents) { |
| 6817 _reportErrorForToken(errorCode, _currentToken, arguments); |
| 6818 } |
| 6819 |
| 6820 /** |
| 6821 * Report an error with the given error code and arguments. |
| 6822 * |
| 6823 * @param errorCode the error code of the error to be reported |
| 6824 * @param node the node specifying the location of the error |
| 6825 * @param arguments the arguments to the error, used to compose the error mess
age |
| 6826 */ |
| 6827 void _reportErrorForNode(ParserErrorCode errorCode, AstNode node, List<Object>
arguments) { |
| 6828 _reportError(new AnalysisError.con2(_source, node.offset, node.length, error
Code, arguments)); |
| 6829 } |
| 6830 |
| 6831 /** |
| 6832 * Report an error with the given error code and arguments. |
| 6833 * |
| 6834 * @param errorCode the error code of the error to be reported |
| 6835 * @param token the token specifying the location of the error |
| 6836 * @param arguments the arguments to the error, used to compose the error mess
age |
| 6837 */ |
| 6838 void _reportErrorForToken(ParserErrorCode errorCode, Token token, List<Object>
arguments) { |
| 6839 if (token.type == TokenType.EOF) { |
| 6840 token = token.previous; |
| 6841 } |
| 6842 _reportError(new AnalysisError.con2(_source, token.offset, Math.max(token.le
ngth, 1), errorCode, arguments)); |
| 6843 } |
| 6844 |
| 6845 /** |
| 6846 * Skips a block with all containing blocks. |
| 6847 */ |
| 6848 void _skipBlock() { |
| 6849 Token endToken = (_currentToken as BeginToken).endToken; |
| 6850 if (endToken == null) { |
| 6851 endToken = _currentToken.next; |
| 6852 while (!identical(endToken, _currentToken)) { |
| 6853 _currentToken = endToken; |
| 6854 endToken = _currentToken.next; |
| 6855 } |
| 6856 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou
s, ["}"]); |
| 6857 } else { |
| 6858 _currentToken = endToken.next; |
| 6859 } |
| 6860 } |
| 6861 |
| 6862 /** |
| 6863 * Parse the 'final', 'const', 'var' or type preceding a variable declaration,
starting at the |
| 6864 * given token, without actually creating a type or changing the current token
. Return the token |
| 6865 * following the type that was parsed, or `null` if the given token is not the
first token |
| 6866 * in a valid type. |
| 6867 * |
| 6868 * <pre> |
| 6869 * finalConstVarOrType ::= |
| 6870 * | 'final' type? |
| 6871 * | 'const' type? |
| 6872 * | 'var' |
| 6873 * | type |
| 6874 * </pre> |
| 6875 * |
| 6876 * @param startToken the token at which parsing is to begin |
| 6877 * @return the token following the type that was parsed |
| 6878 */ |
| 6879 Token _skipFinalConstVarOrType(Token startToken) { |
| 6880 if (_tokenMatchesKeyword(startToken, Keyword.FINAL) || _tokenMatchesKeyword(
startToken, Keyword.CONST)) { |
| 6881 Token next = startToken.next; |
| 6882 if (_tokenMatchesIdentifier(next)) { |
| 6883 Token next2 = next.next; |
| 6884 // "Type parameter" or "Type<" or "prefix.Type" |
| 6885 if (_tokenMatchesIdentifier(next2) || _tokenMatches(next2, TokenType.LT)
|| _tokenMatches(next2, TokenType.PERIOD)) { |
| 6886 return _skipTypeName(next); |
| 6887 } |
| 6888 // "parameter" |
| 6889 return next; |
| 6890 } |
| 6891 } else if (_tokenMatchesKeyword(startToken, Keyword.VAR)) { |
| 6892 return startToken.next; |
| 6893 } else if (_tokenMatchesIdentifier(startToken)) { |
| 6894 Token next = startToken.next; |
| 6895 if (_tokenMatchesIdentifier(next) || _tokenMatches(next, TokenType.LT) ||
_tokenMatchesKeyword(next, Keyword.THIS) || (_tokenMatches(next, TokenType.PERIO
D) && _tokenMatchesIdentifier(next.next) && (_tokenMatchesIdentifier(next.next.n
ext) || _tokenMatches(next.next.next, TokenType.LT) || _tokenMatchesKeyword(next
.next.next, Keyword.THIS)))) { |
| 6896 return _skipReturnType(startToken); |
| 6897 } |
| 6898 } |
| 6899 return null; |
| 6900 } |
| 6901 |
| 6902 /** |
| 6903 * Parse a list of formal parameters, starting at the given token, without act
ually creating a |
| 6904 * formal parameter list or changing the current token. Return the token follo
wing the formal |
| 6905 * parameter list that was parsed, or `null` if the given token is not the fir
st token in a |
| 6906 * valid list of formal parameter. |
| 6907 * |
| 6908 * Note that unlike other skip methods, this method uses a heuristic. In the w
orst case, the |
| 6909 * parameters could be prefixed by metadata, which would require us to be able
to skip arbitrary |
| 6910 * expressions. Rather than duplicate the logic of most of the parse methods w
e simply look for |
| 6911 * something that is likely to be a list of parameters and then skip to return
ing the token after |
| 6912 * the closing parenthesis. |
| 6913 * |
| 6914 * This method must be kept in sync with [parseFormalParameterList]. |
| 6915 * |
| 6916 * <pre> |
| 6917 * formalParameterList ::= |
| 6918 * '(' ')' |
| 6919 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' |
| 6920 * | '(' optionalFormalParameters ')' |
| 6921 * |
| 6922 * normalFormalParameters ::= |
| 6923 * normalFormalParameter (',' normalFormalParameter)* |
| 6924 * |
| 6925 * optionalFormalParameters ::= |
| 6926 * optionalPositionalFormalParameters |
| 6927 * | namedFormalParameters |
| 6928 * |
| 6929 * optionalPositionalFormalParameters ::= |
| 6930 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' |
| 6931 * |
| 6932 * namedFormalParameters ::= |
| 6933 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' |
| 6934 * </pre> |
| 6935 * |
| 6936 * @param startToken the token at which parsing is to begin |
| 6937 * @return the token following the formal parameter list that was parsed |
| 6938 */ |
| 6939 Token _skipFormalParameterList(Token startToken) { |
| 6940 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { |
| 6941 return null; |
| 6942 } |
| 6943 Token next = startToken.next; |
| 6944 if (_tokenMatches(next, TokenType.CLOSE_PAREN)) { |
| 6945 return next.next; |
| 6946 } |
| 6947 // |
| 6948 // Look to see whether the token after the open parenthesis is something tha
t should only occur |
| 6949 // at the beginning of a parameter list. |
| 6950 // |
| 6951 if (next.matchesAny([ |
| 6952 TokenType.AT, |
| 6953 TokenType.OPEN_SQUARE_BRACKET, |
| 6954 TokenType.OPEN_CURLY_BRACKET]) || _tokenMatchesKeyword(next, Keyword.VOI
D) || (_tokenMatchesIdentifier(next) && (next.next.matchesAny([TokenType.COMMA,
TokenType.CLOSE_PAREN])))) { |
| 6955 return _skipPastMatchingToken(startToken); |
| 6956 } |
| 6957 // |
| 6958 // Look to see whether the first parameter is a function typed parameter wit
hout a return type. |
| 6959 // |
| 6960 if (_tokenMatchesIdentifier(next) && _tokenMatches(next.next, TokenType.OPEN
_PAREN)) { |
| 6961 Token afterParameters = _skipFormalParameterList(next.next); |
| 6962 if (afterParameters != null && (afterParameters.matchesAny([TokenType.COMM
A, TokenType.CLOSE_PAREN]))) { |
| 6963 return _skipPastMatchingToken(startToken); |
| 6964 } |
| 6965 } |
| 6966 // |
| 6967 // Look to see whether the first parameter has a type or is a function typed
parameter with a |
| 6968 // return type. |
| 6969 // |
| 6970 Token afterType = _skipFinalConstVarOrType(next); |
| 6971 if (afterType == null) { |
| 6972 return null; |
| 6973 } |
| 6974 if (_skipSimpleIdentifier(afterType) == null) { |
| 6975 return null; |
| 6976 } |
| 6977 return _skipPastMatchingToken(startToken); |
| 6978 } |
| 6979 |
| 6980 /** |
| 6981 * If the given token is a begin token with an associated end token, then retu
rn the token |
| 6982 * following the end token. Otherwise, return `null`. |
| 6983 * |
| 6984 * @param startToken the token that is assumed to be a being token |
| 6985 * @return the token following the matching end token |
| 6986 */ |
| 6987 Token _skipPastMatchingToken(Token startToken) { |
| 6988 if (startToken is! BeginToken) { |
| 6989 return null; |
| 6990 } |
| 6991 Token closeParen = (startToken as BeginToken).endToken; |
| 6992 if (closeParen == null) { |
| 6993 return null; |
| 6994 } |
| 6995 return closeParen.next; |
| 6996 } |
| 6997 |
| 6998 /** |
| 6999 * Parse a prefixed identifier, starting at the given token, without actually
creating a prefixed |
| 7000 * identifier or changing the current token. Return the token following the pr
efixed identifier |
| 7001 * that was parsed, or `null` if the given token is not the first token in a v
alid prefixed |
| 7002 * identifier. |
| 7003 * |
| 7004 * This method must be kept in sync with [parsePrefixedIdentifier]. |
| 7005 * |
| 7006 * <pre> |
| 7007 * prefixedIdentifier ::= |
| 7008 * identifier ('.' identifier)? |
| 7009 * </pre> |
| 7010 * |
| 7011 * @param startToken the token at which parsing is to begin |
| 7012 * @return the token following the prefixed identifier that was parsed |
| 7013 */ |
| 7014 Token _skipPrefixedIdentifier(Token startToken) { |
| 7015 Token token = _skipSimpleIdentifier(startToken); |
| 7016 if (token == null) { |
| 7017 return null; |
| 7018 } else if (!_tokenMatches(token, TokenType.PERIOD)) { |
| 7019 return token; |
| 7020 } |
| 7021 return _skipSimpleIdentifier(token.next); |
| 7022 } |
| 7023 |
| 7024 /** |
| 7025 * Parse a return type, starting at the given token, without actually creating
a return type or |
| 7026 * changing the current token. Return the token following the return type that
was parsed, or |
| 7027 * `null` if the given token is not the first token in a valid return type. |
| 7028 * |
| 7029 * This method must be kept in sync with [parseReturnType]. |
| 7030 * |
| 7031 * <pre> |
| 7032 * returnType ::= |
| 7033 * 'void' |
| 7034 * | type |
| 7035 * </pre> |
| 7036 * |
| 7037 * @param startToken the token at which parsing is to begin |
| 7038 * @return the token following the return type that was parsed |
| 7039 */ |
| 7040 Token _skipReturnType(Token startToken) { |
| 7041 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { |
| 7042 return startToken.next; |
| 7043 } else { |
| 7044 return _skipTypeName(startToken); |
| 7045 } |
| 7046 } |
| 7047 |
| 7048 /** |
| 7049 * Parse a simple identifier, starting at the given token, without actually cr
eating a simple |
| 7050 * identifier or changing the current token. Return the token following the si
mple identifier that |
| 7051 * was parsed, or `null` if the given token is not the first token in a valid
simple |
| 7052 * identifier. |
| 7053 * |
| 7054 * This method must be kept in sync with [parseSimpleIdentifier]. |
| 7055 * |
| 7056 * <pre> |
| 7057 * identifier ::= |
| 7058 * IDENTIFIER |
| 7059 * </pre> |
| 7060 * |
| 7061 * @param startToken the token at which parsing is to begin |
| 7062 * @return the token following the simple identifier that was parsed |
| 7063 */ |
| 7064 Token _skipSimpleIdentifier(Token startToken) { |
| 7065 if (_tokenMatches(startToken, TokenType.IDENTIFIER) || (_tokenMatches(startT
oken, TokenType.KEYWORD) && (startToken as KeywordToken).keyword.isPseudoKeyword
)) { |
| 7066 return startToken.next; |
| 7067 } |
| 7068 return null; |
| 7069 } |
| 7070 |
| 7071 /** |
| 7072 * Parse a string literal that contains interpolations, starting at the given
token, without |
| 7073 * actually creating a string literal or changing the current token. Return th
e token following |
| 7074 * the string literal that was parsed, or `null` if the given token is not the
first token |
| 7075 * in a valid string literal. |
| 7076 * |
| 7077 * This method must be kept in sync with [parseStringInterpolation]. |
| 7078 * |
| 7079 * @param startToken the token at which parsing is to begin |
| 7080 * @return the string literal that was parsed |
| 7081 */ |
| 7082 Token _skipStringInterpolation(Token startToken) { |
| 7083 Token token = startToken; |
| 7084 TokenType type = token.type; |
| 7085 while (type == TokenType.STRING_INTERPOLATION_EXPRESSION || type == TokenTyp
e.STRING_INTERPOLATION_IDENTIFIER) { |
| 7086 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) { |
| 7087 token = token.next; |
| 7088 type = token.type; |
| 7089 // |
| 7090 // Rather than verify that the following tokens represent a valid expres
sion, we simply skip |
| 7091 // tokens until we reach the end of the interpolation, being careful to
handle nested string |
| 7092 // literals. |
| 7093 // |
| 7094 int bracketNestingLevel = 1; |
| 7095 while (bracketNestingLevel > 0) { |
| 7096 if (type == TokenType.EOF) { |
| 7097 return null; |
| 7098 } else if (type == TokenType.OPEN_CURLY_BRACKET) { |
| 7099 bracketNestingLevel++; |
| 7100 } else if (type == TokenType.CLOSE_CURLY_BRACKET) { |
| 7101 bracketNestingLevel--; |
| 7102 } else if (type == TokenType.STRING) { |
| 7103 token = _skipStringLiteral(token); |
| 7104 if (token == null) { |
| 7105 return null; |
| 7106 } |
| 7107 } else { |
| 7108 token = token.next; |
| 7109 } |
| 7110 type = token.type; |
| 7111 } |
| 7112 token = token.next; |
| 7113 type = token.type; |
| 7114 } else { |
| 7115 token = token.next; |
| 7116 if (token.type != TokenType.IDENTIFIER) { |
| 7117 return null; |
| 7118 } |
| 7119 token = token.next; |
| 7120 } |
| 7121 type = token.type; |
| 7122 if (type == TokenType.STRING) { |
| 7123 token = token.next; |
| 7124 type = token.type; |
| 7125 } |
| 7126 } |
| 7127 return token; |
| 7128 } |
| 7129 |
| 7130 /** |
| 7131 * Parse a string literal, starting at the given token, without actually creat
ing a string literal |
| 7132 * or changing the current token. Return the token following the string litera
l that was parsed, |
| 7133 * or `null` if the given token is not the first token in a valid string liter
al. |
| 7134 * |
| 7135 * This method must be kept in sync with [parseStringLiteral]. |
| 7136 * |
| 7137 * <pre> |
| 7138 * stringLiteral ::= |
| 7139 * MULTI_LINE_STRING+ |
| 7140 * | SINGLE_LINE_STRING+ |
| 7141 * </pre> |
| 7142 * |
| 7143 * @param startToken the token at which parsing is to begin |
| 7144 * @return the token following the string literal that was parsed |
| 7145 */ |
| 7146 Token _skipStringLiteral(Token startToken) { |
| 7147 Token token = startToken; |
| 7148 while (token != null && _tokenMatches(token, TokenType.STRING)) { |
| 7149 token = token.next; |
| 7150 TokenType type = token.type; |
| 7151 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION || type == TokenType
.STRING_INTERPOLATION_IDENTIFIER) { |
| 7152 token = _skipStringInterpolation(token); |
| 7153 } |
| 7154 } |
| 7155 if (identical(token, startToken)) { |
| 7156 return null; |
| 7157 } |
| 7158 return token; |
| 7159 } |
| 7160 |
| 7161 /** |
| 7162 * Parse a list of type arguments, starting at the given token, without actual
ly creating a type argument list |
| 7163 * or changing the current token. Return the token following the type argument
list that was parsed, |
| 7164 * or `null` if the given token is not the first token in a valid type argumen
t list. |
| 7165 * |
| 7166 * This method must be kept in sync with [parseTypeArgumentList]. |
| 7167 * |
| 7168 * <pre> |
| 7169 * typeArguments ::= |
| 7170 * '<' typeList '>' |
| 7171 * |
| 7172 * typeList ::= |
| 7173 * type (',' type)* |
| 7174 * </pre> |
| 7175 * |
| 7176 * @param startToken the token at which parsing is to begin |
| 7177 * @return the token following the type argument list that was parsed |
| 7178 */ |
| 7179 Token _skipTypeArgumentList(Token startToken) { |
| 7180 Token token = startToken; |
| 7181 if (!_tokenMatches(token, TokenType.LT)) { |
| 7182 return null; |
| 7183 } |
| 7184 token = _skipTypeName(token.next); |
| 7185 if (token == null) { |
| 7186 return null; |
| 7187 } |
| 7188 while (_tokenMatches(token, TokenType.COMMA)) { |
| 7189 token = _skipTypeName(token.next); |
| 7190 if (token == null) { |
| 7191 return null; |
| 7192 } |
| 7193 } |
| 7194 if (token.type == TokenType.GT) { |
| 7195 return token.next; |
| 7196 } else if (token.type == TokenType.GT_GT) { |
| 7197 Token second = new Token(TokenType.GT, token.offset + 1); |
| 7198 second.setNextWithoutSettingPrevious(token.next); |
| 7199 return second; |
| 7200 } |
| 7201 return null; |
| 7202 } |
| 7203 |
| 7204 /** |
| 7205 * Parse a type name, starting at the given token, without actually creating a
type name or |
| 7206 * changing the current token. Return the token following the type name that w
as parsed, or |
| 7207 * `null` if the given token is not the first token in a valid type name. |
| 7208 * |
| 7209 * This method must be kept in sync with [parseTypeName]. |
| 7210 * |
| 7211 * <pre> |
| 7212 * type ::= |
| 7213 * qualified typeArguments? |
| 7214 * </pre> |
| 7215 * |
| 7216 * @param startToken the token at which parsing is to begin |
| 7217 * @return the token following the type name that was parsed |
| 7218 */ |
| 7219 Token _skipTypeName(Token startToken) { |
| 7220 Token token = _skipPrefixedIdentifier(startToken); |
| 7221 if (token == null) { |
| 7222 return null; |
| 7223 } |
| 7224 if (_tokenMatches(token, TokenType.LT)) { |
| 7225 token = _skipTypeArgumentList(token); |
| 7226 } |
| 7227 return token; |
| 7228 } |
| 7229 |
| 7230 /** |
| 7231 * Parse a list of type parameters, starting at the given token, without actua
lly creating a type |
| 7232 * parameter list or changing the current token. Return the token following th
e type parameter |
| 7233 * list that was parsed, or `null` if the given token is not the first token i
n a valid type |
| 7234 * parameter list. |
| 7235 * |
| 7236 * This method must be kept in sync with [parseTypeParameterList]. |
| 7237 * |
| 7238 * <pre> |
| 7239 * typeParameterList ::= |
| 7240 * '<' typeParameter (',' typeParameter)* '>' |
| 7241 * </pre> |
| 7242 * |
| 7243 * @param startToken the token at which parsing is to begin |
| 7244 * @return the token following the type parameter list that was parsed |
| 7245 */ |
| 7246 Token _skipTypeParameterList(Token startToken) { |
| 7247 if (!_tokenMatches(startToken, TokenType.LT)) { |
| 7248 return null; |
| 7249 } |
| 7250 // |
| 7251 // We can't skip a type parameter because it can be preceeded by metadata, s
o we just assume |
| 7252 // that everything before the matching end token is valid. |
| 7253 // |
| 7254 int depth = 1; |
| 7255 Token next = startToken.next; |
| 7256 while (depth > 0) { |
| 7257 if (_tokenMatches(next, TokenType.EOF)) { |
| 7258 return null; |
| 7259 } else if (_tokenMatches(next, TokenType.LT)) { |
| 7260 depth++; |
| 7261 } else if (_tokenMatches(next, TokenType.GT)) { |
| 7262 depth--; |
| 7263 } else if (_tokenMatches(next, TokenType.GT_EQ)) { |
| 7264 if (depth == 1) { |
| 7265 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2); |
| 7266 fakeEquals.setNextWithoutSettingPrevious(next.next); |
| 7267 return fakeEquals; |
| 7268 } |
| 7269 depth--; |
| 7270 } else if (_tokenMatches(next, TokenType.GT_GT)) { |
| 7271 depth -= 2; |
| 7272 } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) { |
| 7273 if (depth < 2) { |
| 7274 return null; |
| 7275 } else if (depth == 2) { |
| 7276 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2); |
| 7277 fakeEquals.setNextWithoutSettingPrevious(next.next); |
| 7278 return fakeEquals; |
| 7279 } |
| 7280 depth -= 2; |
| 7281 } |
| 7282 next = next.next; |
| 7283 } |
| 7284 return next; |
| 7285 } |
| 7286 |
| 7287 /** |
| 7288 * Return `true` if the given token has the given type. |
| 7289 * |
| 7290 * @param token the token being tested |
| 7291 * @param type the type of token that is being tested for |
| 7292 * @return `true` if the given token has the given type |
| 7293 */ |
| 7294 bool _tokenMatches(Token token, TokenType type) => token.type == type; |
| 7295 |
| 7296 /** |
| 7297 * Return `true` if the given token is a valid identifier. Valid identifiers i
nclude |
| 7298 * built-in identifiers (pseudo-keywords). |
| 7299 * |
| 7300 * @return `true` if the given token is a valid identifier |
| 7301 */ |
| 7302 bool _tokenMatchesIdentifier(Token token) => _tokenMatches(token, TokenType.ID
ENTIFIER) || (_tokenMatches(token, TokenType.KEYWORD) && (token as KeywordToken)
.keyword.isPseudoKeyword); |
| 7303 |
| 7304 /** |
| 7305 * Return `true` if the given token matches the given keyword. |
| 7306 * |
| 7307 * @param token the token being tested |
| 7308 * @param keyword the keyword that is being tested for |
| 7309 * @return `true` if the given token matches the given keyword |
| 7310 */ |
| 7311 bool _tokenMatchesKeyword(Token token, Keyword keyword) => token.type == Token
Type.KEYWORD && (token as KeywordToken).keyword == keyword; |
| 7312 |
| 7313 /** |
| 7314 * Return `true` if the given token matches the given identifier. |
| 7315 * |
| 7316 * @param token the token being tested |
| 7317 * @param identifier the identifier that can optionally appear in the current
location |
| 7318 * @return `true` if the current token matches the given identifier |
| 7319 */ |
| 7320 bool _tokenMatchesString(Token token, String identifier) => token.type == Toke
nType.IDENTIFIER && token.lexeme == identifier; |
| 7321 |
| 7322 /** |
| 7323 * Translate the characters at the given index in the given string, appending
the translated |
| 7324 * character to the given builder. The index is assumed to be valid. |
| 7325 * |
| 7326 * @param builder the builder to which the translated character is to be appen
ded |
| 7327 * @param lexeme the string containing the character(s) to be translated |
| 7328 * @param index the index of the character to be translated |
| 7329 * @return the index of the next character to be translated |
| 7330 */ |
| 7331 int _translateCharacter(JavaStringBuilder builder, String lexeme, int index) { |
| 7332 int currentChar = lexeme.codeUnitAt(index); |
| 7333 if (currentChar != 0x5C) { |
| 7334 builder.appendChar(currentChar); |
| 7335 return index + 1; |
| 7336 } |
| 7337 // |
| 7338 // We have found an escape sequence, so we parse the string to determine wha
t kind of escape |
| 7339 // sequence and what character to add to the builder. |
| 7340 // |
| 7341 int length = lexeme.length; |
| 7342 int currentIndex = index + 1; |
| 7343 if (currentIndex >= length) { |
| 7344 // Illegal escape sequence: no char after escape |
| 7345 // This cannot actually happen because it would require the escape charact
er to be the last |
| 7346 // character in the string, but if it were it would escape the closing quo
te, leaving the |
| 7347 // string unclosed. |
| 7348 // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE); |
| 7349 return length; |
| 7350 } |
| 7351 currentChar = lexeme.codeUnitAt(currentIndex); |
| 7352 if (currentChar == 0x6E) { |
| 7353 builder.appendChar(0xA); |
| 7354 } else if (currentChar == 0x72) { |
| 7355 builder.appendChar(0xD); |
| 7356 } else if (currentChar == 0x66) { |
| 7357 builder.appendChar(0xC); |
| 7358 } else if (currentChar == 0x62) { |
| 7359 builder.appendChar(0x8); |
| 7360 } else if (currentChar == 0x74) { |
| 7361 builder.appendChar(0x9); |
| 7362 } else if (currentChar == 0x76) { |
| 7363 builder.appendChar(0xB); |
| 7364 } else if (currentChar == 0x78) { |
| 7365 if (currentIndex + 2 >= length) { |
| 7366 // Illegal escape sequence: not enough hex digits |
| 7367 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE, []); |
| 7368 return length; |
| 7369 } |
| 7370 int firstDigit = lexeme.codeUnitAt(currentIndex + 1); |
| 7371 int secondDigit = lexeme.codeUnitAt(currentIndex + 2); |
| 7372 if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) { |
| 7373 // Illegal escape sequence: invalid hex digit |
| 7374 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE, []); |
| 7375 } else { |
| 7376 builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.d
igit(secondDigit, 16))); |
| 7377 } |
| 7378 return currentIndex + 3; |
| 7379 } else if (currentChar == 0x75) { |
| 7380 currentIndex++; |
| 7381 if (currentIndex >= length) { |
| 7382 // Illegal escape sequence: not enough hex digits |
| 7383 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); |
| 7384 return length; |
| 7385 } |
| 7386 currentChar = lexeme.codeUnitAt(currentIndex); |
| 7387 if (currentChar == 0x7B) { |
| 7388 currentIndex++; |
| 7389 if (currentIndex >= length) { |
| 7390 // Illegal escape sequence: incomplete escape |
| 7391 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []
); |
| 7392 return length; |
| 7393 } |
| 7394 currentChar = lexeme.codeUnitAt(currentIndex); |
| 7395 int digitCount = 0; |
| 7396 int value = 0; |
| 7397 while (currentChar != 0x7D) { |
| 7398 if (!_isHexDigit(currentChar)) { |
| 7399 // Illegal escape sequence: invalid hex digit |
| 7400 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE,
[]); |
| 7401 currentIndex++; |
| 7402 while (currentIndex < length && lexeme.codeUnitAt(currentIndex) != 0
x7D) { |
| 7403 currentIndex++; |
| 7404 } |
| 7405 return currentIndex + 1; |
| 7406 } |
| 7407 digitCount++; |
| 7408 value = (value << 4) + Character.digit(currentChar, 16); |
| 7409 currentIndex++; |
| 7410 if (currentIndex >= length) { |
| 7411 // Illegal escape sequence: incomplete escape |
| 7412 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE,
[]); |
| 7413 return length; |
| 7414 } |
| 7415 currentChar = lexeme.codeUnitAt(currentIndex); |
| 7416 } |
| 7417 if (digitCount < 1 || digitCount > 6) { |
| 7418 // Illegal escape sequence: not enough or too many hex digits |
| 7419 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []
); |
| 7420 } |
| 7421 _appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), v
alue, index, currentIndex); |
| 7422 return currentIndex + 1; |
| 7423 } else { |
| 7424 if (currentIndex + 3 >= length) { |
| 7425 // Illegal escape sequence: not enough hex digits |
| 7426 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []
); |
| 7427 return length; |
| 7428 } |
| 7429 int firstDigit = currentChar; |
| 7430 int secondDigit = lexeme.codeUnitAt(currentIndex + 1); |
| 7431 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2); |
| 7432 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3); |
| 7433 if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit) || !_isHexDigi
t(thirdDigit) || !_isHexDigit(fourthDigit)) { |
| 7434 // Illegal escape sequence: invalid hex digits |
| 7435 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []
); |
| 7436 } else { |
| 7437 _appendScalarValue(builder, lexeme.substring(index, currentIndex + 1),
(((((Character.digit(firstDigit, 16) << 4) + Character.digit(secondDigit, 16))
<< 4) + Character.digit(thirdDigit, 16)) << 4) + Character.digit(fourthDigit, 16
), index, currentIndex + 3); |
| 7438 } |
| 7439 return currentIndex + 4; |
| 7440 } |
| 7441 } else { |
| 7442 builder.appendChar(currentChar); |
| 7443 } |
| 7444 return currentIndex + 1; |
| 7445 } |
| 7446 |
| 7447 /** |
| 7448 * Decrements the error reporting lock level. If level is more than `0`, then |
| 7449 * [reportError] wont report any error. |
| 7450 */ |
| 7451 void _unlockErrorListener() { |
| 7452 if (_errorListenerLock == 0) { |
| 7453 throw new IllegalStateException("Attempt to unlock not locked error listen
er."); |
| 7454 } |
| 7455 _errorListenerLock--; |
| 7456 } |
| 7457 |
| 7458 /** |
| 7459 * Validate that the given parameter list does not contain any field initializ
ers. |
| 7460 * |
| 7461 * @param parameterList the parameter list to be validated |
| 7462 */ |
| 7463 void _validateFormalParameterList(FormalParameterList parameterList) { |
| 7464 for (FormalParameter parameter in parameterList.parameters) { |
| 7465 if (parameter is FieldFormalParameter) { |
| 7466 _reportErrorForNode(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTO
R, parameter.identifier, []); |
| 7467 } |
| 7468 } |
| 7469 } |
| 7470 |
| 7471 /** |
| 7472 * Validate that the given set of modifiers is appropriate for a class and ret
urn the 'abstract' |
| 7473 * keyword if there is one. |
| 7474 * |
| 7475 * @param modifiers the modifiers being validated |
| 7476 */ |
| 7477 Token _validateModifiersForClass(Modifiers modifiers) { |
| 7478 _validateModifiersForTopLevelDeclaration(modifiers); |
| 7479 if (modifiers.constKeyword != null) { |
| 7480 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword,
[]); |
| 7481 } |
| 7482 if (modifiers.externalKeyword != null) { |
| 7483 _reportErrorForToken(ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKey
word, []); |
| 7484 } |
| 7485 if (modifiers.finalKeyword != null) { |
| 7486 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword,
[]); |
| 7487 } |
| 7488 if (modifiers.varKeyword != null) { |
| 7489 _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword, []); |
| 7490 } |
| 7491 return modifiers.abstractKeyword; |
| 7492 } |
| 7493 |
| 7494 /** |
| 7495 * Validate that the given set of modifiers is appropriate for a constructor a
nd return the |
| 7496 * 'const' keyword if there is one. |
| 7497 * |
| 7498 * @param modifiers the modifiers being validated |
| 7499 * @return the 'const' or 'final' keyword associated with the constructor |
| 7500 */ |
| 7501 Token _validateModifiersForConstructor(Modifiers modifiers) { |
| 7502 if (modifiers.abstractKeyword != null) { |
| 7503 _reportErrorForToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abst
ractKeyword, []); |
| 7504 } |
| 7505 if (modifiers.finalKeyword != null) { |
| 7506 _reportErrorForToken(ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKey
word, []); |
| 7507 } |
| 7508 if (modifiers.staticKeyword != null) { |
| 7509 _reportErrorForToken(ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticK
eyword, []); |
| 7510 } |
| 7511 if (modifiers.varKeyword != null) { |
| 7512 _reportErrorForToken(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifie
rs.varKeyword, []); |
| 7513 } |
| 7514 Token externalKeyword = modifiers.externalKeyword; |
| 7515 Token constKeyword = modifiers.constKeyword; |
| 7516 Token factoryKeyword = modifiers.factoryKeyword; |
| 7517 if (externalKeyword != null && constKeyword != null && constKeyword.offset <
externalKeyword.offset) { |
| 7518 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword
, []); |
| 7519 } |
| 7520 if (externalKeyword != null && factoryKeyword != null && factoryKeyword.offs
et < externalKeyword.offset) { |
| 7521 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeywo
rd, []); |
| 7522 } |
| 7523 return constKeyword; |
| 7524 } |
| 7525 |
| 7526 /** |
| 7527 * Validate that the given set of modifiers is appropriate for a class and ret
urn the 'abstract' |
| 7528 * keyword if there is one. |
| 7529 * |
| 7530 * @param modifiers the modifiers being validated |
| 7531 */ |
| 7532 void _validateModifiersForEnum(Modifiers modifiers) { |
| 7533 _validateModifiersForTopLevelDeclaration(modifiers); |
| 7534 if (modifiers.abstractKeyword != null) { |
| 7535 _reportErrorForToken(ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyw
ord, []); |
| 7536 } |
| 7537 if (modifiers.constKeyword != null) { |
| 7538 _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword, [
]); |
| 7539 } |
| 7540 if (modifiers.externalKeyword != null) { |
| 7541 _reportErrorForToken(ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyw
ord, []); |
| 7542 } |
| 7543 if (modifiers.finalKeyword != null) { |
| 7544 _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword, [
]); |
| 7545 } |
| 7546 if (modifiers.varKeyword != null) { |
| 7547 _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword, []); |
| 7548 } |
| 7549 } |
| 7550 |
| 7551 /** |
| 7552 * Validate that the given set of modifiers is appropriate for a field and ret
urn the 'final', |
| 7553 * 'const' or 'var' keyword if there is one. |
| 7554 * |
| 7555 * @param modifiers the modifiers being validated |
| 7556 * @return the 'final', 'const' or 'var' keyword associated with the field |
| 7557 */ |
| 7558 Token _validateModifiersForField(Modifiers modifiers) { |
| 7559 if (modifiers.abstractKeyword != null) { |
| 7560 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []); |
| 7561 } |
| 7562 if (modifiers.externalKeyword != null) { |
| 7563 _reportErrorForToken(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKey
word, []); |
| 7564 } |
| 7565 if (modifiers.factoryKeyword != null) { |
| 7566 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa
ctoryKeyword, []); |
| 7567 } |
| 7568 Token staticKeyword = modifiers.staticKeyword; |
| 7569 Token constKeyword = modifiers.constKeyword; |
| 7570 Token finalKeyword = modifiers.finalKeyword; |
| 7571 Token varKeyword = modifiers.varKeyword; |
| 7572 if (constKeyword != null) { |
| 7573 if (finalKeyword != null) { |
| 7574 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []); |
| 7575 } |
| 7576 if (varKeyword != null) { |
| 7577 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword, []); |
| 7578 } |
| 7579 if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) { |
| 7580 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword,
[]); |
| 7581 } |
| 7582 } else if (finalKeyword != null) { |
| 7583 if (varKeyword != null) { |
| 7584 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword, []); |
| 7585 } |
| 7586 if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) { |
| 7587 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword,
[]); |
| 7588 } |
| 7589 } else if (varKeyword != null && staticKeyword != null && varKeyword.offset
< staticKeyword.offset) { |
| 7590 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword, []); |
| 7591 } |
| 7592 return _lexicallyFirst([constKeyword, finalKeyword, varKeyword]); |
| 7593 } |
| 7594 |
| 7595 /** |
| 7596 * Validate that the given set of modifiers is appropriate for a local functio
n. |
| 7597 * |
| 7598 * @param modifiers the modifiers being validated |
| 7599 */ |
| 7600 void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) { |
| 7601 if (modifiers.abstractKeyword != null || modifiers.constKeyword != null || m
odifiers.externalKeyword != null || modifiers.factoryKeyword != null || modifier
s.finalKeyword != null || modifiers.staticKeyword != null || modifiers.varKeywor
d != null) { |
| 7602 _reportErrorForCurrentToken(ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MOD
IFIER, []); |
| 7603 } |
| 7604 } |
| 7605 |
| 7606 /** |
| 7607 * Validate that the given set of modifiers is appropriate for a getter, sette
r, or method. |
| 7608 * |
| 7609 * @param modifiers the modifiers being validated |
| 7610 */ |
| 7611 void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) { |
| 7612 if (modifiers.abstractKeyword != null) { |
| 7613 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []); |
| 7614 } |
| 7615 if (modifiers.constKeyword != null) { |
| 7616 _reportErrorForToken(ParserErrorCode.CONST_METHOD, modifiers.constKeyword,
[]); |
| 7617 } |
| 7618 if (modifiers.factoryKeyword != null) { |
| 7619 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa
ctoryKeyword, []); |
| 7620 } |
| 7621 if (modifiers.finalKeyword != null) { |
| 7622 _reportErrorForToken(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword,
[]); |
| 7623 } |
| 7624 if (modifiers.varKeyword != null) { |
| 7625 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword
, []); |
| 7626 } |
| 7627 Token externalKeyword = modifiers.externalKeyword; |
| 7628 Token staticKeyword = modifiers.staticKeyword; |
| 7629 if (externalKeyword != null && staticKeyword != null && staticKeyword.offset
< externalKeyword.offset) { |
| 7630 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeywor
d, []); |
| 7631 } |
| 7632 } |
| 7633 |
| 7634 /** |
| 7635 * Validate that the given set of modifiers is appropriate for a getter, sette
r, or method. |
| 7636 * |
| 7637 * @param modifiers the modifiers being validated |
| 7638 */ |
| 7639 void _validateModifiersForOperator(Modifiers modifiers) { |
| 7640 if (modifiers.abstractKeyword != null) { |
| 7641 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []); |
| 7642 } |
| 7643 if (modifiers.constKeyword != null) { |
| 7644 _reportErrorForToken(ParserErrorCode.CONST_METHOD, modifiers.constKeyword,
[]); |
| 7645 } |
| 7646 if (modifiers.factoryKeyword != null) { |
| 7647 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa
ctoryKeyword, []); |
| 7648 } |
| 7649 if (modifiers.finalKeyword != null) { |
| 7650 _reportErrorForToken(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword,
[]); |
| 7651 } |
| 7652 if (modifiers.staticKeyword != null) { |
| 7653 _reportErrorForToken(ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyw
ord, []); |
| 7654 } |
| 7655 if (modifiers.varKeyword != null) { |
| 7656 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword
, []); |
| 7657 } |
| 7658 } |
| 7659 |
| 7660 /** |
| 7661 * Validate that the given set of modifiers is appropriate for a top-level dec
laration. |
| 7662 * |
| 7663 * @param modifiers the modifiers being validated |
| 7664 */ |
| 7665 void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) { |
| 7666 if (modifiers.factoryKeyword != null) { |
| 7667 _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, modifi
ers.factoryKeyword, []); |
| 7668 } |
| 7669 if (modifiers.staticKeyword != null) { |
| 7670 _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, modifie
rs.staticKeyword, []); |
| 7671 } |
| 7672 } |
| 7673 |
| 7674 /** |
| 7675 * Validate that the given set of modifiers is appropriate for a top-level fun
ction. |
| 7676 * |
| 7677 * @param modifiers the modifiers being validated |
| 7678 */ |
| 7679 void _validateModifiersForTopLevelFunction(Modifiers modifiers) { |
| 7680 _validateModifiersForTopLevelDeclaration(modifiers); |
| 7681 if (modifiers.abstractKeyword != null) { |
| 7682 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, [
]); |
| 7683 } |
| 7684 if (modifiers.constKeyword != null) { |
| 7685 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword,
[]); |
| 7686 } |
| 7687 if (modifiers.finalKeyword != null) { |
| 7688 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword,
[]); |
| 7689 } |
| 7690 if (modifiers.varKeyword != null) { |
| 7691 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword
, []); |
| 7692 } |
| 7693 } |
| 7694 |
| 7695 /** |
| 7696 * Validate that the given set of modifiers is appropriate for a field and ret
urn the 'final', |
| 7697 * 'const' or 'var' keyword if there is one. |
| 7698 * |
| 7699 * @param modifiers the modifiers being validated |
| 7700 * @return the 'final', 'const' or 'var' keyword associated with the field |
| 7701 */ |
| 7702 Token _validateModifiersForTopLevelVariable(Modifiers modifiers) { |
| 7703 _validateModifiersForTopLevelDeclaration(modifiers); |
| 7704 if (modifiers.abstractKeyword != null) { |
| 7705 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, [
]); |
| 7706 } |
| 7707 if (modifiers.externalKeyword != null) { |
| 7708 _reportErrorForToken(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKey
word, []); |
| 7709 } |
| 7710 Token constKeyword = modifiers.constKeyword; |
| 7711 Token finalKeyword = modifiers.finalKeyword; |
| 7712 Token varKeyword = modifiers.varKeyword; |
| 7713 if (constKeyword != null) { |
| 7714 if (finalKeyword != null) { |
| 7715 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []); |
| 7716 } |
| 7717 if (varKeyword != null) { |
| 7718 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword, []); |
| 7719 } |
| 7720 } else if (finalKeyword != null) { |
| 7721 if (varKeyword != null) { |
| 7722 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword, []); |
| 7723 } |
| 7724 } |
| 7725 return _lexicallyFirst([constKeyword, finalKeyword, varKeyword]); |
| 7726 } |
| 7727 |
| 7728 /** |
| 7729 * Validate that the given set of modifiers is appropriate for a class and ret
urn the 'abstract' |
| 7730 * keyword if there is one. |
| 7731 * |
| 7732 * @param modifiers the modifiers being validated |
| 7733 */ |
| 7734 void _validateModifiersForTypedef(Modifiers modifiers) { |
| 7735 _validateModifiersForTopLevelDeclaration(modifiers); |
| 7736 if (modifiers.abstractKeyword != null) { |
| 7737 _reportErrorForToken(ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractK
eyword, []); |
| 7738 } |
| 7739 if (modifiers.constKeyword != null) { |
| 7740 _reportErrorForToken(ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword
, []); |
| 7741 } |
| 7742 if (modifiers.externalKeyword != null) { |
| 7743 _reportErrorForToken(ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalK
eyword, []); |
| 7744 } |
| 7745 if (modifiers.finalKeyword != null) { |
| 7746 _reportErrorForToken(ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword
, []); |
| 7747 } |
| 7748 if (modifiers.varKeyword != null) { |
| 7749 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword, []
); |
| 7750 } |
| 7751 } |
| 7752 } |
| 7753 |
| 7754 /** |
| 7755 * The enumeration `ParserErrorCode` defines the error codes used for errors det
ected by the |
| 7756 * parser. The convention for this class is for the name of the error code to in
dicate the problem |
| 7757 * that caused the error to be generated and for the error message to explain wh
at is wrong and, |
| 7758 * when appropriate, how the problem can be corrected. |
| 7759 */ |
| 7760 class ParserErrorCode extends Enum<ParserErrorCode> implements ErrorCode { |
| 7761 static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode.con
3('ABSTRACT_CLASS_MEMBER', 0, "Members of classes cannot be declared to be 'abst
ract'"); |
| 7762 |
| 7763 static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode.con3('ABSTR
ACT_ENUM', 1, "Enums cannot be declared to be 'abstract'"); |
| 7764 |
| 7765 static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode.co
n3('ABSTRACT_STATIC_METHOD', 2, "Static methods cannot be declared to be 'abstra
ct'"); |
| 7766 |
| 7767 static const ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION = const ParserErrorCo
de.con3('ABSTRACT_TOP_LEVEL_FUNCTION', 3, "Top-level functions cannot be declare
d to be 'abstract'"); |
| 7768 |
| 7769 static const ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE = const ParserErrorCo
de.con3('ABSTRACT_TOP_LEVEL_VARIABLE', 4, "Top-level variables cannot be declare
d to be 'abstract'"); |
| 7770 |
| 7771 static const ParserErrorCode ABSTRACT_TYPEDEF = const ParserErrorCode.con3('AB
STRACT_TYPEDEF', 5, "Type aliases cannot be declared to be 'abstract'"); |
| 7772 |
| 7773 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT = const ParserErr
orCode.con3('ASSERT_DOES_NOT_TAKE_ASSIGNMENT', 6, "Assert cannot be called on an
assignment"); |
| 7774 |
| 7775 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE = const ParserErrorC
ode.con3('ASSERT_DOES_NOT_TAKE_CASCADE', 7, "Assert cannot be called on cascade"
); |
| 7776 |
| 7777 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW = const ParserErrorCod
e.con3('ASSERT_DOES_NOT_TAKE_THROW', 8, "Assert cannot be called on throws"); |
| 7778 |
| 7779 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW = const ParserErrorC
ode.con3('ASSERT_DOES_NOT_TAKE_RETHROW', 9, "Assert cannot be called on rethrows
"); |
| 7780 |
| 7781 static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode.con
3('BREAK_OUTSIDE_OF_LOOP', 10, "A break statement cannot be used outside of a lo
op or switch statement"); |
| 7782 |
| 7783 static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode.con3('CON
ST_AND_FINAL', 11, "Members cannot be declared to be both 'const' and 'final'"); |
| 7784 |
| 7785 static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode.con3('CONST
_AND_VAR', 12, "Members cannot be declared to be both 'const' and 'var'"); |
| 7786 |
| 7787 static const ParserErrorCode CONST_CLASS = const ParserErrorCode.con3('CONST_C
LASS', 13, "Classes cannot be declared to be 'const'"); |
| 7788 |
| 7789 static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY = const ParserErrorCo
de.con3('CONST_CONSTRUCTOR_WITH_BODY', 14, "'const' constructors cannot have a b
ody"); |
| 7790 |
| 7791 static const ParserErrorCode CONST_ENUM = const ParserErrorCode.con3('CONST_EN
UM', 15, "Enums cannot be declared to be 'const'"); |
| 7792 |
| 7793 static const ParserErrorCode CONST_FACTORY = const ParserErrorCode.con3('CONST
_FACTORY', 16, "Only redirecting factory constructors can be declared to be 'con
st'"); |
| 7794 |
| 7795 static const ParserErrorCode CONST_METHOD = const ParserErrorCode.con3('CONST_
METHOD', 17, "Getters, setters and methods cannot be declared to be 'const'"); |
| 7796 |
| 7797 static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode.con3('CONST
_TYPEDEF', 18, "Type aliases cannot be declared to be 'const'"); |
| 7798 |
| 7799 static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = const ParserErrorC
ode.con3('CONSTRUCTOR_WITH_RETURN_TYPE', 19, "Constructors cannot have a return
type"); |
| 7800 |
| 7801 static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode.
con3('CONTINUE_OUTSIDE_OF_LOOP', 20, "A continue statement cannot be used outsid
e of a loop or switch statement"); |
| 7802 |
| 7803 static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = const ParserErro
rCode.con3('CONTINUE_WITHOUT_LABEL_IN_CASE', 21, "A continue statement in a swit
ch statement must have a label as a target"); |
| 7804 |
| 7805 static const ParserErrorCode DEFERRED_IMPORTS_NOT_SUPPORTED = const ParserErro
rCode.con3('DEFERRED_IMPORTS_NOT_SUPPORTED', 22, "Deferred imports are not suppo
rted by default"); |
| 7806 |
| 7807 static const ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS = const ParserErrorCo
de.con3('DEPRECATED_CLASS_TYPE_ALIAS', 23, "The 'typedef' mixin application was
replaced with 'class'"); |
| 7808 |
| 7809 static const ParserErrorCode DIRECTIVE_AFTER_DECLARATION = const ParserErrorCo
de.con3('DIRECTIVE_AFTER_DECLARATION', 24, "Directives must appear before any de
clarations"); |
| 7810 |
| 7811 static const ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = const Parse
rErrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 25, "The label {0} was al
ready used in this switch statement"); |
| 7812 |
| 7813 static const ParserErrorCode DUPLICATED_MODIFIER = const ParserErrorCode.con3(
'DUPLICATED_MODIFIER', 26, "The modifier '{0}' was already specified."); |
| 7814 |
| 7815 static const ParserErrorCode EMPTY_ENUM_BODY = const ParserErrorCode.con3('EMP
TY_ENUM_BODY', 27, "An enum must declare at least one constant name"); |
| 7816 |
| 7817 static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = const Parse
rErrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 28, "Equality expression
cannot be operand of another equality expression."); |
| 7818 |
| 7819 static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode.
con3('EXPECTED_CASE_OR_DEFAULT', 29, "Expected 'case' or 'default'"); |
| 7820 |
| 7821 static const ParserErrorCode EXPECTED_CLASS_MEMBER = const ParserErrorCode.con
3('EXPECTED_CLASS_MEMBER', 30, "Expected a class member"); |
| 7822 |
| 7823 static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode.con3(
'EXPECTED_EXECUTABLE', 31, "Expected a method, getter, setter or operator declar
ation"); |
| 7824 |
| 7825 static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = const ParserErrorC
ode.con3('EXPECTED_LIST_OR_MAP_LITERAL', 32, "Expected a list or map literal"); |
| 7826 |
| 7827 static const ParserErrorCode EXPECTED_STRING_LITERAL = const ParserErrorCode.c
on3('EXPECTED_STRING_LITERAL', 33, "Expected a string literal"); |
| 7828 |
| 7829 static const ParserErrorCode EXPECTED_TOKEN = const ParserErrorCode.con3('EXPE
CTED_TOKEN', 34, "Expected to find '{0}'"); |
| 7830 |
| 7831 static const ParserErrorCode EXPECTED_TYPE_NAME = const ParserErrorCode.con3('
EXPECTED_TYPE_NAME', 35, "Expected a type name"); |
| 7832 |
| 7833 static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = const Par
serErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 36, "Export directive
s must preceed part directives"); |
| 7834 |
| 7835 static const ParserErrorCode EXTERNAL_AFTER_CONST = const ParserErrorCode.con3
('EXTERNAL_AFTER_CONST', 37, "The modifier 'external' should be before the modif
ier 'const'"); |
| 7836 |
| 7837 static const ParserErrorCode EXTERNAL_AFTER_FACTORY = const ParserErrorCode.co
n3('EXTERNAL_AFTER_FACTORY', 38, "The modifier 'external' should be before the m
odifier 'factory'"); |
| 7838 |
| 7839 static const ParserErrorCode EXTERNAL_AFTER_STATIC = const ParserErrorCode.con
3('EXTERNAL_AFTER_STATIC', 39, "The modifier 'external' should be before the mod
ifier 'static'"); |
| 7840 |
| 7841 static const ParserErrorCode EXTERNAL_CLASS = const ParserErrorCode.con3('EXTE
RNAL_CLASS', 40, "Classes cannot be declared to be 'external'"); |
| 7842 |
| 7843 static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = const ParserErro
rCode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 41, "External constructors cannot h
ave a body"); |
| 7844 |
| 7845 static const ParserErrorCode EXTERNAL_ENUM = const ParserErrorCode.con3('EXTER
NAL_ENUM', 42, "Enums cannot be declared to be 'external'"); |
| 7846 |
| 7847 static const ParserErrorCode EXTERNAL_FIELD = const ParserErrorCode.con3('EXTE
RNAL_FIELD', 43, "Fields cannot be declared to be 'external'"); |
| 7848 |
| 7849 static const ParserErrorCode EXTERNAL_GETTER_WITH_BODY = const ParserErrorCode
.con3('EXTERNAL_GETTER_WITH_BODY', 44, "External getters cannot have a body"); |
| 7850 |
| 7851 static const ParserErrorCode EXTERNAL_METHOD_WITH_BODY = const ParserErrorCode
.con3('EXTERNAL_METHOD_WITH_BODY', 45, "External methods cannot have a body"); |
| 7852 |
| 7853 static const ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = const ParserErrorCo
de.con3('EXTERNAL_OPERATOR_WITH_BODY', 46, "External operators cannot have a bod
y"); |
| 7854 |
| 7855 static const ParserErrorCode EXTERNAL_SETTER_WITH_BODY = const ParserErrorCode
.con3('EXTERNAL_SETTER_WITH_BODY', 47, "External setters cannot have a body"); |
| 7856 |
| 7857 static const ParserErrorCode EXTERNAL_TYPEDEF = const ParserErrorCode.con3('EX
TERNAL_TYPEDEF', 48, "Type aliases cannot be declared to be 'external'"); |
| 7858 |
| 7859 static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = const ParserError
Code.con3('FACTORY_TOP_LEVEL_DECLARATION', 49, "Top-level declarations cannot be
declared to be 'factory'"); |
| 7860 |
| 7861 static const ParserErrorCode FACTORY_WITHOUT_BODY = const ParserErrorCode.con3
('FACTORY_WITHOUT_BODY', 50, "A non-redirecting 'factory' constructor must have
a body"); |
| 7862 |
| 7863 static const ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = const Par
serErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 51, "Field initialize
rs can only be used in a constructor"); |
| 7864 |
| 7865 static const ParserErrorCode FINAL_AND_VAR = const ParserErrorCode.con3('FINAL
_AND_VAR', 52, "Members cannot be declared to be both 'final' and 'var'"); |
| 7866 |
| 7867 static const ParserErrorCode FINAL_CLASS = const ParserErrorCode.con3('FINAL_C
LASS', 53, "Classes cannot be declared to be 'final'"); |
| 7868 |
| 7869 static const ParserErrorCode FINAL_CONSTRUCTOR = const ParserErrorCode.con3('F
INAL_CONSTRUCTOR', 54, "A constructor cannot be declared to be 'final'"); |
| 7870 |
| 7871 static const ParserErrorCode FINAL_ENUM = const ParserErrorCode.con3('FINAL_EN
UM', 55, "Enums cannot be declared to be 'final'"); |
| 7872 |
| 7873 static const ParserErrorCode FINAL_METHOD = const ParserErrorCode.con3('FINAL_
METHOD', 56, "Getters, setters and methods cannot be declared to be 'final'"); |
| 7874 |
| 7875 static const ParserErrorCode FINAL_TYPEDEF = const ParserErrorCode.con3('FINAL
_TYPEDEF', 57, "Type aliases cannot be declared to be 'final'"); |
| 7876 |
| 7877 static const ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = const ParserErrorC
ode.con3('FUNCTION_TYPED_PARAMETER_VAR', 58, "Function typed parameters cannot s
pecify 'const', 'final' or 'var' instead of return type"); |
| 7878 |
| 7879 static const ParserErrorCode GETTER_IN_FUNCTION = const ParserErrorCode.con3('
GETTER_IN_FUNCTION', 59, "Getters cannot be defined within methods or functions"
); |
| 7880 |
| 7881 static const ParserErrorCode GETTER_WITH_PARAMETERS = const ParserErrorCode.co
n3('GETTER_WITH_PARAMETERS', 60, "Getter should be declared without a parameter
list"); |
| 7882 |
| 7883 static const ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = const Pars
erErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 61, "Illegal assignment
to non-assignable expression"); |
| 7884 |
| 7885 static const ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = const ParserErrorCode
.con3('IMPLEMENTS_BEFORE_EXTENDS', 62, "The extends clause must be before the im
plements clause"); |
| 7886 |
| 7887 static const ParserErrorCode IMPLEMENTS_BEFORE_WITH = const ParserErrorCode.co
n3('IMPLEMENTS_BEFORE_WITH', 63, "The with clause must be before the implements
clause"); |
| 7888 |
| 7889 static const ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = const Par
serErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 64, "Import directive
s must preceed part directives"); |
| 7890 |
| 7891 static const ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = const ParserEr
rorCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 65, "The loop variable in a for
-each loop cannot be initialized"); |
| 7892 |
| 7893 static const ParserErrorCode INVALID_AWAIT_IN_FOR = const ParserErrorCode.con4
('INVALID_AWAIT_IN_FOR', 66, "The modifier 'await' is not allowed for a normal '
for' statement", "Remove the keyword or use a for-each statement."); |
| 7894 |
| 7895 static const ParserErrorCode INVALID_CODE_POINT = const ParserErrorCode.con3('
INVALID_CODE_POINT', 67, "The escape sequence '{0}' is not a valid code point"); |
| 7896 |
| 7897 static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode
.con3('INVALID_COMMENT_REFERENCE', 68, "Comment references should contain a poss
ibly prefixed identifier and can start with 'new', but should not contain anythi
ng else"); |
| 7898 |
| 7899 static const ParserErrorCode INVALID_HEX_ESCAPE = const ParserErrorCode.con3('
INVALID_HEX_ESCAPE', 69, "An escape sequence starting with '\\x' must be followe
d by 2 hexidecimal digits"); |
| 7900 |
| 7901 static const ParserErrorCode INVALID_OPERATOR = const ParserErrorCode.con3('IN
VALID_OPERATOR', 70, "The string '{0}' is not a valid operator"); |
| 7902 |
| 7903 static const ParserErrorCode INVALID_OPERATOR_FOR_SUPER = const ParserErrorCod
e.con3('INVALID_OPERATOR_FOR_SUPER', 71, "The operator '{0}' cannot be used with
'super'"); |
| 7904 |
| 7905 static const ParserErrorCode INVALID_STAR_AFTER_ASYNC = const ParserErrorCode.
con4('INVALID_STAR_AFTER_ASYNC', 72, "The modifier 'async*' is not allowed for a
n expression function body", "Convert the body to a block."); |
| 7906 |
| 7907 static const ParserErrorCode INVALID_SYNC = const ParserErrorCode.con4('INVALI
D_SYNC', 73, "The modifier 'sync' is not allowed for an exrpression function bod
y", "Convert the body to a block."); |
| 7908 |
| 7909 static const ParserErrorCode INVALID_UNICODE_ESCAPE = const ParserErrorCode.co
n3('INVALID_UNICODE_ESCAPE', 74, "An escape sequence starting with '\\u' must be
followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'"); |
| 7910 |
| 7911 static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = const ParserErrorCo
de.con3('LIBRARY_DIRECTIVE_NOT_FIRST', 75, "The library directive must appear be
fore all other directives"); |
| 7912 |
| 7913 static const ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = const Parse
rErrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 76, "Local function decla
rations cannot specify any modifier"); |
| 7914 |
| 7915 static const ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = const ParserErrorCo
de.con3('MISSING_ASSIGNABLE_SELECTOR', 77, "Missing selector such as \".<identif
ier>\" or \"[0]\""); |
| 7916 |
| 7917 static const ParserErrorCode MISSING_CATCH_OR_FINALLY = const ParserErrorCode.
con3('MISSING_CATCH_OR_FINALLY', 78, "A try statement must have either a catch o
r finally clause"); |
| 7918 |
| 7919 static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode.con3('
MISSING_CLASS_BODY', 79, "A class definition must have a body, even if it is emp
ty"); |
| 7920 |
| 7921 static const ParserErrorCode MISSING_CLOSING_PARENTHESIS = const ParserErrorCo
de.con3('MISSING_CLOSING_PARENTHESIS', 80, "The closing parenthesis is missing")
; |
| 7922 |
| 7923 static const ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = const ParserErr
orCode.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 81, "Variables must be declared u
sing the keywords 'const', 'final', 'var' or a type name"); |
| 7924 |
| 7925 static const ParserErrorCode MISSING_ENUM_BODY = const ParserErrorCode.con3('M
ISSING_ENUM_BODY', 82, "An enum definition must have a body with at least one co
nstant name"); |
| 7926 |
| 7927 static const ParserErrorCode MISSING_EXPRESSION_IN_THROW = const ParserErrorCo
de.con3('MISSING_EXPRESSION_IN_THROW', 83, "Throw expressions must compute the o
bject to be thrown"); |
| 7928 |
| 7929 static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode.con
3('MISSING_FUNCTION_BODY', 84, "A function body must be provided"); |
| 7930 |
| 7931 static const ParserErrorCode MISSING_FUNCTION_PARAMETERS = const ParserErrorCo
de.con3('MISSING_FUNCTION_PARAMETERS', 85, "Functions must have an explicit list
of parameters"); |
| 7932 |
| 7933 static const ParserErrorCode MISSING_GET = const ParserErrorCode.con3('MISSING
_GET', 86, "Getters must have the keyword 'get' before the getter name"); |
| 7934 |
| 7935 static const ParserErrorCode MISSING_IDENTIFIER = const ParserErrorCode.con3('
MISSING_IDENTIFIER', 87, "Expected an identifier"); |
| 7936 |
| 7937 static const ParserErrorCode MISSING_KEYWORD_OPERATOR = const ParserErrorCode.
con3('MISSING_KEYWORD_OPERATOR', 88, "Operator declarations must be preceeded by
the keyword 'operator'"); |
| 7938 |
| 7939 static const ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = const ParserE
rrorCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 89, "Library directives must
include a library name"); |
| 7940 |
| 7941 static const ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = const ParserE
rrorCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 90, "Library directives must
include a library name"); |
| 7942 |
| 7943 static const ParserErrorCode MISSING_PREFIX_IN_DEFERRED_IMPORT = const ParserE
rrorCode.con3('MISSING_PREFIX_IN_DEFERRED_IMPORT', 91, "Deferred imports must ha
ve a prefix"); |
| 7944 |
| 7945 static const ParserErrorCode MISSING_STAR_AFTER_SYNC = const ParserErrorCode.c
on4('MISSING_STAR_AFTER_SYNC', 92, "The modifier 'sync' must be followed by a st
ar ('*')", "Remove the modifier or add a star."); |
| 7946 |
| 7947 static const ParserErrorCode MISSING_STATEMENT = const ParserErrorCode.con3('M
ISSING_STATEMENT', 93, "Expected a statement"); |
| 7948 |
| 7949 static const ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = const Pa
rserErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 94, "There is no '{
0}' to close the parameter group"); |
| 7950 |
| 7951 static const ParserErrorCode MISSING_TYPEDEF_PARAMETERS = const ParserErrorCod
e.con3('MISSING_TYPEDEF_PARAMETERS', 95, "Type aliases for functions must have a
n explicit list of parameters"); |
| 7952 |
| 7953 static const ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = const ParserErrorC
ode.con3('MISSING_VARIABLE_IN_FOR_EACH', 96, "A loop variable must be declared i
n a for-each loop before the 'in', but none were found"); |
| 7954 |
| 7955 static const ParserErrorCode MIXED_PARAMETER_GROUPS = const ParserErrorCode.co
n3('MIXED_PARAMETER_GROUPS', 97, "Cannot have both positional and named paramete
rs in a single parameter list"); |
| 7956 |
| 7957 static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = const ParserErrorCode.
con3('MULTIPLE_EXTENDS_CLAUSES', 98, "Each class definition can have at most one
extends clause"); |
| 7958 |
| 7959 static const ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = const ParserErrorCo
de.con3('MULTIPLE_IMPLEMENTS_CLAUSES', 99, "Each class definition can have at mo
st one implements clause"); |
| 7960 |
| 7961 static const ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = const ParserErrorCo
de.con3('MULTIPLE_LIBRARY_DIRECTIVES', 100, "Only one library directive may be d
eclared in a file"); |
| 7962 |
| 7963 static const ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = const ParserErr
orCode.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 101, "Cannot have multiple groups
of named parameters in a single parameter list"); |
| 7964 |
| 7965 static const ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = const ParserErrorCo
de.con3('MULTIPLE_PART_OF_DIRECTIVES', 102, "Only one part-of directive may be d
eclared in a file"); |
| 7966 |
| 7967 static const ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = const Pars
erErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 103, "Cannot have multi
ple groups of positional parameters in a single parameter list"); |
| 7968 |
| 7969 static const ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = const ParserErro
rCode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 104, "A single loop variable must b
e declared in a for-each loop before the 'in', but {0} were found"); |
| 7970 |
| 7971 static const ParserErrorCode MULTIPLE_WITH_CLAUSES = const ParserErrorCode.con
3('MULTIPLE_WITH_CLAUSES', 105, "Each class definition can have at most one with
clause"); |
| 7972 |
| 7973 static const ParserErrorCode NAMED_FUNCTION_EXPRESSION = const ParserErrorCode
.con3('NAMED_FUNCTION_EXPRESSION', 106, "Function expressions cannot be named"); |
| 7974 |
| 7975 static const ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = const ParserError
Code.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 107, "Named parameters must be enclos
ed in curly braces ('{' and '}')"); |
| 7976 |
| 7977 static const ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = const ParserError
Code.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 108, "Native clause can only be used
in the SDK and code that is loaded through native extensions"); |
| 7978 |
| 7979 static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = const Pars
erErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 109, "Native functions
can only be declared in the SDK and code that is loaded through native extension
s"); |
| 7980 |
| 7981 static const ParserErrorCode NON_CONSTRUCTOR_FACTORY = const ParserErrorCode.c
on3('NON_CONSTRUCTOR_FACTORY', 110, "Only constructors can be declared to be a '
factory'"); |
| 7982 |
| 7983 static const ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = const ParserErrorCo
de.con3('NON_IDENTIFIER_LIBRARY_NAME', 111, "The name of a library must be an id
entifier"); |
| 7984 |
| 7985 static const ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = const ParserError
Code.con3('NON_PART_OF_DIRECTIVE_IN_PART', 112, "The part-of directive must be t
he only directive in a part"); |
| 7986 |
| 7987 static const ParserErrorCode NON_USER_DEFINABLE_OPERATOR = const ParserErrorCo
de.con3('NON_USER_DEFINABLE_OPERATOR', 113, "The operator '{0}' is not user defi
nable"); |
| 7988 |
| 7989 static const ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = const ParserE
rrorCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 114, "Normal parameters must
occur before optional parameters"); |
| 7990 |
| 7991 static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = const ParserErr
orCode.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 115, "Positional arguments must o
ccur before named arguments"); |
| 7992 |
| 7993 static const ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = const Parser
ErrorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 116, "Positional parameters
must be enclosed in square brackets ('[' and ']')"); |
| 7994 |
| 7995 static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = const Pa
rserErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 117, "Only factory
constructor can specify '=' redirection."); |
| 7996 |
| 7997 static const ParserErrorCode SETTER_IN_FUNCTION = const ParserErrorCode.con3('
SETTER_IN_FUNCTION', 118, "Setters cannot be defined within methods or functions
"); |
| 7998 |
| 7999 static const ParserErrorCode STATIC_AFTER_CONST = const ParserErrorCode.con3('
STATIC_AFTER_CONST', 119, "The modifier 'static' should be before the modifier '
const'"); |
| 8000 |
| 8001 static const ParserErrorCode STATIC_AFTER_FINAL = const ParserErrorCode.con3('
STATIC_AFTER_FINAL', 120, "The modifier 'static' should be before the modifier '
final'"); |
| 8002 |
| 8003 static const ParserErrorCode STATIC_AFTER_VAR = const ParserErrorCode.con3('ST
ATIC_AFTER_VAR', 121, "The modifier 'static' should be before the modifier 'var'
"); |
| 8004 |
| 8005 static const ParserErrorCode STATIC_CONSTRUCTOR = const ParserErrorCode.con3('
STATIC_CONSTRUCTOR', 122, "Constructors cannot be static"); |
| 8006 |
| 8007 static const ParserErrorCode STATIC_GETTER_WITHOUT_BODY = const ParserErrorCod
e.con3('STATIC_GETTER_WITHOUT_BODY', 123, "A 'static' getter must have a body"); |
| 8008 |
| 8009 static const ParserErrorCode STATIC_OPERATOR = const ParserErrorCode.con3('STA
TIC_OPERATOR', 124, "Operators cannot be static"); |
| 8010 |
| 8011 static const ParserErrorCode STATIC_SETTER_WITHOUT_BODY = const ParserErrorCod
e.con3('STATIC_SETTER_WITHOUT_BODY', 125, "A 'static' setter must have a body"); |
| 8012 |
| 8013 static const ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = const ParserErrorC
ode.con3('STATIC_TOP_LEVEL_DECLARATION', 126, "Top-level declarations cannot be
declared to be 'static'"); |
| 8014 |
| 8015 static const ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = const Parser
ErrorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 127, "The 'default' case sh
ould be the last case in a switch statement"); |
| 8016 |
| 8017 static const ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = const ParserE
rrorCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 128, "The 'default' case can
only be declared once"); |
| 8018 |
| 8019 static const ParserErrorCode TOP_LEVEL_OPERATOR = const ParserErrorCode.con3('
TOP_LEVEL_OPERATOR', 129, "Operators must be declared within a class"); |
| 8020 |
| 8021 static const ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = const
ParserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 130, "There i
s no '{0}' to open a parameter group"); |
| 8022 |
| 8023 static const ParserErrorCode UNEXPECTED_TOKEN = const ParserErrorCode.con3('UN
EXPECTED_TOKEN', 131, "Unexpected token '{0}'"); |
| 8024 |
| 8025 static const ParserErrorCode WITH_BEFORE_EXTENDS = const ParserErrorCode.con3(
'WITH_BEFORE_EXTENDS', 132, "The extends clause must be before the with clause")
; |
| 8026 |
| 8027 static const ParserErrorCode WITH_WITHOUT_EXTENDS = const ParserErrorCode.con3
('WITH_WITHOUT_EXTENDS', 133, "The with clause cannot be used without an extends
clause"); |
| 8028 |
| 8029 static const ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = const Parse
rErrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 134, "The default value o
f a named parameter should be preceeded by ':'"); |
| 8030 |
| 8031 static const ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = const
ParserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 135, "The defau
lt value of a positional parameter should be preceeded by '='"); |
| 8032 |
| 8033 static const ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = const Pars
erErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 136, "Expected '{0}' to
close parameter group"); |
| 8034 |
| 8035 static const ParserErrorCode VAR_AND_TYPE = const ParserErrorCode.con3('VAR_AN
D_TYPE', 137, "Variables cannot be declared using both 'var' and a type name; re
move the 'var'"); |
| 8036 |
| 8037 static const ParserErrorCode VAR_AS_TYPE_NAME = const ParserErrorCode.con3('VA
R_AS_TYPE_NAME', 138, "The keyword 'var' cannot be used as a type name"); |
| 8038 |
| 8039 static const ParserErrorCode VAR_CLASS = const ParserErrorCode.con3('VAR_CLASS
', 139, "Classes cannot be declared to be 'var'"); |
| 8040 |
| 8041 static const ParserErrorCode VAR_ENUM = const ParserErrorCode.con3('VAR_ENUM',
140, "Enums cannot be declared to be 'var'"); |
| 8042 |
| 8043 static const ParserErrorCode VAR_RETURN_TYPE = const ParserErrorCode.con3('VAR
_RETURN_TYPE', 141, "The return type cannot be 'var'"); |
| 8044 |
| 8045 static const ParserErrorCode VAR_TYPEDEF = const ParserErrorCode.con3('VAR_TYP
EDEF', 142, "Type aliases cannot be declared to be 'var'"); |
| 8046 |
| 8047 static const ParserErrorCode VOID_PARAMETER = const ParserErrorCode.con3('VOID
_PARAMETER', 143, "Parameters cannot have a type of 'void'"); |
| 8048 |
| 8049 static const ParserErrorCode VOID_VARIABLE = const ParserErrorCode.con3('VOID_
VARIABLE', 144, "Variables cannot have a type of 'void'"); |
| 8050 |
| 8051 static const List<ParserErrorCode> values = const [ |
| 8052 ABSTRACT_CLASS_MEMBER, |
| 8053 ABSTRACT_ENUM, |
| 8054 ABSTRACT_STATIC_METHOD, |
| 8055 ABSTRACT_TOP_LEVEL_FUNCTION, |
| 8056 ABSTRACT_TOP_LEVEL_VARIABLE, |
| 8057 ABSTRACT_TYPEDEF, |
| 8058 ASSERT_DOES_NOT_TAKE_ASSIGNMENT, |
| 8059 ASSERT_DOES_NOT_TAKE_CASCADE, |
| 8060 ASSERT_DOES_NOT_TAKE_THROW, |
| 8061 ASSERT_DOES_NOT_TAKE_RETHROW, |
| 8062 BREAK_OUTSIDE_OF_LOOP, |
| 8063 CONST_AND_FINAL, |
| 8064 CONST_AND_VAR, |
| 8065 CONST_CLASS, |
| 8066 CONST_CONSTRUCTOR_WITH_BODY, |
| 8067 CONST_ENUM, |
| 8068 CONST_FACTORY, |
| 8069 CONST_METHOD, |
| 8070 CONST_TYPEDEF, |
| 8071 CONSTRUCTOR_WITH_RETURN_TYPE, |
| 8072 CONTINUE_OUTSIDE_OF_LOOP, |
| 8073 CONTINUE_WITHOUT_LABEL_IN_CASE, |
| 8074 DEFERRED_IMPORTS_NOT_SUPPORTED, |
| 8075 DEPRECATED_CLASS_TYPE_ALIAS, |
| 8076 DIRECTIVE_AFTER_DECLARATION, |
| 8077 DUPLICATE_LABEL_IN_SWITCH_STATEMENT, |
| 8078 DUPLICATED_MODIFIER, |
| 8079 EMPTY_ENUM_BODY, |
| 8080 EQUALITY_CANNOT_BE_EQUALITY_OPERAND, |
| 8081 EXPECTED_CASE_OR_DEFAULT, |
| 8082 EXPECTED_CLASS_MEMBER, |
| 8083 EXPECTED_EXECUTABLE, |
| 8084 EXPECTED_LIST_OR_MAP_LITERAL, |
| 8085 EXPECTED_STRING_LITERAL, |
| 8086 EXPECTED_TOKEN, |
| 8087 EXPECTED_TYPE_NAME, |
| 8088 EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, |
| 8089 EXTERNAL_AFTER_CONST, |
| 8090 EXTERNAL_AFTER_FACTORY, |
| 8091 EXTERNAL_AFTER_STATIC, |
| 8092 EXTERNAL_CLASS, |
| 8093 EXTERNAL_CONSTRUCTOR_WITH_BODY, |
| 8094 EXTERNAL_ENUM, |
| 8095 EXTERNAL_FIELD, |
| 8096 EXTERNAL_GETTER_WITH_BODY, |
| 8097 EXTERNAL_METHOD_WITH_BODY, |
| 8098 EXTERNAL_OPERATOR_WITH_BODY, |
| 8099 EXTERNAL_SETTER_WITH_BODY, |
| 8100 EXTERNAL_TYPEDEF, |
| 8101 FACTORY_TOP_LEVEL_DECLARATION, |
| 8102 FACTORY_WITHOUT_BODY, |
| 8103 FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, |
| 8104 FINAL_AND_VAR, |
| 8105 FINAL_CLASS, |
| 8106 FINAL_CONSTRUCTOR, |
| 8107 FINAL_ENUM, |
| 8108 FINAL_METHOD, |
| 8109 FINAL_TYPEDEF, |
| 8110 FUNCTION_TYPED_PARAMETER_VAR, |
| 8111 GETTER_IN_FUNCTION, |
| 8112 GETTER_WITH_PARAMETERS, |
| 8113 ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, |
| 8114 IMPLEMENTS_BEFORE_EXTENDS, |
| 8115 IMPLEMENTS_BEFORE_WITH, |
| 8116 IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, |
| 8117 INITIALIZED_VARIABLE_IN_FOR_EACH, |
| 8118 INVALID_AWAIT_IN_FOR, |
| 8119 INVALID_CODE_POINT, |
| 8120 INVALID_COMMENT_REFERENCE, |
| 8121 INVALID_HEX_ESCAPE, |
| 8122 INVALID_OPERATOR, |
| 8123 INVALID_OPERATOR_FOR_SUPER, |
| 8124 INVALID_STAR_AFTER_ASYNC, |
| 8125 INVALID_SYNC, |
| 8126 INVALID_UNICODE_ESCAPE, |
| 8127 LIBRARY_DIRECTIVE_NOT_FIRST, |
| 8128 LOCAL_FUNCTION_DECLARATION_MODIFIER, |
| 8129 MISSING_ASSIGNABLE_SELECTOR, |
| 8130 MISSING_CATCH_OR_FINALLY, |
| 8131 MISSING_CLASS_BODY, |
| 8132 MISSING_CLOSING_PARENTHESIS, |
| 8133 MISSING_CONST_FINAL_VAR_OR_TYPE, |
| 8134 MISSING_ENUM_BODY, |
| 8135 MISSING_EXPRESSION_IN_THROW, |
| 8136 MISSING_FUNCTION_BODY, |
| 8137 MISSING_FUNCTION_PARAMETERS, |
| 8138 MISSING_GET, |
| 8139 MISSING_IDENTIFIER, |
| 8140 MISSING_KEYWORD_OPERATOR, |
| 8141 MISSING_NAME_IN_LIBRARY_DIRECTIVE, |
| 8142 MISSING_NAME_IN_PART_OF_DIRECTIVE, |
| 8143 MISSING_PREFIX_IN_DEFERRED_IMPORT, |
| 8144 MISSING_STAR_AFTER_SYNC, |
| 8145 MISSING_STATEMENT, |
| 8146 MISSING_TERMINATOR_FOR_PARAMETER_GROUP, |
| 8147 MISSING_TYPEDEF_PARAMETERS, |
| 8148 MISSING_VARIABLE_IN_FOR_EACH, |
| 8149 MIXED_PARAMETER_GROUPS, |
| 8150 MULTIPLE_EXTENDS_CLAUSES, |
| 8151 MULTIPLE_IMPLEMENTS_CLAUSES, |
| 8152 MULTIPLE_LIBRARY_DIRECTIVES, |
| 8153 MULTIPLE_NAMED_PARAMETER_GROUPS, |
| 8154 MULTIPLE_PART_OF_DIRECTIVES, |
| 8155 MULTIPLE_POSITIONAL_PARAMETER_GROUPS, |
| 8156 MULTIPLE_VARIABLES_IN_FOR_EACH, |
| 8157 MULTIPLE_WITH_CLAUSES, |
| 8158 NAMED_FUNCTION_EXPRESSION, |
| 8159 NAMED_PARAMETER_OUTSIDE_GROUP, |
| 8160 NATIVE_CLAUSE_IN_NON_SDK_CODE, |
| 8161 NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, |
| 8162 NON_CONSTRUCTOR_FACTORY, |
| 8163 NON_IDENTIFIER_LIBRARY_NAME, |
| 8164 NON_PART_OF_DIRECTIVE_IN_PART, |
| 8165 NON_USER_DEFINABLE_OPERATOR, |
| 8166 NORMAL_BEFORE_OPTIONAL_PARAMETERS, |
| 8167 POSITIONAL_AFTER_NAMED_ARGUMENT, |
| 8168 POSITIONAL_PARAMETER_OUTSIDE_GROUP, |
| 8169 REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, |
| 8170 SETTER_IN_FUNCTION, |
| 8171 STATIC_AFTER_CONST, |
| 8172 STATIC_AFTER_FINAL, |
| 8173 STATIC_AFTER_VAR, |
| 8174 STATIC_CONSTRUCTOR, |
| 8175 STATIC_GETTER_WITHOUT_BODY, |
| 8176 STATIC_OPERATOR, |
| 8177 STATIC_SETTER_WITHOUT_BODY, |
| 8178 STATIC_TOP_LEVEL_DECLARATION, |
| 8179 SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, |
| 8180 SWITCH_HAS_MULTIPLE_DEFAULT_CASES, |
| 8181 TOP_LEVEL_OPERATOR, |
| 8182 UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, |
| 8183 UNEXPECTED_TOKEN, |
| 8184 WITH_BEFORE_EXTENDS, |
| 8185 WITH_WITHOUT_EXTENDS, |
| 8186 WRONG_SEPARATOR_FOR_NAMED_PARAMETER, |
| 8187 WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, |
| 8188 WRONG_TERMINATOR_FOR_PARAMETER_GROUP, |
| 8189 VAR_AND_TYPE, |
| 8190 VAR_AS_TYPE_NAME, |
| 8191 VAR_CLASS, |
| 8192 VAR_ENUM, |
| 8193 VAR_RETURN_TYPE, |
| 8194 VAR_TYPEDEF, |
| 8195 VOID_PARAMETER, |
| 8196 VOID_VARIABLE]; |
| 8197 |
| 8198 /** |
| 8199 * The severity of this error. |
| 8200 */ |
| 8201 final ErrorSeverity errorSeverity; |
| 8202 |
| 8203 /** |
| 8204 * The template used to create the message to be displayed for this error. |
| 8205 */ |
| 8206 final String message; |
| 8207 |
| 8208 /** |
| 8209 * The template used to create the correction to be displayed for this error,
or `null` if |
| 8210 * there is no correction information for this error. |
| 8211 */ |
| 8212 final String correction; |
| 8213 |
| 8214 /** |
| 8215 * Initialize a newly created error code to have the given severity and messag
e. |
| 8216 * |
| 8217 * @param errorSeverity the severity of the error |
| 8218 * @param message the message template used to create the message to be displa
yed for the error |
| 8219 */ |
| 8220 const ParserErrorCode.con1(String name, int ordinal, ErrorSeverity errorSeveri
ty, String message) : this.con2(name, ordinal, errorSeverity, message, null); |
| 8221 |
| 8222 /** |
| 8223 * Initialize a newly created error code to have the given severity, message a
nd correction. |
| 8224 * |
| 8225 * @param errorSeverity the severity of the error |
| 8226 * @param message the template used to create the message to be displayed for
the error |
| 8227 * @param correction the template used to create the correction to be displaye
d for the error |
| 8228 */ |
| 8229 const ParserErrorCode.con2(String name, int ordinal, this.errorSeverity, this.
message, this.correction) : super(name, ordinal); |
| 8230 |
| 8231 /** |
| 8232 * Initialize a newly created error code to have the given message and a sever
ity of ERROR. |
| 8233 * |
| 8234 * @param message the message template used to create the message to be displa
yed for the error |
| 8235 */ |
| 8236 const ParserErrorCode.con3(String name, int ordinal, String message) : this.co
n2(name, ordinal, ErrorSeverity.ERROR, message, null); |
| 8237 |
| 8238 /** |
| 8239 * Initialize a newly created error code to have the given message and a sever
ity of ERROR. |
| 8240 * |
| 8241 * @param message the message template used to create the message to be displa
yed for the error |
| 8242 * @param correction the template used to create the correction to be displaye
d for the error |
| 8243 */ |
| 8244 const ParserErrorCode.con4(String name, int ordinal, String message, String co
rrection) : this.con2(name, ordinal, ErrorSeverity.ERROR, message, correction); |
| 8245 |
| 8246 @override |
| 8247 ErrorType get type => ErrorType.SYNTACTIC_ERROR; |
| 8248 |
| 8249 @override |
| 8250 String get uniqueName => "${runtimeType.toString()}.${name}"; |
| 8251 } |
| 8252 |
| 8253 /** |
| 8254 * Instances of the class `SyntheticKeywordToken` implement a synthetic keyword
token. |
| 8255 */ |
| 8256 class Parser_SyntheticKeywordToken extends KeywordToken { |
| 8257 /** |
| 8258 * Initialize a newly created token to represent the given keyword. |
| 8259 * |
| 8260 * @param keyword the keyword being represented by this token |
| 8261 * @param offset the offset from the beginning of the file to the first charac
ter in the token |
| 8262 */ |
| 8263 Parser_SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, off
set); |
| 8264 |
| 8265 @override |
| 8266 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset); |
| 8267 |
| 8268 @override |
| 8269 int get length => 0; |
| 8270 } |
| 8271 |
| 8272 /** |
| 8273 * Instances of the class `ResolutionCopier` copies resolution information from
one AST |
| 8274 * structure to another as long as the structures of the corresponding children
of a pair of nodes |
| 8275 * are the same. |
| 8276 */ |
| 8277 class ResolutionCopier implements AstVisitor<bool> { |
| 8278 /** |
| 8279 * Copy resolution data from one node to another. |
| 8280 * |
| 8281 * @param fromNode the node from which resolution information will be copied |
| 8282 * @param toNode the node to which resolution information will be copied |
| 8283 */ |
| 8284 static void copyResolutionData(AstNode fromNode, AstNode toNode) { |
| 8285 ResolutionCopier copier = new ResolutionCopier(); |
| 8286 copier._isEqualNodes(fromNode, toNode); |
| 8287 } |
| 8288 |
| 8289 /** |
| 8290 * The AST node with which the node being visited is to be compared. This is o
nly valid at the |
| 8291 * beginning of each visit method (until [isEqualNodes] is invoked). |
| 8292 */ |
| 8293 AstNode _toNode; |
| 8294 |
| 8295 @override |
| 8296 bool visitAdjacentStrings(AdjacentStrings node) { |
| 8297 AdjacentStrings toNode = this._toNode as AdjacentStrings; |
| 8298 return _isEqualNodeLists(node.strings, toNode.strings); |
| 8299 } |
| 8300 |
| 8301 @override |
| 8302 bool visitAnnotation(Annotation node) { |
| 8303 Annotation toNode = this._toNode as Annotation; |
| 8304 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke
ns(node.atSign, toNode.atSign), _isEqualNodes(node.name, toNode.name)), _isEqual
Tokens(node.period, toNode.period)), _isEqualNodes(node.constructorName, toNode.
constructorName)), _isEqualNodes(node.arguments, toNode.arguments))) { |
| 8305 toNode.element = node.element; |
| 8306 return true; |
| 8307 } |
| 8308 return false; |
| 8309 } |
| 8310 |
| 8311 @override |
| 8312 bool visitArgumentList(ArgumentList node) { |
| 8313 ArgumentList toNode = this._toNode as ArgumentList; |
| 8314 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftParenthesis, to
Node.leftParenthesis), _isEqualNodeLists(node.arguments, toNode.arguments)), _is
EqualTokens(node.rightParenthesis, toNode.rightParenthesis)); |
| 8315 } |
| 8316 |
| 8317 @override |
| 8318 bool visitAsExpression(AsExpression node) { |
| 8319 AsExpression toNode = this._toNode as AsExpression; |
| 8320 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.expression, toNode.expr
ession), _isEqualTokens(node.asOperator, toNode.asOperator)), _isEqualNodes(node
.type, toNode.type))) { |
| 8321 toNode.propagatedType = node.propagatedType; |
| 8322 toNode.staticType = node.staticType; |
| 8323 return true; |
| 8324 } |
| 8325 return false; |
| 8326 } |
| 8327 |
| 8328 @override |
| 8329 bool visitAssertStatement(AssertStatement node) { |
| 8330 AssertStatement toNode = this._toNode as AssertStatement; |
| 8331 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT
okens(node.keyword, toNode.keyword), _isEqualTokens(node.leftParenthesis, toNode
.leftParenthesis)), _isEqualNodes(node.condition, toNode.condition)), _isEqualTo
kens(node.rightParenthesis, toNode.rightParenthesis)), _isEqualTokens(node.semic
olon, toNode.semicolon)); |
| 8332 } |
| 8333 |
| 8334 @override |
| 8335 bool visitAssignmentExpression(AssignmentExpression node) { |
| 8336 AssignmentExpression toNode = this._toNode as AssignmentExpression; |
| 8337 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.leftHandSide, toNode.le
ftHandSide), _isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node
.rightHandSide, toNode.rightHandSide))) { |
| 8338 toNode.propagatedElement = node.propagatedElement; |
| 8339 toNode.propagatedType = node.propagatedType; |
| 8340 toNode.staticElement = node.staticElement; |
| 8341 toNode.staticType = node.staticType; |
| 8342 return true; |
| 8343 } |
| 8344 return false; |
| 8345 } |
| 8346 |
| 8347 @override |
| 8348 bool visitAwaitExpression(AwaitExpression node) { |
| 8349 AwaitExpression toNode = this._toNode as AwaitExpression; |
| 8350 return javaBooleanAnd(_isEqualTokens(node.awaitKeyword, toNode.awaitKeyword)
, _isEqualNodes(node.expression, toNode.expression)); |
| 8351 } |
| 8352 |
| 8353 @override |
| 8354 bool visitBinaryExpression(BinaryExpression node) { |
| 8355 BinaryExpression toNode = this._toNode as BinaryExpression; |
| 8356 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.leftOperand, toNode.lef
tOperand), _isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node.r
ightOperand, toNode.rightOperand))) { |
| 8357 toNode.propagatedElement = node.propagatedElement; |
| 8358 toNode.propagatedType = node.propagatedType; |
| 8359 toNode.staticElement = node.staticElement; |
| 8360 toNode.staticType = node.staticType; |
| 8361 return true; |
| 8362 } |
| 8363 return false; |
| 8364 } |
| 8365 |
| 8366 @override |
| 8367 bool visitBlock(Block node) { |
| 8368 Block toNode = this._toNode as Block; |
| 8369 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode
.leftBracket), _isEqualNodeLists(node.statements, toNode.statements)), _isEqualT
okens(node.rightBracket, toNode.rightBracket)); |
| 8370 } |
| 8371 |
| 8372 @override |
| 8373 bool visitBlockFunctionBody(BlockFunctionBody node) { |
| 8374 BlockFunctionBody toNode = this._toNode as BlockFunctionBody; |
| 8375 return _isEqualNodes(node.block, toNode.block); |
| 8376 } |
| 8377 |
| 8378 @override |
| 8379 bool visitBooleanLiteral(BooleanLiteral node) { |
| 8380 BooleanLiteral toNode = this._toNode as BooleanLiteral; |
| 8381 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), node.value
== toNode.value)) { |
| 8382 toNode.propagatedType = node.propagatedType; |
| 8383 toNode.staticType = node.staticType; |
| 8384 return true; |
| 8385 } |
| 8386 return false; |
| 8387 } |
| 8388 |
| 8389 @override |
| 8390 bool visitBreakStatement(BreakStatement node) { |
| 8391 BreakStatement toNode = this._toNode as BreakStatement; |
| 8392 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key
word), _isEqualNodes(node.label, toNode.label)), _isEqualTokens(node.semicolon,
toNode.semicolon)); |
| 8393 } |
| 8394 |
| 8395 @override |
| 8396 bool visitCascadeExpression(CascadeExpression node) { |
| 8397 CascadeExpression toNode = this._toNode as CascadeExpression; |
| 8398 if (javaBooleanAnd(_isEqualNodes(node.target, toNode.target), _isEqualNodeLi
sts(node.cascadeSections, toNode.cascadeSections))) { |
| 8399 toNode.propagatedType = node.propagatedType; |
| 8400 toNode.staticType = node.staticType; |
| 8401 return true; |
| 8402 } |
| 8403 return false; |
| 8404 } |
| 8405 |
| 8406 @override |
| 8407 bool visitCatchClause(CatchClause node) { |
| 8408 CatchClause toNode = this._toNode as CatchClause; |
| 8409 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.onKeyword
, toNode.onKeyword), _isEqualNodes(node.exceptionType, toNode.exceptionType)), _
isEqualTokens(node.catchKeyword, toNode.catchKeyword)), _isEqualTokens(node.left
Parenthesis, toNode.leftParenthesis)), _isEqualNodes(node.exceptionParameter, to
Node.exceptionParameter)), _isEqualTokens(node.comma, toNode.comma)), _isEqualNo
des(node.stackTraceParameter, toNode.stackTraceParameter)), _isEqualTokens(node.
rightParenthesis, toNode.rightParenthesis)), _isEqualNodes(node.body, toNode.bod
y)); |
| 8410 } |
| 8411 |
| 8412 @override |
| 8413 bool visitClassDeclaration(ClassDeclaration node) { |
| 8414 ClassDeclaration toNode = this._toNode as ClassDeclaration; |
| 8415 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd
(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentationCom
ment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.a
bstractKeyword, toNode.abstractKeyword)), _isEqualTokens(node.classKeyword, toNo
de.classKeyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.ty
peParameters, toNode.typeParameters)), _isEqualNodes(node.extendsClause, toNode.
extendsClause)), _isEqualNodes(node.withClause, toNode.withClause)), _isEqualNod
es(node.implementsClause, toNode.implementsClause)), _isEqualTokens(node.leftBra
cket, toNode.leftBracket)), _isEqualNodeLists(node.members, toNode.members)), _i
sEqualTokens(node.rightBracket, toNode.rightBracket)); |
| 8416 } |
| 8417 |
| 8418 @override |
| 8419 bool visitClassTypeAlias(ClassTypeAlias node) { |
| 8420 ClassTypeAlias toNode = this._toNode as ClassTypeAlias; |
| 8421 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd
(_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqual
NodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.
keyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.typeParame
ters, toNode.typeParameters)), _isEqualTokens(node.equals, toNode.equals)), _isE
qualTokens(node.abstractKeyword, toNode.abstractKeyword)), _isEqualNodes(node.su
perclass, toNode.superclass)), _isEqualNodes(node.withClause, toNode.withClause)
), _isEqualNodes(node.implementsClause, toNode.implementsClause)), _isEqualToken
s(node.semicolon, toNode.semicolon)); |
| 8422 } |
| 8423 |
| 8424 @override |
| 8425 bool visitComment(Comment node) { |
| 8426 Comment toNode = this._toNode as Comment; |
| 8427 return _isEqualNodeLists(node.references, toNode.references); |
| 8428 } |
| 8429 |
| 8430 @override |
| 8431 bool visitCommentReference(CommentReference node) { |
| 8432 CommentReference toNode = this._toNode as CommentReference; |
| 8433 return javaBooleanAnd(_isEqualTokens(node.newKeyword, toNode.newKeyword), _i
sEqualNodes(node.identifier, toNode.identifier)); |
| 8434 } |
| 8435 |
| 8436 @override |
| 8437 bool visitCompilationUnit(CompilationUnit node) { |
| 8438 CompilationUnit toNode = this._toNode as CompilationUnit; |
| 8439 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke
ns(node.beginToken, toNode.beginToken), _isEqualNodes(node.scriptTag, toNode.scr
iptTag)), _isEqualNodeLists(node.directives, toNode.directives)), _isEqualNodeLi
sts(node.declarations, toNode.declarations)), _isEqualTokens(node.endToken, toNo
de.endToken))) { |
| 8440 toNode.element = node.element; |
| 8441 return true; |
| 8442 } |
| 8443 return false; |
| 8444 } |
| 8445 |
| 8446 @override |
| 8447 bool visitConditionalExpression(ConditionalExpression node) { |
| 8448 ConditionalExpression toNode = this._toNode as ConditionalExpression; |
| 8449 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNode
s(node.condition, toNode.condition), _isEqualTokens(node.question, toNode.questi
on)), _isEqualNodes(node.thenExpression, toNode.thenExpression)), _isEqualTokens
(node.colon, toNode.colon)), _isEqualNodes(node.elseExpression, toNode.elseExpre
ssion))) { |
| 8450 toNode.propagatedType = node.propagatedType; |
| 8451 toNode.staticType = node.staticType; |
| 8452 return true; |
| 8453 } |
| 8454 return false; |
| 8455 } |
| 8456 |
| 8457 @override |
| 8458 bool visitConstructorDeclaration(ConstructorDeclaration node) { |
| 8459 ConstructorDeclaration toNode = this._toNode as ConstructorDeclaration; |
| 8460 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA
nd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(ja
vaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.docu
mentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualT
okens(node.externalKeyword, toNode.externalKeyword)), _isEqualTokens(node.constK
eyword, toNode.constKeyword)), _isEqualTokens(node.factoryKeyword, toNode.factor
yKeyword)), _isEqualNodes(node.returnType, toNode.returnType)), _isEqualTokens(n
ode.period, toNode.period)), _isEqualNodes(node.name, toNode.name)), _isEqualNod
es(node.parameters, toNode.parameters)), _isEqualTokens(node.separator, toNode.s
eparator)), _isEqualNodeLists(node.initializers, toNode.initializers)), _isEqual
Nodes(node.redirectedConstructor, toNode.redirectedConstructor)), _isEqualNodes(
node.body, toNode.body))) { |
| 8461 toNode.element = node.element; |
| 8462 return true; |
| 8463 } |
| 8464 return false; |
| 8465 } |
| 8466 |
| 8467 @override |
| 8468 bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 8469 ConstructorFieldInitializer toNode = this._toNode as ConstructorFieldInitial
izer; |
| 8470 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT
okens(node.keyword, toNode.keyword), _isEqualTokens(node.period, toNode.period))
, _isEqualNodes(node.fieldName, toNode.fieldName)), _isEqualTokens(node.equals,
toNode.equals)), _isEqualNodes(node.expression, toNode.expression)); |
| 8471 } |
| 8472 |
| 8473 @override |
| 8474 bool visitConstructorName(ConstructorName node) { |
| 8475 ConstructorName toNode = this._toNode as ConstructorName; |
| 8476 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.type, toNode.type), _is
EqualTokens(node.period, toNode.period)), _isEqualNodes(node.name, toNode.name))
) { |
| 8477 toNode.staticElement = node.staticElement; |
| 8478 return true; |
| 8479 } |
| 8480 return false; |
| 8481 } |
| 8482 |
| 8483 @override |
| 8484 bool visitContinueStatement(ContinueStatement node) { |
| 8485 ContinueStatement toNode = this._toNode as ContinueStatement; |
| 8486 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key
word), _isEqualNodes(node.label, toNode.label)), _isEqualTokens(node.semicolon,
toNode.semicolon)); |
| 8487 } |
| 8488 |
| 8489 @override |
| 8490 bool visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 8491 DeclaredIdentifier toNode = this._toNode as DeclaredIdentifier; |
| 8492 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)),
_isEqualNodes(node.type, toNode.type)), _isEqualNodes(node.identifier, toNode.i
dentifier)); |
| 8493 } |
| 8494 |
| 8495 @override |
| 8496 bool visitDefaultFormalParameter(DefaultFormalParameter node) { |
| 8497 DefaultFormalParameter toNode = this._toNode as DefaultFormalParameter; |
| 8498 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.param
eter, toNode.parameter), node.kind == toNode.kind), _isEqualTokens(node.separato
r, toNode.separator)), _isEqualNodes(node.defaultValue, toNode.defaultValue)); |
| 8499 } |
| 8500 |
| 8501 @override |
| 8502 bool visitDoStatement(DoStatement node) { |
| 8503 DoStatement toNode = this._toNode as DoStatement; |
| 8504 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualTokens(node.doKeyword, toNode.doKeyword), _isEqualN
odes(node.body, toNode.body)), _isEqualTokens(node.whileKeyword, toNode.whileKey
word)), _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualN
odes(node.condition, toNode.condition)), _isEqualTokens(node.rightParenthesis, t
oNode.rightParenthesis)), _isEqualTokens(node.semicolon, toNode.semicolon)); |
| 8505 } |
| 8506 |
| 8507 @override |
| 8508 bool visitDoubleLiteral(DoubleLiteral node) { |
| 8509 DoubleLiteral toNode = this._toNode as DoubleLiteral; |
| 8510 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), node.value
== toNode.value)) { |
| 8511 toNode.propagatedType = node.propagatedType; |
| 8512 toNode.staticType = node.staticType; |
| 8513 return true; |
| 8514 } |
| 8515 return false; |
| 8516 } |
| 8517 |
| 8518 @override |
| 8519 bool visitEmptyFunctionBody(EmptyFunctionBody node) { |
| 8520 EmptyFunctionBody toNode = this._toNode as EmptyFunctionBody; |
| 8521 return _isEqualTokens(node.semicolon, toNode.semicolon); |
| 8522 } |
| 8523 |
| 8524 @override |
| 8525 bool visitEmptyStatement(EmptyStatement node) { |
| 8526 EmptyStatement toNode = this._toNode as EmptyStatement; |
| 8527 return _isEqualTokens(node.semicolon, toNode.semicolon); |
| 8528 } |
| 8529 |
| 8530 @override |
| 8531 bool visitEnumConstantDeclaration(EnumConstantDeclaration node) { |
| 8532 EnumConstantDeclaration toNode = this._toNode as EnumConstantDeclaration; |
| 8533 return javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment
, toNode.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata
)), _isEqualNodes(node.name, toNode.name)); |
| 8534 } |
| 8535 |
| 8536 @override |
| 8537 bool visitEnumDeclaration(EnumDeclaration node) { |
| 8538 EnumDeclaration toNode = this._toNode as EnumDeclaration; |
| 8539 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati
onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n
ode.keyword, toNode.keyword)), _isEqualNodes(node.name, toNode.name)), _isEqualT
okens(node.leftBracket, toNode.leftBracket)), _isEqualNodeLists(node.constants,
toNode.constants)), _isEqualTokens(node.rightBracket, toNode.rightBracket)); |
| 8540 } |
| 8541 |
| 8542 @override |
| 8543 bool visitExportDirective(ExportDirective node) { |
| 8544 ExportDirective toNode = this._toNode as ExportDirective; |
| 8545 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA
nd(_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqu
alNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNod
e.keyword)), _isEqualNodes(node.uri, toNode.uri)), _isEqualNodeLists(node.combin
ators, toNode.combinators)), _isEqualTokens(node.semicolon, toNode.semicolon)))
{ |
| 8546 toNode.element = node.element; |
| 8547 return true; |
| 8548 } |
| 8549 return false; |
| 8550 } |
| 8551 |
| 8552 @override |
| 8553 bool visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 8554 ExpressionFunctionBody toNode = this._toNode as ExpressionFunctionBody; |
| 8555 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.functionDefinition,
toNode.functionDefinition), _isEqualNodes(node.expression, toNode.expression)),
_isEqualTokens(node.semicolon, toNode.semicolon)); |
| 8556 } |
| 8557 |
| 8558 @override |
| 8559 bool visitExpressionStatement(ExpressionStatement node) { |
| 8560 ExpressionStatement toNode = this._toNode as ExpressionStatement; |
| 8561 return javaBooleanAnd(_isEqualNodes(node.expression, toNode.expression), _is
EqualTokens(node.semicolon, toNode.semicolon)); |
| 8562 } |
| 8563 |
| 8564 @override |
| 8565 bool visitExtendsClause(ExtendsClause node) { |
| 8566 ExtendsClause toNode = this._toNode as ExtendsClause; |
| 8567 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual
Nodes(node.superclass, toNode.superclass)); |
| 8568 } |
| 8569 |
| 8570 @override |
| 8571 bool visitFieldDeclaration(FieldDeclaration node) { |
| 8572 FieldDeclaration toNode = this._toNode as FieldDeclaration; |
| 8573 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualTokens(node.staticKeyword, toNode.stat
icKeyword)), _isEqualNodes(node.fields, toNode.fields)), _isEqualTokens(node.sem
icolon, toNode.semicolon)); |
| 8574 } |
| 8575 |
| 8576 @override |
| 8577 bool visitFieldFormalParameter(FieldFormalParameter node) { |
| 8578 FieldFormalParameter toNode = this._toNode as FieldFormalParameter; |
| 8579 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati
onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n
ode.keyword, toNode.keyword)), _isEqualNodes(node.type, toNode.type)), _isEqualT
okens(node.thisToken, toNode.thisToken)), _isEqualTokens(node.period, toNode.per
iod)), _isEqualNodes(node.identifier, toNode.identifier)); |
| 8580 } |
| 8581 |
| 8582 @override |
| 8583 bool visitForEachStatement(ForEachStatement node) { |
| 8584 ForEachStatement toNode = this._toNode as ForEachStatement; |
| 8585 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualTokens(node.forKeyword, toNode.forKeyword), _isEqua
lTokens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.loopV
ariable, toNode.loopVariable)), _isEqualTokens(node.inKeyword, toNode.inKeyword)
), _isEqualNodes(node.iterator, toNode.iterator)), _isEqualTokens(node.rightPare
nthesis, toNode.rightParenthesis)), _isEqualNodes(node.body, toNode.body)); |
| 8586 } |
| 8587 |
| 8588 @override |
| 8589 bool visitFormalParameterList(FormalParameterList node) { |
| 8590 FormalParameterList toNode = this._toNode as FormalParameterList; |
| 8591 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT
okens(node.leftParenthesis, toNode.leftParenthesis), _isEqualNodeLists(node.para
meters, toNode.parameters)), _isEqualTokens(node.leftDelimiter, toNode.leftDelim
iter)), _isEqualTokens(node.rightDelimiter, toNode.rightDelimiter)), _isEqualTok
ens(node.rightParenthesis, toNode.rightParenthesis)); |
| 8592 } |
| 8593 |
| 8594 @override |
| 8595 bool visitForStatement(ForStatement node) { |
| 8596 ForStatement toNode = this._toNode as ForStatement; |
| 8597 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens
(node.forKeyword, toNode.forKeyword), _isEqualTokens(node.leftParenthesis, toNod
e.leftParenthesis)), _isEqualNodes(node.variables, toNode.variables)), _isEqualN
odes(node.initialization, toNode.initialization)), _isEqualTokens(node.leftSepar
ator, toNode.leftSeparator)), _isEqualNodes(node.condition, toNode.condition)),
_isEqualTokens(node.rightSeparator, toNode.rightSeparator)), _isEqualNodeLists(n
ode.updaters, toNode.updaters)), _isEqualTokens(node.rightParenthesis, toNode.ri
ghtParenthesis)), _isEqualNodes(node.body, toNode.body)); |
| 8598 } |
| 8599 |
| 8600 @override |
| 8601 bool visitFunctionDeclaration(FunctionDeclaration node) { |
| 8602 FunctionDeclaration toNode = this._toNode as FunctionDeclaration; |
| 8603 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati
onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n
ode.externalKeyword, toNode.externalKeyword)), _isEqualNodes(node.returnType, to
Node.returnType)), _isEqualTokens(node.propertyKeyword, toNode.propertyKeyword))
, _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.functionExpression,
toNode.functionExpression)); |
| 8604 } |
| 8605 |
| 8606 @override |
| 8607 bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { |
| 8608 FunctionDeclarationStatement toNode = this._toNode as FunctionDeclarationSta
tement; |
| 8609 return _isEqualNodes(node.functionDeclaration, toNode.functionDeclaration); |
| 8610 } |
| 8611 |
| 8612 @override |
| 8613 bool visitFunctionExpression(FunctionExpression node) { |
| 8614 FunctionExpression toNode = this._toNode as FunctionExpression; |
| 8615 if (javaBooleanAnd(_isEqualNodes(node.parameters, toNode.parameters), _isEqu
alNodes(node.body, toNode.body))) { |
| 8616 toNode.element = node.element; |
| 8617 toNode.propagatedType = node.propagatedType; |
| 8618 toNode.staticType = node.staticType; |
| 8619 return true; |
| 8620 } |
| 8621 return false; |
| 8622 } |
| 8623 |
| 8624 @override |
| 8625 bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 8626 FunctionExpressionInvocation toNode = this._toNode as FunctionExpressionInvo
cation; |
| 8627 if (javaBooleanAnd(_isEqualNodes(node.function, toNode.function), _isEqualNo
des(node.argumentList, toNode.argumentList))) { |
| 8628 toNode.propagatedElement = node.propagatedElement; |
| 8629 toNode.propagatedType = node.propagatedType; |
| 8630 toNode.staticElement = node.staticElement; |
| 8631 toNode.staticType = node.staticType; |
| 8632 return true; |
| 8633 } |
| 8634 return false; |
| 8635 } |
| 8636 |
| 8637 @override |
| 8638 bool visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 8639 FunctionTypeAlias toNode = this._toNode as FunctionTypeAlias; |
| 8640 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toN
ode.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _
isEqualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.returnType, toN
ode.returnType)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.typ
eParameters, toNode.typeParameters)), _isEqualNodes(node.parameters, toNode.para
meters)), _isEqualTokens(node.semicolon, toNode.semicolon)); |
| 8641 } |
| 8642 |
| 8643 @override |
| 8644 bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| 8645 FunctionTypedFormalParameter toNode = this._toNode as FunctionTypedFormalPar
ameter; |
| 8646 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualNodes(node.returnType, toNode.returnTy
pe)), _isEqualNodes(node.identifier, toNode.identifier)), _isEqualNodes(node.par
ameters, toNode.parameters)); |
| 8647 } |
| 8648 |
| 8649 @override |
| 8650 bool visitHideCombinator(HideCombinator node) { |
| 8651 HideCombinator toNode = this._toNode as HideCombinator; |
| 8652 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual
NodeLists(node.hiddenNames, toNode.hiddenNames)); |
| 8653 } |
| 8654 |
| 8655 @override |
| 8656 bool visitIfStatement(IfStatement node) { |
| 8657 IfStatement toNode = this._toNode as IfStatement; |
| 8658 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualTokens(node.ifKeyword, toNode.ifKeyword), _isEqualT
okens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.conditi
on, toNode.condition)), _isEqualTokens(node.rightParenthesis, toNode.rightParent
hesis)), _isEqualNodes(node.thenStatement, toNode.thenStatement)), _isEqualToken
s(node.elseKeyword, toNode.elseKeyword)), _isEqualNodes(node.elseStatement, toNo
de.elseStatement)); |
| 8659 } |
| 8660 |
| 8661 @override |
| 8662 bool visitImplementsClause(ImplementsClause node) { |
| 8663 ImplementsClause toNode = this._toNode as ImplementsClause; |
| 8664 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual
NodeLists(node.interfaces, toNode.interfaces)); |
| 8665 } |
| 8666 |
| 8667 @override |
| 8668 bool visitImportDirective(ImportDirective node) { |
| 8669 ImportDirective toNode = this._toNode as ImportDirective; |
| 8670 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA
nd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode
.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isE
qualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.uri, toNode.uri)),
_isEqualTokens(node.asToken, toNode.asToken)), _isEqualNodes(node.prefix, toNod
e.prefix)), _isEqualNodeLists(node.combinators, toNode.combinators)), _isEqualTo
kens(node.semicolon, toNode.semicolon))) { |
| 8671 toNode.element = node.element; |
| 8672 return true; |
| 8673 } |
| 8674 return false; |
| 8675 } |
| 8676 |
| 8677 @override |
| 8678 bool visitIndexExpression(IndexExpression node) { |
| 8679 IndexExpression toNode = this._toNode as IndexExpression; |
| 8680 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target,
toNode.target), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _isEqualN
odes(node.index, toNode.index)), _isEqualTokens(node.rightBracket, toNode.rightB
racket))) { |
| 8681 toNode.auxiliaryElements = node.auxiliaryElements; |
| 8682 toNode.propagatedElement = node.propagatedElement; |
| 8683 toNode.propagatedType = node.propagatedType; |
| 8684 toNode.staticElement = node.staticElement; |
| 8685 toNode.staticType = node.staticType; |
| 8686 return true; |
| 8687 } |
| 8688 return false; |
| 8689 } |
| 8690 |
| 8691 @override |
| 8692 bool visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 8693 InstanceCreationExpression toNode = this._toNode as InstanceCreationExpressi
on; |
| 8694 if (javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keywor
d), _isEqualNodes(node.constructorName, toNode.constructorName)), _isEqualNodes(
node.argumentList, toNode.argumentList))) { |
| 8695 toNode.propagatedType = node.propagatedType; |
| 8696 toNode.staticElement = node.staticElement; |
| 8697 toNode.staticType = node.staticType; |
| 8698 return true; |
| 8699 } |
| 8700 return false; |
| 8701 } |
| 8702 |
| 8703 @override |
| 8704 bool visitIntegerLiteral(IntegerLiteral node) { |
| 8705 IntegerLiteral toNode = this._toNode as IntegerLiteral; |
| 8706 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), identical(n
ode.value, toNode.value))) { |
| 8707 toNode.propagatedType = node.propagatedType; |
| 8708 toNode.staticType = node.staticType; |
| 8709 return true; |
| 8710 } |
| 8711 return false; |
| 8712 } |
| 8713 |
| 8714 @override |
| 8715 bool visitInterpolationExpression(InterpolationExpression node) { |
| 8716 InterpolationExpression toNode = this._toNode as InterpolationExpression; |
| 8717 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode
.leftBracket), _isEqualNodes(node.expression, toNode.expression)), _isEqualToken
s(node.rightBracket, toNode.rightBracket)); |
| 8718 } |
| 8719 |
| 8720 @override |
| 8721 bool visitInterpolationString(InterpolationString node) { |
| 8722 InterpolationString toNode = this._toNode as InterpolationString; |
| 8723 return javaBooleanAnd(_isEqualTokens(node.contents, toNode.contents), node.v
alue == toNode.value); |
| 8724 } |
| 8725 |
| 8726 @override |
| 8727 bool visitIsExpression(IsExpression node) { |
| 8728 IsExpression toNode = this._toNode as IsExpression; |
| 8729 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.expressi
on, toNode.expression), _isEqualTokens(node.isOperator, toNode.isOperator)), _is
EqualTokens(node.notOperator, toNode.notOperator)), _isEqualNodes(node.type, toN
ode.type))) { |
| 8730 toNode.propagatedType = node.propagatedType; |
| 8731 toNode.staticType = node.staticType; |
| 8732 return true; |
| 8733 } |
| 8734 return false; |
| 8735 } |
| 8736 |
| 8737 @override |
| 8738 bool visitLabel(Label node) { |
| 8739 Label toNode = this._toNode as Label; |
| 8740 return javaBooleanAnd(_isEqualNodes(node.label, toNode.label), _isEqualToken
s(node.colon, toNode.colon)); |
| 8741 } |
| 8742 |
| 8743 @override |
| 8744 bool visitLabeledStatement(LabeledStatement node) { |
| 8745 LabeledStatement toNode = this._toNode as LabeledStatement; |
| 8746 return javaBooleanAnd(_isEqualNodeLists(node.labels, toNode.labels), _isEqua
lNodes(node.statement, toNode.statement)); |
| 8747 } |
| 8748 |
| 8749 @override |
| 8750 bool visitLibraryDirective(LibraryDirective node) { |
| 8751 LibraryDirective toNode = this._toNode as LibraryDirective; |
| 8752 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualTokens(node.libraryToken, toNode.libra
ryToken)), _isEqualNodes(node.name, toNode.name)), _isEqualTokens(node.semicolon
, toNode.semicolon)); |
| 8753 } |
| 8754 |
| 8755 @override |
| 8756 bool visitLibraryIdentifier(LibraryIdentifier node) { |
| 8757 LibraryIdentifier toNode = this._toNode as LibraryIdentifier; |
| 8758 if (_isEqualNodeLists(node.components, toNode.components)) { |
| 8759 toNode.propagatedType = node.propagatedType; |
| 8760 toNode.staticType = node.staticType; |
| 8761 return true; |
| 8762 } |
| 8763 return false; |
| 8764 } |
| 8765 |
| 8766 @override |
| 8767 bool visitListLiteral(ListLiteral node) { |
| 8768 ListLiteral toNode = this._toNode as ListLiteral; |
| 8769 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke
ns(node.constKeyword, toNode.constKeyword), _isEqualNodes(node.typeArguments, to
Node.typeArguments)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _is
EqualNodeLists(node.elements, toNode.elements)), _isEqualTokens(node.rightBracke
t, toNode.rightBracket))) { |
| 8770 toNode.propagatedType = node.propagatedType; |
| 8771 toNode.staticType = node.staticType; |
| 8772 return true; |
| 8773 } |
| 8774 return false; |
| 8775 } |
| 8776 |
| 8777 @override |
| 8778 bool visitMapLiteral(MapLiteral node) { |
| 8779 MapLiteral toNode = this._toNode as MapLiteral; |
| 8780 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke
ns(node.constKeyword, toNode.constKeyword), _isEqualNodes(node.typeArguments, to
Node.typeArguments)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _is
EqualNodeLists(node.entries, toNode.entries)), _isEqualTokens(node.rightBracket,
toNode.rightBracket))) { |
| 8781 toNode.propagatedType = node.propagatedType; |
| 8782 toNode.staticType = node.staticType; |
| 8783 return true; |
| 8784 } |
| 8785 return false; |
| 8786 } |
| 8787 |
| 8788 @override |
| 8789 bool visitMapLiteralEntry(MapLiteralEntry node) { |
| 8790 MapLiteralEntry toNode = this._toNode as MapLiteralEntry; |
| 8791 return javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.key, toNode.key), _i
sEqualTokens(node.separator, toNode.separator)), _isEqualNodes(node.value, toNod
e.value)); |
| 8792 } |
| 8793 |
| 8794 @override |
| 8795 bool visitMethodDeclaration(MethodDeclaration node) { |
| 8796 MethodDeclaration toNode = this._toNode as MethodDeclaration; |
| 8797 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(
node.documentationComment, toNode.documentationComment), _isEqualNodeLists(node.
metadata, toNode.metadata)), _isEqualTokens(node.externalKeyword, toNode.externa
lKeyword)), _isEqualTokens(node.modifierKeyword, toNode.modifierKeyword)), _isEq
ualNodes(node.returnType, toNode.returnType)), _isEqualTokens(node.propertyKeywo
rd, toNode.propertyKeyword)), _isEqualTokens(node.propertyKeyword, toNode.proper
tyKeyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.paramete
rs, toNode.parameters)), _isEqualNodes(node.body, toNode.body)); |
| 8798 } |
| 8799 |
| 8800 @override |
| 8801 bool visitMethodInvocation(MethodInvocation node) { |
| 8802 MethodInvocation toNode = this._toNode as MethodInvocation; |
| 8803 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target,
toNode.target), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(node.
methodName, toNode.methodName)), _isEqualNodes(node.argumentList, toNode.argumen
tList))) { |
| 8804 toNode.propagatedType = node.propagatedType; |
| 8805 toNode.staticType = node.staticType; |
| 8806 return true; |
| 8807 } |
| 8808 return false; |
| 8809 } |
| 8810 |
| 8811 @override |
| 8812 bool visitNamedExpression(NamedExpression node) { |
| 8813 NamedExpression toNode = this._toNode as NamedExpression; |
| 8814 if (javaBooleanAnd(_isEqualNodes(node.name, toNode.name), _isEqualNodes(node
.expression, toNode.expression))) { |
| 8815 toNode.propagatedType = node.propagatedType; |
| 8816 toNode.staticType = node.staticType; |
| 8817 return true; |
| 8818 } |
| 8819 return false; |
| 8820 } |
| 8821 |
| 8822 @override |
| 8823 bool visitNativeClause(NativeClause node) { |
| 8824 NativeClause toNode = this._toNode as NativeClause; |
| 8825 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual
Nodes(node.name, toNode.name)); |
| 8826 } |
| 8827 |
| 8828 @override |
| 8829 bool visitNativeFunctionBody(NativeFunctionBody node) { |
| 8830 NativeFunctionBody toNode = this._toNode as NativeFunctionBody; |
| 8831 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.nativeToken, toNode
.nativeToken), _isEqualNodes(node.stringLiteral, toNode.stringLiteral)), _isEqua
lTokens(node.semicolon, toNode.semicolon)); |
| 8832 } |
| 8833 |
| 8834 @override |
| 8835 bool visitNullLiteral(NullLiteral node) { |
| 8836 NullLiteral toNode = this._toNode as NullLiteral; |
| 8837 if (_isEqualTokens(node.literal, toNode.literal)) { |
| 8838 toNode.propagatedType = node.propagatedType; |
| 8839 toNode.staticType = node.staticType; |
| 8840 return true; |
| 8841 } |
| 8842 return false; |
| 8843 } |
| 8844 |
| 8845 @override |
| 8846 bool visitParenthesizedExpression(ParenthesizedExpression node) { |
| 8847 ParenthesizedExpression toNode = this._toNode as ParenthesizedExpression; |
| 8848 if (javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftParenthesis, toNod
e.leftParenthesis), _isEqualNodes(node.expression, toNode.expression)), _isEqual
Tokens(node.rightParenthesis, toNode.rightParenthesis))) { |
| 8849 toNode.propagatedType = node.propagatedType; |
| 8850 toNode.staticType = node.staticType; |
| 8851 return true; |
| 8852 } |
| 8853 return false; |
| 8854 } |
| 8855 |
| 8856 @override |
| 8857 bool visitPartDirective(PartDirective node) { |
| 8858 PartDirective toNode = this._toNode as PartDirective; |
| 8859 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNode
s(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(nod
e.metadata, toNode.metadata)), _isEqualTokens(node.partToken, toNode.partToken))
, _isEqualNodes(node.uri, toNode.uri)), _isEqualTokens(node.semicolon, toNode.se
micolon))) { |
| 8860 toNode.element = node.element; |
| 8861 return true; |
| 8862 } |
| 8863 return false; |
| 8864 } |
| 8865 |
| 8866 @override |
| 8867 bool visitPartOfDirective(PartOfDirective node) { |
| 8868 PartOfDirective toNode = this._toNode as PartOfDirective; |
| 8869 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA
nd(_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqu
alNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.partToken, toN
ode.partToken)), _isEqualTokens(node.ofToken, toNode.ofToken)), _isEqualNodes(no
de.libraryName, toNode.libraryName)), _isEqualTokens(node.semicolon, toNode.semi
colon))) { |
| 8870 toNode.element = node.element; |
| 8871 return true; |
| 8872 } |
| 8873 return false; |
| 8874 } |
| 8875 |
| 8876 @override |
| 8877 bool visitPostfixExpression(PostfixExpression node) { |
| 8878 PostfixExpression toNode = this._toNode as PostfixExpression; |
| 8879 if (javaBooleanAnd(_isEqualNodes(node.operand, toNode.operand), _isEqualToke
ns(node.operator, toNode.operator))) { |
| 8880 toNode.propagatedElement = node.propagatedElement; |
| 8881 toNode.propagatedType = node.propagatedType; |
| 8882 toNode.staticElement = node.staticElement; |
| 8883 toNode.staticType = node.staticType; |
| 8884 return true; |
| 8885 } |
| 8886 return false; |
| 8887 } |
| 8888 |
| 8889 @override |
| 8890 bool visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 8891 PrefixedIdentifier toNode = this._toNode as PrefixedIdentifier; |
| 8892 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.prefix, toNode.prefix),
_isEqualTokens(node.period, toNode.period)), _isEqualNodes(node.identifier, toN
ode.identifier))) { |
| 8893 toNode.propagatedType = node.propagatedType; |
| 8894 toNode.staticType = node.staticType; |
| 8895 return true; |
| 8896 } |
| 8897 return false; |
| 8898 } |
| 8899 |
| 8900 @override |
| 8901 bool visitPrefixExpression(PrefixExpression node) { |
| 8902 PrefixExpression toNode = this._toNode as PrefixExpression; |
| 8903 if (javaBooleanAnd(_isEqualTokens(node.operator, toNode.operator), _isEqualN
odes(node.operand, toNode.operand))) { |
| 8904 toNode.propagatedElement = node.propagatedElement; |
| 8905 toNode.propagatedType = node.propagatedType; |
| 8906 toNode.staticElement = node.staticElement; |
| 8907 toNode.staticType = node.staticType; |
| 8908 return true; |
| 8909 } |
| 8910 return false; |
| 8911 } |
| 8912 |
| 8913 @override |
| 8914 bool visitPropertyAccess(PropertyAccess node) { |
| 8915 PropertyAccess toNode = this._toNode as PropertyAccess; |
| 8916 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target, toNode.target),
_isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node.propertyNam
e, toNode.propertyName))) { |
| 8917 toNode.propagatedType = node.propagatedType; |
| 8918 toNode.staticType = node.staticType; |
| 8919 return true; |
| 8920 } |
| 8921 return false; |
| 8922 } |
| 8923 |
| 8924 @override |
| 8925 bool visitRedirectingConstructorInvocation(RedirectingConstructorInvocation no
de) { |
| 8926 RedirectingConstructorInvocation toNode = this._toNode as RedirectingConstru
ctorInvocation; |
| 8927 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword
, toNode.keyword), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(no
de.constructorName, toNode.constructorName)), _isEqualNodes(node.argumentList, t
oNode.argumentList))) { |
| 8928 toNode.staticElement = node.staticElement; |
| 8929 return true; |
| 8930 } |
| 8931 return false; |
| 8932 } |
| 8933 |
| 8934 @override |
| 8935 bool visitRethrowExpression(RethrowExpression node) { |
| 8936 RethrowExpression toNode = this._toNode as RethrowExpression; |
| 8937 if (_isEqualTokens(node.keyword, toNode.keyword)) { |
| 8938 toNode.propagatedType = node.propagatedType; |
| 8939 toNode.staticType = node.staticType; |
| 8940 return true; |
| 8941 } |
| 8942 return false; |
| 8943 } |
| 8944 |
| 8945 @override |
| 8946 bool visitReturnStatement(ReturnStatement node) { |
| 8947 ReturnStatement toNode = this._toNode as ReturnStatement; |
| 8948 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key
word), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.s
emicolon, toNode.semicolon)); |
| 8949 } |
| 8950 |
| 8951 @override |
| 8952 bool visitScriptTag(ScriptTag node) { |
| 8953 ScriptTag toNode = this._toNode as ScriptTag; |
| 8954 return _isEqualTokens(node.scriptTag, toNode.scriptTag); |
| 8955 } |
| 8956 |
| 8957 @override |
| 8958 bool visitShowCombinator(ShowCombinator node) { |
| 8959 ShowCombinator toNode = this._toNode as ShowCombinator; |
| 8960 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual
NodeLists(node.shownNames, toNode.shownNames)); |
| 8961 } |
| 8962 |
| 8963 @override |
| 8964 bool visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 8965 SimpleFormalParameter toNode = this._toNode as SimpleFormalParameter; |
| 8966 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)),
_isEqualNodes(node.type, toNode.type)), _isEqualNodes(node.identifier, toNode.i
dentifier)); |
| 8967 } |
| 8968 |
| 8969 @override |
| 8970 bool visitSimpleIdentifier(SimpleIdentifier node) { |
| 8971 SimpleIdentifier toNode = this._toNode as SimpleIdentifier; |
| 8972 if (_isEqualTokens(node.token, toNode.token)) { |
| 8973 toNode.staticElement = node.staticElement; |
| 8974 toNode.staticType = node.staticType; |
| 8975 toNode.propagatedElement = node.propagatedElement; |
| 8976 toNode.propagatedType = node.propagatedType; |
| 8977 toNode.auxiliaryElements = node.auxiliaryElements; |
| 8978 return true; |
| 8979 } |
| 8980 return false; |
| 8981 } |
| 8982 |
| 8983 @override |
| 8984 bool visitSimpleStringLiteral(SimpleStringLiteral node) { |
| 8985 SimpleStringLiteral toNode = this._toNode as SimpleStringLiteral; |
| 8986 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), identical(n
ode.value, toNode.value))) { |
| 8987 toNode.propagatedType = node.propagatedType; |
| 8988 toNode.staticType = node.staticType; |
| 8989 return true; |
| 8990 } |
| 8991 return false; |
| 8992 } |
| 8993 |
| 8994 @override |
| 8995 bool visitStringInterpolation(StringInterpolation node) { |
| 8996 StringInterpolation toNode = this._toNode as StringInterpolation; |
| 8997 if (_isEqualNodeLists(node.elements, toNode.elements)) { |
| 8998 toNode.propagatedType = node.propagatedType; |
| 8999 toNode.staticType = node.staticType; |
| 9000 return true; |
| 9001 } |
| 9002 return false; |
| 9003 } |
| 9004 |
| 9005 @override |
| 9006 bool visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 9007 SuperConstructorInvocation toNode = this._toNode as SuperConstructorInvocati
on; |
| 9008 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword
, toNode.keyword), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(no
de.constructorName, toNode.constructorName)), _isEqualNodes(node.argumentList, t
oNode.argumentList))) { |
| 9009 toNode.staticElement = node.staticElement; |
| 9010 return true; |
| 9011 } |
| 9012 return false; |
| 9013 } |
| 9014 |
| 9015 @override |
| 9016 bool visitSuperExpression(SuperExpression node) { |
| 9017 SuperExpression toNode = this._toNode as SuperExpression; |
| 9018 if (_isEqualTokens(node.keyword, toNode.keyword)) { |
| 9019 toNode.propagatedType = node.propagatedType; |
| 9020 toNode.staticType = node.staticType; |
| 9021 return true; |
| 9022 } |
| 9023 return false; |
| 9024 } |
| 9025 |
| 9026 @override |
| 9027 bool visitSwitchCase(SwitchCase node) { |
| 9028 SwitchCase toNode = this._toNode as SwitchCase; |
| 9029 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odeLists(node.labels, toNode.labels), _isEqualTokens(node.keyword, toNode.keywor
d)), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.col
on, toNode.colon)), _isEqualNodeLists(node.statements, toNode.statements)); |
| 9030 } |
| 9031 |
| 9032 @override |
| 9033 bool visitSwitchDefault(SwitchDefault node) { |
| 9034 SwitchDefault toNode = this._toNode as SwitchDefault; |
| 9035 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodeLists(node.l
abels, toNode.labels), _isEqualTokens(node.keyword, toNode.keyword)), _isEqualTo
kens(node.colon, toNode.colon)), _isEqualNodeLists(node.statements, toNode.state
ments)); |
| 9036 } |
| 9037 |
| 9038 @override |
| 9039 bool visitSwitchStatement(SwitchStatement node) { |
| 9040 SwitchStatement toNode = this._toNode as SwitchStatement; |
| 9041 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole
anAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqualToken
s(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.expression,
toNode.expression)), _isEqualTokens(node.rightParenthesis, toNode.rightParenthe
sis)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _isEqualNodeLists(
node.members, toNode.members)), _isEqualTokens(node.rightBracket, toNode.rightBr
acket)); |
| 9042 } |
| 9043 |
| 9044 @override |
| 9045 bool visitSymbolLiteral(SymbolLiteral node) { |
| 9046 SymbolLiteral toNode = this._toNode as SymbolLiteral; |
| 9047 if (javaBooleanAnd(_isEqualTokens(node.poundSign, toNode.poundSign), _isEqua
lTokenLists(node.components, toNode.components))) { |
| 9048 toNode.propagatedType = node.propagatedType; |
| 9049 toNode.staticType = node.staticType; |
| 9050 return true; |
| 9051 } |
| 9052 return false; |
| 9053 } |
| 9054 |
| 9055 @override |
| 9056 bool visitThisExpression(ThisExpression node) { |
| 9057 ThisExpression toNode = this._toNode as ThisExpression; |
| 9058 if (_isEqualTokens(node.keyword, toNode.keyword)) { |
| 9059 toNode.propagatedType = node.propagatedType; |
| 9060 toNode.staticType = node.staticType; |
| 9061 return true; |
| 9062 } |
| 9063 return false; |
| 9064 } |
| 9065 |
| 9066 @override |
| 9067 bool visitThrowExpression(ThrowExpression node) { |
| 9068 ThrowExpression toNode = this._toNode as ThrowExpression; |
| 9069 if (javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqualNod
es(node.expression, toNode.expression))) { |
| 9070 toNode.propagatedType = node.propagatedType; |
| 9071 toNode.staticType = node.staticType; |
| 9072 return true; |
| 9073 } |
| 9074 return false; |
| 9075 } |
| 9076 |
| 9077 @override |
| 9078 bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 9079 TopLevelVariableDeclaration toNode = this._toNode as TopLevelVariableDeclara
tion; |
| 9080 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.docum
entationComment, toNode.documentationComment), _isEqualNodeLists(node.metadata,
toNode.metadata)), _isEqualNodes(node.variables, toNode.variables)), _isEqualTok
ens(node.semicolon, toNode.semicolon)); |
| 9081 } |
| 9082 |
| 9083 @override |
| 9084 bool visitTryStatement(TryStatement node) { |
| 9085 TryStatement toNode = this._toNode as TryStatement; |
| 9086 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT
okens(node.tryKeyword, toNode.tryKeyword), _isEqualNodes(node.body, toNode.body)
), _isEqualNodeLists(node.catchClauses, toNode.catchClauses)), _isEqualTokens(no
de.finallyKeyword, toNode.finallyKeyword)), _isEqualNodes(node.finallyBlock, toN
ode.finallyBlock)); |
| 9087 } |
| 9088 |
| 9089 @override |
| 9090 bool visitTypeArgumentList(TypeArgumentList node) { |
| 9091 TypeArgumentList toNode = this._toNode as TypeArgumentList; |
| 9092 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode
.leftBracket), _isEqualNodeLists(node.arguments, toNode.arguments)), _isEqualTok
ens(node.rightBracket, toNode.rightBracket)); |
| 9093 } |
| 9094 |
| 9095 @override |
| 9096 bool visitTypeName(TypeName node) { |
| 9097 TypeName toNode = this._toNode as TypeName; |
| 9098 if (javaBooleanAnd(_isEqualNodes(node.name, toNode.name), _isEqualNodes(node
.typeArguments, toNode.typeArguments))) { |
| 9099 toNode.type = node.type; |
| 9100 return true; |
| 9101 } |
| 9102 return false; |
| 9103 } |
| 9104 |
| 9105 @override |
| 9106 bool visitTypeParameter(TypeParameter node) { |
| 9107 TypeParameter toNode = this._toNode as TypeParameter; |
| 9108 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualNodes(node.name, toNode.name)), _isEqu
alTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.bound, toNode.bound)
); |
| 9109 } |
| 9110 |
| 9111 @override |
| 9112 bool visitTypeParameterList(TypeParameterList node) { |
| 9113 TypeParameterList toNode = this._toNode as TypeParameterList; |
| 9114 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode
.leftBracket), _isEqualNodeLists(node.typeParameters, toNode.typeParameters)), _
isEqualTokens(node.rightBracket, toNode.rightBracket)); |
| 9115 } |
| 9116 |
| 9117 @override |
| 9118 bool visitVariableDeclaration(VariableDeclaration node) { |
| 9119 VariableDeclaration toNode = this._toNode as VariableDeclaration; |
| 9120 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualNodes(node.name, toNode.name)), _isEqu
alTokens(node.equals, toNode.equals)), _isEqualNodes(node.initializer, toNode.in
itializer)); |
| 9121 } |
| 9122 |
| 9123 @override |
| 9124 bool visitVariableDeclarationList(VariableDeclarationList node) { |
| 9125 VariableDeclarationList toNode = this._toNode as VariableDeclarationList; |
| 9126 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN
odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(
node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)),
_isEqualNodes(node.type, toNode.type)), _isEqualNodeLists(node.variables, toNod
e.variables)); |
| 9127 } |
| 9128 |
| 9129 @override |
| 9130 bool visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 9131 VariableDeclarationStatement toNode = this._toNode as VariableDeclarationSta
tement; |
| 9132 return javaBooleanAnd(_isEqualNodes(node.variables, toNode.variables), _isEq
ualTokens(node.semicolon, toNode.semicolon)); |
| 9133 } |
| 9134 |
| 9135 @override |
| 9136 bool visitWhileStatement(WhileStatement node) { |
| 9137 WhileStatement toNode = this._toNode as WhileStatement; |
| 9138 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT
okens(node.keyword, toNode.keyword), _isEqualTokens(node.leftParenthesis, toNode
.leftParenthesis)), _isEqualNodes(node.condition, toNode.condition)), _isEqualTo
kens(node.rightParenthesis, toNode.rightParenthesis)), _isEqualNodes(node.body,
toNode.body)); |
| 9139 } |
| 9140 |
| 9141 @override |
| 9142 bool visitWithClause(WithClause node) { |
| 9143 WithClause toNode = this._toNode as WithClause; |
| 9144 return javaBooleanAnd(_isEqualTokens(node.withKeyword, toNode.withKeyword),
_isEqualNodeLists(node.mixinTypes, toNode.mixinTypes)); |
| 9145 } |
| 9146 |
| 9147 @override |
| 9148 bool visitYieldStatement(YieldStatement node) { |
| 9149 YieldStatement toNode = this._toNode as YieldStatement; |
| 9150 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.yieldKeyword, toNod
e.yieldKeyword), _isEqualNodes(node.expression, toNode.expression)), _isEqualTok
ens(node.semicolon, toNode.semicolon)); |
| 9151 } |
| 9152 |
| 9153 /** |
| 9154 * Return `true` if the given lists of AST nodes have the same size and corres
ponding |
| 9155 * elements are equal. |
| 9156 * |
| 9157 * @param first the first node being compared |
| 9158 * @param second the second node being compared |
| 9159 * @return `true` if the given AST nodes have the same size and corresponding
elements are |
| 9160 * equal |
| 9161 */ |
| 9162 bool _isEqualNodeLists(NodeList first, NodeList second) { |
| 9163 if (first == null) { |
| 9164 return second == null; |
| 9165 } else if (second == null) { |
| 9166 return false; |
| 9167 } |
| 9168 int size = first.length; |
| 9169 if (second.length != size) { |
| 9170 return false; |
| 9171 } |
| 9172 bool equal = true; |
| 9173 for (int i = 0; i < size; i++) { |
| 9174 if (!_isEqualNodes(first[i], second[i])) { |
| 9175 equal = false; |
| 9176 } |
| 9177 } |
| 9178 return equal; |
| 9179 } |
| 9180 |
| 9181 /** |
| 9182 * Return `true` if the given AST nodes have the same structure. As a side-eff
ect, if the |
| 9183 * nodes do have the same structure, any resolution data from the first node w
ill be copied to the |
| 9184 * second node. |
| 9185 * |
| 9186 * @param fromNode the node from which resolution information will be copied |
| 9187 * @param toNode the node to which resolution information will be copied |
| 9188 * @return `true` if the given AST nodes have the same structure |
| 9189 */ |
| 9190 bool _isEqualNodes(AstNode fromNode, AstNode toNode) { |
| 9191 if (fromNode == null) { |
| 9192 return toNode == null; |
| 9193 } else if (toNode == null) { |
| 9194 return false; |
| 9195 } else if (fromNode.runtimeType == toNode.runtimeType) { |
| 9196 this._toNode = toNode; |
| 9197 return fromNode.accept(this); |
| 9198 } |
| 9199 // |
| 9200 // Check for a simple transformation caused by entering a period. |
| 9201 // |
| 9202 if (toNode is PrefixedIdentifier) { |
| 9203 SimpleIdentifier prefix = toNode.prefix; |
| 9204 if (fromNode.runtimeType == prefix.runtimeType) { |
| 9205 this._toNode = prefix; |
| 9206 return fromNode.accept(this); |
| 9207 } |
| 9208 } else if (toNode is PropertyAccess) { |
| 9209 Expression target = toNode.target; |
| 9210 if (fromNode.runtimeType == target.runtimeType) { |
| 9211 this._toNode = target; |
| 9212 return fromNode.accept(this); |
| 9213 } |
| 9214 } |
| 9215 return false; |
| 9216 } |
| 9217 |
| 9218 /** |
| 9219 * Return `true` if the given arrays of tokens have the same length and corres
ponding |
| 9220 * elements are equal. |
| 9221 * |
| 9222 * @param first the first node being compared |
| 9223 * @param second the second node being compared |
| 9224 * @return `true` if the given arrays of tokens have the same length and corre
sponding |
| 9225 * elements are equal |
| 9226 */ |
| 9227 bool _isEqualTokenLists(List<Token> first, List<Token> second) { |
| 9228 int length = first.length; |
| 9229 if (second.length != length) { |
| 9230 return false; |
| 9231 } |
| 9232 for (int i = 0; i < length; i++) { |
| 9233 if (!_isEqualTokens(first[i], second[i])) { |
| 9234 return false; |
| 9235 } |
| 9236 } |
| 9237 return true; |
| 9238 } |
| 9239 |
| 9240 /** |
| 9241 * Return `true` if the given tokens have the same structure. |
| 9242 * |
| 9243 * @param first the first node being compared |
| 9244 * @param second the second node being compared |
| 9245 * @return `true` if the given tokens have the same structure |
| 9246 */ |
| 9247 bool _isEqualTokens(Token first, Token second) { |
| 9248 if (first == null) { |
| 9249 return second == null; |
| 9250 } else if (second == null) { |
| 9251 return false; |
| 9252 } |
| 9253 return first.lexeme == second.lexeme; |
| 9254 } |
| 9255 } |
| 9256 Map<String, MethodTrampoline> methodTable_Parser = <String, MethodTrampoline> { |
| 9257 'parseCompilationUnit_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get.parseCompilationUnit(arg0)), |
| 9258 'parseDirectives_1': new MethodTrampoline(1, (Parser target, arg0) => target.p
arseDirectives(arg0)), |
| 9259 'parseExpression_1': new MethodTrampoline(1, (Parser target, arg0) => target.p
arseExpression(arg0)), |
| 9260 'parseStatement_1': new MethodTrampoline(1, (Parser target, arg0) => target.pa
rseStatement(arg0)), |
| 9261 'parseStatements_1': new MethodTrampoline(1, (Parser target, arg0) => target.p
arseStatements(arg0)), |
| 9262 'parseAnnotation_0': new MethodTrampoline(0, (Parser target) => target.parseAn
notation()), |
| 9263 'parseArgument_0': new MethodTrampoline(0, (Parser target) => target.parseArgu
ment()), |
| 9264 'parseArgumentList_0': new MethodTrampoline(0, (Parser target) => target.parse
ArgumentList()), |
| 9265 'parseBitwiseOrExpression_0': new MethodTrampoline(0, (Parser target) => targe
t.parseBitwiseOrExpression()), |
| 9266 'parseBlock_0': new MethodTrampoline(0, (Parser target) => target.parseBlock()
), |
| 9267 'parseClassMember_1': new MethodTrampoline(1, (Parser target, arg0) => target.
parseClassMember(arg0)), |
| 9268 'parseCompilationUnit_0': new MethodTrampoline(0, (Parser target) => target.pa
rseCompilationUnit2()), |
| 9269 'parseConditionalExpression_0': new MethodTrampoline(0, (Parser target) => tar
get.parseConditionalExpression()), |
| 9270 'parseConstructorName_0': new MethodTrampoline(0, (Parser target) => target.pa
rseConstructorName()), |
| 9271 'parseExpression_0': new MethodTrampoline(0, (Parser target) => target.parseEx
pression2()), |
| 9272 'parseExpressionWithoutCascade_0': new MethodTrampoline(0, (Parser target) =>
target.parseExpressionWithoutCascade()), |
| 9273 'parseExtendsClause_0': new MethodTrampoline(0, (Parser target) => target.pars
eExtendsClause()), |
| 9274 'parseFormalParameterList_0': new MethodTrampoline(0, (Parser target) => targe
t.parseFormalParameterList()), |
| 9275 'parseFunctionExpression_0': new MethodTrampoline(0, (Parser target) => target
.parseFunctionExpression()), |
| 9276 'parseImplementsClause_0': new MethodTrampoline(0, (Parser target) => target.p
arseImplementsClause()), |
| 9277 'parseLabel_0': new MethodTrampoline(0, (Parser target) => target.parseLabel()
), |
| 9278 'parseLibraryIdentifier_0': new MethodTrampoline(0, (Parser target) => target.
parseLibraryIdentifier()), |
| 9279 'parseLogicalOrExpression_0': new MethodTrampoline(0, (Parser target) => targe
t.parseLogicalOrExpression()), |
| 9280 'parseMapLiteralEntry_0': new MethodTrampoline(0, (Parser target) => target.pa
rseMapLiteralEntry()), |
| 9281 'parseNormalFormalParameter_0': new MethodTrampoline(0, (Parser target) => tar
get.parseNormalFormalParameter()), |
| 9282 'parsePrefixedIdentifier_0': new MethodTrampoline(0, (Parser target) => target
.parsePrefixedIdentifier()), |
| 9283 'parseReturnType_0': new MethodTrampoline(0, (Parser target) => target.parseRe
turnType()), |
| 9284 'parseSimpleIdentifier_0': new MethodTrampoline(0, (Parser target) => target.p
arseSimpleIdentifier()), |
| 9285 'parseStatement_0': new MethodTrampoline(0, (Parser target) => target.parseSta
tement2()), |
| 9286 'parseStringLiteral_0': new MethodTrampoline(0, (Parser target) => target.pars
eStringLiteral()), |
| 9287 'parseTypeArgumentList_0': new MethodTrampoline(0, (Parser target) => target.p
arseTypeArgumentList()), |
| 9288 'parseTypeName_0': new MethodTrampoline(0, (Parser target) => target.parseType
Name()), |
| 9289 'parseTypeParameter_0': new MethodTrampoline(0, (Parser target) => target.pars
eTypeParameter()), |
| 9290 'parseTypeParameterList_0': new MethodTrampoline(0, (Parser target) => target.
parseTypeParameterList()), |
| 9291 'parseWithClause_0': new MethodTrampoline(0, (Parser target) => target.parseWi
thClause()), |
| 9292 'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()), |
| 9293 'appendScalarValue_5': new MethodTrampoline(5, (Parser target, arg0, arg1, arg
2, arg3, arg4) => target._appendScalarValue(arg0, arg1, arg2, arg3, arg4)), |
| 9294 'computeStringValue_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar
g2) => target._computeStringValue(arg0, arg1, arg2)), |
| 9295 'convertToFunctionDeclaration_1': new MethodTrampoline(1, (Parser target, arg0
) => target._convertToFunctionDeclaration(arg0)), |
| 9296 'couldBeStartOfCompilationUnitMember_0': new MethodTrampoline(0, (Parser targe
t) => target._couldBeStartOfCompilationUnitMember()), |
| 9297 'createSyntheticIdentifier_0': new MethodTrampoline(0, (Parser target) => targ
et._createSyntheticIdentifier()), |
| 9298 'createSyntheticKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => t
arget._createSyntheticKeyword(arg0)), |
| 9299 'createSyntheticStringLiteral_0': new MethodTrampoline(0, (Parser target) => t
arget._createSyntheticStringLiteral()), |
| 9300 'createSyntheticToken_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._createSyntheticToken(arg0)), |
| 9301 'ensureAssignable_1': new MethodTrampoline(1, (Parser target, arg0) => target.
_ensureAssignable(arg0)), |
| 9302 'expect_1': new MethodTrampoline(1, (Parser target, arg0) => target._expect(ar
g0)), |
| 9303 'expectGt_0': new MethodTrampoline(0, (Parser target) => target._expectGt()), |
| 9304 'expectKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => target._ex
pectKeyword(arg0)), |
| 9305 'expectSemicolon_0': new MethodTrampoline(0, (Parser target) => target._expect
Semicolon()), |
| 9306 'findRange_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._
findRange(arg0, arg1)), |
| 9307 'getCodeBlockRanges_1': new MethodTrampoline(1, (Parser target, arg0) => targe
t._getCodeBlockRanges(arg0)), |
| 9308 'getEndToken_1': new MethodTrampoline(1, (Parser target, arg0) => target._getE
ndToken(arg0)), |
| 9309 'injectToken_1': new MethodTrampoline(1, (Parser target, arg0) => target._inje
ctToken(arg0)), |
| 9310 'isFunctionDeclaration_0': new MethodTrampoline(0, (Parser target) => target._
isFunctionDeclaration()), |
| 9311 'isFunctionExpression_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._isFunctionExpression(arg0)), |
| 9312 'isHexDigit_1': new MethodTrampoline(1, (Parser target, arg0) => target._isHex
Digit(arg0)), |
| 9313 'isInitializedVariableDeclaration_0': new MethodTrampoline(0, (Parser target)
=> target._isInitializedVariableDeclaration()), |
| 9314 'isLinkText_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target.
_isLinkText(arg0, arg1)), |
| 9315 'isOperator_1': new MethodTrampoline(1, (Parser target, arg0) => target._isOpe
rator(arg0)), |
| 9316 'isSwitchMember_0': new MethodTrampoline(0, (Parser target) => target._isSwitc
hMember()), |
| 9317 'isTypedIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => target
._isTypedIdentifier(arg0)), |
| 9318 'lexicallyFirst_1': new MethodTrampoline(1, (Parser target, arg0) => target._l
exicallyFirst(arg0)), |
| 9319 'lockErrorListener_0': new MethodTrampoline(0, (Parser target) => target._lock
ErrorListener()), |
| 9320 'matches_1': new MethodTrampoline(1, (Parser target, arg0) => target._matches(
arg0)), |
| 9321 'matchesGt_0': new MethodTrampoline(0, (Parser target) => target._matchesGt())
, |
| 9322 'matchesIdentifier_0': new MethodTrampoline(0, (Parser target) => target._matc
hesIdentifier()), |
| 9323 'matchesKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => target._m
atchesKeyword(arg0)), |
| 9324 'matchesString_1': new MethodTrampoline(1, (Parser target, arg0) => target._ma
tchesString(arg0)), |
| 9325 'optional_1': new MethodTrampoline(1, (Parser target, arg0) => target._optiona
l(arg0)), |
| 9326 'parseAdditiveExpression_0': new MethodTrampoline(0, (Parser target) => target
._parseAdditiveExpression()), |
| 9327 'parseAssertStatement_0': new MethodTrampoline(0, (Parser target) => target._p
arseAssertStatement()), |
| 9328 'parseAssignableExpression_1': new MethodTrampoline(1, (Parser target, arg0) =
> target._parseAssignableExpression(arg0)), |
| 9329 'parseAssignableSelector_2': new MethodTrampoline(2, (Parser target, arg0, arg
1) => target._parseAssignableSelector(arg0, arg1)), |
| 9330 'parseAwaitExpression_0': new MethodTrampoline(0, (Parser target) => target._p
arseAwaitExpression()), |
| 9331 'parseBitwiseAndExpression_0': new MethodTrampoline(0, (Parser target) => targ
et._parseBitwiseAndExpression()), |
| 9332 'parseBitwiseXorExpression_0': new MethodTrampoline(0, (Parser target) => targ
et._parseBitwiseXorExpression()), |
| 9333 'parseBreakStatement_0': new MethodTrampoline(0, (Parser target) => target._pa
rseBreakStatement()), |
| 9334 'parseCascadeSection_0': new MethodTrampoline(0, (Parser target) => target._pa
rseCascadeSection()), |
| 9335 'parseClassDeclaration_2': new MethodTrampoline(2, (Parser target, arg0, arg1)
=> target._parseClassDeclaration(arg0, arg1)), |
| 9336 'parseClassMembers_2': new MethodTrampoline(2, (Parser target, arg0, arg1) =>
target._parseClassMembers(arg0, arg1)), |
| 9337 'parseClassTypeAlias_3': new MethodTrampoline(3, (Parser target, arg0, arg1, a
rg2) => target._parseClassTypeAlias(arg0, arg1, arg2)), |
| 9338 'parseCombinators_0': new MethodTrampoline(0, (Parser target) => target._parse
Combinators()), |
| 9339 'parseCommentAndMetadata_0': new MethodTrampoline(0, (Parser target) => target
._parseCommentAndMetadata()), |
| 9340 'parseCommentReference_2': new MethodTrampoline(2, (Parser target, arg0, arg1)
=> target._parseCommentReference(arg0, arg1)), |
| 9341 'parseCommentReferences_1': new MethodTrampoline(1, (Parser target, arg0) => t
arget._parseCommentReferences(arg0)), |
| 9342 'parseCompilationUnitMember_1': new MethodTrampoline(1, (Parser target, arg0)
=> target._parseCompilationUnitMember(arg0)), |
| 9343 'parseConstExpression_0': new MethodTrampoline(0, (Parser target) => target._p
arseConstExpression()), |
| 9344 'parseConstructor_8': new MethodTrampoline(8, (Parser target, arg0, arg1, arg2
, arg3, arg4, arg5, arg6, arg7) => target._parseConstructor(arg0, arg1, arg2, ar
g3, arg4, arg5, arg6, arg7)), |
| 9345 'parseConstructorFieldInitializer_0': new MethodTrampoline(0, (Parser target)
=> target._parseConstructorFieldInitializer()), |
| 9346 'parseContinueStatement_0': new MethodTrampoline(0, (Parser target) => target.
_parseContinueStatement()), |
| 9347 'parseDirective_1': new MethodTrampoline(1, (Parser target, arg0) => target._p
arseDirective(arg0)), |
| 9348 'parseDirectives_0': new MethodTrampoline(0, (Parser target) => target._parseD
irectives()), |
| 9349 'parseDocumentationComment_0': new MethodTrampoline(0, (Parser target) => targ
et._parseDocumentationComment()), |
| 9350 'parseDoStatement_0': new MethodTrampoline(0, (Parser target) => target._parse
DoStatement()), |
| 9351 'parseEmptyStatement_0': new MethodTrampoline(0, (Parser target) => target._pa
rseEmptyStatement()), |
| 9352 'parseEnumConstantDeclaration_0': new MethodTrampoline(0, (Parser target) => t
arget._parseEnumConstantDeclaration()), |
| 9353 'parseEnumDeclaration_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._parseEnumDeclaration(arg0)), |
| 9354 'parseEqualityExpression_0': new MethodTrampoline(0, (Parser target) => target
._parseEqualityExpression()), |
| 9355 'parseExportDirective_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._parseExportDirective(arg0)), |
| 9356 'parseExpressionList_0': new MethodTrampoline(0, (Parser target) => target._pa
rseExpressionList()), |
| 9357 'parseFinalConstVarOrType_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._parseFinalConstVarOrType(arg0)), |
| 9358 'parseFormalParameter_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._parseFormalParameter(arg0)), |
| 9359 'parseForStatement_0': new MethodTrampoline(0, (Parser target) => target._pars
eForStatement()), |
| 9360 'parseFunctionBody_3': new MethodTrampoline(3, (Parser target, arg0, arg1, arg
2) => target._parseFunctionBody(arg0, arg1, arg2)), |
| 9361 'parseFunctionDeclaration_3': new MethodTrampoline(3, (Parser target, arg0, ar
g1, arg2) => target._parseFunctionDeclaration(arg0, arg1, arg2)), |
| 9362 'parseFunctionDeclarationStatement_0': new MethodTrampoline(0, (Parser target)
=> target._parseFunctionDeclarationStatement()), |
| 9363 'parseFunctionDeclarationStatementAfterReturnType_2': new MethodTrampoline(2,
(Parser target, arg0, arg1) => target._parseFunctionDeclarationStatementAfterRet
urnType(arg0, arg1)), |
| 9364 'parseFunctionTypeAlias_2': new MethodTrampoline(2, (Parser target, arg0, arg1
) => target._parseFunctionTypeAlias(arg0, arg1)), |
| 9365 'parseGetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2, arg
3) => target._parseGetter(arg0, arg1, arg2, arg3)), |
| 9366 'parseIdentifierList_0': new MethodTrampoline(0, (Parser target) => target._pa
rseIdentifierList()), |
| 9367 'parseIfStatement_0': new MethodTrampoline(0, (Parser target) => target._parse
IfStatement()), |
| 9368 'parseImportDirective_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._parseImportDirective(arg0)), |
| 9369 'parseInitializedIdentifierList_4': new MethodTrampoline(4, (Parser target, ar
g0, arg1, arg2, arg3) => target._parseInitializedIdentifierList(arg0, arg1, arg2
, arg3)), |
| 9370 'parseInstanceCreationExpression_1': new MethodTrampoline(1, (Parser target, a
rg0) => target._parseInstanceCreationExpression(arg0)), |
| 9371 'parseLibraryDirective_1': new MethodTrampoline(1, (Parser target, arg0) => ta
rget._parseLibraryDirective(arg0)), |
| 9372 'parseLibraryName_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => t
arget._parseLibraryName(arg0, arg1)), |
| 9373 'parseListLiteral_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => t
arget._parseListLiteral(arg0, arg1)), |
| 9374 'parseListOrMapLiteral_1': new MethodTrampoline(1, (Parser target, arg0) => ta
rget._parseListOrMapLiteral(arg0)), |
| 9375 'parseLogicalAndExpression_0': new MethodTrampoline(0, (Parser target) => targ
et._parseLogicalAndExpression()), |
| 9376 'parseMapLiteral_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => ta
rget._parseMapLiteral(arg0, arg1)), |
| 9377 'parseMethodDeclarationAfterParameters_6': new MethodTrampoline(6, (Parser tar
get, arg0, arg1, arg2, arg3, arg4, arg5) => target._parseMethodDeclarationAfterP
arameters(arg0, arg1, arg2, arg3, arg4, arg5)), |
| 9378 'parseMethodDeclarationAfterReturnType_4': new MethodTrampoline(4, (Parser tar
get, arg0, arg1, arg2, arg3) => target._parseMethodDeclarationAfterReturnType(ar
g0, arg1, arg2, arg3)), |
| 9379 'parseModifiers_0': new MethodTrampoline(0, (Parser target) => target._parseMo
difiers()), |
| 9380 'parseMultiplicativeExpression_0': new MethodTrampoline(0, (Parser target) =>
target._parseMultiplicativeExpression()), |
| 9381 'parseNativeClause_0': new MethodTrampoline(0, (Parser target) => target._pars
eNativeClause()), |
| 9382 'parseNewExpression_0': new MethodTrampoline(0, (Parser target) => target._par
seNewExpression()), |
| 9383 'parseNonLabeledStatement_0': new MethodTrampoline(0, (Parser target) => targe
t._parseNonLabeledStatement()), |
| 9384 'parseOperator_3': new MethodTrampoline(3, (Parser target, arg0, arg1, arg2) =
> target._parseOperator(arg0, arg1, arg2)), |
| 9385 'parseOptionalReturnType_0': new MethodTrampoline(0, (Parser target) => target
._parseOptionalReturnType()), |
| 9386 'parsePartDirective_1': new MethodTrampoline(1, (Parser target, arg0) => targe
t._parsePartDirective(arg0)), |
| 9387 'parsePostfixExpression_0': new MethodTrampoline(0, (Parser target) => target.
_parsePostfixExpression()), |
| 9388 'parsePrimaryExpression_0': new MethodTrampoline(0, (Parser target) => target.
_parsePrimaryExpression()), |
| 9389 'parseRedirectingConstructorInvocation_0': new MethodTrampoline(0, (Parser tar
get) => target._parseRedirectingConstructorInvocation()), |
| 9390 'parseRelationalExpression_0': new MethodTrampoline(0, (Parser target) => targ
et._parseRelationalExpression()), |
| 9391 'parseRethrowExpression_0': new MethodTrampoline(0, (Parser target) => target.
_parseRethrowExpression()), |
| 9392 'parseReturnStatement_0': new MethodTrampoline(0, (Parser target) => target._p
arseReturnStatement()), |
| 9393 'parseSetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2, arg
3) => target._parseSetter(arg0, arg1, arg2, arg3)), |
| 9394 'parseShiftExpression_0': new MethodTrampoline(0, (Parser target) => target._p
arseShiftExpression()), |
| 9395 'parseStatementList_0': new MethodTrampoline(0, (Parser target) => target._par
seStatementList()), |
| 9396 'parseStringInterpolation_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._parseStringInterpolation(arg0)), |
| 9397 'parseSuperConstructorInvocation_0': new MethodTrampoline(0, (Parser target) =
> target._parseSuperConstructorInvocation()), |
| 9398 'parseSwitchStatement_0': new MethodTrampoline(0, (Parser target) => target._p
arseSwitchStatement()), |
| 9399 'parseSymbolLiteral_0': new MethodTrampoline(0, (Parser target) => target._par
seSymbolLiteral()), |
| 9400 'parseThrowExpression_0': new MethodTrampoline(0, (Parser target) => target._p
arseThrowExpression()), |
| 9401 'parseThrowExpressionWithoutCascade_0': new MethodTrampoline(0, (Parser target
) => target._parseThrowExpressionWithoutCascade()), |
| 9402 'parseTryStatement_0': new MethodTrampoline(0, (Parser target) => target._pars
eTryStatement()), |
| 9403 'parseTypeAlias_1': new MethodTrampoline(1, (Parser target, arg0) => target._p
arseTypeAlias(arg0)), |
| 9404 'parseUnaryExpression_0': new MethodTrampoline(0, (Parser target) => target._p
arseUnaryExpression()), |
| 9405 'parseVariableDeclaration_0': new MethodTrampoline(0, (Parser target) => targe
t._parseVariableDeclaration()), |
| 9406 'parseVariableDeclarationListAfterMetadata_1': new MethodTrampoline(1, (Parser
target, arg0) => target._parseVariableDeclarationListAfterMetadata(arg0)), |
| 9407 'parseVariableDeclarationListAfterType_3': new MethodTrampoline(3, (Parser tar
get, arg0, arg1, arg2) => target._parseVariableDeclarationListAfterType(arg0, ar
g1, arg2)), |
| 9408 'parseVariableDeclarationStatementAfterMetadata_1': new MethodTrampoline(1, (P
arser target, arg0) => target._parseVariableDeclarationStatementAfterMetadata(ar
g0)), |
| 9409 'parseVariableDeclarationStatementAfterType_3': new MethodTrampoline(3, (Parse
r target, arg0, arg1, arg2) => target._parseVariableDeclarationStatementAfterTyp
e(arg0, arg1, arg2)), |
| 9410 'parseWhileStatement_0': new MethodTrampoline(0, (Parser target) => target._pa
rseWhileStatement()), |
| 9411 'parseYieldStatement_0': new MethodTrampoline(0, (Parser target) => target._pa
rseYieldStatement()), |
| 9412 'peek_0': new MethodTrampoline(0, (Parser target) => target._peek()), |
| 9413 'peekAt_1': new MethodTrampoline(1, (Parser target, arg0) => target._peekAt(ar
g0)), |
| 9414 'reportError_1': new MethodTrampoline(1, (Parser target, arg0) => target._repo
rtError(arg0)), |
| 9415 'reportErrorForCurrentToken_2': new MethodTrampoline(2, (Parser target, arg0,
arg1) => target._reportErrorForCurrentToken(arg0, arg1)), |
| 9416 'reportErrorForNode_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar
g2) => target._reportErrorForNode(arg0, arg1, arg2)), |
| 9417 'reportErrorForToken_3': new MethodTrampoline(3, (Parser target, arg0, arg1, a
rg2) => target._reportErrorForToken(arg0, arg1, arg2)), |
| 9418 'skipBlock_0': new MethodTrampoline(0, (Parser target) => target._skipBlock())
, |
| 9419 'skipFinalConstVarOrType_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._skipFinalConstVarOrType(arg0)), |
| 9420 'skipFormalParameterList_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._skipFormalParameterList(arg0)), |
| 9421 'skipPastMatchingToken_1': new MethodTrampoline(1, (Parser target, arg0) => ta
rget._skipPastMatchingToken(arg0)), |
| 9422 'skipPrefixedIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => t
arget._skipPrefixedIdentifier(arg0)), |
| 9423 'skipReturnType_1': new MethodTrampoline(1, (Parser target, arg0) => target._s
kipReturnType(arg0)), |
| 9424 'skipSimpleIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._skipSimpleIdentifier(arg0)), |
| 9425 'skipStringInterpolation_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._skipStringInterpolation(arg0)), |
| 9426 'skipStringLiteral_1': new MethodTrampoline(1, (Parser target, arg0) => target
._skipStringLiteral(arg0)), |
| 9427 'skipTypeArgumentList_1': new MethodTrampoline(1, (Parser target, arg0) => tar
get._skipTypeArgumentList(arg0)), |
| 9428 'skipTypeName_1': new MethodTrampoline(1, (Parser target, arg0) => target._ski
pTypeName(arg0)), |
| 9429 'skipTypeParameterList_1': new MethodTrampoline(1, (Parser target, arg0) => ta
rget._skipTypeParameterList(arg0)), |
| 9430 'tokenMatches_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => targe
t._tokenMatches(arg0, arg1)), |
| 9431 'tokenMatchesIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => t
arget._tokenMatchesIdentifier(arg0)), |
| 9432 'tokenMatchesKeyword_2': new MethodTrampoline(2, (Parser target, arg0, arg1) =
> target._tokenMatchesKeyword(arg0, arg1)), |
| 9433 'tokenMatchesString_2': new MethodTrampoline(2, (Parser target, arg0, arg1) =>
target._tokenMatchesString(arg0, arg1)), |
| 9434 'translateCharacter_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar
g2) => target._translateCharacter(arg0, arg1, arg2)), |
| 9435 'unlockErrorListener_0': new MethodTrampoline(0, (Parser target) => target._un
lockErrorListener()), |
| 9436 'validateFormalParameterList_1': new MethodTrampoline(1, (Parser target, arg0)
=> target._validateFormalParameterList(arg0)), |
| 9437 'validateModifiersForClass_1': new MethodTrampoline(1, (Parser target, arg0) =
> target._validateModifiersForClass(arg0)), |
| 9438 'validateModifiersForConstructor_1': new MethodTrampoline(1, (Parser target, a
rg0) => target._validateModifiersForConstructor(arg0)), |
| 9439 'validateModifiersForEnum_1': new MethodTrampoline(1, (Parser target, arg0) =>
target._validateModifiersForEnum(arg0)), |
| 9440 'validateModifiersForField_1': new MethodTrampoline(1, (Parser target, arg0) =
> target._validateModifiersForField(arg0)), |
| 9441 'validateModifiersForFunctionDeclarationStatement_1': new MethodTrampoline(1,
(Parser target, arg0) => target._validateModifiersForFunctionDeclarationStatemen
t(arg0)), |
| 9442 'validateModifiersForGetterOrSetterOrMethod_1': new MethodTrampoline(1, (Parse
r target, arg0) => target._validateModifiersForGetterOrSetterOrMethod(arg0)), |
| 9443 'validateModifiersForOperator_1': new MethodTrampoline(1, (Parser target, arg0
) => target._validateModifiersForOperator(arg0)), |
| 9444 'validateModifiersForTopLevelDeclaration_1': new MethodTrampoline(1, (Parser t
arget, arg0) => target._validateModifiersForTopLevelDeclaration(arg0)), |
| 9445 'validateModifiersForTopLevelFunction_1': new MethodTrampoline(1, (Parser targ
et, arg0) => target._validateModifiersForTopLevelFunction(arg0)), |
| 9446 'validateModifiersForTopLevelVariable_1': new MethodTrampoline(1, (Parser targ
et, arg0) => target._validateModifiersForTopLevelVariable(arg0)), |
| 9447 'validateModifiersForTypedef_1': new MethodTrampoline(1, (Parser target, arg0)
=> target._validateModifiersForTypedef(arg0)),}; |
| 9448 |
| 9449 |
| 9450 Object invokeParserMethodImpl(Parser parser, String methodName, List<Object> obj
ects, Token tokenStream) { |
| 9451 parser.currentToken = tokenStream; |
| 9452 MethodTrampoline method = methodTable_Parser['${methodName}_${objects.length}'
]; |
| 9453 return method.invoke(parser, objects); |
| 9454 } |
| 9455 |
| 9456 |
| 9457 /** |
| 9458 * Wrapper around [Function] which should be called with "target" and "arguments
". |
| 9459 */ |
| 9460 class MethodTrampoline { |
| 9461 int parameterCount; |
| 9462 Function trampoline; |
| 9463 MethodTrampoline(this.parameterCount, this.trampoline); |
| 9464 Object invoke(target, List arguments) { |
| 9465 if (arguments.length != parameterCount) { |
| 9466 throw new IllegalArgumentException("${arguments.length} != $parameterCount
"); |
| 9467 } |
| 9468 switch (parameterCount) { |
| 9469 case 0: |
| 9470 return trampoline(target); |
| 9471 case 1: |
| 9472 return trampoline(target, arguments[0]); |
| 9473 case 2: |
| 9474 return trampoline(target, arguments[0], arguments[1]); |
| 9475 case 3: |
| 9476 return trampoline(target, arguments[0], arguments[1], arguments[2]); |
| 9477 case 4: |
| 9478 return trampoline(target, arguments[0], arguments[1], arguments[2], argu
ments[3]); |
| 9479 default: |
| 9480 throw new IllegalArgumentException("Not implemented for > 4 arguments"); |
| 9481 } |
| 9482 } |
| 9483 } |
OLD | NEW |