1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2010 Ben Gruver
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29tree grammar smaliTreeWalker;
30
31options {
32  tokenVocab=smaliParser;
33  ASTLabelType=CommonTree;
34}
35
36@header {
37package org.jf.smali;
38
39import com.google.common.collect.ImmutableSet;
40import com.google.common.collect.Iterables;
41import com.google.common.collect.Lists;
42import com.google.common.collect.Maps;
43import org.antlr.runtime.BitSet;
44import org.antlr.runtime.*;
45import org.antlr.runtime.tree.CommonTree;
46import org.antlr.runtime.tree.TreeNodeStream;
47import org.antlr.runtime.tree.TreeParser;
48import org.antlr.runtime.tree.TreeRuleReturnScope;
49import org.jf.dexlib2.*;
50import org.jf.dexlib2.builder.Label;
51import org.jf.dexlib2.builder.MethodImplementationBuilder;
52import org.jf.dexlib2.builder.SwitchLabelElement;
53import org.jf.dexlib2.builder.instruction.*;
54import org.jf.dexlib2.iface.Annotation;
55import org.jf.dexlib2.iface.AnnotationElement;
56import org.jf.dexlib2.iface.ClassDef;
57import org.jf.dexlib2.iface.MethodImplementation;
58import org.jf.dexlib2.iface.reference.FieldReference;
59import org.jf.dexlib2.iface.reference.MethodReference;
60import org.jf.dexlib2.iface.value.EncodedValue;
61import org.jf.dexlib2.immutable.ImmutableAnnotation;
62import org.jf.dexlib2.immutable.ImmutableAnnotationElement;
63import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
64import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
65import org.jf.dexlib2.immutable.reference.ImmutableReference;
66import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
67import org.jf.dexlib2.immutable.value.*;
68import org.jf.dexlib2.util.MethodUtil;
69import org.jf.dexlib2.writer.InstructionFactory;
70import org.jf.dexlib2.writer.builder.*;
71import org.jf.util.LinearSearch;
72
73import java.util.*;
74}
75
76@members {
77  public String classType;
78  private boolean verboseErrors = false;
79  private int apiLevel = 15;
80  private Opcodes opcodes = new Opcodes(apiLevel);
81  private DexBuilder dexBuilder;
82
83  public void setDexBuilder(DexBuilder dexBuilder) {
84      this.dexBuilder = dexBuilder;
85  }
86
87  public void setApiLevel(int apiLevel) {
88      this.opcodes = new Opcodes(apiLevel);
89      this.apiLevel = apiLevel;
90  }
91
92  public void setVerboseErrors(boolean verboseErrors) {
93    this.verboseErrors = verboseErrors;
94  }
95
96  private byte parseRegister_nibble(String register)
97      throws SemanticException {
98    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
99    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
100
101    //register should be in the format "v12"
102    int val = Byte.parseByte(register.substring(1));
103    if (register.charAt(0) == 'p') {
104      val = totalMethodRegisters - methodParameterRegisters + val;
105    }
106    if (val >= 2<<4) {
107      throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15");
108    }
109    //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0;
110    return (byte)val;
111  }
112
113  //return a short, because java's byte is signed
114  private short parseRegister_byte(String register)
115      throws SemanticException {
116    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
117    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
118    //register should be in the format "v123"
119    int val = Short.parseShort(register.substring(1));
120    if (register.charAt(0) == 'p') {
121      val = totalMethodRegisters - methodParameterRegisters + val;
122    }
123    if (val >= 2<<8) {
124      throw new SemanticException(input, "The maximum allowed register in this context is v255");
125    }
126    return (short)val;
127  }
128
129  //return an int because java's short is signed
130  private int parseRegister_short(String register)
131      throws SemanticException {
132    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
133    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
134    //register should be in the format "v12345"
135    int val = Integer.parseInt(register.substring(1));
136    if (register.charAt(0) == 'p') {
137      val = totalMethodRegisters - methodParameterRegisters + val;
138    }
139    if (val >= 2<<16) {
140      throw new SemanticException(input, "The maximum allowed register in this context is v65535");
141    }
142    //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
143    return val;
144  }
145
146  public String getErrorMessage(RecognitionException e, String[] tokenNames) {
147    if ( e instanceof SemanticException ) {
148      return e.getMessage();
149    } else {
150      return super.getErrorMessage(e, tokenNames);
151    }
152  }
153
154  public String getErrorHeader(RecognitionException e) {
155    return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
156  }
157}
158
159smali_file returns[ClassDef classDef]
160  : ^(I_CLASS_DEF header methods fields annotations)
161  {
162    $classDef = dexBuilder.internClassDef($header.classType, $header.accessFlags, $header.superType,
163            $header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods);
164  };
165  catch [Exception ex] {
166    if (verboseErrors) {
167      ex.printStackTrace(System.err);
168    }
169    reportError(new SemanticException(input, ex));
170  }
171
172
173header returns[String classType, int accessFlags, String superType, List<String> implementsList, String sourceSpec]
174: class_spec super_spec? implements_list source_spec
175  {
176    classType = $class_spec.type;
177    $classType = classType;
178    $accessFlags = $class_spec.accessFlags;
179    $superType = $super_spec.type;
180    $implementsList = $implements_list.implementsList;
181    $sourceSpec = $source_spec.source;
182  };
183
184
185class_spec returns[String type, int accessFlags]
186  : CLASS_DESCRIPTOR access_list
187  {
188    $type = $CLASS_DESCRIPTOR.text;
189    $accessFlags = $access_list.value;
190  };
191
192super_spec returns[String type]
193  : ^(I_SUPER CLASS_DESCRIPTOR)
194  {
195    $type = $CLASS_DESCRIPTOR.text;
196  };
197
198
199implements_spec returns[String type]
200  : ^(I_IMPLEMENTS CLASS_DESCRIPTOR)
201  {
202    $type = $CLASS_DESCRIPTOR.text;
203  };
204
205implements_list returns[List<String> implementsList]
206@init { List<String> typeList; }
207  : {typeList = Lists.newArrayList();}
208    (implements_spec {typeList.add($implements_spec.type);} )*
209  {
210    if (typeList.size() > 0) {
211      $implementsList = typeList;
212    } else {
213      $implementsList = null;
214    }
215  };
216
217source_spec returns[String source]
218  : {$source = null;}
219    ^(I_SOURCE string_literal {$source = $string_literal.value;})
220  | /*epsilon*/;
221
222access_list returns [int value]
223  @init
224  {
225    $value = 0;
226  }
227  : ^(I_ACCESS_LIST
228      (
229        ACCESS_SPEC
230        {
231          $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue();
232        }
233      )*);
234
235
236fields returns[List<BuilderField> fields]
237  @init {$fields = Lists.newArrayList();}
238  : ^(I_FIELDS
239      (field
240      {
241        $fields.add($field.field);
242      })*);
243
244methods returns[List<BuilderMethod> methods]
245  @init {$methods = Lists.newArrayList();}
246  : ^(I_METHODS
247      (method
248      {
249        $methods.add($method.ret);
250      })*);
251
252field returns [BuilderField field]
253  :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
254  {
255    int accessFlags = $access_list.value;
256
257
258    if (!AccessFlags.STATIC.isSet(accessFlags) && $field_initial_value.encodedValue != null) {
259        throw new SemanticException(input, "Initial field values can only be specified for static fields.");
260    }
261
262    $field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value,
263            $field_initial_value.encodedValue, $annotations.annotations);
264  };
265
266
267field_initial_value returns[EncodedValue encodedValue]
268  : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;}
269  | /*epsilon*/;
270
271literal returns[EncodedValue encodedValue]
272  : integer_literal { $encodedValue = new ImmutableIntEncodedValue($integer_literal.value); }
273  | long_literal { $encodedValue = new ImmutableLongEncodedValue($long_literal.value); }
274  | short_literal { $encodedValue = new ImmutableShortEncodedValue($short_literal.value); }
275  | byte_literal { $encodedValue = new ImmutableByteEncodedValue($byte_literal.value); }
276  | float_literal { $encodedValue = new ImmutableFloatEncodedValue($float_literal.value); }
277  | double_literal { $encodedValue = new ImmutableDoubleEncodedValue($double_literal.value); }
278  | char_literal { $encodedValue = new ImmutableCharEncodedValue($char_literal.value); }
279  | string_literal { $encodedValue = new ImmutableStringEncodedValue($string_literal.value); }
280  | bool_literal { $encodedValue = ImmutableBooleanEncodedValue.forBoolean($bool_literal.value); }
281  | NULL_LITERAL { $encodedValue = ImmutableNullEncodedValue.INSTANCE; }
282  | type_descriptor { $encodedValue = new ImmutableTypeEncodedValue($type_descriptor.type); }
283  | array_literal { $encodedValue = new ImmutableArrayEncodedValue($array_literal.elements); }
284  | subannotation { $encodedValue = new ImmutableAnnotationEncodedValue($subannotation.annotationType, $subannotation.elements); }
285  | field_literal { $encodedValue = new ImmutableFieldEncodedValue($field_literal.value); }
286  | method_literal { $encodedValue = new ImmutableMethodEncodedValue($method_literal.value); }
287  | enum_literal { $encodedValue = new ImmutableEnumEncodedValue($enum_literal.value); };
288
289//everything but string
290fixed_64bit_literal_number returns[Number value]
291  : integer_literal { $value = $integer_literal.value; }
292  | long_literal { $value = $long_literal.value; }
293  | short_literal { $value = $short_literal.value; }
294  | byte_literal { $value = $byte_literal.value; }
295  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
296  | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); }
297  | char_literal { $value = (int)$char_literal.value; }
298  | bool_literal { $value = $bool_literal.value?1:0; };
299
300fixed_64bit_literal returns[long value]
301  : integer_literal { $value = $integer_literal.value; }
302  | long_literal { $value = $long_literal.value; }
303  | short_literal { $value = $short_literal.value; }
304  | byte_literal { $value = $byte_literal.value; }
305  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
306  | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); }
307  | char_literal { $value = $char_literal.value; }
308  | bool_literal { $value = $bool_literal.value?1:0; };
309
310//everything but string and double
311//long is allowed, but it must fit into an int
312fixed_32bit_literal returns[int value]
313  : integer_literal { $value = $integer_literal.value; }
314  | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; }
315  | short_literal { $value = $short_literal.value; }
316  | byte_literal { $value = $byte_literal.value; }
317  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
318  | char_literal { $value = $char_literal.value; }
319  | bool_literal { $value = $bool_literal.value?1:0; };
320
321array_elements returns[List<Number> elements]
322  : {$elements = Lists.newArrayList();}
323    ^(I_ARRAY_ELEMENTS
324      (fixed_64bit_literal_number
325      {
326        $elements.add($fixed_64bit_literal_number.value);
327      })*);
328
329packed_switch_elements returns[List<Label> elements]
330  @init {$elements = Lists.newArrayList();}
331  :
332    ^(I_PACKED_SWITCH_ELEMENTS
333      (label_ref { $elements.add($label_ref.label); })*
334    );
335
336sparse_switch_elements returns[List<SwitchLabelElement> elements]
337  @init {$elements = Lists.newArrayList();}
338  :
339    ^(I_SPARSE_SWITCH_ELEMENTS
340       (fixed_32bit_literal label_ref
341       {
342         $elements.add(new SwitchLabelElement($fixed_32bit_literal.value, $label_ref.label));
343       })*
344    );
345
346method returns[BuilderMethod ret]
347  scope
348  {
349    boolean isStatic;
350    int totalMethodRegisters;
351    int methodParameterRegisters;
352    MethodImplementationBuilder methodBuilder;
353  }
354  @init
355  {
356    $method::totalMethodRegisters = 0;
357    $method::methodParameterRegisters = 0;
358    int accessFlags = 0;
359    $method::isStatic = false;
360  }
361  :
362    ^(I_METHOD
363      method_name_and_prototype
364      access_list
365      {
366        accessFlags = $access_list.value;
367        $method::isStatic = AccessFlags.STATIC.isSet(accessFlags);
368        $method::methodParameterRegisters =
369                MethodUtil.getParameterRegisterCount($method_name_and_prototype.parameters, $method::isStatic);
370      }
371      (
372        (registers_directive
373        {
374          if ($registers_directive.isLocalsDirective) {
375            $method::totalMethodRegisters = $registers_directive.registers + $method::methodParameterRegisters;
376          } else {
377            $method::totalMethodRegisters = $registers_directive.registers;
378          }
379
380          $method::methodBuilder = new MethodImplementationBuilder($method::totalMethodRegisters);
381
382        })
383        |
384        /* epsilon */
385        {
386          $method::methodBuilder = new MethodImplementationBuilder(0);
387        }
388      )
389      ordered_method_items
390      catches
391      parameters[$method_name_and_prototype.parameters]
392      annotations
393    )
394  {
395    MethodImplementation methodImplementation = null;
396    List<BuilderTryBlock> tryBlocks = $catches.tryBlocks;
397
398    boolean isAbstract = false;
399    boolean isNative = false;
400
401    if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) {
402      isAbstract = true;
403    } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) {
404      isNative = true;
405    }
406
407    methodImplementation = $method::methodBuilder.getMethodImplementation();
408
409    if (Iterables.isEmpty(methodImplementation.getInstructions())) {
410      if (!isAbstract && !isNative) {
411        throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction");
412      }
413
414      String methodType;
415      if (isAbstract) {
416        methodType = "an abstract";
417      } else {
418        methodType = "a native";
419      }
420
421      if ($registers_directive.start != null) {
422        if ($registers_directive.isLocalsDirective) {
423          throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType);
424        } else {
425          throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType);
426        }
427      }
428
429      if (methodImplementation.getTryBlocks().size() > 0) {
430        throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType);
431      }
432
433      if (!Iterables.isEmpty(methodImplementation.getDebugItems())) {
434        throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType);
435      }
436
437      methodImplementation = null;
438    } else {
439      if (isAbstract) {
440        throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions");
441      }
442      if (isNative) {
443        throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions");
444      }
445
446      if ($registers_directive.start == null) {
447        throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method");
448      }
449
450      if ($method::totalMethodRegisters < $method::methodParameterRegisters) {
451        throw new SemanticException(input, $registers_directive.start, "This method requires at least " +
452                Integer.toString($method::methodParameterRegisters) +
453                " registers, for the method parameters");
454      }
455    }
456
457    $ret = dexBuilder.internMethod(
458            classType,
459            $method_name_and_prototype.name,
460            $method_name_and_prototype.parameters,
461            $method_name_and_prototype.returnType,
462            accessFlags,
463            $annotations.annotations,
464            methodImplementation);
465  };
466
467method_prototype returns[List<String> parameters, String returnType]
468  : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) method_type_list)
469  {
470    $returnType = $type_descriptor.type;
471    $parameters = $method_type_list.types;
472  };
473
474method_name_and_prototype returns[String name, List<SmaliMethodParameter> parameters, String returnType]
475  : SIMPLE_NAME method_prototype
476  {
477    $name = $SIMPLE_NAME.text;
478    $parameters = Lists.newArrayList();
479
480    int paramRegister = 0;
481    for (String type: $method_prototype.parameters) {
482        $parameters.add(new SmaliMethodParameter(paramRegister++, type));
483        char c = type.charAt(0);
484        if (c == 'D' || c == 'J') {
485            paramRegister++;
486        }
487    }
488    $returnType = $method_prototype.returnType;
489  };
490
491method_type_list returns[List<String> types]
492  @init
493  {
494    $types = Lists.newArrayList();
495  }
496  : (
497      nonvoid_type_descriptor
498      {
499        $types.add($nonvoid_type_descriptor.type);
500      }
501    )*;
502
503
504method_reference returns[ImmutableMethodReference methodReference]
505  : reference_type_descriptor? SIMPLE_NAME method_prototype
506  {
507    String type;
508    if ($reference_type_descriptor.type == null) {
509        type = classType;
510    } else {
511        type = $reference_type_descriptor.type;
512    }
513    $methodReference = new ImmutableMethodReference(type, $SIMPLE_NAME.text,
514             $method_prototype.parameters, $method_prototype.returnType);
515  };
516
517field_reference returns[ImmutableFieldReference fieldReference]
518  : reference_type_descriptor? SIMPLE_NAME nonvoid_type_descriptor
519  {
520    String type;
521    if ($reference_type_descriptor.type == null) {
522        type = classType;
523    } else {
524        type = $reference_type_descriptor.type;
525    }
526    $fieldReference = new ImmutableFieldReference(type, $SIMPLE_NAME.text,
527            $nonvoid_type_descriptor.type);
528  };
529
530registers_directive returns[boolean isLocalsDirective, int registers]
531  : {$registers = 0;}
532    ^(( I_REGISTERS {$isLocalsDirective = false;}
533      | I_LOCALS {$isLocalsDirective = true;}
534      )
535      short_integral_literal {$registers = $short_integral_literal.value;}
536     );
537
538label_def
539  : ^(I_LABEL SIMPLE_NAME)
540  {
541    $method::methodBuilder.addLabel($SIMPLE_NAME.text);
542  };
543
544catches returns[List<BuilderTryBlock> tryBlocks]
545  @init {tryBlocks = Lists.newArrayList();}
546  : ^(I_CATCHES catch_directive* catchall_directive*);
547
548catch_directive
549  : ^(I_CATCH nonvoid_type_descriptor from=label_ref to=label_ref using=label_ref)
550  {
551    $method::methodBuilder.addCatch(dexBuilder.internTypeReference($nonvoid_type_descriptor.type),
552        $from.label, $to.label, $using.label);
553  };
554
555catchall_directive
556  : ^(I_CATCHALL from=label_ref to=label_ref using=label_ref)
557  {
558    $method::methodBuilder.addCatch($from.label, $to.label, $using.label);
559  };
560
561parameters[List<SmaliMethodParameter> parameters]
562  : ^(I_PARAMETERS (parameter[parameters])*);
563
564parameter[List<SmaliMethodParameter> parameters]
565  : ^(I_PARAMETER REGISTER string_literal? annotations)
566    {
567        final int registerNumber = parseRegister_short($REGISTER.text);
568        int totalMethodRegisters = $method::totalMethodRegisters;
569        int methodParameterRegisters = $method::methodParameterRegisters;
570
571        if (registerNumber >= totalMethodRegisters) {
572            throw new SemanticException(input, $I_PARAMETER, "Register \%s is larger than the maximum register v\%d " +
573                    "for this method", $REGISTER.text, totalMethodRegisters-1);
574        }
575        final int indexGuess = registerNumber - (totalMethodRegisters - methodParameterRegisters) - ($method::isStatic?0:1);
576
577        if (indexGuess < 0) {
578            throw new SemanticException(input, $I_PARAMETER, "Register \%s is not a parameter register.",
579                    $REGISTER.text);
580        }
581
582        int parameterIndex = LinearSearch.linearSearch(parameters, SmaliMethodParameter.COMPARATOR,
583            new WithRegister() { public int getRegister() { return indexGuess; } },
584                indexGuess);
585
586        if (parameterIndex < 0) {
587            throw new SemanticException(input, $I_PARAMETER, "Register \%s is the second half of a wide parameter.",
588                                $REGISTER.text);
589        }
590
591        SmaliMethodParameter methodParameter = parameters.get(parameterIndex);
592        methodParameter.name = $string_literal.value;
593        if ($annotations.annotations != null && $annotations.annotations.size() > 0) {
594            methodParameter.annotations = $annotations.annotations;
595        }
596    };
597
598debug_directive
599  : line
600  | local
601  | end_local
602  | restart_local
603  | prologue
604  | epilogue
605  | source;
606
607line
608  : ^(I_LINE integral_literal)
609    {
610        $method::methodBuilder.addLineNumber($integral_literal.value);
611    };
612
613local
614  : ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)?)
615    {
616      int registerNumber = parseRegister_short($REGISTER.text);
617      $method::methodBuilder.addStartLocal(registerNumber,
618              dexBuilder.internNullableStringReference($name.value),
619              dexBuilder.internNullableTypeReference($nonvoid_type_descriptor.type),
620              dexBuilder.internNullableStringReference($signature.value));
621    };
622
623end_local
624  : ^(I_END_LOCAL REGISTER)
625    {
626      int registerNumber = parseRegister_short($REGISTER.text);
627      $method::methodBuilder.addEndLocal(registerNumber);
628    };
629
630restart_local
631  : ^(I_RESTART_LOCAL REGISTER)
632    {
633      int registerNumber = parseRegister_short($REGISTER.text);
634      $method::methodBuilder.addRestartLocal(registerNumber);
635    };
636
637prologue
638  : I_PROLOGUE
639    {
640      $method::methodBuilder.addPrologue();
641    };
642
643epilogue
644  : I_EPILOGUE
645    {
646      $method::methodBuilder.addEpilogue();
647    };
648
649source
650  : ^(I_SOURCE string_literal?)
651    {
652      $method::methodBuilder.addSetSourceFile(dexBuilder.internNullableStringReference($string_literal.value));
653    };
654
655ordered_method_items
656  : ^(I_ORDERED_METHOD_ITEMS (label_def | instruction | debug_directive)*);
657
658label_ref returns[Label label]
659  : SIMPLE_NAME { $label = $method::methodBuilder.getLabel($SIMPLE_NAME.text); };
660
661register_list returns[byte[\] registers, byte registerCount]
662  @init
663  {
664    $registers = new byte[5];
665    $registerCount = 0;
666  }
667  : ^(I_REGISTER_LIST
668      (REGISTER
669      {
670        if ($registerCount == 5) {
671          throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 " +
672                  "registers. Use the <op>/range alternate opcode instead.");
673        }
674        $registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
675      })*);
676
677register_range returns[int startRegister, int endRegister]
678  : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
679    {
680        if ($startReg == null) {
681            $startRegister = 0;
682            $endRegister = -1;
683        } else {
684                $startRegister  = parseRegister_short($startReg.text);
685                if ($endReg == null) {
686                    $endRegister = $startRegister;
687                } else {
688                    $endRegister = parseRegister_short($endReg.text);
689                }
690
691                int registerCount = $endRegister-$startRegister+1;
692                if (registerCount < 1) {
693                    throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first");
694                }
695            }
696    };
697
698verification_error_reference returns[ImmutableReference reference]
699  : CLASS_DESCRIPTOR
700  {
701    $reference = new ImmutableTypeReference($CLASS_DESCRIPTOR.text);
702  }
703  | field_reference
704  {
705    $reference = $field_reference.fieldReference;
706  }
707  | method_reference
708  {
709    $reference = $method_reference.methodReference;
710  };
711
712verification_error_type returns[int verificationError]
713  : VERIFICATION_ERROR_TYPE
714  {
715    $verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text);
716  };
717
718instruction
719  : insn_format10t
720  | insn_format10x
721  | insn_format11n
722  | insn_format11x
723  | insn_format12x
724  | insn_format20bc
725  | insn_format20t
726  | insn_format21c_field
727  | insn_format21c_string
728  | insn_format21c_type
729  | insn_format21ih
730  | insn_format21lh
731  | insn_format21s
732  | insn_format21t
733  | insn_format22b
734  | insn_format22c_field
735  | insn_format22c_type
736  | insn_format22s
737  | insn_format22t
738  | insn_format22x
739  | insn_format23x
740  | insn_format30t
741  | insn_format31c
742  | insn_format31i
743  | insn_format31t
744  | insn_format32x
745  | insn_format35c_method
746  | insn_format35c_type
747  | insn_format3rc_method
748  | insn_format3rc_type
749  | insn_format51l_type
750  | insn_array_data_directive
751  | insn_packed_switch_directive
752  | insn_sparse_switch_directive;
753  catch [Exception ex] {
754    reportError(new SemanticException(input, $start, ex.getMessage()));
755    recover(input, null);
756  }
757
758insn_format10t
759  : //e.g. goto endloop:
760    ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref)
761    {
762      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
763      $method::methodBuilder.addInstruction(new BuilderInstruction10t(opcode, $label_ref.label));
764    };
765
766insn_format10x
767  : //e.g. return
768    ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
769    {
770      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
771      $method::methodBuilder.addInstruction(new BuilderInstruction10x(opcode));
772    };
773
774insn_format11n
775  : //e.g. const/4 v0, 5
776    ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
777    {
778      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11n.text);
779      byte regA = parseRegister_nibble($REGISTER.text);
780
781      short litB = $short_integral_literal.value;
782      LiteralTools.checkNibble(litB);
783
784      $method::methodBuilder.addInstruction(new BuilderInstruction11n(opcode, regA, litB));
785    };
786
787insn_format11x
788  : //e.g. move-result-object v1
789    ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
790    {
791      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
792      short regA = parseRegister_byte($REGISTER.text);
793
794      $method::methodBuilder.addInstruction(new BuilderInstruction11x(opcode, regA));
795    };
796
797insn_format12x
798  : //e.g. move v1 v2
799    ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
800    {
801      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT12x.text);
802      byte regA = parseRegister_nibble($registerA.text);
803      byte regB = parseRegister_nibble($registerB.text);
804
805      $method::methodBuilder.addInstruction(new BuilderInstruction12x(opcode, regA, regB));
806    };
807
808insn_format20bc
809  : //e.g. throw-verification-error generic-error, Lsome/class;
810    ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
811    {
812      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text);
813
814      int verificationError = $verification_error_type.verificationError;
815      ImmutableReference referencedItem = $verification_error_reference.reference;
816
817      $method::methodBuilder.addInstruction(new BuilderInstruction20bc(opcode, verificationError,
818              dexBuilder.internReference(referencedItem)));
819    };
820
821insn_format20t
822  : //e.g. goto/16 endloop:
823    ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t label_ref)
824    {
825      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20t.text);
826      $method::methodBuilder.addInstruction(new BuilderInstruction20t(opcode, $label_ref.label));
827    };
828
829insn_format21c_field
830  : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream;
831    ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER field_reference)
832    {
833      Opcode opcode = opcodes.getOpcodeByName($inst.text);
834      short regA = parseRegister_byte($REGISTER.text);
835
836      ImmutableFieldReference fieldReference = $field_reference.fieldReference;
837
838      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
839              dexBuilder.internFieldReference(fieldReference)));
840    };
841
842insn_format21c_string
843  : //e.g. const-string v1, "Hello World!"
844    ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
845    {
846      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
847      short regA = parseRegister_byte($REGISTER.text);
848
849      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
850              dexBuilder.internStringReference($string_literal.value)));
851    };
852
853insn_format21c_type
854  : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2
855    ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor)
856    {
857      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
858      short regA = parseRegister_byte($REGISTER.text);
859
860      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
861              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
862    };
863
864insn_format21ih
865  : //e.g. const/high16 v1, 1234
866    ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
867    {
868      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21ih.text);
869      short regA = parseRegister_byte($REGISTER.text);
870
871      int litB = $fixed_32bit_literal.value;
872
873      $method::methodBuilder.addInstruction(new BuilderInstruction21ih(opcode, regA, litB));
874    };
875
876insn_format21lh
877  : //e.g. const-wide/high16 v1, 1234
878    ^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal)
879    {
880      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21lh.text);
881      short regA = parseRegister_byte($REGISTER.text);
882
883      long litB = $fixed_64bit_literal.value;
884
885      $method::methodBuilder.addInstruction(new BuilderInstruction21lh(opcode, regA, litB));
886    };
887
888insn_format21s
889  : //e.g. const/16 v1, 1234
890    ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
891    {
892      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21s.text);
893      short regA = parseRegister_byte($REGISTER.text);
894
895      short litB = $short_integral_literal.value;
896
897      $method::methodBuilder.addInstruction(new BuilderInstruction21s(opcode, regA, litB));
898    };
899
900insn_format21t
901  : //e.g. if-eqz v0, endloop:
902    ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER label_ref)
903    {
904      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21t.text);
905      short regA = parseRegister_byte($REGISTER.text);
906
907      $method::methodBuilder.addInstruction(new BuilderInstruction21t(opcode, regA, $label_ref.label));
908    };
909
910insn_format22b
911  : //e.g. add-int v0, v1, 123
912    ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
913    {
914      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22b.text);
915      short regA = parseRegister_byte($registerA.text);
916      short regB = parseRegister_byte($registerB.text);
917
918      short litC = $short_integral_literal.value;
919      LiteralTools.checkByte(litC);
920
921      $method::methodBuilder.addInstruction(new BuilderInstruction22b(opcode, regA, regB, litC));
922    };
923
924insn_format22c_field
925  : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
926    ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER field_reference)
927    {
928      Opcode opcode = opcodes.getOpcodeByName($inst.text);
929      byte regA = parseRegister_nibble($registerA.text);
930      byte regB = parseRegister_nibble($registerB.text);
931
932      ImmutableFieldReference fieldReference = $field_reference.fieldReference;
933
934      $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
935              dexBuilder.internFieldReference(fieldReference)));
936    };
937
938insn_format22c_type
939  : //e.g. instance-of v0, v1, Ljava/lang/String;
940    ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
941    {
942      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text);
943      byte regA = parseRegister_nibble($registerA.text);
944      byte regB = parseRegister_nibble($registerB.text);
945
946      $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
947              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
948    };
949
950insn_format22s
951  : //e.g. add-int/lit16 v0, v1, 12345
952    ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
953    {
954      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22s.text);
955      byte regA = parseRegister_nibble($registerA.text);
956      byte regB = parseRegister_nibble($registerB.text);
957
958      short litC = $short_integral_literal.value;
959
960      $method::methodBuilder.addInstruction(new BuilderInstruction22s(opcode, regA, regB, litC));
961    };
962
963insn_format22t
964  : //e.g. if-eq v0, v1, endloop:
965    ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER label_ref)
966    {
967      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22t.text);
968      byte regA = parseRegister_nibble($registerA.text);
969      byte regB = parseRegister_nibble($registerB.text);
970
971      $method::methodBuilder.addInstruction(new BuilderInstruction22t(opcode, regA, regB, $label_ref.label));
972    };
973
974insn_format22x
975  : //e.g. move/from16 v1, v1234
976    ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
977    {
978      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22x.text);
979      short regA = parseRegister_byte($registerA.text);
980      int regB = parseRegister_short($registerB.text);
981
982      $method::methodBuilder.addInstruction(new BuilderInstruction22x(opcode, regA, regB));
983    };
984
985insn_format23x
986  : //e.g. add-int v1, v2, v3
987    ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
988    {
989      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT23x.text);
990      short regA = parseRegister_byte($registerA.text);
991      short regB = parseRegister_byte($registerB.text);
992      short regC = parseRegister_byte($registerC.text);
993
994      $method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC));
995    };
996
997insn_format30t
998  : //e.g. goto/32 endloop:
999    ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
1000    {
1001      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT30t.text);
1002
1003      $method::methodBuilder.addInstruction(new BuilderInstruction30t(opcode, $label_ref.label));
1004    };
1005
1006insn_format31c
1007  : //e.g. const-string/jumbo v1 "Hello World!"
1008    ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
1009    {
1010      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
1011      short regA = parseRegister_byte($REGISTER.text);
1012
1013      $method::methodBuilder.addInstruction(new BuilderInstruction31c(opcode, regA,
1014              dexBuilder.internStringReference($string_literal.value)));
1015    };
1016
1017insn_format31i
1018  : //e.g. const v0, 123456
1019    ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
1020    {
1021      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31i.text);
1022      short regA = parseRegister_byte($REGISTER.text);
1023
1024      int litB = $fixed_32bit_literal.value;
1025
1026      $method::methodBuilder.addInstruction(new BuilderInstruction31i(opcode, regA, litB));
1027    };
1028
1029insn_format31t
1030  : //e.g. fill-array-data v0, ArrayData:
1031    ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER label_ref)
1032    {
1033      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31t.text);
1034
1035      short regA = parseRegister_byte($REGISTER.text);
1036
1037      $method::methodBuilder.addInstruction(new BuilderInstruction31t(opcode, regA, $label_ref.label));
1038    };
1039
1040insn_format32x
1041  : //e.g. move/16 v5678, v1234
1042    ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
1043    {
1044      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT32x.text);
1045      int regA = parseRegister_short($registerA.text);
1046      int regB = parseRegister_short($registerB.text);
1047
1048      $method::methodBuilder.addInstruction(new BuilderInstruction32x(opcode, regA, regB));
1049    };
1050
1051insn_format35c_method
1052  : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
1053    ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list method_reference)
1054    {
1055      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text);
1056
1057      //this depends on the fact that register_list returns a byte[5]
1058      byte[] registers = $register_list.registers;
1059      byte registerCount = $register_list.registerCount;
1060
1061      ImmutableMethodReference methodReference = $method_reference.methodReference;
1062
1063      $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1],
1064              registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference)));
1065    };
1066
1067insn_format35c_type
1068  : //e.g. filled-new-array {v0,v1}, I
1069    ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor)
1070    {
1071      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text);
1072
1073      //this depends on the fact that register_list returns a byte[5]
1074      byte[] registers = $register_list.registers;
1075      byte registerCount = $register_list.registerCount;
1076
1077      $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1],
1078              registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
1079    };
1080
1081insn_format3rc_method
1082  : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1083    ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range method_reference)
1084    {
1085      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text);
1086      int startRegister = $register_range.startRegister;
1087      int endRegister = $register_range.endRegister;
1088
1089      int registerCount = endRegister-startRegister+1;
1090
1091      ImmutableMethodReference methodReference = $method_reference.methodReference;
1092
1093      $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount,
1094              dexBuilder.internMethodReference(methodReference)));
1095    };
1096
1097insn_format3rc_type
1098  : //e.g. filled-new-array/range {v0..v6} I
1099    ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor)
1100    {
1101      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text);
1102      int startRegister = $register_range.startRegister;
1103      int endRegister = $register_range.endRegister;
1104
1105      int registerCount = endRegister-startRegister+1;
1106
1107      $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount,
1108              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
1109    };
1110
1111insn_format51l_type
1112  : //e.g. const-wide v0, 5000000000L
1113    ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
1114    {
1115      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT51l.text);
1116      short regA = parseRegister_byte($REGISTER.text);
1117
1118      long litB = $fixed_64bit_literal.value;
1119
1120      $method::methodBuilder.addInstruction(new BuilderInstruction51l(opcode, regA, litB));
1121    };
1122
1123insn_array_data_directive
1124  : //e.g. .array-data 4 1000000 .end array-data
1125    ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
1126    {
1127      int elementWidth = $short_integral_literal.value;
1128      List<Number> elements = $array_elements.elements;
1129
1130      $method::methodBuilder.addInstruction(new BuilderArrayPayload(elementWidth, $array_elements.elements));
1131    };
1132
1133insn_packed_switch_directive
1134  :
1135    ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) packed_switch_elements)
1136      {
1137        int startKey = $fixed_32bit_literal.value;
1138        $method::methodBuilder.addInstruction(new BuilderPackedSwitchPayload(startKey,
1139            $packed_switch_elements.elements));
1140      };
1141
1142insn_sparse_switch_directive
1143  :
1144    ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements)
1145    {
1146      $method::methodBuilder.addInstruction(new BuilderSparseSwitchPayload($sparse_switch_elements.elements));
1147    };
1148
1149nonvoid_type_descriptor returns [String type]
1150  : (PRIMITIVE_TYPE
1151  | CLASS_DESCRIPTOR
1152  | ARRAY_DESCRIPTOR)
1153  {
1154    $type = $start.getText();
1155  };
1156
1157reference_type_descriptor returns [String type]
1158  : (CLASS_DESCRIPTOR
1159  | ARRAY_DESCRIPTOR)
1160  {
1161    $type = $start.getText();
1162  };
1163
1164type_descriptor returns [String type]
1165  : VOID_TYPE {$type = "V";}
1166  | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
1167  ;
1168
1169short_integral_literal returns[short value]
1170  : long_literal
1171    {
1172      LiteralTools.checkShort($long_literal.value);
1173      $value = (short)$long_literal.value;
1174    }
1175  | integer_literal
1176    {
1177      LiteralTools.checkShort($integer_literal.value);
1178      $value = (short)$integer_literal.value;
1179    }
1180  | short_literal {$value = $short_literal.value;}
1181  | char_literal {$value = (short)$char_literal.value;}
1182  | byte_literal {$value = $byte_literal.value;};
1183
1184integral_literal returns[int value]
1185  : long_literal
1186    {
1187      LiteralTools.checkInt($long_literal.value);
1188      $value = (int)$long_literal.value;
1189    }
1190  | integer_literal {$value = $integer_literal.value;}
1191  | short_literal {$value = $short_literal.value;}
1192  | byte_literal {$value = $byte_literal.value;};
1193
1194
1195integer_literal returns[int value]
1196  : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); };
1197
1198long_literal returns[long value]
1199  : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); };
1200
1201short_literal returns[short value]
1202  : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); };
1203
1204byte_literal returns[byte value]
1205  : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); };
1206
1207float_literal returns[float value]
1208  : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); };
1209
1210double_literal returns[double value]
1211  : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); };
1212
1213char_literal returns[char value]
1214  : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); };
1215
1216string_literal returns[String value]
1217  : STRING_LITERAL
1218    {
1219      $value = $STRING_LITERAL.text;
1220      $value = $value.substring(1,$value.length()-1);
1221    };
1222
1223bool_literal returns[boolean value]
1224  : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
1225
1226array_literal returns[List<EncodedValue> elements]
1227  : {$elements = Lists.newArrayList();}
1228    ^(I_ENCODED_ARRAY (literal {$elements.add($literal.encodedValue);})*);
1229
1230annotations returns[Set<Annotation> annotations]
1231  : {HashMap<String, Annotation> annotationMap = Maps.newHashMap();}
1232    ^(I_ANNOTATIONS (annotation
1233    {
1234        Annotation anno = $annotation.annotation;
1235        Annotation old = annotationMap.put(anno.getType(), anno);
1236        if (old != null) {
1237            throw new SemanticException(input, "Multiple annotations of type \%s", anno.getType());
1238        }
1239    })*)
1240    {
1241      if (annotationMap.size() > 0) {
1242        $annotations = ImmutableSet.copyOf(annotationMap.values());
1243      }
1244    };
1245
1246annotation returns[Annotation annotation]
1247  : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation)
1248    {
1249      int visibility = AnnotationVisibility.getVisibility($ANNOTATION_VISIBILITY.text);
1250      $annotation = new ImmutableAnnotation(visibility, $subannotation.annotationType, $subannotation.elements);
1251    };
1252
1253annotation_element returns[AnnotationElement element]
1254  : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal)
1255    {
1256      $element = new ImmutableAnnotationElement($SIMPLE_NAME.text, $literal.encodedValue);
1257    };
1258
1259subannotation returns[String annotationType, List<AnnotationElement> elements]
1260  : {ArrayList<AnnotationElement> elements = Lists.newArrayList();}
1261    ^(I_SUBANNOTATION
1262        CLASS_DESCRIPTOR
1263        (annotation_element
1264        {
1265           elements.add($annotation_element.element);
1266        })*
1267     )
1268    {
1269      $annotationType = $CLASS_DESCRIPTOR.text;
1270      $elements = elements;
1271    };
1272
1273field_literal returns[FieldReference value]
1274  : ^(I_ENCODED_FIELD field_reference)
1275    {
1276      $value = $field_reference.fieldReference;
1277    };
1278
1279method_literal returns[MethodReference value]
1280  : ^(I_ENCODED_METHOD method_reference)
1281    {
1282      $value = $method_reference.methodReference;
1283    };
1284
1285enum_literal returns[FieldReference value]
1286  : ^(I_ENCODED_ENUM field_reference)
1287    {
1288      $value = $field_reference.fieldReference;
1289    };
1290