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 }