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