• 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                 default: {
254                     break;
255                 }
256             }
257 
258             CheckNumberLiteralEnd();
259             return;
260         }
261         case LEX_CHAR_0:
262         case LEX_CHAR_1:
263         case LEX_CHAR_2:
264         case LEX_CHAR_3:
265         case LEX_CHAR_4:
266         case LEX_CHAR_5:
267         case LEX_CHAR_6:
268         case LEX_CHAR_7: {
269             ThrowError("Implicit octal literal not allowed");
270             break;
271         }
272         case LEX_CHAR_8:
273         case LEX_CHAR_9: {
274             ThrowError("NonOctalDecimalIntegerLiteral is not enabled in strict mode code");
275             break;
276         }
277         default: {
278             break;
279         }
280     }
281 
282     ScanNumber(Iterator().Peek() == LEX_CHAR_0);
283 }
284 
ScanDecimalNumbers(bool allowNumericSeparator)285 void Lexer::ScanDecimalNumbers(bool allowNumericSeparator)
286 {
287     bool allowNumericOnNext = true;
288 
289     while (true) {
290         switch (Iterator().Peek()) {
291             case LEX_CHAR_0:
292             case LEX_CHAR_1:
293             case LEX_CHAR_2:
294             case LEX_CHAR_3:
295             case LEX_CHAR_4:
296             case LEX_CHAR_5:
297             case LEX_CHAR_6:
298             case LEX_CHAR_7:
299             case LEX_CHAR_8:
300             case LEX_CHAR_9: {
301                 Iterator().Forward(1);
302                 allowNumericOnNext = true;
303                 break;
304             }
305             case LEX_CHAR_UNDERSCORE: {
306                 Iterator().Backward(1);
307                 isUnderscore_ = true;
308 
309                 if (Iterator().Peek() == LEX_CHAR_DOT || !allowNumericSeparator || !allowNumericOnNext) {
310                     Iterator().Forward(1);
311                     ThrowError("Invalid numeric separator");
312                 }
313 
314                 GetToken().flags_ |= TokenFlags::NUMBER_HAS_UNDERSCORE;
315                 Iterator().Forward(2);
316                 allowNumericOnNext = false;
317                 break;
318             }
319             default: {
320                 if (!allowNumericOnNext) {
321                     ThrowError("Numeric separators are not allowed at the end of numeric literals");
322                 }
323                 return;
324             }
325         }
326     }
327 }
328 
ConvertNumber(size_t exponentSignPos)329 void Lexer::ConvertNumber(size_t exponentSignPos)
330 {
331     util::StringView sv = SourceView(GetToken().Start().index, Iterator().Index());
332     std::string utf8 = std::string {sv.Utf8()};
333     bool needConversion = false;
334 
335     if (exponentSignPos != std::numeric_limits<size_t>::max()) {
336         utf8.insert(exponentSignPos, 1, '+');
337         needConversion = true;
338     }
339 
340     if (GetToken().flags_ & TokenFlags::NUMBER_HAS_UNDERSCORE) {
341         utf8.erase(std::remove(utf8.begin(), utf8.end(), LEX_CHAR_UNDERSCORE), utf8.end());
342         needConversion = true;
343     }
344 
345     if (needConversion) {
346         util::UString converted(utf8, Allocator());
347         GetToken().src_ = converted.View();
348     } else {
349         GetToken().src_ = sv;
350     }
351 
352     try {
353         GetToken().number_ = static_cast<double>(std::stold(utf8, nullptr));
354     } catch (const std::invalid_argument &) {
355         ThrowError("Invalid number");
356     } catch (const std::out_of_range &) {
357         // TODO(frobert): look for a more elegant solution to this
358         GetToken().number_ = std::numeric_limits<double>::infinity();
359     }
360 }
ScanNumber(bool allowNumericSeparator,bool allowBigInt)361 void Lexer::ScanNumber(bool allowNumericSeparator, bool allowBigInt)
362 {
363     GetToken().type_ = TokenType::LITERAL_NUMBER;
364 
365     ScanDecimalNumbers(allowNumericSeparator);
366 
367     size_t exponentSignPos = std::numeric_limits<size_t>::max();
368     bool parseExponent = true;
369 
370     if (Iterator().Peek() == LEX_CHAR_DOT) {
371         allowBigInt = false;
372         Iterator().Forward(1);
373 
374         auto cp = Iterator().Peek();
375         if (IsDecimalDigit(cp) || cp == LEX_CHAR_LOWERCASE_E || LEX_CHAR_UPPERCASE_E) {
376             ScanDecimalNumbers(allowNumericSeparator);
377         } else {
378             parseExponent = false;
379         }
380     }
381 
382     switch (Iterator().Peek()) {
383         case LEX_CHAR_LOWERCASE_E:
384         case LEX_CHAR_UPPERCASE_E: {
385             allowBigInt = false;
386 
387             if (!parseExponent) {
388                 break;
389             }
390 
391             Iterator().Forward(1);
392 
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 
408             if (!IsDecimalDigit(Iterator().Peek())) {
409                 ThrowError("Invalid numeric literal");
410             }
411             ScanDecimalNumbers(allowNumericSeparator);
412             break;
413         }
414         default: {
415             break;
416         }
417     }
418 
419     CheckNumberLiteralEnd();
420 
421     if (GetToken().flags_ & TokenFlags::NUMBER_BIGINT) {
422         if (!allowBigInt) {
423             ThrowError("Invalid BigInt number");
424         }
425         if (isUnderscore_) {
426             ConvertNumber(exponentSignPos);
427             isUnderscore_ = false;
428         }
429 
430         return;
431     }
432 
433     ConvertNumber(exponentSignPos);
434 }
435 
PushTemplateContext(TemplateLiteralParserContext * ctx)436 void Lexer::PushTemplateContext(TemplateLiteralParserContext *ctx)
437 {
438     tlCtx_ = ctx;
439 }
440 
ScanTemplateStringEnd()441 void Lexer::ScanTemplateStringEnd()
442 {
443     ASSERT(Iterator().Peek() == LEX_CHAR_BACK_TICK);
444     Iterator().Forward(1);
445     SetTokenEnd();
446     SkipWhiteSpaces();
447 }
448 
ScanTemplateString()449 LexerTemplateString Lexer::ScanTemplateString()
450 {
451     LexerTemplateString templateStr(Allocator());
452     size_t cpSize = 0;
453 
454     while (true) {
455         char32_t cp = Iterator().PeekCp(&cpSize);
456 
457         switch (cp) {
458             case util::StringView::Iterator::INVALID_CP: {
459                 ThrowError("Unexpected token, expected '${' or '`'");
460                 break;
461             }
462             case LEX_CHAR_BACK_TICK: {
463                 templateStr.end = Iterator().Index();
464                 return templateStr;
465             }
466             case LEX_CHAR_CR: {
467                 Iterator().Forward(1);
468 
469                 if (Iterator().Peek() != LEX_CHAR_LF) {
470                     Iterator().Backward(1);
471                 }
472 
473                 [[fallthrough]];
474             }
475             case LEX_CHAR_LF: {
476                 pos_.line++;
477                 templateStr.str.Append(LEX_CHAR_LF);
478                 Iterator().Forward(1);
479                 continue;
480             }
481             case LEX_CHAR_BACKSLASH: {
482                 Iterator().Forward(1);
483 
484                 char32_t nextCp = Iterator().Peek();
485                 if (nextCp == LEX_CHAR_BACK_TICK || nextCp == LEX_CHAR_BACKSLASH || nextCp == LEX_CHAR_DOLLAR_SIGN) {
486                     templateStr.str.Append(cp);
487                     templateStr.str.Append(nextCp);
488                     Iterator().Forward(1);
489                     continue;
490                 }
491 
492                 Iterator().Backward(1);
493                 break;
494             }
495             case LEX_CHAR_DOLLAR_SIGN: {
496                 templateStr.end = Iterator().Index();
497                 Iterator().Forward(1);
498 
499                 if (Iterator().Peek() == LEX_CHAR_LEFT_BRACE) {
500                     Iterator().Forward(1);
501                     templateStr.scanExpression = true;
502                     SkipWhiteSpaces();
503                     return templateStr;
504                 }
505 
506                 templateStr.str.Append(cp);
507                 continue;
508             }
509             default: {
510                 break;
511             }
512         }
513 
514         templateStr.str.Append(cp);
515         Iterator().Forward(cpSize);
516     }
517 
518     UNREACHABLE();
519     return templateStr;
520 }
521 
ResetTokenEnd()522 void Lexer::ResetTokenEnd()
523 {
524     SetTokenStart();
525     pos_.iterator.Reset(GetToken().End().index);
526     pos_.line = GetToken().End().line;
527     pos_.nextTokenLine = 0;
528 }
529 
ScanStringUnicodePart(util::UString * str)530 void Lexer::ScanStringUnicodePart(util::UString *str)
531 {
532     size_t cpSize {};
533     char32_t cp = Iterator().PeekCp(&cpSize);
534 
535     switch (cp) {
536         case util::StringView::Iterator::INVALID_CP: {
537             ThrowError("Unterminated string");
538             break;
539         }
540         case LEX_CHAR_CR: {
541             Iterator().Forward(1);
542             if (Iterator().Peek() != LEX_CHAR_LF) {
543                 Iterator().Backward(1);
544             }
545 
546             [[fallthrough]];
547         }
548         case LEX_CHAR_LS:
549         case LEX_CHAR_PS:
550         case LEX_CHAR_LF: {
551             pos_.line++;
552             Iterator().Forward(cpSize);
553             return;
554         }
555         case LEX_CHAR_LOWERCASE_B: {
556             cp = LEX_CHAR_BS;
557             break;
558         }
559         case LEX_CHAR_LOWERCASE_T: {
560             cp = LEX_CHAR_TAB;
561             break;
562         }
563         case LEX_CHAR_LOWERCASE_N: {
564             cp = LEX_CHAR_LF;
565             break;
566         }
567         case LEX_CHAR_LOWERCASE_V: {
568             cp = LEX_CHAR_VT;
569             break;
570         }
571         case LEX_CHAR_LOWERCASE_F: {
572             cp = LEX_CHAR_FF;
573             break;
574         }
575         case LEX_CHAR_LOWERCASE_R: {
576             cp = LEX_CHAR_CR;
577             break;
578         }
579         case LEX_CHAR_LOWERCASE_X: {
580             Iterator().Forward(1);
581             str->Append(ScanHexEscape<2>());
582             return;
583         }
584         case LEX_CHAR_LOWERCASE_U: {
585             cp = ScanUnicodeEscapeSequence();
586             str->Append(cp);
587             return;
588         }
589         case LEX_CHAR_0: {
590             Iterator().Forward(1);
591             bool isDecimal = IsDecimalDigit(Iterator().Peek());
592             bool isOctal = IsOctalDigit(Iterator().Peek());
593             Iterator().Backward(1);
594 
595             if (!isDecimal) {
596                 cp = LEX_CHAR_NULL;
597                 break;
598             }
599 
600             if (isOctal) {
601                 ThrowError("Octal escape sequences are not allowed in strict mode");
602             }
603 
604             [[fallthrough]];
605         }
606         default: {
607             if (IsDecimalDigit(Iterator().Peek())) {
608                 ThrowError("Invalid character escape sequence in strict mode");
609             }
610 
611             break;
612         }
613     }
614 
615     Iterator().Forward(cpSize);
616     str->Append(cp);
617 }
618 
ScanQuestionPunctuator()619 void Lexer::ScanQuestionPunctuator()
620 {
621     GetToken().type_ = TokenType::PUNCTUATOR_QUESTION_MARK;
622 
623     switch (Iterator().Peek()) {
624         case LEX_CHAR_QUESTION: {
625             GetToken().type_ = TokenType::PUNCTUATOR_NULLISH_COALESCING;
626             Iterator().Forward(1);
627 
628             switch (Iterator().Peek()) {
629                 case LEX_CHAR_EQUALS: {
630                     GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL;
631                     Iterator().Forward(1);
632                     break;
633                 }
634                 default: {
635                     break;
636                 }
637             }
638 
639             break;
640         }
641         case LEX_CHAR_DOT: {
642             Iterator().Forward(1);
643 
644             if (!IsDecimalDigit(Iterator().Peek())) {
645                 GetToken().type_ = TokenType::PUNCTUATOR_QUESTION_DOT;
646                 return;
647             }
648 
649             Iterator().Backward(1);
650             break;
651         }
652         default: {
653             break;
654         }
655     }
656 }
657 
ScanLessThanPunctuator()658 void Lexer::ScanLessThanPunctuator()
659 {
660     GetToken().type_ = TokenType::PUNCTUATOR_LESS_THAN;
661 
662     switch (Iterator().Peek()) {
663         case LEX_CHAR_LESS_THAN: {
664             GetToken().type_ = TokenType::PUNCTUATOR_LEFT_SHIFT;
665             Iterator().Forward(1);
666 
667             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
668                 GetToken().type_ = TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL;
669                 Iterator().Forward(1);
670             }
671             break;
672         }
673         case LEX_CHAR_EQUALS: {
674             GetToken().type_ = TokenType::PUNCTUATOR_LESS_THAN_EQUAL;
675             Iterator().Forward(1);
676             break;
677         }
678         default: {
679             break;
680         }
681     }
682 }
683 
ScanGreaterThanPunctuator()684 void Lexer::ScanGreaterThanPunctuator()
685 {
686     GetToken().type_ = TokenType::PUNCTUATOR_GREATER_THAN;
687 
688     switch (Iterator().Peek()) {
689         case LEX_CHAR_GREATER_THAN: {
690             GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_SHIFT;
691             Iterator().Forward(1);
692 
693             switch (Iterator().Peek()) {
694                 case LEX_CHAR_GREATER_THAN: {
695                     GetToken().type_ = TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT;
696                     Iterator().Forward(1);
697 
698                     if (Iterator().Peek() == LEX_CHAR_EQUALS) {
699                         GetToken().type_ = TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL;
700                         Iterator().Forward(1);
701                     }
702                     break;
703                 }
704                 case LEX_CHAR_EQUALS: {
705                     GetToken().type_ = TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL;
706                     Iterator().Forward(1);
707                     break;
708                 }
709                 default: {
710                     break;
711                 }
712             }
713             break;
714         }
715         case LEX_CHAR_EQUALS: {
716             GetToken().type_ = TokenType::PUNCTUATOR_GREATER_THAN_EQUAL;
717             Iterator().Forward(1);
718             break;
719         }
720         default: {
721             break;
722         }
723     }
724 }
725 
ScanEqualsPunctuator()726 void Lexer::ScanEqualsPunctuator()
727 {
728     GetToken().type_ = TokenType::PUNCTUATOR_SUBSTITUTION;
729 
730     switch (Iterator().Peek()) {
731         case LEX_CHAR_EQUALS: {
732             GetToken().type_ = TokenType::PUNCTUATOR_EQUAL;
733             Iterator().Forward(1);
734 
735             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
736                 GetToken().type_ = TokenType::PUNCTUATOR_STRICT_EQUAL;
737                 Iterator().Forward(1);
738             }
739             break;
740         }
741         case LEX_CHAR_GREATER_THAN: {
742             GetToken().type_ = TokenType::PUNCTUATOR_ARROW;
743             Iterator().Forward(1);
744             break;
745         }
746         default: {
747             break;
748         }
749     }
750 }
751 
ScanExclamationPunctuator()752 void Lexer::ScanExclamationPunctuator()
753 {
754     GetToken().type_ = TokenType::PUNCTUATOR_EXCLAMATION_MARK;
755 
756     switch (Iterator().Peek()) {
757         case LEX_CHAR_EQUALS: {
758             GetToken().type_ = TokenType::PUNCTUATOR_NOT_EQUAL;
759             Iterator().Forward(1);
760 
761             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
762                 GetToken().type_ = TokenType::PUNCTUATOR_NOT_STRICT_EQUAL;
763                 Iterator().Forward(1);
764             }
765             break;
766         }
767         default: {
768             break;
769         }
770     }
771 }
772 
ScanAmpersandPunctuator()773 void Lexer::ScanAmpersandPunctuator()
774 {
775     GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_AND;
776 
777     switch (Iterator().Peek()) {
778         case LEX_CHAR_AMPERSAND: {
779             GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_AND;
780             Iterator().Forward(1);
781 
782             switch (Iterator().Peek()) {
783                 case LEX_CHAR_EQUALS: {
784                     GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL;
785                     Iterator().Forward(1);
786                     break;
787                 }
788                 default: {
789                     break;
790                 }
791             }
792 
793             break;
794         }
795         case LEX_CHAR_EQUALS: {
796             GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_AND_EQUAL;
797             Iterator().Forward(1);
798             break;
799         }
800         default: {
801             break;
802         }
803     }
804 }
805 
ScanVLinePunctuator()806 void Lexer::ScanVLinePunctuator()
807 {
808     GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_OR;
809 
810     switch (Iterator().Peek()) {
811         case LEX_CHAR_VLINE: {
812             GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_OR;
813             Iterator().Forward(1);
814 
815             switch (Iterator().Peek()) {
816                 case LEX_CHAR_EQUALS: {
817                     GetToken().type_ = TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL;
818                     Iterator().Forward(1);
819                     break;
820                 }
821                 default: {
822                     break;
823                 }
824             }
825 
826             break;
827         }
828         case LEX_CHAR_EQUALS: {
829             GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_OR_EQUAL;
830             Iterator().Forward(1);
831             break;
832         }
833         default: {
834             break;
835         }
836     }
837 }
838 
ScanCircumflexPunctuator()839 void Lexer::ScanCircumflexPunctuator()
840 {
841     GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_XOR;
842 
843     switch (Iterator().Peek()) {
844         case LEX_CHAR_EQUALS: {
845             GetToken().type_ = TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL;
846             Iterator().Forward(1);
847             break;
848         }
849         default: {
850             break;
851         }
852     }
853 }
854 
ScanPlusPunctuator()855 void Lexer::ScanPlusPunctuator()
856 {
857     GetToken().type_ = TokenType::PUNCTUATOR_PLUS;
858 
859     switch (Iterator().Peek()) {
860         case LEX_CHAR_PLUS: {
861             GetToken().type_ = TokenType::PUNCTUATOR_PLUS_PLUS;
862             Iterator().Forward(1);
863             break;
864         }
865         case LEX_CHAR_EQUALS: {
866             GetToken().type_ = TokenType::PUNCTUATOR_PLUS_EQUAL;
867             Iterator().Forward(1);
868             break;
869         }
870         default: {
871             break;
872         }
873     }
874 }
875 
ScanMinusPunctuator()876 void Lexer::ScanMinusPunctuator()
877 {
878     GetToken().type_ = TokenType::PUNCTUATOR_MINUS;
879 
880     switch (Iterator().Peek()) {
881         case LEX_CHAR_MINUS: {
882             GetToken().type_ = TokenType::PUNCTUATOR_MINUS_MINUS;
883             Iterator().Forward(1);
884             break;
885         }
886         case LEX_CHAR_EQUALS: {
887             GetToken().type_ = TokenType::PUNCTUATOR_MINUS_EQUAL;
888             Iterator().Forward(1);
889             break;
890         }
891         default: {
892             break;
893         }
894     }
895 }
896 
ScanSlashPunctuator()897 void Lexer::ScanSlashPunctuator()
898 {
899     GetToken().type_ = TokenType::PUNCTUATOR_DIVIDE;
900 
901     switch (Iterator().Peek()) {
902         case LEX_CHAR_EQUALS: {
903             GetToken().type_ = TokenType::PUNCTUATOR_DIVIDE_EQUAL;
904             Iterator().Forward(1);
905             break;
906         }
907         default: {
908             break;
909         }
910     }
911 }
912 
ScanDotPunctuator()913 void Lexer::ScanDotPunctuator()
914 {
915     GetToken().type_ = TokenType::PUNCTUATOR_PERIOD;
916 
917     switch (Iterator().Peek()) {
918         case LEX_CHAR_0:
919         case LEX_CHAR_1:
920         case LEX_CHAR_2:
921         case LEX_CHAR_3:
922         case LEX_CHAR_4:
923         case LEX_CHAR_5:
924         case LEX_CHAR_6:
925         case LEX_CHAR_7:
926         case LEX_CHAR_8:
927         case LEX_CHAR_9: {
928             ScanNumber();
929             break;
930         }
931         case LEX_CHAR_QUESTION: {
932             GetToken().type_ = TokenType::PUNCTUATOR_PERIOD_QUESTION;
933             Iterator().Forward(1);
934             break;
935         }
936         case LEX_CHAR_DOT: {
937             Iterator().Forward(1);
938 
939             if (Iterator().Peek() == LEX_CHAR_DOT) {
940                 GetToken().type_ = TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD;
941                 Iterator().Forward(1);
942                 break;
943             }
944 
945             Iterator().Backward(1);
946             break;
947         }
948         default: {
949             break;
950         }
951     }
952 }
953 
ScanAsterixPunctuator()954 void Lexer::ScanAsterixPunctuator()
955 {
956     GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY;
957 
958     switch (Iterator().Peek()) {
959         case LEX_CHAR_ASTERISK: {
960             GetToken().type_ = TokenType::PUNCTUATOR_EXPONENTIATION;
961             Iterator().Forward(1);
962 
963             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
964                 GetToken().type_ = TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL;
965                 Iterator().Forward(1);
966             }
967             break;
968         }
969         case LEX_CHAR_EQUALS: {
970             GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY_EQUAL;
971             Iterator().Forward(1);
972             break;
973         }
974         default: {
975             break;
976         }
977     }
978 }
979 
ScanPercentPunctuator()980 void Lexer::ScanPercentPunctuator()
981 {
982     GetToken().type_ = TokenType::PUNCTUATOR_MOD;
983 
984     switch (Iterator().Peek()) {
985         case LEX_CHAR_EQUALS: {
986             GetToken().type_ = TokenType::PUNCTUATOR_MOD_EQUAL;
987             Iterator().Forward(1);
988             break;
989         }
990         default: {
991             break;
992         }
993     }
994 }
995 
IsLineTerminatorOrEos() const996 bool Lexer::IsLineTerminatorOrEos() const
997 {
998     switch (Iterator().PeekCp()) {
999         case util::StringView::Iterator::INVALID_CP:
1000         case LEX_CHAR_LF:
1001         case LEX_CHAR_CR:
1002         case LEX_CHAR_LS:
1003         case LEX_CHAR_PS: {
1004             return true;
1005         }
1006         default: {
1007             break;
1008         }
1009     }
1010 
1011     return false;
1012 }
1013 
ScanRegExpPattern()1014 void Lexer::ScanRegExpPattern()
1015 {
1016     bool isCharClass = false;
1017     size_t cpSize {};
1018 
1019     while (true) {
1020         switch (Iterator().PeekCp(&cpSize)) {
1021             case util::StringView::Iterator::INVALID_CP:
1022             case LEX_CHAR_LF:
1023             case LEX_CHAR_CR:
1024             case LEX_CHAR_LS:
1025             case LEX_CHAR_PS: {
1026                 ThrowError("Unterminated RegExp");
1027                 break;
1028             }
1029             case LEX_CHAR_SLASH: {
1030                 if (!isCharClass) {
1031                     return;
1032                 }
1033 
1034                 break;
1035             }
1036             case LEX_CHAR_LEFT_SQUARE: {
1037                 isCharClass = true;
1038                 break;
1039             }
1040             case LEX_CHAR_RIGHT_SQUARE: {
1041                 isCharClass = false;
1042                 break;
1043             }
1044             case LEX_CHAR_BACKSLASH: {
1045                 Iterator().Forward(1);
1046 
1047                 if (IsLineTerminatorOrEos()) {
1048                     continue;
1049                 }
1050 
1051                 break;
1052             }
1053             default: {
1054                 break;
1055             }
1056         }
1057 
1058         Iterator().Forward(cpSize);
1059     }
1060 }
1061 
ScanRegExpFlags()1062 RegExpFlags Lexer::ScanRegExpFlags()
1063 {
1064     RegExpFlags resultFlags = RegExpFlags::EMPTY;
1065 
1066     while (true) {
1067         size_t cpSize {};
1068         auto cp = Iterator().PeekCp(&cpSize);
1069         if (!KeywordsUtil::IsIdentifierPart(cp)) {
1070             break;
1071         }
1072 
1073         Iterator().Forward(cpSize);
1074 
1075         RegExpFlags flag = RegExpFlags::EMPTY;
1076 
1077         switch (cp) {
1078             case LEX_CHAR_LOWERCASE_G: {
1079                 flag = RegExpFlags::GLOBAL;
1080                 break;
1081             }
1082             case LEX_CHAR_LOWERCASE_I: {
1083                 flag = RegExpFlags::IGNORE_CASE;
1084                 break;
1085             }
1086             case LEX_CHAR_LOWERCASE_M: {
1087                 flag = RegExpFlags::MULTILINE;
1088                 break;
1089             }
1090             case LEX_CHAR_LOWERCASE_S: {
1091                 flag = RegExpFlags::DOTALL;
1092                 break;
1093             }
1094             case LEX_CHAR_LOWERCASE_U: {
1095                 flag = RegExpFlags::UNICODE;
1096                 break;
1097             }
1098             case LEX_CHAR_LOWERCASE_Y: {
1099                 flag = RegExpFlags::STICKY;
1100                 break;
1101             }
1102             case LEX_CHAR_SP: {
1103                 return resultFlags;
1104             }
1105             default: {
1106                 ThrowError("Invalid RegExp flag");
1107             }
1108         }
1109 
1110         if (flag == RegExpFlags::EMPTY || (resultFlags & flag) != 0) {
1111             ThrowError("Invalid RegExp flag");
1112         }
1113 
1114         resultFlags = resultFlags | flag;
1115     }
1116 
1117     return resultFlags;
1118 }
1119 
ScanRegExp()1120 RegExp Lexer::ScanRegExp()
1121 {
1122     GetToken().type_ = TokenType::LITERAL_REGEXP;
1123 
1124     const auto patternStart = Iterator().Index();
1125     ScanRegExpPattern();
1126     const auto pattern = SourceView(patternStart, Iterator().Index());
1127 
1128     ASSERT(Iterator().Peek() == LEX_CHAR_SLASH);
1129     Iterator().Forward(1);
1130 
1131     const auto flagsStart = Iterator().Index();
1132     RegExpFlags resultFlags = ScanRegExpFlags();
1133     const auto flags = SourceView(flagsStart, Iterator().Index());
1134 
1135     SkipWhiteSpaces();
1136     SetTokenEnd();
1137 
1138     return {pattern, flags, resultFlags};
1139 }
1140 
CheckArrow()1141 bool Lexer::CheckArrow()
1142 {
1143     if (Iterator().Peek() != LEX_CHAR_EQUALS) {
1144         return false;
1145     }
1146     Iterator().Forward(1);
1147 
1148     bool res = Iterator().Peek() == LEX_CHAR_GREATER_THAN;
1149     Iterator().Backward(1);
1150 
1151     return res;
1152 }
1153 
SetTokenStart()1154 void Lexer::SetTokenStart()
1155 {
1156     if (pos_.nextTokenLine != 0) {
1157         pos_.line += pos_.nextTokenLine;
1158         pos_.nextTokenLine = 0;
1159         GetToken().flags_ = TokenFlags::NEW_LINE;
1160     } else {
1161         GetToken().flags_ = TokenFlags::NONE;
1162     }
1163 
1164     pos_.token.loc_.start = SourcePosition {Iterator().Index(), pos_.line};
1165 }
1166 
SetTokenEnd()1167 void Lexer::SetTokenEnd()
1168 {
1169     pos_.token.loc_.end = SourcePosition {Iterator().Index(), pos_.line};
1170 }
1171 
CheckAwaitKeyword()1172 void Lexer::CheckAwaitKeyword()
1173 {
1174     if (!parserContext_->IsAsync()) {
1175         GetToken().type_ = TokenType::LITERAL_IDENT;
1176         return;
1177     }
1178 
1179     if (parserContext_->DisallowAwait()) {
1180         ThrowError("'await' is not allowed");
1181     }
1182 
1183     GetToken().type_ = TokenType::KEYW_AWAIT;
1184 }
1185 
CheckKeywordEscape(TokenType type)1186 void Lexer::CheckKeywordEscape(TokenType type)
1187 {
1188     if (GetToken().flags_ & TokenFlags::HAS_ESCAPE) {
1189         ThrowError("Escape sequences are not allowed in keywords");
1190     }
1191 
1192     GetToken().type_ = type;
1193 }
1194 
CheckEnumKeyword()1195 void Lexer::CheckEnumKeyword()
1196 {
1197     if (parserContext_->GetProgram()->Extension() == ScriptExtension::JS) {
1198         ThrowError("Unexpected reserved keyword");
1199     }
1200 
1201     if (GetToken().flags_ & TokenFlags::HAS_ESCAPE) {
1202         ThrowError("Escape sequences are not allowed in keywords");
1203     }
1204 
1205     GetToken().type_ = TokenType::LITERAL_IDENT;
1206 }
1207 
CheckLetKeyword()1208 void Lexer::CheckLetKeyword()
1209 {
1210     GetToken().type_ = TokenType::KEYW_LET;
1211 }
1212 
CheckYieldKeyword()1213 void Lexer::CheckYieldKeyword()
1214 {
1215     if (!parserContext_->AllowYield()) {
1216         ThrowError("'yield' is not allowed");
1217     }
1218 
1219     GetToken().type_ = TokenType::KEYW_YIELD;
1220 }
1221 
CheckFutureReservedKeyword(TokenType keywordType)1222 void Lexer::CheckFutureReservedKeyword(TokenType keywordType)
1223 {
1224     GetToken().type_ = TokenType::LITERAL_IDENT;
1225 
1226     if (parserContext_->GetProgram()->Extension() == ScriptExtension::TS && keywordType <= TokenType::KEYW_INTERFACE) {
1227         return;
1228     }
1229 
1230     ThrowError("Unexpected strict mode reserved keyword");
1231 }
1232 
SkipWhiteSpaces()1233 void Lexer::SkipWhiteSpaces()
1234 {
1235     while (true) {
1236         auto cp = Iterator().Peek();
1237 
1238         switch (cp) {
1239             case LEX_CHAR_HASH_MARK: {
1240                 Iterator().Forward(1);
1241                 cp = Iterator().Peek();
1242                 if (cp == LEX_CHAR_EXCLAMATION) {
1243                     Iterator().Forward(1);
1244                     SkipSingleLineComment();
1245                     continue;
1246                 }
1247 
1248                 Iterator().Backward(1);
1249                 return;
1250             }
1251             case LEX_CHAR_CR: {
1252                 Iterator().Forward(1);
1253 
1254                 if (Iterator().Peek() != LEX_CHAR_LF) {
1255                     Iterator().Backward(1);
1256                 }
1257 
1258                 [[fallthrough]];
1259             }
1260             case LEX_CHAR_LF: {
1261                 Iterator().Forward(1);
1262                 pos_.nextTokenLine++;
1263                 continue;
1264             }
1265             case LEX_CHAR_VT:
1266             case LEX_CHAR_FF:
1267             case LEX_CHAR_SP:
1268             case LEX_CHAR_TAB: {
1269                 Iterator().Forward(1);
1270                 continue;
1271             }
1272             case LEX_CHAR_SLASH: {
1273                 Iterator().Forward(1);
1274                 cp = Iterator().Peek();
1275                 if (cp == LEX_CHAR_SLASH) {
1276                     Iterator().Forward(1);
1277                     SkipSingleLineComment();
1278                     continue;
1279                 }
1280                 if (cp == LEX_CHAR_ASTERISK) {
1281                     Iterator().Forward(1);
1282                     SkipMultiLineComment();
1283                     continue;
1284                 }
1285 
1286                 Iterator().Backward(1);
1287                 return;
1288             }
1289             default: {
1290                 if (cp < LEX_ASCII_MAX_BITS) {
1291                     return;
1292                 }
1293 
1294                 size_t cpSize {};
1295                 cp = Iterator().PeekCp(&cpSize);
1296 
1297                 switch (cp) {
1298                     case LEX_CHAR_LS:
1299                     case LEX_CHAR_PS: {
1300                         pos_.nextTokenLine++;
1301                         [[fallthrough]];
1302                     }
1303                     case LEX_CHAR_NBSP:
1304                     case LEX_CHAR_NLINE:
1305                     case LEX_CHAR_IGSP:
1306                     case LEX_CHAR_ZWNBSP: {
1307                         Iterator().Forward(cpSize);
1308                         continue;
1309                     }
1310                     default: {
1311                         return;
1312                     }
1313                 }
1314             }
1315         }
1316     }
1317 }
1318 
1319 // NOLINTNEXTLINE(readability-function-size)
NextToken(LexerNextTokenFlags flags)1320 void Lexer::NextToken(LexerNextTokenFlags flags)
1321 {
1322     Keywords kws(this, flags);
1323     KeywordsUtil &kwu = kws.Util();
1324 
1325     SetTokenStart();
1326 
1327     auto cp = Iterator().Peek();
1328     Iterator().Forward(1);
1329 
1330     GetToken().keywordType_ = TokenType::EOS;
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