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