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