1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be) 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "LiteralParser.h" 29 30#include "ButterflyInlines.h" 31#include "CopiedSpaceInlines.h" 32#include "JSArray.h" 33#include "JSString.h" 34#include "Lexer.h" 35#include "ObjectConstructor.h" 36#include "JSCInlines.h" 37#include "StrongInlines.h" 38#include <wtf/ASCIICType.h> 39#include <wtf/dtoa.h> 40#include <wtf/text/StringBuilder.h> 41 42namespace JSC { 43 44template <typename CharType> 45static inline bool isJSONWhiteSpace(const CharType& c) 46{ 47 // The JSON RFC 4627 defines a list of allowed characters to be considered 48 // insignificant white space: http://www.ietf.org/rfc/rfc4627.txt (2. JSON Grammar). 49 return c == ' ' || c == 0x9 || c == 0xA || c == 0xD; 50} 51 52template <typename CharType> 53bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo) 54{ 55 if (m_lexer.next() != TokIdentifier) 56 return false; 57 do { 58 Vector<JSONPPathEntry> path; 59 // Unguarded next to start off the lexer 60 Identifier name = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start); 61 JSONPPathEntry entry; 62 if (name == m_exec->vm().propertyNames->varKeyword) { 63 if (m_lexer.next() != TokIdentifier) 64 return false; 65 entry.m_type = JSONPPathEntryTypeDeclare; 66 entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start); 67 path.append(entry); 68 } else { 69 entry.m_type = JSONPPathEntryTypeDot; 70 entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start); 71 path.append(entry); 72 } 73 if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName)) 74 return false; 75 TokenType tokenType = m_lexer.next(); 76 if (entry.m_type == JSONPPathEntryTypeDeclare && tokenType != TokAssign) 77 return false; 78 while (tokenType != TokAssign) { 79 switch (tokenType) { 80 case TokLBracket: { 81 entry.m_type = JSONPPathEntryTypeLookup; 82 if (m_lexer.next() != TokNumber) 83 return false; 84 double doubleIndex = m_lexer.currentToken().numberToken; 85 int index = (int)doubleIndex; 86 if (index != doubleIndex || index < 0) 87 return false; 88 entry.m_pathIndex = index; 89 if (m_lexer.next() != TokRBracket) 90 return false; 91 break; 92 } 93 case TokDot: { 94 entry.m_type = JSONPPathEntryTypeDot; 95 if (m_lexer.next() != TokIdentifier) 96 return false; 97 entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start); 98 break; 99 } 100 case TokLParen: { 101 if (path.last().m_type != JSONPPathEntryTypeDot || needsFullSourceInfo) 102 return false; 103 path.last().m_type = JSONPPathEntryTypeCall; 104 entry = path.last(); 105 goto startJSON; 106 } 107 default: 108 return false; 109 } 110 path.append(entry); 111 tokenType = m_lexer.next(); 112 } 113 startJSON: 114 m_lexer.next(); 115 results.append(JSONPData()); 116 results.last().m_value.set(m_exec->vm(), parse(StartParseExpression)); 117 if (!results.last().m_value) 118 return false; 119 results.last().m_path.swap(path); 120 if (entry.m_type == JSONPPathEntryTypeCall) { 121 if (m_lexer.currentToken().type != TokRParen) 122 return false; 123 m_lexer.next(); 124 } 125 if (m_lexer.currentToken().type != TokSemi) 126 break; 127 m_lexer.next(); 128 } while (m_lexer.currentToken().type == TokIdentifier); 129 return m_lexer.currentToken().type == TokEnd; 130} 131 132template <typename CharType> 133ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length) 134{ 135 if (!length) 136 return m_exec->vm().propertyNames->emptyIdentifier; 137 if (characters[0] >= MaximumCachableCharacter) 138 return Identifier(&m_exec->vm(), characters, length); 139 140 if (length == 1) { 141 if (!m_shortIdentifiers[characters[0]].isNull()) 142 return m_shortIdentifiers[characters[0]]; 143 m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length); 144 return m_shortIdentifiers[characters[0]]; 145 } 146 if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length)) 147 return m_recentIdentifiers[characters[0]]; 148 m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length); 149 return m_recentIdentifiers[characters[0]]; 150} 151 152template <typename CharType> 153ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length) 154{ 155 if (!length) 156 return m_exec->vm().propertyNames->emptyIdentifier; 157 if (characters[0] >= MaximumCachableCharacter) 158 return Identifier(&m_exec->vm(), characters, length); 159 160 if (length == 1) { 161 if (!m_shortIdentifiers[characters[0]].isNull()) 162 return m_shortIdentifiers[characters[0]]; 163 m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length); 164 return m_shortIdentifiers[characters[0]]; 165 } 166 if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length)) 167 return m_recentIdentifiers[characters[0]]; 168 m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length); 169 return m_recentIdentifiers[characters[0]]; 170} 171 172template <typename CharType> 173template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token) 174{ 175 while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr)) 176 ++m_ptr; 177 178 ASSERT(m_ptr <= m_end); 179 if (m_ptr >= m_end) { 180 token.type = TokEnd; 181 token.start = token.end = m_ptr; 182 return TokEnd; 183 } 184 token.type = TokError; 185 token.start = m_ptr; 186 switch (*m_ptr) { 187 case '[': 188 token.type = TokLBracket; 189 token.end = ++m_ptr; 190 return TokLBracket; 191 case ']': 192 token.type = TokRBracket; 193 token.end = ++m_ptr; 194 return TokRBracket; 195 case '(': 196 token.type = TokLParen; 197 token.end = ++m_ptr; 198 return TokLParen; 199 case ')': 200 token.type = TokRParen; 201 token.end = ++m_ptr; 202 return TokRParen; 203 case '{': 204 token.type = TokLBrace; 205 token.end = ++m_ptr; 206 return TokLBrace; 207 case '}': 208 token.type = TokRBrace; 209 token.end = ++m_ptr; 210 return TokRBrace; 211 case ',': 212 token.type = TokComma; 213 token.end = ++m_ptr; 214 return TokComma; 215 case ':': 216 token.type = TokColon; 217 token.end = ++m_ptr; 218 return TokColon; 219 case '"': 220 return lexString<mode, '"'>(token); 221 case 't': 222 if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') { 223 m_ptr += 4; 224 token.type = TokTrue; 225 token.end = m_ptr; 226 return TokTrue; 227 } 228 break; 229 case 'f': 230 if (m_end - m_ptr >= 5 && m_ptr[1] == 'a' && m_ptr[2] == 'l' && m_ptr[3] == 's' && m_ptr[4] == 'e') { 231 m_ptr += 5; 232 token.type = TokFalse; 233 token.end = m_ptr; 234 return TokFalse; 235 } 236 break; 237 case 'n': 238 if (m_end - m_ptr >= 4 && m_ptr[1] == 'u' && m_ptr[2] == 'l' && m_ptr[3] == 'l') { 239 m_ptr += 4; 240 token.type = TokNull; 241 token.end = m_ptr; 242 return TokNull; 243 } 244 break; 245 case '-': 246 case '0': 247 case '1': 248 case '2': 249 case '3': 250 case '4': 251 case '5': 252 case '6': 253 case '7': 254 case '8': 255 case '9': 256 return lexNumber(token); 257 } 258 if (m_ptr < m_end) { 259 if (*m_ptr == '.') { 260 token.type = TokDot; 261 token.end = ++m_ptr; 262 return TokDot; 263 } 264 if (*m_ptr == '=') { 265 token.type = TokAssign; 266 token.end = ++m_ptr; 267 return TokAssign; 268 } 269 if (*m_ptr == ';') { 270 token.type = TokSemi; 271 token.end = ++m_ptr; 272 return TokAssign; 273 } 274 if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') 275 return lexIdentifier(token); 276 if (*m_ptr == '\'') { 277 if (mode == StrictJSON) { 278 m_lexErrorMessage = ASCIILiteral("Single quotes (\') are not allowed in JSON"); 279 return TokError; 280 } 281 return lexString<mode, '\''>(token); 282 } 283 } 284 m_lexErrorMessage = String::format("Unrecognized token '%c'", *m_ptr).impl(); 285 return TokError; 286} 287 288template <> 289ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token) 290{ 291 while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')) 292 m_ptr++; 293 token.stringIs8Bit = 1; 294 token.stringToken8 = token.start; 295 token.stringLength = m_ptr - token.start; 296 token.type = TokIdentifier; 297 token.end = m_ptr; 298 return TokIdentifier; 299} 300 301template <> 302ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token) 303{ 304 while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$' || *m_ptr == 0x200C || *m_ptr == 0x200D)) 305 m_ptr++; 306 token.stringIs8Bit = 0; 307 token.stringToken16 = token.start; 308 token.stringLength = m_ptr - token.start; 309 token.type = TokIdentifier; 310 token.end = m_ptr; 311 return TokIdentifier; 312} 313 314template <typename CharType> 315TokenType LiteralParser<CharType>::Lexer::next() 316{ 317 if (m_mode == NonStrictJSON) 318 return lex<NonStrictJSON>(m_currentToken); 319 if (m_mode == JSONP) 320 return lex<JSONP>(m_currentToken); 321 return lex<StrictJSON>(m_currentToken); 322} 323 324template <> 325ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string) 326{ 327 token.stringIs8Bit = 1; 328 token.stringToken8 = string; 329} 330 331template <> 332ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string) 333{ 334 token.stringIs8Bit = 0; 335 token.stringToken16 = string; 336} 337 338template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c) 339{ 340 return (c >= ' ' && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON); 341} 342 343template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c) 344{ 345 return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON); 346} 347 348template <typename CharType> 349template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token) 350{ 351 ++m_ptr; 352 const CharType* runStart = m_ptr; 353 StringBuilder builder; 354 do { 355 runStart = m_ptr; 356 while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr)) 357 ++m_ptr; 358 if (builder.length()) 359 builder.append(runStart, m_ptr - runStart); 360 if ((mode != NonStrictJSON) && m_ptr < m_end && *m_ptr == '\\') { 361 if (builder.isEmpty() && runStart < m_ptr) 362 builder.append(runStart, m_ptr - runStart); 363 ++m_ptr; 364 if (m_ptr >= m_end) { 365 m_lexErrorMessage = ASCIILiteral("Unterminated string"); 366 return TokError; 367 } 368 switch (*m_ptr) { 369 case '"': 370 builder.append('"'); 371 m_ptr++; 372 break; 373 case '\\': 374 builder.append('\\'); 375 m_ptr++; 376 break; 377 case '/': 378 builder.append('/'); 379 m_ptr++; 380 break; 381 case 'b': 382 builder.append('\b'); 383 m_ptr++; 384 break; 385 case 'f': 386 builder.append('\f'); 387 m_ptr++; 388 break; 389 case 'n': 390 builder.append('\n'); 391 m_ptr++; 392 break; 393 case 'r': 394 builder.append('\r'); 395 m_ptr++; 396 break; 397 case 't': 398 builder.append('\t'); 399 m_ptr++; 400 break; 401 402 case 'u': 403 if ((m_end - m_ptr) < 5) { 404 m_lexErrorMessage = ASCIILiteral("\\u must be followed by 4 hex digits"); 405 return TokError; 406 } // uNNNN == 5 characters 407 for (int i = 1; i < 5; i++) { 408 if (!isASCIIHexDigit(m_ptr[i])) { 409 m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", String(m_ptr, 5).ascii().data()).impl(); 410 return TokError; 411 } 412 } 413 builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4])); 414 m_ptr += 5; 415 break; 416 417 default: 418 if (*m_ptr == '\'' && mode != StrictJSON) { 419 builder.append('\''); 420 m_ptr++; 421 break; 422 } 423 m_lexErrorMessage = String::format("Invalid escape character %c", *m_ptr).impl(); 424 return TokError; 425 } 426 } 427 } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator); 428 429 if (m_ptr >= m_end || *m_ptr != terminator) { 430 m_lexErrorMessage = ASCIILiteral("Unterminated string"); 431 return TokError; 432 } 433 434 if (builder.isEmpty()) { 435 token.stringBuffer = String(); 436 setParserTokenString<CharType>(token, runStart); 437 token.stringLength = m_ptr - runStart; 438 } else { 439 token.stringBuffer = builder.toString(); 440 if (token.stringBuffer.is8Bit()) { 441 token.stringIs8Bit = 1; 442 token.stringToken8 = token.stringBuffer.characters8(); 443 } else { 444 token.stringIs8Bit = 0; 445 token.stringToken16 = token.stringBuffer.characters16(); 446 } 447 token.stringLength = token.stringBuffer.length(); 448 } 449 token.type = TokString; 450 token.end = ++m_ptr; 451 return TokString; 452} 453 454template <typename CharType> 455TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token) 456{ 457 // ES5 and json.org define numbers as 458 // number 459 // int 460 // int frac? exp? 461 // 462 // int 463 // -? 0 464 // -? digit1-9 digits? 465 // 466 // digits 467 // digit digits? 468 // 469 // -?(0 | [1-9][0-9]*) ('.' [0-9]+)? ([eE][+-]? [0-9]+)? 470 471 if (m_ptr < m_end && *m_ptr == '-') // -? 472 ++m_ptr; 473 474 // (0 | [1-9][0-9]*) 475 if (m_ptr < m_end && *m_ptr == '0') // 0 476 ++m_ptr; 477 else if (m_ptr < m_end && *m_ptr >= '1' && *m_ptr <= '9') { // [1-9] 478 ++m_ptr; 479 // [0-9]* 480 while (m_ptr < m_end && isASCIIDigit(*m_ptr)) 481 ++m_ptr; 482 } else { 483 m_lexErrorMessage = ASCIILiteral("Invalid number"); 484 return TokError; 485 } 486 487 // ('.' [0-9]+)? 488 if (m_ptr < m_end && *m_ptr == '.') { 489 ++m_ptr; 490 // [0-9]+ 491 if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) { 492 m_lexErrorMessage = ASCIILiteral("Invalid digits after decimal point"); 493 return TokError; 494 } 495 496 ++m_ptr; 497 while (m_ptr < m_end && isASCIIDigit(*m_ptr)) 498 ++m_ptr; 499 } else if (m_ptr < m_end && (*m_ptr != 'e' && *m_ptr != 'E') && (m_ptr - token.start) < 10) { 500 int result = 0; 501 token.type = TokNumber; 502 token.end = m_ptr; 503 const CharType* digit = token.start; 504 int negative = 1; 505 if (*digit == '-') { 506 negative = -1; 507 digit++; 508 } 509 510 while (digit < m_ptr) 511 result = result * 10 + (*digit++) - '0'; 512 result *= negative; 513 token.numberToken = result; 514 return TokNumber; 515 } 516 517 // ([eE][+-]? [0-9]+)? 518 if (m_ptr < m_end && (*m_ptr == 'e' || *m_ptr == 'E')) { // [eE] 519 ++m_ptr; 520 521 // [-+]? 522 if (m_ptr < m_end && (*m_ptr == '-' || *m_ptr == '+')) 523 ++m_ptr; 524 525 // [0-9]+ 526 if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) { 527 m_lexErrorMessage = ASCIILiteral("Exponent symbols should be followed by an optional '+' or '-' and then by at least one number"); 528 return TokError; 529 } 530 531 ++m_ptr; 532 while (m_ptr < m_end && isASCIIDigit(*m_ptr)) 533 ++m_ptr; 534 } 535 536 token.type = TokNumber; 537 token.end = m_ptr; 538 size_t parsedLength; 539 token.numberToken = parseDouble(token.start, token.end - token.start, parsedLength); 540 return TokNumber; 541} 542 543template <typename CharType> 544JSValue LiteralParser<CharType>::parse(ParserState initialState) 545{ 546 ParserState state = initialState; 547 MarkedArgumentBuffer objectStack; 548 JSValue lastValue; 549 Vector<ParserState, 16, UnsafeVectorOverflow> stateStack; 550 Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack; 551 while (1) { 552 switch(state) { 553 startParseArray: 554 case StartParseArray: { 555 JSArray* array = constructEmptyArray(m_exec, 0); 556 objectStack.append(array); 557 } 558 doParseArrayStartExpression: 559 FALLTHROUGH; 560 case DoParseArrayStartExpression: { 561 TokenType lastToken = m_lexer.currentToken().type; 562 if (m_lexer.next() == TokRBracket) { 563 if (lastToken == TokComma) { 564 m_parseErrorMessage = ASCIILiteral("Unexpected comma at the end of array expression"); 565 return JSValue(); 566 } 567 m_lexer.next(); 568 lastValue = objectStack.last(); 569 objectStack.removeLast(); 570 break; 571 } 572 573 stateStack.append(DoParseArrayEndExpression); 574 goto startParseExpression; 575 } 576 case DoParseArrayEndExpression: { 577 JSArray* array = asArray(objectStack.last()); 578 array->putDirectIndex(m_exec, array->length(), lastValue); 579 580 if (m_lexer.currentToken().type == TokComma) 581 goto doParseArrayStartExpression; 582 583 if (m_lexer.currentToken().type != TokRBracket) { 584 m_parseErrorMessage = ASCIILiteral("Expected ']'"); 585 return JSValue(); 586 } 587 588 m_lexer.next(); 589 lastValue = objectStack.last(); 590 objectStack.removeLast(); 591 break; 592 } 593 startParseObject: 594 case StartParseObject: { 595 JSObject* object = constructEmptyObject(m_exec); 596 objectStack.append(object); 597 598 TokenType type = m_lexer.next(); 599 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) { 600 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken(); 601 602 // Check for colon 603 if (m_lexer.next() != TokColon) { 604 m_parseErrorMessage = ASCIILiteral("Expected ':' before value in object property definition"); 605 return JSValue(); 606 } 607 608 m_lexer.next(); 609 if (identifierToken.stringIs8Bit) 610 identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength)); 611 else 612 identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength)); 613 stateStack.append(DoParseObjectEndExpression); 614 goto startParseExpression; 615 } 616 if (type != TokRBrace) { 617 m_parseErrorMessage = ASCIILiteral("Expected '}'"); 618 return JSValue(); 619 } 620 m_lexer.next(); 621 lastValue = objectStack.last(); 622 objectStack.removeLast(); 623 break; 624 } 625 doParseObjectStartExpression: 626 case DoParseObjectStartExpression: { 627 TokenType type = m_lexer.next(); 628 if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) { 629 m_parseErrorMessage = ASCIILiteral("Property name must be a string literal"); 630 return JSValue(); 631 } 632 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken(); 633 634 // Check for colon 635 if (m_lexer.next() != TokColon) { 636 m_parseErrorMessage = ASCIILiteral("Expected ':'"); 637 return JSValue(); 638 } 639 640 m_lexer.next(); 641 if (identifierToken.stringIs8Bit) 642 identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength)); 643 else 644 identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength)); 645 stateStack.append(DoParseObjectEndExpression); 646 goto startParseExpression; 647 } 648 case DoParseObjectEndExpression: 649 { 650 JSObject* object = asObject(objectStack.last()); 651 PropertyName ident = identifierStack.last(); 652 unsigned i = ident.asIndex(); 653 if (i != PropertyName::NotAnIndex) 654 object->putDirectIndex(m_exec, i, lastValue); 655 else 656 object->putDirect(m_exec->vm(), ident, lastValue); 657 identifierStack.removeLast(); 658 if (m_lexer.currentToken().type == TokComma) 659 goto doParseObjectStartExpression; 660 if (m_lexer.currentToken().type != TokRBrace) { 661 m_parseErrorMessage = ASCIILiteral("Expected '}'"); 662 return JSValue(); 663 } 664 m_lexer.next(); 665 lastValue = objectStack.last(); 666 objectStack.removeLast(); 667 break; 668 } 669 startParseExpression: 670 case StartParseExpression: { 671 switch (m_lexer.currentToken().type) { 672 case TokLBracket: 673 goto startParseArray; 674 case TokLBrace: 675 goto startParseObject; 676 case TokString: { 677 LiteralParserToken<CharType> stringToken = m_lexer.currentToken(); 678 m_lexer.next(); 679 if (stringToken.stringIs8Bit) 680 lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).string()); 681 else 682 lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).string()); 683 break; 684 } 685 case TokNumber: { 686 LiteralParserToken<CharType> numberToken = m_lexer.currentToken(); 687 m_lexer.next(); 688 lastValue = jsNumber(numberToken.numberToken); 689 break; 690 } 691 case TokNull: 692 m_lexer.next(); 693 lastValue = jsNull(); 694 break; 695 696 case TokTrue: 697 m_lexer.next(); 698 lastValue = jsBoolean(true); 699 break; 700 701 case TokFalse: 702 m_lexer.next(); 703 lastValue = jsBoolean(false); 704 break; 705 case TokRBracket: 706 m_parseErrorMessage = ASCIILiteral("Unexpected token ']'"); 707 return JSValue(); 708 case TokRBrace: 709 m_parseErrorMessage = ASCIILiteral("Unexpected token '}'"); 710 return JSValue(); 711 case TokIdentifier: { 712 const LiteralParserToken<CharType>& token = m_lexer.currentToken(); 713 if (token.stringIs8Bit) 714 m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl(); 715 else 716 m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl(); 717 return JSValue(); 718 } 719 case TokColon: 720 m_parseErrorMessage = ASCIILiteral("Unexpected token ':'"); 721 return JSValue(); 722 case TokLParen: 723 m_parseErrorMessage = ASCIILiteral("Unexpected token '('"); 724 return JSValue(); 725 case TokRParen: 726 m_parseErrorMessage = ASCIILiteral("Unexpected token ')'"); 727 return JSValue(); 728 case TokComma: 729 m_parseErrorMessage = ASCIILiteral("Unexpected token ','"); 730 return JSValue(); 731 case TokDot: 732 m_parseErrorMessage = ASCIILiteral("Unexpected token '.'"); 733 return JSValue(); 734 case TokAssign: 735 m_parseErrorMessage = ASCIILiteral("Unexpected token '='"); 736 return JSValue(); 737 case TokSemi: 738 m_parseErrorMessage = ASCIILiteral("Unexpected token ';'"); 739 return JSValue(); 740 case TokEnd: 741 m_parseErrorMessage = ASCIILiteral("Unexpected EOF"); 742 return JSValue(); 743 case TokError: 744 default: 745 // Error 746 m_parseErrorMessage = ASCIILiteral("Could not parse value expression"); 747 return JSValue(); 748 } 749 break; 750 } 751 case StartParseStatement: { 752 switch (m_lexer.currentToken().type) { 753 case TokLBracket: 754 case TokNumber: 755 case TokString: 756 goto startParseExpression; 757 758 case TokLParen: { 759 m_lexer.next(); 760 stateStack.append(StartParseStatementEndStatement); 761 goto startParseExpression; 762 } 763 case TokRBracket: 764 m_parseErrorMessage = ASCIILiteral("Unexpected token ']'"); 765 return JSValue(); 766 case TokLBrace: 767 m_parseErrorMessage = ASCIILiteral("Unexpected token '{'"); 768 return JSValue(); 769 case TokRBrace: 770 m_parseErrorMessage = ASCIILiteral("Unexpected token '}'"); 771 return JSValue(); 772 case TokIdentifier: 773 m_parseErrorMessage = ASCIILiteral("Unexpected identifier"); 774 return JSValue(); 775 case TokColon: 776 m_parseErrorMessage = ASCIILiteral("Unexpected token ':'"); 777 return JSValue(); 778 case TokRParen: 779 m_parseErrorMessage = ASCIILiteral("Unexpected token ')'"); 780 return JSValue(); 781 case TokComma: 782 m_parseErrorMessage = ASCIILiteral("Unexpected token ','"); 783 return JSValue(); 784 case TokTrue: 785 m_parseErrorMessage = ASCIILiteral("Unexpected token 'true'"); 786 return JSValue(); 787 case TokFalse: 788 m_parseErrorMessage = ASCIILiteral("Unexpected token 'false'"); 789 return JSValue(); 790 case TokNull: 791 m_parseErrorMessage = ASCIILiteral("Unexpected token 'null'"); 792 return JSValue(); 793 case TokEnd: 794 m_parseErrorMessage = ASCIILiteral("Unexpected EOF"); 795 return JSValue(); 796 case TokDot: 797 m_parseErrorMessage = ASCIILiteral("Unexpected token '.'"); 798 return JSValue(); 799 case TokAssign: 800 m_parseErrorMessage = ASCIILiteral("Unexpected token '='"); 801 return JSValue(); 802 case TokSemi: 803 m_parseErrorMessage = ASCIILiteral("Unexpected token ';'"); 804 return JSValue(); 805 case TokError: 806 default: 807 m_parseErrorMessage = ASCIILiteral("Could not parse statement"); 808 return JSValue(); 809 } 810 } 811 case StartParseStatementEndStatement: { 812 ASSERT(stateStack.isEmpty()); 813 if (m_lexer.currentToken().type != TokRParen) 814 return JSValue(); 815 if (m_lexer.next() == TokEnd) 816 return lastValue; 817 m_parseErrorMessage = ASCIILiteral("Unexpected content at end of JSON literal"); 818 return JSValue(); 819 } 820 default: 821 RELEASE_ASSERT_NOT_REACHED(); 822 } 823 if (stateStack.isEmpty()) 824 return lastValue; 825 state = stateStack.last(); 826 stateStack.removeLast(); 827 continue; 828 } 829} 830 831// Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h 832template class LiteralParser<LChar>; 833template class LiteralParser<UChar>; 834 835} 836