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