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