1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Redistribution and use in source and binary forms, with or without
3257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// modification, are permitted provided that the following conditions are
4257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// met:
5257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//
6257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Redistributions of source code must retain the above copyright
7257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Redistributions in binary form must reproduce the above
9257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       copyright notice, this list of conditions and the following
10257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       with the distribution.
12257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       contributors may be used to endorse or promote products derived
14257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//       from this software without specific prior written permission.
15257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//
16257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifndef V8_JSON_PARSER_H_
29257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define V8_JSON_PARSER_H_
30257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "v8.h"
323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "char-predicates-inl.h"
343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "v8conversions.h"
353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "messages.h"
363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "spaces-inl.h"
37257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "token.h"
38257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochnamespace v8 {
40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochnamespace internal {
41257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// A simple json parser.
433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass JsonParser BASE_EMBEDDED {
45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static Handle<Object> Parse(Handle<String> source) {
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return JsonParser().ParseJson(source);
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kEndOfString = -1;
51257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Parse a string containing a single JSON value.
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> ParseJson(Handle<String> source);
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void Advance() {
573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    position_++;
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (position_ >= source_length_) {
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      c0_ = kEndOfString;
603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (seq_ascii) {
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      c0_ = seq_source_->SeqAsciiStringGet(position_);
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      c0_ = source_->Get(position_);
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The JSON lexical grammar is specified in the ECMAScript 5 standard,
683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // section 15.12.1.1. The only allowed whitespace characters between tokens
693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // are tab, carriage-return, newline and space.
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline void AdvanceSkipWhitespace() {
723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ');
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline void SkipWhitespace() {
783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ') {
793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline uc32 AdvanceGetChar() {
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Advance();
853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return c0_;
863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Checks that current charater is c.
893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If so, then consume c and skip whitespace.
903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline bool MatchSkipWhiteSpace(uc32 c) {
913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ == c) {
923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AdvanceSkipWhitespace();
933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return true;
943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return false;
963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // A JSON string (production JSONString) is subset of valid JavaScript string
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // literals. The string must only be double-quoted (not single-quoted), and
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> ParseJsonString() {
1033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ScanJsonString<false>();
1043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> ParseJsonSymbol() {
1063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ScanJsonString<true>();
1073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  template <bool is_symbol>
1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> ScanJsonString();
1103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Creates a new string and copies prefix[start..end] into the beginning
1113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // of it. Then scans the rest of the string, adding characters after the
1123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  template <typename StringType, typename SinkChar>
1143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // A JSON number (production JSONNumber) is a subset of the valid JavaScript
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // decimal number literals.
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // It includes an optional minus sign, must have at least one
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // digit before and after a decimal point, may not have prefixed zeros (unless
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the integer part is zero), and may include an exponent part (e.g., "e-10").
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Hexadecimal and octal numbers are not allowed.
1223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Object> ParseJsonNumber();
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Parse a single JSON value from input (grammar production JSONValue).
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // A JSON value is either a (double-quoted) string literal, a number literal,
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // one of "true", "false", or "null", or an object or array literal.
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> ParseJsonValue();
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Parse a JSON object literal (grammar production JSONObject).
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // An object literal is a squiggly-braced and comma separated sequence
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (possibly empty) of key/value pairs, where the key is a JSON string
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // literal, the value is a JSON value, and the two are separated by a colon.
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A JSON array doesn't allow numbers and identifiers as keys, like a
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // JavaScript array.
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> ParseJsonObject();
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Parses a JSON array literal (grammar production JSONArray). An array
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // literal is a square-bracketed and comma separated sequence (possibly empty)
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // of JSON values.
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // A JSON array doesn't allow leaving out values from the sequence, nor does
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // it allow a terminal comma, like a JavaScript array does.
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> ParseJsonArray();
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Mark that a parsing error has happened at the current token, and
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // return a null handle. Primarily for readability.
1473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline Handle<Object> ReportUnexpectedCharacter() {
1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return Handle<Object>::null();
1493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline Isolate* isolate() { return isolate_; }
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const int kInitialSpecialStringLength = 1024;
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<String> source_;
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int source_length_;
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<SeqAsciiString> seq_source_;
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate_;
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uc32 c0_;
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int position_;
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate_ = source->map()->GetHeap()->isolate();
16969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  FlattenString(source);
17069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  source_ = source;
1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  source_length_ = source_->length();
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Optimized fast case where we only have ASCII characters.
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (seq_ascii) {
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    seq_source_ = Handle<SeqAsciiString>::cast(source_);
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set initial position right before the string.
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  position_ = -1;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Advance to the first character (possibly EOS)
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Object> result = ParseJsonValue();
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (result.is_null() || c0_ != kEndOfString) {
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Parse failed. Current character is the unexpected token.
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    const char* message;
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Factory* factory = isolate()->factory();
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Handle<JSArray> array;
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    switch (c0_) {
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case kEndOfString:
1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        message = "unexpected_eos";
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        array = factory->NewJSArray(0);
1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '-':
1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '0':
1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '1':
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '2':
1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '3':
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '4':
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '5':
2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '6':
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '7':
2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '8':
2053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '9':
2063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        message = "unexpected_token_number";
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        array = factory->NewJSArray(0);
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case '"':
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        message = "unexpected_token_string";
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        array = factory->NewJSArray(0);
2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
2133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      default:
2143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        message = "unexpected_token";
2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Handle<Object> name = LookupSingleCharacterStringFromCode(c0_);
2163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Handle<FixedArray> element = factory->NewFixedArray(1);
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        element->set(0, *name);
2183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        array = factory->NewJSArrayWithElements(element);
2193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
2203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MessageLocation location(factory->NewScript(source),
2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             position_,
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             position_ + 1);
2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Handle<Object> result = factory->NewSyntaxError(message, array);
2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    isolate()->Throw(*result, &location);
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return Handle<Object>::null();
2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return result;
2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
2313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Parse any JSON value.
2343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
2353fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
2363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (c0_) {
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '"':
2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ParseJsonString();
2393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '-':
2403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '0':
2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '1':
2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '2':
2433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '3':
2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '4':
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '5':
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '6':
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '7':
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '8':
2493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '9':
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ParseJsonNumber();
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case 'f':
2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
2533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AdvanceSkipWhitespace();
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return isolate()->factory()->false_value();
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
2573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return ReportUnexpectedCharacter();
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case 't':
2603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
2613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          AdvanceGetChar() == 'e') {
2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AdvanceSkipWhitespace();
2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return isolate()->factory()->true_value();
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return ReportUnexpectedCharacter();
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case 'n':
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          AdvanceGetChar() == 'l') {
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AdvanceSkipWhitespace();
2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return isolate()->factory()->null_value();
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
2733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return ReportUnexpectedCharacter();
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '{':
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ParseJsonObject();
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case '[':
2783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ParseJsonArray();
2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    default:
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ReportUnexpectedCharacter();
2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Parse a JSON object. Position must be right at '{'.
2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
2883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<JSFunction> object_constructor(
2893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      isolate()->global_context()->object_function());
2903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<JSObject> json_object =
2913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      isolate()->factory()->NewJSObject(object_constructor);
2923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(c0_, '{');
2933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ != '}') {
2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (c0_ != '"') return ReportUnexpectedCharacter();
2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Handle<String> key = ParseJsonSymbol();
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AdvanceSkipWhitespace();
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Handle<Object> value = ParseJsonValue();
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (value.is_null()) return ReportUnexpectedCharacter();
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      uint32_t index;
3053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (key->AsArrayIndex(&index)) {
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        JSObject::SetOwnElement(json_object, index, value, kNonStrictMode);
3073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
3083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        SetPrototype(json_object, value);
3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        JSObject::SetLocalPropertyIgnoreAttributes(
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            json_object, key, value, NONE);
3123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (MatchSkipWhiteSpace(','));
3143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ != '}') {
3153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ReportUnexpectedCharacter();
3163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return json_object;
3203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Parse a JSON array. Position must be right at '['.
3233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
3243fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
3253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneScope zone_scope(isolate(), DELETE_ON_EXIT);
3263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneList<Handle<Object> > elements(4);
3273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(c0_, '[');
3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
3303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ != ']') {
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Handle<Object> element = ParseJsonValue();
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (element.is_null()) return ReportUnexpectedCharacter();
3343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      elements.Add(element);
3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (MatchSkipWhiteSpace(','));
3363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ != ']') {
3373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ReportUnexpectedCharacter();
3383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
3413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Allocate a fixed array with all the elements.
3423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<FixedArray> fast_elements =
3433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      isolate()->factory()->NewFixedArray(elements.length());
3443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0, n = elements.length(); i < n; i++) {
3453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    fast_elements->set(i, *elements[i]);
3463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return isolate()->factory()->NewJSArrayWithElements(fast_elements);
3483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
3523fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
3533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool negative = false;
3543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int beg_pos = position_;
3553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ == '-') {
3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Advance();
3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    negative = true;
3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ == '0') {
3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Advance();
3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Prefix zero is only allowed if it's the only digit before
3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // a decimal point or exponent.
3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
3653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int i = 0;
3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int digits = 0;
3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
3693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      i = i * 10 + c0_ - '0';
3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      digits++;
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (c0_ >= '0' && c0_ <= '9');
3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      SkipWhitespace();
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ == '.') {
3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Advance();
3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
3813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (c0_ >= '0' && c0_ <= '9');
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (AsciiAlphaToLower(c0_) == 'e') {
3863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Advance();
3873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ == '-' || c0_ == '+') Advance();
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
3913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (c0_ >= '0' && c0_ <= '9');
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int length = position_ - beg_pos;
3943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  double number;
3953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (seq_ascii) {
3963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Vector<const char> chars(seq_source_->GetChars() +  beg_pos, length);
3973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    number = StringToDouble(isolate()->unicode_cache(),
3983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             chars,
3993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             NO_FLAGS,  // Hex, octal or trailing junk.
4003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             OS::nan_value());
4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Vector<char> buffer = Vector<char>::New(length);
4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Vector<const char> result =
4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        length);
4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    number = StringToDouble(isolate()->unicode_cache(),
4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             result,
4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             NO_FLAGS,  // Hex, octal or trailing junk.
4103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             0.0);
4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    buffer.Dispose();
4123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SkipWhitespace();
4143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return isolate()->factory()->NewNumber(number);
4153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <typename StringType>
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <>
4223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
4233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  seq_str->SeqTwoByteStringSet(i, c);
4243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <>
4273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline void SeqStringSet(Handle<SeqAsciiString> seq_str, int i, uc32 c) {
4283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  seq_str->SeqAsciiStringSet(i, c);
4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <typename StringType>
4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline Handle<StringType> NewRawString(Factory* factory, int length);
4333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <>
4353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length) {
4363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return factory->NewRawTwoByteString(length, NOT_TENURED);
4373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <>
4403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochinline Handle<SeqAsciiString> NewRawString(Factory* factory, int length) {
4413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return factory->NewRawAsciiString(length, NOT_TENURED);
4423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Scans the rest of a JSON string starting from position_ and writes
4463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// prefix[start..end] along with the scanned characters into a
4473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// sequential string of type StringType.
4483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
4493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <typename StringType, typename SinkChar>
4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<String> JsonParser<seq_ascii>::SlowScanJsonString(
4513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Handle<String> prefix, int start, int end) {
4523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int count = end - start;
4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int max_length = count + source_length_ - position_;
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
4553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<StringType> seq_str = NewRawString<StringType>(isolate()->factory(),
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                        length);
4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Copy prefix into seq_str.
4583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SinkChar* dest = seq_str->GetChars();
4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  String::WriteToFlat(*prefix, dest, start, end);
4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (c0_ != '"') {
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check for control character (0x00-0x1f) or unterminated string (<0).
4633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ < 0x20) return Handle<String>::null();
4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (count >= length) {
4653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // We need to create a longer sequential string for the result.
4663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
4673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ != '\\') {
4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // If the sink can contain UC16 characters, or source_ contains only
4703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // ASCII characters, there's no need to test whether we can store the
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // character. Otherwise check whether the UC16 source character can fit
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // in the ASCII sink.
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (sizeof(SinkChar) == kUC16Size ||
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          seq_ascii ||
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          c0_ <= kMaxAsciiCharCode) {
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        SeqStringSet(seq_str, count++, c0_);
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Advance();
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // StringType is SeqAsciiString and we just read a non-ASCII char.
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str, 0, count);
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();  // Advance past the \.
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      switch (c0_) {
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case '"':
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case '\\':
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case '/':
4883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, c0_);
4893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
4903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 'b':
4913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, '\x08');
4923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 'f':
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, '\x0c');
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 'n':
4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, '\x0a');
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 'r':
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, '\x0d');
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 't':
5033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          SeqStringSet(seq_str, count++, '\x09');
5043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          break;
5053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        case 'u': {
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          uc32 value = 0;
5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          for (int i = 0; i < 4; i++) {
5083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            Advance();
5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            int digit = HexValue(c0_);
5103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            if (digit < 0) {
5113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              return Handle<String>::null();
5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            }
5133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            value = value * 16 + digit;
5143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
5153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (sizeof(SinkChar) == kUC16Size || value <= kMaxAsciiCharCode) {
5163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SeqStringSet(seq_str, count++, value);
5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            break;
5183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          } else {
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            // StringType is SeqAsciiString and we just read a non-ASCII char.
5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            position_ -= 6;  // Rewind position_ to \ in \uxxxx.
5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            Advance();
5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str,
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                              0,
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                              count);
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
5263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        default:
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return Handle<String>::null();
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Advance();
5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Shrink seq_string length to count.
5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (isolate()->heap()->InNewSpace(*seq_str)) {
5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    isolate()->heap()->new_space()->
5363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        template ShrinkStringAtAllocationBoundary<StringType>(
5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            *seq_str, count);
5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int string_size = StringType::SizeFor(count);
5403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int allocated_string_size = StringType::SizeFor(length);
5413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int delta = allocated_string_size - string_size;
5423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Address start_filler_object = seq_str->address() + string_size;
5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    seq_str->set_length(count);
5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta);
5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ('"', c0_);
5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Advance past the last '"'.
5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return seq_str;
5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool seq_ascii>
5543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <bool is_symbol>
5553fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<String> JsonParser<seq_ascii>::ScanJsonString() {
5563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ('"', c0_);
5573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Advance();
5583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (c0_ == '"') {
5593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AdvanceSkipWhitespace();
5603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return Handle<String>(isolate()->heap()->empty_string());
5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int beg_pos = position_;
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Fast case for ASCII only without escape characters.
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  do {
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check for control character (0x00-0x1f) or unterminated string (<0).
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ < 0x20) return Handle<String>::null();
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (c0_ != '\\') {
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (seq_ascii || c0_ <= kMaxAsciiCharCode) {
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Advance();
5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                          beg_pos,
5733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                          position_);
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return SlowScanJsonString<SeqAsciiString, char>(source_,
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      beg_pos,
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      position_);
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } while (c0_ != '"');
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int length = position_ - beg_pos;
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> result;
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (seq_ascii && is_symbol) {
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result = isolate()->factory()->LookupAsciiSymbol(seq_source_,
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     beg_pos,
5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     length);
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result = isolate()->factory()->NewRawAsciiString(length);
5893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char* dest = SeqAsciiString::cast(*result)->GetChars();
5903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    String::WriteToFlat(*source_, dest, beg_pos, position_);
5913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ('"', c0_);
5933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Advance past the last '"'.
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AdvanceSkipWhitespace();
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return result;
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} }  // namespace v8::internal
599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif  // V8_JSON_PARSER_H_
601