• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 2023 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 panda::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 
SkipMultiLineComment()97 void ETSLexer::SkipMultiLineComment()
98 {
99     uint32_t depth = 1U;
100 
101     // Just to reduce extra nested level(s)
102     auto const checkAsterisk = [this, &depth]() -> bool {
103         if (Iterator().Peek() == LEX_CHAR_SLASH) {
104             Iterator().Forward(1);
105 
106             if (--depth == 0U) {
107                 return false;
108             }
109         }
110         return true;
111     };
112 
113     while (true) {
114         switch (Iterator().Next()) {
115             case util::StringView::Iterator::INVALID_CP: {
116                 ThrowError("Unterminated multi-line comment");
117                 break;
118             }
119             case LEX_CHAR_LF:
120             case LEX_CHAR_CR:
121             case LEX_CHAR_LS:
122             case LEX_CHAR_PS: {
123                 Pos().NextTokenLine()++;
124                 continue;
125             }
126             case LEX_CHAR_ASTERISK: {
127                 if (!checkAsterisk()) {
128                     return;
129                 }
130                 break;
131             }
132             case LEX_CHAR_SLASH: {
133                 if (Iterator().Peek() == LEX_CHAR_ASTERISK) {
134                     Iterator().Forward(1);
135                     depth++;
136                 }
137                 break;
138             }
139 
140             default: {
141                 break;
142             }
143         }
144     }
145 }
146 
ScanAsteriskPunctuator()147 void ETSLexer::ScanAsteriskPunctuator()
148 {
149     GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY;
150 
151     switch (Iterator().Peek()) {
152         case LEX_CHAR_EQUALS: {
153             GetToken().type_ = TokenType::PUNCTUATOR_MULTIPLY_EQUAL;
154             Iterator().Forward(1);
155             break;
156         }
157         default: {
158             break;
159         }
160     }
161 }
162 
ConvertNumber(const std::string & utf8,NumberFlags flags)163 void ETSLexer::ConvertNumber(const std::string &utf8, NumberFlags flags)
164 {
165     GetToken().number_ = lexer::Number(GetToken().src_, utf8, flags);
166 
167     if (GetToken().number_.ConversionError()) {
168         ThrowError("Invalid number");
169     }
170 }
171 
ScanEqualsPunctuator()172 void ETSLexer::ScanEqualsPunctuator()
173 {
174     GetToken().type_ = TokenType::PUNCTUATOR_SUBSTITUTION;
175 
176     switch (Iterator().Peek()) {
177         case LEX_CHAR_EQUALS: {
178             GetToken().type_ = TokenType::PUNCTUATOR_EQUAL;
179             Iterator().Forward(1);
180 
181             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
182                 GetToken().type_ = TokenType::PUNCTUATOR_STRICT_EQUAL;
183                 Iterator().Forward(1);
184             }
185             break;
186         }
187         case LEX_CHAR_GREATER_THAN: {
188             GetToken().type_ = TokenType::PUNCTUATOR_ARROW;
189             Iterator().Forward(1);
190             break;
191         }
192         default: {
193             break;
194         }
195     }
196 }
197 
ScanExclamationPunctuator()198 void ETSLexer::ScanExclamationPunctuator()
199 {
200     GetToken().type_ = TokenType::PUNCTUATOR_EXCLAMATION_MARK;
201 
202     switch (Iterator().Peek()) {
203         case LEX_CHAR_EQUALS: {
204             GetToken().type_ = TokenType::PUNCTUATOR_NOT_EQUAL;
205             Iterator().Forward(1);
206 
207             if (Iterator().Peek() == LEX_CHAR_EQUALS) {
208                 GetToken().type_ = TokenType::PUNCTUATOR_NOT_STRICT_EQUAL;
209                 Iterator().Forward(1);
210             }
211             break;
212         }
213         default: {
214             break;
215         }
216     }
217 }
218 
ScanDollarPunctuator()219 bool ETSLexer::ScanDollarPunctuator()
220 {
221     if (Iterator().Peek() != LEX_CHAR_DOLLAR_SIGN) {
222         return false;
223     }
224 
225     GetToken().type_ = TokenType::PUNCTUATOR_DOLLAR_DOLLAR;
226     Iterator().Forward(1);
227     return true;
228 }
229 }  // namespace panda::es2panda::lexer
230