5 #include "src/asmjs/asm-scanner.h" 7 #include "src/char-predicates-inl.h" 8 #include "src/conversions.h" 10 #include "src/parsing/scanner.h" 18 static const int kMaxIdentifierCount = 0xF000000;
21 AsmJsScanner::AsmJsScanner(Utf16CharacterStream* stream)
23 token_(kUninitialized),
24 preceding_token_(kUninitialized),
25 next_token_(kUninitialized),
27 preceding_position_(0),
30 in_local_scope_(false),
34 preceded_by_newline_(false) {
35 #define V(name, _junk1, _junk2, _junk3) property_names_[#name] = kToken_##name; 36 STDLIB_MATH_FUNCTION_LIST(
V)
37 STDLIB_ARRAY_TYPE_LIST(
V)
39 #define V(name, _junk1) property_names_[#name] = kToken_##name; 40 STDLIB_MATH_VALUE_LIST(
V)
42 #define V(name) property_names_[#name] = kToken_##name; 45 #define V(name) global_names_[#name] = kToken_##name; 51 void AsmJsScanner::Next() {
53 preceding_token_ = token_;
54 preceding_position_ = position_;
56 position_ = next_position_;
57 next_token_ = kUninitialized;
63 if (token_ == kEndOfInput || token_ == kParseError) {
68 if (FLAG_trace_asm_scanner) {
69 if (Token() == kDouble) {
70 PrintF(
"%lf ", AsDouble());
71 }
else if (Token() == kUnsigned) {
72 PrintF(
"%" PRIu32
" ", AsUnsigned());
74 std::string name = Name(Token());
75 PrintF(
"%s ", name.c_str());
80 preceded_by_newline_ =
false;
81 preceding_token_ = token_;
82 preceding_position_ = position_;
85 position_ = stream_->pos();
86 uc32 ch = stream_->Advance();
97 preceded_by_newline_ =
true;
101 token_ = kEndOfInput;
110 ch = stream_->Advance();
113 }
else if (ch ==
'*') {
114 if (!ConsumeCComment()) {
115 token_ = kParseError;
131 ConsumeCompareOrShift(ch);
134 #define V(single_char_token) case single_char_token: 135 SIMPLE_SINGLE_TOKEN_LIST(
V)
142 if (IsIdentifierStart(ch)) {
143 ConsumeIdentifier(ch);
144 }
else if (IsNumberStart(ch)) {
148 token_ = kParseError;
155 void AsmJsScanner::Rewind() {
156 DCHECK_NE(kUninitialized, preceding_token_);
161 next_token_ = token_;
162 next_position_ = position_;
163 token_ = preceding_token_;
164 position_ = preceding_position_;
165 preceding_token_ = kUninitialized;
166 preceding_position_ = 0;
168 identifier_string_.clear();
171 void AsmJsScanner::ResetLocals() { local_names_.clear(); }
175 std::string AsmJsScanner::Name(token_t token)
const {
176 if (token >= 32 && token < 127) {
177 return std::string(1, static_cast<char>(token));
179 for (
auto&
i : local_names_) {
180 if (
i.second == token) {
184 for (
auto&
i : global_names_) {
185 if (
i.second == token) {
189 for (
auto&
i : property_names_) {
190 if (
i.second == token) {
195 #define V(rawname, name) \ 196 case kToken_##name: \ 198 LONG_SYMBOL_NAME_LIST(
V)
200 #define V(name, value, string_name) \ 203 SPECIAL_TOKEN_LIST(
V)
212 void AsmJsScanner::Seek(
size_t pos) {
214 preceding_token_ = kUninitialized;
215 token_ = kUninitialized;
216 next_token_ = kUninitialized;
217 preceding_position_ = 0;
224 void AsmJsScanner::ConsumeIdentifier(uc32 ch) {
226 identifier_string_.clear();
227 while (IsIdentifierPart(ch)) {
228 identifier_string_ += ch;
229 ch = stream_->Advance();
235 if (preceding_token_ ==
'.') {
236 auto i = property_names_.find(identifier_string_);
237 if (
i != property_names_.end()) {
243 auto i = local_names_.find(identifier_string_);
244 if (
i != local_names_.end()) {
249 if (!in_local_scope_) {
250 auto i = global_names_.find(identifier_string_);
251 if (
i != global_names_.end()) {
257 if (preceding_token_ ==
'.') {
258 CHECK_LT(global_count_, kMaxIdentifierCount);
259 token_ = kGlobalsStart + global_count_++;
260 property_names_[identifier_string_] = token_;
261 }
else if (in_local_scope_) {
262 CHECK_LT(local_names_.size(), kMaxIdentifierCount);
263 token_ = kLocalsStart -
static_cast<token_t
>(local_names_.size());
264 local_names_[identifier_string_] = token_;
266 CHECK_LT(global_count_, kMaxIdentifierCount);
267 token_ = kGlobalsStart + global_count_++;
268 global_names_[identifier_string_] = token_;
272 void AsmJsScanner::ConsumeNumber(uc32 ch) {
275 bool has_dot = ch ==
'.';
276 bool has_prefix =
false;
278 ch = stream_->Advance();
279 if ((ch >=
'0' && ch <=
'9') || (ch >=
'a' && ch <=
'f') ||
280 (ch >=
'A' && ch <=
'F') || ch ==
'.' || ch ==
'b' || ch ==
'o' ||
282 ((ch ==
'-' || ch ==
'+') && !has_prefix &&
283 (number[number.size() - 1] ==
'e' ||
284 number[number.size() - 1] ==
'E'))) {
289 if (ch ==
'b' || ch ==
'o' || ch ==
'x') {
292 number.push_back(ch);
299 if (number.size() == 1 && number[0] ==
'0') {
305 if (number.size() == 1 && number[0] ==
'.') {
310 double_value_ = StringToDouble(
311 Vector<const uint8_t>::cast(VectorOf(number)),
312 ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL);
313 if (std::isnan(double_value_)) {
319 if (number[0] ==
'.') {
320 for (
size_t k = 1; k < number.size(); ++k) {
327 token_ = kParseError;
334 if (double_value_ > static_cast<double>(kMaxUInt32)) {
335 token_ = kParseError;
338 unsigned_value_ =
static_cast<uint32_t>(double_value_);
343 bool AsmJsScanner::ConsumeCComment() {
345 uc32 ch = stream_->Advance();
347 ch = stream_->Advance();
353 preceded_by_newline_ =
true;
355 if (ch == kEndOfInput) {
361 void AsmJsScanner::ConsumeCPPComment() {
363 uc32 ch = stream_->Advance();
365 preceded_by_newline_ =
true;
368 if (ch == kEndOfInput) {
374 void AsmJsScanner::ConsumeString(uc32 quote) {
376 const char* expected =
"use asm";
377 for (; *expected !=
'\0'; ++expected) {
378 if (stream_->Advance() != *expected) {
379 token_ = kParseError;
383 if (stream_->Advance() != quote) {
384 token_ = kParseError;
387 token_ = kToken_UseAsm;
390 void AsmJsScanner::ConsumeCompareOrShift(uc32 ch) {
391 uc32 next_ch = stream_->Advance();
392 if (next_ch ==
'=') {
409 }
else if (ch ==
'<' && next_ch ==
'<') {
411 }
else if (ch ==
'>' && next_ch ==
'>') {
412 if (stream_->Advance() ==
'>') {
424 bool AsmJsScanner::IsIdentifierStart(uc32 ch) {
425 return IsInRange(AsciiAlphaToLower(ch),
'a',
'z') || ch ==
'_' || ch ==
'$';
428 bool AsmJsScanner::IsIdentifierPart(uc32 ch) {
return IsAsciiIdentifier(ch); }
430 bool AsmJsScanner::IsNumberStart(uc32 ch) {
431 return ch ==
'.' || IsDecimalDigit(ch);