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 QUESTIONDOT,
140 LastUntaggedToken,
141
142 // Begin tagged tokens
143 PLUSPLUS = 0 | UnaryOpTokenFlag,
144 MINUSMINUS = 1 | UnaryOpTokenFlag,
145 AUTOPLUSPLUS = 2 | UnaryOpTokenFlag,
146 AUTOMINUSMINUS = 3 | UnaryOpTokenFlag,
147 EXCLAMATION = 4 | UnaryOpTokenFlag,
148 TILDE = 5 | UnaryOpTokenFlag,
149 TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag,
150 VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
151 DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
152 COALESCE = 0 | BINARY_OP_PRECEDENCE(1),
153 OR = 0 | BINARY_OP_PRECEDENCE(2),
154 AND = 0 | BINARY_OP_PRECEDENCE(3),
155 BITOR = 0 | BINARY_OP_PRECEDENCE(4),
156 BITXOR = 0 | BINARY_OP_PRECEDENCE(5),
157 BITAND = 0 | BINARY_OP_PRECEDENCE(6),
158 EQEQ = 0 | BINARY_OP_PRECEDENCE(7),
159 NE = 1 | BINARY_OP_PRECEDENCE(7),
160 STREQ = 2 | BINARY_OP_PRECEDENCE(7),
161 STRNEQ = 3 | BINARY_OP_PRECEDENCE(7),
162 LT = 0 | BINARY_OP_PRECEDENCE(8),
163 GT = 1 | BINARY_OP_PRECEDENCE(8),
164 LE = 2 | BINARY_OP_PRECEDENCE(8),
165 GE = 3 | BINARY_OP_PRECEDENCE(8),
166 INSTANCEOF = 4 | BINARY_OP_PRECEDENCE(8) | KeywordTokenFlag,
167 INTOKEN = 5 | IN_OP_PRECEDENCE(8) | KeywordTokenFlag,
168 LSHIFT = 0 | BINARY_OP_PRECEDENCE(9),
169 RSHIFT = 1 | BINARY_OP_PRECEDENCE(9),
170 URSHIFT = 2 | BINARY_OP_PRECEDENCE(9),
171 PLUS = 0 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
172 MINUS = 1 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
173 TIMES = 0 | BINARY_OP_PRECEDENCE(11),
174 DIVIDE = 1 | BINARY_OP_PRECEDENCE(11),
175 MOD = 2 | BINARY_OP_PRECEDENCE(11),
176 POW = 0 | BINARY_OP_PRECEDENCE(12) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
177 ERRORTOK = 0 | ErrorTokenFlag,
178 UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
179 INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | ErrorTokenFlag,
180 UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 2 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
181 INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | ErrorTokenFlag,
182 UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
183 UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
184 UNTERMINATED_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
185 INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag,
186 UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
187 INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
188 INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag,
189 UNTERMINATED_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
190 UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
191 UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
192 UNTERMINATED_REGEXP_LITERAL_ERRORTOK = 14 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
193 INVALID_TEMPLATE_LITERAL_ERRORTOK = 15 | ErrorTokenFlag,
194 UNEXPECTED_ESCAPE_ERRORTOK = 16 | ErrorTokenFlag,
195};
196static_assert(static_cast<unsigned>(POW) <= 0x00ffffffU, "JSTokenType must be 24bits.");
197
198struct JSTextPosition {
199 JSTextPosition() = default;
200 JSTextPosition(int _line, int _offset, int _lineStartOffset) : line(_line), offset(_offset), lineStartOffset(_lineStartOffset) { }
201
202 JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); }
203 JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); }
204 JSTextPosition operator-(int adjustment) const { return *this + (- adjustment); }
205 JSTextPosition operator-(unsigned adjustment) const { return *this + (- static_cast<int>(adjustment)); }
206
207 operator int() const { return offset; }
208
209 bool operator==(const JSTextPosition& other) const
210 {
211 return line == other.line
212 && offset == other.offset
213 && lineStartOffset == other.lineStartOffset;
214 }
215 bool operator!=(const JSTextPosition& other) const
216 {
217 return !(*this == other);
218 }
219
220 int column() const { return offset - lineStartOffset; }
221
222 int line { 0 };
223 int offset { 0 };
224 int lineStartOffset { 0 };
225};
226
227union JSTokenData {
228 struct {
229 const Identifier* cooked;
230 const Identifier* raw;
231 bool isTail;
232 };
233 struct {
234 uint32_t line;
235 uint32_t offset;
236 uint32_t lineStartOffset;
237 };
238 double doubleValue;
239 struct {
240 const Identifier* ident;
241 bool escaped;
242 };
243 struct {
244 const Identifier* bigIntString;
245 uint8_t radix;
246 };
247 struct {
248 const Identifier* pattern;
249 const Identifier* flags;
250 };
251};
252
253struct JSTokenLocation {
254 JSTokenLocation() = default;
255
256 int line { 0 };
257 unsigned lineStartOffset { 0 };
258 unsigned startOffset { 0 };
259 unsigned endOffset { 0 };
260};
261
262struct JSToken {
263 JSTokenType m_type { ERRORTOK };
264 JSTokenData m_data { { nullptr, nullptr, false } };
265 JSTokenLocation m_location;
266 JSTextPosition m_startPosition;
267 JSTextPosition m_endPosition;
268};
269
270ALWAYS_INLINE bool isUpdateOp(JSTokenType token)
271{
272 return token >= PLUSPLUS && token <= AUTOMINUSMINUS;
273}
274
275ALWAYS_INLINE bool isUnaryOp(JSTokenType token)
276{
277 return token & UnaryOpTokenFlag;
278}
279
280} // namespace JSC
281