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 29tree grammar smaliTreeWalker; 30 31options { 32 tokenVocab=smaliParser; 33 ASTLabelType=CommonTree; 34} 35 36@header { 37package org.jf.smali; 38 39import com.google.common.collect.ImmutableSet; 40import com.google.common.collect.Iterables; 41import com.google.common.collect.Lists; 42import com.google.common.collect.Maps; 43import org.antlr.runtime.BitSet; 44import org.antlr.runtime.*; 45import org.antlr.runtime.tree.CommonTree; 46import org.antlr.runtime.tree.TreeNodeStream; 47import org.antlr.runtime.tree.TreeParser; 48import org.antlr.runtime.tree.TreeRuleReturnScope; 49import org.jf.dexlib2.*; 50import org.jf.dexlib2.builder.Label; 51import org.jf.dexlib2.builder.MethodImplementationBuilder; 52import org.jf.dexlib2.builder.SwitchLabelElement; 53import org.jf.dexlib2.builder.instruction.*; 54import org.jf.dexlib2.iface.Annotation; 55import org.jf.dexlib2.iface.AnnotationElement; 56import org.jf.dexlib2.iface.ClassDef; 57import org.jf.dexlib2.iface.MethodImplementation; 58import org.jf.dexlib2.iface.reference.FieldReference; 59import org.jf.dexlib2.iface.reference.MethodReference; 60import org.jf.dexlib2.iface.value.EncodedValue; 61import org.jf.dexlib2.immutable.ImmutableAnnotation; 62import org.jf.dexlib2.immutable.ImmutableAnnotationElement; 63import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; 64import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; 65import org.jf.dexlib2.immutable.reference.ImmutableReference; 66import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; 67import org.jf.dexlib2.immutable.value.*; 68import org.jf.dexlib2.util.MethodUtil; 69import org.jf.dexlib2.writer.InstructionFactory; 70import org.jf.dexlib2.writer.builder.*; 71import org.jf.util.LinearSearch; 72 73import java.util.*; 74} 75 76@members { 77 public String classType; 78 private boolean verboseErrors = false; 79 private int apiLevel = 15; 80 private Opcodes opcodes = new Opcodes(apiLevel); 81 private DexBuilder dexBuilder; 82 83 public void setDexBuilder(DexBuilder dexBuilder) { 84 this.dexBuilder = dexBuilder; 85 } 86 87 public void setApiLevel(int apiLevel) { 88 this.opcodes = new Opcodes(apiLevel); 89 this.apiLevel = apiLevel; 90 } 91 92 public void setVerboseErrors(boolean verboseErrors) { 93 this.verboseErrors = verboseErrors; 94 } 95 96 private byte parseRegister_nibble(String register) 97 throws SemanticException { 98 int totalMethodRegisters = method_stack.peek().totalMethodRegisters; 99 int methodParameterRegisters = method_stack.peek().methodParameterRegisters; 100 101 //register should be in the format "v12" 102 int val = Byte.parseByte(register.substring(1)); 103 if (register.charAt(0) == 'p') { 104 val = totalMethodRegisters - methodParameterRegisters + val; 105 } 106 if (val >= 2<<4) { 107 throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15"); 108 } 109 //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0; 110 return (byte)val; 111 } 112 113 //return a short, because java's byte is signed 114 private short parseRegister_byte(String register) 115 throws SemanticException { 116 int totalMethodRegisters = method_stack.peek().totalMethodRegisters; 117 int methodParameterRegisters = method_stack.peek().methodParameterRegisters; 118 //register should be in the format "v123" 119 int val = Short.parseShort(register.substring(1)); 120 if (register.charAt(0) == 'p') { 121 val = totalMethodRegisters - methodParameterRegisters + val; 122 } 123 if (val >= 2<<8) { 124 throw new SemanticException(input, "The maximum allowed register in this context is v255"); 125 } 126 return (short)val; 127 } 128 129 //return an int because java's short is signed 130 private int parseRegister_short(String register) 131 throws SemanticException { 132 int totalMethodRegisters = method_stack.peek().totalMethodRegisters; 133 int methodParameterRegisters = method_stack.peek().methodParameterRegisters; 134 //register should be in the format "v12345" 135 int val = Integer.parseInt(register.substring(1)); 136 if (register.charAt(0) == 'p') { 137 val = totalMethodRegisters - methodParameterRegisters + val; 138 } 139 if (val >= 2<<16) { 140 throw new SemanticException(input, "The maximum allowed register in this context is v65535"); 141 } 142 //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0; 143 return val; 144 } 145 146 public String getErrorMessage(RecognitionException e, String[] tokenNames) { 147 if ( e instanceof SemanticException ) { 148 return e.getMessage(); 149 } else { 150 return super.getErrorMessage(e, tokenNames); 151 } 152 } 153 154 public String getErrorHeader(RecognitionException e) { 155 return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; 156 } 157} 158 159smali_file returns[ClassDef classDef] 160 : ^(I_CLASS_DEF header methods fields annotations) 161 { 162 $classDef = dexBuilder.internClassDef($header.classType, $header.accessFlags, $header.superType, 163 $header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods); 164 }; 165 catch [Exception ex] { 166 if (verboseErrors) { 167 ex.printStackTrace(System.err); 168 } 169 reportError(new SemanticException(input, ex)); 170 } 171 172 173header returns[String classType, int accessFlags, String superType, List<String> implementsList, String sourceSpec] 174: class_spec super_spec? implements_list source_spec 175 { 176 classType = $class_spec.type; 177 $classType = classType; 178 $accessFlags = $class_spec.accessFlags; 179 $superType = $super_spec.type; 180 $implementsList = $implements_list.implementsList; 181 $sourceSpec = $source_spec.source; 182 }; 183 184 185class_spec returns[String type, int accessFlags] 186 : CLASS_DESCRIPTOR access_list 187 { 188 $type = $CLASS_DESCRIPTOR.text; 189 $accessFlags = $access_list.value; 190 }; 191 192super_spec returns[String type] 193 : ^(I_SUPER CLASS_DESCRIPTOR) 194 { 195 $type = $CLASS_DESCRIPTOR.text; 196 }; 197 198 199implements_spec returns[String type] 200 : ^(I_IMPLEMENTS CLASS_DESCRIPTOR) 201 { 202 $type = $CLASS_DESCRIPTOR.text; 203 }; 204 205implements_list returns[List<String> implementsList] 206@init { List<String> typeList; } 207 : {typeList = Lists.newArrayList();} 208 (implements_spec {typeList.add($implements_spec.type);} )* 209 { 210 if (typeList.size() > 0) { 211 $implementsList = typeList; 212 } else { 213 $implementsList = null; 214 } 215 }; 216 217source_spec returns[String source] 218 : {$source = null;} 219 ^(I_SOURCE string_literal {$source = $string_literal.value;}) 220 | /*epsilon*/; 221 222access_list returns [int value] 223 @init 224 { 225 $value = 0; 226 } 227 : ^(I_ACCESS_LIST 228 ( 229 ACCESS_SPEC 230 { 231 $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue(); 232 } 233 )*); 234 235 236fields returns[List<BuilderField> fields] 237 @init {$fields = Lists.newArrayList();} 238 : ^(I_FIELDS 239 (field 240 { 241 $fields.add($field.field); 242 })*); 243 244methods returns[List<BuilderMethod> methods] 245 @init {$methods = Lists.newArrayList();} 246 : ^(I_METHODS 247 (method 248 { 249 $methods.add($method.ret); 250 })*); 251 252field returns [BuilderField field] 253 :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) 254 { 255 int accessFlags = $access_list.value; 256 257 258 if (!AccessFlags.STATIC.isSet(accessFlags) && $field_initial_value.encodedValue != null) { 259 throw new SemanticException(input, "Initial field values can only be specified for static fields."); 260 } 261 262 $field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value, 263 $field_initial_value.encodedValue, $annotations.annotations); 264 }; 265 266 267field_initial_value returns[EncodedValue encodedValue] 268 : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;} 269 | /*epsilon*/; 270 271literal returns[EncodedValue encodedValue] 272 : integer_literal { $encodedValue = new ImmutableIntEncodedValue($integer_literal.value); } 273 | long_literal { $encodedValue = new ImmutableLongEncodedValue($long_literal.value); } 274 | short_literal { $encodedValue = new ImmutableShortEncodedValue($short_literal.value); } 275 | byte_literal { $encodedValue = new ImmutableByteEncodedValue($byte_literal.value); } 276 | float_literal { $encodedValue = new ImmutableFloatEncodedValue($float_literal.value); } 277 | double_literal { $encodedValue = new ImmutableDoubleEncodedValue($double_literal.value); } 278 | char_literal { $encodedValue = new ImmutableCharEncodedValue($char_literal.value); } 279 | string_literal { $encodedValue = new ImmutableStringEncodedValue($string_literal.value); } 280 | bool_literal { $encodedValue = ImmutableBooleanEncodedValue.forBoolean($bool_literal.value); } 281 | NULL_LITERAL { $encodedValue = ImmutableNullEncodedValue.INSTANCE; } 282 | type_descriptor { $encodedValue = new ImmutableTypeEncodedValue($type_descriptor.type); } 283 | array_literal { $encodedValue = new ImmutableArrayEncodedValue($array_literal.elements); } 284 | subannotation { $encodedValue = new ImmutableAnnotationEncodedValue($subannotation.annotationType, $subannotation.elements); } 285 | field_literal { $encodedValue = new ImmutableFieldEncodedValue($field_literal.value); } 286 | method_literal { $encodedValue = new ImmutableMethodEncodedValue($method_literal.value); } 287 | enum_literal { $encodedValue = new ImmutableEnumEncodedValue($enum_literal.value); }; 288 289//everything but string 290fixed_64bit_literal_number returns[Number value] 291 : integer_literal { $value = $integer_literal.value; } 292 | long_literal { $value = $long_literal.value; } 293 | short_literal { $value = $short_literal.value; } 294 | byte_literal { $value = $byte_literal.value; } 295 | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } 296 | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } 297 | char_literal { $value = (int)$char_literal.value; } 298 | bool_literal { $value = $bool_literal.value?1:0; }; 299 300fixed_64bit_literal returns[long value] 301 : integer_literal { $value = $integer_literal.value; } 302 | long_literal { $value = $long_literal.value; } 303 | short_literal { $value = $short_literal.value; } 304 | byte_literal { $value = $byte_literal.value; } 305 | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } 306 | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } 307 | char_literal { $value = $char_literal.value; } 308 | bool_literal { $value = $bool_literal.value?1:0; }; 309 310//everything but string and double 311//long is allowed, but it must fit into an int 312fixed_32bit_literal returns[int value] 313 : integer_literal { $value = $integer_literal.value; } 314 | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; } 315 | short_literal { $value = $short_literal.value; } 316 | byte_literal { $value = $byte_literal.value; } 317 | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } 318 | char_literal { $value = $char_literal.value; } 319 | bool_literal { $value = $bool_literal.value?1:0; }; 320 321array_elements returns[List<Number> elements] 322 : {$elements = Lists.newArrayList();} 323 ^(I_ARRAY_ELEMENTS 324 (fixed_64bit_literal_number 325 { 326 $elements.add($fixed_64bit_literal_number.value); 327 })*); 328 329packed_switch_elements returns[List<Label> elements] 330 @init {$elements = Lists.newArrayList();} 331 : 332 ^(I_PACKED_SWITCH_ELEMENTS 333 (label_ref { $elements.add($label_ref.label); })* 334 ); 335 336sparse_switch_elements returns[List<SwitchLabelElement> elements] 337 @init {$elements = Lists.newArrayList();} 338 : 339 ^(I_SPARSE_SWITCH_ELEMENTS 340 (fixed_32bit_literal label_ref 341 { 342 $elements.add(new SwitchLabelElement($fixed_32bit_literal.value, $label_ref.label)); 343 })* 344 ); 345 346method returns[BuilderMethod ret] 347 scope 348 { 349 boolean isStatic; 350 int totalMethodRegisters; 351 int methodParameterRegisters; 352 MethodImplementationBuilder methodBuilder; 353 } 354 @init 355 { 356 $method::totalMethodRegisters = 0; 357 $method::methodParameterRegisters = 0; 358 int accessFlags = 0; 359 $method::isStatic = false; 360 } 361 : 362 ^(I_METHOD 363 method_name_and_prototype 364 access_list 365 { 366 accessFlags = $access_list.value; 367 $method::isStatic = AccessFlags.STATIC.isSet(accessFlags); 368 $method::methodParameterRegisters = 369 MethodUtil.getParameterRegisterCount($method_name_and_prototype.parameters, $method::isStatic); 370 } 371 ( 372 (registers_directive 373 { 374 if ($registers_directive.isLocalsDirective) { 375 $method::totalMethodRegisters = $registers_directive.registers + $method::methodParameterRegisters; 376 } else { 377 $method::totalMethodRegisters = $registers_directive.registers; 378 } 379 380 $method::methodBuilder = new MethodImplementationBuilder($method::totalMethodRegisters); 381 382 }) 383 | 384 /* epsilon */ 385 { 386 $method::methodBuilder = new MethodImplementationBuilder(0); 387 } 388 ) 389 ordered_method_items 390 catches 391 parameters[$method_name_and_prototype.parameters] 392 annotations 393 ) 394 { 395 MethodImplementation methodImplementation = null; 396 List<BuilderTryBlock> tryBlocks = $catches.tryBlocks; 397 398 boolean isAbstract = false; 399 boolean isNative = false; 400 401 if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) { 402 isAbstract = true; 403 } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) { 404 isNative = true; 405 } 406 407 methodImplementation = $method::methodBuilder.getMethodImplementation(); 408 409 if (Iterables.isEmpty(methodImplementation.getInstructions())) { 410 if (!isAbstract && !isNative) { 411 throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction"); 412 } 413 414 String methodType; 415 if (isAbstract) { 416 methodType = "an abstract"; 417 } else { 418 methodType = "a native"; 419 } 420 421 if ($registers_directive.start != null) { 422 if ($registers_directive.isLocalsDirective) { 423 throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); 424 } else { 425 throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); 426 } 427 } 428 429 if (methodImplementation.getTryBlocks().size() > 0) { 430 throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); 431 } 432 433 if (!Iterables.isEmpty(methodImplementation.getDebugItems())) { 434 throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); 435 } 436 437 methodImplementation = null; 438 } else { 439 if (isAbstract) { 440 throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions"); 441 } 442 if (isNative) { 443 throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions"); 444 } 445 446 if ($registers_directive.start == null) { 447 throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method"); 448 } 449 450 if ($method::totalMethodRegisters < $method::methodParameterRegisters) { 451 throw new SemanticException(input, $registers_directive.start, "This method requires at least " + 452 Integer.toString($method::methodParameterRegisters) + 453 " registers, for the method parameters"); 454 } 455 } 456 457 $ret = dexBuilder.internMethod( 458 classType, 459 $method_name_and_prototype.name, 460 $method_name_and_prototype.parameters, 461 $method_name_and_prototype.returnType, 462 accessFlags, 463 $annotations.annotations, 464 methodImplementation); 465 }; 466 467method_prototype returns[List<String> parameters, String returnType] 468 : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) method_type_list) 469 { 470 $returnType = $type_descriptor.type; 471 $parameters = $method_type_list.types; 472 }; 473 474method_name_and_prototype returns[String name, List<SmaliMethodParameter> parameters, String returnType] 475 : SIMPLE_NAME method_prototype 476 { 477 $name = $SIMPLE_NAME.text; 478 $parameters = Lists.newArrayList(); 479 480 int paramRegister = 0; 481 for (String type: $method_prototype.parameters) { 482 $parameters.add(new SmaliMethodParameter(paramRegister++, type)); 483 char c = type.charAt(0); 484 if (c == 'D' || c == 'J') { 485 paramRegister++; 486 } 487 } 488 $returnType = $method_prototype.returnType; 489 }; 490 491method_type_list returns[List<String> types] 492 @init 493 { 494 $types = Lists.newArrayList(); 495 } 496 : ( 497 nonvoid_type_descriptor 498 { 499 $types.add($nonvoid_type_descriptor.type); 500 } 501 )*; 502 503 504method_reference returns[ImmutableMethodReference methodReference] 505 : reference_type_descriptor? SIMPLE_NAME method_prototype 506 { 507 String type; 508 if ($reference_type_descriptor.type == null) { 509 type = classType; 510 } else { 511 type = $reference_type_descriptor.type; 512 } 513 $methodReference = new ImmutableMethodReference(type, $SIMPLE_NAME.text, 514 $method_prototype.parameters, $method_prototype.returnType); 515 }; 516 517field_reference returns[ImmutableFieldReference fieldReference] 518 : reference_type_descriptor? SIMPLE_NAME nonvoid_type_descriptor 519 { 520 String type; 521 if ($reference_type_descriptor.type == null) { 522 type = classType; 523 } else { 524 type = $reference_type_descriptor.type; 525 } 526 $fieldReference = new ImmutableFieldReference(type, $SIMPLE_NAME.text, 527 $nonvoid_type_descriptor.type); 528 }; 529 530registers_directive returns[boolean isLocalsDirective, int registers] 531 : {$registers = 0;} 532 ^(( I_REGISTERS {$isLocalsDirective = false;} 533 | I_LOCALS {$isLocalsDirective = true;} 534 ) 535 short_integral_literal {$registers = $short_integral_literal.value;} 536 ); 537 538label_def 539 : ^(I_LABEL SIMPLE_NAME) 540 { 541 $method::methodBuilder.addLabel($SIMPLE_NAME.text); 542 }; 543 544catches returns[List<BuilderTryBlock> tryBlocks] 545 @init {tryBlocks = Lists.newArrayList();} 546 : ^(I_CATCHES catch_directive* catchall_directive*); 547 548catch_directive 549 : ^(I_CATCH nonvoid_type_descriptor from=label_ref to=label_ref using=label_ref) 550 { 551 $method::methodBuilder.addCatch(dexBuilder.internTypeReference($nonvoid_type_descriptor.type), 552 $from.label, $to.label, $using.label); 553 }; 554 555catchall_directive 556 : ^(I_CATCHALL from=label_ref to=label_ref using=label_ref) 557 { 558 $method::methodBuilder.addCatch($from.label, $to.label, $using.label); 559 }; 560 561parameters[List<SmaliMethodParameter> parameters] 562 : ^(I_PARAMETERS (parameter[parameters])*); 563 564parameter[List<SmaliMethodParameter> parameters] 565 : ^(I_PARAMETER REGISTER string_literal? annotations) 566 { 567 final int registerNumber = parseRegister_short($REGISTER.text); 568 int totalMethodRegisters = $method::totalMethodRegisters; 569 int methodParameterRegisters = $method::methodParameterRegisters; 570 571 if (registerNumber >= totalMethodRegisters) { 572 throw new SemanticException(input, $I_PARAMETER, "Register \%s is larger than the maximum register v\%d " + 573 "for this method", $REGISTER.text, totalMethodRegisters-1); 574 } 575 final int indexGuess = registerNumber - (totalMethodRegisters - methodParameterRegisters) - ($method::isStatic?0:1); 576 577 if (indexGuess < 0) { 578 throw new SemanticException(input, $I_PARAMETER, "Register \%s is not a parameter register.", 579 $REGISTER.text); 580 } 581 582 int parameterIndex = LinearSearch.linearSearch(parameters, SmaliMethodParameter.COMPARATOR, 583 new WithRegister() { public int getRegister() { return indexGuess; } }, 584 indexGuess); 585 586 if (parameterIndex < 0) { 587 throw new SemanticException(input, $I_PARAMETER, "Register \%s is the second half of a wide parameter.", 588 $REGISTER.text); 589 } 590 591 SmaliMethodParameter methodParameter = parameters.get(parameterIndex); 592 methodParameter.name = $string_literal.value; 593 if ($annotations.annotations != null && $annotations.annotations.size() > 0) { 594 methodParameter.annotations = $annotations.annotations; 595 } 596 }; 597 598debug_directive 599 : line 600 | local 601 | end_local 602 | restart_local 603 | prologue 604 | epilogue 605 | source; 606 607line 608 : ^(I_LINE integral_literal) 609 { 610 $method::methodBuilder.addLineNumber($integral_literal.value); 611 }; 612 613local 614 : ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)?) 615 { 616 int registerNumber = parseRegister_short($REGISTER.text); 617 $method::methodBuilder.addStartLocal(registerNumber, 618 dexBuilder.internNullableStringReference($name.value), 619 dexBuilder.internNullableTypeReference($nonvoid_type_descriptor.type), 620 dexBuilder.internNullableStringReference($signature.value)); 621 }; 622 623end_local 624 : ^(I_END_LOCAL REGISTER) 625 { 626 int registerNumber = parseRegister_short($REGISTER.text); 627 $method::methodBuilder.addEndLocal(registerNumber); 628 }; 629 630restart_local 631 : ^(I_RESTART_LOCAL REGISTER) 632 { 633 int registerNumber = parseRegister_short($REGISTER.text); 634 $method::methodBuilder.addRestartLocal(registerNumber); 635 }; 636 637prologue 638 : I_PROLOGUE 639 { 640 $method::methodBuilder.addPrologue(); 641 }; 642 643epilogue 644 : I_EPILOGUE 645 { 646 $method::methodBuilder.addEpilogue(); 647 }; 648 649source 650 : ^(I_SOURCE string_literal?) 651 { 652 $method::methodBuilder.addSetSourceFile(dexBuilder.internNullableStringReference($string_literal.value)); 653 }; 654 655ordered_method_items 656 : ^(I_ORDERED_METHOD_ITEMS (label_def | instruction | debug_directive)*); 657 658label_ref returns[Label label] 659 : SIMPLE_NAME { $label = $method::methodBuilder.getLabel($SIMPLE_NAME.text); }; 660 661register_list returns[byte[\] registers, byte registerCount] 662 @init 663 { 664 $registers = new byte[5]; 665 $registerCount = 0; 666 } 667 : ^(I_REGISTER_LIST 668 (REGISTER 669 { 670 if ($registerCount == 5) { 671 throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 " + 672 "registers. Use the <op>/range alternate opcode instead."); 673 } 674 $registers[$registerCount++] = parseRegister_nibble($REGISTER.text); 675 })*); 676 677register_range returns[int startRegister, int endRegister] 678 : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) 679 { 680 if ($startReg == null) { 681 $startRegister = 0; 682 $endRegister = -1; 683 } else { 684 $startRegister = parseRegister_short($startReg.text); 685 if ($endReg == null) { 686 $endRegister = $startRegister; 687 } else { 688 $endRegister = parseRegister_short($endReg.text); 689 } 690 691 int registerCount = $endRegister-$startRegister+1; 692 if (registerCount < 1) { 693 throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first"); 694 } 695 } 696 }; 697 698verification_error_reference returns[ImmutableReference reference] 699 : CLASS_DESCRIPTOR 700 { 701 $reference = new ImmutableTypeReference($CLASS_DESCRIPTOR.text); 702 } 703 | field_reference 704 { 705 $reference = $field_reference.fieldReference; 706 } 707 | method_reference 708 { 709 $reference = $method_reference.methodReference; 710 }; 711 712verification_error_type returns[int verificationError] 713 : VERIFICATION_ERROR_TYPE 714 { 715 $verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text); 716 }; 717 718instruction 719 : insn_format10t 720 | insn_format10x 721 | insn_format11n 722 | insn_format11x 723 | insn_format12x 724 | insn_format20bc 725 | insn_format20t 726 | insn_format21c_field 727 | insn_format21c_string 728 | insn_format21c_type 729 | insn_format21ih 730 | insn_format21lh 731 | insn_format21s 732 | insn_format21t 733 | insn_format22b 734 | insn_format22c_field 735 | insn_format22c_type 736 | insn_format22s 737 | insn_format22t 738 | insn_format22x 739 | insn_format23x 740 | insn_format30t 741 | insn_format31c 742 | insn_format31i 743 | insn_format31t 744 | insn_format32x 745 | insn_format35c_method 746 | insn_format35c_type 747 | insn_format3rc_method 748 | insn_format3rc_type 749 | insn_format51l_type 750 | insn_array_data_directive 751 | insn_packed_switch_directive 752 | insn_sparse_switch_directive; 753 catch [Exception ex] { 754 reportError(new SemanticException(input, $start, ex.getMessage())); 755 recover(input, null); 756 } 757 758insn_format10t 759 : //e.g. goto endloop: 760 ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref) 761 { 762 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10t.text); 763 $method::methodBuilder.addInstruction(new BuilderInstruction10t(opcode, $label_ref.label)); 764 }; 765 766insn_format10x 767 : //e.g. return 768 ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) 769 { 770 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text); 771 $method::methodBuilder.addInstruction(new BuilderInstruction10x(opcode)); 772 }; 773 774insn_format11n 775 : //e.g. const/4 v0, 5 776 ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) 777 { 778 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11n.text); 779 byte regA = parseRegister_nibble($REGISTER.text); 780 781 short litB = $short_integral_literal.value; 782 LiteralTools.checkNibble(litB); 783 784 $method::methodBuilder.addInstruction(new BuilderInstruction11n(opcode, regA, litB)); 785 }; 786 787insn_format11x 788 : //e.g. move-result-object v1 789 ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) 790 { 791 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text); 792 short regA = parseRegister_byte($REGISTER.text); 793 794 $method::methodBuilder.addInstruction(new BuilderInstruction11x(opcode, regA)); 795 }; 796 797insn_format12x 798 : //e.g. move v1 v2 799 ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) 800 { 801 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT12x.text); 802 byte regA = parseRegister_nibble($registerA.text); 803 byte regB = parseRegister_nibble($registerB.text); 804 805 $method::methodBuilder.addInstruction(new BuilderInstruction12x(opcode, regA, regB)); 806 }; 807 808insn_format20bc 809 : //e.g. throw-verification-error generic-error, Lsome/class; 810 ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) 811 { 812 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); 813 814 int verificationError = $verification_error_type.verificationError; 815 ImmutableReference referencedItem = $verification_error_reference.reference; 816 817 $method::methodBuilder.addInstruction(new BuilderInstruction20bc(opcode, verificationError, 818 dexBuilder.internReference(referencedItem))); 819 }; 820 821insn_format20t 822 : //e.g. goto/16 endloop: 823 ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t label_ref) 824 { 825 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20t.text); 826 $method::methodBuilder.addInstruction(new BuilderInstruction20t(opcode, $label_ref.label)); 827 }; 828 829insn_format21c_field 830 : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream; 831 ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER field_reference) 832 { 833 Opcode opcode = opcodes.getOpcodeByName($inst.text); 834 short regA = parseRegister_byte($REGISTER.text); 835 836 ImmutableFieldReference fieldReference = $field_reference.fieldReference; 837 838 $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, 839 dexBuilder.internFieldReference(fieldReference))); 840 }; 841 842insn_format21c_string 843 : //e.g. const-string v1, "Hello World!" 844 ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) 845 { 846 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); 847 short regA = parseRegister_byte($REGISTER.text); 848 849 $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, 850 dexBuilder.internStringReference($string_literal.value))); 851 }; 852 853insn_format21c_type 854 : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2 855 ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor) 856 { 857 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); 858 short regA = parseRegister_byte($REGISTER.text); 859 860 $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, 861 dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); 862 }; 863 864insn_format21ih 865 : //e.g. const/high16 v1, 1234 866 ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal) 867 { 868 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21ih.text); 869 short regA = parseRegister_byte($REGISTER.text); 870 871 int litB = $fixed_32bit_literal.value; 872 873 $method::methodBuilder.addInstruction(new BuilderInstruction21ih(opcode, regA, litB)); 874 }; 875 876insn_format21lh 877 : //e.g. const-wide/high16 v1, 1234 878 ^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal) 879 { 880 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21lh.text); 881 short regA = parseRegister_byte($REGISTER.text); 882 883 long litB = $fixed_64bit_literal.value; 884 885 $method::methodBuilder.addInstruction(new BuilderInstruction21lh(opcode, regA, litB)); 886 }; 887 888insn_format21s 889 : //e.g. const/16 v1, 1234 890 ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) 891 { 892 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21s.text); 893 short regA = parseRegister_byte($REGISTER.text); 894 895 short litB = $short_integral_literal.value; 896 897 $method::methodBuilder.addInstruction(new BuilderInstruction21s(opcode, regA, litB)); 898 }; 899 900insn_format21t 901 : //e.g. if-eqz v0, endloop: 902 ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER label_ref) 903 { 904 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21t.text); 905 short regA = parseRegister_byte($REGISTER.text); 906 907 $method::methodBuilder.addInstruction(new BuilderInstruction21t(opcode, regA, $label_ref.label)); 908 }; 909 910insn_format22b 911 : //e.g. add-int v0, v1, 123 912 ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) 913 { 914 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22b.text); 915 short regA = parseRegister_byte($registerA.text); 916 short regB = parseRegister_byte($registerB.text); 917 918 short litC = $short_integral_literal.value; 919 LiteralTools.checkByte(litC); 920 921 $method::methodBuilder.addInstruction(new BuilderInstruction22b(opcode, regA, regB, litC)); 922 }; 923 924insn_format22c_field 925 : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 926 ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER field_reference) 927 { 928 Opcode opcode = opcodes.getOpcodeByName($inst.text); 929 byte regA = parseRegister_nibble($registerA.text); 930 byte regB = parseRegister_nibble($registerB.text); 931 932 ImmutableFieldReference fieldReference = $field_reference.fieldReference; 933 934 $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB, 935 dexBuilder.internFieldReference(fieldReference))); 936 }; 937 938insn_format22c_type 939 : //e.g. instance-of v0, v1, Ljava/lang/String; 940 ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) 941 { 942 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); 943 byte regA = parseRegister_nibble($registerA.text); 944 byte regB = parseRegister_nibble($registerB.text); 945 946 $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB, 947 dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); 948 }; 949 950insn_format22s 951 : //e.g. add-int/lit16 v0, v1, 12345 952 ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) 953 { 954 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22s.text); 955 byte regA = parseRegister_nibble($registerA.text); 956 byte regB = parseRegister_nibble($registerB.text); 957 958 short litC = $short_integral_literal.value; 959 960 $method::methodBuilder.addInstruction(new BuilderInstruction22s(opcode, regA, regB, litC)); 961 }; 962 963insn_format22t 964 : //e.g. if-eq v0, v1, endloop: 965 ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER label_ref) 966 { 967 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22t.text); 968 byte regA = parseRegister_nibble($registerA.text); 969 byte regB = parseRegister_nibble($registerB.text); 970 971 $method::methodBuilder.addInstruction(new BuilderInstruction22t(opcode, regA, regB, $label_ref.label)); 972 }; 973 974insn_format22x 975 : //e.g. move/from16 v1, v1234 976 ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) 977 { 978 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22x.text); 979 short regA = parseRegister_byte($registerA.text); 980 int regB = parseRegister_short($registerB.text); 981 982 $method::methodBuilder.addInstruction(new BuilderInstruction22x(opcode, regA, regB)); 983 }; 984 985insn_format23x 986 : //e.g. add-int v1, v2, v3 987 ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) 988 { 989 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT23x.text); 990 short regA = parseRegister_byte($registerA.text); 991 short regB = parseRegister_byte($registerB.text); 992 short regC = parseRegister_byte($registerC.text); 993 994 $method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC)); 995 }; 996 997insn_format30t 998 : //e.g. goto/32 endloop: 999 ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref) 1000 { 1001 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT30t.text); 1002 1003 $method::methodBuilder.addInstruction(new BuilderInstruction30t(opcode, $label_ref.label)); 1004 }; 1005 1006insn_format31c 1007 : //e.g. const-string/jumbo v1 "Hello World!" 1008 ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) 1009 { 1010 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text); 1011 short regA = parseRegister_byte($REGISTER.text); 1012 1013 $method::methodBuilder.addInstruction(new BuilderInstruction31c(opcode, regA, 1014 dexBuilder.internStringReference($string_literal.value))); 1015 }; 1016 1017insn_format31i 1018 : //e.g. const v0, 123456 1019 ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) 1020 { 1021 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31i.text); 1022 short regA = parseRegister_byte($REGISTER.text); 1023 1024 int litB = $fixed_32bit_literal.value; 1025 1026 $method::methodBuilder.addInstruction(new BuilderInstruction31i(opcode, regA, litB)); 1027 }; 1028 1029insn_format31t 1030 : //e.g. fill-array-data v0, ArrayData: 1031 ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER label_ref) 1032 { 1033 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31t.text); 1034 1035 short regA = parseRegister_byte($REGISTER.text); 1036 1037 $method::methodBuilder.addInstruction(new BuilderInstruction31t(opcode, regA, $label_ref.label)); 1038 }; 1039 1040insn_format32x 1041 : //e.g. move/16 v5678, v1234 1042 ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) 1043 { 1044 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT32x.text); 1045 int regA = parseRegister_short($registerA.text); 1046 int regB = parseRegister_short($registerB.text); 1047 1048 $method::methodBuilder.addInstruction(new BuilderInstruction32x(opcode, regA, regB)); 1049 }; 1050 1051insn_format35c_method 1052 : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V 1053 ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list method_reference) 1054 { 1055 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); 1056 1057 //this depends on the fact that register_list returns a byte[5] 1058 byte[] registers = $register_list.registers; 1059 byte registerCount = $register_list.registerCount; 1060 1061 ImmutableMethodReference methodReference = $method_reference.methodReference; 1062 1063 $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1], 1064 registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference))); 1065 }; 1066 1067insn_format35c_type 1068 : //e.g. filled-new-array {v0,v1}, I 1069 ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor) 1070 { 1071 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); 1072 1073 //this depends on the fact that register_list returns a byte[5] 1074 byte[] registers = $register_list.registers; 1075 byte registerCount = $register_list.registerCount; 1076 1077 $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1], 1078 registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); 1079 }; 1080 1081insn_format3rc_method 1082 : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1083 ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range method_reference) 1084 { 1085 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); 1086 int startRegister = $register_range.startRegister; 1087 int endRegister = $register_range.endRegister; 1088 1089 int registerCount = endRegister-startRegister+1; 1090 1091 ImmutableMethodReference methodReference = $method_reference.methodReference; 1092 1093 $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount, 1094 dexBuilder.internMethodReference(methodReference))); 1095 }; 1096 1097insn_format3rc_type 1098 : //e.g. filled-new-array/range {v0..v6} I 1099 ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor) 1100 { 1101 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text); 1102 int startRegister = $register_range.startRegister; 1103 int endRegister = $register_range.endRegister; 1104 1105 int registerCount = endRegister-startRegister+1; 1106 1107 $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount, 1108 dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); 1109 }; 1110 1111insn_format51l_type 1112 : //e.g. const-wide v0, 5000000000L 1113 ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) 1114 { 1115 Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT51l.text); 1116 short regA = parseRegister_byte($REGISTER.text); 1117 1118 long litB = $fixed_64bit_literal.value; 1119 1120 $method::methodBuilder.addInstruction(new BuilderInstruction51l(opcode, regA, litB)); 1121 }; 1122 1123insn_array_data_directive 1124 : //e.g. .array-data 4 1000000 .end array-data 1125 ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) 1126 { 1127 int elementWidth = $short_integral_literal.value; 1128 List<Number> elements = $array_elements.elements; 1129 1130 $method::methodBuilder.addInstruction(new BuilderArrayPayload(elementWidth, $array_elements.elements)); 1131 }; 1132 1133insn_packed_switch_directive 1134 : 1135 ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) packed_switch_elements) 1136 { 1137 int startKey = $fixed_32bit_literal.value; 1138 $method::methodBuilder.addInstruction(new BuilderPackedSwitchPayload(startKey, 1139 $packed_switch_elements.elements)); 1140 }; 1141 1142insn_sparse_switch_directive 1143 : 1144 ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements) 1145 { 1146 $method::methodBuilder.addInstruction(new BuilderSparseSwitchPayload($sparse_switch_elements.elements)); 1147 }; 1148 1149nonvoid_type_descriptor returns [String type] 1150 : (PRIMITIVE_TYPE 1151 | CLASS_DESCRIPTOR 1152 | ARRAY_DESCRIPTOR) 1153 { 1154 $type = $start.getText(); 1155 }; 1156 1157reference_type_descriptor returns [String type] 1158 : (CLASS_DESCRIPTOR 1159 | ARRAY_DESCRIPTOR) 1160 { 1161 $type = $start.getText(); 1162 }; 1163 1164type_descriptor returns [String type] 1165 : VOID_TYPE {$type = "V";} 1166 | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;} 1167 ; 1168 1169short_integral_literal returns[short value] 1170 : long_literal 1171 { 1172 LiteralTools.checkShort($long_literal.value); 1173 $value = (short)$long_literal.value; 1174 } 1175 | integer_literal 1176 { 1177 LiteralTools.checkShort($integer_literal.value); 1178 $value = (short)$integer_literal.value; 1179 } 1180 | short_literal {$value = $short_literal.value;} 1181 | char_literal {$value = (short)$char_literal.value;} 1182 | byte_literal {$value = $byte_literal.value;}; 1183 1184integral_literal returns[int value] 1185 : long_literal 1186 { 1187 LiteralTools.checkInt($long_literal.value); 1188 $value = (int)$long_literal.value; 1189 } 1190 | integer_literal {$value = $integer_literal.value;} 1191 | short_literal {$value = $short_literal.value;} 1192 | byte_literal {$value = $byte_literal.value;}; 1193 1194 1195integer_literal returns[int value] 1196 : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); }; 1197 1198long_literal returns[long value] 1199 : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); }; 1200 1201short_literal returns[short value] 1202 : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); }; 1203 1204byte_literal returns[byte value] 1205 : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); }; 1206 1207float_literal returns[float value] 1208 : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); }; 1209 1210double_literal returns[double value] 1211 : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); }; 1212 1213char_literal returns[char value] 1214 : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); }; 1215 1216string_literal returns[String value] 1217 : STRING_LITERAL 1218 { 1219 $value = $STRING_LITERAL.text; 1220 $value = $value.substring(1,$value.length()-1); 1221 }; 1222 1223bool_literal returns[boolean value] 1224 : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); }; 1225 1226array_literal returns[List<EncodedValue> elements] 1227 : {$elements = Lists.newArrayList();} 1228 ^(I_ENCODED_ARRAY (literal {$elements.add($literal.encodedValue);})*); 1229 1230annotations returns[Set<Annotation> annotations] 1231 : {HashMap<String, Annotation> annotationMap = Maps.newHashMap();} 1232 ^(I_ANNOTATIONS (annotation 1233 { 1234 Annotation anno = $annotation.annotation; 1235 Annotation old = annotationMap.put(anno.getType(), anno); 1236 if (old != null) { 1237 throw new SemanticException(input, "Multiple annotations of type \%s", anno.getType()); 1238 } 1239 })*) 1240 { 1241 if (annotationMap.size() > 0) { 1242 $annotations = ImmutableSet.copyOf(annotationMap.values()); 1243 } 1244 }; 1245 1246annotation returns[Annotation annotation] 1247 : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation) 1248 { 1249 int visibility = AnnotationVisibility.getVisibility($ANNOTATION_VISIBILITY.text); 1250 $annotation = new ImmutableAnnotation(visibility, $subannotation.annotationType, $subannotation.elements); 1251 }; 1252 1253annotation_element returns[AnnotationElement element] 1254 : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal) 1255 { 1256 $element = new ImmutableAnnotationElement($SIMPLE_NAME.text, $literal.encodedValue); 1257 }; 1258 1259subannotation returns[String annotationType, List<AnnotationElement> elements] 1260 : {ArrayList<AnnotationElement> elements = Lists.newArrayList();} 1261 ^(I_SUBANNOTATION 1262 CLASS_DESCRIPTOR 1263 (annotation_element 1264 { 1265 elements.add($annotation_element.element); 1266 })* 1267 ) 1268 { 1269 $annotationType = $CLASS_DESCRIPTOR.text; 1270 $elements = elements; 1271 }; 1272 1273field_literal returns[FieldReference value] 1274 : ^(I_ENCODED_FIELD field_reference) 1275 { 1276 $value = $field_reference.fieldReference; 1277 }; 1278 1279method_literal returns[MethodReference value] 1280 : ^(I_ENCODED_METHOD method_reference) 1281 { 1282 $value = $method_reference.methodReference; 1283 }; 1284 1285enum_literal returns[FieldReference value] 1286 : ^(I_ENCODED_ENUM field_reference) 1287 { 1288 $value = $field_reference.fieldReference; 1289 }; 1290