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 | |
31 | namespace JSC { |
32 | |
33 | class Identifier; |
34 | |
35 | enum { |
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 | |
59 | enum 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 | = 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 | }; |
196 | static_assert(static_cast<unsigned>(POW) <= 0x00ffffffU, "JSTokenType must be 24bits." ); |
197 | |
198 | struct 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 | |
227 | union 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 | |
253 | struct JSTokenLocation { |
254 | JSTokenLocation() = default; |
255 | |
256 | int line { 0 }; |
257 | unsigned lineStartOffset { 0 }; |
258 | unsigned startOffset { 0 }; |
259 | unsigned endOffset { 0 }; |
260 | }; |
261 | |
262 | struct 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 | |
270 | ALWAYS_INLINE bool isUpdateOp(JSTokenType token) |
271 | { |
272 | return token >= PLUSPLUS && token <= AUTOMINUSMINUS; |
273 | } |
274 | |
275 | ALWAYS_INLINE bool isUnaryOp(JSTokenType token) |
276 | { |
277 | return token & UnaryOpTokenFlag; |
278 | } |
279 | |
280 | } // namespace JSC |
281 | |