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    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}
309