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