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_METHOD_OR_METHOD_HANDLE_TYPE 404 | INSTRUCTION_FORMAT35c_TYPE 405 | INSTRUCTION_FORMAT35mi_METHOD 406 | INSTRUCTION_FORMAT35ms_METHOD 407 | INSTRUCTION_FORMAT51l; 408 409member_name 410 @init { Marker marker = mark(); } 411 : member_name_inner 412 { marker.done(SmaliElementTypes.MEMBER_NAME); }; 413 414member_name_inner 415 : (simple_name 416 | MEMBER_NAME); 417 catch [RecognitionException re] { 418 Marker errorMarker = mark(); 419 recover(input, re); 420 reportError(errorMarker, re, false); 421 } 422 423method_prototype 424 @init { Marker marker = mark(); } 425 : open_paren param_list close_paren type_descriptor 426 { marker.done(SmaliElementTypes.METHOD_PROTOTYPE); }; 427 catch [RecognitionException re] { 428 recover(input, re); 429 reportError(marker, re, false); 430 } 431 432open_paren 433 : OPEN_PAREN; 434 catch [RecognitionException re] { 435 Marker errorMarker = mark(); 436 recover(input, re); 437 reportError(errorMarker, re, false); 438 } 439 440close_paren 441 : CLOSE_PAREN; 442 catch [RecognitionException re] { 443 Marker errorMarker = mark(); 444 recover(input, re); 445 reportError(errorMarker, re, false); 446 } 447 448open_brace 449 : OPEN_BRACE; 450 catch [RecognitionException re] { 451 Marker errorMarker = mark(); 452 recover(input, re); 453 reportError(errorMarker, re, false); 454 } 455 456close_brace 457 : CLOSE_BRACE; 458 catch [RecognitionException re] { 459 Marker errorMarker = mark(); 460 recover(input, re); 461 reportError(errorMarker, re, false); 462 } 463 464comma 465 : COMMA; 466 catch [RecognitionException re] { 467 Marker errorMarker = mark(); 468 recover(input, re); 469 reportError(errorMarker, re, false); 470 } 471 472colon 473 : COLON; 474 catch [RecognitionException re] { 475 Marker errorMarker = mark(); 476 recover(input, re); 477 reportError(errorMarker, re, false); 478 } 479 480dotdot 481 : DOTDOT; 482 catch [RecognitionException re] { 483 Marker errorMarker = mark(); 484 recover(input, re); 485 reportError(errorMarker, re, false); 486 } 487 488param_list_inner 489 : param+; 490 catch [RecognitionException re] { 491 Marker errorMarker = mark(); 492 recover(input, re); 493 reportError(errorMarker, re, false); 494 } 495 496param_list 497 @init { Marker marker = mark(); } 498 : param_list_inner? 499 { marker.done(SmaliElementTypes.METHOD_PARAM_LIST); }; 500 501param 502 @init { 503 Marker marker = mark(); 504 mark().done(SmaliElementTypes.MODIFIER_LIST); 505 } 506 : nonvoid_type_descriptor 507 { marker.done(SmaliElementTypes.METHOD_PARAMETER); }; 508 catch [RecognitionException re] { 509 recover(input, re); 510 reportError(marker, re, false); 511 } 512 513method_prototype_reference 514 : open_paren param_list_reference close_paren type_descriptor; 515 516param_list_reference 517 @init { 518 Marker marker = mark(); 519 } 520 : nonvoid_type_descriptor* 521 { marker.done(SmaliElementTypes.METHOD_REFERENCE_PARAM_LIST); }; 522 catch [RecognitionException re] { 523 recover(input, re); 524 reportError(marker, re, false); 525 } 526 527primitive_type 528 @init { Marker marker = mark(); } 529 : (PRIMITIVE_TYPE | PARAM_LIST_OR_ID_PRIMITIVE_TYPE) 530 { finishToken(marker, SmaliElementTypes.PRIMITIVE_TYPE); }; 531 catch [RecognitionException re] { 532 recover(input, re); 533 reportError(marker, re, false); 534 } 535 536class_descriptor 537 @init { Marker marker = mark(); } 538 : CLASS_DESCRIPTOR 539 { finishToken(marker, SmaliElementTypes.CLASS_TYPE); }; 540 catch [RecognitionException re] { 541 recover(input, re); 542 reportError(marker, re, false); 543 } 544 545array_descriptor 546 @init { Marker marker = mark(); } 547 : ARRAY_TYPE_PREFIX (primitive_type | class_descriptor) 548 { finishToken(marker, SmaliElementTypes.ARRAY_TYPE); }; 549 catch [RecognitionException re] { 550 recover(input, re); 551 reportError(marker, re, false); 552 } 553 554void_type 555 @init { Marker marker = mark(); } 556 : VOID_TYPE 557 { finishToken(marker, SmaliElementTypes.VOID_TYPE); }; 558 catch [RecognitionException re] { 559 recover(input, re); 560 reportError(marker, re, false); 561 } 562 563type_descriptor 564 : void_type 565 | primitive_type 566 | class_descriptor 567 | array_descriptor; 568 catch [RecognitionException re] { 569 Marker marker = mark(); 570 recover(input, re); 571 reportError(marker, re, false); 572 } 573 574nonvoid_type_descriptor 575 : primitive_type 576 | class_descriptor 577 | array_descriptor; 578 catch [RecognitionException re] { 579 Marker marker = mark(); 580 recover(input, re); 581 reportError(marker, re, false); 582 } 583 584reference_type_descriptor 585 : class_descriptor 586 | array_descriptor; 587 catch [RecognitionException re] { 588 Marker marker = mark(); 589 recover(input, re); 590 reportError(marker, re, false); 591 } 592 593null_literal 594 @init { Marker marker = mark(); } 595 : NULL_LITERAL 596 { finishToken(marker, SmaliElementTypes.LITERAL); }; 597 catch [RecognitionException re] { 598 recover(input, re); 599 reportError(marker, re, false); 600 } 601 602bool_literal 603 @init { Marker marker = mark(); } 604 : BOOL_LITERAL 605 { finishToken(marker, SmaliElementTypes.LITERAL); }; 606 catch [RecognitionException re] { 607 recover(input, re); 608 reportError(marker, re, false); 609 } 610 611byte_literal 612 @init { Marker marker = mark(); } 613 : BYTE_LITERAL 614 { finishToken(marker, SmaliElementTypes.LITERAL); }; 615 catch [RecognitionException re] { 616 recover(input, re); 617 reportError(marker, re, false); 618 } 619 620char_literal 621 @init { Marker marker = mark(); } 622 : CHAR_LITERAL 623 { finishToken(marker, SmaliElementTypes.LITERAL); }; 624 catch [RecognitionException re] { 625 recover(input, re); 626 reportError(marker, re, false); 627 } 628 629short_literal 630 @init { Marker marker = mark(); } 631 : SHORT_LITERAL 632 { finishToken(marker, SmaliElementTypes.LITERAL); }; 633 catch [RecognitionException re] { 634 recover(input, re); 635 reportError(marker, re, false); 636 } 637 638integer_literal 639 @init { Marker marker = mark(); } 640 : ( POSITIVE_INTEGER_LITERAL 641 | NEGATIVE_INTEGER_LITERAL) 642 { finishToken(marker, SmaliElementTypes.LITERAL); }; 643 catch [RecognitionException re] { 644 recover(input, re); 645 reportError(marker, re, false); 646 } 647 648long_literal 649 @init { Marker marker = mark(); } 650 : LONG_LITERAL 651 { finishToken(marker, SmaliElementTypes.LITERAL); }; 652 catch [RecognitionException re] { 653 recover(input, re); 654 reportError(marker, re, false); 655 } 656 657float_literal 658 @init { Marker marker = mark(); } 659 : ( FLOAT_LITERAL_OR_ID 660 | FLOAT_LITERAL ) 661 { finishToken(marker, SmaliElementTypes.LITERAL); }; 662 catch [RecognitionException re] { 663 recover(input, re); 664 reportError(marker, re, false); 665 } 666 667double_literal 668 @init { Marker marker = mark(); } 669 : ( DOUBLE_LITERAL_OR_ID 670 | DOUBLE_LITERAL) 671 { finishToken(marker, SmaliElementTypes.LITERAL); }; 672 catch [RecognitionException re] { 673 recover(input, re); 674 reportError(marker, re, false); 675 } 676 677string_literal 678 @init { Marker marker = mark(); } 679 : STRING_LITERAL 680 { finishToken(marker, SmaliElementTypes.LITERAL); }; 681 catch [RecognitionException re] { 682 recover(input, re); 683 reportError(marker, re, false); 684 } 685 686array_literal 687 @init { Marker marker = mark(); } 688 : open_brace (literal (comma literal)* | ) close_brace 689 { marker.done(SmaliElementTypes.LITERAL); }; 690 catch [RecognitionException re] { 691 recover(input, re); 692 reportError(marker, re, false); 693 } 694 695enum_literal 696 @init { Marker marker = mark(); } 697 : ENUM_DIRECTIVE fully_qualified_field 698 { marker.done(SmaliElementTypes.LITERAL); }; 699 catch [RecognitionException re] { 700 recover(input, re); 701 reportError(marker, re, false); 702 } 703 704type_field_method_literal 705 @init { Marker marker = mark(); } 706 : ( type_descriptor 707 | fully_qualified_field 708 | fully_qualified_method) 709 { marker.done(SmaliElementTypes.LITERAL); }; 710 catch [RecognitionException re] { 711 recover(input, re); 712 reportError(marker, re, false); 713 } 714 715subannotation 716 @init { 717 Marker marker = mark(); 718 Marker paramListMarker = null; 719 } 720 : SUBANNOTATION_DIRECTIVE class_descriptor 721 { paramListMarker = mark(); } 722 annotation_element* 723 { paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); } 724 end_subannotation_directive 725 { marker.done(SmaliElementTypes.ANNOTATION); }; 726 catch [RecognitionException re] { 727 recover(input, re); 728 reportError(marker, re, false); 729 } 730 731end_subannotation_directive 732 : END_SUBANNOTATION_DIRECTIVE; 733 catch [RecognitionException re] { 734 Marker errorMarker = mark(); 735 recover(input, re); 736 reportError(errorMarker, re, false); 737 } 738 739literal 740 : long_literal 741 | integer_literal 742 | short_literal 743 | byte_literal 744 | float_literal 745 | double_literal 746 | char_literal 747 | string_literal 748 | bool_literal 749 | null_literal 750 | array_literal 751 | subannotation 752 | type_field_method_literal 753 | enum_literal; 754 catch [RecognitionException re] { 755 Marker errorMarker = mark(); 756 recover(input, re); 757 reportError(errorMarker, re, false); 758 } 759 760string_or_null_literal 761 : string_literal 762 | null_literal; 763 catch [RecognitionException re] { 764 Marker errorMarker = mark(); 765 recover(input, re); 766 reportError(errorMarker, re, false); 767 } 768 769integral_literal 770 : long_literal 771 | integer_literal 772 | short_literal 773 | char_literal 774 | byte_literal; 775 catch [RecognitionException re] { 776 Marker errorMarker = mark(); 777 recover(input, re); 778 reportError(errorMarker, re, false); 779 } 780 781fixed_32bit_literal 782 : long_literal 783 | integer_literal 784 | short_literal 785 | byte_literal 786 | float_literal 787 | char_literal 788 | bool_literal; 789 catch [RecognitionException re] { 790 Marker errorMarker = mark(); 791 recover(input, re); 792 reportError(errorMarker, re, false); 793 } 794 795fixed_literal 796 : integer_literal 797 | long_literal 798 | short_literal 799 | byte_literal 800 | float_literal 801 | double_literal 802 | char_literal 803 | bool_literal; 804 catch [RecognitionException re] { 805 Marker errorMarker = mark(); 806 recover(input, re); 807 reportError(errorMarker, re, false); 808 } 809 810annotation_element 811 @init { 812 Marker marker = mark(); 813 Marker nameMarker = null; 814 } 815 : { nameMarker = mark(); } simple_name { nameMarker.done(SmaliElementTypes.ANNOTATION_ELEMENT_NAME); } 816 equal literal 817 { marker.done(SmaliElementTypes.ANNOTATION_ELEMENT); }; 818 catch [RecognitionException re] { 819 recover(input, re); 820 reportError(marker, re, false); 821 } 822 823equal 824 : EQUAL; 825 catch [RecognitionException re] { 826 Marker errorMarker = mark(); 827 recover(input, re); 828 reportError(errorMarker, re, false); 829 } 830 831annotation 832 @init { 833 Marker marker = mark(); 834 Marker paramListMarker = null; 835 } 836 : ANNOTATION_DIRECTIVE annotation_visibility class_descriptor 837 { paramListMarker = mark(); } 838 annotation_element* 839 { paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); } 840 end_annotation_directive 841 { marker.done(SmaliElementTypes.ANNOTATION); }; 842 843annotation_visibility 844 : ANNOTATION_VISIBILITY; 845 catch [RecognitionException re] { 846 Marker errorMarker = mark(); 847 recover(input, re); 848 reportError(errorMarker, re, false); 849 } 850 851end_annotation_directive 852 : END_ANNOTATION_DIRECTIVE; 853 catch [RecognitionException re] { 854 Marker errorMarker = mark(); 855 recover(input, re); 856 reportError(errorMarker, re, false); 857 } 858 859arrow 860 : ARROW; 861 catch [RecognitionException re] { 862 Marker errorMarker = mark(); 863 recover(input, re); 864 reportError(errorMarker, re, false); 865 } 866 867fully_qualified_method 868 @init { Marker marker = mark(); } 869 : reference_type_descriptor arrow member_name method_prototype_reference 870 { marker.done(SmaliElementTypes.METHOD_REFERENCE); }; 871 catch [RecognitionException re] { 872 recover(input, re); 873 reportError(marker, re, false); 874 } 875 876fully_qualified_field 877 @init { Marker marker = mark(); } 878 : reference_type_descriptor arrow member_name colon nonvoid_type_descriptor 879 { marker.done(SmaliElementTypes.FIELD_REFERENCE); }; 880 catch [RecognitionException re] { 881 recover(input, re); 882 reportError(marker, re, false); 883 } 884 885label 886 @init { Marker marker = mark(); } 887 : colon simple_name 888 { marker.done(SmaliElementTypes.LABEL); }; 889 catch [RecognitionException re] { 890 recover(input, re); 891 reportError(marker, re, false); 892 } 893 894label_ref 895 @init { Marker marker = mark(); } 896 : colon simple_name 897 { marker.done(SmaliElementTypes.LABEL_REFERENCE); }; 898 catch [RecognitionException re] { 899 recover(input, re); 900 reportError(marker, re, false); 901 } 902 903register_list 904 : open_brace (register (comma register)*)? close_brace; 905 906register_range 907 : open_brace (register (dotdot register)?)? close_brace; 908 909verification_error_reference 910 : class_descriptor | fully_qualified_field | fully_qualified_method; 911 912catch_directive 913 @init { Marker marker = mark(); } 914 : CATCH_DIRECTIVE nonvoid_type_descriptor open_brace label_ref dotdot label_ref close_brace label_ref 915 { marker.done(SmaliElementTypes.CATCH_STATEMENT); }; 916 catch [RecognitionException re] { 917 recover(input, re); 918 reportError(marker, re, false); 919 } 920 921catchall_directive 922 @init { Marker marker = mark(); } 923 : CATCHALL_DIRECTIVE open_brace label_ref dotdot label_ref close_brace label_ref 924 { marker.done(SmaliElementTypes.CATCH_ALL_STATEMENT); }; 925 catch [RecognitionException re] { 926 recover(input, re); 927 reportError(marker, re, false); 928 } 929 930/*When there are annotations immediately after a parameter definition, we don't know whether they are parameter annotations 931or method annotations until we determine if there is an .end parameter directive. In either case, we still "consume" and parse 932the annotations. If it turns out that they are parameter annotations, we include them in the I_PARAMETER AST. Otherwise, we 933add them to the $statements_and_directives::methodAnnotations list*/ 934parameter_directive 935 @init { 936 Marker marker = mark(); 937 Marker annotationsMarker = null; 938 boolean gotEndParam = false; 939 } 940 : PARAMETER_DIRECTIVE register 941 (comma local_name)? 942 { annotationsMarker = mark(); } parameter_annotations 943 ( end_parameter_directive { gotEndParam = true; } )? 944 { 945 if (gotEndParam) { 946 annotationsMarker.drop(); 947 marker.done(SmaliElementTypes.PARAMETER_STATEMENT); 948 } else { 949 marker.doneBefore(SmaliElementTypes.PARAMETER_STATEMENT, annotationsMarker); 950 annotationsMarker.drop(); 951 } 952 }; 953 catch [RecognitionException re] { 954 if (annotationsMarker != null) { 955 annotationsMarker.drop(); 956 } 957 recover(input, re); 958 reportError(marker, re, false); 959 } 960 961parameter_annotations 962 : ((ANNOTATION_DIRECTIVE)=> annotation)*; 963 catch [RecognitionException re] { 964 Marker errorMarker = mark(); 965 recover(input, re); 966 reportError(errorMarker, re, false); 967 } 968 969end_parameter_directive 970 : END_PARAMETER_DIRECTIVE; 971 972local_name 973 @init { 974 Marker localNameMarker = mark(); 975 Marker stringMarker = mark(); 976 } 977 : STRING_LITERAL 978 { 979 finishToken(stringMarker, SmaliElementTypes.LITERAL); 980 finishToken(localNameMarker, SmaliElementTypes.LOCAL_NAME); 981 }; 982 catch [RecognitionException re] { 983 stringMarker.drop(); 984 recover(input, re); 985 reportError(localNameMarker, re, false); 986 } 987 988register 989 @init { Marker marker = mark(); } 990 : REGISTER 991 { finishToken(marker, SmaliElementTypes.REGISTER_REFERENCE); }; 992 catch [RecognitionException re] { 993 recover(input, re); 994 reportError(marker, re, false); 995 } 996 997debug_directive 998 : line_directive 999 | local_directive 1000 | end_local_directive 1001 | restart_local_directive 1002 | prologue_directive 1003 | epilogue_directive 1004 | source_directive; 1005 1006line_directive 1007 @init { Marker marker = mark(); } 1008 : LINE_DIRECTIVE integral_literal 1009 { marker.done(SmaliElementTypes.LINE_DEBUG_STATEMENT); }; 1010 catch [RecognitionException re] { 1011 recover(input, re); 1012 reportError(marker, re, false); 1013 } 1014 1015local_directive 1016 @init { Marker marker = mark(); } 1017 : LOCAL_DIRECTIVE register (comma string_or_null_literal colon type_descriptor 1018 (comma string_literal)? )? 1019 { marker.done(SmaliElementTypes.LOCAL_DEBUG_STATEMENT); }; 1020 catch [RecognitionException re] { 1021 recover(input, re); 1022 reportError(marker, re, false); 1023 } 1024 1025end_local_directive 1026 @init { Marker marker = mark(); } 1027 : END_LOCAL_DIRECTIVE register 1028 { marker.done(SmaliElementTypes.END_LOCAL_DEBUG_STATEMENT); }; 1029 catch [RecognitionException re] { 1030 recover(input, re); 1031 reportError(marker, re, false); 1032 } 1033 1034restart_local_directive 1035 @init { Marker marker = mark(); } 1036 : RESTART_LOCAL_DIRECTIVE register 1037 { marker.done(SmaliElementTypes.RESTART_LOCAL_DEBUG_STATEMENT); }; 1038 catch [RecognitionException re] { 1039 recover(input, re); 1040 reportError(marker, re, false); 1041 } 1042 1043prologue_directive 1044 @init { Marker marker = mark(); } 1045 : PROLOGUE_DIRECTIVE 1046 { marker.done(SmaliElementTypes.PROLOGUE_DEBUG_STATEMENT); }; 1047 catch [RecognitionException re] { 1048 recover(input, re); 1049 reportError(marker, re, false); 1050 } 1051 1052epilogue_directive 1053 @init { Marker marker = mark(); } 1054 : EPILOGUE_DIRECTIVE 1055 { marker.done(SmaliElementTypes.EPILOGUE_DEBUG_STATEMENT); }; 1056 catch [RecognitionException re] { 1057 recover(input, re); 1058 reportError(marker, re, false); 1059 } 1060 1061source_directive 1062 @init { Marker marker = mark(); } 1063 : SOURCE_DIRECTIVE string_literal? 1064 { marker.done(SmaliElementTypes.SOURCE_DEBUG_STATEMENT); }; 1065 catch [RecognitionException re] { 1066 recover(input, re); 1067 reportError(marker, re, false); 1068 } 1069 1070instruction_format12x 1071 : INSTRUCTION_FORMAT12x 1072 | INSTRUCTION_FORMAT12x_OR_ID; 1073 1074instruction_format22s 1075 : INSTRUCTION_FORMAT22s 1076 | INSTRUCTION_FORMAT22s_OR_ID; 1077 1078instruction_format31i 1079 : INSTRUCTION_FORMAT31i 1080 | INSTRUCTION_FORMAT31i_OR_ID; 1081 1082instruction 1083 @init { Marker marker = mark(); } 1084 : ( insn_format10t 1085 | insn_format10x 1086 | insn_format10x_odex 1087 | insn_format11n 1088 | insn_format11x 1089 | insn_format12x 1090 | insn_format20bc 1091 | insn_format20t 1092 | insn_format21c_field 1093 | insn_format21c_field_odex 1094 | insn_format21c_string 1095 | insn_format21c_type 1096 | insn_format21ih 1097 | insn_format21lh 1098 | insn_format21s 1099 | insn_format21t 1100 | insn_format22b 1101 | insn_format22c_field 1102 | insn_format22c_field_odex 1103 | insn_format22c_type 1104 | insn_format22cs_field 1105 | insn_format22s 1106 | insn_format22t 1107 | insn_format22x 1108 | insn_format23x 1109 | insn_format30t 1110 | insn_format31c 1111 | insn_format31i 1112 | insn_format31t 1113 | insn_format32x 1114 | insn_format35c_method 1115 | insn_format35c_type 1116 | insn_format35c_method_odex 1117 | insn_format35mi_method 1118 | insn_format35ms_method 1119 | insn_format3rc_method 1120 | insn_format3rc_method_odex 1121 | insn_format3rc_type 1122 | insn_format3rmi_method 1123 | insn_format3rms_method 1124 | insn_format51l 1125 | insn_array_data_directive 1126 | insn_packed_switch_directive 1127 | insn_sparse_switch_directive ) 1128 { marker.done(SmaliElementTypes.INSTRUCTION); }; 1129 catch [RecognitionException re] { 1130 recover(input, re); 1131 reportError(marker, re, false); 1132 } 1133 1134insn_format10t 1135 : //e.g. goto endloop: 1136 //e.g. goto +3 1137 INSTRUCTION_FORMAT10t label_ref; 1138 1139insn_format10x 1140 : //e.g. return-void 1141 INSTRUCTION_FORMAT10x; 1142 1143insn_format10x_odex 1144 : //e.g. return-void-barrier 1145 INSTRUCTION_FORMAT10x_ODEX; 1146 1147insn_format11n 1148 : //e.g. const/4 v0, 5 1149 INSTRUCTION_FORMAT11n register comma integral_literal; 1150 1151insn_format11x 1152 : //e.g. move-result-object v1 1153 INSTRUCTION_FORMAT11x register; 1154 1155insn_format12x 1156 : //e.g. move v1 v2 1157 instruction_format12x register comma register; 1158 1159insn_format20bc 1160 : //e.g. throw-verification-error generic-error, Lsome/class; 1161 INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE comma verification_error_reference; 1162 1163insn_format20t 1164 : //e.g. goto/16 endloop: 1165 INSTRUCTION_FORMAT20t label_ref; 1166 1167insn_format21c_field 1168 : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream; 1169 INSTRUCTION_FORMAT21c_FIELD register comma fully_qualified_field; 1170 1171insn_format21c_field_odex 1172 : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; 1173 INSTRUCTION_FORMAT21c_FIELD_ODEX register comma fully_qualified_field; 1174 1175insn_format21c_string 1176 : //e.g. const-string v1, "Hello World!" 1177 INSTRUCTION_FORMAT21c_STRING register comma string_literal; 1178 1179insn_format21c_type 1180 : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2; 1181 INSTRUCTION_FORMAT21c_TYPE register comma nonvoid_type_descriptor; 1182 1183insn_format21ih 1184 : //e.g. const/high16 v1, 1234 1185 INSTRUCTION_FORMAT21ih register comma fixed_32bit_literal; 1186 1187insn_format21lh 1188 : //e.g. const-wide/high16 v1, 1234 1189 INSTRUCTION_FORMAT21lh register comma fixed_32bit_literal; 1190 1191insn_format21s 1192 : //e.g. const/16 v1, 1234 1193 INSTRUCTION_FORMAT21s register comma integral_literal; 1194 1195insn_format21t 1196 : //e.g. if-eqz v0, endloop: 1197 INSTRUCTION_FORMAT21t register comma label_ref; 1198 1199insn_format22b 1200 : //e.g. add-int v0, v1, 123 1201 INSTRUCTION_FORMAT22b register comma register comma integral_literal; 1202 1203insn_format22c_field 1204 : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 1205 INSTRUCTION_FORMAT22c_FIELD register comma register comma fully_qualified_field; 1206 1207insn_format22c_field_odex 1208 : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 1209 INSTRUCTION_FORMAT22c_FIELD_ODEX register comma register comma fully_qualified_field; 1210 1211insn_format22c_type 1212 : //e.g. instance-of v0, v1, Ljava/lang/String; 1213 INSTRUCTION_FORMAT22c_TYPE register comma register comma nonvoid_type_descriptor; 1214 1215insn_format22cs_field 1216 : //e.g. iget-quick v0, v1, field@0xc 1217 INSTRUCTION_FORMAT22cs_FIELD register comma register comma FIELD_OFFSET; 1218 1219insn_format22s 1220 : //e.g. add-int/lit16 v0, v1, 12345 1221 instruction_format22s register comma register comma integral_literal; 1222 1223insn_format22t 1224 : //e.g. if-eq v0, v1, endloop: 1225 INSTRUCTION_FORMAT22t register comma register comma label_ref; 1226 1227insn_format22x 1228 : //e.g. move/from16 v1, v1234 1229 INSTRUCTION_FORMAT22x register comma register; 1230 1231insn_format23x 1232 : //e.g. add-int v1, v2, v3 1233 INSTRUCTION_FORMAT23x register comma register comma register; 1234 1235insn_format30t 1236 : //e.g. goto/32 endloop: 1237 INSTRUCTION_FORMAT30t label_ref; 1238 1239insn_format31c 1240 : //e.g. const-string/jumbo v1 "Hello World!" 1241 INSTRUCTION_FORMAT31c register comma string_literal; 1242 1243insn_format31i 1244 : //e.g. const v0, 123456 1245 instruction_format31i register comma fixed_32bit_literal; 1246 1247insn_format31t 1248 : //e.g. fill-array-data v0, ArrayData: 1249 INSTRUCTION_FORMAT31t register comma label_ref; 1250 1251insn_format32x 1252 : //e.g. move/16 v4567, v1234 1253 INSTRUCTION_FORMAT32x register comma register; 1254 1255insn_format35c_method 1256 : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V 1257 (INSTRUCTION_FORMAT35c_METHOD | INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE) register_list comma fully_qualified_method; 1258 1259insn_format35c_type 1260 : //e.g. filled-new-array {v0,v1}, I 1261 INSTRUCTION_FORMAT35c_TYPE register_list comma nonvoid_type_descriptor; 1262 1263insn_format35c_method_odex 1264 : //e.g. invoke-direct {p0}, Ljava/lang/Object;-><init>()V 1265 INSTRUCTION_FORMAT35c_METHOD_ODEX register_list comma fully_qualified_method; 1266 1267insn_format35mi_method 1268 : //e.g. execute-inline {v0, v1}, inline@0x4 1269 INSTRUCTION_FORMAT35mi_METHOD register_list comma INLINE_INDEX; 1270 1271insn_format35ms_method 1272 : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4 1273 INSTRUCTION_FORMAT35ms_METHOD register_list comma VTABLE_INDEX; 1274 1275insn_format3rc_method 1276 : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1277 INSTRUCTION_FORMAT3rc_METHOD register_range comma fully_qualified_method; 1278 1279insn_format3rc_method_odex 1280 : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;-><init>()V 1281 INSTRUCTION_FORMAT3rc_METHOD_ODEX register_list comma fully_qualified_method; 1282 1283insn_format3rc_type 1284 : //e.g. filled-new-array/range {v0..v6}, I 1285 INSTRUCTION_FORMAT3rc_TYPE register_range comma nonvoid_type_descriptor; 1286 1287insn_format3rmi_method 1288 : //e.g. execute-inline/range {v0 .. v10}, inline@0x14 1289 INSTRUCTION_FORMAT3rmi_METHOD register_range comma INLINE_INDEX; 1290 1291insn_format3rms_method 1292 : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14 1293 INSTRUCTION_FORMAT3rms_METHOD register_range comma VTABLE_INDEX; 1294 1295insn_format51l 1296 : //e.g. const-wide v0, 5000000000L 1297 INSTRUCTION_FORMAT51l register comma fixed_literal; 1298 1299insn_array_data_directive 1300 : ARRAY_DATA_DIRECTIVE 1301 integer_literal 1302 array_data_element* end_array_data_directive; 1303 1304end_array_data_directive 1305 : END_ARRAY_DATA_DIRECTIVE; 1306 catch [RecognitionException re] { 1307 Marker errorMarker = mark(); 1308 recover(input, re); 1309 reportError(errorMarker, re, false); 1310 } 1311 1312array_data_element 1313 @init { Marker marker = mark(); } 1314 : fixed_literal 1315 { marker.done(SmaliElementTypes.ARRAY_DATA_ELEMENT); }; 1316 catch [RecognitionException re] { 1317 recover(input, re); 1318 reportError(marker, re, false); 1319 } 1320 1321insn_packed_switch_directive 1322 : PACKED_SWITCH_DIRECTIVE 1323 fixed_32bit_literal 1324 packed_switch_element* 1325 end_packed_switch_directive; 1326 1327end_packed_switch_directive 1328 : END_PACKED_SWITCH_DIRECTIVE; 1329 catch [RecognitionException re] { 1330 Marker errorMarker = mark(); 1331 recover(input, re); 1332 reportError(errorMarker, re, false); 1333 } 1334 1335packed_switch_element 1336 @init { Marker marker = mark(); } 1337 : label_ref 1338 { marker.done(SmaliElementTypes.PACKED_SWITCH_ELEMENT); }; 1339 catch [RecognitionException re] { 1340 recover(input, re); 1341 reportError(marker, re, false); 1342 } 1343 1344insn_sparse_switch_directive 1345 : SPARSE_SWITCH_DIRECTIVE 1346 sparse_switch_element* 1347 end_sparse_switch_directive; 1348 1349end_sparse_switch_directive 1350 : END_SPARSE_SWITCH_DIRECTIVE; 1351 catch [RecognitionException re] { 1352 Marker errorMarker = mark(); 1353 recover(input, re); 1354 reportError(errorMarker, re, false); 1355 } 1356 1357sparse_switch_element 1358 @init { Marker marker = mark(); } 1359 : fixed_32bit_literal arrow label_ref 1360 { marker.done(SmaliElementTypes.SPARSE_SWITCH_ELEMENT); }; 1361 catch [RecognitionException re] { 1362 recover(input, re); 1363 reportError(marker, re, false); 1364 } 1365