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