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