1 /*
   2  * Copyright (c) 2010, 2013, 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  */
  25 
  26 package jdk.nashorn.internal.parser;
  27 
  28 import static jdk.nashorn.internal.parser.TokenKind.BINARY;
  29 import static jdk.nashorn.internal.parser.TokenKind.BRACKET;
  30 import static jdk.nashorn.internal.parser.TokenKind.FUTURE;
  31 import static jdk.nashorn.internal.parser.TokenKind.FUTURESTRICT;
  32 import static jdk.nashorn.internal.parser.TokenKind.IR;
  33 import static jdk.nashorn.internal.parser.TokenKind.KEYWORD;
  34 import static jdk.nashorn.internal.parser.TokenKind.LITERAL;
  35 import static jdk.nashorn.internal.parser.TokenKind.SPECIAL;
  36 import static jdk.nashorn.internal.parser.TokenKind.UNARY;
  37 
  38 /**
  39  * Description of all the JavaScript tokens.
  40  */
  41 @SuppressWarnings("javadoc")
  42 public enum TokenType {
  43     ERROR          (SPECIAL,  null),
  44     EOF            (SPECIAL,  null),
  45     EOL            (SPECIAL,  null),
  46 
  47     NOT            (UNARY,   "!",    14, false),
  48     NE             (BINARY,  "!=",    9, true),
  49     NE_STRICT      (BINARY,  "!==",   9, true),
  50     MOD            (BINARY,  "%",    13, true),
  51     ASSIGN_MOD     (BINARY,  "%=",    2, false),
  52     BIT_AND        (BINARY,  "&",     8, true),
  53     AND            (BINARY,  "&&",    5, true),
  54     ASSIGN_BIT_AND (BINARY,  "&=",    2, false),
  55     LPAREN         (BRACKET, "(",    16, true),
  56     RPAREN         (BRACKET, ")",     0, true),
  57     MUL            (BINARY,  "*",    13, true),
  58     ASSIGN_MUL     (BINARY,  "*=",    2, false),
  59     ADD            (BINARY,  "+",    12, true),
  60     INCPREFIX      (UNARY,   "++",   15, true),
  61     ASSIGN_ADD     (BINARY,  "+=",    2, false),
  62     COMMARIGHT     (BINARY,  ",",     1, true),
  63     SUB            (BINARY,  "-",    12, true),
  64     DECPREFIX      (UNARY,   "--",   15, true),
  65     ASSIGN_SUB     (BINARY,  "-=",    2, false),
  66     PERIOD         (BRACKET, ".",    17, true),
  67     DIV            (BINARY,  "/",    13, true),
  68     ASSIGN_DIV     (BINARY,  "/=",    2, false),
  69     COLON          (BINARY,  ":"),
  70     SEMICOLON      (BINARY,  ";"),
  71     LT             (BINARY,  "<",    10, true),
  72     SHL            (BINARY,  "<<",   11, true),
  73     ASSIGN_SHL     (BINARY,  "<<=",   2, false),
  74     LE             (BINARY,  "<=",   10, true),
  75     ASSIGN         (BINARY,  "=",     2, false),
  76     EQ             (BINARY,  "==",    9, true),
  77     EQ_STRICT      (BINARY,  "===",   9, true),
  78     BIND           (BINARY,  "=>",    9, true),
  79     GT             (BINARY,  ">",    10, true),
  80     GE             (BINARY,  ">=",   10, true),
  81     SAR            (BINARY,  ">>",   11, true),
  82     ASSIGN_SAR     (BINARY,  ">>=",   2, false),
  83     SHR            (BINARY,  ">>>",  11, true),
  84     ASSIGN_SHR     (BINARY,  ">>>=",  2, false),
  85     TERNARY        (BINARY,  "?",     3, false),
  86     LBRACKET       (BRACKET, "[",    17, true),
  87     RBRACKET       (BRACKET, "]",     0, true),
  88     BIT_XOR        (BINARY,  "^",     7, true),
  89     ASSIGN_BIT_XOR (BINARY,  "^=",    2, false),
  90     LBRACE         (BRACKET,  "{"),
  91     BIT_OR         (BINARY,  "|",     6, true),
  92     ASSIGN_BIT_OR  (BINARY,  "|=",    2, false),
  93     OR             (BINARY,  "||",    4, true),
  94     RBRACE         (BRACKET, "}"),
  95     BIT_NOT        (BINARY,  "~",    14, false),
  96 
  97     // ECMA 7.6.1.1 Keywords, 7.6.1.2 Future Reserved Words.
  98     // All other Java keywords are commented out.
  99 
 100 //  ABSTRACT       (FUTURE,   "abstract"),
 101 //  BOOLEAN        (FUTURE,   "boolean"),
 102     BREAK          (KEYWORD,  "break"),
 103 //  BYTE           (FUTURE,   "byte"),
 104     CASE           (KEYWORD,  "case"),
 105     CATCH          (KEYWORD,  "catch"),
 106 //  CHAR           (FUTURE,   "char"),
 107     CLASS          (FUTURE,   "class"),
 108     CONST          (FUTURE,  "const"),
 109     CONTINUE       (KEYWORD,  "continue"),
 110     DEBUGGER       (KEYWORD,  "debugger"),
 111     DEFAULT        (KEYWORD,  "default"),
 112     DELETE         (UNARY,    "delete",     14, false),
 113     DO             (KEYWORD,  "do"),
 114 //  DOUBLE         (FUTURE,   "double"),
 115 //  EACH           (KEYWORD,  "each"),  // Contextual.
 116     ELSE           (KEYWORD,  "else"),
 117     ENUM           (FUTURE,   "enum"),
 118     EXPORT         (FUTURE,   "export"),
 119     EXTENDS        (FUTURE,   "extends"),
 120     FALSE          (LITERAL,  "false"),
 121 //  FINAL          (FUTURE,   "final"),
 122     FINALLY        (KEYWORD,  "finally"),
 123 //  FLOAT          (FUTURE,   "float"),
 124     FOR            (KEYWORD,  "for"),
 125     FUNCTION       (KEYWORD,  "function"),
 126 //  GET            (KEYWORD,  "get"), // Contextual.
 127 //  GOTO           (FUTURE,   "goto"),
 128     IF             (KEYWORD,   "if"),
 129     IMPLEMENTS     (FUTURESTRICT,   "implements"),
 130     IMPORT         (FUTURE,   "import"),
 131     IN             (BINARY,   "in",         10, true),
 132     INSTANCEOF     (BINARY,   "instanceof", 10, true),
 133 //  INT            (FUTURE,   "int"),
 134     INTERFACE      (FUTURESTRICT,   "interface"),
 135     LET            (FUTURESTRICT,   "let"),
 136 //  LONG           (FUTURE,   "long"),
 137 //  NATIVE         (FUTURE,   "native"),
 138     NEW            (UNARY,    "new",        17, false),
 139     NULL           (LITERAL,  "null"),
 140     PACKAGE        (FUTURESTRICT,   "package"),
 141     PRIVATE        (FUTURESTRICT,   "private"),
 142     PROTECTED      (FUTURESTRICT,   "protected"),
 143     PUBLIC         (FUTURESTRICT,   "public"),
 144     RETURN         (KEYWORD,  "return"),
 145 //  SET            (KEYWORD,  "set"), // Contextual.
 146 //  SHORT          (FUTURE,   "short"),
 147     STATIC         (FUTURESTRICT,   "static"),
 148     SUPER          (FUTURE,   "super"),
 149     SWITCH         (KEYWORD,  "switch"),
 150 //  SYNCHRONIZED   (FUTURE,   "synchronized"),
 151     THIS           (KEYWORD,  "this"),
 152     THROW          (KEYWORD,  "throw"),
 153 //  THROWS         (FUTURE,   "throws"),
 154 //  TRANSIENT      (FUTURE,   "transient"),
 155     TRUE           (LITERAL,  "true"),
 156     TRY            (KEYWORD,  "try"),
 157     TYPEOF         (UNARY,    "typeof",     14, false),
 158     VAR            (KEYWORD,  "var"),
 159     VOID           (UNARY,    "void",       14, false),
 160 //  VOLATILE       (FUTURE,   "volatile"),
 161     WHILE          (KEYWORD,  "while"),
 162     WITH           (KEYWORD,  "with"),
 163     YIELD          (FUTURESTRICT,  "yield"),
 164 
 165     DECIMAL        (LITERAL,  null),
 166     OCTAL          (LITERAL,  null),
 167     HEXADECIMAL    (LITERAL,  null),
 168     FLOATING       (LITERAL,  null),
 169     STRING         (LITERAL,  null),
 170     ESCSTRING      (LITERAL,  null),
 171     EXECSTRING     (LITERAL,  null),
 172     IDENT          (LITERAL,  null),
 173     REGEX          (LITERAL,  null),
 174     XML            (LITERAL,  null),
 175     OBJECT         (LITERAL,  null),
 176     ARRAY          (LITERAL,  null),
 177 
 178     COMMALEFT      (IR,       null),
 179     CONVERT        (IR,       null),
 180     DISCARD        (IR,       null),
 181     DECPOSTFIX     (IR,       null),
 182     INCPOSTFIX     (IR,       null);
 183 
 184     /** Next token kind in token lookup table. */
 185     private TokenType next;
 186 
 187     /** Classification of token. */
 188     private final TokenKind kind;
 189 
 190     /** Printable name of token. */
 191     private final String name;
 192 
 193     /** Operator precedence. */
 194     private final int precedence;
 195 
 196     /** Left associativity */
 197     private final boolean isLeftAssociative;
 198 
 199     /** Cache values to avoid cloning. */
 200     private static final TokenType[] values;
 201 
 202     TokenType(final TokenKind kind, final String name) {
 203         next              = null;
 204         this.kind         = kind;
 205         this.name         = name;
 206         precedence        = 0;
 207         isLeftAssociative = false;
 208     }
 209 
 210     TokenType(final TokenKind kind, final String name, final int precedence, final boolean isLeftAssociative) {
 211         next                   = null;
 212         this.kind              = kind;
 213         this.name              = name;
 214         this.precedence        = precedence;
 215         this.isLeftAssociative = isLeftAssociative;
 216     }
 217 
 218     /**
 219      * Determines if the token has greater precedence than other.
 220      * @param other  Compare token.
 221      * @param isLeft Is to the left of the other.
 222      * @return True if greater precedence.
 223      */
 224     public boolean needsParens(final TokenType other, final boolean isLeft) {
 225         return other.precedence != 0 &&
 226                (precedence > other.precedence ||
 227                precedence == other.precedence && isLeftAssociative && !isLeft);
 228     }
 229 
 230     /**
 231      * Determines if the type is a valid operator.
 232      * @param noIn TRUE if IN operator should be ignored.
 233      * @return TRUE if valid operator.
 234      */
 235     public boolean isOperator(final boolean noIn) {
 236         return kind == BINARY && (!noIn || this != IN) && precedence != 0;
 237     }
 238 
 239     /**
 240      * Accessors.
 241      */
 242     public int getLength() {
 243         assert name != null : "Token name not set";
 244         return name.length();
 245     }
 246 
 247     public String getName() {
 248         return name;
 249     }
 250 
 251     public String getNameOrType() {
 252         return name == null ? super.name().toLowerCase() : name;
 253     }
 254 
 255     public TokenType getNext() {
 256         return next;
 257     }
 258 
 259     public void setNext(final TokenType next) {
 260         this.next = next;
 261     }
 262 
 263     public TokenKind getKind() {
 264         return kind;
 265     }
 266 
 267     public int getPrecedence() {
 268         return precedence;
 269     }
 270 
 271     public boolean isLeftAssociative() {
 272         return isLeftAssociative;
 273     }
 274 
 275     boolean startsWith(final char c) {
 276         return name != null && name.length() > 0 && name.charAt(0) == c;
 277     }
 278 
 279     static TokenType[] getValues() {
 280        return values;
 281     }
 282 
 283     @Override
 284     public String toString() {
 285         return name;
 286     }
 287 
 288     static {
 289         // Avoid cloning of enumeration.
 290         values = TokenType.values();
 291     }
 292 }