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 WTF {
|
---|
32 | class PrintStream;
|
---|
33 | }
|
---|
34 |
|
---|
35 | namespace JSC {
|
---|
36 |
|
---|
37 | class Identifier;
|
---|
38 |
|
---|
39 | #define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
|
---|
40 | #define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))
|
---|
41 |
|
---|
42 | enum JSTokenType {
|
---|
43 | // Token Bitfield: 0b000000000RTE00IIIIPPPPKUXXXXXXXX
|
---|
44 | // R = right-associative bit
|
---|
45 | // T = unterminated error flag
|
---|
46 | // E = error flag
|
---|
47 | // I = binary operator allows 'in'
|
---|
48 | // P = binary operator precedence
|
---|
49 | // K = keyword flag
|
---|
50 | // U = unary operator flag
|
---|
51 | //
|
---|
52 | // We must keep the upper 8bit (1byte) region empty. JSTokenType must be 24bits.
|
---|
53 | UnaryOpTokenFlag = 1 << 8,
|
---|
54 | KeywordTokenFlag = 1 << 9,
|
---|
55 | BinaryOpTokenPrecedenceShift = 10,
|
---|
56 | BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
|
---|
57 | BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift,
|
---|
58 | CanBeErrorTokenFlag = 1 << (BinaryOpTokenAllowsInPrecedenceAdditionalShift + BinaryOpTokenPrecedenceShift + 6),
|
---|
59 | UnterminatedCanBeErrorTokenFlag = CanBeErrorTokenFlag << 1,
|
---|
60 | RightAssociativeBinaryOpTokenFlag = UnterminatedCanBeErrorTokenFlag << 1,
|
---|
61 |
|
---|
62 |
|
---|
63 | NULLTOKEN = KeywordTokenFlag,
|
---|
64 | TRUETOKEN,
|
---|
65 | FALSETOKEN,
|
---|
66 | BREAK,
|
---|
67 | CASE,
|
---|
68 | DEFAULT,
|
---|
69 | FOR,
|
---|
70 | NEW,
|
---|
71 | VAR,
|
---|
72 | CONSTTOKEN,
|
---|
73 | CONTINUE,
|
---|
74 | FUNCTION,
|
---|
75 | RETURN,
|
---|
76 | IF,
|
---|
77 | THISTOKEN,
|
---|
78 | DO,
|
---|
79 | WHILE,
|
---|
80 | SWITCH,
|
---|
81 | WITH,
|
---|
82 | RESERVED,
|
---|
83 | RESERVED_IF_STRICT,
|
---|
84 | THROW,
|
---|
85 | TRY,
|
---|
86 | CATCH,
|
---|
87 | FINALLY,
|
---|
88 | DEBUGGER,
|
---|
89 | ELSE,
|
---|
90 | IMPORT,
|
---|
91 | EXPORT_,
|
---|
92 | CLASSTOKEN,
|
---|
93 | EXTENDS,
|
---|
94 | SUPER,
|
---|
95 |
|
---|
96 | // Contextual keywords
|
---|
97 |
|
---|
98 | LET,
|
---|
99 | YIELD,
|
---|
100 | AWAIT,
|
---|
101 |
|
---|
102 | FirstContextualKeywordToken = LET,
|
---|
103 | LastContextualKeywordToken = AWAIT,
|
---|
104 |
|
---|
105 | OPENBRACE = 0,
|
---|
106 | CLOSEBRACE,
|
---|
107 | OPENPAREN,
|
---|
108 | CLOSEPAREN,
|
---|
109 | OPENBRACKET,
|
---|
110 | CLOSEBRACKET,
|
---|
111 | COMMA,
|
---|
112 | QUESTION,
|
---|
113 | BACKQUOTE,
|
---|
114 | INTEGER,
|
---|
115 | DOUBLE,
|
---|
116 | BIGINT,
|
---|
117 | IDENT,
|
---|
118 | PRIVATENAME,
|
---|
119 | STRING,
|
---|
120 | TEMPLATE,
|
---|
121 | REGEXP,
|
---|
122 | SEMICOLON,
|
---|
123 | COLON,
|
---|
124 | DOT,
|
---|
125 | EOFTOK,
|
---|
126 | EQUAL,
|
---|
127 | PLUSEQUAL,
|
---|
128 | MINUSEQUAL,
|
---|
129 | MULTEQUAL,
|
---|
130 | DIVEQUAL,
|
---|
131 | LSHIFTEQUAL,
|
---|
132 | RSHIFTEQUAL,
|
---|
133 | URSHIFTEQUAL,
|
---|
134 | MODEQUAL,
|
---|
135 | POWEQUAL,
|
---|
136 | BITANDEQUAL,
|
---|
137 | BITXOREQUAL,
|
---|
138 | BITOREQUAL,
|
---|
139 | COALESCEEQUAL,
|
---|
140 | OREQUAL,
|
---|
141 | ANDEQUAL,
|
---|
142 | DOTDOTDOT,
|
---|
143 | ARROWFUNCTION,
|
---|
144 | QUESTIONDOT,
|
---|
145 | LastUntaggedToken,
|
---|
146 |
|
---|
147 | // Begin tagged tokens
|
---|
148 | PLUSPLUS = 0 | UnaryOpTokenFlag,
|
---|
149 | MINUSMINUS = 1 | UnaryOpTokenFlag,
|
---|
150 | AUTOPLUSPLUS = 2 | UnaryOpTokenFlag,
|
---|
151 | AUTOMINUSMINUS = 3 | UnaryOpTokenFlag,
|
---|
152 | EXCLAMATION = 4 | UnaryOpTokenFlag,
|
---|
153 | TILDE = 5 | UnaryOpTokenFlag,
|
---|
154 | TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag,
|
---|
155 | VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
|
---|
156 | DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
|
---|
157 | COALESCE = 0 | BINARY_OP_PRECEDENCE(1),
|
---|
158 | OR = 0 | BINARY_OP_PRECEDENCE(2),
|
---|
159 | AND = 0 | BINARY_OP_PRECEDENCE(3),
|
---|
160 | BITOR = 0 | BINARY_OP_PRECEDENCE(4),
|
---|
161 | BITXOR = 0 | BINARY_OP_PRECEDENCE(5),
|
---|
162 | BITAND = 0 | BINARY_OP_PRECEDENCE(6),
|
---|
163 | EQEQ = 0 | BINARY_OP_PRECEDENCE(7),
|
---|
164 | NE = 1 | BINARY_OP_PRECEDENCE(7),
|
---|
165 | STREQ = 2 | BINARY_OP_PRECEDENCE(7),
|
---|
166 | STRNEQ = 3 | BINARY_OP_PRECEDENCE(7),
|
---|
167 | LT = 0 | BINARY_OP_PRECEDENCE(8),
|
---|
168 | GT = 1 | BINARY_OP_PRECEDENCE(8),
|
---|
169 | LE = 2 | BINARY_OP_PRECEDENCE(8),
|
---|
170 | GE = 3 | BINARY_OP_PRECEDENCE(8),
|
---|
171 | INSTANCEOF = 4 | BINARY_OP_PRECEDENCE(8) | KeywordTokenFlag,
|
---|
172 | INTOKEN = 5 | IN_OP_PRECEDENCE(8) | KeywordTokenFlag,
|
---|
173 | LSHIFT = 0 | BINARY_OP_PRECEDENCE(9),
|
---|
174 | RSHIFT = 1 | BINARY_OP_PRECEDENCE(9),
|
---|
175 | URSHIFT = 2 | BINARY_OP_PRECEDENCE(9),
|
---|
176 | PLUS = 0 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
|
---|
177 | MINUS = 1 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
|
---|
178 | TIMES = 0 | BINARY_OP_PRECEDENCE(11),
|
---|
179 | DIVIDE = 1 | BINARY_OP_PRECEDENCE(11),
|
---|
180 | MOD = 2 | BINARY_OP_PRECEDENCE(11),
|
---|
181 | POW = 0 | BINARY_OP_PRECEDENCE(12) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
|
---|
182 | ERRORTOK = 0 | CanBeErrorTokenFlag,
|
---|
183 | UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
184 | INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | CanBeErrorTokenFlag,
|
---|
185 | UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 2 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
186 | INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | CanBeErrorTokenFlag,
|
---|
187 | UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
188 | UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
189 | UNTERMINATED_OCTAL_NUMBER_ERRORTOK = 6 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
190 | INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | CanBeErrorTokenFlag,
|
---|
191 | UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
192 | INVALID_STRING_LITERAL_ERRORTOK = 9 | CanBeErrorTokenFlag,
|
---|
193 | INVALID_PRIVATE_NAME_ERRORTOK = 10 | CanBeErrorTokenFlag,
|
---|
194 | UNTERMINATED_HEX_NUMBER_ERRORTOK = 11 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
195 | UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
196 | UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
197 | UNTERMINATED_REGEXP_LITERAL_ERRORTOK = 14 | CanBeErrorTokenFlag | UnterminatedCanBeErrorTokenFlag,
|
---|
198 | INVALID_TEMPLATE_LITERAL_ERRORTOK = 15 | CanBeErrorTokenFlag,
|
---|
199 | ESCAPED_KEYWORD = 16 | CanBeErrorTokenFlag,
|
---|
200 | INVALID_UNICODE_ENCODING_ERRORTOK = 17 | CanBeErrorTokenFlag,
|
---|
201 | INVALID_IDENTIFIER_UNICODE_ERRORTOK = 18 | CanBeErrorTokenFlag,
|
---|
202 | };
|
---|
203 | static_assert(static_cast<unsigned>(POW) <= 0x00ffffffU, "JSTokenType must be 24bits.");
|
---|
204 |
|
---|
205 | struct JSTextPosition {
|
---|
206 | JSTextPosition() = default;
|
---|
207 | JSTextPosition(int _line, int _offset, int _lineStartOffset)
|
---|
208 | : line(_line)
|
---|
209 | , offset(_offset)
|
---|
210 | , lineStartOffset(_lineStartOffset)
|
---|
211 | {
|
---|
212 | checkConsistency();
|
---|
213 | }
|
---|
214 |
|
---|
215 | JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); }
|
---|
216 | JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); }
|
---|
217 | JSTextPosition operator-(int adjustment) const { return *this + (- adjustment); }
|
---|
218 | JSTextPosition operator-(unsigned adjustment) const { return *this + (- static_cast<int>(adjustment)); }
|
---|
219 |
|
---|
220 | operator int() const { return offset; }
|
---|
221 |
|
---|
222 | bool operator==(const JSTextPosition& other) const
|
---|
223 | {
|
---|
224 | return line == other.line
|
---|
225 | && offset == other.offset
|
---|
226 | && lineStartOffset == other.lineStartOffset;
|
---|
227 | }
|
---|
228 | bool operator!=(const JSTextPosition& other) const
|
---|
229 | {
|
---|
230 | return !(*this == other);
|
---|
231 | }
|
---|
232 |
|
---|
233 | int column() const { return offset - lineStartOffset; }
|
---|
234 | void checkConsistency()
|
---|
235 | {
|
---|
236 | // FIXME: We should test ASSERT(offset >= lineStartOffset); but that breaks a lot of tests.
|
---|
237 | ASSERT(line >= 0);
|
---|
238 | ASSERT(offset >= 0);
|
---|
239 | ASSERT(lineStartOffset >= 0);
|
---|
240 | }
|
---|
241 |
|
---|
242 | // FIXME: these should be unsigned.
|
---|
243 | int line { -1 };
|
---|
244 | int offset { -1 };
|
---|
245 | int lineStartOffset { -1 };
|
---|
246 | };
|
---|
247 |
|
---|
248 | union JSTokenData {
|
---|
249 | struct {
|
---|
250 | const Identifier* cooked;
|
---|
251 | const Identifier* raw;
|
---|
252 | bool isTail;
|
---|
253 | };
|
---|
254 | struct {
|
---|
255 | uint32_t line;
|
---|
256 | uint32_t offset;
|
---|
257 | uint32_t lineStartOffset;
|
---|
258 | };
|
---|
259 | double doubleValue;
|
---|
260 | struct {
|
---|
261 | const Identifier* ident;
|
---|
262 | bool escaped;
|
---|
263 | };
|
---|
264 | struct {
|
---|
265 | const Identifier* bigIntString;
|
---|
266 | uint8_t radix;
|
---|
267 | };
|
---|
268 | struct {
|
---|
269 | const Identifier* pattern;
|
---|
270 | const Identifier* flags;
|
---|
271 | };
|
---|
272 | };
|
---|
273 |
|
---|
274 | struct JSTokenLocation {
|
---|
275 | JSTokenLocation() = default;
|
---|
276 |
|
---|
277 | int line { 0 };
|
---|
278 | unsigned lineStartOffset { 0 };
|
---|
279 | unsigned startOffset { 0 };
|
---|
280 | unsigned endOffset { 0 };
|
---|
281 | };
|
---|
282 |
|
---|
283 | struct JSToken {
|
---|
284 | JSTokenType m_type { ERRORTOK };
|
---|
285 | JSTokenData m_data { { nullptr, nullptr, false } };
|
---|
286 | JSTokenLocation m_location;
|
---|
287 | JSTextPosition m_startPosition;
|
---|
288 | JSTextPosition m_endPosition;
|
---|
289 |
|
---|
290 | void dump(WTF::PrintStream&) const;
|
---|
291 | };
|
---|
292 |
|
---|
293 | ALWAYS_INLINE bool isUpdateOp(JSTokenType token)
|
---|
294 | {
|
---|
295 | return token >= PLUSPLUS && token <= AUTOMINUSMINUS;
|
---|
296 | }
|
---|
297 |
|
---|
298 | ALWAYS_INLINE bool isUnaryOp(JSTokenType token)
|
---|
299 | {
|
---|
300 | return token & UnaryOpTokenFlag;
|
---|
301 | }
|
---|
302 |
|
---|
303 | } // namespace JSC
|
---|