| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, 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 grammar Dart; | |
| 6 | |
| 7 options { | |
| 8 backtrack = true; | |
| 9 memoize = true; | |
| 10 output = AST; | |
| 11 } | |
| 12 | |
| 13 | |
| 14 // ----------------------------------------------------------------- | |
| 15 // Keyword definitions. | |
| 16 // ----------------------------------------------------------------- | |
| 17 tokens { | |
| 18 BREAK = 'break'; | |
| 19 CASE = 'case'; | |
| 20 CATCH = 'catch'; | |
| 21 CONST = 'const'; | |
| 22 CONTINUE = 'continue'; | |
| 23 DEFAULT = 'default'; | |
| 24 DO = 'do'; | |
| 25 ELSE = 'else'; | |
| 26 FALSE = 'false'; | |
| 27 FINAL = 'final'; | |
| 28 FINALLY = 'finally'; | |
| 29 FOR = 'for'; | |
| 30 IF = 'if'; | |
| 31 IN = 'in'; | |
| 32 NEW = 'new'; | |
| 33 NULL = 'null'; | |
| 34 RETURN = 'return'; | |
| 35 SUPER = 'super'; | |
| 36 SWITCH = 'switch'; | |
| 37 THIS = 'this'; | |
| 38 THROW = 'throw'; | |
| 39 TRUE = 'true'; | |
| 40 TRY = 'try'; | |
| 41 VAR = 'var'; | |
| 42 VOID = 'void'; | |
| 43 WHILE = 'while'; | |
| 44 | |
| 45 // Pseudo-keywords that should also be valid identifiers. | |
| 46 ABSTRACT = 'abstract'; | |
| 47 ASSERT = 'assert'; | |
| 48 CLASS = 'class'; | |
| 49 EXTENDS = 'extends'; | |
| 50 FACTORY = 'factory'; | |
| 51 GET = 'get'; | |
| 52 IMPLEMENTS = 'implements'; | |
| 53 IMPORT = 'import'; | |
| 54 INTERFACE = 'interface'; | |
| 55 IS = 'is'; | |
| 56 LIBRARY = 'library'; | |
| 57 NATIVE = 'native'; | |
| 58 NEGATE = 'negate'; | |
| 59 OPERATOR = 'operator'; | |
| 60 SET = 'set'; | |
| 61 SOURCE = 'source'; | |
| 62 STATIC = 'static'; | |
| 63 TYPEDEF = 'typedef'; | |
| 64 } | |
| 65 | |
| 66 @header { | |
| 67 package com.google.dart.antlr; | |
| 68 } | |
| 69 | |
| 70 @lexer::header { | |
| 71 package com.google.dart.antlr; | |
| 72 } | |
| 73 | |
| 74 @lexer::members { | |
| 75 public boolean hasErrors = false; | |
| 76 | |
| 77 @Override | |
| 78 public String getErrorHeader(RecognitionException exception) { | |
| 79 String sourceName = input.getSourceName(); | |
| 80 if (sourceName == null) { | |
| 81 sourceName = "<unknown source>"; | |
| 82 } | |
| 83 return sourceName + ":" + exception.line + ":" | |
| 84 + (exception.charPositionInLine + 1) + ":"; | |
| 85 } | |
| 86 | |
| 87 @Override | |
| 88 public void reportError(RecognitionException exception) { | |
| 89 hasErrors = true; | |
| 90 super.reportError(exception); | |
| 91 } | |
| 92 | |
| 93 // Disable single token insertion and deletion, see: | |
| 94 // http://www.antlr.org/wiki/display/ANTLR3/Error+reporting+and+recovery | |
| 95 @Override | |
| 96 protected Object recoverFromMismatchedToken(IntStream input, | |
| 97 int ttype, | |
| 98 BitSet follow) | |
| 99 throws RecognitionException | |
| 100 { | |
| 101 throw new MismatchedTokenException(ttype, input); | |
| 102 } | |
| 103 | |
| 104 private void error(String message) { | |
| 105 hasErrors = true; | |
| 106 int line = state.tokenStartLine; | |
| 107 int column = state.tokenStartCharPositionInLine; | |
| 108 String sourceName = input.getSourceName(); | |
| 109 if (sourceName == null) { | |
| 110 sourceName = "<unknown source>"; | |
| 111 } | |
| 112 emitErrorMessage(sourceName + ":" + line + ":" + (column + 1) + ": " | |
| 113 + message); | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 @members { | |
| 118 public boolean hasErrors = false; | |
| 119 | |
| 120 private boolean parseFunctionExpressions = true; | |
| 121 private boolean setParseFunctionExpressions(boolean value) { | |
| 122 boolean old = parseFunctionExpressions; | |
| 123 parseFunctionExpressions = value; | |
| 124 return old; | |
| 125 } | |
| 126 | |
| 127 @Override | |
| 128 public String getErrorHeader(RecognitionException exception) { | |
| 129 String sourceName = input.getSourceName(); | |
| 130 if (sourceName == null) { | |
| 131 sourceName = "<unknown source>"; | |
| 132 } | |
| 133 return sourceName + ":" + exception.line + ":" | |
| 134 + (exception.charPositionInLine + 1) + ":"; | |
| 135 } | |
| 136 | |
| 137 @Override | |
| 138 public void reportError(RecognitionException exception) { | |
| 139 hasErrors = true; | |
| 140 super.reportError(exception); | |
| 141 } | |
| 142 | |
| 143 // What to do with this method? Currently, error recovery | |
| 144 // is brain-dead and we often get too many error messages just from | |
| 145 // one error. This method represents one extreme solution to that | |
| 146 // problem. | |
| 147 // @Override | |
| 148 // public void recover(IntStream input, RecognitionException re) { | |
| 149 // // Consume all input so we only see one parser error. This trick | |
| 150 // // does not work for the lexer. | |
| 151 // consumeUntil(input, Token.EOF); | |
| 152 // } | |
| 153 | |
| 154 // Disable single token insertion and deletion, see: | |
| 155 // http://www.antlr.org/wiki/display/ANTLR3/Error+reporting+and+recovery | |
| 156 @Override | |
| 157 protected Object recoverFromMismatchedToken(IntStream input, | |
| 158 int ttype, | |
| 159 BitSet follow) | |
| 160 throws RecognitionException | |
| 161 { | |
| 162 throw new MismatchedTokenException(ttype, input); | |
| 163 } | |
| 164 | |
| 165 private Token firstHiddenToken() { | |
| 166 Token token = input.LT(1); // The next token. | |
| 167 int index = token.getTokenIndex() - 1; // The previous token. | |
| 168 if (index >= 0) { | |
| 169 token = input.get(index); | |
| 170 } | |
| 171 // Skip whitespace, comments, etc. | |
| 172 while ((index > 0) && (token.getChannel() == Token.HIDDEN_CHANNEL)) { | |
| 173 token = input.get(--index); | |
| 174 } | |
| 175 return input.get(index + 1); | |
| 176 } | |
| 177 | |
| 178 private void emitMessage(Token token, String message) { | |
| 179 int line = token.getLine(); | |
| 180 int column = token.getCharPositionInLine(); | |
| 181 String sourceName = input.getSourceName(); | |
| 182 if (sourceName == null) { | |
| 183 sourceName = "<unknown source>"; | |
| 184 } | |
| 185 emitErrorMessage(sourceName + ":" + line + ":" + (column + 1) + ": " | |
| 186 + message); | |
| 187 } | |
| 188 | |
| 189 private void warning(Token token, String message) { | |
| 190 emitMessage(token, "warning: " + message); | |
| 191 } | |
| 192 | |
| 193 private void legacy(Token token, String message) { | |
| 194 warning(token, message); | |
| 195 } | |
| 196 | |
| 197 private void semicolon() { | |
| 198 error(null, "missing ';'"); | |
| 199 } | |
| 200 | |
| 201 private void error(Token token, String message) { | |
| 202 if (token == null) { | |
| 203 token = firstHiddenToken(); | |
| 204 } | |
| 205 hasErrors = true; | |
| 206 emitMessage(token, message); | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 // ----------------------------------------------------------------- | |
| 211 // Grammar productions. | |
| 212 // ----------------------------------------------------------------- | |
| 213 compilationUnit | |
| 214 : HASHBANG? directive* topLevelDefinition* EOF | |
| 215 ; | |
| 216 | |
| 217 directive | |
| 218 : '#' identifier arguments ';' | |
| 219 ; | |
| 220 | |
| 221 topLevelDefinition | |
| 222 : (CLASS)=> classDefinition | |
| 223 | (INTERFACE)=> interfaceDefinition | |
| 224 | (TYPEDEF)=> functionTypeAlias | |
| 225 | functionDeclaration functionBodyOrNative | |
| 226 | returnType? getOrSet identifier formalParameterList functionBodyOrNative | |
| 227 | FINAL type? staticFinalDeclarationList ';' | |
| 228 | constInitializedVariableDeclaration ';' | |
| 229 ; | |
| 230 | |
| 231 classDefinition | |
| 232 : CLASS identifier typeParameters? superclass? interfaces? | |
| 233 '{' classMemberDefinition* '}' | |
| 234 | CLASS identifier typeParameters? interfaces? NATIVE STRING | |
| 235 '{' classMemberDefinition* '}' | |
| 236 { warning($start, "DartC: native can only be used in platform code"); } | |
| 237 ; | |
| 238 | |
| 239 typeParameter | |
| 240 : identifier (EXTENDS type)? | |
| 241 ; | |
| 242 | |
| 243 typeParameters | |
| 244 : '<' typeParameter (',' typeParameter)* '>' | |
| 245 ; | |
| 246 | |
| 247 superclass | |
| 248 : EXTENDS type | |
| 249 ; | |
| 250 | |
| 251 interfaces | |
| 252 : IMPLEMENTS typeList | |
| 253 ; | |
| 254 | |
| 255 superinterfaces | |
| 256 : EXTENDS typeList | |
| 257 ; | |
| 258 | |
| 259 // This rule is organized in a way that may not be most readable, but | |
| 260 // gives the best error messages. | |
| 261 classMemberDefinition | |
| 262 : declaration ';' | |
| 263 | constructorDeclaration ';' | |
| 264 | methodDeclaration functionBodyOrNative | |
| 265 | CONST factoryConstructorDeclaration functionNative | |
| 266 ; | |
| 267 | |
| 268 functionBodyOrNative | |
| 269 : NATIVE functionBody | |
| 270 { warning($start, "native function with body only works on DartC"); } | |
| 271 | functionNative | |
| 272 | functionBody | |
| 273 ; | |
| 274 | |
| 275 functionNative | |
| 276 : NATIVE STRING? ';' | |
| 277 { warning($start, "native can only be used in platform code"); } | |
| 278 ; | |
| 279 | |
| 280 // A method, operator, or constructor (which all should be followed by | |
| 281 // a block of code). | |
| 282 methodDeclaration | |
| 283 : factoryConstructorDeclaration | |
| 284 | STATIC functionDeclaration | |
| 285 | specialSignatureDefinition | |
| 286 | functionDeclaration initializers? | |
| 287 | namedConstructorDeclaration initializers? | |
| 288 ; | |
| 289 | |
| 290 // An abstract method/operator, a field, or const constructor (which | |
| 291 // all should be followed by a semicolon). | |
| 292 declaration | |
| 293 : constantConstructorDeclaration (redirection | initializers)? | |
| 294 | functionDeclaration redirection | |
| 295 | namedConstructorDeclaration redirection | |
| 296 | ABSTRACT specialSignatureDefinition | |
| 297 | ABSTRACT functionDeclaration | |
| 298 | STATIC FINAL type? staticFinalDeclarationList | |
| 299 | STATIC? constInitializedVariableDeclaration | |
| 300 ; | |
| 301 | |
| 302 initializers | |
| 303 : ':' superCallOrFieldInitializer (',' superCallOrFieldInitializer)* | |
| 304 ; | |
| 305 | |
| 306 redirection | |
| 307 : ':' THIS ('.' identifier)? arguments | |
| 308 ; | |
| 309 | |
| 310 fieldInitializer | |
| 311 @init { boolean old = setParseFunctionExpressions(false); } | |
| 312 : (THIS '.')? identifier '=' conditionalExpression | |
| 313 ; | |
| 314 finally { setParseFunctionExpressions(old); } | |
| 315 | |
| 316 superCallOrFieldInitializer | |
| 317 : SUPER arguments | |
| 318 | SUPER '.' identifier arguments | |
| 319 | fieldInitializer | |
| 320 ; | |
| 321 | |
| 322 staticFinalDeclarationList | |
| 323 : staticFinalDeclaration (',' staticFinalDeclaration)* | |
| 324 ; | |
| 325 | |
| 326 staticFinalDeclaration | |
| 327 : identifier '=' constantExpression | |
| 328 ; | |
| 329 | |
| 330 interfaceDefinition | |
| 331 : INTERFACE identifier typeParameters? superinterfaces? | |
| 332 factorySpecification? '{' (interfaceMemberDefinition)* '}' | |
| 333 ; | |
| 334 | |
| 335 factorySpecification | |
| 336 : FACTORY type | |
| 337 ; | |
| 338 | |
| 339 functionTypeAlias | |
| 340 : TYPEDEF functionPrefix typeParameters? formalParameterList ';' | |
| 341 ; | |
| 342 | |
| 343 interfaceMemberDefinition | |
| 344 : STATIC FINAL type? initializedIdentifierList ';' | |
| 345 | functionDeclaration ';' | |
| 346 | constantConstructorDeclaration ';' | |
| 347 | namedConstructorDeclaration ';' | |
| 348 | specialSignatureDefinition ';' | |
| 349 | variableDeclaration ';' | |
| 350 ; | |
| 351 | |
| 352 factoryConstructorDeclaration | |
| 353 : FACTORY qualified typeParameters? ('.' identifier)? formalParameterList | |
| 354 ; | |
| 355 | |
| 356 namedConstructorDeclaration | |
| 357 : identifier '.' identifier formalParameterList | |
| 358 ; | |
| 359 | |
| 360 constructorDeclaration | |
| 361 : identifier formalParameterList (redirection | initializers)? | |
| 362 | namedConstructorDeclaration (redirection | initializers)? | |
| 363 ; | |
| 364 | |
| 365 constantConstructorDeclaration | |
| 366 : CONST qualified formalParameterList | |
| 367 ; | |
| 368 | |
| 369 specialSignatureDefinition | |
| 370 : STATIC? returnType? getOrSet identifier formalParameterList | |
| 371 | returnType? OPERATOR userDefinableOperator formalParameterList | |
| 372 ; | |
| 373 | |
| 374 getOrSet | |
| 375 : GET | |
| 376 | SET | |
| 377 ; | |
| 378 | |
| 379 userDefinableOperator | |
| 380 : multiplicativeOperator | |
| 381 | additiveOperator | |
| 382 | shiftOperator | |
| 383 | relationalOperator | |
| 384 | bitwiseOperator | |
| 385 | '==' // Disallow negative and === equality checks. | |
| 386 | '~' // Disallow ! operator. | |
| 387 | NEGATE | |
| 388 | '[' ']' { "[]".equals($text) }? | |
| 389 | '[' ']' '=' { "[]=".equals($text) }? | |
| 390 ; | |
| 391 | |
| 392 prefixOperator | |
| 393 : additiveOperator | |
| 394 | negateOperator | |
| 395 ; | |
| 396 | |
| 397 postfixOperator | |
| 398 : incrementOperator | |
| 399 ; | |
| 400 | |
| 401 negateOperator | |
| 402 : '!' | |
| 403 | '~' | |
| 404 ; | |
| 405 | |
| 406 multiplicativeOperator | |
| 407 : '*' | |
| 408 | '/' | |
| 409 | '%' | |
| 410 | '~/' | |
| 411 ; | |
| 412 | |
| 413 assignmentOperator | |
| 414 : '=' | |
| 415 | '*=' | |
| 416 | '/=' | |
| 417 | '~/=' | |
| 418 | '%=' | |
| 419 | '+=' | |
| 420 | '-=' | |
| 421 | '<<=' | |
| 422 | '>' '>' '>' '=' { ">>>=".equals($text) }? | |
| 423 | '>' '>' '=' { ">>=".equals($text) }? | |
| 424 | '&=' | |
| 425 | '^=' | |
| 426 | '|=' | |
| 427 ; | |
| 428 | |
| 429 additiveOperator | |
| 430 : '+' | |
| 431 | '-' | |
| 432 ; | |
| 433 | |
| 434 incrementOperator | |
| 435 : '++' | |
| 436 | '--' | |
| 437 ; | |
| 438 | |
| 439 shiftOperator | |
| 440 : '<<' | |
| 441 | '>' '>' '>' { ">>>".equals($text) }? | |
| 442 | '>' '>' { ">>".equals($text) }? | |
| 443 ; | |
| 444 | |
| 445 relationalOperator | |
| 446 : '>' '=' { ">=".equals($text) }? | |
| 447 | '>' | |
| 448 | '<=' | |
| 449 | '<' | |
| 450 ; | |
| 451 | |
| 452 equalityOperator | |
| 453 : '==' | |
| 454 | '!=' | |
| 455 | '===' | |
| 456 | '!==' | |
| 457 ; | |
| 458 | |
| 459 bitwiseOperator | |
| 460 : '&' | |
| 461 | '^' | |
| 462 | '|' | |
| 463 ; | |
| 464 | |
| 465 formalParameterList | |
| 466 : '(' namedFormalParameters? ')' | |
| 467 | '(' normalFormalParameter normalFormalParameterTail? ')' | |
| 468 ; | |
| 469 | |
| 470 normalFormalParameterTail | |
| 471 : ',' namedFormalParameters | |
| 472 | ',' normalFormalParameter normalFormalParameterTail? | |
| 473 ; | |
| 474 | |
| 475 normalFormalParameter | |
| 476 : functionDeclaration | |
| 477 | fieldFormalParameter | |
| 478 | simpleFormalParameter | |
| 479 ; | |
| 480 | |
| 481 simpleFormalParameter | |
| 482 : declaredIdentifier | |
| 483 | identifier | |
| 484 ; | |
| 485 | |
| 486 fieldFormalParameter | |
| 487 : finalVarOrType? THIS '.' identifier | |
| 488 ; | |
| 489 | |
| 490 namedFormalParameters | |
| 491 : '[' defaultFormalParameter (',' defaultFormalParameter)* ']' | |
| 492 ; | |
| 493 | |
| 494 defaultFormalParameter | |
| 495 : normalFormalParameter ('=' constantExpression)? | |
| 496 ; | |
| 497 | |
| 498 returnType | |
| 499 : VOID | |
| 500 | type | |
| 501 ; | |
| 502 | |
| 503 finalVarOrType | |
| 504 : FINAL type? | |
| 505 | VAR | |
| 506 | type | |
| 507 ; | |
| 508 | |
| 509 // We have to introduce a separate rule for 'declared' identifiers to | |
| 510 // allow ANTLR to decide if the first identifier we encounter after | |
| 511 // final is a type or an identifier. Before this change, we used the | |
| 512 // production 'finalVarOrType identifier' in numerous places. | |
| 513 declaredIdentifier | |
| 514 : FINAL type? identifier | |
| 515 | VAR identifier | |
| 516 | type identifier | |
| 517 ; | |
| 518 | |
| 519 identifier | |
| 520 : IDENTIFIER_NO_DOLLAR | |
| 521 | IDENTIFIER | |
| 522 | ABSTRACT | |
| 523 | ASSERT | |
| 524 | CLASS | |
| 525 | EXTENDS | |
| 526 | FACTORY | |
| 527 | GET | |
| 528 | IMPLEMENTS | |
| 529 | IMPORT | |
| 530 | INTERFACE | |
| 531 | IS | |
| 532 | LIBRARY | |
| 533 | NATIVE | |
| 534 | NEGATE | |
| 535 | OPERATOR | |
| 536 | SET | |
| 537 | SOURCE | |
| 538 | STATIC | |
| 539 | TYPEDEF | |
| 540 ; | |
| 541 | |
| 542 qualified | |
| 543 : identifier ('.' identifier)? | |
| 544 ; | |
| 545 | |
| 546 type | |
| 547 : qualified typeArguments? | |
| 548 ; | |
| 549 | |
| 550 typeArguments | |
| 551 : '<' typeList '>' | |
| 552 ; | |
| 553 | |
| 554 typeList | |
| 555 : type (',' type)* | |
| 556 ; | |
| 557 | |
| 558 block | |
| 559 : '{' statements '}' | |
| 560 ; | |
| 561 | |
| 562 statements | |
| 563 : statement* | |
| 564 ; | |
| 565 | |
| 566 statement | |
| 567 : label* nonLabelledStatement | |
| 568 ; | |
| 569 | |
| 570 nonLabelledStatement | |
| 571 : ('{')=> block // Guard to break tie with map literal. | |
| 572 | initializedVariableDeclaration ';' | |
| 573 | iterationStatement | |
| 574 | selectionStatement | |
| 575 | tryStatement | |
| 576 | BREAK identifier? ';' | |
| 577 | CONTINUE identifier? ';' | |
| 578 | RETURN expression? ';' | |
| 579 | THROW expression? ';' | |
| 580 | expression? ';' | |
| 581 | ASSERT '(' conditionalExpression ')' ';' | |
| 582 | functionDeclaration functionBody | |
| 583 ; | |
| 584 | |
| 585 label | |
| 586 : identifier ':' | |
| 587 ; | |
| 588 | |
| 589 iterationStatement | |
| 590 : WHILE '(' expression ')' statement | |
| 591 | DO statement WHILE '(' expression ')' ';' | |
| 592 | FOR '(' forLoopParts ')' statement | |
| 593 ; | |
| 594 | |
| 595 forLoopParts | |
| 596 : forInitializerStatement expression? ';' expressionList? | |
| 597 | declaredIdentifier IN expression | |
| 598 | identifier IN expression | |
| 599 ; | |
| 600 | |
| 601 forInitializerStatement | |
| 602 : initializedVariableDeclaration ';' | |
| 603 | expression? ';' | |
| 604 ; | |
| 605 | |
| 606 selectionStatement | |
| 607 : IF '(' expression ')' statement ((ELSE)=> ELSE statement)? | |
| 608 | SWITCH '(' expression ')' '{' switchCase* defaultCase? '}' | |
| 609 ; | |
| 610 | |
| 611 switchCase | |
| 612 : label? (CASE expression ':')+ statements | |
| 613 ; | |
| 614 | |
| 615 defaultCase | |
| 616 : label? (CASE expression ':')* DEFAULT ':' statements | |
| 617 ; | |
| 618 | |
| 619 tryStatement | |
| 620 : TRY block (catchPart+ finallyPart? | finallyPart) | |
| 621 ; | |
| 622 | |
| 623 catchPart | |
| 624 : CATCH '(' declaredIdentifier (',' declaredIdentifier)? ')' block | |
| 625 ; | |
| 626 | |
| 627 finallyPart | |
| 628 : FINALLY block | |
| 629 ; | |
| 630 | |
| 631 variableDeclaration | |
| 632 : declaredIdentifier (',' identifier)* | |
| 633 ; | |
| 634 | |
| 635 initializedVariableDeclaration | |
| 636 : declaredIdentifier ('=' expression)? (',' initializedIdentifier)* | |
| 637 ; | |
| 638 | |
| 639 initializedIdentifierList | |
| 640 : initializedIdentifier (',' initializedIdentifier)* | |
| 641 ; | |
| 642 | |
| 643 initializedIdentifier | |
| 644 : identifier ('=' expression)? | |
| 645 ; | |
| 646 | |
| 647 constInitializedVariableDeclaration | |
| 648 : declaredIdentifier ('=' constantExpression)? | |
| 649 (',' constInitializedIdentifier)* | |
| 650 ; | |
| 651 | |
| 652 constInitializedIdentifier | |
| 653 : identifier ('=' constantExpression)? | |
| 654 ; | |
| 655 | |
| 656 // The constant expression production is used to mark certain expressions | |
| 657 // as only being allowed to hold a compile-time constant. The grammar cannot | |
| 658 // express these restrictions (yet), so this will have to be enforced by a | |
| 659 // separate analysis phase. | |
| 660 constantExpression | |
| 661 : expression | |
| 662 ; | |
| 663 | |
| 664 expression | |
| 665 : assignableExpression assignmentOperator expression | |
| 666 | conditionalExpression | |
| 667 ; | |
| 668 | |
| 669 expressionList | |
| 670 : expression (',' expression)* | |
| 671 ; | |
| 672 | |
| 673 arguments | |
| 674 @init { boolean old = setParseFunctionExpressions(true); } | |
| 675 : '(' argumentList? ')' | |
| 676 ; | |
| 677 finally { setParseFunctionExpressions(old); } | |
| 678 | |
| 679 argumentList | |
| 680 : namedArgument (',' namedArgument)* | |
| 681 | expressionList (',' namedArgument)* | |
| 682 ; | |
| 683 | |
| 684 namedArgument | |
| 685 : label expression | |
| 686 ; | |
| 687 | |
| 688 assignableExpression | |
| 689 : primary (arguments* assignableSelector)+ | |
| 690 | SUPER assignableSelector | |
| 691 | identifier | |
| 692 ; | |
| 693 | |
| 694 conditionalExpression | |
| 695 : logicalOrExpression ('?' expression ':' expression)? | |
| 696 ; | |
| 697 | |
| 698 logicalOrExpression | |
| 699 : logicalAndExpression ('||' logicalAndExpression)* | |
| 700 ; | |
| 701 | |
| 702 logicalAndExpression | |
| 703 : bitwiseOrExpression ('&&' bitwiseOrExpression)* | |
| 704 ; | |
| 705 | |
| 706 bitwiseOrExpression | |
| 707 : bitwiseXorExpression ('|' bitwiseXorExpression)* | |
| 708 | SUPER ('|' bitwiseXorExpression)+ | |
| 709 ; | |
| 710 | |
| 711 bitwiseXorExpression | |
| 712 : bitwiseAndExpression ('^' bitwiseAndExpression)* | |
| 713 | SUPER ('^' bitwiseAndExpression)+ | |
| 714 ; | |
| 715 | |
| 716 bitwiseAndExpression | |
| 717 : equalityExpression ('&' equalityExpression)* | |
| 718 | SUPER ('&' equalityExpression)+ | |
| 719 ; | |
| 720 | |
| 721 equalityExpression | |
| 722 : relationalExpression (equalityOperator relationalExpression)? | |
| 723 | SUPER equalityOperator relationalExpression | |
| 724 ; | |
| 725 | |
| 726 relationalExpression | |
| 727 : shiftExpression (isOperator type | relationalOperator shiftExpression)? | |
| 728 | SUPER relationalOperator shiftExpression | |
| 729 ; | |
| 730 | |
| 731 isOperator | |
| 732 : IS '!'? | |
| 733 ; | |
| 734 | |
| 735 shiftExpression | |
| 736 : additiveExpression (shiftOperator additiveExpression)* | |
| 737 | SUPER (shiftOperator additiveExpression)+ | |
| 738 ; | |
| 739 | |
| 740 additiveExpression | |
| 741 : multiplicativeExpression (additiveOperator multiplicativeExpression)* | |
| 742 | SUPER (additiveOperator multiplicativeExpression)+ | |
| 743 ; | |
| 744 | |
| 745 multiplicativeExpression | |
| 746 : unaryExpression (multiplicativeOperator unaryExpression)* | |
| 747 | SUPER (multiplicativeOperator unaryExpression)+ | |
| 748 ; | |
| 749 | |
| 750 unaryExpression | |
| 751 : postfixExpression | |
| 752 | prefixOperator unaryExpression | |
| 753 | negateOperator SUPER | |
| 754 | '-' SUPER // Invokes the NEGATE operator. | |
| 755 | incrementOperator assignableExpression | |
| 756 ; | |
| 757 | |
| 758 postfixExpression | |
| 759 : assignableExpression postfixOperator | |
| 760 | primary selector* | |
| 761 ; | |
| 762 | |
| 763 selector | |
| 764 : assignableSelector | |
| 765 | arguments | |
| 766 ; | |
| 767 | |
| 768 assignableSelector | |
| 769 @init { boolean old = setParseFunctionExpressions(true); } | |
| 770 : '[' expression ']' | |
| 771 | '.' identifier | |
| 772 ; | |
| 773 finally { setParseFunctionExpressions(old); } | |
| 774 | |
| 775 primary | |
| 776 : {!parseFunctionExpressions}?=> primaryNoFE | |
| 777 | primaryFE | |
| 778 ; | |
| 779 | |
| 780 primaryFE | |
| 781 : functionExpression | |
| 782 | primaryNoFE | |
| 783 ; | |
| 784 | |
| 785 primaryNoFE | |
| 786 : THIS | |
| 787 | SUPER assignableSelector | |
| 788 | literal | |
| 789 | identifier | |
| 790 | CONST? typeArguments? compoundLiteral | |
| 791 | (NEW | CONST) type ('.' identifier)? arguments | |
| 792 | expressionInParentheses | |
| 793 ; | |
| 794 | |
| 795 expressionInParentheses | |
| 796 @init { boolean old = setParseFunctionExpressions(true); } | |
| 797 :'(' expression ')' | |
| 798 ; | |
| 799 finally { setParseFunctionExpressions(old); } | |
| 800 | |
| 801 literal | |
| 802 : NULL | |
| 803 | TRUE | |
| 804 | FALSE | |
| 805 | HEX_NUMBER | |
| 806 | NUMBER | |
| 807 | STRING | |
| 808 ; | |
| 809 | |
| 810 compoundLiteral | |
| 811 @init { boolean old = setParseFunctionExpressions(true); } | |
| 812 : listLiteral | |
| 813 | mapLiteral | |
| 814 ; | |
| 815 finally { setParseFunctionExpressions(old); } | |
| 816 | |
| 817 // The list literal syntax doesn't allow elided elements, unlike | |
| 818 // in ECMAScript. We do allow a trailing comma. | |
| 819 listLiteral | |
| 820 : '[' (expressionList ','?)? ']' | |
| 821 ; | |
| 822 | |
| 823 mapLiteral | |
| 824 : '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' | |
| 825 ; | |
| 826 | |
| 827 mapLiteralEntry | |
| 828 : STRING ':' expression | |
| 829 ; | |
| 830 | |
| 831 functionExpression | |
| 832 : (returnType? identifier)? formalParameterList functionExpressionBody | |
| 833 ; | |
| 834 | |
| 835 functionDeclaration | |
| 836 : returnType? identifier formalParameterList | |
| 837 ; | |
| 838 | |
| 839 functionPrefix | |
| 840 : returnType? identifier | |
| 841 ; | |
| 842 | |
| 843 functionBody | |
| 844 : '=>' expression ';' | |
| 845 | block | |
| 846 ; | |
| 847 | |
| 848 functionExpressionBody | |
| 849 : '=>' expression | |
| 850 | block | |
| 851 ; | |
| 852 | |
| 853 // ----------------------------------------------------------------- | |
| 854 // Library files. | |
| 855 // ----------------------------------------------------------------- | |
| 856 libraryUnit | |
| 857 : libraryDefinition EOF | |
| 858 ; | |
| 859 | |
| 860 libraryDefinition | |
| 861 : LIBRARY '{' libraryBody '}' | |
| 862 ; | |
| 863 | |
| 864 libraryBody | |
| 865 : libraryImport? librarySource? | |
| 866 ; | |
| 867 | |
| 868 libraryImport | |
| 869 : IMPORT '=' '[' importReferences? ']' | |
| 870 ; | |
| 871 | |
| 872 importReferences | |
| 873 : importReference (',' importReference)* ','? | |
| 874 ; | |
| 875 | |
| 876 importReference | |
| 877 : (IDENTIFIER ':')? STRING | |
| 878 ; | |
| 879 | |
| 880 librarySource | |
| 881 : SOURCE '=' '[' sourceUrls? ']' | |
| 882 ; | |
| 883 | |
| 884 sourceUrls | |
| 885 : STRING (',' STRING)* ','? | |
| 886 ; | |
| 887 | |
| 888 | |
| 889 // ----------------------------------------------------------------- | |
| 890 // Lexical tokens. | |
| 891 // ----------------------------------------------------------------- | |
| 892 IDENTIFIER_NO_DOLLAR | |
| 893 : IDENTIFIER_START_NO_DOLLAR IDENTIFIER_PART_NO_DOLLAR* | |
| 894 ; | |
| 895 | |
| 896 IDENTIFIER | |
| 897 : IDENTIFIER_START IDENTIFIER_PART* | |
| 898 ; | |
| 899 | |
| 900 HEX_NUMBER | |
| 901 : '0x' HEX_DIGIT+ | |
| 902 | '0X' HEX_DIGIT+ | |
| 903 ; | |
| 904 | |
| 905 NUMBER | |
| 906 : DIGIT+ NUMBER_OPT_FRACTIONAL_PART EXPONENT? NUMBER_OPT_ILLEGAL_END | |
| 907 | '.' DIGIT+ EXPONENT? NUMBER_OPT_ILLEGAL_END | |
| 908 ; | |
| 909 | |
| 910 fragment NUMBER_OPT_FRACTIONAL_PART | |
| 911 : ('.' DIGIT)=> ('.' DIGIT+) | |
| 912 | // Empty fractional part. | |
| 913 ; | |
| 914 | |
| 915 fragment NUMBER_OPT_ILLEGAL_END | |
| 916 : (IDENTIFIER_START)=> { error("numbers cannot contain identifiers"); } | |
| 917 | // Empty illegal end (good!). | |
| 918 ; | |
| 919 | |
| 920 fragment HEX_DIGIT | |
| 921 : 'a'..'f' | |
| 922 | 'A'..'F' | |
| 923 | DIGIT | |
| 924 ; | |
| 925 | |
| 926 fragment IDENTIFIER_START | |
| 927 : IDENTIFIER_START_NO_DOLLAR | |
| 928 | '$' | |
| 929 ; | |
| 930 | |
| 931 fragment IDENTIFIER_START_NO_DOLLAR | |
| 932 : LETTER | |
| 933 | '_' | |
| 934 ; | |
| 935 | |
| 936 fragment IDENTIFIER_PART_NO_DOLLAR | |
| 937 : IDENTIFIER_START_NO_DOLLAR | |
| 938 | DIGIT | |
| 939 ; | |
| 940 | |
| 941 fragment IDENTIFIER_PART | |
| 942 : IDENTIFIER_START | |
| 943 | DIGIT | |
| 944 ; | |
| 945 | |
| 946 // Bug 5408613: Should be Unicode characters. | |
| 947 fragment LETTER | |
| 948 : 'a'..'z' | |
| 949 | 'A'..'Z' | |
| 950 ; | |
| 951 | |
| 952 fragment DIGIT | |
| 953 : '0'..'9' | |
| 954 ; | |
| 955 | |
| 956 fragment EXPONENT | |
| 957 : ('e' | 'E') ('+' | '-')? DIGIT+ | |
| 958 ; | |
| 959 | |
| 960 STRING | |
| 961 : '@'? MULTI_LINE_STRING | |
| 962 | SINGLE_LINE_STRING | |
| 963 ; | |
| 964 | |
| 965 fragment MULTI_LINE_STRING | |
| 966 options { greedy=false; } | |
| 967 : '"""' .* '"""' | |
| 968 | '\'\'\'' .* '\'\'\'' | |
| 969 ; | |
| 970 | |
| 971 fragment SINGLE_LINE_STRING | |
| 972 : '"' STRING_CONTENT_DQ* '"' | |
| 973 | '\'' STRING_CONTENT_SQ* '\'' | |
| 974 | '@' '\'' (~( '\'' | NEWLINE ))* '\'' | |
| 975 | '@' '"' (~( '"' | NEWLINE ))* '"' | |
| 976 ; | |
| 977 | |
| 978 fragment STRING_CONTENT_DQ | |
| 979 : ~( '\\' | '"' | NEWLINE ) | |
| 980 | '\\' ~( NEWLINE ) | |
| 981 ; | |
| 982 | |
| 983 fragment STRING_CONTENT_SQ | |
| 984 : ~( '\\' | '\'' | NEWLINE ) | |
| 985 | '\\' ~( NEWLINE ) | |
| 986 ; | |
| 987 | |
| 988 fragment NEWLINE | |
| 989 : '\n' | |
| 990 | '\r' | |
| 991 ; | |
| 992 | |
| 993 BAD_STRING | |
| 994 : UNTERMINATED_STRING NEWLINE { error("unterminated string"); } | |
| 995 ; | |
| 996 | |
| 997 fragment UNTERMINATED_STRING | |
| 998 : '@'? '\'' (~( '\'' | NEWLINE ))* | |
| 999 | '@'? '"' (~( '"' | NEWLINE ))* | |
| 1000 ; | |
| 1001 | |
| 1002 HASHBANG | |
| 1003 : '#!' ~(NEWLINE)* (NEWLINE)? | |
| 1004 ; | |
| 1005 | |
| 1006 | |
| 1007 // ----------------------------------------------------------------- | |
| 1008 // Whitespace and comments. | |
| 1009 // ----------------------------------------------------------------- | |
| 1010 WHITESPACE | |
| 1011 : ('\t' | ' ' | NEWLINE)+ { $channel=HIDDEN; } | |
| 1012 ; | |
| 1013 | |
| 1014 SINGLE_LINE_COMMENT | |
| 1015 : '//' ~(NEWLINE)* (NEWLINE)? { $channel=HIDDEN; } | |
| 1016 ; | |
| 1017 | |
| 1018 MULTI_LINE_COMMENT | |
| 1019 : '/*' (options { greedy=false; } : .)* '*/' { $channel=HIDDEN; } | |
| 1020 ; | |
| OLD | NEW |