src/share/classes/com/sun/tools/javac/parser/Tokens.java

Mon, 24 Oct 2011 13:00:20 +0100

author
mcimadamore
date
Mon, 24 Oct 2011 13:00:20 +0100
changeset 1113
d346ab55031b
child 1125
56830d5cb5bb
permissions
-rw-r--r--

7096014: Javac tokens should retain state
Summary: Refactor javac tokens from enum constants to stateful instances (to keep track of position, comments, etc.)
Reviewed-by: jjg

mcimadamore@1113 1 /*
mcimadamore@1113 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1113 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1113 4 *
mcimadamore@1113 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1113 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1113 7 * published by the Free Software Foundation. Oracle designates this
mcimadamore@1113 8 * particular file as subject to the "Classpath" exception as provided
mcimadamore@1113 9 * by Oracle in the LICENSE file that accompanied this code.
mcimadamore@1113 10 *
mcimadamore@1113 11 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1113 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1113 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1113 14 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1113 15 * accompanied this code).
mcimadamore@1113 16 *
mcimadamore@1113 17 * You should have received a copy of the GNU General Public License version
mcimadamore@1113 18 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1113 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1113 20 *
mcimadamore@1113 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1113 22 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1113 23 * questions.
mcimadamore@1113 24 */
mcimadamore@1113 25
mcimadamore@1113 26 package com.sun.tools.javac.parser;
mcimadamore@1113 27
mcimadamore@1113 28 import java.util.Locale;
mcimadamore@1113 29
mcimadamore@1113 30 import com.sun.tools.javac.api.Formattable;
mcimadamore@1113 31 import com.sun.tools.javac.api.Messages;
mcimadamore@1113 32 import com.sun.tools.javac.parser.Tokens.Token.Tag;
mcimadamore@1113 33 import com.sun.tools.javac.util.Name;
mcimadamore@1113 34 import com.sun.tools.javac.util.Context;
mcimadamore@1113 35 import com.sun.tools.javac.util.Names;
mcimadamore@1113 36
mcimadamore@1113 37 /** A class that defines codes/utilities for Java source tokens
mcimadamore@1113 38 * returned from lexical analysis.
mcimadamore@1113 39 *
mcimadamore@1113 40 * <p><b>This is NOT part of any supported API.
mcimadamore@1113 41 * If you write code that depends on this, you do so at your own risk.
mcimadamore@1113 42 * This code and its internal interfaces are subject to change or
mcimadamore@1113 43 * deletion without notice.</b>
mcimadamore@1113 44 */
mcimadamore@1113 45 public class Tokens {
mcimadamore@1113 46
mcimadamore@1113 47 private final Names names;
mcimadamore@1113 48
mcimadamore@1113 49 /**
mcimadamore@1113 50 * Keyword array. Maps name indices to Token.
mcimadamore@1113 51 */
mcimadamore@1113 52 private final TokenKind[] key;
mcimadamore@1113 53
mcimadamore@1113 54 /** The number of the last entered keyword.
mcimadamore@1113 55 */
mcimadamore@1113 56 private int maxKey = 0;
mcimadamore@1113 57
mcimadamore@1113 58 /** The names of all tokens.
mcimadamore@1113 59 */
mcimadamore@1113 60 private Name[] tokenName = new Name[TokenKind.values().length];
mcimadamore@1113 61
mcimadamore@1113 62 public static final Context.Key<Tokens> tokensKey =
mcimadamore@1113 63 new Context.Key<Tokens>();
mcimadamore@1113 64
mcimadamore@1113 65 public static Tokens instance(Context context) {
mcimadamore@1113 66 Tokens instance = context.get(tokensKey);
mcimadamore@1113 67 if (instance == null)
mcimadamore@1113 68 instance = new Tokens(context);
mcimadamore@1113 69 return instance;
mcimadamore@1113 70 }
mcimadamore@1113 71
mcimadamore@1113 72 protected Tokens(Context context) {
mcimadamore@1113 73 context.put(tokensKey, this);
mcimadamore@1113 74 names = Names.instance(context);
mcimadamore@1113 75
mcimadamore@1113 76 for (TokenKind t : TokenKind.values()) {
mcimadamore@1113 77 if (t.name != null)
mcimadamore@1113 78 enterKeyword(t.name, t);
mcimadamore@1113 79 else
mcimadamore@1113 80 tokenName[t.ordinal()] = null;
mcimadamore@1113 81 }
mcimadamore@1113 82
mcimadamore@1113 83 key = new TokenKind[maxKey+1];
mcimadamore@1113 84 for (int i = 0; i <= maxKey; i++) key[i] = TokenKind.IDENTIFIER;
mcimadamore@1113 85 for (TokenKind t : TokenKind.values()) {
mcimadamore@1113 86 if (t.name != null)
mcimadamore@1113 87 key[tokenName[t.ordinal()].getIndex()] = t;
mcimadamore@1113 88 }
mcimadamore@1113 89 }
mcimadamore@1113 90
mcimadamore@1113 91 private void enterKeyword(String s, TokenKind token) {
mcimadamore@1113 92 Name n = names.fromString(s);
mcimadamore@1113 93 tokenName[token.ordinal()] = n;
mcimadamore@1113 94 if (n.getIndex() > maxKey) maxKey = n.getIndex();
mcimadamore@1113 95 }
mcimadamore@1113 96
mcimadamore@1113 97 /**
mcimadamore@1113 98 * Create a new token given a name; if the name corresponds to a token name,
mcimadamore@1113 99 * a new token of the corresponding kind is returned; otherwise, an
mcimadamore@1113 100 * identifier token is returned.
mcimadamore@1113 101 */
mcimadamore@1113 102 TokenKind lookupKind(Name name) {
mcimadamore@1113 103 return (name.getIndex() > maxKey) ? TokenKind.IDENTIFIER : key[name.getIndex()];
mcimadamore@1113 104 }
mcimadamore@1113 105
mcimadamore@1113 106 TokenKind lookupKind(String name) {
mcimadamore@1113 107 return lookupKind(names.fromString(name));
mcimadamore@1113 108 }
mcimadamore@1113 109
mcimadamore@1113 110 /**
mcimadamore@1113 111 * This enum defines all tokens used by the javac scanner. A token is
mcimadamore@1113 112 * optionally associated with a name.
mcimadamore@1113 113 */
mcimadamore@1113 114 public enum TokenKind implements Formattable {
mcimadamore@1113 115 EOF(),
mcimadamore@1113 116 ERROR(),
mcimadamore@1113 117 IDENTIFIER(Tag.NAMED),
mcimadamore@1113 118 ABSTRACT("abstract"),
mcimadamore@1113 119 ASSERT("assert", Tag.NAMED),
mcimadamore@1113 120 BOOLEAN("boolean", Tag.NAMED),
mcimadamore@1113 121 BREAK("break"),
mcimadamore@1113 122 BYTE("byte", Tag.NAMED),
mcimadamore@1113 123 CASE("case"),
mcimadamore@1113 124 CATCH("catch"),
mcimadamore@1113 125 CHAR("char", Tag.NAMED),
mcimadamore@1113 126 CLASS("class"),
mcimadamore@1113 127 CONST("const"),
mcimadamore@1113 128 CONTINUE("continue"),
mcimadamore@1113 129 DEFAULT("default"),
mcimadamore@1113 130 DO("do"),
mcimadamore@1113 131 DOUBLE("double", Tag.NAMED),
mcimadamore@1113 132 ELSE("else"),
mcimadamore@1113 133 ENUM("enum", Tag.NAMED),
mcimadamore@1113 134 EXTENDS("extends"),
mcimadamore@1113 135 FINAL("final"),
mcimadamore@1113 136 FINALLY("finally"),
mcimadamore@1113 137 FLOAT("float", Tag.NAMED),
mcimadamore@1113 138 FOR("for"),
mcimadamore@1113 139 GOTO("goto"),
mcimadamore@1113 140 IF("if"),
mcimadamore@1113 141 IMPLEMENTS("implements"),
mcimadamore@1113 142 IMPORT("import"),
mcimadamore@1113 143 INSTANCEOF("instanceof"),
mcimadamore@1113 144 INT("int", Tag.NAMED),
mcimadamore@1113 145 INTERFACE("interface"),
mcimadamore@1113 146 LONG("long", Tag.NAMED),
mcimadamore@1113 147 NATIVE("native"),
mcimadamore@1113 148 NEW("new"),
mcimadamore@1113 149 PACKAGE("package"),
mcimadamore@1113 150 PRIVATE("private"),
mcimadamore@1113 151 PROTECTED("protected"),
mcimadamore@1113 152 PUBLIC("public"),
mcimadamore@1113 153 RETURN("return"),
mcimadamore@1113 154 SHORT("short", Tag.NAMED),
mcimadamore@1113 155 STATIC("static"),
mcimadamore@1113 156 STRICTFP("strictfp"),
mcimadamore@1113 157 SUPER("super", Tag.NAMED),
mcimadamore@1113 158 SWITCH("switch"),
mcimadamore@1113 159 SYNCHRONIZED("synchronized"),
mcimadamore@1113 160 THIS("this", Tag.NAMED),
mcimadamore@1113 161 THROW("throw"),
mcimadamore@1113 162 THROWS("throws"),
mcimadamore@1113 163 TRANSIENT("transient"),
mcimadamore@1113 164 TRY("try"),
mcimadamore@1113 165 VOID("void", Tag.NAMED),
mcimadamore@1113 166 VOLATILE("volatile"),
mcimadamore@1113 167 WHILE("while"),
mcimadamore@1113 168 INTLITERAL(Tag.NUMERIC),
mcimadamore@1113 169 LONGLITERAL(Tag.NUMERIC),
mcimadamore@1113 170 FLOATLITERAL(Tag.NUMERIC),
mcimadamore@1113 171 DOUBLELITERAL(Tag.NUMERIC),
mcimadamore@1113 172 CHARLITERAL(Tag.NUMERIC),
mcimadamore@1113 173 STRINGLITERAL(Tag.STRING),
mcimadamore@1113 174 TRUE("true", Tag.NAMED),
mcimadamore@1113 175 FALSE("false", Tag.NAMED),
mcimadamore@1113 176 NULL("null", Tag.NAMED),
mcimadamore@1113 177 LPAREN("("),
mcimadamore@1113 178 RPAREN(")"),
mcimadamore@1113 179 LBRACE("{"),
mcimadamore@1113 180 RBRACE("}"),
mcimadamore@1113 181 LBRACKET("["),
mcimadamore@1113 182 RBRACKET("]"),
mcimadamore@1113 183 SEMI(";"),
mcimadamore@1113 184 COMMA(","),
mcimadamore@1113 185 DOT("."),
mcimadamore@1113 186 ELLIPSIS("..."),
mcimadamore@1113 187 EQ("="),
mcimadamore@1113 188 GT(">"),
mcimadamore@1113 189 LT("<"),
mcimadamore@1113 190 BANG("!"),
mcimadamore@1113 191 TILDE("~"),
mcimadamore@1113 192 QUES("?"),
mcimadamore@1113 193 COLON(":"),
mcimadamore@1113 194 EQEQ("=="),
mcimadamore@1113 195 LTEQ("<="),
mcimadamore@1113 196 GTEQ(">="),
mcimadamore@1113 197 BANGEQ("!="),
mcimadamore@1113 198 AMPAMP("&&"),
mcimadamore@1113 199 BARBAR("||"),
mcimadamore@1113 200 PLUSPLUS("++"),
mcimadamore@1113 201 SUBSUB("--"),
mcimadamore@1113 202 PLUS("+"),
mcimadamore@1113 203 SUB("-"),
mcimadamore@1113 204 STAR("*"),
mcimadamore@1113 205 SLASH("/"),
mcimadamore@1113 206 AMP("&"),
mcimadamore@1113 207 BAR("|"),
mcimadamore@1113 208 CARET("^"),
mcimadamore@1113 209 PERCENT("%"),
mcimadamore@1113 210 LTLT("<<"),
mcimadamore@1113 211 GTGT(">>"),
mcimadamore@1113 212 GTGTGT(">>>"),
mcimadamore@1113 213 PLUSEQ("+="),
mcimadamore@1113 214 SUBEQ("-="),
mcimadamore@1113 215 STAREQ("*="),
mcimadamore@1113 216 SLASHEQ("/="),
mcimadamore@1113 217 AMPEQ("&="),
mcimadamore@1113 218 BAREQ("|="),
mcimadamore@1113 219 CARETEQ("^="),
mcimadamore@1113 220 PERCENTEQ("%="),
mcimadamore@1113 221 LTLTEQ("<<="),
mcimadamore@1113 222 GTGTEQ(">>="),
mcimadamore@1113 223 GTGTGTEQ(">>>="),
mcimadamore@1113 224 MONKEYS_AT("@"),
mcimadamore@1113 225 CUSTOM;
mcimadamore@1113 226
mcimadamore@1113 227 public final String name;
mcimadamore@1113 228 public final Tag tag;
mcimadamore@1113 229
mcimadamore@1113 230 TokenKind() {
mcimadamore@1113 231 this(null, Tag.DEFAULT);
mcimadamore@1113 232 }
mcimadamore@1113 233
mcimadamore@1113 234 TokenKind(String name) {
mcimadamore@1113 235 this(name, Tag.DEFAULT);
mcimadamore@1113 236 }
mcimadamore@1113 237
mcimadamore@1113 238 TokenKind(Tag tag) {
mcimadamore@1113 239 this(null, tag);
mcimadamore@1113 240 }
mcimadamore@1113 241
mcimadamore@1113 242 TokenKind(String name, Tag tag) {
mcimadamore@1113 243 this.name = name;
mcimadamore@1113 244 this.tag = tag;
mcimadamore@1113 245 }
mcimadamore@1113 246
mcimadamore@1113 247 public String toString() {
mcimadamore@1113 248 switch (this) {
mcimadamore@1113 249 case IDENTIFIER:
mcimadamore@1113 250 return "token.identifier";
mcimadamore@1113 251 case CHARLITERAL:
mcimadamore@1113 252 return "token.character";
mcimadamore@1113 253 case STRINGLITERAL:
mcimadamore@1113 254 return "token.string";
mcimadamore@1113 255 case INTLITERAL:
mcimadamore@1113 256 return "token.integer";
mcimadamore@1113 257 case LONGLITERAL:
mcimadamore@1113 258 return "token.long-integer";
mcimadamore@1113 259 case FLOATLITERAL:
mcimadamore@1113 260 return "token.float";
mcimadamore@1113 261 case DOUBLELITERAL:
mcimadamore@1113 262 return "token.double";
mcimadamore@1113 263 case ERROR:
mcimadamore@1113 264 return "token.bad-symbol";
mcimadamore@1113 265 case EOF:
mcimadamore@1113 266 return "token.end-of-input";
mcimadamore@1113 267 case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
mcimadamore@1113 268 case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
mcimadamore@1113 269 return "'" + name + "'";
mcimadamore@1113 270 default:
mcimadamore@1113 271 return name;
mcimadamore@1113 272 }
mcimadamore@1113 273 }
mcimadamore@1113 274
mcimadamore@1113 275 public String getKind() {
mcimadamore@1113 276 return "Token";
mcimadamore@1113 277 }
mcimadamore@1113 278
mcimadamore@1113 279 public String toString(Locale locale, Messages messages) {
mcimadamore@1113 280 return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
mcimadamore@1113 281 }
mcimadamore@1113 282 }
mcimadamore@1113 283
mcimadamore@1113 284 /**
mcimadamore@1113 285 * This is the class representing a javac token. Each token has several fields
mcimadamore@1113 286 * that are set by the javac lexer (i.e. start/end position, string value, etc).
mcimadamore@1113 287 */
mcimadamore@1113 288 public static class Token {
mcimadamore@1113 289
mcimadamore@1113 290 /** tags constants **/
mcimadamore@1113 291 enum Tag {
mcimadamore@1113 292 DEFAULT,
mcimadamore@1113 293 NAMED,
mcimadamore@1113 294 STRING,
mcimadamore@1113 295 NUMERIC;
mcimadamore@1113 296 }
mcimadamore@1113 297
mcimadamore@1113 298 /** The token kind */
mcimadamore@1113 299 public final TokenKind kind;
mcimadamore@1113 300
mcimadamore@1113 301 /** The start position of this token */
mcimadamore@1113 302 public final int pos;
mcimadamore@1113 303
mcimadamore@1113 304 /** The end position of this token */
mcimadamore@1113 305 public final int endPos;
mcimadamore@1113 306
mcimadamore@1113 307 /** Is this token preceeded by a deprecated comment? */
mcimadamore@1113 308 public final boolean deprecatedFlag;
mcimadamore@1113 309
mcimadamore@1113 310 /** Is this token preceeded by a deprecated comment? */
mcimadamore@1113 311 public String docComment;
mcimadamore@1113 312
mcimadamore@1113 313 Token(TokenKind kind, int pos, int endPos,
mcimadamore@1113 314 boolean deprecatedFlag) {
mcimadamore@1113 315 this.kind = kind;
mcimadamore@1113 316 this.pos = pos;
mcimadamore@1113 317 this.endPos = endPos;
mcimadamore@1113 318 this.deprecatedFlag = deprecatedFlag;
mcimadamore@1113 319 checkKind();
mcimadamore@1113 320 }
mcimadamore@1113 321
mcimadamore@1113 322 Token[] split(Tokens tokens) {
mcimadamore@1113 323 if (kind.name.length() < 2 || kind.tag != Tag.DEFAULT) {
mcimadamore@1113 324 throw new AssertionError("Cant split" + kind);
mcimadamore@1113 325 }
mcimadamore@1113 326
mcimadamore@1113 327 TokenKind t1 = tokens.lookupKind(kind.name.substring(0, 1));
mcimadamore@1113 328 TokenKind t2 = tokens.lookupKind(kind.name.substring(1));
mcimadamore@1113 329
mcimadamore@1113 330 if (t1 == null || t2 == null) {
mcimadamore@1113 331 throw new AssertionError("Cant split - bad subtokens");
mcimadamore@1113 332 }
mcimadamore@1113 333 return new Token[] {
mcimadamore@1113 334 new Token(t1, pos, pos + t1.name.length(), deprecatedFlag),
mcimadamore@1113 335 new Token(t2, pos + t1.name.length(), endPos, false)
mcimadamore@1113 336 };
mcimadamore@1113 337 }
mcimadamore@1113 338
mcimadamore@1113 339 protected void checkKind() {
mcimadamore@1113 340 if (kind.tag != Tag.DEFAULT) {
mcimadamore@1113 341 throw new AssertionError("Bad token kind - expected " + Tag.STRING);
mcimadamore@1113 342 }
mcimadamore@1113 343 }
mcimadamore@1113 344
mcimadamore@1113 345 public Name name() {
mcimadamore@1113 346 throw new UnsupportedOperationException();
mcimadamore@1113 347 }
mcimadamore@1113 348
mcimadamore@1113 349 public String stringVal() {
mcimadamore@1113 350 throw new UnsupportedOperationException();
mcimadamore@1113 351 }
mcimadamore@1113 352
mcimadamore@1113 353 public int radix() {
mcimadamore@1113 354 throw new UnsupportedOperationException();
mcimadamore@1113 355 }
mcimadamore@1113 356 }
mcimadamore@1113 357
mcimadamore@1113 358 final static class NamedToken extends Token {
mcimadamore@1113 359 /** The name of this token */
mcimadamore@1113 360 public final Name name;
mcimadamore@1113 361
mcimadamore@1113 362 public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) {
mcimadamore@1113 363 super(kind, pos, endPos, deprecatedFlag);
mcimadamore@1113 364 this.name = name;
mcimadamore@1113 365 }
mcimadamore@1113 366
mcimadamore@1113 367 protected void checkKind() {
mcimadamore@1113 368 if (kind.tag != Tag.NAMED) {
mcimadamore@1113 369 throw new AssertionError("Bad token kind - expected " + Tag.NAMED);
mcimadamore@1113 370 }
mcimadamore@1113 371 }
mcimadamore@1113 372
mcimadamore@1113 373 @Override
mcimadamore@1113 374 public Name name() {
mcimadamore@1113 375 return name;
mcimadamore@1113 376 }
mcimadamore@1113 377 }
mcimadamore@1113 378
mcimadamore@1113 379 static class StringToken extends Token {
mcimadamore@1113 380 /** The string value of this token */
mcimadamore@1113 381 public final String stringVal;
mcimadamore@1113 382
mcimadamore@1113 383 public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) {
mcimadamore@1113 384 super(kind, pos, endPos, deprecatedFlag);
mcimadamore@1113 385 this.stringVal = stringVal;
mcimadamore@1113 386 }
mcimadamore@1113 387
mcimadamore@1113 388 protected void checkKind() {
mcimadamore@1113 389 if (kind.tag != Tag.STRING) {
mcimadamore@1113 390 throw new AssertionError("Bad token kind - expected " + Tag.STRING);
mcimadamore@1113 391 }
mcimadamore@1113 392 }
mcimadamore@1113 393
mcimadamore@1113 394 @Override
mcimadamore@1113 395 public String stringVal() {
mcimadamore@1113 396 return stringVal;
mcimadamore@1113 397 }
mcimadamore@1113 398 }
mcimadamore@1113 399
mcimadamore@1113 400 final static class NumericToken extends StringToken {
mcimadamore@1113 401 /** The 'radix' value of this token */
mcimadamore@1113 402 public final int radix;
mcimadamore@1113 403
mcimadamore@1113 404 public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) {
mcimadamore@1113 405 super(kind, pos, endPos, stringVal, deprecatedFlag);
mcimadamore@1113 406 this.radix = radix;
mcimadamore@1113 407 }
mcimadamore@1113 408
mcimadamore@1113 409 protected void checkKind() {
mcimadamore@1113 410 if (kind.tag != Tag.NUMERIC) {
mcimadamore@1113 411 throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC);
mcimadamore@1113 412 }
mcimadamore@1113 413 }
mcimadamore@1113 414
mcimadamore@1113 415 @Override
mcimadamore@1113 416 public int radix() {
mcimadamore@1113 417 return radix;
mcimadamore@1113 418 }
mcimadamore@1113 419 }
mcimadamore@1113 420
mcimadamore@1113 421 public static final Token DUMMY =
mcimadamore@1113 422 new Token(TokenKind.ERROR, 0, 0, false);
mcimadamore@1113 423 }

mercurial