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