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