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 26package jdk.nashorn.internal.parser; 27 28import static jdk.nashorn.internal.parser.TokenKind.BINARY; 29import static jdk.nashorn.internal.parser.TokenKind.BRACKET; 30import static jdk.nashorn.internal.parser.TokenKind.FUTURE; 31import static jdk.nashorn.internal.parser.TokenKind.FUTURESTRICT; 32import static jdk.nashorn.internal.parser.TokenKind.IR; 33import static jdk.nashorn.internal.parser.TokenKind.KEYWORD; 34import static jdk.nashorn.internal.parser.TokenKind.LITERAL; 35import static jdk.nashorn.internal.parser.TokenKind.SPECIAL; 36import static jdk.nashorn.internal.parser.TokenKind.UNARY; 37 38import java.util.Locale; 39 40/** 41 * Description of all the JavaScript tokens. 42 */ 43@SuppressWarnings("javadoc") 44public 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 COMMALEFT (IR, null), 195 DECPOSTFIX (IR, null), 196 INCPOSTFIX (IR, null), 197 SPREAD_ARGUMENT(IR, null), 198 SPREAD_ARRAY (IR, null), 199 YIELD_STAR (IR, null); 200 201 /** Next token kind in token lookup table. */ 202 private TokenType next; 203 204 /** Classification of token. */ 205 private final TokenKind kind; 206 207 /** Printable name of token. */ 208 private final String name; 209 210 /** Operator precedence. */ 211 private final int precedence; 212 213 /** Left associativity */ 214 private final boolean isLeftAssociative; 215 216 /** Cache values to avoid cloning. */ 217 private static final TokenType[] values; 218 219 TokenType(final TokenKind kind, final String name) { 220 next = null; 221 this.kind = kind; 222 this.name = name; 223 precedence = 0; 224 isLeftAssociative = false; 225 } 226 227 TokenType(final TokenKind kind, final String name, final int precedence, final boolean isLeftAssociative) { 228 next = null; 229 this.kind = kind; 230 this.name = name; 231 this.precedence = precedence; 232 this.isLeftAssociative = isLeftAssociative; 233 } 234 235 /** 236 * Determines if the token has greater precedence than other. 237 * 238 * @param other Compare token. 239 * @param isLeft Is to the left of the other. 240 * 241 * @return {@code true} if greater precedence. 242 */ 243 public boolean needsParens(final TokenType other, final boolean isLeft) { 244 return other.precedence != 0 && 245 (precedence > other.precedence || 246 precedence == other.precedence && isLeftAssociative && !isLeft); 247 } 248 249 /** 250 * Determines if the type is a valid operator. 251 * 252 * @param noIn {@code true} if IN operator should be ignored. 253 * 254 * @return {@code true} if valid operator. 255 */ 256 public boolean isOperator(final boolean noIn) { 257 return kind == BINARY && (!noIn || this != IN) && precedence != 0; 258 } 259 260 public int getLength() { 261 assert name != null : "Token name not set"; 262 return name.length(); 263 } 264 265 public String getName() { 266 return name; 267 } 268 269 public String getNameOrType() { 270 return name == null ? super.name().toLowerCase(Locale.ENGLISH) : name; 271 } 272 273 public TokenType getNext() { 274 return next; 275 } 276 277 public void setNext(final TokenType next) { 278 this.next = next; 279 } 280 281 public TokenKind getKind() { 282 return kind; 283 } 284 285 public int getPrecedence() { 286 return precedence; 287 } 288 289 public boolean isLeftAssociative() { 290 return isLeftAssociative; 291 } 292 293 boolean startsWith(final char c) { 294 return name != null && name.length() > 0 && name.charAt(0) == c; 295 } 296 297 static TokenType[] getValues() { 298 return values; 299 } 300 301 @Override 302 public String toString() { 303 return getNameOrType(); 304 } 305 306 static { 307 // Avoid cloning of enumeration. 308 values = TokenType.values(); 309 } 310} 311