1 /*
  2  * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jasm;
 24 
 25 import java.util.Arrays;
 26 import java.util.EnumSet;
 27 import java.util.Optional;
 28 
 29 /**
 30  *
 31  * JasmTokens
 32  *
 33  * This class contains tokens specific to parsing JASM syntax.
 34  *
 35  * The classes in JasmTokens are following a Singleton Pattern. These classes are Enums,
 36  * and they are contained in private hash maps (lookup tables and reverse lookup tables).
 37  * These hash maps all have public accessors, which clients use to look-up enums.
 38  *
 39  * Tokens in this table carry no external state, and are typically treated as constants.
 40  * They do not need to be reset.
 41  */
 42 public class JasmTokens {
 43 
 44     /*-------------------------------------------------------- */
 45     /* Marker: describes the type of Keyword */
 46     static public enum KeywordType {
 47         TOKEN            (0, "TOKEN"),
 48         VALUE            (1, "VALUE"),
 49         JASMIDENTIFIER   (2, "JASM"),
 50         KEYWORD          (3, "KEYWORD");
 51 
 52         private final Integer value;
 53         private final String printval;
 54 
 55         KeywordType(Integer val, String print) {
 56             value = val;
 57             printval = print;
 58         }
 59 
 60         public String printval() {
 61             return printval;
 62         }
 63     }
 64 
 65 
 66     /*--------------------------------------------------------  */
 67     /* Marker - describes the type of token                     */
 68     /*    this is rather cosmetic, no function currently.       */
 69     static public enum TokenType {
 70         MODIFIER            (1, "Modifier"),
 71         OPERATOR            (2, "Operator"),
 72         VALUE               (3, "Value"),
 73         TYPE                (4, "Type"),
 74         EXPRESSION          (5, "Expression"),
 75         STATEMENT           (6, "Statement"),
 76         DECLARATION         (7, "Declaration"),
 77         PUNCTUATION         (8, "Punctuation"),
 78         SPECIAL             (9, "Special"),
 79         JASM                (10, "Jasm"),
 80         MISC                (11, "Misc"),
 81         JASM_IDENT          (12, "Jasm identifier"),
 82         MODULE_NAME         (13, "Module Name"),
 83         TYPE_PATH_KIND      (14, "Type path kind")          // Table 4.7.20.2-A Interpretation of type_path_kind values
 84         ;
 85 
 86         private final Integer value;
 87         private final String printval;
 88 
 89         TokenType(Integer val, String print) {
 90             value = val;
 91             printval = print;
 92         }
 93         public String printval() {
 94             return printval;
 95         }
 96     }
 97 
 98     public enum AnnotationType {
 99         Visible("@+"),
100         Invisible("@-"),
101         VisibleType("@T+"),
102         InvisibleType("@T-");
103 
104         private final String jasmPrefix;
105 
106         AnnotationType(String jasmPrefix) {
107             this.jasmPrefix = jasmPrefix;
108         }
109 
110         /**
111          * isAnnotationToken
112          *
113          * examines the beginning of a string to see if it starts with an annotation
114          * characters ('@+' = visible annotation, '@-' = invisible).
115          *
116          * @param str String to be analyzed
117          * @return True if the string starts with an annotation char.
118          */
119         static public boolean isAnnotationToken(String str) {
120             return (str.startsWith(AnnotationType.Invisible.jasmPrefix) ||
121                     str.startsWith(AnnotationType.Visible.jasmPrefix));
122         }
123 
124         /**
125          * isTypeAnnotationToken
126          *
127          * examines the beginning of a string to see if it starts with type annotation
128          * characters ('@T+' = visible type annotation, '@T-' = invisible).
129          *
130          * @param str String to be analyzed
131          * @return True if the string starts with an annotation char.
132          */
133         static public boolean isTypeAnnotationToken(String str) {
134             return (str.startsWith(AnnotationType.InvisibleType.jasmPrefix) ||
135                     str.startsWith(AnnotationType.VisibleType.jasmPrefix));
136         }
137 
138         /**
139          * isAnnotation
140          *
141          * examines the beginning of a string to see if it starts with an annotation character
142          *
143          * @param str String to be analyzed
144          * @return True if the string starts with an annotation char.
145          */
146         static public boolean isAnnotation(String str) {
147             return (str.startsWith("@"));
148         }
149 
150         /**
151          * isInvisibleAnnotationToken
152          *
153          * examines the end of an annotation token to determine visibility ('+' = visible
154          * annotation, '-' = invisible).
155          *
156          * @param str String to be analyzed
157          * @return True if the token implies invisible annotation.
158          */
159         static public boolean isInvisibleAnnotationToken(String str) {
160             return (str.endsWith("-"));
161         }
162     }
163 
164     /**
165      * Scanner Tokens (Definitive List)
166      */
167     public enum Token {
168         EOF                 (-1, "EOF",         "EOF",  EnumSet.of(TokenType.MISC)),
169         COMMA               (0, "COMMA",        ",",    EnumSet.of(TokenType.OPERATOR)),
170         ASSIGN              (1, "ASSIGN",       "=",    EnumSet.of(TokenType.OPERATOR)),
171 
172         ASGMUL              (2, "ASGMUL",       "*=",   EnumSet.of(TokenType.OPERATOR)),
173         ASGDIV              (3, "ASGDIV",       "/=",   EnumSet.of(TokenType.OPERATOR)),
174         ASGREM              (4, "ASGREM",       "%=",   EnumSet.of(TokenType.OPERATOR)),
175         ASGADD              (5, "ASGADD",       "+=",   EnumSet.of(TokenType.OPERATOR)),
176         ASGSUB              (6, "ASGSUB",       "-=",   EnumSet.of(TokenType.OPERATOR)),
177         ASGLSHIFT           (7, "ASGLSHIFT",    "<<=",  EnumSet.of(TokenType.OPERATOR)),
178         ASGRSHIFT           (8, "ASGRSHIFT",    ">>=",  EnumSet.of(TokenType.OPERATOR)),
179         ASGURSHIFT          (9, "ASGURSHIFT",   "<<<=", EnumSet.of(TokenType.OPERATOR)),
180         ASGBITAND           (10, "ASGBITAND",   "&=",   EnumSet.of(TokenType.OPERATOR)),
181         ASGBITOR            (11, "ASGBITOR",    "|=",   EnumSet.of(TokenType.OPERATOR)),
182         ASGBITXOR           (12, "ASGBITXOR",   "^=",   EnumSet.of(TokenType.OPERATOR)),
183 
184         COND                (13, "COND",        "?:",   EnumSet.of(TokenType.OPERATOR)),
185         OR                  (14, "OR",          "||",   EnumSet.of(TokenType.OPERATOR)),
186         AND                 (15, "AND",         "&&",   EnumSet.of(TokenType.OPERATOR)),
187         BITOR               (16, "BITOR",       "|",    EnumSet.of(TokenType.OPERATOR)),
188         BITXOR              (17, "BITXOR",      "^",    EnumSet.of(TokenType.OPERATOR)),
189         BITAND              (18, "BITAND",      "&",    EnumSet.of(TokenType.OPERATOR)),
190         NE                  (19, "NE",          "!=",   EnumSet.of(TokenType.OPERATOR)),
191         EQ                  (20, "EQ",          "==",   EnumSet.of(TokenType.OPERATOR)),
192         GE                  (21, "GE",          ">=",   EnumSet.of(TokenType.OPERATOR)),
193         GT                  (22, "GT",          ">",    EnumSet.of(TokenType.OPERATOR)),
194         LE                  (23, "LE",          "<=",   EnumSet.of(TokenType.OPERATOR)),
195         LT                  (24, "LT",          "<",    EnumSet.of(TokenType.OPERATOR)),
196         INSTANCEOF          (25, "INSTANCEOF",  "instanceof",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
197         LSHIFT              (26, "LSHIFT",      "<<",   EnumSet.of(TokenType.OPERATOR)),
198         RSHIFT              (27, "RSHIFT",      ">>",   EnumSet.of(TokenType.OPERATOR)),
199         URSHIFT             (28, "URSHIFT",     "<<<",  EnumSet.of(TokenType.OPERATOR)),
200         ADD                 (29, "ADD",         "+",    EnumSet.of(TokenType.OPERATOR)),
201         SUB                 (30, "SUB",         "-",    EnumSet.of(TokenType.OPERATOR)),
202         DIV                 (31, "DIV",         "/",    EnumSet.of(TokenType.OPERATOR)),
203         REM                 (32, "REM",         "%",    EnumSet.of(TokenType.OPERATOR)),
204         MUL                 (33, "MUL",         "*",    EnumSet.of(TokenType.OPERATOR)),
205         CAST                (34, "CAST",        "cast", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
206         POS                 (35, "POS",         "+",    EnumSet.of(TokenType.OPERATOR)),
207         NEG                 (36, "NEG",         "-",    EnumSet.of(TokenType.OPERATOR)),
208         NOT                 (37, "NOT",         "!",    EnumSet.of(TokenType.OPERATOR)),
209         BITNOT              (38, "BITNOT",      "~",    EnumSet.of(TokenType.OPERATOR)),
210         PREINC              (39, "PREINC",      "++",   EnumSet.of(TokenType.OPERATOR)),
211         PREDEC              (40, "PREDEC",      "--",   EnumSet.of(TokenType.OPERATOR)),
212         NEWARRAY            (41, "NEWARRAY",    "new",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
213         NEWINSTANCE         (42, "NEWINSTANCE", "new",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
214         NEWFROMNAME         (43, "NEWFROMNAME", "new",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
215         POSTINC             (44, "POSTINC",     "++",   EnumSet.of(TokenType.OPERATOR)),
216         POSTDEC             (45, "POSTDEC",     "--",   EnumSet.of(TokenType.OPERATOR)),
217         FIELD               (46, "FIELD",       "field", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
218         METHOD              (47, "METHOD",      "method",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
219         ARRAYACCESS         (48, "ARRAYACCESS", "[]",   EnumSet.of(TokenType.OPERATOR)),
220         NEW                 (49, "NEW",         "new",  EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
221         INC                 (50, "INC",         "++",   EnumSet.of(TokenType.OPERATOR)),
222         DEC                 (51, "DEC",         "--",   EnumSet.of(TokenType.OPERATOR)),
223 
224         CONVERT             (55, "CONVERT",     "convert", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
225         EXPR                (56, "EXPR",        "expr", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
226         ARRAY               (57, "ARRAY",       "array", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
227         GOTO                (58, "GOTO",        "goto", EnumSet.of(TokenType.OPERATOR, TokenType.MODULE_NAME)),
228 
229     /*
230      * Value tokens
231      */
232         IDENT               (60, "IDENT",       "Identifier", EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME, TokenType.JASM_IDENT), KeywordType.VALUE),
233         BOOLEANVAL          (61, "BOOLEANVAL",  "Boolean",    EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
234         BYTEVAL             (62, "BYTEVAL",     "Byte",       EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME)),
235         CHARVAL             (63, "CHARVAL",     "Char",       EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME)),
236         SHORTVAL            (64, "SHORTVAL",    "Short",      EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME)),
237         INTVAL              (65, "INTVAL",      "Integer",    EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
238         LONGVAL             (66, "LONGVAL",     "Long",       EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
239         FLOATVAL            (67, "FLOATVAL",    "Float",      EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
240         DOUBLEVAL           (68, "DOUBLEVAL",   "Double",     EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
241         STRINGVAL           (69, "STRINGVAL",   "String",     EnumSet.of(TokenType.VALUE, TokenType.MODULE_NAME),   KeywordType.VALUE),
242 
243     /*
244      * Type keywords
245      */
246         BYTE                (70, "BYTE",        "byte",     EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME )),
247         CHAR                (71, "CHAR",        "char",     EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME )),
248         SHORT               (72, "SHORT",       "short",    EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME )),
249         INT                 (73, "INT",         "int",      EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME )),
250         LONG                (74, "LONG",        "long",     EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME )),
251         FLOAT               (75, "FLOAT",       "float",    EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME)),
252         DOUBLE              (76, "DOUBLE",      "double",   EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME)),
253         VOID                (77, "VOID",        "void",     EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME)),
254         BOOLEAN             (78, "BOOLEAN",     "boolean",  EnumSet.of(TokenType.TYPE, TokenType.MODULE_NAME)),
255 
256     /*
257      * Expression keywords
258      */
259         TRUE                (80, "TRUE",        "true",     EnumSet.of(TokenType.EXPRESSION, TokenType.MODULE_NAME )),
260         FALSE               (81, "FALSE",       "false",    EnumSet.of(TokenType.EXPRESSION, TokenType.MODULE_NAME )),
261         THIS                (82, "THIS",        "this",     EnumSet.of(TokenType.EXPRESSION, TokenType.MODULE_NAME )),
262         SUPER               (83, "SUPER",       "super",    EnumSet.of(TokenType.MODIFIER,   TokenType.MODULE_NAME ), KeywordType.KEYWORD),
263         NULL                (84, "NULL",        "null",     EnumSet.of(TokenType.EXPRESSION, TokenType.MODULE_NAME )),
264 
265     /*
266      * Statement keywords
267      */
268         IF                  (90, "IF",          "if",       EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
269         ELSE                (91, "ELSE",        "else",     EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
270         FOR                 (92, "FOR",         "for",      EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
271         WHILE               (93, "WHILE",       "while",    EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
272         DO                  (94, "DO",          "do",       EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
273         SWITCH              (95, "SWITCH",      "switch",   EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
274         CASE                (96, "CASE",        "case",     EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
275         DEFAULT             (97,  "DEFAULT",    "default",  EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
276         BREAK               (98, "BREAK",       "break",    EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
277         CONTINUE            (99, "CONTINUE",    "continue", EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
278         RETURN              (100, "RETURN",     "return",   EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
279         TRY                 (101, "TRY",        "try",      EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
280 
281         CATCH               (102, "CATCH",      "catch",    EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
282         FINALLY             (103, "FINALLY",    "finally",  EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
283         THROW               (104, "THROW",      "throw",            EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
284         STAT                (105, "STAT",       "stat",             EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
285         EXPRESSION          (106, "EXPRESSION", "expression",       EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
286         DECLARATION         (107, "DECLARATION", "declaration",     EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
287         VARDECLARATION      (108, "VARDECLARATION", "vdeclaration", EnumSet.of(TokenType.STATEMENT, TokenType.MODULE_NAME )),
288 
289     /*
290      * Declaration keywords
291      */
292         IMPORT              (110, "IMPORT",     "import",   EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME )),
293         CLASS               (111, "CLASS",      "class",    EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
294         EXTENDS             (112, "EXTENDS",    "extends",  EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
295         IMPLEMENTS          (113, "IMPLEMENTS", "implements",   EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
296         INTERFACE           (114, "INTERFACE",  "interface",    EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
297         PACKAGE             (115, "PACKAGE",    "package",  EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
298         ENUM                (116, "ENUM",       "enum",     EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
299         MANDATED            (117, "MANDATED",   "mandated", EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
300         THROWS              (118, "THROWS",     "throws",   EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
301 
302     /*
303      * Modifier keywords
304      */
305         ANNOTATION_ACCESS   (119, "ANNOTATION_ACCESS",  "annotation",       EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
306         PRIVATE             (120, "PRIVATE",            "private",          EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
307         PUBLIC              (121, "PUBLIC",             "public",           EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
308         PROTECTED           (122, "PROTECTED",          "protected",        EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
309         CONST               (123, "CONST",              "const",            EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME), KeywordType.KEYWORD),
310         STATIC              (124, "STATIC",             "static",           EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
311         TRANSIENT           (125, "TRANSIENT",          "transient",        EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
312         SYNCHRONIZED        (126, "SYNCHRONIZED",       "synchronized",     EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
313         NATIVE              (127, "NATIVE",             "native",           EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
314         FINAL               (128, "FINAL",              "final",            EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
315         VOLATILE            (129, "VOLATILE",           "volatile",         EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
316         ABSTRACT            (130, "ABSTRACT",           "abstract",         EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
317         TRANSITIVE          (131, "TRANSITIVE",         "transitive",       EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
318         OPEN                (132, "OPEN",               "open",             EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
319 
320     /*
321      * Punctuation
322      */
323         AT_SIGN             (133, "AT",         ";",       EnumSet.of(TokenType.PUNCTUATION), KeywordType.VALUE),
324         SEMICOLON           (134, "SEMICOLON",  ";",       EnumSet.of(TokenType.PUNCTUATION), KeywordType.VALUE),
325         COLON               (135, "COLON",      ":",       EnumSet.of(TokenType.PUNCTUATION), KeywordType.VALUE),
326         QUESTIONMARK        (136, "QUESTIONMARK", "?",     EnumSet.of(TokenType.PUNCTUATION)),
327         LBRACE              (137, "LBRACE",     "{",       EnumSet.of(TokenType.PUNCTUATION), KeywordType.VALUE),
328         RBRACE              (138, "RBRACE",     "}",       EnumSet.of(TokenType.PUNCTUATION), KeywordType.VALUE),
329         LPAREN              (139, "LPAREN",     "(",       EnumSet.of(TokenType.PUNCTUATION)),
330         RPAREN              (140, "RPAREN",     ")",       EnumSet.of(TokenType.PUNCTUATION)),
331         LSQBRACKET          (141, "LSQBRACKET", "[",       EnumSet.of(TokenType.PUNCTUATION)),
332         RSQBRACKET          (142, "RSQBRACKET", "]",       EnumSet.of(TokenType.PUNCTUATION)),
333 
334         ESCAPED_COLON       (201, "ESCCOLON",     "\\:",     EnumSet.of(TokenType.PUNCTUATION, TokenType.MODULE_NAME)),
335         ESCAPED_ATSIGH      (202, "ESCATSIGH",    "\\@",     EnumSet.of(TokenType.PUNCTUATION, TokenType.MODULE_NAME)),
336         ESCAPED_BACKSLASH   (203, "ESCBACKSLASH", "\\\\",    EnumSet.of(TokenType.PUNCTUATION, TokenType.MODULE_NAME)),
337     /*
338      * Special tokens
339      */
340         ERROR               (145, "ERROR",      "error",    EnumSet.of(TokenType.MODIFIER,    TokenType.MODULE_NAME)),
341         COMMENT             (146, "COMMENT",    "comment",  EnumSet.of(TokenType.MODIFIER,    TokenType.MODULE_NAME)),
342         TYPE                (147, "TYPE",       "type",     EnumSet.of(TokenType.MODIFIER,    TokenType.MODULE_NAME)),
343         LENGTH              (148, "LENGTH",     "length",   EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME )),
344         INLINERETURN        (149, "INLINERETURN", "inline-return",  EnumSet.of(TokenType.MODIFIER)),
345         INLINEMETHOD        (150, "INLINEMETHOD", "inline-method",  EnumSet.of(TokenType.MODIFIER)),
346         INLINENEWINSTANCE   (151, "INLINENEWINSTANCE", "inline-new",EnumSet.of(TokenType.MODIFIER)),
347 
348     /*
349      * Added for jasm
350      */
351         METHODREF           (152, "METHODREF",  "Method",   EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
352         FIELDREF            (153, "FIELD",      "Field",    EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
353         STACK               (154, "STACK",      "stack",    EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
354         LOCAL               (155, "LOCAL",      "locals",   EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
355         CPINDEX             (156, "CPINDEX",    "CPINDEX",  EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME )),
356         CPNAME              (157, "CPNAME",     "CPName",   EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME )),
357         SIGN                (158, "SIGN",       "SIGN",     EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME )),
358         BITS                (159, "BITS",       "bits",                 EnumSet.of(TokenType.MISC, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
359 
360         INF                 (160, "INF",        "Inf", "Infinity",  EnumSet.of(TokenType.MISC, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
361         NAN                 (161, "NAN",        "NaN",                  EnumSet.of(TokenType.MISC, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
362 
363         INNERCLASS          (162, "INNERCLASS", "InnerClass",       EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
364         OF                  (163, "OF",         "of",               EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
365         SYNTHETIC           (164, "SYNTHETIC",  "synthetic",  EnumSet.of(TokenType.MODIFIER, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
366         STRICT              (165, "STRICT",     "strict",     EnumSet.of(TokenType.MODIFIER, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
367         DEPRECATED          (166, "DEPRECATED", "deprecated", EnumSet.of(TokenType.MODIFIER, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
368         VERSION             (167, "VERSION",    "version",    EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
369         MODULE              (168, "MODULE",     "module",   EnumSet.of(TokenType.DECLARATION, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
370         ANNOTATION          (169, "ANNOTATION", "@",        EnumSet.of(TokenType.MISC, TokenType.MODULE_NAME )),
371         PARAM_NAME          (173, "PARAM_NAME", "#",        EnumSet.of(TokenType.MISC, TokenType.MODULE_NAME )),
372 
373         VARARGS             (170, "VARARGS",    "varargs",  EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
374         BRIDGE              (171, "BRIDGE",     "bridge",   EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
375 
376         // Declaration keywords
377         BOOTSTRAPMETHOD     (172, "BOOTSTRAPMETHOD", "BootstrapMethod", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
378         NESTHOST            (173, "NESTHOST",       "NestHost",         EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
379         NESTMEMBERS         (174, "NESTMEMBERS",    "NestMembers",      EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
380         //
381         RECORD              (175, "RECORD",    "Record",                EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
382         COMPONENT           (176, "COMPONENT", "Component",             EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
383         //
384         PERMITTEDSUBCLASSES (177, "PERMITTEDSUBCLASSES", "PermittedSubclasses", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
385 
386         //Module statements
387         REQUIRES            (180, "REQUIRES", "requires", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
388         EXPORTS             (182, "EXPORTS",  "exports",  EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
389         TO                  (183, "TO",       "to",       EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
390         USES                (184, "USES",     "uses",     EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
391         PROVIDES            (185, "PROVIDES", "provides", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
392         WITH                (186, "WITH",     "with",     EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
393         OPENS               (187, "OPENS",    "opens",    EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
394 
395         // Table 4.7.20.2-1 type_path_kind
396         ARRAY_TYPEPATH         (188, TypeAnnotationTypes.EPathKind.ARRAY.parseKey(),    TypeAnnotationTypes.EPathKind.ARRAY.parseKey(),
397                 EnumSet.of(TokenType.TYPE_PATH_KIND, TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
398         INNER_TYPE_TYPEPATH    (189, TypeAnnotationTypes.EPathKind.INNER_TYPE.parseKey(),    TypeAnnotationTypes.EPathKind.INNER_TYPE.parseKey(),
399                 EnumSet.of(TokenType.TYPE_PATH_KIND, TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
400         WILDCARD_TYPEPATH      (190, TypeAnnotationTypes.EPathKind.WILDCARD.parseKey(),    TypeAnnotationTypes.EPathKind.WILDCARD.parseKey(),
401                 EnumSet.of(TokenType.TYPE_PATH_KIND, TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
402         TYPE_ARGUMENT_TYPEPATH (191, TypeAnnotationTypes.EPathKind.TYPE_ARGUMENT.parseKey(),    TypeAnnotationTypes.EPathKind.TYPE_ARGUMENT.parseKey(),
403                 EnumSet.of(TokenType.TYPE_PATH_KIND, TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
404 
405         // Valhalla
406         VALUE              (200, "VALUE",     "value",     EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
407         PERMITS_VALUE      (201, "PERMITS_VALUE", "permits_value", EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
408         PRIMITIVE          (202, "PRIMITIVE", "primitive", EnumSet.of(TokenType.MODIFIER, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
409         PRELOAD            (203, "PRELOAD",    "Preload",  EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD);
410 
411 
412         final static EnumSet<Token> ALL_TOKENS = EnumSet.allOf(Token.class);
413         // Misc Keywords
414         final private Integer value;                    // 160
415         final private String  printval;                 // INF
416         final private String  parsekey;                 // inf
417         final private String  alias;                    // Infinity
418         final private EnumSet<TokenType>  tokenType;    // TokenType.MISC, TokenType.MODULE_NAME
419         final private KeywordType key_type;             // KeywordType.KEYWORD
420 
421         public static Optional<Token> get(String  parsekey, KeywordType ktype) {
422             return ALL_TOKENS.stream().
423                     filter(t->t.key_type == ktype).
424                     filter(t->t.parsekey.equals(parsekey) || ( t.alias != null && t.alias.equals(parsekey))).
425                     findFirst();
426         }
427 
428         /**
429          * Checks that this enum element is in an enum list
430          *
431          * @param tokens the list of enum elements for checking
432          * @return true if a tokens list contains this enum element
433          */
434         public boolean in(Token... tokens) {
435             return (tokens == null) ? false : Arrays.asList(tokens).contains(this);
436         }
437 
438         // By default, if a KeywordType is not specified, it has the value 'TOKEN'
439         Token(Integer val, String print, String parsekey, EnumSet<TokenType> ttype) {
440             this(val, print, parsekey, null, ttype, KeywordType.TOKEN);
441         }
442 
443         Token(Integer val, String print, String parsekey, String als, EnumSet<TokenType> ttype) {
444             this(val, print, parsekey, als, ttype, KeywordType.TOKEN);
445         }
446 
447         Token(Integer val, String print, String parsekey, EnumSet<TokenType> ttype, KeywordType ktype) {
448             this(val, print, parsekey, null, ttype, ktype);
449         }
450 
451         Token(Integer val, String print, String parsekey, String als, EnumSet<TokenType> ttype, KeywordType ktype) {
452             this.value = val;
453             this.printval = print;
454             this.parsekey = parsekey;
455             this.tokenType = ttype;
456             this.key_type = ktype;
457             this.alias = als;
458         }
459 
460         public String printValue() {
461             return printval;
462         }
463 
464         public String parseKey() {
465             return parsekey;
466         }
467 
468         public int value() {
469             return value;
470         }
471 
472         public boolean possibleJasmIdentifier() {
473             return tokenType.contains(TokenType.JASM_IDENT);
474         }
475 
476         public boolean possibleModuleName() {  return tokenType.contains(TokenType.MODULE_NAME)  && !tokenType.contains(TokenType.PUNCTUATION); }
477 
478         /**
479          * Checks a token belonging to the table: Table 4.7.20.2-A. Interpretation of type_path_kind values
480          *
481          * @return true if token is ARRAY, INNER_TYPE, WILDCARD or TYPE_ARGUMENT
482          */
483         public boolean possibleTypePathKind() { return tokenType.contains(TokenType.TYPE_PATH_KIND); }
484 
485         @Override
486         public String toString() {
487             return "<" + printval + "> [" + value + "]";
488         }
489     }
490 
491     public static Token keyword_token_ident(String idValue) {
492         return Token.get(idValue,KeywordType.KEYWORD).orElse(Token.IDENT);
493     }
494 }