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 }