1/*
2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <limits.h>
29#include <stdint.h>
30
31namespace JSC {
32
33class Identifier;
34
35enum {
36 // Token Bitfield: 0b000000000RTE000IIIIPPPPKUXXXXXXX
37 // R = right-associative bit
38 // T = unterminated error flag
39 // E = error flag
40 // I = binary operator allows 'in'
41 // P = binary operator precedence
42 // K = keyword flag
43 // U = unary operator flag
44 //
45 // We must keep the upper 8bit (1byte) region empty. JSTokenType must be 24bits.
46 UnaryOpTokenFlag = 128,
47 KeywordTokenFlag = 256,
48 BinaryOpTokenPrecedenceShift = 9,
49 BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
50 BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift,
51 ErrorTokenFlag = 1 << (BinaryOpTokenAllowsInPrecedenceAdditionalShift + BinaryOpTokenPrecedenceShift + 7),
52 UnterminatedErrorTokenFlag = ErrorTokenFlag << 1,
53 RightAssociativeBinaryOpTokenFlag = UnterminatedErrorTokenFlag << 1
54};
55
56#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
57#define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))
58
59enum JSTokenType {
60 NULLTOKEN = KeywordTokenFlag,
61 TRUETOKEN,
62 FALSETOKEN,
63 BREAK,
64 CASE,
65 DEFAULT,
66 FOR,
67 NEW,
68 VAR,
69 CONSTTOKEN,
70 CONTINUE,
71 FUNCTION,
72 RETURN,
73 IF,
74 THISTOKEN,
75 DO,
76 WHILE,
77 SWITCH,
78 WITH,
79 RESERVED,
80 RESERVED_IF_STRICT,
81 THROW,
82 TRY,
83 CATCH,
84 FINALLY,
85 DEBUGGER,
86 ELSE,
87 IMPORT,
88 EXPORT,
89 CLASSTOKEN,
90 EXTENDS,
91 SUPER,
92
93 // Contextual keywords
94
95 LET,
96 YIELD,
97 AWAIT,
98
99 FirstContextualKeywordToken = LET,
100 LastContextualKeywordToken = AWAIT,
101 FirstSafeContextualKeywordToken = AWAIT,
102 LastSafeContextualKeywordToken = LastContextualKeywordToken,
103
104 OPENBRACE = 0,
105 CLOSEBRACE,
106 OPENPAREN,
107 CLOSEPAREN,
108 OPENBRACKET,
109 CLOSEBRACKET,
110 COMMA,
111 QUESTION,
112 BACKQUOTE,
113 INTEGER,
114 DOUBLE,
115 BIGINT,
116 IDENT,
117 STRING,
118 TEMPLATE,
119 REGEXP,
120 SEMICOLON,
121 COLON,
122 DOT,
123 EOFTOK,
124 EQUAL,
125 PLUSEQUAL,
126 MINUSEQUAL,
127 MULTEQUAL,
128 DIVEQUAL,
129 LSHIFTEQUAL,
130 RSHIFTEQUAL,
131 URSHIFTEQUAL,
132 ANDEQUAL,
133 MODEQUAL,
134 POWEQUAL,
135 XOREQUAL,
136 OREQUAL,
137 DOTDOTDOT,
138 ARROWFUNCTION,
139 LastUntaggedToken,
140
141 // Begin tagged tokens
142 PLUSPLUS = 0 | UnaryOpTokenFlag,
143 MINUSMINUS = 1 | UnaryOpTokenFlag,
144 AUTOPLUSPLUS = 2 | UnaryOpTokenFlag,
145 AUTOMINUSMINUS = 3 | UnaryOpTokenFlag,
146 EXCLAMATION = 4 | UnaryOpTokenFlag,
147 TILDE = 5 | UnaryOpTokenFlag,
148 TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag,
149 VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
150 DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
151 OR = 0 | BINARY_OP_PRECEDENCE(1),
152 AND = 1 | BINARY_OP_PRECEDENCE(2),
153 BITOR = 2 | BINARY_OP_PRECEDENCE(3),
154 BITXOR = 3 | BINARY_OP_PRECEDENCE(4),
155 BITAND = 4 | BINARY_OP_PRECEDENCE(5),
156 EQEQ = 5 | BINARY_OP_PRECEDENCE(6),
157 NE = 6 | BINARY_OP_PRECEDENCE(6),
158 STREQ = 7 | BINARY_OP_PRECEDENCE(6),
159 STRNEQ = 8 | BINARY_OP_PRECEDENCE(6),
160 LT = 9 | BINARY_OP_PRECEDENCE(7),
161 GT = 10 | BINARY_OP_PRECEDENCE(7),
162 LE = 11 | BINARY_OP_PRECEDENCE(7),
163 GE = 12 | BINARY_OP_PRECEDENCE(7),
164 INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7) | KeywordTokenFlag,
165 INTOKEN = 14 | IN_OP_PRECEDENCE(7) | KeywordTokenFlag,
166 LSHIFT = 15 | BINARY_OP_PRECEDENCE(8),
167 RSHIFT = 16 | BINARY_OP_PRECEDENCE(8),
168 URSHIFT = 17 | BINARY_OP_PRECEDENCE(8),
169 PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
170 MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
171 TIMES = 20 | BINARY_OP_PRECEDENCE(10),
172 DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
173 MOD = 22 | BINARY_OP_PRECEDENCE(10),
174 POW = 23 | BINARY_OP_PRECEDENCE(11) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
175 ERRORTOK = 0 | ErrorTokenFlag,
176 UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
177 INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | ErrorTokenFlag,
178 UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 2 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
179 INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | ErrorTokenFlag,
180 UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
181 UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
182 UNTERMINATED_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
183 INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag,
184 UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
185 INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
186 INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag,
187 UNTERMINATED_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
188 UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
189 UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
190 UNTERMINATED_REGEXP_LITERAL_ERRORTOK = 14 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
191 INVALID_TEMPLATE_LITERAL_ERRORTOK = 15 | ErrorTokenFlag,
192 UNEXPECTED_ESCAPE_ERRORTOK = 16 | ErrorTokenFlag,
193};
194static_assert(static_cast<unsigned>(POW) <= 0x00ffffffU, "JSTokenType must be 24bits.");
195
196struct JSTextPosition {
197 JSTextPosition() = default;
198 JSTextPosition(int _line, int _offset, int _lineStartOffset) : line(_line), offset(_offset), lineStartOffset(_lineStartOffset) { }
199
200 JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); }
201 JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); }
202 JSTextPosition operator-(int adjustment) const { return *this + (- adjustment); }
203 JSTextPosition operator-(unsigned adjustment) const { return *this + (- static_cast<int>(adjustment)); }
204
205 operator int() const { return offset; }
206
207 bool operator==(const JSTextPosition& other) const
208 {
209 return line == other.line
210 && offset == other.offset
211 && lineStartOffset == other.lineStartOffset;
212 }
213 bool operator!=(const JSTextPosition& other) const
214 {
215 return !(*this == other);
216 }
217
218 int line { 0 };
219 int offset { 0 };
220 int lineStartOffset { 0 };
221};
222
223union JSTokenData {
224 struct {
225 const Identifier* cooked;
226 const Identifier* raw;
227 bool isTail;
228 };
229 struct {
230 uint32_t line;
231 uint32_t offset;
232 uint32_t lineStartOffset;
233 };
234 double doubleValue;
235 struct {
236 const Identifier* ident;
237 bool escaped;
238 };
239 struct {
240 const Identifier* bigIntString;
241 uint8_t radix;
242 };
243 struct {
244 const Identifier* pattern;
245 const Identifier* flags;
246 };
247};
248
249struct JSTokenLocation {
250 JSTokenLocation() = default;
251
252 int line { 0 };
253 unsigned lineStartOffset { 0 };
254 unsigned startOffset { 0 };
255 unsigned endOffset { 0 };
256};
257
258struct JSToken {
259 JSTokenType m_type { ERRORTOK };
260 JSTokenData m_data { { nullptr, nullptr, false } };
261 JSTokenLocation m_location;
262 JSTextPosition m_startPosition;
263 JSTextPosition m_endPosition;
264};
265
266ALWAYS_INLINE bool isUpdateOp(JSTokenType token)
267{
268 return token >= PLUSPLUS && token <= AUTOMINUSMINUS;
269}
270
271ALWAYS_INLINE bool isUnaryOp(JSTokenType token)
272{
273 return token & UnaryOpTokenFlag;
274}
275
276} // namespace JSC
277