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