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