smaliParser.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
29parser grammar smaliParser;
30
31options {
32  output=AST;
33  ASTLabelType=CommonTree;
34}
35
36tokens {
37  //Lexer tokens
38  ACCESS_SPEC;
39  ANNOTATION_DIRECTIVE;
40  ANNOTATION_VISIBILITY;
41  ARRAY_DATA_DIRECTIVE;
42  ARRAY_DESCRIPTOR;
43  ARROW;
44  BASE_ARRAY_DESCRIPTOR;
45  BASE_CHAR_LITERAL;
46  BASE_CLASS_DESCRIPTOR;
47  BASE_FLOAT;
48  BASE_FLOAT_OR_ID;
49  BASE_INTEGER;
50  BASE_PRIMITIVE_TYPE;
51  BASE_SIMPLE_NAME;
52  BASE_STRING_LITERAL;
53  BASE_TYPE;
54  BINARY_EXPONENT;
55  BOOL_LITERAL;
56  BYTE_LITERAL;
57  CATCH_DIRECTIVE;
58  CATCHALL_DIRECTIVE;
59  CHAR_LITERAL;
60  CLASS_DESCRIPTOR;
61  CLASS_DIRECTIVE;
62  CLOSE_BRACE;
63  CLOSE_PAREN;
64  COLON;
65  COMMA;
66  DECIMAL_EXPONENT;
67  DOTDOT;
68  DOUBLE_LITERAL;
69  DOUBLE_LITERAL_OR_ID;
70  END_ANNOTATION_DIRECTIVE;
71  END_ARRAY_DATA_DIRECTIVE;
72  END_FIELD_DIRECTIVE;
73  END_LOCAL_DIRECTIVE;
74  END_METHOD_DIRECTIVE;
75  END_PACKED_SWITCH_DIRECTIVE;
76  END_PARAMETER_DIRECTIVE;
77  END_SPARSE_SWITCH_DIRECTIVE;
78  END_SUBANNOTATION_DIRECTIVE;
79  ENUM_DIRECTIVE;
80  EPILOGUE_DIRECTIVE;
81  EQUAL;
82  ESCAPE_SEQUENCE;
83  FIELD_DIRECTIVE;
84  FIELD_OFFSET;
85  FLOAT_LITERAL;
86  FLOAT_LITERAL_OR_ID;
87  HEX_DIGIT;
88  HEX_DIGITS;
89  HEX_PREFIX;
90  IMPLEMENTS_DIRECTIVE;
91  INLINE_INDEX;
92  INSTRUCTION_FORMAT10t;
93  INSTRUCTION_FORMAT10x;
94  INSTRUCTION_FORMAT10x_ODEX;
95  INSTRUCTION_FORMAT11n;
96  INSTRUCTION_FORMAT11x;
97  INSTRUCTION_FORMAT12x;
98  INSTRUCTION_FORMAT12x_OR_ID;
99  INSTRUCTION_FORMAT20bc;
100  INSTRUCTION_FORMAT20t;
101  INSTRUCTION_FORMAT21c_FIELD;
102  INSTRUCTION_FORMAT21c_FIELD_ODEX;
103  INSTRUCTION_FORMAT21c_STRING;
104  INSTRUCTION_FORMAT21c_TYPE;
105  INSTRUCTION_FORMAT21h;
106  INSTRUCTION_FORMAT21s;
107  INSTRUCTION_FORMAT21t;
108  INSTRUCTION_FORMAT22b;
109  INSTRUCTION_FORMAT22c_FIELD;
110  INSTRUCTION_FORMAT22c_FIELD_ODEX;
111  INSTRUCTION_FORMAT22c_TYPE;
112  INSTRUCTION_FORMAT22cs_FIELD;
113  INSTRUCTION_FORMAT22s;
114  INSTRUCTION_FORMAT22s_OR_ID;
115  INSTRUCTION_FORMAT22t;
116  INSTRUCTION_FORMAT22x;
117  INSTRUCTION_FORMAT23x;
118  INSTRUCTION_FORMAT30t;
119  INSTRUCTION_FORMAT31c;
120  INSTRUCTION_FORMAT31i;
121  INSTRUCTION_FORMAT31i_OR_ID;
122  INSTRUCTION_FORMAT31t;
123  INSTRUCTION_FORMAT32x;
124  INSTRUCTION_FORMAT35c_METHOD;
125  INSTRUCTION_FORMAT35c_METHOD_ODEX;
126  INSTRUCTION_FORMAT35c_TYPE;
127  INSTRUCTION_FORMAT35mi_METHOD;
128  INSTRUCTION_FORMAT35ms_METHOD;
129  INSTRUCTION_FORMAT3rc_METHOD;
130  INSTRUCTION_FORMAT3rc_METHOD_ODEX;
131  INSTRUCTION_FORMAT3rc_TYPE;
132  INSTRUCTION_FORMAT3rmi_METHOD;
133  INSTRUCTION_FORMAT3rms_METHOD;
134  INSTRUCTION_FORMAT51l;
135  INVALID_TOKEN;
136  LINE_COMMENT;
137  LINE_DIRECTIVE;
138  LOCAL_DIRECTIVE;
139  LOCALS_DIRECTIVE;
140  LONG_LITERAL;
141  METHOD_DIRECTIVE;
142  METHOD_NAME;
143  NEGATIVE_INTEGER_LITERAL;
144  NULL_LITERAL;
145  OFFSET;
146  OPEN_BRACE;
147  OPEN_PAREN;
148  PACKED_SWITCH_DIRECTIVE;
149  PARAM_LIST;
150  PARAM_LIST_OR_ID;
151  PARAMETER_DIRECTIVE;
152  POSITIVE_INTEGER_LITERAL;
153  PRIMITIVE_TYPE;
154  PROLOGUE_DIRECTIVE;
155  REGISTER;
156  REGISTERS_DIRECTIVE;
157  RESTART_LOCAL_DIRECTIVE;
158  SHORT_LITERAL;
159  SIMPLE_NAME;
160  SOURCE_DIRECTIVE;
161  SPARSE_SWITCH_DIRECTIVE;
162  STRING_LITERAL;
163  SUBANNOTATION_DIRECTIVE;
164  SUPER_DIRECTIVE;
165  VERIFICATION_ERROR_TYPE;
166  VOID_TYPE;
167  VTABLE_INDEX;
168  WHITE_SPACE;
169
170  //A couple of generated types that we remap other tokens to, to simplify the generated AST
171  LABEL;
172  INTEGER_LITERAL;
173
174  //I_* tokens are imaginary tokens used as parent AST nodes
175  I_CLASS_DEF;
176  I_SUPER;
177  I_IMPLEMENTS;
178  I_SOURCE;
179  I_ACCESS_LIST;
180  I_METHODS;
181  I_FIELDS;
182  I_FIELD;
183  I_FIELD_TYPE;
184  I_FIELD_INITIAL_VALUE;
185  I_METHOD;
186  I_METHOD_PROTOTYPE;
187  I_METHOD_RETURN_TYPE;
188  I_REGISTERS;
189  I_LOCALS;
190  I_LABELS;
191  I_LABEL;
192  I_ANNOTATIONS;
193  I_ANNOTATION;
194  I_ANNOTATION_ELEMENT;
195  I_SUBANNOTATION;
196  I_ENCODED_FIELD;
197  I_ENCODED_METHOD;
198  I_ENCODED_ENUM;
199  I_ENCODED_ARRAY;
200  I_ARRAY_ELEMENT_SIZE;
201  I_ARRAY_ELEMENTS;
202  I_PACKED_SWITCH_START_KEY;
203  I_PACKED_SWITCH_TARGET_COUNT;
204  I_PACKED_SWITCH_TARGETS;
205  I_PACKED_SWITCH_DECLARATION;
206  I_PACKED_SWITCH_DECLARATIONS;
207  I_SPARSE_SWITCH_KEYS;
208  I_SPARSE_SWITCH_TARGET_COUNT;
209  I_SPARSE_SWITCH_TARGETS;
210  I_SPARSE_SWITCH_DECLARATION;
211  I_SPARSE_SWITCH_DECLARATIONS;
212  I_ADDRESS;
213  I_CATCH;
214  I_CATCHALL;
215  I_CATCHES;
216  I_PARAMETER;
217  I_PARAMETERS;
218  I_PARAMETER_NOT_SPECIFIED;
219  I_ORDERED_DEBUG_DIRECTIVES;
220  I_LINE;
221  I_LOCAL;
222  I_END_LOCAL;
223  I_RESTART_LOCAL;
224  I_PROLOGUE;
225  I_EPILOGUE;
226  I_STATEMENTS;
227  I_STATEMENT_FORMAT10t;
228  I_STATEMENT_FORMAT10x;
229  I_STATEMENT_FORMAT11n;
230  I_STATEMENT_FORMAT11x;
231  I_STATEMENT_FORMAT12x;
232  I_STATEMENT_FORMAT20bc;
233  I_STATEMENT_FORMAT20t;
234  I_STATEMENT_FORMAT21c_TYPE;
235  I_STATEMENT_FORMAT21c_FIELD;
236  I_STATEMENT_FORMAT21c_STRING;
237  I_STATEMENT_FORMAT21h;
238  I_STATEMENT_FORMAT21s;
239  I_STATEMENT_FORMAT21t;
240  I_STATEMENT_FORMAT22b;
241  I_STATEMENT_FORMAT22c_FIELD;
242  I_STATEMENT_FORMAT22c_TYPE;
243  I_STATEMENT_FORMAT22s;
244  I_STATEMENT_FORMAT22t;
245  I_STATEMENT_FORMAT22x;
246  I_STATEMENT_FORMAT23x;
247  I_STATEMENT_FORMAT30t;
248  I_STATEMENT_FORMAT31c;
249  I_STATEMENT_FORMAT31i;
250  I_STATEMENT_FORMAT31t;
251  I_STATEMENT_FORMAT32x;
252  I_STATEMENT_FORMAT35c_METHOD;
253  I_STATEMENT_FORMAT35c_TYPE;
254  I_STATEMENT_FORMAT3rc_METHOD;
255  I_STATEMENT_FORMAT3rc_TYPE;
256  I_STATEMENT_FORMAT41c_TYPE;
257  I_STATEMENT_FORMAT41c_FIELD;
258  I_STATEMENT_FORMAT51l;
259  I_STATEMENT_FORMAT52c_TYPE;
260  I_STATEMENT_FORMAT52c_FIELD;
261  I_STATEMENT_FORMAT5rc_METHOD;
262  I_STATEMENT_FORMAT5rc_TYPE;
263  I_STATEMENT_ARRAY_DATA;
264  I_STATEMENT_PACKED_SWITCH;
265  I_STATEMENT_SPARSE_SWITCH;
266  I_REGISTER_RANGE;
267  I_REGISTER_LIST;
268}
269
270@header {
271package org.jf.smali;
272
273import org.jf.dexlib.Code.Format.*;
274import org.jf.dexlib.Code.Opcode;
275}
276
277
278@members {
279  public static final int ERROR_CHANNEL = 100;
280
281  private boolean verboseErrors = false;
282  private boolean allowOdex = false;
283  private int apiLevel;
284
285  public void setVerboseErrors(boolean verboseErrors) {
286    this.verboseErrors = verboseErrors;
287  }
288
289  public void setAllowOdex(boolean allowOdex) {
290      this.allowOdex = allowOdex;
291  }
292
293  public void setApiLevel(int apiLevel) {
294      this.apiLevel = apiLevel;
295  }
296
297  public String getErrorMessage(RecognitionException e,
298    String[] tokenNames) {
299
300    if (verboseErrors) {
301      List stack = getRuleInvocationStack(e, this.getClass().getName());
302      String msg = null;
303
304      if (e instanceof NoViableAltException) {
305        NoViableAltException nvae = (NoViableAltException)e;
306        msg = " no viable alt; token="+getTokenErrorDisplay(e.token)+
307        " (decision="+nvae.decisionNumber+
308        " state "+nvae.stateNumber+")"+
309        " decision=<<"+nvae.grammarDecisionDescription+">>";
310      } else {
311        msg = super.getErrorMessage(e, tokenNames);
312      }
313
314      return stack + " " + msg;
315    } else {
316      return super.getErrorMessage(e, tokenNames);
317    }
318  }
319
320  public String getTokenErrorDisplay(Token t) {
321    if (!verboseErrors) {
322      String s = t.getText();
323      if ( s==null ) {
324        if ( t.getType()==Token.EOF ) {
325          s = "<EOF>";
326        }
327        else {
328          s = "<"+tokenNames[t.getType()]+">";
329        }
330      }
331      s = s.replaceAll("\n","\\\\n");
332      s = s.replaceAll("\r","\\\\r");
333      s = s.replaceAll("\t","\\\\t");
334      return "'"+s+"'";
335    }
336
337    CommonToken ct = (CommonToken)t;
338
339    String channelStr = "";
340    if (t.getChannel()>0) {
341      channelStr=",channel="+t.getChannel();
342    }
343    String txt = t.getText();
344    if ( txt!=null ) {
345      txt = txt.replaceAll("\n","\\\\n");
346      txt = txt.replaceAll("\r","\\\\r");
347      txt = txt.replaceAll("\t","\\\\t");
348    }
349    else {
350      txt = "<no text>";
351    }
352    return "[@"+t.getTokenIndex()+","+ct.getStartIndex()+":"+ct.getStopIndex()+"='"+txt+"',<"+tokenNames[t.getType()]+">"+channelStr+","+t.getLine()+":"+t.getCharPositionInLine()+"]";
353  }
354
355  public String getErrorHeader(RecognitionException e) {
356    return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
357  }
358
359  private CommonTree buildTree(int type, String text, List<CommonTree> children) {
360    CommonTree root = new CommonTree(new CommonToken(type, text));
361    for (CommonTree child: children) {
362      root.addChild(child);
363    }
364    return root;
365  }
366
367  private CommonToken getParamListSubToken(CommonToken baseToken, String str, int typeStartIndex) {
368    CommonToken token = new CommonToken(baseToken);
369    token.setStartIndex(baseToken.getStartIndex() + typeStartIndex);
370
371    switch (str.charAt(typeStartIndex)) {
372      case 'Z':
373      case 'B':
374      case 'S':
375      case 'C':
376      case 'I':
377      case 'J':
378      case 'F':
379      case 'D':
380      {
381        token.setType(PRIMITIVE_TYPE);
382        token.setText(str.substring(typeStartIndex, typeStartIndex+1));
383        token.setStopIndex(baseToken.getStartIndex() + typeStartIndex);
384        break;
385      }
386      case 'L':
387      {
388        int i = typeStartIndex;
389        while (str.charAt(++i) != ';');
390
391        token.setType(CLASS_DESCRIPTOR);
392        token.setText(str.substring(typeStartIndex, i + 1));
393        token.setStopIndex(baseToken.getStartIndex() + i);
394        break;
395      }
396      case '[':
397      {
398        int i = typeStartIndex;
399            while (str.charAt(++i) == '[');
400
401            if (str.charAt(i++) == 'L') {
402                while (str.charAt(i++) != ';');
403        }
404
405            token.setType(ARRAY_DESCRIPTOR);
406            token.setText(str.substring(typeStartIndex, i));
407            token.setStopIndex(baseToken.getStartIndex() + i - 1);
408            break;
409      }
410      default:
411        throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex));
412    }
413
414    return token;
415  }
416
417  private CommonTree parseParamList(CommonToken paramListToken) {
418    String paramList = paramListToken.getText();
419    CommonTree root = new CommonTree();
420
421    int startIndex = paramListToken.getStartIndex();
422
423    int i=0;
424    while (i<paramList.length()) {
425      CommonToken token = getParamListSubToken(paramListToken, paramList, i);
426      root.addChild(new CommonTree(token));
427      i += token.getText().length();
428    }
429
430    if (root.getChildCount() == 0) {
431      return null;
432    }
433    return root;
434  }
435
436  private void throwOdexedInstructionException(IntStream input, String odexedInstruction)
437      throws OdexedInstructionException {
438    /*this has to be done in a separate method, otherwise java will complain about the
439    auto-generated code in the rule after the throw not being reachable*/
440    throw new OdexedInstructionException(input, odexedInstruction);
441  }
442}
443
444
445smali_file
446  scope
447  {
448    boolean hasClassSpec;
449    boolean hasSuperSpec;
450    boolean hasSourceSpec;
451    List<CommonTree> classAnnotations;
452  }
453  @init
454  { $smali_file::hasClassSpec = $smali_file::hasSuperSpec = $smali_file::hasSourceSpec = false;
455    $smali_file::classAnnotations = new ArrayList<CommonTree>();
456  }
457  :
458  ( {!$smali_file::hasClassSpec}?=> class_spec {$smali_file::hasClassSpec = true;}
459  | {!$smali_file::hasSuperSpec}?=> super_spec {$smali_file::hasSuperSpec = true;}
460  | implements_spec
461  | {!$smali_file::hasSourceSpec}?=> source_spec {$smali_file::hasSourceSpec = true;}
462  | method
463  | field
464  | annotation {$smali_file::classAnnotations.add($annotation.tree);}
465  )+
466  EOF
467  {
468    if (!$smali_file::hasClassSpec) {
469      throw new SemanticException(input, "The file must contain a .class directive");
470    }
471
472    if (!$smali_file::hasSuperSpec) {
473      if (!$class_spec.className.equals("Ljava/lang/Object;")) {
474        throw new SemanticException(input, "The file must contain a .super directive");
475      }
476    }
477  }
478  -> ^(I_CLASS_DEF
479       class_spec
480       super_spec?
481       implements_spec*
482       source_spec?
483       ^(I_METHODS method*) ^(I_FIELDS field*) {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $smali_file::classAnnotations)});
484
485class_spec returns[String className]
486  : CLASS_DIRECTIVE access_list CLASS_DESCRIPTOR {$className = $CLASS_DESCRIPTOR.text;} -> CLASS_DESCRIPTOR access_list;
487
488super_spec
489  : SUPER_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_SUPER[$start, "I_SUPER"] CLASS_DESCRIPTOR);
490
491implements_spec
492  : IMPLEMENTS_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_IMPLEMENTS[$start, "I_IMPLEMENTS"] CLASS_DESCRIPTOR);
493
494source_spec
495  : SOURCE_DIRECTIVE STRING_LITERAL -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL);
496
497access_list
498  : ACCESS_SPEC* -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC*);
499
500
501/*When there are annotations immediately after a field definition, we don't know whether they are field annotations
502or class annotations until we determine if there is an .end field directive. In either case, we still "consume" and parse
503the annotations. If it turns out that they are field annotations, we include them in the I_FIELD AST. Otherwise, we
504add them to the $smali_file::classAnnotations list*/
505field
506  @init {List<CommonTree> annotations = new ArrayList<CommonTree>();}
507  : FIELD_DIRECTIVE access_list simple_name COLON nonvoid_type_descriptor (EQUAL literal)?
508    ( ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})*
509      ( END_FIELD_DIRECTIVE
510        -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*))
511      | /*epsilon*/ {$smali_file::classAnnotations.addAll(annotations);}
512        -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS))
513      )
514    );
515
516method
517  scope {int currentAddress;}
518  : {$method::currentAddress = 0;}
519    METHOD_DIRECTIVE access_list method_name method_prototype statements_and_directives
520    END_METHOD_DIRECTIVE
521    -> ^(I_METHOD[$start, "I_METHOD"] method_name method_prototype access_list statements_and_directives);
522
523statements_and_directives
524  scope
525  {
526    boolean hasRegistersDirective;
527    List<CommonTree> packedSwitchDeclarations;
528    List<CommonTree> sparseSwitchDeclarations;
529    List<CommonTree> methodAnnotations;
530  }
531  : {
532      $method::currentAddress = 0;
533      $statements_and_directives::hasRegistersDirective = false;
534      $statements_and_directives::packedSwitchDeclarations = new ArrayList<CommonTree>();
535      $statements_and_directives::sparseSwitchDeclarations = new ArrayList<CommonTree>();
536      $statements_and_directives::methodAnnotations = new ArrayList<CommonTree>();
537    }
538    ( instruction {$method::currentAddress += $instruction.size/2;}
539    | registers_directive
540    | label
541    | catch_directive
542    | catchall_directive
543    | parameter_directive
544    | ordered_debug_directive
545    | annotation  {$statements_and_directives::methodAnnotations.add($annotation.tree);}
546    )*
547    -> registers_directive?
548       ^(I_LABELS label*)
549       {buildTree(I_PACKED_SWITCH_DECLARATIONS, "I_PACKED_SWITCH_DECLARATIONS", $statements_and_directives::packedSwitchDeclarations)}
550       {buildTree(I_SPARSE_SWITCH_DECLARATIONS, "I_SPARSE_SWITCH_DECLARATIONS", $statements_and_directives::sparseSwitchDeclarations)}
551       ^(I_STATEMENTS instruction*)
552       ^(I_CATCHES catch_directive* catchall_directive*)
553       ^(I_PARAMETERS parameter_directive*)
554       ^(I_ORDERED_DEBUG_DIRECTIVES ordered_debug_directive*)
555       {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $statements_and_directives::methodAnnotations)};
556
557registers_directive
558  : (
559      directive=REGISTERS_DIRECTIVE regCount=integral_literal -> ^(I_REGISTERS[$REGISTERS_DIRECTIVE, "I_REGISTERS"] $regCount)
560    | directive=LOCALS_DIRECTIVE regCount2=integral_literal -> ^(I_LOCALS[$LOCALS_DIRECTIVE, "I_LOCALS"] $regCount2)
561    )
562    {
563      if ($statements_and_directives::hasRegistersDirective) {
564        throw new SemanticException(input, $directive, "There can only be a single .registers or .locals directive in a method");
565      }
566      $statements_and_directives::hasRegistersDirective=true;
567    };
568
569/*identifiers are much more general than most languages. Any of the below can either be
570the indicated type OR an identifier, depending on the context*/
571simple_name
572  : SIMPLE_NAME
573  | ACCESS_SPEC -> SIMPLE_NAME[$ACCESS_SPEC]
574  | VERIFICATION_ERROR_TYPE -> SIMPLE_NAME[$VERIFICATION_ERROR_TYPE]
575  | POSITIVE_INTEGER_LITERAL -> SIMPLE_NAME[$POSITIVE_INTEGER_LITERAL]
576  | NEGATIVE_INTEGER_LITERAL -> SIMPLE_NAME[$NEGATIVE_INTEGER_LITERAL]
577  | FLOAT_LITERAL_OR_ID -> SIMPLE_NAME[$FLOAT_LITERAL_OR_ID]
578  | DOUBLE_LITERAL_OR_ID -> SIMPLE_NAME[$DOUBLE_LITERAL_OR_ID]
579  | BOOL_LITERAL -> SIMPLE_NAME[$BOOL_LITERAL]
580  | NULL_LITERAL -> SIMPLE_NAME[$NULL_LITERAL]
581  | REGISTER -> SIMPLE_NAME[$REGISTER]
582  | PARAM_LIST_OR_ID -> SIMPLE_NAME[$PARAM_LIST_OR_ID]
583  | PRIMITIVE_TYPE -> SIMPLE_NAME[$PRIMITIVE_TYPE]
584  | VOID_TYPE -> SIMPLE_NAME[$VOID_TYPE]
585  | ANNOTATION_VISIBILITY -> SIMPLE_NAME[$ANNOTATION_VISIBILITY]
586  | INSTRUCTION_FORMAT10t -> SIMPLE_NAME[$INSTRUCTION_FORMAT10t]
587  | INSTRUCTION_FORMAT10x -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x]
588  | INSTRUCTION_FORMAT10x_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x_ODEX]
589  | INSTRUCTION_FORMAT11x -> SIMPLE_NAME[$INSTRUCTION_FORMAT11x]
590  | INSTRUCTION_FORMAT12x_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT12x_OR_ID]
591  | INSTRUCTION_FORMAT21c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD]
592  | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX]
593  | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING]
594  | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE]
595  | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t]
596  | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD]
597  | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX]
598  | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE]
599  | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD]
600  | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID]
601  | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t]
602  | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x]
603  | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID]
604  | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t]
605  | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
606  | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX]
607  | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
608  | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD]
609  | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD]
610  | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l];
611
612method_name
613  : simple_name
614  | METHOD_NAME -> SIMPLE_NAME[$METHOD_NAME];
615
616method_prototype
617  : OPEN_PAREN param_list CLOSE_PAREN type_descriptor
618    -> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) param_list?);
619
620param_list
621  : PARAM_LIST -> { parseParamList((CommonToken)$PARAM_LIST) }
622  | PARAM_LIST_OR_ID -> { parseParamList((CommonToken)$PARAM_LIST_OR_ID) }
623  | nonvoid_type_descriptor*;
624
625type_descriptor
626  : VOID_TYPE
627  | PRIMITIVE_TYPE
628  | CLASS_DESCRIPTOR
629  | ARRAY_DESCRIPTOR;
630
631nonvoid_type_descriptor
632  : PRIMITIVE_TYPE
633  | CLASS_DESCRIPTOR
634  | ARRAY_DESCRIPTOR;
635
636reference_type_descriptor
637  : CLASS_DESCRIPTOR
638  | ARRAY_DESCRIPTOR;
639
640integer_literal
641  : POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL]
642  | NEGATIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$NEGATIVE_INTEGER_LITERAL];
643
644float_literal
645  : FLOAT_LITERAL_OR_ID -> FLOAT_LITERAL[$FLOAT_LITERAL_OR_ID]
646  | FLOAT_LITERAL;
647
648double_literal
649  : DOUBLE_LITERAL_OR_ID -> DOUBLE_LITERAL[$DOUBLE_LITERAL_OR_ID]
650  | DOUBLE_LITERAL;
651
652literal
653  : LONG_LITERAL
654  | integer_literal
655  | SHORT_LITERAL
656  | BYTE_LITERAL
657  | float_literal
658  | double_literal
659  | CHAR_LITERAL
660  | STRING_LITERAL
661  | BOOL_LITERAL
662  | NULL_LITERAL
663  | array_literal
664  | subannotation
665  | type_field_method_literal
666  | enum_literal;
667
668integral_literal
669  : LONG_LITERAL
670  | integer_literal
671  | SHORT_LITERAL
672  | CHAR_LITERAL
673  | BYTE_LITERAL;
674
675fixed_32bit_literal
676  : LONG_LITERAL
677  | integer_literal
678  | SHORT_LITERAL
679  | BYTE_LITERAL
680  | float_literal
681  | CHAR_LITERAL
682  | BOOL_LITERAL;
683
684fixed_literal returns[int size]
685  : integer_literal {$size = 4;}
686  | LONG_LITERAL {$size = 8;}
687  | SHORT_LITERAL {$size = 2;}
688  | BYTE_LITERAL {$size = 1;}
689  | float_literal {$size = 4;}
690  | double_literal {$size = 8;}
691  | CHAR_LITERAL {$size = 2;}
692  | BOOL_LITERAL {$size = 1;};
693
694array_literal
695  : OPEN_BRACE (literal (COMMA literal)* | ) CLOSE_BRACE
696    -> ^(I_ENCODED_ARRAY[$start, "I_ENCODED_ARRAY"] literal*);
697
698annotation_element
699  : simple_name EQUAL literal
700    -> ^(I_ANNOTATION_ELEMENT[$start, "I_ANNOTATION_ELEMENT"] simple_name literal);
701
702annotation
703  : ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY CLASS_DESCRIPTOR
704    annotation_element* END_ANNOTATION_DIRECTIVE
705    -> ^(I_ANNOTATION[$start, "I_ANNOTATION"] ANNOTATION_VISIBILITY ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*));
706
707subannotation
708  : SUBANNOTATION_DIRECTIVE CLASS_DESCRIPTOR annotation_element* END_SUBANNOTATION_DIRECTIVE
709    -> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*);
710
711enum_literal
712  : ENUM_DIRECTIVE reference_type_descriptor ARROW simple_name COLON reference_type_descriptor
713  -> ^(I_ENCODED_ENUM reference_type_descriptor simple_name reference_type_descriptor);
714
715type_field_method_literal
716  : reference_type_descriptor
717    ( ARROW
718      ( simple_name COLON nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor simple_name nonvoid_type_descriptor)
719      | method_name method_prototype -> ^(I_ENCODED_METHOD reference_type_descriptor method_name method_prototype)
720      )
721    | -> reference_type_descriptor
722    )
723  | PRIMITIVE_TYPE
724  | VOID_TYPE;
725
726fully_qualified_method
727  : reference_type_descriptor ARROW method_name method_prototype
728  -> reference_type_descriptor method_name method_prototype;
729
730fully_qualified_field
731  : reference_type_descriptor ARROW simple_name COLON nonvoid_type_descriptor
732  -> reference_type_descriptor simple_name nonvoid_type_descriptor;
733
734label
735  : COLON simple_name -> ^(I_LABEL[$COLON, "I_LABEL"] simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
736
737label_ref_or_offset
738  : COLON simple_name -> simple_name
739  | OFFSET
740  | NEGATIVE_INTEGER_LITERAL -> OFFSET[$NEGATIVE_INTEGER_LITERAL];
741
742register_list
743  : REGISTER (COMMA REGISTER)* -> ^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"] REGISTER*)
744  | ->^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"]);
745
746register_range
747  : (startreg=REGISTER (DOTDOT endreg=REGISTER)?)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] $startreg? $endreg?);
748
749verification_error_reference
750  : CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method;
751
752catch_directive
753  : CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset
754    -> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using);
755
756catchall_directive
757  : CATCHALL_DIRECTIVE OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset
758    -> ^(I_CATCHALL[$start, "I_CATCHALL"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] $from $to $using);
759
760/*When there are annotations immediately after a parameter definition, we don't know whether they are parameter annotations
761or method annotations until we determine if there is an .end parameter directive. In either case, we still "consume" and parse
762the annotations. If it turns out that they are parameter annotations, we include them in the I_PARAMETER AST. Otherwise, we
763add them to the $statements_and_directives::methodAnnotations list*/
764parameter_directive
765  @init {List<CommonTree> annotations = new ArrayList<CommonTree>();}
766  : PARAMETER_DIRECTIVE
767    STRING_LITERAL?
768    ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})*
769
770    ( END_PARAMETER_DIRECTIVE
771      -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS annotation*))
772    | /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);}
773      -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS))
774    );
775
776ordered_debug_directive
777  : line_directive
778  | local_directive
779  | end_local_directive
780  | restart_local_directive
781  | prologue_directive
782  | epilogue_directive
783  | source_directive;
784
785line_directive
786  : LINE_DIRECTIVE integral_literal
787    -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
788
789local_directive
790  : LOCAL_DIRECTIVE REGISTER COMMA simple_name COLON nonvoid_type_descriptor (COMMA STRING_LITERAL)?
791    -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER simple_name nonvoid_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
792
793end_local_directive
794  : END_LOCAL_DIRECTIVE REGISTER
795    -> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
796
797restart_local_directive
798  : RESTART_LOCAL_DIRECTIVE REGISTER
799    -> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
800
801prologue_directive
802  : PROLOGUE_DIRECTIVE
803    -> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
804
805epilogue_directive
806  : EPILOGUE_DIRECTIVE
807    -> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
808
809source_directive
810  : SOURCE_DIRECTIVE STRING_LITERAL
811    -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
812
813instruction_format12x
814  : INSTRUCTION_FORMAT12x
815  | INSTRUCTION_FORMAT12x_OR_ID -> INSTRUCTION_FORMAT12x[$INSTRUCTION_FORMAT12x_OR_ID];
816
817instruction_format22s
818  : INSTRUCTION_FORMAT22s
819  | INSTRUCTION_FORMAT22s_OR_ID -> INSTRUCTION_FORMAT22s[$INSTRUCTION_FORMAT22s_OR_ID];
820
821instruction_format31i
822  : INSTRUCTION_FORMAT31i
823  | INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID];
824
825
826
827instruction returns [int size]
828  : insn_format10t { $size = $insn_format10t.size; }
829  | insn_format10x { $size = $insn_format10x.size; }
830  | insn_format10x_odex { $size = $insn_format10x_odex.size; }
831  | insn_format11n { $size = $insn_format11n.size; }
832  | insn_format11x { $size = $insn_format11x.size; }
833  | insn_format12x { $size = $insn_format12x.size; }
834  | insn_format20bc { $size = $insn_format20bc.size; }
835  | insn_format20t { $size = $insn_format20t.size; }
836  | insn_format21c_field { $size = $insn_format21c_field.size; }
837  | insn_format21c_field_odex { $size = $insn_format21c_field_odex.size; }
838  | insn_format21c_string { $size = $insn_format21c_string.size; }
839  | insn_format21c_type { $size = $insn_format21c_type.size; }
840  | insn_format21h { $size = $insn_format21h.size; }
841  | insn_format21s { $size = $insn_format21s.size; }
842  | insn_format21t { $size = $insn_format21t.size; }
843  | insn_format22b { $size = $insn_format22b.size; }
844  | insn_format22c_field { $size = $insn_format22c_field.size; }
845  | insn_format22c_field_odex { $size = $insn_format22c_field_odex.size; }
846  | insn_format22c_type { $size = $insn_format22c_type.size; }
847  | insn_format22cs_field { $size = $insn_format22cs_field.size; }
848  | insn_format22s { $size = $insn_format22s.size; }
849  | insn_format22t { $size = $insn_format22t.size; }
850  | insn_format22x { $size = $insn_format22x.size; }
851  | insn_format23x { $size = $insn_format23x.size; }
852  | insn_format30t { $size = $insn_format30t.size; }
853  | insn_format31c { $size = $insn_format31c.size; }
854  | insn_format31i { $size = $insn_format31i.size; }
855  | insn_format31t { $size = $insn_format31t.size; }
856  | insn_format32x { $size = $insn_format32x.size; }
857  | insn_format35c_method { $size = $insn_format35c_method.size; }
858  | insn_format35c_type { $size = $insn_format35c_type.size; }
859  | insn_format35c_method_odex { $size = $insn_format35c_method_odex.size; }
860  | insn_format35mi_method { $size = $insn_format35mi_method.size; }
861  | insn_format35ms_method { $size = $insn_format35ms_method.size; }
862  | insn_format3rc_method { $size = $insn_format3rc_method.size; }
863  | insn_format3rc_method_odex { $size = $insn_format3rc_method_odex.size; }
864  | insn_format3rc_type { $size = $insn_format3rc_type.size; }
865  | insn_format3rmi_method { $size = $insn_format3rmi_method.size; }
866  | insn_format3rms_method { $size = $insn_format3rms_method.size; }
867  | insn_format41c_type { $size = $insn_format41c_type.size; }
868  | insn_format41c_field { $size = $insn_format41c_field.size; }
869  | insn_format41c_field_odex { $size = $insn_format41c_field_odex.size; }
870  | insn_format51l { $size = $insn_format51l.size; }
871  | insn_format52c_type { $size = $insn_format52c_type.size; }
872  |  insn_format52c_field { $size = $insn_format52c_field.size; }
873  |  insn_format52c_field_odex { $size = $insn_format52c_field_odex.size; }
874  |  insn_format5rc_method { $size = $insn_format5rc_method.size; }
875  |  insn_format5rc_method_odex { $size = $insn_format5rc_method_odex.size; }
876  |  insn_format5rc_type { $size = $insn_format5rc_type.size; }
877  | insn_array_data_directive { $size = $insn_array_data_directive.size; }
878  | insn_packed_switch_directive { $size = $insn_packed_switch_directive.size; }
879  | insn_sparse_switch_directive { $size = $insn_sparse_switch_directive.size; };
880
881insn_format10t returns [int size]
882  : //e.g. goto endloop:
883    //e.g. goto +3
884    INSTRUCTION_FORMAT10t label_ref_or_offset {$size = Format.Format10t.size;}
885    -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t label_ref_or_offset);
886
887insn_format10x returns [int size]
888  : //e.g. return-void
889    INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;}
890    -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x);
891
892insn_format10x_odex returns [int size]
893  : //e.g. return-void-barrier
894    INSTRUCTION_FORMAT10x_ODEX {$size = Format.Format10x.size;}
895    {
896      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT10x_ODEX.text);
897    };
898
899insn_format11n returns [int size]
900  : //e.g. const/4 v0, 5
901    INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal {$size = Format.Format11n.size;}
902    -> ^(I_STATEMENT_FORMAT11n[$start, "I_STATEMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal);
903
904insn_format11x returns [int size]
905  : //e.g. move-result-object v1
906    INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;}
907    -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER);
908
909insn_format12x returns [int size]
910  : //e.g. move v1 v2
911    instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;}
912    -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER);
913
914insn_format20bc returns [int size]
915  : //e.g. throw-verification-error generic-error, Lsome/class;
916    INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;}
917    {
918      if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) {
919        throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text);
920      }
921    }
922    -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference);
923    //TODO: check if dalvik has a jumbo version of throw-verification-error
924
925insn_format20t returns [int size]
926  : //e.g. goto/16 endloop:
927    INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;}
928    -> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset);
929
930insn_format21c_field returns [int size]
931  : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream;
932    INSTRUCTION_FORMAT21c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;}
933    -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field);
934
935insn_format21c_field_odex returns [int size]
936  : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream;
937    INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;}
938    {
939      if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) {
940        throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text);
941      }
942    }
943    -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER fully_qualified_field);
944
945insn_format21c_string returns [int size]
946  : //e.g. const-string v1, "Hello World!"
947    INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;}
948    -> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL);
949
950insn_format21c_type returns [int size]
951  : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2;
952    INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;}
953    -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor);
954
955insn_format21h returns [int size]
956  : //e.g. const/high16 v1, 1234
957    INSTRUCTION_FORMAT21h REGISTER COMMA integral_literal {$size = Format.Format21h.size;}
958    -> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal);
959
960insn_format21s returns [int size]
961  : //e.g. const/16 v1, 1234
962    INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal {$size = Format.Format21s.size;}
963    -> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal);
964
965insn_format21t returns [int size]
966  : //e.g. if-eqz v0, endloop:
967    INSTRUCTION_FORMAT21t REGISTER COMMA (label_ref_or_offset) {$size = Format.Format21t.size;}
968    -> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER label_ref_or_offset);
969
970insn_format22b returns [int size]
971  : //e.g. add-int v0, v1, 123
972    INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22b.size;}
973    -> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal);
974
975insn_format22c_field returns [int size]
976  : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
977    INSTRUCTION_FORMAT22c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;}
978    -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field);
979
980insn_format22c_field_odex returns [int size]
981  : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
982    INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;}
983    {
984      if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) {
985        throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text);
986      }
987    }
988    -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER REGISTER fully_qualified_field);
989
990insn_format22c_type returns [int size]
991  : //e.g. instance-of v0, v1, Ljava/lang/String;
992    INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format22c.size;}
993    -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
994
995insn_format22cs_field returns [int size]
996  : //e.g. iget-quick v0, v1, field@0xc
997    INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET
998    {
999      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22cs_FIELD.text);
1000    };
1001
1002insn_format22s returns [int size]
1003  : //e.g. add-int/lit16 v0, v1, 12345
1004    instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22s.size;}
1005    -> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] instruction_format22s REGISTER REGISTER integral_literal);
1006
1007insn_format22t returns [int size]
1008  : //e.g. if-eq v0, v1, endloop:
1009    INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref_or_offset {$size = Format.Format22t.size;}
1010    -> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER label_ref_or_offset);
1011
1012insn_format22x returns [int size]
1013  : //e.g. move/from16 v1, v1234
1014    INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER {$size = Format.Format22x.size;}
1015    -> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER);
1016
1017insn_format23x returns [int size]
1018  : //e.g. add-int v1, v2, v3
1019    INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER {$size = Format.Format23x.size;}
1020    -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER);
1021
1022insn_format30t returns [int size]
1023  : //e.g. goto/32 endloop:
1024    INSTRUCTION_FORMAT30t label_ref_or_offset {$size = Format.Format30t.size;}
1025    -> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t label_ref_or_offset);
1026
1027insn_format31c returns [int size]
1028  : //e.g. const-string/jumbo v1 "Hello World!"
1029    INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL {$size = Format.Format31c.size;}
1030    ->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL);
1031
1032insn_format31i returns [int size]
1033  : //e.g. const v0, 123456
1034    instruction_format31i REGISTER COMMA fixed_32bit_literal {$size = Format.Format31i.size;}
1035    -> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] instruction_format31i REGISTER fixed_32bit_literal);
1036
1037insn_format31t returns [int size]
1038  : //e.g. fill-array-data v0, ArrayData:
1039    INSTRUCTION_FORMAT31t REGISTER COMMA label_ref_or_offset {$size = Format.Format31t.size;}
1040    {
1041      if ($INSTRUCTION_FORMAT31t.text.equals("packed-switch")) {
1042        CommonTree root = new CommonTree(new CommonToken(I_PACKED_SWITCH_DECLARATION, "I_PACKED_SWITCH_DECLARATION"));
1043        CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress)));
1044        root.addChild(address);
1045        root.addChild($label_ref_or_offset.tree.dupNode());
1046        $statements_and_directives::packedSwitchDeclarations.add(root);
1047      } else if ($INSTRUCTION_FORMAT31t.text.equals("sparse-switch")) {
1048        CommonTree root = new CommonTree(new CommonToken(I_SPARSE_SWITCH_DECLARATION, "I_SPARSE_SWITCH_DECLARATION"));
1049        CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress)));
1050        root.addChild(address);
1051        root.addChild($label_ref_or_offset.tree.dupNode());
1052        $statements_and_directives::sparseSwitchDeclarations.add(root);
1053      }
1054    }
1055    -> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER label_ref_or_offset);
1056
1057insn_format32x returns [int size]
1058  : //e.g. move/16 v4567, v1234
1059    INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER {$size = Format.Format32x.size;}
1060    -> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER);
1061
1062insn_format35c_method returns [int size]
1063  : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
1064    INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format35c.size;}
1065    -> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method);
1066
1067insn_format35c_type returns [int size]
1068  : //e.g. filled-new-array {v0,v1}, I
1069    INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format35c.size;}
1070    -> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor);
1071
1072insn_format35c_method_odex returns [int size]
1073  : //e.g. invoke-direct {p0}, Ljava/lang/Object;-><init>()V
1074    INSTRUCTION_FORMAT35c_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method
1075    {
1076      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35c_METHOD_ODEX.text);
1077    };
1078
1079insn_format35mi_method returns [int size]
1080  : //e.g. execute-inline {v0, v1}, inline@0x4
1081    INSTRUCTION_FORMAT35mi_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA INLINE_INDEX
1082    {
1083      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35mi_METHOD.text);
1084    };
1085
1086insn_format35ms_method returns [int size]
1087  : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4
1088    INSTRUCTION_FORMAT35ms_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA VTABLE_INDEX
1089    {
1090      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35ms_METHOD.text);
1091    };
1092
1093insn_format3rc_method returns [int size]
1094  : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1095    INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format3rc.size;}
1096    -> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method);
1097
1098insn_format3rc_method_odex returns [int size]
1099  : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;-><init>()V
1100    INSTRUCTION_FORMAT3rc_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method
1101    {
1102      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rc_METHOD_ODEX.text);
1103    };
1104
1105insn_format3rc_type returns [int size]
1106  : //e.g. filled-new-array/range {v0..v6}, I
1107    INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format3rc.size;}
1108    -> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor);
1109
1110insn_format3rmi_method returns [int size]
1111  : //e.g. execute-inline/range {v0 .. v10}, inline@0x14
1112    INSTRUCTION_FORMAT3rmi_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA INLINE_INDEX
1113    {
1114      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rmi_METHOD.text);
1115    };
1116
1117insn_format3rms_method returns [int size]
1118  : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14
1119    INSTRUCTION_FORMAT3rms_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA VTABLE_INDEX
1120    {
1121      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text);
1122    };
1123
1124insn_format41c_type returns [int size]
1125  : //e.g. const-class/jumbo v2, Lorg/jf/HelloWorld2/HelloWorld2;
1126    INSTRUCTION_FORMAT41c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format41c.size;}
1127    -> ^(I_STATEMENT_FORMAT41c_TYPE[$start, "I_STATEMENT_FORMAT41c"] INSTRUCTION_FORMAT41c_TYPE REGISTER reference_type_descriptor);
1128
1129insn_format41c_field returns [int size]
1130  : //e.g. sget-object/jumbo v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
1131    INSTRUCTION_FORMAT41c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format41c.size;}
1132    -> ^(I_STATEMENT_FORMAT41c_FIELD[$start, "I_STATEMENT_FORMAT41c_FIELD"] INSTRUCTION_FORMAT41c_FIELD REGISTER fully_qualified_field);
1133
1134insn_format41c_field_odex returns [int size]
1135  : //e.g. sget-object-volatile/jumbo v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
1136    INSTRUCTION_FORMAT41c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format41c.size;}
1137    {
1138      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT41c_FIELD_ODEX.text);
1139    };
1140
1141insn_format51l returns [int size]
1142  : //e.g. const-wide v0, 5000000000L
1143    INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;}
1144    -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal);
1145
1146insn_format52c_type returns [int size]
1147  : //e.g. instance-of/jumbo v0, v1, Ljava/lang/String;
1148    INSTRUCTION_FORMAT52c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format52c.size;}
1149    -> ^(I_STATEMENT_FORMAT52c_TYPE[$start, "I_STATEMENT_FORMAT52c_TYPE"] INSTRUCTION_FORMAT52c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
1150
1151insn_format52c_field returns [int size]
1152  : //e.g. iput-object/jumbo v1, v0 Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String;
1153    INSTRUCTION_FORMAT52c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format52c.size;}
1154    -> ^(I_STATEMENT_FORMAT52c_FIELD[$start, "I_STATEMENT_FORMAT52c_FIELD"] INSTRUCTION_FORMAT52c_FIELD REGISTER REGISTER fully_qualified_field);
1155
1156insn_format52c_field_odex returns [int size]
1157  : //e.g. iput-object-volatile/jumbo v1, v0 Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String;
1158    INSTRUCTION_FORMAT52c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format52c.size;}
1159    {
1160      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT52c_FIELD_ODEX.text);
1161    };
1162
1163insn_format5rc_method returns [int size]
1164  : //e.g. invoke-virtual/jumbo {v25..v26}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1165    INSTRUCTION_FORMAT5rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;}
1166    -> ^(I_STATEMENT_FORMAT5rc_METHOD[$start, "I_STATEMENT_FORMAT5rc_METHOD"] INSTRUCTION_FORMAT5rc_METHOD register_range fully_qualified_method);
1167
1168insn_format5rc_method_odex returns [int size]
1169  : //e.g. invoke-object-init/jumbo {v25}, Ljava/lang/Object-><init>()V
1170    INSTRUCTION_FORMAT5rc_METHOD_ODEX OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;}
1171    {
1172      throwOdexedInstructionException(input, $INSTRUCTION_FORMAT5rc_METHOD_ODEX.text);
1173    };
1174
1175insn_format5rc_type returns [int size]
1176  : //e.g. filled-new-array/jumbo {v0..v6}, I
1177    INSTRUCTION_FORMAT5rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format5rc.size;}
1178    -> ^(I_STATEMENT_FORMAT5rc_TYPE[$start, "I_STATEMENT_FORMAT5rc_TYPE"] INSTRUCTION_FORMAT5rc_TYPE register_range nonvoid_type_descriptor);
1179
1180insn_array_data_directive returns [int size]
1181    @init {boolean needsNop = false;}
1182  :   ARRAY_DATA_DIRECTIVE
1183    {
1184      if (($method::currentAddress \% 2) != 0) {
1185        needsNop = true;
1186        $size = 2;
1187      } else {
1188        $size = 0;
1189      }
1190    }
1191
1192    integral_literal (fixed_literal {$size+=$fixed_literal.size;})* END_ARRAY_DATA_DIRECTIVE
1193    {$size = (($size + 1)/2)*2 + 8;}
1194
1195    /*add a nop statement before this if needed to force the correct alignment*/
1196    -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start,  "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
1197       ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*))
1198
1199    -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal)
1200       ^(I_ARRAY_ELEMENTS fixed_literal*));
1201
1202insn_packed_switch_directive returns [int size]
1203    @init {boolean needsNop = false; int targetCount = 0;}
1204    :   PACKED_SWITCH_DIRECTIVE
1205    {
1206      targetCount = 0;
1207      if (($method::currentAddress \% 2) != 0) {
1208        needsNop = true;
1209        $size = 2;
1210      } else {
1211        $size = 0;
1212      }
1213    }
1214
1215    fixed_32bit_literal
1216
1217    (switch_target += label_ref_or_offset {$size+=4; targetCount++;})*
1218
1219    END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;}
1220
1221    /*add a nop statement before this if needed to force the correct alignment*/
1222    -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start,  "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
1223         ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
1224         ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
1225         ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"]
1226           I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
1227       )
1228
1229    -> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
1230         ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
1231         ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"]
1232           I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
1233       );
1234
1235insn_sparse_switch_directive returns [int size]
1236    @init {boolean needsNop = false; int targetCount = 0;}
1237  :   SPARSE_SWITCH_DIRECTIVE
1238    {
1239      targetCount = 0;
1240      if (($method::currentAddress \% 2) != 0) {
1241        needsNop = true;
1242        $size = 2;
1243      } else {
1244        $size = 0;
1245      }
1246    }
1247
1248    (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8; targetCount++;})*
1249
1250    END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;}
1251
1252    /*add a nop statement before this if needed to force the correct alignment*/
1253    -> {needsNop}?
1254       ^(I_STATEMENT_FORMAT10x[$start,  "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
1255       ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
1256         I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
1257         ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
1258         ^(I_SPARSE_SWITCH_TARGETS $switch_target*)
1259       )
1260
1261    -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
1262       I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
1263       ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
1264       ^(I_SPARSE_SWITCH_TARGETS $switch_target*));