1/**
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "lexer.h"
17
18#include "es2panda.h"
19#include "generated/keywords.h"
20#include "lexer/token/letters.h"
21#include "lexer/token/tokenType.h"
22#include "parser/context/parserContext.h"
23#include "parser/program/program.h"
24
25#include <array>
26
27namespace ark::es2panda::lexer {
28LexerPosition::LexerPosition(const util::StringView &source) : iterator_(source) {}
29
30Lexer::Lexer(const parser::ParserContext *parserContext, bool startLexer)
31    : allocator_(parserContext->GetProgram()->Allocator()),
32      parserContext_(parserContext),
33      source_(parserContext->GetProgram()->SourceCode()),
34      pos_(source_)
35{
36    if (startLexer) {
37        SkipWhiteSpaces();
38    }
39}
40
41char32_t Lexer::ScanUnicodeEscapeSequence()
42{
43    ASSERT(Iterator().Peek() == LEX_CHAR_LOWERCASE_U);
44    auto constexpr UNICODE_ESCAPE_SEQUENCE_LENGTH = 4;
45
46    Iterator().Forward(1);
47
48    if (Iterator().Peek() == LEX_CHAR_LEFT_BRACE) {
49        Iterator().Forward(1);
50        return ScanUnicodeCodePointEscape();
51    }
52
53    if (parserContext_->GetProgram()->Extension() == ScriptExtension::AS) {
54        return ScanHexEscape<UNICODE_ESCAPE_SEQUENCE_LENGTH, true>();
55    }
56
57    return ScanHexEscape<UNICODE_ESCAPE_SEQUENCE_LENGTH>();
58}
59
60//  '/u{...}' escape sequence should have at least one hex digit inside brackets!
61char32_t Lexer::ScanUnicodeCodePointEscape()
62{
63    double code = 0;
64    char32_t cp = Iterator().Peek();
65    if (!IsHexDigit(cp)) {
66        ThrowError("Invalid unicode escape sequence");
67    }
68
69    while (true) {
70        Iterator().Forward(1);
71
72        constexpr auto MULTIPLIER = 16;
73        code = code * MULTIPLIER + HexValue(cp);
74        if (code > UNICODE_CODE_POINT_MAX) {
75            ThrowError("Invalid unicode escape sequence");
76        }
77
78        cp = Iterator().Peek();
79        if (!IsHexDigit(cp)) {
80            break;
81        }
82    }
83
84    if (cp != LEX_CHAR_RIGHT_BRACE) {
85        ThrowError("Invalid unicode escape sequence");
86    }
87
88    Iterator().Forward(1);
89    return static_cast<char32_t>(code);
90}
91
92ArenaAllocator *Lexer::Allocator()
93{
94    return allocator_;
95}
96
97Token &Lexer::GetToken()
98{
99    return pos_.token_;
100}
101
102const Token &Lexer::GetToken() const
103{
104    return pos_.token_;
105}
106
107size_t Lexer::Line() const
108{
109    return pos_.line_;
110}
111
112LexerPosition Lexer::Save() const
113{
114    return pos_;
115}
116
117void Lexer::BackwardToken(TokenType type, size_t offset)
118{
119    pos_.token_.type_ = type;
120    pos_.iterator_.Reset(GetToken().End().index - offset);
121    pos_.nextTokenLine_ = 0;
122}
123
124void Lexer::ForwardToken(TokenType type, size_t offset)
125{
126    pos_.token_.type_ = type;
127    pos_.iterator_.Forward(offset);
128    SkipWhiteSpaces();
129}
130
131void Lexer::Rewind(const LexerPosition &pos)
132{
133    pos_ = pos;
134}
135
136char32_t Lexer::Lookahead()
137{
138    return Iterator().Peek();
139}
140
141util::StringView Lexer::SourceView(const util::StringView::Iterator &begin, const util::StringView::Iterator &end) const
142{
143    return SourceView(begin.Index(), end.Index());
144}
145
146util::StringView Lexer::SourceView(size_t begin, size_t end) const
147{
148    return source_.Substr(begin, end);
149}
150
151void Lexer::SkipMultiLineComment()
152{
153    while (true) {
154        switch (Iterator().Next()) {
155            case util::StringView::Iterator::INVALID_CP: {
156                ThrowError("Unterminated multi-line comment");
157            }
158            case LEX_CHAR_LF:
159            case LEX_CHAR_CR:
160            case LEX_CHAR_LS:
161            case LEX_CHAR_PS: {
162                pos_.nextTokenLine_++;
163                continue;
164            }
165            case LEX_CHAR_ASTERISK: {
166                if (Iterator().Peek() == LEX_CHAR_SLASH) {
167                    Iterator().Forward(1);
168                    return;
169                }
170
171                break;
172            }
173            default: {
174                break;
175            }
176        }
177    }
178}
179
180/* New line character is not processed */
181void Lexer::SkipSingleLineComment()
182{
183    while (true) {
184        switch (Iterator().Next()) {
185            case util::StringView::Iterator::INVALID_CP:
186            case LEX_CHAR_CR: {
187                if (Iterator().Peek() == LEX_CHAR_LF) {
188                    Iterator().Forward(1);
189                }
190
191                [[fallthrough]];
192            }
193            case LEX_CHAR_LF:
194            case LEX_CHAR_LS:
195            case LEX_CHAR_PS: {
196                pos_.nextTokenLine_++;
197                return;
198            }
199            default: {
200                break;
201            }
202        }
203    }
204}
205
206[[noreturn]] void Lexer::ThrowUnexpectedToken(lexer::TokenType tokenType) const
207{
208    std::stringstream ss;
209    ss << "Unexpected token: '" << TokenToString(tokenType) << "'.";
210    ThrowError(ss.str());
211}
212
213[[noreturn]] void Lexer::ThrowError(std::string_view message) const
214{
215    lexer::LineIndex index(source_);
216    lexer::SourceLocation loc = index.GetLocation(SourcePosition(Iterator().Index(), pos_.line_));
217
218    throw Error(es2panda::ErrorType::SYNTAX, parserContext_->GetProgram()->SourceFilePath().Utf8(), message, loc.line,
219                loc.col);
220}
221
222void Lexer::CheckNumberLiteralEnd()
223{
224    if (Iterator().Peek() == LEX_CHAR_LOWERCASE_N) {
225        GetToken().flags_ |= TokenFlags::NUMBER_BIGINT;
226        GetToken().src_ = SourceView(GetToken().Start().index, Iterator().Index());
227        Iterator().Forward(1);
228    } else {
229        GetToken().src_ = SourceView(GetToken().Start().index, Iterator().Index());
230    }
231
232    const auto nextCp = Iterator().PeekCp();
233    if (KeywordsUtil::IsIdentifierStart(nextCp) || IsDecimalDigit(nextCp)) {
234        ThrowError("Invalid numeric literal");
235    }
236}
237
238void Lexer::ScanDecimalNumbers()
239{
240    bool allowNumericOnNext = true;
241
242    while (true) {
243        switch (Iterator().Peek()) {
244            case LEX_CHAR_0:
245            case LEX_CHAR_1:
246            case LEX_CHAR_2:
247            case LEX_CHAR_3:
248            case LEX_CHAR_4:
249            case LEX_CHAR_5:
250            case LEX_CHAR_6:
251            case LEX_CHAR_7:
252            case LEX_CHAR_8:
253            case LEX_CHAR_9: {
254                Iterator().Forward(1);
255                allowNumericOnNext = true;
256                break;
257            }
258            case LEX_CHAR_UNDERSCORE: {
259                Iterator().Backward(1);
260
261                if (Iterator().Peek() == LEX_CHAR_DOT || !allowNumericOnNext) {
262                    Iterator().Forward(1);
263                    ThrowError("Invalid numeric separator");
264                }
265
266                GetToken().flags_ |= TokenFlags::NUMBER_HAS_UNDERSCORE;
267                Iterator().Forward(2U);
268                allowNumericOnNext = false;
269                break;
270            }
271            default: {
272                if (!allowNumericOnNext) {
273                    ThrowError("Numeric separators are not allowed at the end of numeric literals");
274                }
275                return;
276            }
277        }
278    }
279}
280
281void Lexer::ConvertNumber(const std::string &utf8, [[maybe_unused]] NumberFlags flags)
282{
283    ConversionResult res;
284    const long double temp = StrToNumeric(&std::strtold, utf8.c_str(), res);
285    if (res == ConversionResult::SUCCESS) {
286        GetToken().number_ = Number(GetToken().src_, static_cast<double>(temp));
287    } else if (res == ConversionResult::INVALID_ARGUMENT) {
288        ThrowError("Invalid number");
289    } else if (res == ConversionResult::OUT_OF_RANGE) {
290        GetToken().number_ = Number(GetToken().src_, std::numeric_limits<double>::infinity());
291    }
292}
293
294void Lexer::ScanNumber(bool allowBigInt)
295{
296    const bool isPeriod = GetToken().type_ == TokenType::PUNCTUATOR_PERIOD;
297    GetToken().type_ = TokenType::LITERAL_NUMBER;
298    GetToken().keywordType_ = TokenType::LITERAL_NUMBER;
299
300    if (!isPeriod) {
301        ScanDecimalNumbers();
302    }
303
304    size_t exponentSignPos = std::numeric_limits<size_t>::max();
305    bool parseExponent = true;
306    auto flags = NumberFlags::NONE;
307
308    if (Iterator().Peek() == LEX_CHAR_DOT || isPeriod) {
309        flags |= NumberFlags::DECIMAL_POINT;
310        allowBigInt = false;
311        if (!isPeriod) {
312            Iterator().Forward(1);
313        }
314
315        auto cp = Iterator().Peek();
316        if (IsDecimalDigit(cp) || cp == LEX_CHAR_LOWERCASE_E || cp == LEX_CHAR_UPPERCASE_E) {
317            ScanDecimalNumbers();
318        } else {
319            parseExponent = false;
320        }
321    }
322
323    std::tie(exponentSignPos, allowBigInt, flags) = ScanCharLex(allowBigInt, parseExponent, flags);
324
325    CheckNumberLiteralEnd();
326
327    if ((GetToken().flags_ & TokenFlags::NUMBER_BIGINT) != 0) {
328        if (!allowBigInt) {
329            ThrowError("Invalid BigInt number");
330        }
331
332        return;
333    }
334
335    util::StringView sv = SourceView(GetToken().Start().index, Iterator().Index());
336    std::string utf8 = std::string {sv.Utf8()};
337    bool needConversion = false;
338
339    if (exponentSignPos != std::numeric_limits<size_t>::max()) {
340        utf8.insert(exponentSignPos, 1, '+');
341        needConversion = true;
342    }
343
344    if ((GetToken().flags_ & TokenFlags::NUMBER_HAS_UNDERSCORE) != 0U) {
345        utf8.erase(std::remove(utf8.begin(), utf8.end(), LEX_CHAR_UNDERSCORE), utf8.end());
346        needConversion = true;
347    }
348
349    if (needConversion) {
350        util::UString converted(utf8, Allocator());
351        GetToken().src_ = converted.View();
352    } else {
353        GetToken().src_ = sv;
354    }
355
356    ConvertNumber(utf8, flags);
357}
358
359std::tuple<size_t, bool, NumberFlags> Lexer::ScanCharLex(bool allowBigInt, bool parseExponent, NumberFlags flags)
360{
361    size_t exponentSignPos = std::numeric_limits<size_t>::max();
362    switch (Iterator().Peek()) {
363        case LEX_CHAR_LOWERCASE_E:
364        case LEX_CHAR_UPPERCASE_E: {
365            allowBigInt = false;
366
367            if (!parseExponent) {
368                break;
369            }
370
371            flags |= NumberFlags::EXPONENT;
372
373            Iterator().Forward(1);
374
375            exponentSignPos = ScanSignOfNumber();
376
377            if (!IsDecimalDigit(Iterator().Peek())) {
378                ThrowError("Invalid numeric literal");
379            }
380            ScanDecimalNumbers();
381            break;
382        }
383        default: {
384            break;
385        }
386    }
387    return {exponentSignPos, allowBigInt, flags};
388}
389
390size_t Lexer::ScanSignOfNumber()
391{
392    size_t exponentSignPos = std::numeric_limits<size_t>::max();
393    switch (Iterator().Peek()) {
394        case LEX_CHAR_UNDERSCORE: {
395            break;
396        }
397        case LEX_CHAR_PLUS:
398        case LEX_CHAR_MINUS: {
399            Iterator().Forward(1);
400            break;
401        }
402        default: {
403            exponentSignPos = Iterator().Index() - GetToken().Start().index;
404            break;
405        }
406    }
407    return exponentSignPos;
408}
409
410void Lexer::PushTemplateContext(TemplateLiteralParserContext *ctx)
411{
412    tlCtx_ = ctx;
413}
414
415void Lexer::ScanTemplateStringEnd()
416{
417    ASSERT(Iterator().Peek() == LEX_CHAR_BACK_TICK);
418    Iterator().Forward(1);
419    SetTokenEnd();
420    SkipWhiteSpaces();
421}
422
423LexerTemplateString Lexer::ScanTemplateString()
424{
425    LexerTemplateString templateStr(Allocator());
426    size_t cpSize = 0U;
427
428    auto const checkOctalDigit = [this](char32_t const nextCp) -> void {
429        if (IsOctalDigit(nextCp)) {
430            Iterator().Forward(1);
431
432            if (Iterator().Peek() != LEX_CHAR_BACK_TICK) {
433                ThrowError("Octal escape sequences are not allowed in template strings");
434            }
435
436            Iterator().Backward(1);
437        }
438    };
439
440    while (true) {
441        char32_t cp = Iterator().PeekCp(&cpSize);
442
443        switch (cp) {
444            case util::StringView::Iterator::INVALID_CP: {
445                ThrowError("Unexpected token, expected '${' or '`'");
446                break;
447            }
448            case LEX_CHAR_BACK_TICK: {
449                templateStr.end = Iterator().Index();
450                return templateStr;
451            }
452            case LEX_CHAR_CR: {
453                Iterator().Forward(1);
454
455                if (Iterator().Peek() != LEX_CHAR_LF) {
456                    Iterator().Backward(1);
457                }
458
459                [[fallthrough]];
460            }
461            case LEX_CHAR_LF: {
462                pos_.line_++;
463                templateStr.str.Append(LEX_CHAR_LF);
464                Iterator().Forward(1);
465                continue;
466            }
467            case LEX_CHAR_BACKSLASH: {
468                Iterator().Forward(1);
469
470                char32_t nextCp = Iterator().Peek();
471                checkOctalDigit(nextCp);
472
473                if (nextCp == LEX_CHAR_BACK_TICK || nextCp == LEX_CHAR_BACKSLASH || nextCp == LEX_CHAR_DOLLAR_SIGN) {
474                    templateStr.str.Append(cp);
475                    templateStr.str.Append(nextCp);
476                    Iterator().Forward(1);
477                    continue;
478                }
479
480                Iterator().Backward(1);
481                break;
482            }
483            case LEX_CHAR_DOLLAR_SIGN: {
484                templateStr.end = Iterator().Index();
485                Iterator().Forward(1);
486
487                if (Iterator().Peek() == LEX_CHAR_LEFT_BRACE) {
488                    Iterator().Forward(1);
489                    templateStr.scanExpression = true;
490                    SkipWhiteSpaces();
491                    return templateStr;
492                }
493
494                templateStr.str.Append(cp);
495                continue;
496            }
497            default: {
498                break;
499            }
500        }
501
502        templateStr.str.Append(cp);
503        Iterator().Forward(cpSize);
504    }
505
506    UNREACHABLE();
507    return templateStr;
508}
509
510void Lexer::ResetTokenEnd()
511{
512    SetTokenStart();
513    pos_.iterator_.Reset(GetToken().End().index);
514    pos_.line_ = GetToken().End().line;
515    pos_.nextTokenLine_ = 0;
516}
517
518void Lexer::ScanStringUnicodePart(util::UString *str)
519{
520    if (auto cp = ScanUnicodeCharacter(); cp != util::StringView::Iterator::INVALID_CP) {
521        str->Append(cp);
522    }
523}
524
525char32_t Lexer::ScanUnicodeCharacter()
526{
527    size_t cpSize {};
528    char32_t cp = Iterator().PeekCp(&cpSize);
529
530    switch (cp) {
531        case util::StringView::Iterator::INVALID_CP: {
532            ThrowError("Unterminated string");
533            break;
534        }
535        case LEX_CHAR_CR: {
536            Iterator().Forward(1);
537            if (Iterator().Peek() != LEX_CHAR_LF) {
538                Iterator().Backward(1);
539            }
540
541            [[fallthrough]];
542        }
543        case LEX_CHAR_LS:
544        case LEX_CHAR_PS:
545        case LEX_CHAR_LF: {
546            pos_.line_++;
547            Iterator().Forward(cpSize);
548            return util::StringView::Iterator::INVALID_CP;
549        }
550        case LEX_CHAR_LOWERCASE_B: {
551            cp = LEX_CHAR_BS;
552            break;
553        }
554        case LEX_CHAR_LOWERCASE_T: {
555            cp = LEX_CHAR_TAB;
556            break;
557        }
558        case LEX_CHAR_LOWERCASE_N: {
559            cp = LEX_CHAR_LF;
560            break;
561        }
562        case LEX_CHAR_LOWERCASE_V: {
563            cp = LEX_CHAR_VT;
564            break;
565        }
566        case LEX_CHAR_LOWERCASE_F: {
567            cp = LEX_CHAR_FF;
568            break;
569        }
570        case LEX_CHAR_LOWERCASE_R: {
571            cp = LEX_CHAR_CR;
572            break;
573        }
574        case LEX_CHAR_LOWERCASE_X: {
575            Iterator().Forward(1);
576            cp = ScanHexEscape<2U>();
577            return cp;
578        }
579        case LEX_CHAR_LOWERCASE_U: {
580            cp = ScanUnicodeEscapeSequence();
581            return cp;
582        }
583        case LEX_CHAR_0: {
584            Iterator().Forward(1);
585            bool isDecimal = IsDecimalDigit(Iterator().Peek());
586            Iterator().Backward(1);
587
588            if (!isDecimal) {
589                cp = LEX_CHAR_NULL;
590                break;
591            }
592
593            [[fallthrough]];
594        }
595        default: {
596            if (IsDecimalDigit(Iterator().Peek())) {
597                ThrowError("Invalid character escape sequence in strict mode");
598            }
599
600            break;
601        }
602    }
603
604    Iterator().Forward(cpSize);
605    return cp;
606}
607
608void Lexer::ScanQuestionPunctuator()
609{
610    GetToken().type_ = TokenType::PUNCTUATOR_QUESTION_MARK;
611
612    switch (Iterator().Peek()) {
613        case LEX_CHAR_QUESTION: {
614            GetToken().type_ = TokenType::PUNCTUATOR_NULLISH_COALESCING;
615            Iterator().Forward(1);
616
617            switch (Iterator().Peek()) {
618                case LEX_CHAR_EQUALS: {
619                    GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL;
620                    Iterator().Forward(1);
621                    break;
622                }
623                default: {
624                    break;
625                }
626            }
627
628            break;
629        }
630        case LEX_CHAR_DOT: {
631            Iterator().Forward(1);
632
633            if (!IsDecimalDigit(Iterator().Peek())) {
634                GetToken().type_ = TokenType::PUNCTUATOR_QUESTION_DOT;
635                return;
636            }
637
638            Iterator().Backward(1);
639            break;
640        }
641        default: {
642            break;
643        }
644    }
645}
646
647void Lexer::ScanLessThanPunctuator()
648{
649    GetToken().type_ = TokenType::PUNCTUATOR_LESS_THAN;
650
651    switch (Iterator().Peek()) {
652        case LEX_CHAR_LESS_THAN: {
653            GetToken().type_ = TokenType::PUNCTUATOR_LEFT_SHIFT;
654            Iterator().Forward(1);
655
656            if (Iterator().Peek() == LEX_CHAR_EQUALS) {
657                GetToken().type_ = TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL;
658                Iterator().Forward(1);
659            }
660            break;
661        }
662        case LEX_CHAR_EQUALS: {
663            GetToken().type_ = TokenType::PUNCTUATOR_LESS_THAN_EQUAL;
664            Iterator().Forward(1);
665            break;
666        }
667        default: {
668            break;
669        }
670    }
671}
672
673void Lexer::ScanGreaterThanPunctuator()
674{
675    GetToken().type_ = TokenType::PUNCTUATOR_GREATER_THAN;
676
677    switch (Iterator().Peek()) {
678        case LEX_CHAR_GREATER_THAN: {
679            GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_SHIFT;
680            Iterator().Forward(1);
681
682            switch (Iterator().Peek()) {
683                case LEX_CHAR_GREATER_THAN: {
684                    GetToken().type_ = TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT;
685                    Iterator().Forward(1);
686
687                    if (Iterator().Peek() == LEX_CHAR_EQUALS) {
688                        GetToken().type_ = TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL;
689                        Iterator().Forward(1);
690                    }
691                    break;
692                }
693                case LEX_CHAR_EQUALS: {
694                    GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL;
695                    Iterator().Forward(1);
696                    break;
697                }
698                default: {
699                    break;
700                }
701            }
702            break;
703        }
704        case LEX_CHAR_EQUALS: {
705            GetToken().type_ = TokenType::PUNCTUATOR_GREATER_THAN_EQUAL;
706            Iterator().Forward(1);
707            break;
708        }
709        default: {
710            break;
711        }
712    }
713}
714
715void Lexer::ScanEqualsPunctuator()
716{
717    GetToken().type_ = TokenType::PUNCTUATOR_SUBSTITUTION;
718
719    switch (Iterator().Peek()) {
720        case LEX_CHAR_EQUALS: {
721            GetToken().type_ = TokenType::PUNCTUATOR_EQUAL;
722            Iterator().Forward(1);
723
724            if (Iterator().Peek() == LEX_CHAR_EQUALS) {
725                GetToken().type_ = TokenType::PUNCTUATOR_STRICT_EQUAL;
726                Iterator().Forward(1);
727            }
728            break;
729        }
730        case LEX_CHAR_GREATER_THAN: {
731            GetToken().type_ = TokenType::PUNCTUATOR_ARROW;
732            Iterator().Forward(1);
733            break;
734        }
735        default: {
736            break;
737        }
738    }
739}
740
741void Lexer::ScanExclamationPunctuator()
742{
743    GetToken().type_ = TokenType::PUNCTUATOR_EXCLAMATION_MARK;
744
745    switch (Iterator().Peek()) {
746        case LEX_CHAR_EQUALS: {
747            GetToken().type_ = TokenType::PUNCTUATOR_NOT_EQUAL;
748            Iterator().Forward(1);
749
750            if (Iterator().Peek() == LEX_CHAR_EQUALS) {
751                GetToken().type_ = TokenType::PUNCTUATOR_NOT_STRICT_EQUAL;
752                Iterator().Forward(1);
753            }
754            break;
755        }
756        default: {
757            break;
758        }
759    }
760}
761
762void Lexer::ScanAmpersandPunctuator()
763{
764    GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_AND;
765
766    switch (Iterator().Peek()) {
767        case LEX_CHAR_AMPERSAND: {
768            GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_AND;
769            Iterator().Forward(1);
770
771            switch (Iterator().Peek()) {
772                case LEX_CHAR_EQUALS: {
773                    GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL;
774                    Iterator().Forward(1);
775                    break;
776                }
777                default: {
778                    break;
779                }
780            }
781
782            break;
783        }
784        case LEX_CHAR_EQUALS: {
785            GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_AND_EQUAL;
786            Iterator().Forward(1);
787            break;
788        }
789        default: {
790            break;
791        }
792    }
793}
794
795void Lexer::ScanAtPunctuator()
796{
797    GetToken().type_ = TokenType::PUNCTUATOR_AT;
798
799    if (Iterator().Peek() == LEX_CHAR_AT) {
800        GetToken().type_ = TokenType::PUNCTUATOR_FORMAT;
801        Iterator().Forward(1U);
802    }
803}
804
805void Lexer::ScanVLinePunctuator()
806{
807    GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_OR;
808
809    switch (Iterator().Peek()) {
810        case LEX_CHAR_VLINE: {
811            GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_OR;
812            Iterator().Forward(1);
813
814            switch (Iterator().Peek()) {
815                case LEX_CHAR_EQUALS: {
816                    GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL;
817                    Iterator().Forward(1);
818                    break;
819                }
820                default: {
821                    break;
822                }
823            }
824
825            break;
826        }
827        case LEX_CHAR_EQUALS: {
828            GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_OR_EQUAL;
829            Iterator().Forward(1);
830            break;
831        }
832        default: {
833            break;
834        }
835    }
836}
837
838void Lexer::ScanCircumflexPunctuator()
839{
840    GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_XOR;
841
842    switch (Iterator().Peek()) {
843        case LEX_CHAR_EQUALS: {
844            GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL;
845            Iterator().Forward(1);
846            break;
847        }
848        default: {
849            break;
850        }
851    }
852}
853
854void Lexer::ScanPlusPunctuator()
855{
856    GetToken().type_ = TokenType::PUNCTUATOR_PLUS;
857
858    switch (Iterator().Peek()) {
859        case LEX_CHAR_PLUS: {
860            GetToken().type_ = TokenType::PUNCTUATOR_PLUS_PLUS;
861            Iterator().Forward(1);
862            break;
863        }
864        case LEX_CHAR_EQUALS: {
865            GetToken().type_ = TokenType::PUNCTUATOR_PLUS_EQUAL;
866            Iterator().Forward(1);
867            break;
868        }
869        default: {
870            break;
871        }
872    }
873}
874
875void Lexer::ScanMinusPunctuator()
876{
877    GetToken().type_ = TokenType::PUNCTUATOR_MINUS;
878
879    switch (Iterator().Peek()) {
880        case LEX_CHAR_MINUS: {
881            GetToken().type_ = TokenType::PUNCTUATOR_MINUS_MINUS;
882            Iterator().Forward(1);
883            break;
884        }
885        case LEX_CHAR_EQUALS: {
886            GetToken().type_ = TokenType::PUNCTUATOR_MINUS_EQUAL;
887            Iterator().Forward(1);
888            break;
889        }
890        default: {
891            break;
892        }
893    }
894}
895
896void Lexer::ScanSlashPunctuator()
897{
898    GetToken().type_ = TokenType::PUNCTUATOR_DIVIDE;
899
900    switch (Iterator().Peek()) {
901        case LEX_CHAR_EQUALS: {
902            GetToken().type_ = TokenType::PUNCTUATOR_DIVIDE_EQUAL;
903            Iterator().Forward(1);
904            break;
905        }
906        default: {
907            break;
908        }
909    }
910}
911
912void Lexer::ScanDotPunctuator()
913{
914    GetToken().type_ = TokenType::PUNCTUATOR_PERIOD;
915
916    switch (Iterator().Peek()) {
917        case LEX_CHAR_0:
918        case LEX_CHAR_1:
919        case LEX_CHAR_2:
920        case LEX_CHAR_3:
921        case LEX_CHAR_4:
922        case LEX_CHAR_5:
923        case LEX_CHAR_6:
924        case LEX_CHAR_7:
925        case LEX_CHAR_8:
926        case LEX_CHAR_9: {
927            ScanNumber();
928            break;
929        }
930        case LEX_CHAR_QUESTION: {
931            GetToken().type_ = TokenType::PUNCTUATOR_PERIOD_QUESTION;
932            Iterator().Forward(1);
933            break;
934        }
935        case LEX_CHAR_DOT: {
936            Iterator().Forward(1);
937
938            if (Iterator().Peek() == LEX_CHAR_DOT) {
939                GetToken().type_ = TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD;
940                Iterator().Forward(1);
941                break;
942            }
943
944            Iterator().Backward(1);
945            break;
946        }
947        default: {
948            break;
949        }
950    }
951}
952
953void Lexer::ScanAsteriskPunctuator()
954{
955    GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY;
956
957    switch (Iterator().Peek()) {
958        case LEX_CHAR_ASTERISK: {
959            GetToken().type_ = TokenType::PUNCTUATOR_EXPONENTIATION;
960            Iterator().Forward(1);
961
962            if (Iterator().Peek() == LEX_CHAR_EQUALS) {
963                GetToken().type_ = TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL;
964                Iterator().Forward(1);
965            }
966            break;
967        }
968        case LEX_CHAR_EQUALS: {
969            GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY_EQUAL;
970            Iterator().Forward(1);
971            break;
972        }
973        default: {
974            break;
975        }
976    }
977}
978
979void Lexer::ScanPercentPunctuator()
980{
981    GetToken().type_ = TokenType::PUNCTUATOR_MOD;
982
983    switch (Iterator().Peek()) {
984        case LEX_CHAR_EQUALS: {
985            GetToken().type_ = TokenType::PUNCTUATOR_MOD_EQUAL;
986            Iterator().Forward(1);
987            break;
988        }
989        default: {
990            break;
991        }
992    }
993}
994
995bool Lexer::IsLineTerminatorOrEos() const
996{
997    switch (Iterator().PeekCp()) {
998        case util::StringView::Iterator::INVALID_CP:
999        case LEX_CHAR_LF:
1000        case LEX_CHAR_CR:
1001        case LEX_CHAR_LS:
1002        case LEX_CHAR_PS: {
1003            return true;
1004        }
1005        default: {
1006            break;
1007        }
1008    }
1009
1010    return false;
1011}
1012
1013void Lexer::ScanRegExpPattern()
1014{
1015    bool isCharClass = false;
1016    size_t cpSize {};
1017
1018    while (true) {
1019        switch (Iterator().PeekCp(&cpSize)) {
1020            case util::StringView::Iterator::INVALID_CP:
1021            case LEX_CHAR_LF:
1022            case LEX_CHAR_CR:
1023            case LEX_CHAR_LS:
1024            case LEX_CHAR_PS: {
1025                ThrowError("Unterminated RegExp");
1026            }
1027            case LEX_CHAR_SLASH: {
1028                if (!isCharClass) {
1029                    return;
1030                }
1031
1032                break;
1033            }
1034            case LEX_CHAR_LEFT_SQUARE: {
1035                isCharClass = true;
1036                break;
1037            }
1038            case LEX_CHAR_RIGHT_SQUARE: {
1039                isCharClass = false;
1040                break;
1041            }
1042            case LEX_CHAR_BACKSLASH: {
1043                Iterator().Forward(1);
1044
1045                if (IsLineTerminatorOrEos()) {
1046                    continue;
1047                }
1048
1049                break;
1050            }
1051            default: {
1052                break;
1053            }
1054        }
1055
1056        Iterator().Forward(cpSize);
1057    }
1058}
1059
1060RegExpFlags Lexer::ScanRegExpFlags()
1061{
1062    RegExpFlags resultFlags = RegExpFlags::EMPTY;
1063
1064    while (true) {
1065        size_t cpSize {};
1066        auto cp = Iterator().PeekCp(&cpSize);
1067        if (!KeywordsUtil::IsIdentifierPart(cp)) {
1068            break;
1069        }
1070
1071        Iterator().Forward(cpSize);
1072
1073        RegExpFlags flag = RegExpFlags::EMPTY;
1074
1075        switch (cp) {
1076            case LEX_CHAR_LOWERCASE_G: {
1077                flag = RegExpFlags::GLOBAL;
1078                break;
1079            }
1080            case LEX_CHAR_LOWERCASE_I: {
1081                flag = RegExpFlags::IGNORE_CASE;
1082                break;
1083            }
1084            case LEX_CHAR_LOWERCASE_M: {
1085                flag = RegExpFlags::MULTILINE;
1086                break;
1087            }
1088            case LEX_CHAR_LOWERCASE_S: {
1089                flag = RegExpFlags::DOTALL;
1090                break;
1091            }
1092            case LEX_CHAR_LOWERCASE_U: {
1093                flag = RegExpFlags::UNICODE;
1094                break;
1095            }
1096            case LEX_CHAR_LOWERCASE_Y: {
1097                flag = RegExpFlags::STICKY;
1098                break;
1099            }
1100            case LEX_CHAR_SP: {
1101                return resultFlags;
1102            }
1103            default: {
1104                ThrowError("Invalid RegExp flag");
1105            }
1106        }
1107
1108        if (flag == RegExpFlags::EMPTY || (resultFlags & flag) != 0) {
1109            ThrowError("Invalid RegExp flag");
1110        }
1111
1112        resultFlags = resultFlags | flag;
1113    }
1114
1115    return resultFlags;
1116}
1117
1118void Lexer::CheckOctal()
1119{
1120    switch (Iterator().Peek()) {
1121        case LEX_CHAR_8:
1122        case LEX_CHAR_9: {
1123            ThrowError("Invalid octal digit");
1124        }
1125        default: {
1126            break;
1127        }
1128    }
1129}
1130
1131RegExp Lexer::ScanRegExp()
1132{
1133    // for proper handling such regexps as /=/
1134    if (GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL) {
1135        Iterator().Backward(1);
1136    }
1137
1138    GetToken().type_ = TokenType::LITERAL_REGEXP;
1139    GetToken().keywordType_ = TokenType::LITERAL_REGEXP;
1140
1141    const auto patternStart = Iterator().Index();
1142    ScanRegExpPattern();
1143    const auto pattern = SourceView(patternStart, Iterator().Index());
1144
1145    ASSERT(Iterator().Peek() == LEX_CHAR_SLASH);
1146    Iterator().Forward(1);
1147
1148    const auto flagsStart = Iterator().Index();
1149    RegExpFlags resultFlags = ScanRegExpFlags();
1150    const auto flags = SourceView(flagsStart, Iterator().Index());
1151
1152    SkipWhiteSpaces();
1153    SetTokenEnd();
1154
1155    return {pattern, flags, resultFlags};
1156}
1157
1158bool Lexer::CheckArrow()
1159{
1160    if (Iterator().Peek() != LEX_CHAR_EQUALS) {
1161        return false;
1162    }
1163    Iterator().Forward(1);
1164
1165    bool res = Iterator().Peek() == LEX_CHAR_GREATER_THAN;
1166    Iterator().Backward(1);
1167
1168    return res;
1169}
1170
1171void Lexer::SetTokenStart()
1172{
1173    if (pos_.nextTokenLine_ != 0) {
1174        pos_.line_ += pos_.nextTokenLine_;
1175        pos_.nextTokenLine_ = 0;
1176        GetToken().flags_ = TokenFlags::NEW_LINE;
1177    } else {
1178        GetToken().flags_ = TokenFlags::NONE;
1179    }
1180
1181    pos_.token_.loc_.start = SourcePosition {Iterator().Index(), pos_.line_};
1182    GetToken().keywordType_ = TokenType::EOS;
1183}
1184
1185void Lexer::SetTokenEnd()
1186{
1187    pos_.token_.loc_.end = SourcePosition {Iterator().Index(), pos_.line_};
1188}
1189
1190void Lexer::SkipWhiteSpaces()
1191{
1192    while (true) {
1193        auto cp = Iterator().Peek();
1194
1195        switch (cp) {
1196            case LEX_CHAR_CR: {
1197                Iterator().Forward(1);
1198
1199                if (Iterator().Peek() != LEX_CHAR_LF) {
1200                    Iterator().Backward(1);
1201                }
1202
1203                [[fallthrough]];
1204            }
1205            case LEX_CHAR_LF: {
1206                Iterator().Forward(1);
1207                pos_.nextTokenLine_++;
1208                continue;
1209            }
1210            case LEX_CHAR_VT:
1211            case LEX_CHAR_FF:
1212            case LEX_CHAR_SP:
1213            case LEX_CHAR_TAB: {
1214                Iterator().Forward(1);
1215                continue;
1216            }
1217            case LEX_CHAR_SLASH: {
1218                Iterator().Forward(1);
1219                cp = Iterator().Peek();
1220                if (cp == LEX_CHAR_SLASH) {
1221                    Iterator().Forward(1);
1222                    SkipSingleLineComment();
1223                    continue;
1224                }
1225                if (cp == LEX_CHAR_ASTERISK) {
1226                    Iterator().Forward(1);
1227                    SkipMultiLineComment();
1228                    continue;
1229                }
1230
1231                Iterator().Backward(1);
1232                return;
1233            }
1234            default: {
1235                if (cp < LEX_ASCII_MAX_BITS) {
1236                    return;
1237                }
1238
1239                size_t cpSize {};
1240                cp = Iterator().PeekCp(&cpSize);
1241
1242                switch (cp) {
1243                    case LEX_CHAR_LS:
1244                    case LEX_CHAR_PS: {
1245                        pos_.nextTokenLine_++;
1246                        [[fallthrough]];
1247                    }
1248                    case LEX_CHAR_NBSP:
1249                    case LEX_CHAR_ZWNBSP: {
1250                        Iterator().Forward(cpSize);
1251                        continue;
1252                    }
1253                    default: {
1254                        return;
1255                    }
1256                }
1257            }
1258        }
1259    }
1260}
1261
1262void Lexer::ScanHashMark()
1263{
1264    GetToken().type_ = TokenType::PUNCTUATOR_HASH_MARK;
1265}
1266
1267void Lexer::ScanBackTick()
1268{
1269    GetToken().type_ = TokenType::PUNCTUATOR_BACK_TICK;
1270    SetTokenEnd();
1271}
1272
1273// NOLINTNEXTLINE(google-default-arguments)
1274void Lexer::NextToken(NextTokenFlags flags)
1275{
1276    JSKeywords kws(this, flags);
1277    NextToken(&kws);
1278}
1279
1280void Lexer::ScanColonPunctuator()
1281{
1282    GetToken().type_ = TokenType::PUNCTUATOR_COLON;
1283}
1284
1285bool Lexer::ScanDollarPunctuator()
1286{
1287    return false;
1288}
1289
1290// NOLINTNEXTLINE(readability-function-size)
1291void Lexer::NextToken(Keywords *kws)
1292{
1293    KeywordsUtil &kwu = kws->Util();
1294
1295    SetTokenStart();
1296
1297    auto cp = Iterator().Peek();
1298    Iterator().Forward(1);
1299
1300    switch (cp) {
1301        case LEX_CHAR_EXCLAMATION: {
1302            ScanExclamationPunctuator();
1303            break;
1304        }
1305        case LEX_CHAR_SINGLE_QUOTE: {
1306            ScanString<LEX_CHAR_SINGLE_QUOTE>();
1307            break;
1308        }
1309        case LEX_CHAR_DOUBLE_QUOTE: {
1310            ScanString<LEX_CHAR_DOUBLE_QUOTE>();
1311            break;
1312        }
1313        case LEX_CHAR_HASH_MARK: {
1314            ScanHashMark();
1315            break;
1316        }
1317        case LEX_CHAR_PERCENT: {
1318            ScanPercentPunctuator();
1319            break;
1320        }
1321        case LEX_CHAR_AMPERSAND: {
1322            ScanAmpersandPunctuator();
1323            break;
1324        }
1325        case LEX_CHAR_LEFT_PAREN: {
1326            GetToken().type_ = TokenType::PUNCTUATOR_LEFT_PARENTHESIS;
1327            break;
1328        }
1329        case LEX_CHAR_RIGHT_PAREN: {
1330            GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_PARENTHESIS;
1331            break;
1332        }
1333        case LEX_CHAR_ASTERISK: {
1334            ScanAsteriskPunctuator();
1335            break;
1336        }
1337        case LEX_CHAR_PLUS: {
1338            ScanPlusPunctuator();
1339            break;
1340        }
1341        case LEX_CHAR_COMMA: {
1342            GetToken().type_ = TokenType::PUNCTUATOR_COMMA;
1343            break;
1344        }
1345        case LEX_CHAR_MINUS: {
1346            ScanMinusPunctuator();
1347            break;
1348        }
1349        case LEX_CHAR_DOT: {
1350            ScanDotPunctuator();
1351            break;
1352        }
1353        case LEX_CHAR_SLASH: {
1354            ScanSlashPunctuator();
1355            break;
1356        }
1357        case LEX_CHAR_0: {
1358            ScanNumberLeadingZero();
1359            break;
1360        }
1361        case LEX_CHAR_1:
1362        case LEX_CHAR_2:
1363        case LEX_CHAR_3:
1364        case LEX_CHAR_4:
1365        case LEX_CHAR_5:
1366        case LEX_CHAR_6:
1367        case LEX_CHAR_7:
1368        case LEX_CHAR_8:
1369        case LEX_CHAR_9: {
1370            ScanNumber();
1371            break;
1372        }
1373        case LEX_CHAR_COLON: {
1374            ScanColonPunctuator();
1375            break;
1376        }
1377        case LEX_CHAR_SEMICOLON: {
1378            GetToken().type_ = TokenType::PUNCTUATOR_SEMI_COLON;
1379            break;
1380        }
1381        case LEX_CHAR_LESS_THAN: {
1382            ScanLessThanPunctuator();
1383            break;
1384        }
1385        case LEX_CHAR_EQUALS: {
1386            ScanEqualsPunctuator();
1387            break;
1388        }
1389        case LEX_CHAR_GREATER_THAN: {
1390            ScanGreaterThanPunctuator();
1391            break;
1392        }
1393        case LEX_CHAR_QUESTION: {
1394            ScanQuestionPunctuator();
1395            break;
1396        }
1397        case LEX_CHAR_AT: {
1398            ScanAtPunctuator();
1399            break;
1400        }
1401        case LEX_CHAR_DOLLAR_SIGN: {
1402            if (ScanDollarPunctuator()) {
1403                break;
1404            }
1405
1406            [[fallthrough]];
1407        }
1408        case LEX_CHAR_UPPERCASE_A:
1409        case LEX_CHAR_UPPERCASE_B:
1410        case LEX_CHAR_UPPERCASE_C:
1411        case LEX_CHAR_UPPERCASE_D:
1412        case LEX_CHAR_UPPERCASE_E:
1413        case LEX_CHAR_UPPERCASE_F:
1414        case LEX_CHAR_UPPERCASE_G:
1415        case LEX_CHAR_UPPERCASE_H:
1416        case LEX_CHAR_UPPERCASE_I:
1417        case LEX_CHAR_UPPERCASE_J:
1418        case LEX_CHAR_UPPERCASE_K:
1419        case LEX_CHAR_UPPERCASE_L:
1420        case LEX_CHAR_UPPERCASE_M:
1421        case LEX_CHAR_UPPERCASE_N:
1422        case LEX_CHAR_UPPERCASE_O:
1423        case LEX_CHAR_UPPERCASE_P:
1424        case LEX_CHAR_UPPERCASE_Q:
1425        case LEX_CHAR_UPPERCASE_R:
1426        case LEX_CHAR_UPPERCASE_S:
1427        case LEX_CHAR_UPPERCASE_T:
1428        case LEX_CHAR_UPPERCASE_U:
1429        case LEX_CHAR_UPPERCASE_V:
1430        case LEX_CHAR_UPPERCASE_W:
1431        case LEX_CHAR_UPPERCASE_X:
1432        case LEX_CHAR_UPPERCASE_Y:
1433        case LEX_CHAR_UPPERCASE_Z:
1434        case LEX_CHAR_UNDERSCORE: {
1435            kwu.ScanIdContinue();
1436            break;
1437        }
1438        case LEX_CHAR_LEFT_SQUARE: {
1439            GetToken().type_ = TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
1440            break;
1441        }
1442        case LEX_CHAR_BACKSLASH: {
1443            GetToken().flags_ |= TokenFlags::HAS_ESCAPE;
1444
1445            if (Iterator().Peek() != LEX_CHAR_LOWERCASE_U) {
1446                ThrowError("Invalid character");
1447            }
1448
1449            cp = ScanUnicodeEscapeSequence();
1450
1451            kwu.ScanIdentifierStart(kws, cp);
1452            break;
1453        }
1454        case LEX_CHAR_RIGHT_SQUARE: {
1455            GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET;
1456            break;
1457        }
1458        case LEX_CHAR_CIRCUMFLEX: {
1459            ScanCircumflexPunctuator();
1460            break;
1461        }
1462        case LEX_CHAR_BACK_TICK: {
1463            ScanBackTick();
1464            return;
1465        }
1466        case LEX_CHAR_LOWERCASE_C: {
1467            if (ScanCharLiteral()) {
1468                break;
1469            }
1470        }
1471            [[fallthrough]];
1472        case LEX_CHAR_LOWERCASE_A:
1473        case LEX_CHAR_LOWERCASE_B:
1474        case LEX_CHAR_LOWERCASE_D:
1475        case LEX_CHAR_LOWERCASE_E:
1476        case LEX_CHAR_LOWERCASE_F:
1477        case LEX_CHAR_LOWERCASE_G:
1478        case LEX_CHAR_LOWERCASE_H:
1479        case LEX_CHAR_LOWERCASE_I:
1480        case LEX_CHAR_LOWERCASE_J:
1481        case LEX_CHAR_LOWERCASE_K:
1482        case LEX_CHAR_LOWERCASE_L:
1483        case LEX_CHAR_LOWERCASE_M:
1484        case LEX_CHAR_LOWERCASE_N:
1485        case LEX_CHAR_LOWERCASE_O:
1486        case LEX_CHAR_LOWERCASE_P:
1487        case LEX_CHAR_LOWERCASE_Q:
1488        case LEX_CHAR_LOWERCASE_R:
1489        case LEX_CHAR_LOWERCASE_S:
1490        case LEX_CHAR_LOWERCASE_T:
1491        case LEX_CHAR_LOWERCASE_U:
1492        case LEX_CHAR_LOWERCASE_V:
1493        case LEX_CHAR_LOWERCASE_W:
1494        case LEX_CHAR_LOWERCASE_X:
1495        case LEX_CHAR_LOWERCASE_Y:
1496        case LEX_CHAR_LOWERCASE_Z: {
1497            kws->ScanKeyword(cp);
1498            break;
1499        }
1500        case LEX_CHAR_LEFT_BRACE: {
1501            GetToken().type_ = TokenType::PUNCTUATOR_LEFT_BRACE;
1502
1503            if (tlCtx_ != nullptr) {
1504                tlCtx_->ConsumeLeftBrace();
1505            }
1506
1507            break;
1508        }
1509        case LEX_CHAR_VLINE: {
1510            ScanVLinePunctuator();
1511            break;
1512        }
1513        case LEX_CHAR_RIGHT_BRACE: {
1514            GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_BRACE;
1515
1516            if (tlCtx_ != nullptr && tlCtx_->ConsumeRightBrace()) {
1517                SetTokenEnd();
1518                return;
1519            }
1520
1521            break;
1522        }
1523        case LEX_CHAR_TILDE: {
1524            GetToken().type_ = TokenType::PUNCTUATOR_TILDE;
1525            break;
1526        }
1527        default: {
1528            Iterator().Backward(1);
1529
1530            if (cp == util::StringView::Iterator::INVALID_CP) {
1531                GetToken().type_ = TokenType::EOS;
1532                break;
1533            }
1534
1535            cp = Iterator().Next();
1536            kwu.ScanIdentifierStart(kws, cp);
1537            break;
1538        }
1539    }
1540
1541    SetTokenEnd();
1542    SkipWhiteSpaces();
1543}
1544
1545void Lexer::ScanNumberLeadingZeroImplNonAllowedCases()
1546{
1547    switch (Iterator().Peek()) {
1548        case LEX_CHAR_0:
1549        case LEX_CHAR_1:
1550        case LEX_CHAR_2:
1551        case LEX_CHAR_3:
1552        case LEX_CHAR_4:
1553        case LEX_CHAR_5:
1554        case LEX_CHAR_6:
1555        case LEX_CHAR_7: {
1556            ThrowError("Implicit octal literal not allowed");
1557        }
1558        case LEX_CHAR_8:
1559        case LEX_CHAR_9: {
1560            ThrowError("NonOctalDecimalIntegerLiteral is not enabled in strict mode code");
1561        }
1562        case LEX_CHAR_UNDERSCORE: {
1563            ThrowError("Numeric separator '_' is not allowed in numbers that start with '0'.");
1564        }
1565        default: {
1566            break;
1567        }
1568    }
1569}
1570
1571LexerPosition &Lexer::Pos()
1572{
1573    return pos_;
1574}
1575
1576const LexerPosition &Lexer::Pos() const
1577{
1578    return pos_;
1579}
1580}  // namespace ark::es2panda::lexer
1581