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