|  | /* | 
|  | * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 
|  | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 
|  | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
|  | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 
|  | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 
|  | * THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <limits.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | namespace JSC { | 
|  |  | 
|  | class Identifier; | 
|  |  | 
|  | enum { | 
|  | // Token Bitfield: 0b000000000RTE00IIIIPPPPKUXXXXXXXX | 
|  | // R = right-associative bit | 
|  | // T = unterminated error flag | 
|  | // E = error flag | 
|  | // I = binary operator allows 'in' | 
|  | // P = binary operator precedence | 
|  | // K = keyword flag | 
|  | // U = unary operator flag | 
|  | // | 
|  | // We must keep the upper 8bit (1byte) region empty. JSTokenType must be 24bits. | 
|  | UnaryOpTokenFlag = 1 << 8, | 
|  | KeywordTokenFlag = 1 << 9, | 
|  | BinaryOpTokenPrecedenceShift = 10, | 
|  | BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4, | 
|  | BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift, | 
|  | ErrorTokenFlag = 1 << (BinaryOpTokenAllowsInPrecedenceAdditionalShift + BinaryOpTokenPrecedenceShift + 6), | 
|  | UnterminatedErrorTokenFlag = ErrorTokenFlag << 1, | 
|  | RightAssociativeBinaryOpTokenFlag = UnterminatedErrorTokenFlag << 1 | 
|  | }; | 
|  |  | 
|  | #define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))) | 
|  | #define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)) | 
|  |  | 
|  | enum JSTokenType { | 
|  | NULLTOKEN = KeywordTokenFlag, | 
|  | TRUETOKEN, | 
|  | FALSETOKEN, | 
|  | BREAK, | 
|  | CASE, | 
|  | DEFAULT, | 
|  | FOR, | 
|  | NEW, | 
|  | VAR, | 
|  | CONSTTOKEN, | 
|  | CONTINUE, | 
|  | FUNCTION, | 
|  | RETURN, | 
|  | IF, | 
|  | THISTOKEN, | 
|  | DO, | 
|  | WHILE, | 
|  | SWITCH, | 
|  | WITH, | 
|  | RESERVED, | 
|  | RESERVED_IF_STRICT, | 
|  | THROW, | 
|  | TRY, | 
|  | CATCH, | 
|  | FINALLY, | 
|  | DEBUGGER, | 
|  | ELSE, | 
|  | IMPORT, | 
|  | EXPORT_, | 
|  | CLASSTOKEN, | 
|  | EXTENDS, | 
|  | SUPER, | 
|  |  | 
|  | // Contextual keywords | 
|  |  | 
|  | LET, | 
|  | YIELD, | 
|  | AWAIT, | 
|  |  | 
|  | FirstContextualKeywordToken = LET, | 
|  | LastContextualKeywordToken = AWAIT, | 
|  | FirstSafeContextualKeywordToken = AWAIT, | 
|  | LastSafeContextualKeywordToken = LastContextualKeywordToken, | 
|  |  | 
|  | OPENBRACE = 0, | 
|  | CLOSEBRACE, | 
|  | OPENPAREN, | 
|  | CLOSEPAREN, | 
|  | OPENBRACKET, | 
|  | CLOSEBRACKET, | 
|  | COMMA, | 
|  | QUESTION, | 
|  | BACKQUOTE, | 
|  | INTEGER, | 
|  | DOUBLE, | 
|  | BIGINT, | 
|  | IDENT, | 
|  | PRIVATENAME, | 
|  | STRING, | 
|  | TEMPLATE, | 
|  | REGEXP, | 
|  | SEMICOLON, | 
|  | COLON, | 
|  | DOT, | 
|  | EOFTOK, | 
|  | EQUAL, | 
|  | PLUSEQUAL, | 
|  | MINUSEQUAL, | 
|  | MULTEQUAL, | 
|  | DIVEQUAL, | 
|  | LSHIFTEQUAL, | 
|  | RSHIFTEQUAL, | 
|  | URSHIFTEQUAL, | 
|  | MODEQUAL, | 
|  | POWEQUAL, | 
|  | BITANDEQUAL, | 
|  | BITXOREQUAL, | 
|  | BITOREQUAL, | 
|  | COALESCEEQUAL, | 
|  | OREQUAL, | 
|  | ANDEQUAL, | 
|  | DOTDOTDOT, | 
|  | ARROWFUNCTION, | 
|  | QUESTIONDOT, | 
|  | LastUntaggedToken, | 
|  |  | 
|  | // Begin tagged tokens | 
|  | PLUSPLUS = 0 | UnaryOpTokenFlag, | 
|  | MINUSMINUS = 1 | UnaryOpTokenFlag, | 
|  | AUTOPLUSPLUS = 2 | UnaryOpTokenFlag, | 
|  | AUTOMINUSMINUS = 3 | UnaryOpTokenFlag, | 
|  | EXCLAMATION = 4 | UnaryOpTokenFlag, | 
|  | TILDE = 5 | UnaryOpTokenFlag, | 
|  | TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag, | 
|  | VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag, | 
|  | DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag, | 
|  | COALESCE = 0 | BINARY_OP_PRECEDENCE(1), | 
|  | OR = 0 | BINARY_OP_PRECEDENCE(2), | 
|  | AND = 0 | BINARY_OP_PRECEDENCE(3), | 
|  | BITOR = 0 | BINARY_OP_PRECEDENCE(4), | 
|  | BITXOR = 0 | BINARY_OP_PRECEDENCE(5), | 
|  | BITAND = 0 | BINARY_OP_PRECEDENCE(6), | 
|  | EQEQ = 0 | BINARY_OP_PRECEDENCE(7), | 
|  | NE = 1 | BINARY_OP_PRECEDENCE(7), | 
|  | STREQ = 2 | BINARY_OP_PRECEDENCE(7), | 
|  | STRNEQ = 3 | BINARY_OP_PRECEDENCE(7), | 
|  | LT = 0 | BINARY_OP_PRECEDENCE(8), | 
|  | GT = 1 | BINARY_OP_PRECEDENCE(8), | 
|  | LE = 2 | BINARY_OP_PRECEDENCE(8), | 
|  | GE = 3 | BINARY_OP_PRECEDENCE(8), | 
|  | INSTANCEOF = 4 | BINARY_OP_PRECEDENCE(8) | KeywordTokenFlag, | 
|  | INTOKEN = 5 | IN_OP_PRECEDENCE(8) | KeywordTokenFlag, | 
|  | LSHIFT = 0 | BINARY_OP_PRECEDENCE(9), | 
|  | RSHIFT = 1 | BINARY_OP_PRECEDENCE(9), | 
|  | URSHIFT = 2 | BINARY_OP_PRECEDENCE(9), | 
|  | PLUS = 0 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag, | 
|  | MINUS = 1 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag, | 
|  | TIMES = 0 | BINARY_OP_PRECEDENCE(11), | 
|  | DIVIDE = 1 | BINARY_OP_PRECEDENCE(11), | 
|  | MOD = 2 | BINARY_OP_PRECEDENCE(11), | 
|  | POW = 0 | BINARY_OP_PRECEDENCE(12) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence. | 
|  | ERRORTOK = 0 | ErrorTokenFlag, | 
|  | UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | ErrorTokenFlag, | 
|  | UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 2 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | ErrorTokenFlag, | 
|  | UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | UNTERMINATED_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag, | 
|  | UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag, | 
|  | INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag, | 
|  | UNTERMINATED_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | UNTERMINATED_REGEXP_LITERAL_ERRORTOK = 14 | ErrorTokenFlag | UnterminatedErrorTokenFlag, | 
|  | INVALID_TEMPLATE_LITERAL_ERRORTOK = 15 | ErrorTokenFlag, | 
|  | UNEXPECTED_ESCAPE_ERRORTOK = 16 | ErrorTokenFlag, | 
|  | INVALID_UNICODE_ENCODING_ERRORTOK = 17 | ErrorTokenFlag, | 
|  | INVALID_IDENTIFIER_UNICODE_ERRORTOK = 18 | ErrorTokenFlag, | 
|  | }; | 
|  | static_assert(static_cast<unsigned>(POW) <= 0x00ffffffU, "JSTokenType must be 24bits."); | 
|  |  | 
|  | struct JSTextPosition { | 
|  | JSTextPosition() = default; | 
|  | JSTextPosition(int _line, int _offset, int _lineStartOffset) | 
|  | : line(_line) | 
|  | , offset(_offset) | 
|  | , lineStartOffset(_lineStartOffset) | 
|  | { | 
|  | checkConsistency(); | 
|  | } | 
|  |  | 
|  | JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); } | 
|  | JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); } | 
|  | JSTextPosition operator-(int adjustment) const { return *this + (- adjustment); } | 
|  | JSTextPosition operator-(unsigned adjustment) const { return *this + (- static_cast<int>(adjustment)); } | 
|  |  | 
|  | operator int() const { return offset; } | 
|  |  | 
|  | bool operator==(const JSTextPosition& other) const | 
|  | { | 
|  | return line == other.line | 
|  | && offset == other.offset | 
|  | && lineStartOffset == other.lineStartOffset; | 
|  | } | 
|  | bool operator!=(const JSTextPosition& other) const | 
|  | { | 
|  | return !(*this == other); | 
|  | } | 
|  |  | 
|  | int column() const { return offset - lineStartOffset; } | 
|  | void checkConsistency() | 
|  | { | 
|  | // FIXME: We should test ASSERT(offset >= lineStartOffset); but that breaks a lot of tests. | 
|  | ASSERT(line >= 0); | 
|  | ASSERT(offset >= 0); | 
|  | ASSERT(lineStartOffset >= 0); | 
|  | } | 
|  |  | 
|  | // FIXME: these should be unsigned. | 
|  | int line { -1 }; | 
|  | int offset { -1 }; | 
|  | int lineStartOffset { -1 }; | 
|  | }; | 
|  |  | 
|  | union JSTokenData { | 
|  | struct { | 
|  | const Identifier* cooked; | 
|  | const Identifier* raw; | 
|  | bool isTail; | 
|  | }; | 
|  | struct { | 
|  | uint32_t line; | 
|  | uint32_t offset; | 
|  | uint32_t lineStartOffset; | 
|  | }; | 
|  | double doubleValue; | 
|  | struct { | 
|  | const Identifier* ident; | 
|  | bool escaped; | 
|  | }; | 
|  | struct { | 
|  | const Identifier* bigIntString; | 
|  | uint8_t radix; | 
|  | }; | 
|  | struct { | 
|  | const Identifier* pattern; | 
|  | const Identifier* flags; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | struct JSTokenLocation { | 
|  | JSTokenLocation() = default; | 
|  |  | 
|  | int line { 0 }; | 
|  | unsigned lineStartOffset { 0 }; | 
|  | unsigned startOffset { 0 }; | 
|  | unsigned endOffset { 0 }; | 
|  | }; | 
|  |  | 
|  | struct JSToken { | 
|  | JSTokenType m_type { ERRORTOK }; | 
|  | JSTokenData m_data { { nullptr, nullptr, false } }; | 
|  | JSTokenLocation m_location; | 
|  | JSTextPosition m_startPosition; | 
|  | JSTextPosition m_endPosition; | 
|  | }; | 
|  |  | 
|  | ALWAYS_INLINE bool isUpdateOp(JSTokenType token) | 
|  | { | 
|  | return token >= PLUSPLUS && token <= AUTOMINUSMINUS; | 
|  | } | 
|  |  | 
|  | ALWAYS_INLINE bool isUnaryOp(JSTokenType token) | 
|  | { | 
|  | return token & UnaryOpTokenFlag; | 
|  | } | 
|  |  | 
|  | } // namespace JSC |