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 }