13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#ifndef ES2PANDA_PARSER_CORE_LEXER_H
173af6ab5fSopenharmony_ci#define ES2PANDA_PARSER_CORE_LEXER_H
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include <lexer/regexp/regexp.h>
203af6ab5fSopenharmony_ci#include <lexer/token/letters.h>
213af6ab5fSopenharmony_ci#include <lexer/token/token.h>
223af6ab5fSopenharmony_ci#include <util/enumbitops.h>
233af6ab5fSopenharmony_ci
243af6ab5fSopenharmony_cinamespace panda::es2panda::parser {
253af6ab5fSopenharmony_ciclass ParserContext;
263af6ab5fSopenharmony_ci}  // namespace panda::es2panda::parser
273af6ab5fSopenharmony_ci
283af6ab5fSopenharmony_cinamespace panda::es2panda::lexer {
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_cienum class LexerNextTokenFlags : uint8_t {
313af6ab5fSopenharmony_ci    NONE = 0,
323af6ab5fSopenharmony_ci    KEYWORD_TO_IDENT = 1 << 0,
333af6ab5fSopenharmony_ci    NUMERIC_SEPARATOR_ALLOWED = 1 << 1,
343af6ab5fSopenharmony_ci    BIGINT_ALLOWED = 1 << 2,
353af6ab5fSopenharmony_ci};
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_ciDEFINE_BITOPS(LexerNextTokenFlags)
383af6ab5fSopenharmony_ci
393af6ab5fSopenharmony_ciclass LexerPosition {
403af6ab5fSopenharmony_cipublic:
413af6ab5fSopenharmony_ci    explicit LexerPosition(const util::StringView &source);
423af6ab5fSopenharmony_ci    DEFAULT_COPY_SEMANTIC(LexerPosition);
433af6ab5fSopenharmony_ci    DEFAULT_MOVE_SEMANTIC(LexerPosition);
443af6ab5fSopenharmony_ci    ~LexerPosition() = default;
453af6ab5fSopenharmony_ci
463af6ab5fSopenharmony_ci    Token token {};
473af6ab5fSopenharmony_ci    util::StringView::Iterator iterator;
483af6ab5fSopenharmony_ci    size_t line {};
493af6ab5fSopenharmony_ci    size_t nextTokenLine {};
503af6ab5fSopenharmony_ci};
513af6ab5fSopenharmony_ci
523af6ab5fSopenharmony_ciclass LexerTemplateString {
533af6ab5fSopenharmony_cipublic:
543af6ab5fSopenharmony_ci    explicit LexerTemplateString(ArenaAllocator *allocator) : str(allocator) {}
553af6ab5fSopenharmony_ci    DEFAULT_COPY_SEMANTIC(LexerTemplateString);
563af6ab5fSopenharmony_ci    DEFAULT_MOVE_SEMANTIC(LexerTemplateString);
573af6ab5fSopenharmony_ci    ~LexerTemplateString() = default;
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_ci    util::UString str;
603af6ab5fSopenharmony_ci    size_t end {};
613af6ab5fSopenharmony_ci    bool scanExpression {};
623af6ab5fSopenharmony_ci};
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ciclass TemplateLiteralParserContext;
653af6ab5fSopenharmony_ci
663af6ab5fSopenharmony_ciclass Lexer {
673af6ab5fSopenharmony_cipublic:
683af6ab5fSopenharmony_ci    explicit Lexer(const parser::ParserContext *parserContext);
693af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(Lexer);
703af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(Lexer);
713af6ab5fSopenharmony_ci    ~Lexer() = default;
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci    void NextToken(LexerNextTokenFlags flags = LexerNextTokenFlags::NONE);
743af6ab5fSopenharmony_ci
753af6ab5fSopenharmony_ci    Token &GetToken();
763af6ab5fSopenharmony_ci    const Token &GetToken() const;
773af6ab5fSopenharmony_ci    size_t Line() const;
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_ci    LexerPosition Save() const;
803af6ab5fSopenharmony_ci    void Rewind(const LexerPosition &pos);
813af6ab5fSopenharmony_ci    void BackwardToken(TokenType type, size_t offset);
823af6ab5fSopenharmony_ci    void ForwardToken(TokenType type, size_t offset);
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci    char32_t Lookahead();
853af6ab5fSopenharmony_ci    bool CheckArrow();
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci    RegExp ScanRegExp();
883af6ab5fSopenharmony_ci    template <char32_t end>
893af6ab5fSopenharmony_ci    void ScanString();
903af6ab5fSopenharmony_ci    void ResetTokenEnd();
913af6ab5fSopenharmony_ci    LexerTemplateString ScanTemplateString();
923af6ab5fSopenharmony_ci    void ScanTemplateStringEnd();
933af6ab5fSopenharmony_ci    void PushTemplateContext(TemplateLiteralParserContext *ctx);
943af6ab5fSopenharmony_ci    void AssignTokenTaggedTemplate();
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_ciprivate:
973af6ab5fSopenharmony_ci    ArenaAllocator *Allocator();
983af6ab5fSopenharmony_ci    bool IsLineTerminatorOrEos() const;
993af6ab5fSopenharmony_ci    void ScanRegExpPattern();
1003af6ab5fSopenharmony_ci    bool GetRegExpFlag(char32_t cp, RegExpFlags &flag);
1013af6ab5fSopenharmony_ci    RegExpFlags ScanRegExpFlags();
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci    void ThrowError(std::string_view message);
1043af6ab5fSopenharmony_ci
1053af6ab5fSopenharmony_ci    void SetTokenStart();
1063af6ab5fSopenharmony_ci    void SetTokenEnd();
1073af6ab5fSopenharmony_ci    bool CheckTokenIsTaggedTemplate() const;
1083af6ab5fSopenharmony_ci
1093af6ab5fSopenharmony_ci    inline util::StringView::Iterator &Iterator()
1103af6ab5fSopenharmony_ci    {
1113af6ab5fSopenharmony_ci        return pos_.iterator;
1123af6ab5fSopenharmony_ci    }
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    inline const util::StringView::Iterator &Iterator() const
1153af6ab5fSopenharmony_ci    {
1163af6ab5fSopenharmony_ci        return pos_.iterator;
1173af6ab5fSopenharmony_ci    }
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ci    util::StringView SourceView(const util::StringView::Iterator &begin, const util::StringView::Iterator &end) const;
1203af6ab5fSopenharmony_ci    util::StringView SourceView(size_t begin, size_t end) const;
1213af6ab5fSopenharmony_ci
1223af6ab5fSopenharmony_ci    void SkipWhiteSpaces();
1233af6ab5fSopenharmony_ci    void SkipSingleLineComment();
1243af6ab5fSopenharmony_ci    void SkipMultiLineComment();
1253af6ab5fSopenharmony_ci    template <TokenType keyword_type>
1263af6ab5fSopenharmony_ci    void CheckKeyword([[maybe_unused]] TokenType type, [[maybe_unused]] LexerNextTokenFlags flags);
1273af6ab5fSopenharmony_ci    void CheckKeywordEscape(TokenType type);
1283af6ab5fSopenharmony_ci    void CheckAwaitKeyword();
1293af6ab5fSopenharmony_ci    void CheckArgumentsKeyword();
1303af6ab5fSopenharmony_ci    void CheckEnumKeyword();
1313af6ab5fSopenharmony_ci    void CheckLetKeyword();
1323af6ab5fSopenharmony_ci    void CheckYieldKeyword();
1333af6ab5fSopenharmony_ci    void CheckFutureReservedKeyword(TokenType keywordType);
1343af6ab5fSopenharmony_ci
1353af6ab5fSopenharmony_ci    bool ScanPunctuator();
1363af6ab5fSopenharmony_ci    void ScanQuestionPunctuator();
1373af6ab5fSopenharmony_ci    void ScanLessThanPunctuator();
1383af6ab5fSopenharmony_ci    void ScanGreaterThanPunctuator();
1393af6ab5fSopenharmony_ci    void ScanEqualsPunctuator();
1403af6ab5fSopenharmony_ci    void ScanExclamationPunctuator();
1413af6ab5fSopenharmony_ci    void ScanAmpersandPunctuator();
1423af6ab5fSopenharmony_ci    void ScanVLinePunctuator();
1433af6ab5fSopenharmony_ci    void ScanCircumflexPunctuator();
1443af6ab5fSopenharmony_ci    void ScanPlusPunctuator();
1453af6ab5fSopenharmony_ci    void ScanMinusPunctuator();
1463af6ab5fSopenharmony_ci    void ScanAsterixPunctuator();
1473af6ab5fSopenharmony_ci    void ScanSlashPunctuator();
1483af6ab5fSopenharmony_ci    void ScanPercentPunctuator();
1493af6ab5fSopenharmony_ci    void ScanDotPunctuator();
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci    char32_t ScanUnicodeEscapeSequence();
1523af6ab5fSopenharmony_ci    template <int N>
1533af6ab5fSopenharmony_ci    char32_t ScanHexEscape();
1543af6ab5fSopenharmony_ci    char32_t ScanUnicodeCodePointEscape();
1553af6ab5fSopenharmony_ci
1563af6ab5fSopenharmony_ci    void ScanStringUnicodePart(util::UString *str);
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_ci    void ScanNumberLeadingZero();
1593af6ab5fSopenharmony_ci    void ScanDecimalNumbers(bool allowNumericSeparator);
1603af6ab5fSopenharmony_ci    template <bool rangeCheck(char32_t), int radix>
1613af6ab5fSopenharmony_ci    void ScanNumberRadix(bool allowNumericSeparator = true);
1623af6ab5fSopenharmony_ci    void ScanNumber(bool allowNumericSeparator = true, bool allowBigInt = true);
1633af6ab5fSopenharmony_ci    void ConvertNumber(size_t exponentSignPos);
1643af6ab5fSopenharmony_ci    void ScanDecimalLiteral();
1653af6ab5fSopenharmony_ci    void ScanDecimalDigits(bool allowNumericSeparator);
1663af6ab5fSopenharmony_ci    void CheckNumberLiteralEnd();
1673af6ab5fSopenharmony_ci    void AssignTokenEscapeError();
1683af6ab5fSopenharmony_ci
1693af6ab5fSopenharmony_ci    inline static uint32_t HexValue(char32_t ch);
1703af6ab5fSopenharmony_ci    inline static bool IsDecimalDigit(uint32_t cp);
1713af6ab5fSopenharmony_ci    inline static bool IsHexDigit(char32_t ch);
1723af6ab5fSopenharmony_ci    inline static bool IsBinaryDigit(char32_t ch);
1733af6ab5fSopenharmony_ci    inline static bool IsOctalDigit(char32_t ch);
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci    friend class KeywordsUtil;
1763af6ab5fSopenharmony_ci    friend class TemplateLiteralParserContext;
1773af6ab5fSopenharmony_ci    TemplateLiteralParserContext *tlCtx_ {};
1783af6ab5fSopenharmony_ci    ArenaAllocator *allocator_;
1793af6ab5fSopenharmony_ci    const parser::ParserContext *parserContext_;
1803af6ab5fSopenharmony_ci    util::StringView source_;
1813af6ab5fSopenharmony_ci    LexerPosition pos_;
1823af6ab5fSopenharmony_ci    bool isUnderscore_ = false;
1833af6ab5fSopenharmony_ci};
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_ciclass TemplateLiteralParserContext {
1863af6ab5fSopenharmony_cipublic:
1873af6ab5fSopenharmony_ci    explicit TemplateLiteralParserContext(Lexer *lexer) : lexer_(lexer), prev_(lexer_->tlCtx_) {}
1883af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(TemplateLiteralParserContext);
1893af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(TemplateLiteralParserContext);
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci    ~TemplateLiteralParserContext()
1923af6ab5fSopenharmony_ci    {
1933af6ab5fSopenharmony_ci        lexer_->tlCtx_ = prev_;
1943af6ab5fSopenharmony_ci    }
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci    void ConsumeLeftBrace()
1973af6ab5fSopenharmony_ci    {
1983af6ab5fSopenharmony_ci        braceDepth_++;
1993af6ab5fSopenharmony_ci    }
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    bool ConsumeRightBrace()
2023af6ab5fSopenharmony_ci    {
2033af6ab5fSopenharmony_ci        braceDepth_--;
2043af6ab5fSopenharmony_ci
2053af6ab5fSopenharmony_ci        return braceDepth_ == 0;
2063af6ab5fSopenharmony_ci    }
2073af6ab5fSopenharmony_ci
2083af6ab5fSopenharmony_ciprivate:
2093af6ab5fSopenharmony_ci    Lexer *lexer_;
2103af6ab5fSopenharmony_ci    TemplateLiteralParserContext *prev_ {};
2113af6ab5fSopenharmony_ci    size_t braceDepth_ {1};
2123af6ab5fSopenharmony_ci};
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_citemplate <char32_t end>
2153af6ab5fSopenharmony_civoid Lexer::ScanString()
2163af6ab5fSopenharmony_ci{
2173af6ab5fSopenharmony_ci    util::UString str(Allocator());
2183af6ab5fSopenharmony_ci    GetToken().type_ = TokenType::LITERAL_STRING;
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ci    const auto startPos = Iterator().Index();
2213af6ab5fSopenharmony_ci    auto escapeEnd = startPos;
2223af6ab5fSopenharmony_ci
2233af6ab5fSopenharmony_ci    do {
2243af6ab5fSopenharmony_ci        char32_t cp = Iterator().Peek();
2253af6ab5fSopenharmony_ci
2263af6ab5fSopenharmony_ci        switch (cp) {
2273af6ab5fSopenharmony_ci            case util::StringView::Iterator::INVALID_CP: {
2283af6ab5fSopenharmony_ci                ThrowError("Unterminated string");
2293af6ab5fSopenharmony_ci                break;
2303af6ab5fSopenharmony_ci            }
2313af6ab5fSopenharmony_ci            case LEX_CHAR_CR:
2323af6ab5fSopenharmony_ci            case LEX_CHAR_LF: {
2333af6ab5fSopenharmony_ci                // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
2343af6ab5fSopenharmony_ci                if constexpr (end != LEX_CHAR_BACK_TICK) {
2353af6ab5fSopenharmony_ci                    ThrowError("Newline is not allowed in strings");
2363af6ab5fSopenharmony_ci                }
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ci                GetToken().flags_ |= TokenFlags::HAS_ESCAPE;
2393af6ab5fSopenharmony_ci                str.Append(SourceView(escapeEnd, Iterator().Index()));
2403af6ab5fSopenharmony_ci
2413af6ab5fSopenharmony_ci                if (cp == LEX_CHAR_CR) {
2423af6ab5fSopenharmony_ci                    Iterator().Forward(1);
2433af6ab5fSopenharmony_ci
2443af6ab5fSopenharmony_ci                    if (Iterator().Peek() != LEX_CHAR_LF) {
2453af6ab5fSopenharmony_ci                        Iterator().Backward(1);
2463af6ab5fSopenharmony_ci                    }
2473af6ab5fSopenharmony_ci                }
2483af6ab5fSopenharmony_ci
2493af6ab5fSopenharmony_ci                pos_.line++;
2503af6ab5fSopenharmony_ci                str.Append(LEX_CHAR_LF);
2513af6ab5fSopenharmony_ci                Iterator().Forward(1);
2523af6ab5fSopenharmony_ci                escapeEnd = Iterator().Index();
2533af6ab5fSopenharmony_ci                continue;
2543af6ab5fSopenharmony_ci            }
2553af6ab5fSopenharmony_ci            case LEX_CHAR_BACKSLASH: {
2563af6ab5fSopenharmony_ci                GetToken().flags_ |= TokenFlags::HAS_ESCAPE;
2573af6ab5fSopenharmony_ci                str.Append(SourceView(escapeEnd, Iterator().Index()));
2583af6ab5fSopenharmony_ci
2593af6ab5fSopenharmony_ci                Iterator().Forward(1);
2603af6ab5fSopenharmony_ci                ScanStringUnicodePart(&str);
2613af6ab5fSopenharmony_ci                escapeEnd = Iterator().Index();
2623af6ab5fSopenharmony_ci                continue;
2633af6ab5fSopenharmony_ci            }
2643af6ab5fSopenharmony_ci            case LEX_CHAR_BACK_TICK:
2653af6ab5fSopenharmony_ci            case LEX_CHAR_SINGLE_QUOTE:
2663af6ab5fSopenharmony_ci            case LEX_CHAR_DOUBLE_QUOTE: {
2673af6ab5fSopenharmony_ci                if (end == cp) {
2683af6ab5fSopenharmony_ci                    break;
2693af6ab5fSopenharmony_ci                }
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci                Iterator().Forward(1);
2723af6ab5fSopenharmony_ci                continue;
2733af6ab5fSopenharmony_ci            }
2743af6ab5fSopenharmony_ci            case LEX_CHAR_DOLLAR_SIGN: {
2753af6ab5fSopenharmony_ci                Iterator().Forward(1);
2763af6ab5fSopenharmony_ci
2773af6ab5fSopenharmony_ci                // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
2783af6ab5fSopenharmony_ci                if constexpr (end == LEX_CHAR_BACK_TICK) {
2793af6ab5fSopenharmony_ci                    if (Iterator().Peek() == LEX_CHAR_LEFT_BRACE) {
2803af6ab5fSopenharmony_ci                        Iterator().Backward(1);
2813af6ab5fSopenharmony_ci                        break;
2823af6ab5fSopenharmony_ci                    }
2833af6ab5fSopenharmony_ci                }
2843af6ab5fSopenharmony_ci
2853af6ab5fSopenharmony_ci                continue;
2863af6ab5fSopenharmony_ci            }
2873af6ab5fSopenharmony_ci            default: {
2883af6ab5fSopenharmony_ci                Iterator().SkipCp();
2893af6ab5fSopenharmony_ci                continue;
2903af6ab5fSopenharmony_ci            }
2913af6ab5fSopenharmony_ci        }
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci        if (GetToken().flags_ & TokenFlags::HAS_ESCAPE) {
2943af6ab5fSopenharmony_ci            str.Append(SourceView(escapeEnd, Iterator().Index()));
2953af6ab5fSopenharmony_ci            GetToken().src_ = str.View();
2963af6ab5fSopenharmony_ci        } else {
2973af6ab5fSopenharmony_ci            GetToken().src_ = SourceView(startPos, Iterator().Index());
2983af6ab5fSopenharmony_ci        }
2993af6ab5fSopenharmony_ci
3003af6ab5fSopenharmony_ci        break;
3013af6ab5fSopenharmony_ci    } while (true);
3023af6ab5fSopenharmony_ci
3033af6ab5fSopenharmony_ci    // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
3043af6ab5fSopenharmony_ci    if constexpr (end != LEX_CHAR_BACK_TICK) {
3053af6ab5fSopenharmony_ci        Iterator().Forward(1);
3063af6ab5fSopenharmony_ci    }
3073af6ab5fSopenharmony_ci}
3083af6ab5fSopenharmony_ci
3093af6ab5fSopenharmony_citemplate <int N>
3103af6ab5fSopenharmony_cichar32_t Lexer::ScanHexEscape()
3113af6ab5fSopenharmony_ci{
3123af6ab5fSopenharmony_ci    char32_t code = 0;
3133af6ab5fSopenharmony_ci
3143af6ab5fSopenharmony_ci    for (size_t i = 0; i < N; ++i) {
3153af6ab5fSopenharmony_ci        const auto cp = Iterator().Peek();
3163af6ab5fSopenharmony_ci        Iterator().Forward(1);
3173af6ab5fSopenharmony_ci
3183af6ab5fSopenharmony_ci        if (!IsHexDigit(cp)) {
3193af6ab5fSopenharmony_ci            // Should not throw error in tagged template in ES2021
3203af6ab5fSopenharmony_ci            if (CheckTokenIsTaggedTemplate()) {
3213af6ab5fSopenharmony_ci                AssignTokenEscapeError();
3223af6ab5fSopenharmony_ci            } else {
3233af6ab5fSopenharmony_ci                ThrowError("Invalid unicode escape sequence");
3243af6ab5fSopenharmony_ci            }
3253af6ab5fSopenharmony_ci        }
3263af6ab5fSopenharmony_ci
3273af6ab5fSopenharmony_ci        constexpr auto MULTIPLIER = 16;
3283af6ab5fSopenharmony_ci        code = code * MULTIPLIER + HexValue(cp);
3293af6ab5fSopenharmony_ci    }
3303af6ab5fSopenharmony_ci
3313af6ab5fSopenharmony_ci    return code;
3323af6ab5fSopenharmony_ci}
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_citemplate <bool rangeCheck(char32_t), int radix>
3353af6ab5fSopenharmony_civoid Lexer::ScanNumberRadix(bool allowNumericSeparator)
3363af6ab5fSopenharmony_ci{
3373af6ab5fSopenharmony_ci    double number = 0.0;
3383af6ab5fSopenharmony_ci
3393af6ab5fSopenharmony_ci    auto cp = Iterator().Peek();
3403af6ab5fSopenharmony_ci    if (!rangeCheck(cp)) {
3413af6ab5fSopenharmony_ci        ThrowError("Invalid digit");
3423af6ab5fSopenharmony_ci    }
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_ci    bool allowNumericOnNext = true;
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    do {
3473af6ab5fSopenharmony_ci        cp = Iterator().Peek();
3483af6ab5fSopenharmony_ci        if (rangeCheck(cp)) {
3493af6ab5fSopenharmony_ci            number = number * radix + HexValue(cp);
3503af6ab5fSopenharmony_ci            Iterator().Forward(1);
3513af6ab5fSopenharmony_ci            allowNumericOnNext = true;
3523af6ab5fSopenharmony_ci            continue;
3533af6ab5fSopenharmony_ci        }
3543af6ab5fSopenharmony_ci
3553af6ab5fSopenharmony_ci        if (cp == LEX_CHAR_UNDERSCORE) {
3563af6ab5fSopenharmony_ci            if (!allowNumericSeparator || !allowNumericOnNext) {
3573af6ab5fSopenharmony_ci                ThrowError("Invalid numeric separator");
3583af6ab5fSopenharmony_ci            }
3593af6ab5fSopenharmony_ci
3603af6ab5fSopenharmony_ci            GetToken().flags_ |= TokenFlags::NUMBER_HAS_UNDERSCORE;
3613af6ab5fSopenharmony_ci            Iterator().Forward(1);
3623af6ab5fSopenharmony_ci            allowNumericOnNext = false;
3633af6ab5fSopenharmony_ci            continue;
3643af6ab5fSopenharmony_ci        }
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_ci        if (!allowNumericOnNext) {
3673af6ab5fSopenharmony_ci            Iterator().Backward(1);
3683af6ab5fSopenharmony_ci            ThrowError("Numeric separators are not allowed at the end of numeric literals");
3693af6ab5fSopenharmony_ci        }
3703af6ab5fSopenharmony_ci
3713af6ab5fSopenharmony_ci        break;
3723af6ab5fSopenharmony_ci    } while (true);
3733af6ab5fSopenharmony_ci
3743af6ab5fSopenharmony_ci    GetToken().number_ = number;
3753af6ab5fSopenharmony_ci}
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_citemplate <TokenType keyword_type>
3783af6ab5fSopenharmony_civoid Lexer::CheckKeyword([[maybe_unused]] TokenType type, [[maybe_unused]] LexerNextTokenFlags flags)
3793af6ab5fSopenharmony_ci{
3803af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
3813af6ab5fSopenharmony_ci    if constexpr (keyword_type == TokenType::KEYW_AWAIT) {
3823af6ab5fSopenharmony_ci        CheckAwaitKeyword();
3833af6ab5fSopenharmony_ci        return;
3843af6ab5fSopenharmony_ci    }
3853af6ab5fSopenharmony_ci
3863af6ab5fSopenharmony_ci    if constexpr (keyword_type == TokenType::KEYW_ARGUMENTS) {
3873af6ab5fSopenharmony_ci        CheckArgumentsKeyword();
3883af6ab5fSopenharmony_ci    }
3893af6ab5fSopenharmony_ci
3903af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
3913af6ab5fSopenharmony_ci    if constexpr (keyword_type == TokenType::KEYW_ENUM) {
3923af6ab5fSopenharmony_ci        CheckEnumKeyword();
3933af6ab5fSopenharmony_ci        return;
3943af6ab5fSopenharmony_ci    }
3953af6ab5fSopenharmony_ci
3963af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
3973af6ab5fSopenharmony_ci    if constexpr (keyword_type == TokenType::KEYW_YIELD) {
3983af6ab5fSopenharmony_ci        CheckYieldKeyword();
3993af6ab5fSopenharmony_ci        return;
4003af6ab5fSopenharmony_ci    }
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
4033af6ab5fSopenharmony_ci    if constexpr (keyword_type == TokenType::KEYW_LET) {
4043af6ab5fSopenharmony_ci        CheckLetKeyword();
4053af6ab5fSopenharmony_ci        return;
4063af6ab5fSopenharmony_ci    }
4073af6ab5fSopenharmony_ci
4083af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
4093af6ab5fSopenharmony_ci    if constexpr (keyword_type <= TokenType::KEYW_ASYNC) {
4103af6ab5fSopenharmony_ci        CheckKeywordEscape(type);
4113af6ab5fSopenharmony_ci        return;
4123af6ab5fSopenharmony_ci    }
4133af6ab5fSopenharmony_ci
4143af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
4153af6ab5fSopenharmony_ci    if constexpr (keyword_type >= TokenType::KEYW_PUBLIC) {
4163af6ab5fSopenharmony_ci        // NOLINTNEXTLINE
4173af6ab5fSopenharmony_ci        CheckFutureReservedKeyword(keyword_type);
4183af6ab5fSopenharmony_ci        return;
4193af6ab5fSopenharmony_ci    }
4203af6ab5fSopenharmony_ci
4213af6ab5fSopenharmony_ci    GetToken().type_ = TokenType::LITERAL_IDENT;
4223af6ab5fSopenharmony_ci}
4233af6ab5fSopenharmony_ci
4243af6ab5fSopenharmony_ciinline uint32_t Lexer::HexValue(char32_t ch)
4253af6ab5fSopenharmony_ci{
4263af6ab5fSopenharmony_ci    constexpr uint32_t HEX_MASK = 0xF;
4273af6ab5fSopenharmony_ci    constexpr uint32_t DEC_OFFSET = 10;
4283af6ab5fSopenharmony_ci    return ch < LEX_CHAR_UPPERCASE_A ? ch - LEX_CHAR_0 : ((ch - LEX_CHAR_UPPERCASE_A + DEC_OFFSET) & HEX_MASK);
4293af6ab5fSopenharmony_ci}
4303af6ab5fSopenharmony_ci
4313af6ab5fSopenharmony_ciinline bool Lexer::IsDecimalDigit(uint32_t cp)
4323af6ab5fSopenharmony_ci{
4333af6ab5fSopenharmony_ci    return (cp >= LEX_CHAR_0 && cp <= LEX_CHAR_9);
4343af6ab5fSopenharmony_ci}
4353af6ab5fSopenharmony_ci
4363af6ab5fSopenharmony_ciinline bool Lexer::IsHexDigit(char32_t ch)
4373af6ab5fSopenharmony_ci{
4383af6ab5fSopenharmony_ci    return ch < LEX_ASCII_MAX_BITS && std::isxdigit(static_cast<unsigned char>(ch));
4393af6ab5fSopenharmony_ci}
4403af6ab5fSopenharmony_ci
4413af6ab5fSopenharmony_ciinline bool Lexer::IsBinaryDigit(char32_t ch)
4423af6ab5fSopenharmony_ci{
4433af6ab5fSopenharmony_ci    return ch == LEX_CHAR_0 || ch == LEX_CHAR_1;
4443af6ab5fSopenharmony_ci}
4453af6ab5fSopenharmony_ci
4463af6ab5fSopenharmony_ciinline bool Lexer::IsOctalDigit(char32_t ch)
4473af6ab5fSopenharmony_ci{
4483af6ab5fSopenharmony_ci    return (ch >= LEX_CHAR_0 && ch <= LEX_CHAR_7);
4493af6ab5fSopenharmony_ci}
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci}  // namespace panda::es2panda::lexer
4523af6ab5fSopenharmony_ci
4533af6ab5fSopenharmony_ci#endif
454