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