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

Fri, 04 Nov 2011 12:36:40 +0000

author
mcimadamore
date
Fri, 04 Nov 2011 12:36:40 +0000
changeset 1125
56830d5cb5bb
parent 1113
d346ab55031b
child 1144
9448fe783fd2
permissions
-rw-r--r--

7104201: Refactor DocCommentScanner
Summary: Add new Comment helper class to parse contents of comments in source code
Reviewed-by: jjg

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

mercurial