1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29parser grammar smalideaParser; 30 31options { 32 tokenVocab=smaliParser; 33} 34 35@header { 36package org.jf.smalidea; 37 38import com.intellij.lang.PsiBuilder; 39import com.intellij.lang.PsiBuilder.Marker; 40import com.intellij.psi.tree.IElementType; 41import org.jf.smalidea.psi.SmaliElementTypes; 42 43import javax.annotation.Nonnull; 44import javax.annotation.Nullable; 45} 46 47 48@members { 49 private PsiBuilder psiBuilder; 50 51 public void setPsiBuilder(PsiBuilder psiBuilder) { 52 this.psiBuilder = psiBuilder; 53 } 54 55 public Marker mark() { 56 return psiBuilder.mark(); 57 } 58 59 protected void syncToFollows(boolean acceptEof) { 60 BitSet follow = computeErrorRecoverySet(); 61 int mark = input.mark(); 62 Marker marker = null; 63 try { 64 int token = input.LA(1); 65 while (!follow.member(token)) { 66 if (token == Token.EOF) { 67 if (acceptEof) { 68 break; 69 } 70 input.rewind(mark); 71 mark = -1; 72 marker = null; 73 return; 74 } 75 if (marker == null) { 76 marker = mark(); 77 } 78 input.consume(); 79 token = input.LA(1); 80 } 81 } finally { 82 if (mark != -1) { 83 input.release(mark); 84 } 85 if (marker != null) { 86 marker.error("Unexpected tokens"); 87 } 88 } 89 } 90 91 @Override 92 public void recover(IntStream input, RecognitionException re) { 93 BitSet followSet = computeErrorRecoverySet(); 94 beginResync(); 95 consumeUntil(input, followSet); 96 endResync(); 97 } 98 99 @Override 100 protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) 101 throws RecognitionException 102 { 103 RecognitionException e = null; 104 // if next token is what we are looking for then "delete" this token 105 if ( mismatchIsUnwantedToken(input, ttype) ) { 106 e = new UnwantedTokenException(ttype, input); 107 beginResync(); 108 Marker mark = mark(); 109 input.consume(); // simply delete extra token 110 mark.error(getErrorMessage(e, tokenNames)); 111 endResync(); 112 reportError(null, e, true); // report after consuming so AW sees the token in the exception 113 // we want to return the token we're actually matching 114 Object matchedSymbol = getCurrentInputSymbol(input); 115 input.consume(); // move past ttype token as if all were ok 116 return matchedSymbol; 117 } 118 // can't recover with single token deletion, try insertion 119 if ( mismatchIsMissingToken(input, follow) ) { 120 Object inserted = getMissingSymbol(input, e, ttype, follow); 121 Marker mark = mark(); 122 e = new MissingTokenException(ttype, input, inserted); 123 mark.error(getErrorMessage(e, tokenNames)); 124 reportError(null, e, true); // report after inserting so AW sees the token in the exception 125 return inserted; 126 } 127 128 // even that didn't work; must throw the exception 129 e = new MismatchedTokenException(ttype, input); 130 throw e; 131 } 132 133 @Override 134 public void reportError(RecognitionException e) { 135 reportError(mark(), e, false); 136 } 137 138 public void reportError(@Nullable Marker marker, RecognitionException e, boolean alreadyReported) { 139 // if we've already reported an error and have not matched a token 140 // yet successfully, don't report any errors. 141 if ( state.errorRecovery ) { 142 if (marker != null) { 143 marker.drop(); 144 } 145 return; 146 } 147 state.syntaxErrors++; // don't count spurious 148 state.errorRecovery = true; 149 150 if (marker != null) { 151 if (!alreadyReported) { 152 displayRecognitionError(marker, this.getTokenNames(), e); 153 } else { 154 marker.drop(); 155 } 156 } 157 } 158 159 public void finishToken(Marker marker, IElementType elementType) { 160 if (state.errorRecovery) { 161 marker.drop(); 162 } else { 163 marker.done(elementType); 164 } 165 } 166 167 @Override 168 public void displayRecognitionError(String[] tokenNames, RecognitionException e) { 169 displayRecognitionError(mark(), tokenNames, e); 170 } 171 172 public void displayRecognitionError(@Nonnull Marker marker, String[] tokenNames, RecognitionException e) { 173 marker.error(getErrorMessage(e, tokenNames)); 174 } 175} 176 177sync[boolean toEof] 178 @init { syncToFollows($toEof); } 179 : /*epsilon*/; 180 181smali_file 182 @init { 183 mark().done(SmaliElementTypes.EXTENDS_LIST); 184 mark().done(SmaliElementTypes.IMPLEMENTS_LIST); 185 } 186 : 187 ( 188 ( class_spec 189 | super_spec 190 | implements_spec 191 | source_spec 192 | method 193 | field 194 | annotation 195 ) 196 sync[true] 197 )+ 198 EOF; 199 200class_spec 201 @init { Marker marker = mark(); } 202 : CLASS_DIRECTIVE class_access_list class_descriptor 203 { marker.done(SmaliElementTypes.CLASS_STATEMENT); }; 204 catch [RecognitionException re] { 205 recover(input, re); 206 reportError(marker, re, false); 207 } 208 209super_spec 210 @init { Marker marker = mark(); } 211 : SUPER_DIRECTIVE class_descriptor 212 { marker.done(SmaliElementTypes.SUPER_STATEMENT); }; 213 catch [RecognitionException re] { 214 recover(input, re); 215 reportError(marker, re, false); 216 } 217 218implements_spec 219 @init { Marker marker = mark(); } 220 : IMPLEMENTS_DIRECTIVE class_descriptor 221 { marker.done(SmaliElementTypes.IMPLEMENTS_STATEMENT); }; 222 catch [RecognitionException re] { 223 recover(input, re); 224 reportError(marker, re, false); 225 } 226 227source_spec 228 @init { Marker marker = mark(); } 229 : SOURCE_DIRECTIVE string_literal 230 { marker.done(SmaliElementTypes.SOURCE_STATEMENT); }; 231 catch [RecognitionException re] { 232 recover(input, re); 233 reportError(marker, re, false); 234 } 235 236// class_access_list should be separate from access_list, because 237// it exists in a slightly different context, and can consume 238// ACCESS_SPECs greedily, without having to look ahead. 239class_access_list 240 @init { Marker marker = mark(); } 241 : ACCESS_SPEC* 242 { marker.done(SmaliElementTypes.MODIFIER_LIST); }; 243 catch [RecognitionException re] { 244 recover(input, re); 245 reportError(marker, re, false); 246 } 247 248access_list 249 @init { Marker marker = mark(); } 250 : ACCESS_SPEC* 251 { marker.done(SmaliElementTypes.MODIFIER_LIST); }; 252 catch [RecognitionException re] { 253 recover(input, re); 254 reportError(marker, re, false); 255 } 256 257/*When there are annotations immediately after a field definition, we don't know whether they are field annotations 258or class annotations until we determine if there is an .end field directive. In either case, we still "consume" and parse 259the annotations. If it turns out that they are field annotations, we include them in the I_FIELD AST. Otherwise, we 260add them to the $smali_file::classAnnotations list*/ 261field 262 @init { 263 Marker marker = mark(); 264 Marker annotationsMarker = null; 265 boolean gotEndField = false; 266 } 267 : FIELD_DIRECTIVE 268 access_list 269 member_name colon nonvoid_type_descriptor 270 field_initializer? 271 ( 272 (ANNOTATION_DIRECTIVE)=> ( 273 { annotationsMarker = mark(); } 274 ((ANNOTATION_DIRECTIVE)=> annotation)+ 275 ) 276 )? 277 ( end_field_directive { gotEndField = true; } )? 278 { 279 if (annotationsMarker != null) { 280 if (gotEndField) { 281 annotationsMarker.drop(); 282 marker.done(SmaliElementTypes.FIELD); 283 } else { 284 marker.doneBefore(SmaliElementTypes.FIELD, annotationsMarker); 285 annotationsMarker.drop(); 286 } 287 } else { 288 marker.done(SmaliElementTypes.FIELD); 289 } 290 }; 291 catch [RecognitionException re] { 292 if (annotationsMarker != null) { 293 annotationsMarker.drop(); 294 } 295 recover(input, re); 296 reportError(marker, re, false); 297 } 298 299end_field_directive 300 : END_FIELD_DIRECTIVE; 301 302field_initializer 303 @init { Marker marker = mark(); } 304 : EQUAL literal 305 { marker.done(SmaliElementTypes.FIELD_INITIALIZER); }; 306 catch [RecognitionException re] { 307 recover(input, re); 308 reportError(marker, re, false); 309 } 310 311method 312 @init { 313 Marker marker = mark(); 314 mark().done(SmaliElementTypes.THROWS_LIST); 315 } 316 : METHOD_DIRECTIVE access_list member_name method_prototype statements_and_directives 317 end_method_directive 318 { marker.done(SmaliElementTypes.METHOD); }; 319 catch [RecognitionException re] { 320 recover(input, re); 321 reportError(marker, re, false); 322 } 323 324end_method_directive 325 : END_METHOD_DIRECTIVE; 326catch [RecognitionException re] { 327 Marker errorMarker = mark(); 328 recover(input, re); 329 reportError(errorMarker, re, false); 330 } 331 332statements_and_directives 333 : ( 334 ( ordered_method_item 335 | registers_directive 336 | catch_directive 337 | catchall_directive 338 | parameter_directive 339 | annotation 340 ) 341 sync[false] 342 )*; 343 344/* Method items whose order/location is important */ 345ordered_method_item 346 : label 347 | instruction 348 | debug_directive; 349 350registers_directive 351 @init { Marker marker = mark(); } 352 : ( 353 REGISTERS_DIRECTIVE integral_literal 354 | LOCALS_DIRECTIVE integral_literal 355 ) 356 { marker.done(SmaliElementTypes.REGISTERS_STATEMENT); }; 357 catch [RecognitionException re] { 358 recover(input, re); 359 reportError(marker, re, false); 360 } 361 362param_list_or_id 363 : PARAM_LIST_OR_ID_PRIMITIVE_TYPE+; 364 365/*identifiers are much more general than most languages. Any of the below can either be 366the indicated type OR an identifier, depending on the context*/ 367simple_name 368 : SIMPLE_NAME 369 | ACCESS_SPEC 370 | VERIFICATION_ERROR_TYPE 371 | POSITIVE_INTEGER_LITERAL 372 | NEGATIVE_INTEGER_LITERAL 373 | FLOAT_LITERAL_OR_ID 374 | DOUBLE_LITERAL_OR_ID 375 | BOOL_LITERAL 376 | NULL_LITERAL 377 | register 378 | param_list_or_id 379 | PRIMITIVE_TYPE 380 | VOID_TYPE 381 | ANNOTATION_VISIBILITY 382 | INSTRUCTION_FORMAT10t 383 | INSTRUCTION_FORMAT10x 384 | INSTRUCTION_FORMAT10x_ODEX 385 | INSTRUCTION_FORMAT11x 386 | INSTRUCTION_FORMAT12x_OR_ID 387 | INSTRUCTION_FORMAT21c_FIELD 388 | INSTRUCTION_FORMAT21c_FIELD_ODEX 389 | INSTRUCTION_FORMAT21c_STRING 390 | INSTRUCTION_FORMAT21c_TYPE 391 | INSTRUCTION_FORMAT21t 392 | INSTRUCTION_FORMAT22c_FIELD 393 | INSTRUCTION_FORMAT22c_FIELD_ODEX 394 | INSTRUCTION_FORMAT22c_TYPE 395 | INSTRUCTION_FORMAT22cs_FIELD 396 | INSTRUCTION_FORMAT22s_OR_ID 397 | INSTRUCTION_FORMAT22t 398 | INSTRUCTION_FORMAT23x 399 | INSTRUCTION_FORMAT31i_OR_ID 400 | INSTRUCTION_FORMAT31t 401 | INSTRUCTION_FORMAT35c_METHOD 402 | INSTRUCTION_FORMAT35c_METHOD_ODEX 403 | INSTRUCTION_FORMAT35c_TYPE 404 | INSTRUCTION_FORMAT35mi_METHOD 405 | INSTRUCTION_FORMAT35ms_METHOD 406 | INSTRUCTION_FORMAT51l; 407 408member_name 409 @init { Marker marker = mark(); } 410 : member_name_inner 411 { marker.done(SmaliElementTypes.MEMBER_NAME); }; 412 413member_name_inner 414 : (simple_name 415 | MEMBER_NAME); 416 catch [RecognitionException re] { 417 Marker errorMarker = mark(); 418 recover(input, re); 419 reportError(errorMarker, re, false); 420 } 421 422method_prototype 423 @init { Marker marker = mark(); } 424 : open_paren param_list close_paren type_descriptor 425 { marker.done(SmaliElementTypes.METHOD_PROTOTYPE); }; 426 catch [RecognitionException re] { 427 recover(input, re); 428 reportError(marker, re, false); 429 } 430 431open_paren 432 : OPEN_PAREN; 433 catch [RecognitionException re] { 434 Marker errorMarker = mark(); 435 recover(input, re); 436 reportError(errorMarker, re, false); 437 } 438 439close_paren 440 : CLOSE_PAREN; 441 catch [RecognitionException re] { 442 Marker errorMarker = mark(); 443 recover(input, re); 444 reportError(errorMarker, re, false); 445 } 446 447open_brace 448 : OPEN_BRACE; 449 catch [RecognitionException re] { 450 Marker errorMarker = mark(); 451 recover(input, re); 452 reportError(errorMarker, re, false); 453 } 454 455close_brace 456 : CLOSE_BRACE; 457 catch [RecognitionException re] { 458 Marker errorMarker = mark(); 459 recover(input, re); 460 reportError(errorMarker, re, false); 461 } 462 463comma 464 : COMMA; 465 catch [RecognitionException re] { 466 Marker errorMarker = mark(); 467 recover(input, re); 468 reportError(errorMarker, re, false); 469 } 470 471colon 472 : COLON; 473 catch [RecognitionException re] { 474 Marker errorMarker = mark(); 475 recover(input, re); 476 reportError(errorMarker, re, false); 477 } 478 479dotdot 480 : DOTDOT; 481 catch [RecognitionException re] { 482 Marker errorMarker = mark(); 483 recover(input, re); 484 reportError(errorMarker, re, false); 485 } 486 487param_list_inner 488 : param+; 489 catch [RecognitionException re] { 490 Marker errorMarker = mark(); 491 recover(input, re); 492 reportError(errorMarker, re, false); 493 } 494 495param_list 496 @init { Marker marker = mark(); } 497 : param_list_inner? 498 { marker.done(SmaliElementTypes.METHOD_PARAM_LIST); }; 499 500param 501 @init { 502 Marker marker = mark(); 503 mark().done(SmaliElementTypes.MODIFIER_LIST); 504 } 505 : nonvoid_type_descriptor 506 { marker.done(SmaliElementTypes.METHOD_PARAMETER); }; 507 catch [RecognitionException re] { 508 recover(input, re); 509 reportError(marker, re, false); 510 } 511 512method_prototype_reference 513 : open_paren param_list_reference close_paren type_descriptor; 514 515param_list_reference 516 @init { 517 Marker marker = mark(); 518 } 519 : nonvoid_type_descriptor* 520 { marker.done(SmaliElementTypes.METHOD_REFERENCE_PARAM_LIST); }; 521 catch [RecognitionException re] { 522 recover(input, re); 523 reportError(marker, re, false); 524 } 525 526primitive_type 527 @init { Marker marker = mark(); } 528 : (PRIMITIVE_TYPE | PARAM_LIST_OR_ID_PRIMITIVE_TYPE) 529 { finishToken(marker, SmaliElementTypes.PRIMITIVE_TYPE); }; 530 catch [RecognitionException re] { 531 recover(input, re); 532 reportError(marker, re, false); 533 } 534 535class_descriptor 536 @init { Marker marker = mark(); } 537 : CLASS_DESCRIPTOR 538 { finishToken(marker, SmaliElementTypes.CLASS_TYPE); }; 539 catch [RecognitionException re] { 540 recover(input, re); 541 reportError(marker, re, false); 542 } 543 544array_descriptor 545 @init { Marker marker = mark(); } 546 : ARRAY_TYPE_PREFIX (primitive_type | class_descriptor) 547 { finishToken(marker, SmaliElementTypes.ARRAY_TYPE); }; 548 catch [RecognitionException re] { 549 recover(input, re); 550 reportError(marker, re, false); 551 } 552 553void_type 554 @init { Marker marker = mark(); } 555 : VOID_TYPE 556 { finishToken(marker, SmaliElementTypes.VOID_TYPE); }; 557 catch [RecognitionException re] { 558 recover(input, re); 559 reportError(marker, re, false); 560 } 561 562type_descriptor 563 : void_type 564 | primitive_type 565 | class_descriptor 566 | array_descriptor; 567 catch [RecognitionException re] { 568 Marker marker = mark(); 569 recover(input, re); 570 reportError(marker, re, false); 571 } 572 573nonvoid_type_descriptor 574 : primitive_type 575 | class_descriptor 576 | array_descriptor; 577 catch [RecognitionException re] { 578 Marker marker = mark(); 579 recover(input, re); 580 reportError(marker, re, false); 581 } 582 583reference_type_descriptor 584 : class_descriptor 585 | array_descriptor; 586 catch [RecognitionException re] { 587 Marker marker = mark(); 588 recover(input, re); 589 reportError(marker, re, false); 590 } 591 592null_literal 593 @init { Marker marker = mark(); } 594 : NULL_LITERAL 595 { finishToken(marker, SmaliElementTypes.LITERAL); }; 596 catch [RecognitionException re] { 597 recover(input, re); 598 reportError(marker, re, false); 599 } 600 601bool_literal 602 @init { Marker marker = mark(); } 603 : BOOL_LITERAL 604 { finishToken(marker, SmaliElementTypes.LITERAL); }; 605 catch [RecognitionException re] { 606 recover(input, re); 607 reportError(marker, re, false); 608 } 609 610byte_literal 611 @init { Marker marker = mark(); } 612 : BYTE_LITERAL 613 { finishToken(marker, SmaliElementTypes.LITERAL); }; 614 catch [RecognitionException re] { 615 recover(input, re); 616 reportError(marker, re, false); 617 } 618 619char_literal 620 @init { Marker marker = mark(); } 621 : CHAR_LITERAL 622 { finishToken(marker, SmaliElementTypes.LITERAL); }; 623 catch [RecognitionException re] { 624 recover(input, re); 625 reportError(marker, re, false); 626 } 627 628short_literal 629 @init { Marker marker = mark(); } 630 : SHORT_LITERAL 631 { finishToken(marker, SmaliElementTypes.LITERAL); }; 632 catch [RecognitionException re] { 633 recover(input, re); 634 reportError(marker, re, false); 635 } 636 637integer_literal 638 @init { Marker marker = mark(); } 639 : ( POSITIVE_INTEGER_LITERAL 640 | NEGATIVE_INTEGER_LITERAL) 641 { finishToken(marker, SmaliElementTypes.LITERAL); }; 642 catch [RecognitionException re] { 643 recover(input, re); 644 reportError(marker, re, false); 645 } 646 647long_literal 648 @init { Marker marker = mark(); } 649 : LONG_LITERAL 650 { finishToken(marker, SmaliElementTypes.LITERAL); }; 651 catch [RecognitionException re] { 652 recover(input, re); 653 reportError(marker, re, false); 654 } 655 656float_literal 657 @init { Marker marker = mark(); } 658 : ( FLOAT_LITERAL_OR_ID 659 | FLOAT_LITERAL ) 660 { finishToken(marker, SmaliElementTypes.LITERAL); }; 661 catch [RecognitionException re] { 662 recover(input, re); 663 reportError(marker, re, false); 664 } 665 666double_literal 667 @init { Marker marker = mark(); } 668 : ( DOUBLE_LITERAL_OR_ID 669 | DOUBLE_LITERAL) 670 { finishToken(marker, SmaliElementTypes.LITERAL); }; 671 catch [RecognitionException re] { 672 recover(input, re); 673 reportError(marker, re, false); 674 } 675 676string_literal 677 @init { Marker marker = mark(); } 678 : STRING_LITERAL 679 { finishToken(marker, SmaliElementTypes.LITERAL); }; 680 catch [RecognitionException re] { 681 recover(input, re); 682 reportError(marker, re, false); 683 } 684 685array_literal 686 @init { Marker marker = mark(); } 687 : open_brace (literal (comma literal)* | ) close_brace 688 { marker.done(SmaliElementTypes.LITERAL); }; 689 catch [RecognitionException re] { 690 recover(input, re); 691 reportError(marker, re, false); 692 } 693 694enum_literal 695 @init { Marker marker = mark(); } 696 : ENUM_DIRECTIVE fully_qualified_field 697 { marker.done(SmaliElementTypes.LITERAL); }; 698 catch [RecognitionException re] { 699 recover(input, re); 700 reportError(marker, re, false); 701 } 702 703type_field_method_literal 704 @init { Marker marker = mark(); } 705 : ( type_descriptor 706 | fully_qualified_field 707 | fully_qualified_method) 708 { marker.done(SmaliElementTypes.LITERAL); }; 709 catch [RecognitionException re] { 710 recover(input, re); 711 reportError(marker, re, false); 712 } 713 714subannotation 715 @init { 716 Marker marker = mark(); 717 Marker paramListMarker = null; 718 } 719 : SUBANNOTATION_DIRECTIVE class_descriptor 720 { paramListMarker = mark(); } 721 annotation_element* 722 { paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); } 723 end_subannotation_directive 724 { marker.done(SmaliElementTypes.ANNOTATION); }; 725 catch [RecognitionException re] { 726 recover(input, re); 727 reportError(marker, re, false); 728 } 729 730end_subannotation_directive 731 : END_SUBANNOTATION_DIRECTIVE; 732 catch [RecognitionException re] { 733 Marker errorMarker = mark(); 734 recover(input, re); 735 reportError(errorMarker, re, false); 736 } 737 738literal 739 : long_literal 740 | integer_literal 741 | short_literal 742 | byte_literal 743 | float_literal 744 | double_literal 745 | char_literal 746 | string_literal 747 | bool_literal 748 | null_literal 749 | array_literal 750 | subannotation 751 | type_field_method_literal 752 | enum_literal; 753 catch [RecognitionException re] { 754 Marker errorMarker = mark(); 755 recover(input, re); 756 reportError(errorMarker, re, false); 757 } 758 759string_or_null_literal 760 : string_literal 761 | null_literal; 762 catch [RecognitionException re] { 763 Marker errorMarker = mark(); 764 recover(input, re); 765 reportError(errorMarker, re, false); 766 } 767 768integral_literal 769 : long_literal 770 | integer_literal 771 | short_literal 772 | char_literal 773 | byte_literal; 774 catch [RecognitionException re] { 775 Marker errorMarker = mark(); 776 recover(input, re); 777 reportError(errorMarker, re, false); 778 } 779 780fixed_32bit_literal 781 : long_literal 782 | integer_literal 783 | short_literal 784 | byte_literal 785 | float_literal 786 | char_literal 787 | bool_literal; 788 catch [RecognitionException re] { 789 Marker errorMarker = mark(); 790 recover(input, re); 791 reportError(errorMarker, re, false); 792 } 793 794fixed_literal 795 : integer_literal 796 | long_literal 797 | short_literal 798 | byte_literal 799 | float_literal 800 | double_literal 801 | char_literal 802 | bool_literal; 803 catch [RecognitionException re] { 804 Marker errorMarker = mark(); 805 recover(input, re); 806 reportError(errorMarker, re, false); 807 } 808 809annotation_element 810 @init { 811 Marker marker = mark(); 812 Marker nameMarker = null; 813 } 814 : { nameMarker = mark(); } simple_name { nameMarker.done(SmaliElementTypes.ANNOTATION_ELEMENT_NAME); } 815 equal literal 816 { marker.done(SmaliElementTypes.ANNOTATION_ELEMENT); }; 817 catch [RecognitionException re] { 818 recover(input, re); 819 reportError(marker, re, false); 820 } 821 822equal 823 : EQUAL; 824 catch [RecognitionException re] { 825 Marker errorMarker = mark(); 826 recover(input, re); 827 reportError(errorMarker, re, false); 828 } 829 830annotation 831 @init { 832 Marker marker = mark(); 833 Marker paramListMarker = null; 834 } 835 : ANNOTATION_DIRECTIVE annotation_visibility class_descriptor 836 { paramListMarker = mark(); } 837 annotation_element* 838 { paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); } 839 end_annotation_directive 840 { marker.done(SmaliElementTypes.ANNOTATION); }; 841 842annotation_visibility 843 : ANNOTATION_VISIBILITY; 844 catch [RecognitionException re] { 845 Marker errorMarker = mark(); 846 recover(input, re); 847 reportError(errorMarker, re, false); 848 } 849 850end_annotation_directive 851 : END_ANNOTATION_DIRECTIVE; 852 catch [RecognitionException re] { 853 Marker errorMarker = mark(); 854 recover(input, re); 855 reportError(errorMarker, re, false); 856 } 857 858arrow 859 : ARROW; 860 catch [RecognitionException re] { 861 Marker errorMarker = mark(); 862 recover(input, re); 863 reportError(errorMarker, re, false); 864 } 865 866fully_qualified_method 867 @init { Marker marker = mark(); } 868 : reference_type_descriptor arrow member_name method_prototype_reference 869 { marker.done(SmaliElementTypes.METHOD_REFERENCE); }; 870 catch [RecognitionException re] { 871 recover(input, re); 872 reportError(marker, re, false); 873 } 874 875fully_qualified_field 876 @init { Marker marker = mark(); } 877 : reference_type_descriptor arrow member_name colon nonvoid_type_descriptor 878 { marker.done(SmaliElementTypes.FIELD_REFERENCE); }; 879 catch [RecognitionException re] { 880 recover(input, re); 881 reportError(marker, re, false); 882 } 883 884label 885 @init { Marker marker = mark(); } 886 : colon simple_name 887 { marker.done(SmaliElementTypes.LABEL); }; 888 catch [RecognitionException re] { 889 recover(input, re); 890 reportError(marker, re, false); 891 } 892 893label_ref 894 @init { Marker marker = mark(); } 895 : colon simple_name 896 { marker.done(SmaliElementTypes.LABEL_REFERENCE); }; 897 catch [RecognitionException re] { 898 recover(input, re); 899 reportError(marker, re, false); 900 } 901 902register_list 903 : open_brace (register (comma register)*)? close_brace; 904 905register_range 906 : open_brace (register (dotdot register)?)? close_brace; 907 908verification_error_reference 909 : class_descriptor | fully_qualified_field | fully_qualified_method; 910 911catch_directive 912 @init { Marker marker = mark(); } 913 : CATCH_DIRECTIVE nonvoid_type_descriptor open_brace label_ref dotdot label_ref close_brace label_ref 914 { marker.done(SmaliElementTypes.CATCH_STATEMENT); }; 915 catch [RecognitionException re] { 916 recover(input, re); 917 reportError(marker, re, false); 918 } 919 920catchall_directive 921 @init { Marker marker = mark(); } 922 : CATCHALL_DIRECTIVE open_brace label_ref dotdot label_ref close_brace label_ref 923 { marker.done(SmaliElementTypes.CATCH_ALL_STATEMENT); }; 924 catch [RecognitionException re] { 925 recover(input, re); 926 reportError(marker, re, false); 927 } 928 929/*When there are annotations immediately after a parameter definition, we don't know whether they are parameter annotations 930or method annotations until we determine if there is an .end parameter directive. In either case, we still "consume" and parse 931the annotations. If it turns out that they are parameter annotations, we include them in the I_PARAMETER AST. Otherwise, we 932add them to the $statements_and_directives::methodAnnotations list*/ 933parameter_directive 934 @init { 935 Marker marker = mark(); 936 Marker annotationsMarker = null; 937 boolean gotEndParam = false; 938 } 939 : PARAMETER_DIRECTIVE register 940 (comma local_name)? 941 { annotationsMarker = mark(); } parameter_annotations 942 ( end_parameter_directive { gotEndParam = true; } )? 943 { 944 if (gotEndParam) { 945 annotationsMarker.drop(); 946 marker.done(SmaliElementTypes.PARAMETER_STATEMENT); 947 } else { 948 marker.doneBefore(SmaliElementTypes.PARAMETER_STATEMENT, annotationsMarker); 949 annotationsMarker.drop(); 950 } 951 }; 952 catch [RecognitionException re] { 953 if (annotationsMarker != null) { 954 annotationsMarker.drop(); 955 } 956 recover(input, re); 957 reportError(marker, re, false); 958 } 959 960parameter_annotations 961 : ((ANNOTATION_DIRECTIVE)=> annotation)*; 962 catch [RecognitionException re] { 963 Marker errorMarker = mark(); 964 recover(input, re); 965 reportError(errorMarker, re, false); 966 } 967 968end_parameter_directive 969 : END_PARAMETER_DIRECTIVE; 970 971local_name 972 @init { 973 Marker localNameMarker = mark(); 974 Marker stringMarker = mark(); 975 } 976 : STRING_LITERAL 977 { 978 finishToken(stringMarker, SmaliElementTypes.LITERAL); 979 finishToken(localNameMarker, SmaliElementTypes.LOCAL_NAME); 980 }; 981 catch [RecognitionException re] { 982 stringMarker.drop(); 983 recover(input, re); 984 reportError(localNameMarker, re, false); 985 } 986 987register 988 @init { Marker marker = mark(); } 989 : REGISTER 990 { finishToken(marker, SmaliElementTypes.REGISTER_REFERENCE); }; 991 catch [RecognitionException re] { 992 recover(input, re); 993 reportError(marker, re, false); 994 } 995 996debug_directive 997 : line_directive 998 | local_directive 999 | end_local_directive 1000 | restart_local_directive 1001 | prologue_directive 1002 | epilogue_directive 1003 | source_directive; 1004 1005line_directive 1006 @init { Marker marker = mark(); } 1007 : LINE_DIRECTIVE integral_literal 1008 { marker.done(SmaliElementTypes.LINE_DEBUG_STATEMENT); }; 1009 catch [RecognitionException re] { 1010 recover(input, re); 1011 reportError(marker, re, false); 1012 } 1013 1014local_directive 1015 @init { Marker marker = mark(); } 1016 : LOCAL_DIRECTIVE register (comma string_or_null_literal colon type_descriptor 1017 (comma string_literal)? )? 1018 { marker.done(SmaliElementTypes.LOCAL_DEBUG_STATEMENT); }; 1019 catch [RecognitionException re] { 1020 recover(input, re); 1021 reportError(marker, re, false); 1022 } 1023 1024end_local_directive 1025 @init { Marker marker = mark(); } 1026 : END_LOCAL_DIRECTIVE register 1027 { marker.done(SmaliElementTypes.END_LOCAL_DEBUG_STATEMENT); }; 1028 catch [RecognitionException re] { 1029 recover(input, re); 1030 reportError(marker, re, false); 1031 } 1032 1033restart_local_directive 1034 @init { Marker marker = mark(); } 1035 : RESTART_LOCAL_DIRECTIVE register 1036 { marker.done(SmaliElementTypes.RESTART_LOCAL_DEBUG_STATEMENT); }; 1037 catch [RecognitionException re] { 1038 recover(input, re); 1039 reportError(marker, re, false); 1040 } 1041 1042prologue_directive 1043 @init { Marker marker = mark(); } 1044 : PROLOGUE_DIRECTIVE 1045 { marker.done(SmaliElementTypes.PROLOGUE_DEBUG_STATEMENT); }; 1046 catch [RecognitionException re] { 1047 recover(input, re); 1048 reportError(marker, re, false); 1049 } 1050 1051epilogue_directive 1052 @init { Marker marker = mark(); } 1053 : EPILOGUE_DIRECTIVE 1054 { marker.done(SmaliElementTypes.EPILOGUE_DEBUG_STATEMENT); }; 1055 catch [RecognitionException re] { 1056 recover(input, re); 1057 reportError(marker, re, false); 1058 } 1059 1060source_directive 1061 @init { Marker marker = mark(); } 1062 : SOURCE_DIRECTIVE string_literal? 1063 { marker.done(SmaliElementTypes.SOURCE_DEBUG_STATEMENT); }; 1064 catch [RecognitionException re] { 1065 recover(input, re); 1066 reportError(marker, re, false); 1067 } 1068 1069instruction_format12x 1070 : INSTRUCTION_FORMAT12x 1071 | INSTRUCTION_FORMAT12x_OR_ID; 1072 1073instruction_format22s 1074 : INSTRUCTION_FORMAT22s 1075 | INSTRUCTION_FORMAT22s_OR_ID; 1076 1077instruction_format31i 1078 : INSTRUCTION_FORMAT31i 1079 | INSTRUCTION_FORMAT31i_OR_ID; 1080 1081instruction 1082 @init { Marker marker = mark(); } 1083 : ( insn_format10t 1084 | insn_format10x 1085 | insn_format10x_odex 1086 | insn_format11n 1087 | insn_format11x 1088 | insn_format12x 1089 | insn_format20bc 1090 | insn_format20t 1091 | insn_format21c_field 1092 | insn_format21c_field_odex 1093 | insn_format21c_string 1094 | insn_format21c_type 1095 | insn_format21ih 1096 | insn_format21lh 1097 | insn_format21s 1098 | insn_format21t 1099 | insn_format22b 1100 | insn_format22c_field 1101 | insn_format22c_field_odex 1102 | insn_format22c_type 1103 | insn_format22cs_field 1104 | insn_format22s 1105 | insn_format22t 1106 | insn_format22x 1107 | insn_format23x 1108 | insn_format30t 1109 | insn_format31c 1110 | insn_format31i 1111 | insn_format31t 1112 | insn_format32x 1113 | insn_format35c_method 1114 | insn_format35c_type 1115 | insn_format35c_method_odex 1116 | insn_format35mi_method 1117 | insn_format35ms_method 1118 | insn_format3rc_method 1119 | insn_format3rc_method_odex 1120 | insn_format3rc_type 1121 | insn_format3rmi_method 1122 | insn_format3rms_method 1123 | insn_format51l 1124 | insn_array_data_directive 1125 | insn_packed_switch_directive 1126 | insn_sparse_switch_directive ) 1127 { marker.done(SmaliElementTypes.INSTRUCTION); }; 1128 catch [RecognitionException re] { 1129 recover(input, re); 1130 reportError(marker, re, false); 1131 } 1132 1133insn_format10t 1134 : //e.g. goto endloop: 1135 //e.g. goto +3 1136 INSTRUCTION_FORMAT10t label_ref; 1137 1138insn_format10x 1139 : //e.g. return-void 1140 INSTRUCTION_FORMAT10x; 1141 1142insn_format10x_odex 1143 : //e.g. return-void-barrier 1144 INSTRUCTION_FORMAT10x_ODEX; 1145 1146insn_format11n 1147 : //e.g. const/4 v0, 5 1148 INSTRUCTION_FORMAT11n register comma integral_literal; 1149 1150insn_format11x 1151 : //e.g. move-result-object v1 1152 INSTRUCTION_FORMAT11x register; 1153 1154insn_format12x 1155 : //e.g. move v1 v2 1156 instruction_format12x register comma register; 1157 1158insn_format20bc 1159 : //e.g. throw-verification-error generic-error, Lsome/class; 1160 INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE comma verification_error_reference; 1161 1162insn_format20t 1163 : //e.g. goto/16 endloop: 1164 INSTRUCTION_FORMAT20t label_ref; 1165 1166insn_format21c_field 1167 : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream; 1168 INSTRUCTION_FORMAT21c_FIELD register comma fully_qualified_field; 1169 1170insn_format21c_field_odex 1171 : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; 1172 INSTRUCTION_FORMAT21c_FIELD_ODEX register comma fully_qualified_field; 1173 1174insn_format21c_string 1175 : //e.g. const-string v1, "Hello World!" 1176 INSTRUCTION_FORMAT21c_STRING register comma string_literal; 1177 1178insn_format21c_type 1179 : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2; 1180 INSTRUCTION_FORMAT21c_TYPE register comma nonvoid_type_descriptor; 1181 1182insn_format21ih 1183 : //e.g. const/high16 v1, 1234 1184 INSTRUCTION_FORMAT21ih register comma fixed_32bit_literal; 1185 1186insn_format21lh 1187 : //e.g. const-wide/high16 v1, 1234 1188 INSTRUCTION_FORMAT21lh register comma fixed_32bit_literal; 1189 1190insn_format21s 1191 : //e.g. const/16 v1, 1234 1192 INSTRUCTION_FORMAT21s register comma integral_literal; 1193 1194insn_format21t 1195 : //e.g. if-eqz v0, endloop: 1196 INSTRUCTION_FORMAT21t register comma label_ref; 1197 1198insn_format22b 1199 : //e.g. add-int v0, v1, 123 1200 INSTRUCTION_FORMAT22b register comma register comma integral_literal; 1201 1202insn_format22c_field 1203 : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 1204 INSTRUCTION_FORMAT22c_FIELD register comma register comma fully_qualified_field; 1205 1206insn_format22c_field_odex 1207 : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 1208 INSTRUCTION_FORMAT22c_FIELD_ODEX register comma register comma fully_qualified_field; 1209 1210insn_format22c_type 1211 : //e.g. instance-of v0, v1, Ljava/lang/String; 1212 INSTRUCTION_FORMAT22c_TYPE register comma register comma nonvoid_type_descriptor; 1213 1214insn_format22cs_field 1215 : //e.g. iget-quick v0, v1, field@0xc 1216 INSTRUCTION_FORMAT22cs_FIELD register comma register comma FIELD_OFFSET; 1217 1218insn_format22s 1219 : //e.g. add-int/lit16 v0, v1, 12345 1220 instruction_format22s register comma register comma integral_literal; 1221 1222insn_format22t 1223 : //e.g. if-eq v0, v1, endloop: 1224 INSTRUCTION_FORMAT22t register comma register comma label_ref; 1225 1226insn_format22x 1227 : //e.g. move/from16 v1, v1234 1228 INSTRUCTION_FORMAT22x register comma register; 1229 1230insn_format23x 1231 : //e.g. add-int v1, v2, v3 1232 INSTRUCTION_FORMAT23x register comma register comma register; 1233 1234insn_format30t 1235 : //e.g. goto/32 endloop: 1236 INSTRUCTION_FORMAT30t label_ref; 1237 1238insn_format31c 1239 : //e.g. const-string/jumbo v1 "Hello World!" 1240 INSTRUCTION_FORMAT31c register comma string_literal; 1241 1242insn_format31i 1243 : //e.g. const v0, 123456 1244 instruction_format31i register comma fixed_32bit_literal; 1245 1246insn_format31t 1247 : //e.g. fill-array-data v0, ArrayData: 1248 INSTRUCTION_FORMAT31t register comma label_ref; 1249 1250insn_format32x 1251 : //e.g. move/16 v4567, v1234 1252 INSTRUCTION_FORMAT32x register comma register; 1253 1254insn_format35c_method 1255 : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V 1256 INSTRUCTION_FORMAT35c_METHOD register_list comma fully_qualified_method; 1257 1258insn_format35c_type 1259 : //e.g. filled-new-array {v0,v1}, I 1260 INSTRUCTION_FORMAT35c_TYPE register_list comma nonvoid_type_descriptor; 1261 1262insn_format35c_method_odex 1263 : //e.g. invoke-direct {p0}, Ljava/lang/Object;-><init>()V 1264 INSTRUCTION_FORMAT35c_METHOD_ODEX register_list comma fully_qualified_method; 1265 1266insn_format35mi_method 1267 : //e.g. execute-inline {v0, v1}, inline@0x4 1268 INSTRUCTION_FORMAT35mi_METHOD register_list comma INLINE_INDEX; 1269 1270insn_format35ms_method 1271 : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4 1272 INSTRUCTION_FORMAT35ms_METHOD register_list comma VTABLE_INDEX; 1273 1274insn_format3rc_method 1275 : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1276 INSTRUCTION_FORMAT3rc_METHOD register_range comma fully_qualified_method; 1277 1278insn_format3rc_method_odex 1279 : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;-><init>()V 1280 INSTRUCTION_FORMAT3rc_METHOD_ODEX register_list comma fully_qualified_method; 1281 1282insn_format3rc_type 1283 : //e.g. filled-new-array/range {v0..v6}, I 1284 INSTRUCTION_FORMAT3rc_TYPE register_range comma nonvoid_type_descriptor; 1285 1286insn_format3rmi_method 1287 : //e.g. execute-inline/range {v0 .. v10}, inline@0x14 1288 INSTRUCTION_FORMAT3rmi_METHOD register_range comma INLINE_INDEX; 1289 1290insn_format3rms_method 1291 : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14 1292 INSTRUCTION_FORMAT3rms_METHOD register_range comma VTABLE_INDEX; 1293 1294insn_format51l 1295 : //e.g. const-wide v0, 5000000000L 1296 INSTRUCTION_FORMAT51l register comma fixed_literal; 1297 1298insn_array_data_directive 1299 : ARRAY_DATA_DIRECTIVE 1300 integer_literal 1301 array_data_element* end_array_data_directive; 1302 1303end_array_data_directive 1304 : END_ARRAY_DATA_DIRECTIVE; 1305 catch [RecognitionException re] { 1306 Marker errorMarker = mark(); 1307 recover(input, re); 1308 reportError(errorMarker, re, false); 1309 } 1310 1311array_data_element 1312 @init { Marker marker = mark(); } 1313 : fixed_literal 1314 { marker.done(SmaliElementTypes.ARRAY_DATA_ELEMENT); }; 1315 catch [RecognitionException re] { 1316 recover(input, re); 1317 reportError(marker, re, false); 1318 } 1319 1320insn_packed_switch_directive 1321 : PACKED_SWITCH_DIRECTIVE 1322 fixed_32bit_literal 1323 packed_switch_element* 1324 end_packed_switch_directive; 1325 1326end_packed_switch_directive 1327 : END_PACKED_SWITCH_DIRECTIVE; 1328 catch [RecognitionException re] { 1329 Marker errorMarker = mark(); 1330 recover(input, re); 1331 reportError(errorMarker, re, false); 1332 } 1333 1334packed_switch_element 1335 @init { Marker marker = mark(); } 1336 : label_ref 1337 { marker.done(SmaliElementTypes.PACKED_SWITCH_ELEMENT); }; 1338 catch [RecognitionException re] { 1339 recover(input, re); 1340 reportError(marker, re, false); 1341 } 1342 1343insn_sparse_switch_directive 1344 : SPARSE_SWITCH_DIRECTIVE 1345 sparse_switch_element* 1346 end_sparse_switch_directive; 1347 1348end_sparse_switch_directive 1349 : END_SPARSE_SWITCH_DIRECTIVE; 1350 catch [RecognitionException re] { 1351 Marker errorMarker = mark(); 1352 recover(input, re); 1353 reportError(errorMarker, re, false); 1354 } 1355 1356sparse_switch_element 1357 @init { Marker marker = mark(); } 1358 : fixed_32bit_literal arrow label_ref 1359 { marker.done(SmaliElementTypes.SPARSE_SWITCH_ELEMENT); }; 1360 catch [RecognitionException re] { 1361 recover(input, re); 1362 reportError(marker, re, false); 1363 } 1364