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 HEXADECIMAL (LITERAL, null), 174 OCTAL_LEGACY (LITERAL, null), 175 OCTAL (LITERAL, null), 176 BINARY_NUMBER (LITERAL, null), 177 FLOATING (LITERAL, null), 178 STRING (LITERAL, null), 179 ESCSTRING (LITERAL, null), 180 EXECSTRING (LITERAL, null), 181 IDENT (LITERAL, null), 182 REGEX (LITERAL, null), 183 XML (LITERAL, null), 184 OBJECT (LITERAL, null), 185 ARRAY (LITERAL, null), 186 TEMPLATE (LITERAL, null), 187 TEMPLATE_HEAD (LITERAL, null), 188 TEMPLATE_MIDDLE(LITERAL, null), 189 TEMPLATE_TAIL (LITERAL, null), 190 191 COMMALEFT (IR, null), 192 DECPOSTFIX (IR, null), 193 INCPOSTFIX (IR, null); 194 195 /** Next token kind in token lookup table. */ 196 private TokenType next; 197 198 /** Classification of token. */ 199 private final TokenKind kind; 200 201 /** Printable name of token. */ 202 private final String name; 203 204 /** Operator precedence. */ 205 private final int precedence; 206 207 /** Left associativity */ 208 private final boolean isLeftAssociative; 209 210 /** Cache values to avoid cloning. */ 211 private static final TokenType[] values; 212 213 TokenType(final TokenKind kind, final String name) { 214 next = null; 215 this.kind = kind; 216 this.name = name; 217 precedence = 0; 218 isLeftAssociative = false; 219 } 220 221 TokenType(final TokenKind kind, final String name, final int precedence, final boolean isLeftAssociative) { 222 next = null; 223 this.kind = kind; 224 this.name = name; 225 this.precedence = precedence; 226 this.isLeftAssociative = isLeftAssociative; 227 } 228 229 /** 230 * Determines if the token has greater precedence than other. 231 * 232 * @param other Compare token. 233 * @param isLeft Is to the left of the other. 234 * 235 * @return {@code true} if greater precedence. 236 */ 237 public boolean needsParens(final TokenType other, final boolean isLeft) { 238 return other.precedence != 0 && 239 (precedence > other.precedence || 240 precedence == other.precedence && isLeftAssociative && !isLeft); 241 } 242 243 /** 244 * Determines if the type is a valid operator. 245 * 246 * @param noIn {@code true} if IN operator should be ignored. 247 * 248 * @return {@code true} if valid operator. 249 */ 250 public boolean isOperator(final boolean noIn) { 251 return kind == BINARY && (!noIn || this != IN) && precedence != 0; 252 } 253 254 255 public int getLength() { 256 assert name != null : "Token name not set"; 257 return name.length(); 258 } 259 260 public String getName() { 261 return name; 262 } 263 264 public String getNameOrType() { 265 return name == null ? super.name().toLowerCase(Locale.ENGLISH) : name; 266 } 267 268 public TokenType getNext() { 269 return next; 270 } 271 272 public void setNext(final TokenType next) { 273 this.next = next; 274 } 275 276 public TokenKind getKind() { 277 return kind; 278 } 279 280 public int getPrecedence() { 281 return precedence; 282 } 283 284 public boolean isLeftAssociative() { 285 return isLeftAssociative; 286 } 287 288 boolean startsWith(final char c) { 289 return name != null && name.length() > 0 && name.charAt(0) == c; 290 } 291 292 static TokenType[] getValues() { 293 return values; 294 } 295 296 @Override 297 public String toString() { 298 return getNameOrType(); 299 } 300 301 static { 302 // Avoid cloning of enumeration. 303 values = TokenType.values(); 304 } 305 }