smaliTreeWalker.g revision 9a9a664af23fb4582ef65ec6df4462b94690f0ee
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 java.util.HashMap;
40import java.util.LinkedList;
41import java.util.regex.*;
42import java.lang.Float;
43import java.lang.Double;
44
45import org.jf.dexlib.*;
46import org.jf.dexlib.EncodedValue.*;
47import org.jf.dexlib.Util.*;
48import org.jf.dexlib.Code.*;
49import org.jf.dexlib.Code.Format.*;
50}
51
52@members {
53  public DexFile dexFile;
54  public TypeIdItem classType;
55  private boolean verboseErrors = false;
56
57  public void setVerboseErrors(boolean verboseErrors) {
58    this.verboseErrors = verboseErrors;
59  }
60
61  private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters)
62    throws SemanticException {
63    //register should be in the format "v12"
64    int val = Byte.parseByte(register.substring(1));
65    if (register.charAt(0) == 'p') {
66      val = totalMethodRegisters - methodParameterRegisters + val;
67    }
68    if (val >= 2<<4) {
69      throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15");
70    }
71    //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0;
72    return (byte)val;
73  }
74
75  //return a short, because java's byte is signed
76  private short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters)
77    throws SemanticException {
78    //register should be in the format "v123"
79    int val = Short.parseShort(register.substring(1));
80    if (register.charAt(0) == 'p') {
81      val = totalMethodRegisters - methodParameterRegisters + val;
82    }
83    if (val >= 2<<8) {
84      throw new SemanticException(input, "The maximum allowed register in this context is v255");
85    }
86    return (short)val;
87  }
88
89  //return an int because java's short is signed
90  private int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters)
91    throws SemanticException {
92    //register should be in the format "v12345"
93    int val = Integer.parseInt(register.substring(1));
94    if (register.charAt(0) == 'p') {
95      val = totalMethodRegisters - methodParameterRegisters + val;
96    }
97    if (val >= 2<<16) {
98      throw new SemanticException(input, "The maximum allowed register in this context is v65535");
99    }
100    //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
101    return val;
102  }
103
104  public String getErrorMessage(RecognitionException e, String[] tokenNames) {
105    if ( e instanceof SemanticException ) {
106      return e.getMessage();
107    } else {
108      return super.getErrorMessage(e, tokenNames);
109    }
110  }
111
112  public String getErrorHeader(RecognitionException e) {
113    return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
114  }
115}
116
117
118
119smali_file
120  : ^(I_CLASS_DEF header methods fields annotations)
121  {
122    AnnotationDirectoryItem annotationDirectoryItem = null;
123    ClassDefItem classDefItem = null;
124    ClassDataItem classDataItem = null;
125
126    if ($methods.methodAnnotations != null ||
127        $methods.parameterAnnotations != null ||
128        $fields.fieldAnnotations != null ||
129        $annotations.annotationSetItem != null) {
130        annotationDirectoryItem = AnnotationDirectoryItem.internAnnotationDirectoryItem(
131          dexFile,
132          $annotations.annotationSetItem,
133          $fields.fieldAnnotations,
134          $methods.methodAnnotations,
135          $methods.parameterAnnotations);
136    }
137
138    if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 ||
139        $methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) {
140      classDataItem = ClassDataItem.internClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields,
141                  $methods.directMethods, $methods.virtualMethods);
142    }
143
144    classDefItem = ClassDefItem.internClassDefItem(dexFile, $header.classType, $header.accessFlags,
145        $header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem,
146        classDataItem, $fields.staticFieldInitialValues);
147  };
148  catch [Exception ex] {
149    if (verboseErrors) {
150      ex.printStackTrace(System.err);
151    }
152    reportError(new SemanticException(input, ex));
153  }
154
155
156header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec]
157: class_spec super_spec? implements_list source_spec
158  {
159    classType = $class_spec.type;
160    $classType = classType;
161    $accessFlags = $class_spec.accessFlags;
162    $superType = $super_spec.type;
163    $implementsList = $implements_list.implementsList;
164    $sourceSpec = $source_spec.source;
165  };
166
167
168class_spec returns[TypeIdItem type, int accessFlags]
169  : class_type_descriptor access_list
170  {
171    $type = $class_type_descriptor.type;
172    $accessFlags = $access_list.value;
173  };
174
175super_spec returns[TypeIdItem type]
176  : ^(I_SUPER class_type_descriptor)
177  {
178    $type = $class_type_descriptor.type;
179  };
180
181
182implements_spec returns[TypeIdItem type]
183  : ^(I_IMPLEMENTS class_type_descriptor)
184  {
185    $type = $class_type_descriptor.type;
186  };
187
188implements_list returns[TypeListItem implementsList]
189@init { List<TypeIdItem> typeList; }
190  : {typeList = new LinkedList<TypeIdItem>();}
191    (implements_spec {typeList.add($implements_spec.type);} )*
192  {
193    if (typeList.size() > 0) {
194      $implementsList = TypeListItem.internTypeListItem(dexFile, typeList);
195    } else {
196      $implementsList = null;
197    }
198  };
199
200source_spec returns[StringIdItem source]
201  : {$source = null;}
202    ^(I_SOURCE string_literal {$source = StringIdItem.internStringIdItem(dexFile, $string_literal.value);})
203  | /*epsilon*/;
204
205
206
207access_list returns [int value]
208  @init
209  {
210    $value = 0;
211  }
212  : ^(I_ACCESS_LIST
213      (
214        ACCESS_SPEC
215        {
216          $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue();
217        }
218      )*);
219
220
221fields returns[List<ClassDataItem.EncodedField> staticFields, List<ClassDataItem.EncodedField> instanceFields,
222         List<ClassDefItem.StaticFieldInitializer> staticFieldInitialValues, List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotations]
223  @init
224  {
225    $staticFields = new LinkedList<ClassDataItem.EncodedField>();
226    $instanceFields = new LinkedList<ClassDataItem.EncodedField>();
227    $staticFieldInitialValues = new ArrayList<ClassDefItem.StaticFieldInitializer>();
228  }
229  : ^(I_FIELDS
230      (field
231      {
232        if ($field.encodedField.isStatic()) {
233          $staticFields.add($field.encodedField);
234          $staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer(
235            $field.encodedValue, $field.encodedField));
236        } else {
237          $instanceFields.add($field.encodedField);
238        }
239        if ($field.fieldAnnotationSet != null) {
240          if ($fieldAnnotations == null) {
241            $fieldAnnotations = new LinkedList<AnnotationDirectoryItem.FieldAnnotation>();
242          }
243          AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation(
244            $field.encodedField.field, $field.fieldAnnotationSet);
245          $fieldAnnotations.add(fieldAnnotation);
246        }
247      })*);
248
249methods returns[List<ClassDataItem.EncodedMethod> directMethods,
250    List<ClassDataItem.EncodedMethod> virtualMethods,
251    List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotations,
252    List<AnnotationDirectoryItem.ParameterAnnotation> parameterAnnotations]
253  @init
254  {
255    $directMethods = new LinkedList<ClassDataItem.EncodedMethod>();
256    $virtualMethods = new LinkedList<ClassDataItem.EncodedMethod>();
257  }
258  : ^(I_METHODS
259      (method
260      {
261        if ($method.encodedMethod.isDirect()) {
262          $directMethods.add($method.encodedMethod);
263        } else {
264          $virtualMethods.add($method.encodedMethod);
265        }
266        if ($method.methodAnnotationSet != null) {
267          if ($methodAnnotations == null) {
268            $methodAnnotations = new LinkedList<AnnotationDirectoryItem.MethodAnnotation>();
269          }
270          AnnotationDirectoryItem.MethodAnnotation methodAnnotation =
271            new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet);
272          $methodAnnotations.add(methodAnnotation);
273        }
274        if ($method.parameterAnnotationSets != null) {
275          if ($parameterAnnotations == null) {
276            $parameterAnnotations = new LinkedList<AnnotationDirectoryItem.ParameterAnnotation>();
277          }
278          AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation =
279            new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method,
280              $method.parameterAnnotationSets);
281          $parameterAnnotations.add(parameterAnnotation);
282        }
283      })*);
284
285field returns [ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationSetItem fieldAnnotationSet]
286  :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
287  {
288    StringIdItem memberName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text);
289    TypeIdItem fieldType = $nonvoid_type_descriptor.type;
290
291    FieldIdItem fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, memberName);
292    $encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value);
293
294    if ($field_initial_value.encodedValue != null) {
295      if (!$encodedField.isStatic()) {
296        throw new SemanticException(input, "Initial field values can only be specified for static fields.");
297      }
298
299      $encodedValue = $field_initial_value.encodedValue;
300    } else {
301      $encodedValue = null;
302    }
303
304    if ($annotations.annotationSetItem != null) {
305      $fieldAnnotationSet = $annotations.annotationSetItem;
306    }
307  };
308
309
310field_initial_value returns[EncodedValue encodedValue]
311  : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;}
312  | /*epsilon*/;
313
314literal returns[EncodedValue encodedValue]
315  : integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); }
316  | long_literal { $encodedValue = new LongEncodedValue($long_literal.value); }
317  | short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); }
318  | byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); }
319  | float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); }
320  | double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); }
321  | char_literal { $encodedValue = new CharEncodedValue($char_literal.value); }
322  | string_literal { $encodedValue = new StringEncodedValue(StringIdItem.internStringIdItem(dexFile, $string_literal.value)); }
323  | bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; }
324  | NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; }
325  | type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); }
326  | array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); }
327  | subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); }
328  | field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); }
329  | method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); }
330  | enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); };
331
332
333//everything but string
334fixed_size_literal returns[byte[\] value]
335  : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); }
336  | long_literal { $value = LiteralTools.longToBytes($long_literal.value); }
337  | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); }
338  | byte_literal { $value = new byte[] { $byte_literal.value }; }
339  | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); }
340  | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); }
341  | char_literal { $value = LiteralTools.charToBytes($char_literal.value); }
342  | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); };
343
344//everything but string
345fixed_64bit_literal returns[long value]
346  : integer_literal { $value = $integer_literal.value; }
347  | long_literal { $value = $long_literal.value; }
348  | short_literal { $value = $short_literal.value; }
349  | byte_literal { $value = $byte_literal.value; }
350  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
351  | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); }
352  | char_literal { $value = $char_literal.value; }
353  | bool_literal { $value = $bool_literal.value?1:0; };
354
355//everything but string and double
356//long is allowed, but it must fit into an int
357fixed_32bit_literal returns[int value]
358  : integer_literal { $value = $integer_literal.value; }
359  | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; }
360  | short_literal { $value = $short_literal.value; }
361  | byte_literal { $value = $byte_literal.value; }
362  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
363  | char_literal { $value = $char_literal.value; }
364  | bool_literal { $value = $bool_literal.value?1:0; };
365
366array_elements returns[List<byte[\]> values]
367  : {$values = new ArrayList<byte[]>();}
368    ^(I_ARRAY_ELEMENTS
369      (fixed_size_literal
370      {
371        $values.add($fixed_size_literal.value);
372      })*);
373
374packed_switch_target_count returns[int targetCount]
375  : I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);};
376
377packed_switch_targets[int baseAddress] returns[int[\] targets]
378  :
379    ^(I_PACKED_SWITCH_TARGETS
380      packed_switch_target_count
381      {
382        int targetCount = $packed_switch_target_count.targetCount;
383        $targets = new int[targetCount];
384        int targetsPosition = 0;
385      }
386
387      (offset_or_label
388      {
389        $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress;
390      })*
391    );
392
393sparse_switch_target_count returns[int targetCount]
394  : I_SPARSE_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_SPARSE_SWITCH_TARGET_COUNT.text);};
395
396sparse_switch_keys[int targetCount] returns[int[\] keys]
397  : {
398      $keys = new int[$targetCount];
399      int keysPosition = 0;
400    }
401    ^(I_SPARSE_SWITCH_KEYS
402      (fixed_32bit_literal
403      {
404        $keys[keysPosition++] = $fixed_32bit_literal.value;
405      })*
406    );
407
408
409sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets]
410  : {
411      $targets = new int[$targetCount];
412      int targetsPosition = 0;
413    }
414    ^(I_SPARSE_SWITCH_TARGETS
415      (offset_or_label
416      {
417        $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress;
418      })*
419    );
420
421method returns[ClassDataItem.EncodedMethod encodedMethod,
422    AnnotationSetItem methodAnnotationSet,
423    AnnotationSetRefList parameterAnnotationSets]
424  scope
425  {
426    HashMap<String, Integer> labels;
427    TryListBuilder tryList;
428    int currentAddress;
429    DebugInfoBuilder debugInfo;
430    HashMap<Integer, Integer> packedSwitchDeclarations;
431    HashMap<Integer, Integer> sparseSwitchDeclarations;
432  }
433  @init
434  {
435    MethodIdItem methodIdItem = null;
436    int totalMethodRegisters = 0;
437    int methodParameterRegisters = 0;
438    int accessFlags = 0;
439    boolean isStatic = false;
440  }
441  : {
442      $method::labels = new HashMap<String, Integer>();
443      $method::tryList = new TryListBuilder();
444      $method::currentAddress = 0;
445      $method::debugInfo = new DebugInfoBuilder();
446      $method::packedSwitchDeclarations = new HashMap<Integer, Integer>();
447      $method::sparseSwitchDeclarations = new HashMap<Integer, Integer>();
448    }
449    ^(I_METHOD
450      method_name_and_prototype
451      access_list
452      {
453        methodIdItem = $method_name_and_prototype.methodIdItem;
454        accessFlags = $access_list.value;
455        isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0;
456        methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount();
457        if (!isStatic) {
458          methodParameterRegisters++;
459        }
460      }
461      (registers_directive
462       {
463         if ($registers_directive.isLocalsDirective) {
464           totalMethodRegisters = $registers_directive.registers + methodParameterRegisters;
465         } else {
466           totalMethodRegisters = $registers_directive.registers;
467         }
468       }
469      )?
470      labels
471      packed_switch_declarations
472      sparse_switch_declarations
473      statements[totalMethodRegisters, methodParameterRegisters]
474      catches
475      parameters
476      ordered_debug_directives[totalMethodRegisters, methodParameterRegisters]
477      annotations
478    )
479  {
480    Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries();
481    List<CodeItem.TryItem> tries = temp.first;
482    List<CodeItem.EncodedCatchHandler> handlers = temp.second;
483
484    DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
485
486    CodeItem codeItem;
487
488    boolean isAbstract = false;
489    boolean isNative = false;
490
491    if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) {
492      isAbstract = true;
493    } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) {
494      isNative = true;
495    }
496
497    if ($statements.instructions.size() == 0) {
498      if (!isAbstract && !isNative) {
499        throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction");
500      }
501
502      String methodType;
503      if (isAbstract) {
504        methodType = "an abstract";
505      } else {
506        methodType = "a native";
507      }
508
509          if ($registers_directive.start != null) {
510            if ($registers_directive.isLocalsDirective) {
511              throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType);
512            } else {
513              throw new SemanticException(input, $registers_directive.start, "A  .registers directive is not valid in \%s method", methodType);
514            }
515          }
516
517          if ($method::labels.size() > 0) {
518            throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType);
519          }
520
521          if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) {
522            throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType);
523          }
524
525          if (debugInfoItem != null) {
526            throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType);
527          }
528
529          codeItem = null;
530    } else {
531      if (isAbstract) {
532        throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions");
533      }
534      if (isNative) {
535        throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions");
536      }
537
538      if ($registers_directive.start == null) {
539        throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method");
540      }
541
542      if (totalMethodRegisters < methodParameterRegisters) {
543        throw new SemanticException(input, $registers_directive.start, "This method requires at least " +
544                Integer.toString(methodParameterRegisters) +
545                " registers, for the method parameters");
546      }
547
548      int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount();
549      if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
550        throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " +
551                Integer.toString(methodParameterCount) +
552                " parameters.");
553      }
554
555      codeItem = CodeItem.internCodeItem(dexFile,
556            totalMethodRegisters,
557            methodParameterRegisters,
558            $statements.maxOutRegisters,
559            debugInfoItem,
560            $statements.instructions,
561            tries,
562            handlers);
563    }
564
565    $encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem);
566
567    if ($annotations.annotationSetItem != null) {
568      $methodAnnotationSet = $annotations.annotationSetItem;
569    }
570
571    if ($parameters.parameterAnnotations != null) {
572      $parameterAnnotationSets = $parameters.parameterAnnotations;
573    }
574  };
575
576method_prototype returns[ProtoIdItem protoIdItem]
577  : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list)
578  {
579    TypeIdItem returnType = $type_descriptor.type;
580    List<TypeIdItem> parameterTypes = $field_type_list.types;
581    TypeListItem parameterTypeListItem = null;
582    if (parameterTypes != null && parameterTypes.size() > 0) {
583      parameterTypeListItem = TypeListItem.internTypeListItem(dexFile, parameterTypes);
584    }
585
586    $protoIdItem = ProtoIdItem.internProtoIdItem(dexFile, returnType, parameterTypeListItem);
587  };
588
589method_name_and_prototype returns[MethodIdItem methodIdItem]
590  : SIMPLE_NAME method_prototype
591  {
592    String methodNameString = $SIMPLE_NAME.text;
593    StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, methodNameString);
594    ProtoIdItem protoIdItem = $method_prototype.protoIdItem;
595
596    $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, protoIdItem, methodName);
597  };
598
599field_type_list returns[List<TypeIdItem> types]
600  @init
601  {
602    $types = new LinkedList<TypeIdItem>();
603  }
604  : (
605      nonvoid_type_descriptor
606      {
607        $types.add($nonvoid_type_descriptor.type);
608      }
609    )*;
610
611
612fully_qualified_method returns[MethodIdItem methodIdItem]
613  : reference_type_descriptor SIMPLE_NAME method_prototype
614  {
615    TypeIdItem classType = $reference_type_descriptor.type;
616    StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text);
617    ProtoIdItem prototype = $method_prototype.protoIdItem;
618    $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, prototype, methodName);
619  };
620
621fully_qualified_field returns[FieldIdItem fieldIdItem]
622  : reference_type_descriptor SIMPLE_NAME nonvoid_type_descriptor
623  {
624    TypeIdItem classType = $reference_type_descriptor.type;
625    StringIdItem fieldName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text);
626    TypeIdItem fieldType = $nonvoid_type_descriptor.type;
627    $fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, fieldName);
628  };
629
630registers_directive returns[boolean isLocalsDirective, int registers]
631  : {$registers = 0;}
632    ^(( I_REGISTERS {$isLocalsDirective = false;}
633      | I_LOCALS {$isLocalsDirective = true;}
634      )
635      short_integral_literal {$registers = $short_integral_literal.value;}
636     );
637
638labels
639  : ^(I_LABELS label_def*);
640
641label_def
642  : ^(I_LABEL SIMPLE_NAME address)
643    {
644      if ($method::labels.containsKey($SIMPLE_NAME.text)) {
645        throw new SemanticException(input, $I_LABEL, "Label " + $SIMPLE_NAME.text + " has multiple defintions.");
646      }
647
648      $method::labels.put($SIMPLE_NAME.text, $address.address);
649    };
650
651packed_switch_declarations
652  : ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*);
653packed_switch_declaration
654  : ^(I_PACKED_SWITCH_DECLARATION address offset_or_label_absolute[$address.address])
655    {
656      int switchDataAddress = $offset_or_label_absolute.address;
657      if ((switchDataAddress \% 2) != 0) {
658        switchDataAddress++;
659      }
660      if (!$method::packedSwitchDeclarations.containsKey(switchDataAddress)) {
661        $method::packedSwitchDeclarations.put(switchDataAddress, $address.address);
662      }
663    };
664
665sparse_switch_declarations
666  : ^(I_SPARSE_SWITCH_DECLARATIONS sparse_switch_declaration*);
667sparse_switch_declaration
668  : ^(I_SPARSE_SWITCH_DECLARATION address offset_or_label_absolute[$address.address])
669    {
670      int switchDataAddress = $offset_or_label_absolute.address;
671      if ((switchDataAddress \% 2) != 0) {
672        switchDataAddress++;
673      }
674      if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) {
675        $method::sparseSwitchDeclarations.put(switchDataAddress, $address.address);
676      }
677
678    };
679
680catches : ^(I_CATCHES catch_directive* catchall_directive*);
681
682catch_directive
683  : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address]
684        using=offset_or_label_absolute[$address.address])
685    {
686      TypeIdItem type = $nonvoid_type_descriptor.type;
687      int startAddress = $from.address;
688      int endAddress = $to.address;
689      int handlerAddress = $using.address;
690
691      $method::tryList.addHandler(type, startAddress, endAddress, handlerAddress);
692    };
693
694catchall_directive
695  : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address]
696        using=offset_or_label_absolute[$address.address])
697    {
698      int startAddress = $from.address;
699      int endAddress = $to.address;
700      int handlerAddress = $using.address;
701
702      $method::tryList.addCatchAllHandler(startAddress, endAddress, handlerAddress);
703    };
704
705address returns[int address]
706  : I_ADDRESS
707    {
708      $address = Integer.parseInt($I_ADDRESS.text);
709    };
710
711parameters returns[AnnotationSetRefList parameterAnnotations]
712  @init
713  {
714    int parameterCount = 0;
715    List<AnnotationSetItem> annotationSetItems = new ArrayList<AnnotationSetItem>();
716  }
717  : ^(I_PARAMETERS (parameter
718        {
719          if ($parameter.parameterAnnotationSet != null) {
720            while (annotationSetItems.size() < parameterCount) {
721              annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null));
722            }
723            annotationSetItems.add($parameter.parameterAnnotationSet);
724          }
725
726          parameterCount++;
727        })*
728    )
729    {
730      if (annotationSetItems.size() > 0) {
731        while (annotationSetItems.size() < parameterCount) {
732          annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null));
733        }
734        $parameterAnnotations = AnnotationSetRefList.internAnnotationSetRefList(dexFile, annotationSetItems);
735      }
736    };
737
738parameter returns[AnnotationSetItem parameterAnnotationSet]
739  : ^(I_PARAMETER (string_literal {$method::debugInfo.addParameterName($string_literal.value);}
740                  | {$method::debugInfo.addParameterName(null);}
741                  )
742        annotations {$parameterAnnotationSet = $annotations.annotationSetItem;}
743    );
744
745ordered_debug_directives[int totalMethodRegisters, int methodParameterRegisters]
746  : ^(I_ORDERED_DEBUG_DIRECTIVES
747       ( line
748       | local[$totalMethodRegisters, $methodParameterRegisters]
749       | end_local[$totalMethodRegisters, $methodParameterRegisters]
750       | restart_local[$totalMethodRegisters, $methodParameterRegisters]
751       | prologue
752       | epilogue
753       | source
754       )*
755     );
756
757line
758  : ^(I_LINE integral_literal address)
759    {
760      $method::debugInfo.addLine($address.address, $integral_literal.value);
761    };
762
763local[int totalMethodRegisters, int methodParameterRegisters]
764  : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address)
765    {
766      int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
767
768      if ($string_literal.value != null) {
769        $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value);
770      } else {
771        $method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor());
772      }
773    };
774
775end_local[int totalMethodRegisters, int methodParameterRegisters]
776  : ^(I_END_LOCAL REGISTER address)
777    {
778      int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
779
780      $method::debugInfo.addEndLocal($address.address, registerNumber);
781    };
782
783restart_local[int totalMethodRegisters, int methodParameterRegisters]
784  : ^(I_RESTART_LOCAL REGISTER address)
785    {
786      int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
787
788      $method::debugInfo.addRestartLocal($address.address, registerNumber);
789    };
790
791prologue
792  : ^(I_PROLOGUE address)
793    {
794      $method::debugInfo.addPrologue($address.address);
795    };
796
797epilogue
798  : ^(I_EPILOGUE address)
799    {
800      $method::debugInfo.addEpilogue($address.address);
801    };
802
803source
804  : ^(I_SOURCE string_literal address)
805    {
806      $method::debugInfo.addSetFile($address.address, $string_literal.value);
807    };
808
809statements[int totalMethodRegisters, int methodParameterRegisters] returns[List<Instruction> instructions, int maxOutRegisters]
810  @init
811  {
812    $instructions = new LinkedList<Instruction>();
813    $maxOutRegisters = 0;
814  }
815  : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, $instructions]
816        {
817          $method::currentAddress += $instructions.get($instructions.size() - 1).getSize($method::currentAddress);
818          if ($maxOutRegisters < $instruction.outRegisters) {
819            $maxOutRegisters = $instruction.outRegisters;
820          }
821        })*);
822
823label_ref returns[int labelAddress]
824  : SIMPLE_NAME
825    {
826      Integer labelAdd = $method::labels.get($SIMPLE_NAME.text);
827
828      if (labelAdd == null) {
829        throw new SemanticException(input, $SIMPLE_NAME, "Label \"" + $SIMPLE_NAME.text + "\" is not defined.");
830      }
831
832      $labelAddress = labelAdd;
833    };
834
835offset returns[int offsetValue]
836  : OFFSET
837    {
838      String offsetText = $OFFSET.text;
839      if (offsetText.charAt(0) == '+') {
840        offsetText = offsetText.substring(1);
841      }
842      $offsetValue = LiteralTools.parseInt(offsetText);
843    };
844
845offset_or_label_absolute[int baseAddress] returns[int address]
846  : offset {$address = $offset.offsetValue + $baseAddress;}
847  | label_ref {$address = $label_ref.labelAddress;};
848
849offset_or_label returns[int offsetValue]
850  : offset {$offsetValue = $offset.offsetValue;}
851  | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
852
853
854register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount]
855  @init
856  {
857    $registers = new byte[5];
858    $registerCount = 0;
859  }
860  : ^(I_REGISTER_LIST
861      (REGISTER
862      {
863        if ($registerCount == 5) {
864          throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
865        }
866        $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
867      })*);
868
869register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister]
870  : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
871    {
872        if ($startReg == null) {
873            $startRegister = 0;
874            $endRegister = -1;
875        } else {
876                $startRegister  = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters);
877                if ($endReg == null) {
878                    $endRegister = $startRegister;
879                } else {
880                    $endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
881                }
882
883                int registerCount = $endRegister-$startRegister+1;
884                if (registerCount < 1) {
885                    throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first");
886                }
887            }
888    }
889  ;
890
891verification_error_reference returns[Item item]
892  : CLASS_DESCRIPTOR
893  {
894    $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText());
895  }
896  | fully_qualified_field
897  {
898    $item = $fully_qualified_field.fieldIdItem;
899  }
900  | fully_qualified_method
901  {
902    $item = $fully_qualified_method.methodIdItem;
903  };
904
905verification_error_type returns[VerificationErrorType verificationErrorType]
906  : VERIFICATION_ERROR_TYPE
907  {
908    $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text);
909  };
910
911instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
912  : insn_format10t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10t.outRegisters; }
913  | insn_format10x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10x.outRegisters; }
914  | insn_format11n[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11n.outRegisters; }
915  | insn_format11x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11x.outRegisters; }
916  | insn_format12x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format12x.outRegisters; }
917  | insn_format20bc[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20bc.outRegisters; }
918  | insn_format20t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20t.outRegisters; }
919  | insn_format21c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_field.outRegisters; }
920  | insn_format21c_string[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_string.outRegisters; }
921  | insn_format21c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_type.outRegisters; }
922  | insn_format21h[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21h.outRegisters; }
923  | insn_format21s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21s.outRegisters; }
924  | insn_format21t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21t.outRegisters; }
925  | insn_format22b[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22b.outRegisters; }
926  | insn_format22c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_field.outRegisters; }
927  | insn_format22c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_type.outRegisters; }
928  | insn_format22s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22s.outRegisters; }
929  | insn_format22t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22t.outRegisters; }
930  | insn_format22x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22x.outRegisters; }
931  | insn_format23x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format23x.outRegisters; }
932  | insn_format30t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format30t.outRegisters; }
933  | insn_format31c[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31c.outRegisters; }
934  | insn_format31i[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31i.outRegisters; }
935  | insn_format31t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31t.outRegisters; }
936  | insn_format32x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format32x.outRegisters; }
937  | insn_format35c_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_method.outRegisters; }
938  | insn_format35c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_type.outRegisters; }
939  | insn_format3rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_method.outRegisters; }
940  | insn_format3rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_type.outRegisters; }
941  | insn_format41c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_type.outRegisters; }
942  | insn_format41c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_field.outRegisters; }
943  | insn_format51l_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format51l_type.outRegisters; }
944  | insn_format52c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_type.outRegisters; }
945  | insn_format52c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_field.outRegisters; }
946  | insn_format5rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_method.outRegisters; }
947  | insn_format5rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_type.outRegisters; }
948  | insn_array_data_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_array_data_directive.outRegisters; }
949  | insn_packed_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; }
950  | insn_sparse_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; };
951    catch [Exception ex] {
952      reportError(new SemanticException(input, ex));
953      recover(input, null);
954    }
955
956
957insn_format10t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
958  : //e.g. goto endloop:
959    {$outRegisters = 0;}
960    ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
961    {
962      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
963
964      int addressOffset = $offset_or_label.offsetValue;
965
966      $instructions.add(new Instruction10t(opcode, addressOffset));
967    };
968
969insn_format10x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
970  : //e.g. return
971    ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
972    {
973      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
974      $instructions.add(new Instruction10x(opcode));
975    };
976
977insn_format11n[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
978  : //e.g. const/4 v0, 5
979    ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
980    {
981      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text);
982      byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
983
984      short litB = $short_integral_literal.value;
985      LiteralTools.checkNibble(litB);
986
987      $instructions.add(new Instruction11n(opcode, regA, (byte)litB));
988    };
989
990insn_format11x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
991  : //e.g. move-result-object v1
992    ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
993    {
994      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
995      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
996
997      $instructions.add(new Instruction11x(opcode, regA));
998    };
999
1000insn_format12x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1001  : //e.g. move v1 v2
1002    ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
1003    {
1004      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text);
1005      byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1006      byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1007
1008      $instructions.add(new Instruction12x(opcode, regA, regB));
1009    };
1010
1011insn_format20bc[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1012  : //e.g. throw-verification-error generic-error, Lsome/class;
1013    ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
1014    {
1015      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text);
1016
1017      VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType;
1018      Item referencedItem = $verification_error_reference.item;
1019
1020      $instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem));
1021    };
1022
1023insn_format20t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1024  : //e.g. goto/16 endloop:
1025    ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label)
1026    {
1027      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20t.text);
1028
1029      int addressOffset = $offset_or_label.offsetValue;
1030
1031      $instructions.add(new Instruction20t(opcode, addressOffset));
1032    };
1033
1034insn_format21c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1035  : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream;
1036    ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field)
1037    {
1038      Opcode opcode = Opcode.getOpcodeByName($inst.text);
1039      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1040
1041      FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
1042
1043      $instructions.add(new Instruction21c(opcode, regA, fieldIdItem));
1044    };
1045
1046insn_format21c_string[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1047  : //e.g. const-string v1, "Hello World!"
1048    ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
1049    {
1050      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
1051      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1052
1053      StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value);
1054
1055      instructions.add(new Instruction21c(opcode, regA, stringIdItem));
1056    };
1057
1058insn_format21c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1059  : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2
1060    ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
1061    {
1062      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
1063      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1064
1065      TypeIdItem typeIdItem = $reference_type_descriptor.type;
1066
1067      $instructions.add(new Instruction21c(opcode, regA, typeIdItem));
1068    };
1069
1070insn_format21h[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1071  : //e.g. const/high16 v1, 1234
1072    ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal)
1073    {
1074      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text);
1075      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1076
1077      short litB = $short_integral_literal.value;
1078
1079      instructions.add(new Instruction21h(opcode, regA, litB));
1080    };
1081
1082insn_format21s[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1083  : //e.g. const/16 v1, 1234
1084    ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
1085    {
1086      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text);
1087      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1088
1089      short litB = $short_integral_literal.value;
1090
1091      $instructions.add(new Instruction21s(opcode, regA, litB));
1092    };
1093
1094insn_format21t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1095  : //e.g. if-eqz v0, endloop:
1096    ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label)
1097    {
1098      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text);
1099      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1100
1101      int addressOffset = $offset_or_label.offsetValue;
1102
1103      if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
1104        throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
1105      }
1106
1107      $instructions.add(new Instruction21t(opcode, regA, (short)addressOffset));
1108    };
1109
1110insn_format22b[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1111  : //e.g. add-int v0, v1, 123
1112    ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
1113    {
1114      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text);
1115      short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1116      short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1117
1118      short litC = $short_integral_literal.value;
1119      LiteralTools.checkByte(litC);
1120
1121      $instructions.add(new Instruction22b(opcode, regA, regB, (byte)litC));
1122    };
1123
1124insn_format22c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1125  : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
1126    ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field)
1127    {
1128      Opcode opcode = Opcode.getOpcodeByName($inst.text);
1129      byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1130      byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1131
1132      FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
1133
1134      $instructions.add(new Instruction22c(opcode, regA, regB, fieldIdItem));
1135    };
1136
1137insn_format22c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1138  : //e.g. instance-of v0, v1, Ljava/lang/String;
1139    ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
1140    {
1141      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text);
1142      byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1143      byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1144
1145      TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
1146
1147      $instructions.add(new Instruction22c(opcode, regA, regB, typeIdItem));
1148    };
1149
1150insn_format22s[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1151  : //e.g. add-int/lit16 v0, v1, 12345
1152    ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
1153    {
1154      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text);
1155      byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1156      byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1157
1158      short litC = $short_integral_literal.value;
1159
1160      $instructions.add(new Instruction22s(opcode, regA, regB, litC));
1161    };
1162
1163insn_format22t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1164  : //e.g. if-eq v0, v1, endloop:
1165    ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label)
1166    {
1167      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text);
1168      byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1169      byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1170
1171      int addressOffset = $offset_or_label.offsetValue;
1172
1173      if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
1174        throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
1175      }
1176
1177      $instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset));
1178    };
1179
1180insn_format22x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1181  : //e.g. move/from16 v1, v1234
1182    ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
1183    {
1184      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text);
1185      short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1186      int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1187
1188      $instructions.add(new Instruction22x(opcode, regA, regB));
1189    };
1190
1191insn_format23x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1192  : //e.g. add-int v1, v2, v3
1193    ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
1194    {
1195      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text);
1196      short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1197      short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1198      short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters);
1199
1200      $instructions.add(new Instruction23x(opcode, regA, regB, regC));
1201    };
1202
1203insn_format30t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1204  : //e.g. goto/32 endloop:
1205    ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label)
1206    {
1207      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT30t.text);
1208
1209      int addressOffset = $offset_or_label.offsetValue;
1210
1211      $instructions.add(new Instruction30t(opcode, addressOffset));
1212    };
1213
1214insn_format31c[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1215  : //e.g. const-string/jumbo v1 "Hello World!"
1216    ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
1217    {
1218      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
1219      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1220
1221      StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value);
1222
1223      $instructions.add(new Instruction31c(opcode, regA, stringIdItem));
1224    };
1225
1226insn_format31i[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1227  : //e.g. const v0, 123456
1228    ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
1229    {
1230      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text);
1231      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1232
1233      int litB = $fixed_32bit_literal.value;
1234
1235      $instructions.add(new Instruction31i(opcode, regA, litB));
1236    };
1237
1238insn_format31t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1239  : //e.g. fill-array-data v0, ArrayData:
1240    ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label)
1241    {
1242      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text);
1243
1244      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1245
1246      int addressOffset = $offset_or_label.offsetValue;
1247      if (($method::currentAddress + addressOffset) \% 2 != 0) {
1248        addressOffset++;
1249      }
1250
1251      $instructions.add(new Instruction31t(opcode, regA, addressOffset));
1252    };
1253
1254insn_format32x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1255  : //e.g. move/16 v5678, v1234
1256    ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
1257    {
1258      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text);
1259      int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1260      int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1261
1262      $instructions.add(new Instruction32x(opcode, regA, regB));
1263    };
1264
1265insn_format35c_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1266  : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
1267    ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
1268    {
1269      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text);
1270
1271      //this depends on the fact that register_list returns a byte[5]
1272      byte[] registers = $register_list.registers;
1273      byte registerCount = $register_list.registerCount;
1274      $outRegisters = registerCount;
1275
1276      MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
1277
1278      $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem));
1279    };
1280
1281insn_format35c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1282  : //e.g. filled-new-array {v0,v1}, I
1283    ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
1284    {
1285      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text);
1286
1287      //this depends on the fact that register_list returns a byte[5]
1288      byte[] registers = $register_list.registers;
1289      byte registerCount = $register_list.registerCount;
1290      $outRegisters = registerCount;
1291
1292      TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
1293
1294      $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem));
1295    };
1296
1297insn_format3rc_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1298  : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1299    ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
1300    {
1301      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text);
1302      int startRegister = $register_range.startRegister;
1303      int endRegister = $register_range.endRegister;
1304
1305      int registerCount = endRegister-startRegister+1;
1306      $outRegisters = registerCount;
1307
1308      MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
1309
1310      $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, methodIdItem));
1311    };
1312
1313insn_format3rc_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1314  : //e.g. filled-new-array/range {v0..v6} I
1315    ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
1316    {
1317      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text);
1318      int startRegister = $register_range.startRegister;
1319      int endRegister = $register_range.endRegister;
1320
1321      int registerCount = endRegister-startRegister+1;
1322      $outRegisters = registerCount;
1323
1324      TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
1325
1326      $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, typeIdItem));
1327    };
1328
1329insn_format41c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1330  : //e.g. const-class/jumbo v2, org/jf/HelloWorld2/HelloWorld2
1331    ^(I_STATEMENT_FORMAT41c_TYPE INSTRUCTION_FORMAT41c_TYPE REGISTER reference_type_descriptor)
1332    {
1333      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_TYPE.text);
1334      int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1335
1336      TypeIdItem typeIdItem = $reference_type_descriptor.type;
1337
1338      $instructions.add(new Instruction41c(opcode, regA, typeIdItem));
1339    };
1340
1341insn_format41c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1342  : //e.g. sget-object/jumbo v0, Ljava/lang/System;->out:LJava/io/PrintStream;
1343    ^(I_STATEMENT_FORMAT41c_FIELD INSTRUCTION_FORMAT41c_FIELD REGISTER fully_qualified_field)
1344    {
1345      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_FIELD.text);
1346      int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1347
1348      FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
1349
1350      $instructions.add(new Instruction41c(opcode, regA, fieldIdItem));
1351    };
1352
1353insn_format51l_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1354  : //e.g. const-wide v0, 5000000000L
1355    ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
1356    {
1357      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text);
1358      short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
1359
1360      long litB = $fixed_64bit_literal.value;
1361
1362      $instructions.add(new Instruction51l(opcode, regA, litB));
1363    };
1364
1365insn_format52c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1366  : //e.g. instance-of/jumbo v0, v1, Ljava/lang/String;
1367    ^(I_STATEMENT_FORMAT52c_TYPE INSTRUCTION_FORMAT52c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
1368    {
1369      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_TYPE.text);
1370      int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1371      int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1372
1373      TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
1374
1375      $instructions.add(new Instruction52c(opcode, regA, regB, typeIdItem));
1376    };
1377
1378insn_format52c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1379  : //e.g. iput-object/jumbo v1, v0, Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String;
1380    ^(I_STATEMENT_FORMAT52c_FIELD INSTRUCTION_FORMAT52c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field)
1381    {
1382      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_FIELD.text);
1383      int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
1384      int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
1385
1386      FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
1387
1388      $instructions.add(new Instruction52c(opcode, regA, regB, fieldIdItem));
1389    };
1390
1391insn_format5rc_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1392  : //e.g. invoke-virtual/jumbo {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1393    ^(I_STATEMENT_FORMAT5rc_METHOD INSTRUCTION_FORMAT5rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
1394    {
1395      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_METHOD.text);
1396      int startRegister = $register_range.startRegister;
1397      int endRegister = $register_range.endRegister;
1398
1399      int registerCount = endRegister-startRegister+1;
1400      $outRegisters = registerCount;
1401
1402      MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
1403
1404      $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, methodIdItem));
1405    };
1406
1407insn_format5rc_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1408  : //e.g. filled-new-array/jumbo {v0..v6} I
1409    ^(I_STATEMENT_FORMAT5rc_TYPE INSTRUCTION_FORMAT5rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
1410    {
1411      Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_TYPE.text);
1412      int startRegister = $register_range.startRegister;
1413      int endRegister = $register_range.endRegister;
1414
1415      int registerCount = endRegister-startRegister+1;
1416      $outRegisters = registerCount;
1417
1418      TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
1419
1420      $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, typeIdItem));
1421    };
1422
1423insn_array_data_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1424  : //e.g. .array-data 4 1000000 .end array-data
1425    ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
1426    {
1427      if (($method::currentAddress \% 2) != 0) {
1428        $instructions.add(new Instruction10x(Opcode.NOP));
1429        $method::currentAddress++;
1430      }
1431
1432      int elementWidth = $short_integral_literal.value;
1433      List<byte[]> byteValues = $array_elements.values;
1434
1435      int length = 0;
1436      for (byte[] byteValue: byteValues) {
1437        length+=byteValue.length;
1438      }
1439
1440      byte[] encodedValues = new byte[length];
1441      int index = 0;
1442      for (byte[] byteValue: byteValues) {
1443        System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length);
1444        index+=byteValue.length;
1445      }
1446
1447      $instructions.add(new ArrayDataPseudoInstruction(elementWidth, encodedValues));
1448    };
1449
1450insn_packed_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1451  :
1452    ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
1453      {
1454        if (($method::currentAddress \% 2) != 0) {
1455          $instructions.add(new Instruction10x(Opcode.NOP));
1456          $method::currentAddress++;
1457        }
1458        Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress);
1459        if (baseAddress == null) {
1460          baseAddress = 0;
1461        }
1462      }
1463      packed_switch_targets[baseAddress])
1464    {
1465
1466      int startKey = $fixed_32bit_literal.value;
1467      int[] targets = $packed_switch_targets.targets;
1468
1469      $instructions.add(new PackedSwitchDataPseudoInstruction(startKey, targets));
1470    };
1471
1472insn_sparse_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
1473  :
1474    ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount]
1475      {
1476        if (($method::currentAddress \% 2) != 0) {
1477          $instructions.add(new Instruction10x(Opcode.NOP));
1478          $method::currentAddress++;
1479        }
1480        Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress);
1481        if (baseAddress == null) {
1482          baseAddress = 0;
1483        }
1484      }
1485
1486      sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount])
1487    {
1488      int[] keys = $sparse_switch_keys.keys;
1489      int[] targets = $sparse_switch_targets.targets;
1490
1491      $instructions.add(new SparseSwitchDataPseudoInstruction(keys, targets));
1492    };
1493
1494nonvoid_type_descriptor returns [TypeIdItem type]
1495  : (PRIMITIVE_TYPE
1496  | CLASS_DESCRIPTOR
1497  | ARRAY_DESCRIPTOR)
1498  {
1499    $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText());
1500  };
1501
1502
1503reference_type_descriptor returns [TypeIdItem type]
1504  : (CLASS_DESCRIPTOR
1505  | ARRAY_DESCRIPTOR)
1506  {
1507    $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText());
1508  };
1509
1510
1511
1512
1513
1514
1515class_type_descriptor returns [TypeIdItem type]
1516  : CLASS_DESCRIPTOR
1517  {
1518    $type = TypeIdItem.internTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text);
1519  };
1520
1521type_descriptor returns [TypeIdItem type]
1522  : VOID_TYPE {$type = TypeIdItem.internTypeIdItem(dexFile, "V");}
1523  | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
1524  ;
1525
1526short_integral_literal returns[short value]
1527  : long_literal
1528    {
1529      LiteralTools.checkShort($long_literal.value);
1530      $value = (short)$long_literal.value;
1531    }
1532  | integer_literal
1533    {
1534      LiteralTools.checkShort($integer_literal.value);
1535      $value = (short)$integer_literal.value;
1536    }
1537  | short_literal {$value = $short_literal.value;}
1538  | char_literal {$value = (short)$char_literal.value;}
1539  | byte_literal {$value = $byte_literal.value;};
1540
1541integral_literal returns[int value]
1542  : long_literal
1543    {
1544      LiteralTools.checkInt($long_literal.value);
1545      $value = (int)$long_literal.value;
1546    }
1547  | integer_literal {$value = $integer_literal.value;}
1548  | short_literal {$value = $short_literal.value;}
1549  | byte_literal {$value = $byte_literal.value;};
1550
1551
1552integer_literal returns[int value]
1553  : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); };
1554
1555long_literal returns[long value]
1556  : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); };
1557
1558short_literal returns[short value]
1559  : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); };
1560
1561byte_literal returns[byte value]
1562  : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); };
1563
1564float_literal returns[float value]
1565  : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); };
1566
1567double_literal returns[double value]
1568  : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); };
1569
1570char_literal returns[char value]
1571  : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); };
1572
1573string_literal returns[String value]
1574  : STRING_LITERAL
1575    {
1576      $value = $STRING_LITERAL.text;
1577      $value = $value.substring(1,$value.length()-1);
1578    };
1579
1580bool_literal returns[boolean value]
1581  : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
1582
1583array_literal returns[EncodedValue[\] values]
1584  : {ArrayList<EncodedValue> valuesList = new ArrayList<EncodedValue>();}
1585    ^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*)
1586    {
1587      $values = new EncodedValue[valuesList.size()];
1588      valuesList.toArray($values);
1589    };
1590
1591
1592annotations returns[AnnotationSetItem annotationSetItem]
1593  : {ArrayList<AnnotationItem> annotationList = new ArrayList<AnnotationItem>();}
1594    ^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*)
1595    {
1596      if (annotationList.size() > 0) {
1597        $annotationSetItem = AnnotationSetItem.internAnnotationSetItem(dexFile, annotationList);
1598      }
1599    };
1600
1601
1602annotation returns[AnnotationItem annotationItem]
1603  : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation)
1604    {
1605      AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase());
1606      AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType,
1607          $subannotation.elementNames, $subannotation.elementValues);
1608      $annotationItem = AnnotationItem.internAnnotationItem(dexFile, visibility, encodedAnnotation);
1609    };
1610
1611annotation_element returns[StringIdItem elementName, EncodedValue elementValue]
1612  : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal)
1613    {
1614      $elementName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text);
1615      $elementValue = $literal.encodedValue;
1616    };
1617
1618subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues]
1619  : {ArrayList<StringIdItem> elementNamesList = new ArrayList<StringIdItem>();
1620    ArrayList<EncodedValue> elementValuesList = new ArrayList<EncodedValue>();}
1621    ^(I_SUBANNOTATION
1622        class_type_descriptor
1623        (annotation_element
1624        {
1625          elementNamesList.add($annotation_element.elementName);
1626          elementValuesList.add($annotation_element.elementValue);
1627        }
1628        )*
1629     )
1630    {
1631      $annotationType = $class_type_descriptor.type;
1632      $elementNames = new StringIdItem[elementNamesList.size()];
1633      elementNamesList.toArray($elementNames);
1634      $elementValues = new EncodedValue[elementValuesList.size()];
1635      elementValuesList.toArray($elementValues);
1636    };
1637
1638field_literal returns[FieldIdItem value]
1639  : ^(I_ENCODED_FIELD fully_qualified_field)
1640    {
1641      $value = $fully_qualified_field.fieldIdItem;
1642    };
1643
1644method_literal returns[MethodIdItem value]
1645  : ^(I_ENCODED_METHOD fully_qualified_method)
1646    {
1647      $value = $fully_qualified_method.methodIdItem;
1648    };
1649
1650enum_literal returns[FieldIdItem value]
1651  : ^(I_ENCODED_ENUM fully_qualified_field)
1652    {
1653      $value = $fully_qualified_field.fieldIdItem;
1654    };
1655