1 /*
  2  * Copyright (c) 1996, 2017, 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.jcoder;
 24 
 25 import static org.openjdk.asmtools.jasm.Tables.*;
 26 
 27 import java.io.PrintWriter;
 28 import java.util.HashMap;
 29 
 30 /**
 31  *
 32  * JcodTokens
 33  *
 34  * This class contains tokens specific to parsing JCOD syntax.
 35  *
 36  * The classes in JcodTokens are following a Singleton Pattern. These classes are Enums,
 37  * and they are contained in private hash maps (lookup tables and reverse lookup tables).
 38  * These hash maps all have public accessors, which clients use to look-up enums.
 39  *
 40  * Tokens in this table carry no external state, and are typically treated as constants.
 41  * They do not need to be reset.
 42  */
 43 public class JcodTokens {
 44 
 45     /*-------------------------------------------------------- */
 46     /* Marker: describes the type of Keyword */
 47     static public enum KeywordType {
 48 
 49         TOKEN(0, "TOKEN"),
 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     /* Marker - describes the type of token */
 67     /*    this is rather cosmetic, no function currently. */
 68     static public enum TokenType {
 69         VALUE               (0, "Value"),
 70         KEYWORDS            (1, "Keywords"),
 71         PUNCTUATION         (2, "Punctuation"),
 72         JDEC                (3, "JDec"),
 73         STACKMAP            (4, "StackMap"),
 74         MISC                (5, "Misc");
 75 
 76         private final Integer value;
 77         private final String printval;
 78 
 79         TokenType(Integer val, String print) {
 80             value = val;
 81             printval = print;
 82         }
 83 
 84         public String printval() {
 85             return printval;
 86         }
 87     }
 88 
 89   /*-------------------------------------------------------- */
 90   /** Scanner Tokens (Definitive List) */
 91     static public enum Token {
 92         EOF                 (-1, "EOF",             "EOF",          TokenType.MISC),
 93         IDENT               (60, "IDENT",           "IDENT",        TokenType.VALUE),
 94         LONGSTRINGVAL       (61, "LONGSTRINGVAL",   "LONGSTRING",   TokenType.VALUE),
 95         INTVAL              (65, "INTVAL",          "INT",          TokenType.VALUE),
 96         LONGVAL             (66, "LONGVAL",         "LONG",         TokenType.VALUE),
 97         STRINGVAL           (69, "STRINGVAL",       "STRING",       TokenType.VALUE),
 98 
 99         CLASS               (70, "CLASS",           "class",        TokenType.KEYWORDS, KeywordType.KEYWORD),
100         INTERFACE           (71, "INTERFACE",       "interface",    TokenType.KEYWORDS, KeywordType.KEYWORD),
101         DIV                 (72, "DIV",             "div",          TokenType.KEYWORDS),
102         EQ                  (73, "EQ",              "eq",           TokenType.KEYWORDS),
103         ASSIGN              (74, "ASSIGN",          "assign",       TokenType.KEYWORDS),
104         MODULE              (75, "MODULE",          "module",       TokenType.KEYWORDS, KeywordType.KEYWORD),
105 
106         COLON               (134, "COLON",        ":",    TokenType.PUNCTUATION),
107         SEMICOLON           (135, "SEMICOLON",    ";",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
108         COMMA               (0,   "COMMA",        ",",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
109         LBRACE              (138, "LBRACE",       "{",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
110         RBRACE              (139, "RBRACE",       "}",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
111         LPAREN              (140, "LPAREN",       "(",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
112         RPAREN              (141, "RPAREN",       ")",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
113         LSQBRACKET          (142, "LSQBRACKET",   "[",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
114         RSQBRACKET          (143, "RSQBRACKET",   "]",    TokenType.PUNCTUATION, KeywordType.KEYWORD),
115 
116 
117         BYTEINDEX           (156, "BYTEINDEX",   "b",       TokenType.JDEC, KeywordType.KEYWORD),
118         SHORTINDEX          (157, "SHORTINDEX",  "s",       TokenType.JDEC, KeywordType.KEYWORD),
119         ATTR                (158, "ATTR",        "Attr",    TokenType.JDEC, KeywordType.KEYWORD),
120         BYTES               (159, "BYTES",       "Bytes",   TokenType.JDEC, KeywordType.KEYWORD),
121         MACRO               (160, "MACRO",        "Attr",    TokenType.JDEC),
122         COMP                (161, "COMP",        "Component", TokenType.JDEC, KeywordType.KEYWORD),
123         FILE                (162, "FILE",        "file",    TokenType.JDEC, KeywordType.KEYWORD),
124 
125         ZEROINDEX           (163, "ZEROINDEX",   "z",       TokenType.STACKMAP, KeywordType.KEYWORD);
126 
127         private Integer value;
128         private String printval;
129         private String parsekey;
130         private TokenType tk_type;
131         private KeywordType key_type;
132 
133         // By default, if a KeywordType is not specified, it has the value 'TOKEN'
134         Token(Integer val, String print, String op) {
135             init(val, print, op, TokenType.VALUE, KeywordType.TOKEN);
136         }
137 
138         Token(Integer val, String print, String op, TokenType tt) {
139             init(val, print, op, tt, KeywordType.TOKEN);
140         }
141 
142         Token(Integer val, String print, String op, TokenType tt, KeywordType kt) {
143             init(val, print, op, tt, kt);
144         }
145 
146         private void init(Integer val, String print, String op, TokenType tt, KeywordType kt) {
147             value = val;
148             printval = print;
149             parsekey = op;
150             tk_type = tt;
151             key_type = kt;
152         }
153 
154         public String printval() {
155             return printval;
156         }
157 
158         public String parsekey() {
159             return parsekey;
160         }
161 
162         public int value() {
163             return value;
164         }
165 
166         @Override
167         public String toString() {
168             return "<" + printval + "> [" + value + "]";
169         }
170 
171     }
172 
173     /**
174      * Initialized keyword and token Hash Maps (and Reverse Tables)
175      */
176     protected static final int MaxTokens = 172;
177     private static HashMap<Integer, Token> TagToTokens = new HashMap<>(MaxTokens);
178     private static HashMap<String, Token> SymbolToTokens = new HashMap<>(MaxTokens);
179     private static HashMap<String, Token> ParsekeyToTokens = new HashMap<>(MaxTokens);
180 
181     protected static final int MaxKeywords = 40;
182     private static HashMap<Integer, Token> TagToKeywords = new HashMap<>(MaxKeywords);
183     private static HashMap<String, Token> SymbolToKeywords = new HashMap<>(MaxKeywords);
184     private static HashMap<String, Token> ParsekeyToKeywords = new HashMap<>(MaxKeywords);
185 
186     static {
187 
188         // register all of the tokens
189         for (Token tk : Token.values()) {
190             registerToken(tk);
191         }
192 
193         SymbolToKeywords.put(Token.INTVAL.printval(), Token.INTVAL);
194         ParsekeyToKeywords.put(Token.INTVAL.parsekey(), Token.INTVAL);
195         SymbolToKeywords.put(Token.STRINGVAL.printval(), Token.STRINGVAL);
196         ParsekeyToKeywords.put(Token.STRINGVAL.parsekey(), Token.STRINGVAL);
197     }
198 
199     private static void registerToken(Token tk) {
200         // Tag is a keyword
201         if (tk.key_type == KeywordType.KEYWORD) {
202             TagToKeywords.put(tk.value, tk);
203             SymbolToKeywords.put(tk.printval, tk);
204             if (tk.parsekey != null) {
205                 ParsekeyToKeywords.put(tk.parsekey, tk);
206             }
207         }
208 
209         // Finally, register all tokens
210         TagToTokens.put(tk.value, tk);
211         SymbolToTokens.put(tk.printval, tk);
212         ParsekeyToTokens.put(tk.printval, tk);
213     }
214 
215     /* Token accessors */
216     public static Token token(int tk) {
217         return TagToTokens.get(tk);
218     }
219 
220     public static Token keyword_token(int tk) {
221         return TagToKeywords.get(tk);
222     }
223 
224     /* Reverse lookup accessors */
225     public static Token token(String parsekey) {
226         return ParsekeyToTokens.get(parsekey);
227     }
228 
229     public static Token keyword_token(String parsekey) {
230         return ParsekeyToKeywords.get(parsekey);
231     }
232 
233     /* Reverse lookup by ID accessors */
234     public static Token token_ID(String ID) {
235         return ParsekeyToTokens.get(ID);
236     }
237 
238     public static Token keyword_token_ID(String ID) {
239         return ParsekeyToKeywords.get(ID);
240     }
241 
242     public static String keywordName(int token) {
243         String retval = "";
244         if (token > TagToTokens.size()) {
245             retval = null;
246         } else {
247             Token tk = keyword_token(token);
248             if (tk != null) {
249                 retval = tk.parsekey;
250             }
251         }
252         return retval;
253     }
254 
255     public static Token keyword_token_ident(String idValue) {
256         Token kwd = keyword_token(idValue);
257 
258         if (kwd == null) {
259             kwd = Token.IDENT;
260         }
261         return kwd;
262     }
263 
264     public static int keyword_token_int(String idValue) {
265         return keyword_token_ident(idValue).value();
266     }
267 
268     private static HashMap<String, ConstType> NameToConstantType = new HashMap<>(ConstType.maxTag);
269     private static HashMap<Integer, ConstType> ConstantTypes = new HashMap<>(ConstType.maxTag);
270 
271     static {
272         // register all of the tokens
273         for (ConstType ct : ConstType.values()) {
274             registerConstantType(ct);
275         }
276     }
277 
278     /**
279      * ConstType
280      *
281      * A (typed) tag (constant) representing the type of Constant in the Constant Pool.
282      *
283      * This is more-or-less a copy of jasm.ConstType. Unfortunately, there's no way to
284      * sub-class (or slightly alter) the members of an enum. This enum set is slightly
285      * modified from the Jasm one.
286      */
287     static public enum ConstType {
288 //        CONSTANT_ZERO                       (-3, "CONSTANT_ZERO", ""),
289         CONSTANT_UTF8                       (1, "CONSTANT_UTF8", "Asciz", "Utf8"),
290         CONSTANT_UNICODE                    (2, "CONSTANT_UNICODE", ""),
291         CONSTANT_INTEGER                    (3, "CONSTANT_INTEGER", "int", "u4"),
292         CONSTANT_FLOAT                      (4, "CONSTANT_FLOAT", "float"),
293         CONSTANT_LONG                       (5, "CONSTANT_LONG", "long"),
294         CONSTANT_DOUBLE                     (6, "CONSTANT_DOUBLE", "double"),
295         // Class is removed for JavaCard (???)
296         CONSTANT_CLASS                      (7, "CONSTANT_CLASS", "class"),
297         CONSTANT_STRING                     (8, "CONSTANT_STRING", "String"),
298         CONSTANT_FIELD                      (9, "CONSTANT_FIELD", "Field"),
299         CONSTANT_METHOD                     (10, "CONSTANT_METHOD", "Method"),
300         CONSTANT_INTERFACEMETHOD            (11, "CONSTANT_INTERFACEMETHOD", "InterfaceMethod"),
301         CONSTANT_NAMEANDTYPE                (12, "CONSTANT_NAMEANDTYPE", "NameAndType"),
302         // added for JavaCard
303         CONSTANT_JAVACARD_PACKAGE           (13, "CONSTANT_PACKAGE", "package"),  // in javacard export file
304         // Constant 14 reserved
305         CONSTANT_METHODHANDLE               (15, "CONSTANT_METHODHANDLE", "MethodHandle"),
306         CONSTANT_METHODTYPE                 (16, "CONSTANT_METHODTYPE", "MethodType"),
307         CONSTANT_DYNAMIC                    (17, "CONSTANT_DYNAMIC", "Dynamic"),
308         CONSTANT_INVOKEDYNAMIC              (18, "CONSTANT_INVOKEDYNAMIC", "InvokeDynamic"),
309         CONSTANT_MODULE                     (19, "CONSTANT_MODULE",  "Module"),
310         CONSTANT_MODULE_PACKAGE             (20, "CONSTANT_PACKAGE", "Package");
311 
312         public static final int maxTag = 20;
313 
314         private final int value;
315         private final String parseKey;
316         private final String printval;
317         private final String alias;
318 
319         ConstType(int val, String print, String parse) {
320             value = val;
321             parseKey = parse;
322             printval = print;
323             alias = null;
324         }
325 
326         ConstType(int val, String print, String parse, String als) {
327             value = val;
328             parseKey = parse;
329             printval = print;
330             alias = als;
331         }
332 
333         public int value() {
334             return value;
335         }
336 
337         public String parseKey() {
338             return parseKey;
339         }
340 
341         public String printval() {
342             return printval;
343         }
344 
345         public void print(PrintWriter out) {
346             out.print(parseKey);
347         }
348 
349         @Override
350         public String toString() {
351             return "<" + printval + "> [" + Integer.toString(value) + "]";
352         }
353     };
354 
355     static public ConstType constType(int i) {
356         return ConstantTypes.get(i);
357     }
358 
359     static public ConstType constType(String parsekey) {
360         return NameToConstantType.get(parsekey);
361     }
362 
363     private static void registerConstantType(ConstType tt) {
364         NameToConstantType.put(tt.parseKey, tt);
365         if (tt.alias != null) {
366             NameToConstantType.put(tt.alias, tt);
367         }
368         ConstantTypes.put(tt.value, tt);
369     }
370 
371     public static int constValue(String stringValue) {
372         ConstType Val = constType(stringValue);
373         int val = -1;
374 
375         if (Val != null) {
376             val = Val.value();
377         } else {
378             StackMapType smt = stackMapTypeKey(stringValue);
379 
380             if (smt != null) {
381                 val = smt.value();
382             }
383         }
384         return val;
385     }
386 
387 }