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