• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package org.jf.smali;
2
3import java.io.*;
4import org.antlr.runtime.*;
5import org.jf.util.*;
6import static org.jf.smali.smaliParser.*;
7
8%%
9
10%public
11%class smaliFlexLexer
12%implements TokenSource
13%implements LexerErrorInterface
14%type Token
15%unicode
16%line
17%column
18%char
19
20%{
21    private StringBuffer sb = new StringBuffer();
22    private String stringOrCharError = null;
23    private int stringStartLine;
24    private int stringStartCol;
25    private int stringStartChar;
26
27    private int lexerErrors = 0;
28
29    private File sourceFile;
30
31    private boolean suppressErrors;
32
33    public Token nextToken() {
34        try {
35            Token token = yylex();
36            if (token instanceof InvalidToken) {
37                InvalidToken invalidToken = (InvalidToken)token;
38                if (!suppressErrors) {
39                    System.err.println(getErrorHeader(invalidToken) + " Error for input '" +
40                        invalidToken.getText() + "': " + invalidToken.getMessage());
41                }
42                lexerErrors++;
43            }
44            return token;
45        }
46        catch (java.io.IOException e) {
47            System.err.println("shouldn't happen: " + e.getMessage());
48            return newToken(EOF);
49        }
50    }
51
52    public void setLine(int line) {
53        this.yyline = line-1;
54    }
55
56    public void setColumn(int column) {
57        this.yycolumn = column;
58    }
59
60    public int getLine() {
61        return this.yyline+1;
62    }
63
64    public int getColumn() {
65        return this.yycolumn;
66    }
67
68    public void setSuppressErrors(boolean suppressErrors) {
69        this.suppressErrors = suppressErrors;
70    }
71
72    public void setSourceFile(File sourceFile) {
73        this.sourceFile = sourceFile;
74    }
75
76    public String getSourceName() {
77        if (sourceFile == null) {
78            return "";
79        }
80        try {
81            return  PathUtil.getRelativeFile(new File("."), sourceFile).getPath();
82        } catch (IOException ex) {
83            return sourceFile.getAbsolutePath();
84        }
85    }
86
87    public int getNumberOfSyntaxErrors() {
88        return lexerErrors;
89    }
90
91    private Token newToken(int type, String text, boolean hidden) {
92        CommonToken token = new CommonToken(type, text);
93        if (hidden) {
94            token.setChannel(Token.HIDDEN_CHANNEL);
95        }
96
97        token.setStartIndex(yychar);
98        token.setStopIndex(yychar + yylength() - 1);
99        token.setLine(getLine());
100        token.setCharPositionInLine(getColumn());
101        return token;
102    }
103
104    private Token newToken(int type, String text) {
105        return newToken(type, text, false);
106    }
107
108    private Token newToken(int type, boolean hidden) {
109        return newToken(type, yytext(), hidden);
110    }
111
112    private Token newToken(int type) {
113        return newToken(type, yytext(), false);
114    }
115
116    private Token invalidToken(String message, String text) {
117        InvalidToken token = new InvalidToken(message, text);
118
119        token.setStartIndex(yychar);
120        token.setStopIndex(yychar + yylength() - 1);
121        token.setLine(getLine());
122        token.setCharPositionInLine(getColumn());
123
124        return token;
125    }
126
127    private Token invalidToken(String message) {
128        return invalidToken(message, yytext());
129    }
130
131    private void beginStringOrChar(int state) {
132        yybegin(state);
133        sb.setLength(0);
134        stringStartLine = getLine();
135        stringStartCol = getColumn();
136        stringStartChar = yychar;
137        stringOrCharError = null;
138    }
139
140    private Token endStringOrChar(int type) {
141        yybegin(YYINITIAL);
142
143        if (stringOrCharError != null) {
144            return invalidStringOrChar(stringOrCharError);
145        }
146
147        CommonToken token = new CommonToken(type, sb.toString());
148        token.setStartIndex(stringStartChar);
149        token.setStopIndex(yychar + yylength() - 1);
150        token.setLine(stringStartLine);
151        token.setCharPositionInLine(stringStartCol);
152        return token;
153    }
154
155    private void setStringOrCharError(String message) {
156        if (stringOrCharError == null) {
157            stringOrCharError = message;
158        }
159    }
160
161    private Token invalidStringOrChar(String message) {
162        yybegin(YYINITIAL);
163
164        InvalidToken token = new InvalidToken(message, sb.toString());
165        token.setStartIndex(stringStartChar);
166        token.setStopIndex(yychar + yylength() - 1);
167        token.setLine(stringStartLine);
168        token.setCharPositionInLine(stringStartCol);
169        return token;
170    }
171
172    public String getErrorHeader(InvalidToken token) {
173        return getSourceName()+"["+ token.getLine()+","+token.getCharPositionInLine()+"]";
174    }
175
176    public void reset(CharSequence charSequence, int start, int end, int initialState) {
177        zzReader = BlankReader.INSTANCE;
178        zzBuffer = new char[charSequence.length()];
179        for (int i=0; i<charSequence.length(); i++) {
180            zzBuffer[i] = charSequence.charAt(i);
181        }
182
183        yychar = zzCurrentPos = zzMarkedPos = zzStartRead = start;
184        zzEndRead = end;
185        zzAtBOL = true;
186        zzAtEOF = false;
187        yybegin(initialState);
188    }
189%}
190
191HexPrefix = 0 [xX]
192
193HexDigit = [0-9a-fA-F]
194HexDigits = [0-9a-fA-F]{4}
195FewerHexDigits = [0-9a-fA-F]{0,3}
196
197Integer1 = 0
198Integer2 = [1-9] [0-9]*
199Integer3 = 0 [0-7]+
200Integer4 = {HexPrefix} {HexDigit}+
201Integer = {Integer1} | {Integer2} | {Integer3} | {Integer4}
202
203DecimalExponent = [eE] -? [0-9]+
204
205BinaryExponent = [pP] -? [0-9]+
206
207/*This can either be a floating point number or an identifier*/
208FloatOrID1 = -? [0-9]+ {DecimalExponent}
209FloatOrID2 = -? {HexPrefix} {HexDigit}+ {BinaryExponent}
210FloatOrID3 = -? [iI][nN][fF][iI][nN][iI][tT][yY]
211FloatOrID4 = [nN][aA][nN]
212FloatOrID =  {FloatOrID1} | {FloatOrID2} | {FloatOrID3} | {FloatOrID4}
213
214
215/*This can only be a float and not an identifier, due to the decimal point*/
216Float1 = -? [0-9]+ "." [0-9]* {DecimalExponent}?
217Float2 = -? "." [0-9]+ {DecimalExponent}?
218Float3 = -? {HexPrefix} {HexDigit}+ "." {HexDigit}* {BinaryExponent}
219Float4 = -? {HexPrefix} "." {HexDigit}+ {BinaryExponent}
220Float =  {Float1} | {Float2} | {Float3} | {Float4}
221
222HighSurrogate = [\ud800-\udbff]
223
224LowSurrogate = [\udc00-\udfff]
225
226SimpleNameCharacter = ({HighSurrogate} {LowSurrogate}) | [A-Za-z0-9$\-_\u00a1-\u1fff\u2010-\u2027\u2030-\ud7ff\ue000-\uffef]
227
228SimpleName = {SimpleNameCharacter}+
229
230PrimitiveType = [ZBSCIJFD]
231
232ClassDescriptor = L ({SimpleName} "/")* {SimpleName} ;
233
234ArrayPrefix = "["+
235
236Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | {PrimitiveType})
237
238
239%state PARAM_LIST_OR_ID
240%state PARAM_LIST
241%state ARRAY_DESCRIPTOR
242%state STRING
243%state CHAR
244
245%%
246
247/*Directives*/
248<YYINITIAL>
249{
250    ".class" { return newToken(CLASS_DIRECTIVE); }
251    ".super" { return newToken(SUPER_DIRECTIVE); }
252    ".implements" { return newToken(IMPLEMENTS_DIRECTIVE); }
253    ".source" { return newToken(SOURCE_DIRECTIVE); }
254    ".field" { return newToken(FIELD_DIRECTIVE); }
255    ".end field" { return newToken(END_FIELD_DIRECTIVE); }
256    ".subannotation" { return newToken(SUBANNOTATION_DIRECTIVE); }
257    ".end subannotation" { return newToken(END_SUBANNOTATION_DIRECTIVE); }
258    ".annotation" { return newToken(ANNOTATION_DIRECTIVE); }
259    ".end annotation" { return newToken(END_ANNOTATION_DIRECTIVE); }
260    ".enum" { return newToken(ENUM_DIRECTIVE); }
261    ".method" { return newToken(METHOD_DIRECTIVE); }
262    ".end method" { return newToken(END_METHOD_DIRECTIVE); }
263    ".registers" { return newToken(REGISTERS_DIRECTIVE); }
264    ".locals" { return newToken(LOCALS_DIRECTIVE); }
265    ".array-data" { return newToken(ARRAY_DATA_DIRECTIVE); }
266    ".end array-data" { return newToken(END_ARRAY_DATA_DIRECTIVE); }
267    ".packed-switch" { return newToken(PACKED_SWITCH_DIRECTIVE); }
268    ".end packed-switch" { return newToken(END_PACKED_SWITCH_DIRECTIVE); }
269    ".sparse-switch" { return newToken(SPARSE_SWITCH_DIRECTIVE); }
270    ".end sparse-switch" { return newToken(END_SPARSE_SWITCH_DIRECTIVE); }
271    ".catch" { return newToken(CATCH_DIRECTIVE); }
272    ".catchall" { return newToken(CATCHALL_DIRECTIVE); }
273    ".line" { return newToken(LINE_DIRECTIVE); }
274    ".param" { return newToken(PARAMETER_DIRECTIVE); }
275    ".end param" { return newToken(END_PARAMETER_DIRECTIVE); }
276    ".local" { return newToken(LOCAL_DIRECTIVE); }
277    ".end local" { return newToken(END_LOCAL_DIRECTIVE); }
278    ".restart local" { return newToken(RESTART_LOCAL_DIRECTIVE); }
279    ".prologue" { return newToken(PROLOGUE_DIRECTIVE); }
280    ".epilogue" { return newToken(EPILOGUE_DIRECTIVE); }
281
282    ".end" { return invalidToken("Invalid directive"); }
283    ".end " [a-zA-z0-9\-_]+ { return invalidToken("Invalid directive"); }
284    ".restart" { return invalidToken("Invalid directive"); }
285    ".restart " [a-zA-z0-9\-_]+ { return invalidToken("Invalid directive"); }
286}
287
288/*Literals*/
289<YYINITIAL> {
290    {Integer} { return newToken(POSITIVE_INTEGER_LITERAL); }
291    - {Integer} { return newToken(NEGATIVE_INTEGER_LITERAL); }
292    -? {Integer} [lL] { return newToken(LONG_LITERAL); }
293    -? {Integer} [sS] { return newToken(SHORT_LITERAL); }
294    -? {Integer} [tT] { return newToken(BYTE_LITERAL); }
295
296    {FloatOrID} [fF] | -? [0-9]+ [fF] { return newToken(FLOAT_LITERAL_OR_ID); }
297    {FloatOrID} [dD]? | -? [0-9]+ [dD] { return newToken(DOUBLE_LITERAL_OR_ID); }
298    {Float} [fF] { return newToken(FLOAT_LITERAL); }
299    {Float} [dD]? { return newToken(DOUBLE_LITERAL); }
300
301    "true"|"false" { return newToken(BOOL_LITERAL); }
302    "null" { return newToken(NULL_LITERAL); }
303
304    "\"" { beginStringOrChar(STRING); sb.append('"'); }
305
306    ' { beginStringOrChar(CHAR); sb.append('\''); }
307}
308
309<PARAM_LIST_OR_ID> {
310    {PrimitiveType} { return newToken(PARAM_LIST_OR_ID_PRIMITIVE_TYPE); }
311    [^] { yypushback(1); yybegin(YYINITIAL); }
312    <<EOF>> { yybegin(YYINITIAL); }
313}
314
315<PARAM_LIST> {
316    {PrimitiveType} { return newToken(PRIMITIVE_TYPE); }
317    {ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); }
318    {ArrayPrefix} { return newToken(ARRAY_TYPE_PREFIX); }
319    [^] { yypushback(1); yybegin(YYINITIAL);}
320    <<EOF>> { yybegin(YYINITIAL);}
321}
322
323<STRING> {
324    "\""  { sb.append('"'); return endStringOrChar(STRING_LITERAL); }
325
326    [^\r\n\"\\]+ { sb.append(yytext()); }
327    "\\b" { sb.append('\b'); }
328    "\\t" { sb.append('\t'); }
329    "\\n" { sb.append('\n'); }
330    "\\f" { sb.append('\f'); }
331    "\\r" { sb.append('\r'); }
332    "\\'" { sb.append('\''); }
333    "\\\"" { sb.append('"'); }
334    "\\\\" { sb.append('\\'); }
335    "\\u" {HexDigits} { sb.append((char)Integer.parseInt(yytext().substring(2,6), 16)); }
336
337    "\\u" {FewerHexDigits} {
338        sb.append(yytext());
339        setStringOrCharError("Invalid \\u sequence. \\u must be followed by 4 hex digits");
340    }
341
342    "\\" [^btnfr'\"\\u] {
343        sb.append(yytext());
344        setStringOrCharError("Invalid escape sequence " + yytext());
345    }
346
347    [\r\n] { return invalidStringOrChar("Unterminated string literal"); }
348    <<EOF>> { return invalidStringOrChar("Unterminated string literal"); }
349}
350
351<CHAR> {
352    ' {
353        sb.append('\'');
354        if (sb.length() == 2) {
355            return invalidStringOrChar("Empty character literal");
356        } else if (sb.length() > 3) {
357            return invalidStringOrChar("Character literal with multiple chars");
358        }
359
360        return endStringOrChar(CHAR_LITERAL);
361    }
362
363    [^\r\n'\\]+ { sb.append(yytext()); }
364    "\\b" { sb.append('\b'); }
365    "\\t" { sb.append('\t'); }
366    "\\n" { sb.append('\n'); }
367    "\\f" { sb.append('\f'); }
368    "\\r" { sb.append('\r'); }
369    "\\'" { sb.append('\''); }
370    "\\\"" { sb.append('"'); }
371    "\\\\" { sb.append('\\'); }
372    "\\u" {HexDigits} { sb.append((char)Integer.parseInt(yytext().substring(2,6), 16)); }
373
374    "\\u" {HexDigit}* {
375        sb.append(yytext());
376        setStringOrCharError("Invalid \\u sequence. \\u must be followed by exactly 4 hex digits");
377    }
378
379    "\\" [^btnfr'\"\\u] {
380        sb.append(yytext());
381        setStringOrCharError("Invalid escape sequence " + yytext());
382    }
383
384    [\r\n] { return invalidStringOrChar("Unterminated character literal"); }
385    <<EOF>> { return invalidStringOrChar("Unterminated character literal"); }
386}
387
388/*Misc*/
389<YYINITIAL> {
390    [vp] [0-9]+ { return newToken(REGISTER); }
391
392    "build" | "runtime" | "system" {
393        return newToken(ANNOTATION_VISIBILITY);
394    }
395
396    "public" | "private" | "protected" | "static" | "final" | "synchronized" | "bridge" | "varargs" | "native" |
397    "abstract" | "strictfp" | "synthetic" | "constructor" | "declared-synchronized" | "interface" | "enum" |
398    "annotation" | "volatile" | "transient" {
399        return newToken(ACCESS_SPEC);
400    }
401
402    "no-error" | "generic-error" | "no-such-class" | "no-such-field" | "no-such-method" | "illegal-class-access" |
403    "illegal-field-access" | "illegal-method-access" | "class-change-error" | "instantiation-error" {
404        return newToken(VERIFICATION_ERROR_TYPE);
405    }
406
407    "inline@0x" {HexDigit}+ { return newToken(INLINE_INDEX); }
408    "vtable@0x" {HexDigit}+ { return newToken(VTABLE_INDEX); }
409    "field@0x" {HexDigit}+ { return newToken(FIELD_OFFSET); }
410
411    # [^\r\n]* { return newToken(LINE_COMMENT, true); }
412}
413
414/*Instructions*/
415<YYINITIAL> {
416    "goto" {
417        return newToken(INSTRUCTION_FORMAT10t);
418    }
419
420    "return-void" | "nop" {
421        return newToken(INSTRUCTION_FORMAT10x);
422    }
423
424    "return-void-barrier" | "return-void-no-barrier" {
425        return newToken(INSTRUCTION_FORMAT10x_ODEX);
426    }
427
428    "const/4" {
429        return newToken(INSTRUCTION_FORMAT11n);
430    }
431
432    "move-result" | "move-result-wide" | "move-result-object" | "move-exception" | "return" | "return-wide" |
433    "return-object" | "monitor-enter" | "monitor-exit" | "throw" {
434        return newToken(INSTRUCTION_FORMAT11x);
435    }
436
437    "move" | "move-wide" | "move-object" | "array-length" | "neg-int" | "not-int" | "neg-long" | "not-long" |
438    "neg-float" | "neg-double" | "int-to-long" | "int-to-float" | "int-to-double" | "long-to-int" | "long-to-float" |
439    "long-to-double" | "float-to-int" | "float-to-long" | "float-to-double" | "double-to-int" | "double-to-long" |
440    "double-to-float" | "int-to-byte" | "int-to-char" | "int-to-short" {
441        return newToken(INSTRUCTION_FORMAT12x_OR_ID);
442    }
443
444    "add-int/2addr" | "sub-int/2addr" | "mul-int/2addr" | "div-int/2addr" | "rem-int/2addr" | "and-int/2addr" |
445    "or-int/2addr" | "xor-int/2addr" | "shl-int/2addr" | "shr-int/2addr" | "ushr-int/2addr" | "add-long/2addr" |
446    "sub-long/2addr" | "mul-long/2addr" | "div-long/2addr" | "rem-long/2addr" | "and-long/2addr" | "or-long/2addr" |
447    "xor-long/2addr" | "shl-long/2addr" | "shr-long/2addr" | "ushr-long/2addr" | "add-float/2addr" |
448    "sub-float/2addr" | "mul-float/2addr" | "div-float/2addr" | "rem-float/2addr" | "add-double/2addr" |
449    "sub-double/2addr" | "mul-double/2addr" | "div-double/2addr" | "rem-double/2addr" {
450        return newToken(INSTRUCTION_FORMAT12x);
451    }
452
453    "throw-verification-error" {
454        return newToken(INSTRUCTION_FORMAT20bc);
455    }
456
457    "goto/16" {
458        return newToken(INSTRUCTION_FORMAT20t);
459    }
460
461    "sget" | "sget-wide" | "sget-object" | "sget-boolean" | "sget-byte" | "sget-char" | "sget-short" | "sput" |
462    "sput-wide" | "sput-object" | "sput-boolean" | "sput-byte" | "sput-char" | "sput-short" {
463        return newToken(INSTRUCTION_FORMAT21c_FIELD);
464    }
465
466    "sget-volatile" | "sget-wide-volatile" | "sget-object-volatile" | "sput-volatile" | "sput-wide-volatile" |
467    "sput-object-volatile" {
468        return newToken(INSTRUCTION_FORMAT21c_FIELD_ODEX);
469    }
470
471    "const-string" {
472        return newToken(INSTRUCTION_FORMAT21c_STRING);
473    }
474
475    "check-cast" | "new-instance" | "const-class" {
476        return newToken(INSTRUCTION_FORMAT21c_TYPE);
477    }
478
479    "const/high16" {
480        return newToken(INSTRUCTION_FORMAT21ih);
481    }
482
483    "const-wide/high16" {
484        return newToken(INSTRUCTION_FORMAT21lh);
485    }
486
487    "const/16" | "const-wide/16" {
488        return newToken(INSTRUCTION_FORMAT21s);
489    }
490
491    "if-eqz" | "if-nez" | "if-ltz" | "if-gez" | "if-gtz" | "if-lez" {
492        return newToken(INSTRUCTION_FORMAT21t);
493    }
494
495    "add-int/lit8" | "rsub-int/lit8" | "mul-int/lit8" | "div-int/lit8" | "rem-int/lit8" | "and-int/lit8" |
496    "or-int/lit8" | "xor-int/lit8" | "shl-int/lit8" | "shr-int/lit8" | "ushr-int/lit8" {
497        return newToken(INSTRUCTION_FORMAT22b);
498    }
499
500    "iget" | "iget-wide" | "iget-object" | "iget-boolean" | "iget-byte" | "iget-char" | "iget-short" | "iput" |
501    "iput-wide" | "iput-object" | "iput-boolean" | "iput-byte" | "iput-char" | "iput-short" {
502        return newToken(INSTRUCTION_FORMAT22c_FIELD);
503    }
504
505    "iget-volatile" | "iget-wide-volatile" | "iget-object-volatile" | "iput-volatile" | "iput-wide-volatile" |
506    "iput-object-volatile" {
507        return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX);
508    }
509
510    "instance-of" | "new-array" {
511        return newToken(INSTRUCTION_FORMAT22c_TYPE);
512    }
513
514    "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" |
515    "iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" {
516        return newToken(INSTRUCTION_FORMAT22cs_FIELD);
517    }
518
519    "rsub-int" {
520        return newToken(INSTRUCTION_FORMAT22s_OR_ID);
521    }
522
523    "add-int/lit16" | "mul-int/lit16" | "div-int/lit16" | "rem-int/lit16" | "and-int/lit16" | "or-int/lit16" |
524    "xor-int/lit16" {
525        return newToken(INSTRUCTION_FORMAT22s);
526    }
527
528    "if-eq" | "if-ne" | "if-lt" | "if-ge" | "if-gt" | "if-le" {
529        return newToken(INSTRUCTION_FORMAT22t);
530    }
531
532    "move/from16" | "move-wide/from16" | "move-object/from16" {
533        return newToken(INSTRUCTION_FORMAT22x);
534    }
535
536    "cmpl-float" | "cmpg-float" | "cmpl-double" | "cmpg-double" | "cmp-long" | "aget" | "aget-wide" | "aget-object" |
537    "aget-boolean" | "aget-byte" | "aget-char" | "aget-short" | "aput" | "aput-wide" | "aput-object" | "aput-boolean" |
538    "aput-byte" | "aput-char" | "aput-short" | "add-int" | "sub-int" | "mul-int" | "div-int" | "rem-int" | "and-int" |
539    "or-int" | "xor-int" | "shl-int" | "shr-int" | "ushr-int" | "add-long" | "sub-long" | "mul-long" | "div-long" |
540    "rem-long" | "and-long" | "or-long" | "xor-long" | "shl-long" | "shr-long" | "ushr-long" | "add-float" |
541    "sub-float" | "mul-float" | "div-float" | "rem-float" | "add-double" | "sub-double" | "mul-double" | "div-double" |
542    "rem-double" {
543        return newToken(INSTRUCTION_FORMAT23x);
544    }
545
546    "goto/32" {
547        return newToken(INSTRUCTION_FORMAT30t);
548    }
549
550    "const-string/jumbo" {
551        return newToken(INSTRUCTION_FORMAT31c);
552    }
553
554    "const" {
555        return newToken(INSTRUCTION_FORMAT31i_OR_ID);
556    }
557
558    "const-wide/32" {
559        return newToken(INSTRUCTION_FORMAT31i);
560    }
561
562    "fill-array-data" | "packed-switch" | "sparse-switch" {
563        return newToken(INSTRUCTION_FORMAT31t);
564    }
565
566    "move/16" | "move-wide/16" | "move-object/16" {
567        return newToken(INSTRUCTION_FORMAT32x);
568    }
569
570    "invoke-virtual" | "invoke-super" | "invoke-direct" | "invoke-static" | "invoke-interface" {
571        return newToken(INSTRUCTION_FORMAT35c_METHOD);
572    }
573
574    "invoke-direct-empty" {
575        return newToken(INSTRUCTION_FORMAT35c_METHOD_ODEX);
576    }
577
578    "filled-new-array" {
579        return newToken(INSTRUCTION_FORMAT35c_TYPE);
580    }
581
582    "execute-inline" {
583        return newToken(INSTRUCTION_FORMAT35mi_METHOD);
584    }
585
586    "invoke-virtual-quick" | "invoke-super-quick" {
587        return newToken(INSTRUCTION_FORMAT35ms_METHOD);
588    }
589
590    "invoke-virtual/range" | "invoke-super/range" | "invoke-direct/range" | "invoke-static/range" |
591    "invoke-interface/range" {
592        return newToken(INSTRUCTION_FORMAT3rc_METHOD);
593    }
594
595    "invoke-object-init/range" {
596        return newToken(INSTRUCTION_FORMAT3rc_METHOD_ODEX);
597    }
598
599    "filled-new-array/range" {
600        return newToken(INSTRUCTION_FORMAT3rc_TYPE);
601    }
602
603    "execute-inline/range" {
604        return newToken(INSTRUCTION_FORMAT3rmi_METHOD);
605    }
606
607    "invoke-virtual-quick/range" | "invoke-super-quick/range" {
608        return newToken(INSTRUCTION_FORMAT3rms_METHOD);
609    }
610
611    "invoke-polymorphic" {
612        return newToken(INSTRUCTION_FORMAT45cc_METHOD);
613    }
614
615    "invoke-polymorphic/range" {
616        return newToken(INSTRUCTION_FORMAT4rcc_METHOD);
617    }
618
619    "const-wide" {
620        return newToken(INSTRUCTION_FORMAT51l);
621    }
622}
623
624<ARRAY_DESCRIPTOR> {
625   {PrimitiveType} { yybegin(YYINITIAL); return newToken(PRIMITIVE_TYPE); }
626   {ClassDescriptor} { yybegin(YYINITIAL); return newToken(CLASS_DESCRIPTOR); }
627   [^] { yypushback(1); yybegin(YYINITIAL); }
628   <<EOF>> { yybegin(YYINITIAL); }
629}
630
631/*Types*/
632<YYINITIAL> {
633    {PrimitiveType} { return newToken(PRIMITIVE_TYPE); }
634    V { return newToken(VOID_TYPE); }
635    {ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); }
636
637    // we have to drop into a separate state so that we don't parse something like
638    // "[I->" as "[" followed by "I-" as a SIMPLE_NAME
639    {ArrayPrefix} {
640      yybegin(ARRAY_DESCRIPTOR);
641      return newToken(ARRAY_TYPE_PREFIX);
642    }
643
644    {PrimitiveType} {PrimitiveType}+ {
645        // go back and re-lex it as a PARAM_LIST_OR_ID
646        yypushback(yylength());
647        yybegin(PARAM_LIST_OR_ID);
648    }
649
650    {Type} {Type}+ {
651        // go back and re-lex it as a PARAM_LIST
652        yypushback(yylength());
653        yybegin(PARAM_LIST);
654    }
655
656    {SimpleName} { return newToken(SIMPLE_NAME); }
657    "<" {SimpleName} ">" { return newToken(MEMBER_NAME); }
658}
659
660/*Symbols/Whitespace/EOF*/
661<YYINITIAL> {
662    ".." { return newToken(DOTDOT); }
663    "->" { return newToken(ARROW); }
664    "=" { return newToken(EQUAL); }
665    ":" { return newToken(COLON); }
666    "," { return newToken(COMMA); }
667    "{" { return newToken(OPEN_BRACE); }
668    "}" { return newToken(CLOSE_BRACE); }
669    "(" { return newToken(OPEN_PAREN); }
670    ")" { return newToken(CLOSE_PAREN); }
671    [\r\n\t ]+ { return newToken(WHITE_SPACE, true); }
672    <<EOF>> { return newToken(EOF); }
673}
674
675/*catch all*/
676<YYINITIAL> {
677    "." { return invalidToken("Invalid directive"); }
678    "." [a-zA-z\-_] { return invalidToken("Invalid directive"); }
679    "." [a-zA-z\-_] [a-zA-z0-9\-_]* { return invalidToken("Invalid directive"); }
680    [^] { return invalidToken("Invalid text"); }
681}
682