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

changeset 1113
d346ab55031b
child 1125
56830d5cb5bb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Mon Oct 24 13:00:20 2011 +0100
     1.3 @@ -0,0 +1,423 @@
     1.4 +/*
     1.5 + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.javac.parser;
    1.30 +
    1.31 +import java.util.Locale;
    1.32 +
    1.33 +import com.sun.tools.javac.api.Formattable;
    1.34 +import com.sun.tools.javac.api.Messages;
    1.35 +import com.sun.tools.javac.parser.Tokens.Token.Tag;
    1.36 +import com.sun.tools.javac.util.Name;
    1.37 +import com.sun.tools.javac.util.Context;
    1.38 +import com.sun.tools.javac.util.Names;
    1.39 +
    1.40 +/** A class that defines codes/utilities for Java source tokens
    1.41 + *  returned from lexical analysis.
    1.42 + *
    1.43 + *  <p><b>This is NOT part of any supported API.
    1.44 + *  If you write code that depends on this, you do so at your own risk.
    1.45 + *  This code and its internal interfaces are subject to change or
    1.46 + *  deletion without notice.</b>
    1.47 + */
    1.48 +public class Tokens {
    1.49 +
    1.50 +    private final Names names;
    1.51 +
    1.52 +    /**
    1.53 +     * Keyword array. Maps name indices to Token.
    1.54 +     */
    1.55 +    private final TokenKind[] key;
    1.56 +
    1.57 +    /**  The number of the last entered keyword.
    1.58 +     */
    1.59 +    private int maxKey = 0;
    1.60 +
    1.61 +    /** The names of all tokens.
    1.62 +     */
    1.63 +    private Name[] tokenName = new Name[TokenKind.values().length];
    1.64 +
    1.65 +    public static final Context.Key<Tokens> tokensKey =
    1.66 +        new Context.Key<Tokens>();
    1.67 +
    1.68 +    public static Tokens instance(Context context) {
    1.69 +        Tokens instance = context.get(tokensKey);
    1.70 +        if (instance == null)
    1.71 +            instance = new Tokens(context);
    1.72 +        return instance;
    1.73 +    }
    1.74 +
    1.75 +    protected Tokens(Context context) {
    1.76 +        context.put(tokensKey, this);
    1.77 +        names = Names.instance(context);
    1.78 +
    1.79 +        for (TokenKind t : TokenKind.values()) {
    1.80 +            if (t.name != null)
    1.81 +                enterKeyword(t.name, t);
    1.82 +            else
    1.83 +                tokenName[t.ordinal()] = null;
    1.84 +        }
    1.85 +
    1.86 +        key = new TokenKind[maxKey+1];
    1.87 +        for (int i = 0; i <= maxKey; i++) key[i] = TokenKind.IDENTIFIER;
    1.88 +        for (TokenKind t : TokenKind.values()) {
    1.89 +            if (t.name != null)
    1.90 +            key[tokenName[t.ordinal()].getIndex()] = t;
    1.91 +        }
    1.92 +    }
    1.93 +
    1.94 +    private void enterKeyword(String s, TokenKind token) {
    1.95 +        Name n = names.fromString(s);
    1.96 +        tokenName[token.ordinal()] = n;
    1.97 +        if (n.getIndex() > maxKey) maxKey = n.getIndex();
    1.98 +    }
    1.99 +
   1.100 +    /**
   1.101 +     * Create a new token given a name; if the name corresponds to a token name,
   1.102 +     * a new token of the corresponding kind is returned; otherwise, an
   1.103 +     * identifier token is returned.
   1.104 +     */
   1.105 +    TokenKind lookupKind(Name name) {
   1.106 +        return (name.getIndex() > maxKey) ? TokenKind.IDENTIFIER : key[name.getIndex()];
   1.107 +    }
   1.108 +
   1.109 +    TokenKind lookupKind(String name) {
   1.110 +        return lookupKind(names.fromString(name));
   1.111 +    }
   1.112 +
   1.113 +    /**
   1.114 +     * This enum defines all tokens used by the javac scanner. A token is
   1.115 +     * optionally associated with a name.
   1.116 +     */
   1.117 +    public enum TokenKind implements Formattable {
   1.118 +        EOF(),
   1.119 +        ERROR(),
   1.120 +        IDENTIFIER(Tag.NAMED),
   1.121 +        ABSTRACT("abstract"),
   1.122 +        ASSERT("assert", Tag.NAMED),
   1.123 +        BOOLEAN("boolean", Tag.NAMED),
   1.124 +        BREAK("break"),
   1.125 +        BYTE("byte", Tag.NAMED),
   1.126 +        CASE("case"),
   1.127 +        CATCH("catch"),
   1.128 +        CHAR("char", Tag.NAMED),
   1.129 +        CLASS("class"),
   1.130 +        CONST("const"),
   1.131 +        CONTINUE("continue"),
   1.132 +        DEFAULT("default"),
   1.133 +        DO("do"),
   1.134 +        DOUBLE("double", Tag.NAMED),
   1.135 +        ELSE("else"),
   1.136 +        ENUM("enum", Tag.NAMED),
   1.137 +        EXTENDS("extends"),
   1.138 +        FINAL("final"),
   1.139 +        FINALLY("finally"),
   1.140 +        FLOAT("float", Tag.NAMED),
   1.141 +        FOR("for"),
   1.142 +        GOTO("goto"),
   1.143 +        IF("if"),
   1.144 +        IMPLEMENTS("implements"),
   1.145 +        IMPORT("import"),
   1.146 +        INSTANCEOF("instanceof"),
   1.147 +        INT("int", Tag.NAMED),
   1.148 +        INTERFACE("interface"),
   1.149 +        LONG("long", Tag.NAMED),
   1.150 +        NATIVE("native"),
   1.151 +        NEW("new"),
   1.152 +        PACKAGE("package"),
   1.153 +        PRIVATE("private"),
   1.154 +        PROTECTED("protected"),
   1.155 +        PUBLIC("public"),
   1.156 +        RETURN("return"),
   1.157 +        SHORT("short", Tag.NAMED),
   1.158 +        STATIC("static"),
   1.159 +        STRICTFP("strictfp"),
   1.160 +        SUPER("super", Tag.NAMED),
   1.161 +        SWITCH("switch"),
   1.162 +        SYNCHRONIZED("synchronized"),
   1.163 +        THIS("this", Tag.NAMED),
   1.164 +        THROW("throw"),
   1.165 +        THROWS("throws"),
   1.166 +        TRANSIENT("transient"),
   1.167 +        TRY("try"),
   1.168 +        VOID("void", Tag.NAMED),
   1.169 +        VOLATILE("volatile"),
   1.170 +        WHILE("while"),
   1.171 +        INTLITERAL(Tag.NUMERIC),
   1.172 +        LONGLITERAL(Tag.NUMERIC),
   1.173 +        FLOATLITERAL(Tag.NUMERIC),
   1.174 +        DOUBLELITERAL(Tag.NUMERIC),
   1.175 +        CHARLITERAL(Tag.NUMERIC),
   1.176 +        STRINGLITERAL(Tag.STRING),
   1.177 +        TRUE("true", Tag.NAMED),
   1.178 +        FALSE("false", Tag.NAMED),
   1.179 +        NULL("null", Tag.NAMED),
   1.180 +        LPAREN("("),
   1.181 +        RPAREN(")"),
   1.182 +        LBRACE("{"),
   1.183 +        RBRACE("}"),
   1.184 +        LBRACKET("["),
   1.185 +        RBRACKET("]"),
   1.186 +        SEMI(";"),
   1.187 +        COMMA(","),
   1.188 +        DOT("."),
   1.189 +        ELLIPSIS("..."),
   1.190 +        EQ("="),
   1.191 +        GT(">"),
   1.192 +        LT("<"),
   1.193 +        BANG("!"),
   1.194 +        TILDE("~"),
   1.195 +        QUES("?"),
   1.196 +        COLON(":"),
   1.197 +        EQEQ("=="),
   1.198 +        LTEQ("<="),
   1.199 +        GTEQ(">="),
   1.200 +        BANGEQ("!="),
   1.201 +        AMPAMP("&&"),
   1.202 +        BARBAR("||"),
   1.203 +        PLUSPLUS("++"),
   1.204 +        SUBSUB("--"),
   1.205 +        PLUS("+"),
   1.206 +        SUB("-"),
   1.207 +        STAR("*"),
   1.208 +        SLASH("/"),
   1.209 +        AMP("&"),
   1.210 +        BAR("|"),
   1.211 +        CARET("^"),
   1.212 +        PERCENT("%"),
   1.213 +        LTLT("<<"),
   1.214 +        GTGT(">>"),
   1.215 +        GTGTGT(">>>"),
   1.216 +        PLUSEQ("+="),
   1.217 +        SUBEQ("-="),
   1.218 +        STAREQ("*="),
   1.219 +        SLASHEQ("/="),
   1.220 +        AMPEQ("&="),
   1.221 +        BAREQ("|="),
   1.222 +        CARETEQ("^="),
   1.223 +        PERCENTEQ("%="),
   1.224 +        LTLTEQ("<<="),
   1.225 +        GTGTEQ(">>="),
   1.226 +        GTGTGTEQ(">>>="),
   1.227 +        MONKEYS_AT("@"),
   1.228 +        CUSTOM;
   1.229 +
   1.230 +        public final String name;
   1.231 +        public final Tag tag;
   1.232 +
   1.233 +        TokenKind() {
   1.234 +            this(null, Tag.DEFAULT);
   1.235 +        }
   1.236 +
   1.237 +        TokenKind(String name) {
   1.238 +            this(name, Tag.DEFAULT);
   1.239 +        }
   1.240 +
   1.241 +        TokenKind(Tag tag) {
   1.242 +            this(null, tag);
   1.243 +        }
   1.244 +
   1.245 +        TokenKind(String name, Tag tag) {
   1.246 +            this.name = name;
   1.247 +            this.tag = tag;
   1.248 +        }
   1.249 +
   1.250 +        public String toString() {
   1.251 +            switch (this) {
   1.252 +            case IDENTIFIER:
   1.253 +                return "token.identifier";
   1.254 +            case CHARLITERAL:
   1.255 +                return "token.character";
   1.256 +            case STRINGLITERAL:
   1.257 +                return "token.string";
   1.258 +            case INTLITERAL:
   1.259 +                return "token.integer";
   1.260 +            case LONGLITERAL:
   1.261 +                return "token.long-integer";
   1.262 +            case FLOATLITERAL:
   1.263 +                return "token.float";
   1.264 +            case DOUBLELITERAL:
   1.265 +                return "token.double";
   1.266 +            case ERROR:
   1.267 +                return "token.bad-symbol";
   1.268 +            case EOF:
   1.269 +                return "token.end-of-input";
   1.270 +            case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
   1.271 +            case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
   1.272 +                return "'" + name + "'";
   1.273 +            default:
   1.274 +                return name;
   1.275 +            }
   1.276 +        }
   1.277 +
   1.278 +        public String getKind() {
   1.279 +            return "Token";
   1.280 +        }
   1.281 +
   1.282 +        public String toString(Locale locale, Messages messages) {
   1.283 +            return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
   1.284 +        }
   1.285 +    }
   1.286 +
   1.287 +    /**
   1.288 +     * This is the class representing a javac token. Each token has several fields
   1.289 +     * that are set by the javac lexer (i.e. start/end position, string value, etc).
   1.290 +     */
   1.291 +    public static class Token {
   1.292 +
   1.293 +        /** tags constants **/
   1.294 +        enum Tag {
   1.295 +            DEFAULT,
   1.296 +            NAMED,
   1.297 +            STRING,
   1.298 +            NUMERIC;
   1.299 +        }
   1.300 +
   1.301 +        /** The token kind */
   1.302 +        public final TokenKind kind;
   1.303 +
   1.304 +        /** The start position of this token */
   1.305 +        public final int pos;
   1.306 +
   1.307 +        /** The end position of this token */
   1.308 +        public final int endPos;
   1.309 +
   1.310 +        /** Is this token preceeded by a deprecated comment? */
   1.311 +        public final boolean deprecatedFlag;
   1.312 +
   1.313 +        /** Is this token preceeded by a deprecated comment? */
   1.314 +        public String docComment;
   1.315 +
   1.316 +        Token(TokenKind kind, int pos, int endPos,
   1.317 +                boolean deprecatedFlag) {
   1.318 +            this.kind = kind;
   1.319 +            this.pos = pos;
   1.320 +            this.endPos = endPos;
   1.321 +            this.deprecatedFlag = deprecatedFlag;
   1.322 +            checkKind();
   1.323 +        }
   1.324 +
   1.325 +        Token[] split(Tokens tokens) {
   1.326 +            if (kind.name.length() < 2 || kind.tag != Tag.DEFAULT) {
   1.327 +                throw new AssertionError("Cant split" + kind);
   1.328 +            }
   1.329 +
   1.330 +            TokenKind t1 = tokens.lookupKind(kind.name.substring(0, 1));
   1.331 +            TokenKind t2 = tokens.lookupKind(kind.name.substring(1));
   1.332 +
   1.333 +            if (t1 == null || t2 == null) {
   1.334 +                throw new AssertionError("Cant split - bad subtokens");
   1.335 +            }
   1.336 +            return new Token[] {
   1.337 +                new Token(t1, pos, pos + t1.name.length(), deprecatedFlag),
   1.338 +                new Token(t2, pos + t1.name.length(), endPos, false)
   1.339 +            };
   1.340 +        }
   1.341 +
   1.342 +        protected void checkKind() {
   1.343 +            if (kind.tag != Tag.DEFAULT) {
   1.344 +                throw new AssertionError("Bad token kind - expected " + Tag.STRING);
   1.345 +            }
   1.346 +        }
   1.347 +
   1.348 +        public Name name() {
   1.349 +            throw new UnsupportedOperationException();
   1.350 +        }
   1.351 +
   1.352 +        public String stringVal() {
   1.353 +            throw new UnsupportedOperationException();
   1.354 +        }
   1.355 +
   1.356 +        public int radix() {
   1.357 +            throw new UnsupportedOperationException();
   1.358 +        }
   1.359 +    }
   1.360 +
   1.361 +    final static class NamedToken extends Token {
   1.362 +        /** The name of this token */
   1.363 +        public final Name name;
   1.364 +
   1.365 +        public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) {
   1.366 +            super(kind, pos, endPos, deprecatedFlag);
   1.367 +            this.name = name;
   1.368 +        }
   1.369 +
   1.370 +        protected void checkKind() {
   1.371 +            if (kind.tag != Tag.NAMED) {
   1.372 +                throw new AssertionError("Bad token kind - expected " + Tag.NAMED);
   1.373 +            }
   1.374 +        }
   1.375 +
   1.376 +        @Override
   1.377 +        public Name name() {
   1.378 +            return name;
   1.379 +        }
   1.380 +    }
   1.381 +
   1.382 +    static class StringToken extends Token {
   1.383 +        /** The string value of this token */
   1.384 +        public final String stringVal;
   1.385 +
   1.386 +        public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) {
   1.387 +            super(kind, pos, endPos, deprecatedFlag);
   1.388 +            this.stringVal = stringVal;
   1.389 +        }
   1.390 +
   1.391 +        protected void checkKind() {
   1.392 +            if (kind.tag != Tag.STRING) {
   1.393 +                throw new AssertionError("Bad token kind - expected " + Tag.STRING);
   1.394 +            }
   1.395 +        }
   1.396 +
   1.397 +        @Override
   1.398 +        public String stringVal() {
   1.399 +            return stringVal;
   1.400 +        }
   1.401 +    }
   1.402 +
   1.403 +    final static class NumericToken extends StringToken {
   1.404 +        /** The 'radix' value of this token */
   1.405 +        public final int radix;
   1.406 +
   1.407 +        public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) {
   1.408 +            super(kind, pos, endPos, stringVal, deprecatedFlag);
   1.409 +            this.radix = radix;
   1.410 +        }
   1.411 +
   1.412 +        protected void checkKind() {
   1.413 +            if (kind.tag != Tag.NUMERIC) {
   1.414 +                throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC);
   1.415 +            }
   1.416 +        }
   1.417 +
   1.418 +        @Override
   1.419 +        public int radix() {
   1.420 +            return radix;
   1.421 +        }
   1.422 +    }
   1.423 +
   1.424 +    public static final Token DUMMY =
   1.425 +                new Token(TokenKind.ERROR, 0, 0, false);
   1.426 +}

mercurial