1 /*
2 * Copyright (c) 2021 - 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 "ETSLexer.h"
17 #include "generated/keywords.h"
18
19 namespace ark::es2panda::lexer {
20 // NOLINTNEXTLINE(google-default-arguments)
NextToken(NextTokenFlags flags)21 void ETSLexer::NextToken(NextTokenFlags flags)
22 {
23 ETSKeywords kws(this, static_cast<NextTokenFlags>(flags & ~NextTokenFlags::KEYWORD_TO_IDENT));
24 Lexer::NextToken(&kws);
25 }
26
ScanHashMark()27 void ETSLexer::ScanHashMark()
28 {
29 ThrowUnexpectedToken(TokenType::PUNCTUATOR_HASH_MARK);
30 }
31
ScanCharLiteral()32 bool ETSLexer::ScanCharLiteral()
33 {
34 // Note: for character literal on call iterator is pointed to the opening single quote (') character!
35 // Otherwise it's another token.
36 if (Iterator().Peek() != LEX_CHAR_SINGLE_QUOTE) {
37 return false;
38 }
39
40 GetToken().type_ = TokenType::LITERAL_CHAR;
41
42 Iterator().Forward(1);
43 char32_t cp = Iterator().PeekCp();
44
45 switch (cp) {
46 case LEX_CHAR_SINGLE_QUOTE:
47 case util::StringView::Iterator::INVALID_CP: {
48 ThrowError("Invalid character literal");
49 break;
50 }
51 case LEX_CHAR_BACKSLASH: {
52 GetToken().flags_ |= TokenFlags::HAS_ESCAPE;
53
54 Iterator().Forward(1);
55 cp = ScanUnicodeCharacter();
56 break;
57 }
58 default: {
59 Iterator().SkipCp();
60 break;
61 }
62 }
63
64 CheckUtf16Compatible(cp);
65 GetToken().c16_ = cp;
66
67 if (Iterator().Peek() != LEX_CHAR_SINGLE_QUOTE) {
68 ThrowError("Unterminated character literal");
69 }
70
71 Iterator().Forward(1);
72 return true;
73 }
74
CheckNumberLiteralEnd()75 void ETSLexer::CheckNumberLiteralEnd()
76 {
77 if (Iterator().Peek() == LEX_CHAR_LOWERCASE_F) {
78 GetToken().flags_ |= TokenFlags::NUMBER_FLOAT;
79 GetToken().src_ = SourceView(GetToken().Start().index, Iterator().Index());
80 Iterator().Forward(1);
81 const auto nextCp = Iterator().PeekCp();
82 if (KeywordsUtil::IsIdentifierStart(nextCp) || IsDecimalDigit(nextCp)) {
83 ThrowError("Invalid numeric literal");
84 }
85 } else {
86 Lexer::CheckNumberLiteralEnd();
87 }
88 }
89
CheckUtf16Compatible(char32_t cp) const90 void ETSLexer::CheckUtf16Compatible(char32_t cp) const
91 {
92 if (cp >= util::StringView::Constants::CELESTIAL_OFFSET) {
93 ThrowError("Unsupported character literal");
94 }
95 }
96
ScanAsteriskPunctuator()97 void ETSLexer::ScanAsteriskPunctuator()
98 {
99 GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY;
100
101 switch (Iterator().Peek()) {
102 case LEX_CHAR_EQUALS: {
103 GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY_EQUAL;
104 Iterator().Forward(1);
105 break;
106 }
107 default: {
108 break;
109 }
110 }
111 }
112
ConvertNumber(const std::string & utf8,NumberFlags flags)113 void ETSLexer::ConvertNumber(const std::string &utf8, NumberFlags flags)
114 {
115 GetToken().number_ = lexer::Number(GetToken().src_, utf8, flags);
116
117 if (GetToken().number_.ConversionError()) {
118 ThrowError("Invalid number");
119 }
120 }
121
ScanEqualsPunctuator()122 void ETSLexer::ScanEqualsPunctuator()
123 {
124 GetToken().type_ = TokenType::PUNCTUATOR_SUBSTITUTION;
125
126 switch (Iterator().Peek()) {
127 case LEX_CHAR_EQUALS: {
128 GetToken().type_ = TokenType::PUNCTUATOR_EQUAL;
129 Iterator().Forward(1);
130
131 if (Iterator().Peek() == LEX_CHAR_EQUALS) {
132 GetToken().type_ = TokenType::PUNCTUATOR_STRICT_EQUAL;
133 Iterator().Forward(1);
134 }
135 break;
136 }
137 case LEX_CHAR_GREATER_THAN: {
138 GetToken().type_ = TokenType::PUNCTUATOR_ARROW;
139 Iterator().Forward(1);
140 break;
141 }
142 default: {
143 break;
144 }
145 }
146 }
147
ScanExclamationPunctuator()148 void ETSLexer::ScanExclamationPunctuator()
149 {
150 GetToken().type_ = TokenType::PUNCTUATOR_EXCLAMATION_MARK;
151
152 switch (Iterator().Peek()) {
153 case LEX_CHAR_EQUALS: {
154 GetToken().type_ = TokenType::PUNCTUATOR_NOT_EQUAL;
155 Iterator().Forward(1);
156
157 if (Iterator().Peek() == LEX_CHAR_EQUALS) {
158 GetToken().type_ = TokenType::PUNCTUATOR_NOT_STRICT_EQUAL;
159 Iterator().Forward(1);
160 }
161 break;
162 }
163 default: {
164 break;
165 }
166 }
167 }
168
ScanDollarPunctuator()169 bool ETSLexer::ScanDollarPunctuator()
170 {
171 if (Iterator().Peek() != LEX_CHAR_DOLLAR_SIGN) {
172 return false;
173 }
174
175 GetToken().type_ = TokenType::PUNCTUATOR_DOLLAR_DOLLAR;
176 Iterator().Forward(1);
177 return true;
178 }
179 } // namespace ark::es2panda::lexer
180