2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "LiteralParser.h"
30 #include "ButterflyInlines.h"
31 #include "CopiedSpaceInlines.h"
35 #include "ObjectConstructor.h"
36 #include "JSCInlines.h"
37 #include "StrongInlines.h"
38 #include <wtf/ASCIICType.h>
40 #include <wtf/text/StringBuilder.h>
44 template <typename CharType
>
45 static inline bool isJSONWhiteSpace(const CharType
& c
)
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;
52 template <typename CharType
>
53 bool LiteralParser
<CharType
>::tryJSONPParse(Vector
<JSONPData
>& results
, bool needsFullSourceInfo
)
55 if (m_lexer
.next() != TokIdentifier
)
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
);
62 if (name
== m_exec
->vm().propertyNames
->varKeyword
) {
63 if (m_lexer
.next() != TokIdentifier
)
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
);
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
);
73 if (m_exec
->vm().keywords
->isKeyword(entry
.m_pathEntryName
))
75 TokenType tokenType
= m_lexer
.next();
76 if (entry
.m_type
== JSONPPathEntryTypeDeclare
&& tokenType
!= TokAssign
)
78 while (tokenType
!= TokAssign
) {
81 entry
.m_type
= JSONPPathEntryTypeLookup
;
82 if (m_lexer
.next() != TokNumber
)
84 double doubleIndex
= m_lexer
.currentToken().numberToken
;
85 int index
= (int)doubleIndex
;
86 if (index
!= doubleIndex
|| index
< 0)
88 entry
.m_pathIndex
= index
;
89 if (m_lexer
.next() != TokRBracket
)
94 entry
.m_type
= JSONPPathEntryTypeDot
;
95 if (m_lexer
.next() != TokIdentifier
)
97 entry
.m_pathEntryName
= Identifier(&m_exec
->vm(), m_lexer
.currentToken().start
, m_lexer
.currentToken().end
- m_lexer
.currentToken().start
);
101 if (path
.last().m_type
!= JSONPPathEntryTypeDot
|| needsFullSourceInfo
)
103 path
.last().m_type
= JSONPPathEntryTypeCall
;
111 tokenType
= m_lexer
.next();
115 results
.append(JSONPData());
116 results
.last().m_value
.set(m_exec
->vm(), parse(StartParseExpression
));
117 if (!results
.last().m_value
)
119 results
.last().m_path
.swap(path
);
120 if (entry
.m_type
== JSONPPathEntryTypeCall
) {
121 if (m_lexer
.currentToken().type
!= TokRParen
)
125 if (m_lexer
.currentToken().type
!= TokSemi
)
128 } while (m_lexer
.currentToken().type
== TokIdentifier
);
129 return m_lexer
.currentToken().type
== TokEnd
;
132 template <typename CharType
>
133 ALWAYS_INLINE
const Identifier LiteralParser
<CharType
>::makeIdentifier(const LChar
* characters
, size_t length
)
136 return m_exec
->vm().propertyNames
->emptyIdentifier
;
137 if (characters
[0] >= MaximumCachableCharacter
)
138 return Identifier(&m_exec
->vm(), characters
, length
);
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]];
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]];
152 template <typename CharType
>
153 ALWAYS_INLINE
const Identifier LiteralParser
<CharType
>::makeIdentifier(const UChar
* characters
, size_t length
)
156 return m_exec
->vm().propertyNames
->emptyIdentifier
;
157 if (characters
[0] >= MaximumCachableCharacter
)
158 return Identifier(&m_exec
->vm(), characters
, length
);
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]];
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]];
172 template <typename CharType
>
173 template <ParserMode mode
> TokenType LiteralParser
<CharType
>::Lexer::lex(LiteralParserToken
<CharType
>& token
)
175 while (m_ptr
< m_end
&& isJSONWhiteSpace(*m_ptr
))
178 ASSERT(m_ptr
<= m_end
);
179 if (m_ptr
>= m_end
) {
181 token
.start
= token
.end
= m_ptr
;
184 token
.type
= TokError
;
188 token
.type
= TokLBracket
;
192 token
.type
= TokRBracket
;
196 token
.type
= TokLParen
;
200 token
.type
= TokRParen
;
204 token
.type
= TokLBrace
;
208 token
.type
= TokRBrace
;
212 token
.type
= TokComma
;
216 token
.type
= TokColon
;
220 return lexString
<mode
, '"'>(token
);
222 if (m_end
- m_ptr
>= 4 && m_ptr
[1] == 'r' && m_ptr
[2] == 'u' && m_ptr
[3] == 'e') {
224 token
.type
= TokTrue
;
230 if (m_end
- m_ptr
>= 5 && m_ptr
[1] == 'a' && m_ptr
[2] == 'l' && m_ptr
[3] == 's' && m_ptr
[4] == 'e') {
232 token
.type
= TokFalse
;
238 if (m_end
- m_ptr
>= 4 && m_ptr
[1] == 'u' && m_ptr
[2] == 'l' && m_ptr
[3] == 'l') {
240 token
.type
= TokNull
;
256 return lexNumber(token
);
265 token
.type
= TokAssign
;
270 token
.type
= TokSemi
;
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");
281 return lexString
<mode
, '\''>(token
);
284 m_lexErrorMessage
= String::format("Unrecognized token '%c'", *m_ptr
).impl();
289 ALWAYS_INLINE TokenType LiteralParser
<LChar
>::Lexer::lexIdentifier(LiteralParserToken
<LChar
>& token
)
291 while (m_ptr
< m_end
&& (isASCIIAlphanumeric(*m_ptr
) || *m_ptr
== '_' || *m_ptr
== '$'))
293 token
.stringIs8Bit
= 1;
294 token
.stringToken8
= token
.start
;
295 token
.stringLength
= m_ptr
- token
.start
;
296 token
.type
= TokIdentifier
;
298 return TokIdentifier
;
302 ALWAYS_INLINE TokenType LiteralParser
<UChar
>::Lexer::lexIdentifier(LiteralParserToken
<UChar
>& token
)
304 while (m_ptr
< m_end
&& (isASCIIAlphanumeric(*m_ptr
) || *m_ptr
== '_' || *m_ptr
== '$' || *m_ptr
== 0x200C || *m_ptr
== 0x200D))
306 token
.stringIs8Bit
= 0;
307 token
.stringToken16
= token
.start
;
308 token
.stringLength
= m_ptr
- token
.start
;
309 token
.type
= TokIdentifier
;
311 return TokIdentifier
;
314 template <typename CharType
>
315 TokenType LiteralParser
<CharType
>::Lexer::next()
317 if (m_mode
== NonStrictJSON
)
318 return lex
<NonStrictJSON
>(m_currentToken
);
320 return lex
<JSONP
>(m_currentToken
);
321 return lex
<StrictJSON
>(m_currentToken
);
325 ALWAYS_INLINE
void setParserTokenString
<LChar
>(LiteralParserToken
<LChar
>& token
, const LChar
* string
)
327 token
.stringIs8Bit
= 1;
328 token
.stringToken8
= string
;
332 ALWAYS_INLINE
void setParserTokenString
<UChar
>(LiteralParserToken
<UChar
>& token
, const UChar
* string
)
334 token
.stringIs8Bit
= 0;
335 token
.stringToken16
= string
;
338 template <ParserMode mode
, typename CharType
, LChar terminator
> static inline bool isSafeStringCharacter(LChar c
)
340 return (c
>= ' ' && c
!= '\\' && c
!= terminator
) || (c
== '\t' && mode
!= StrictJSON
);
343 template <ParserMode mode
, typename CharType
, UChar terminator
> static inline bool isSafeStringCharacter(UChar c
)
345 return (c
>= ' ' && (mode
== StrictJSON
|| c
<= 0xff) && c
!= '\\' && c
!= terminator
) || (c
== '\t' && mode
!= StrictJSON
);
348 template <typename CharType
>
349 template <ParserMode mode
, char terminator
> ALWAYS_INLINE TokenType LiteralParser
<CharType
>::Lexer::lexString(LiteralParserToken
<CharType
>& token
)
352 const CharType
* runStart
= m_ptr
;
353 StringBuilder builder
;
356 while (m_ptr
< m_end
&& isSafeStringCharacter
<mode
, CharType
, terminator
>(*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
);
364 if (m_ptr
>= m_end
) {
365 m_lexErrorMessage
= ASCIILiteral("Unterminated string");
374 builder
.append('\\');
382 builder
.append('\b');
386 builder
.append('\f');
390 builder
.append('\n');
394 builder
.append('\r');
398 builder
.append('\t');
403 if ((m_end
- m_ptr
) < 5) {
404 m_lexErrorMessage
= ASCIILiteral("\\u must be followed by 4 hex digits");
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();
413 builder
.append(JSC::Lexer
<CharType
>::convertUnicode(m_ptr
[1], m_ptr
[2], m_ptr
[3], m_ptr
[4]));
418 if (*m_ptr
== '\'' && mode
!= StrictJSON
) {
419 builder
.append('\'');
423 m_lexErrorMessage
= String::format("Invalid escape character %c", *m_ptr
).impl();
427 } while ((mode
!= NonStrictJSON
) && m_ptr
!= runStart
&& (m_ptr
< m_end
) && *m_ptr
!= terminator
);
429 if (m_ptr
>= m_end
|| *m_ptr
!= terminator
) {
430 m_lexErrorMessage
= ASCIILiteral("Unterminated string");
434 if (builder
.isEmpty()) {
435 token
.stringBuffer
= String();
436 setParserTokenString
<CharType
>(token
, runStart
);
437 token
.stringLength
= m_ptr
- runStart
;
439 token
.stringBuffer
= builder
.toString();
440 if (token
.stringBuffer
.is8Bit()) {
441 token
.stringIs8Bit
= 1;
442 token
.stringToken8
= token
.stringBuffer
.characters8();
444 token
.stringIs8Bit
= 0;
445 token
.stringToken16
= token
.stringBuffer
.characters16();
447 token
.stringLength
= token
.stringBuffer
.length();
449 token
.type
= TokString
;
454 template <typename CharType
>
455 TokenType LiteralParser
<CharType
>::Lexer::lexNumber(LiteralParserToken
<CharType
>& token
)
457 // ES5 and json.org define numbers as
464 // -? digit1-9 digits?
469 // -?(0 | [1-9][0-9]*) ('.' [0-9]+)? ([eE][+-]? [0-9]+)?
471 if (m_ptr
< m_end
&& *m_ptr
== '-') // -?
475 if (m_ptr
< m_end
&& *m_ptr
== '0') // 0
477 else if (m_ptr
< m_end
&& *m_ptr
>= '1' && *m_ptr
<= '9') { // [1-9]
480 while (m_ptr
< m_end
&& isASCIIDigit(*m_ptr
))
483 m_lexErrorMessage
= ASCIILiteral("Invalid number");
488 if (m_ptr
< m_end
&& *m_ptr
== '.') {
491 if (m_ptr
>= m_end
|| !isASCIIDigit(*m_ptr
)) {
492 m_lexErrorMessage
= ASCIILiteral("Invalid digits after decimal point");
497 while (m_ptr
< m_end
&& isASCIIDigit(*m_ptr
))
499 } else if (m_ptr
< m_end
&& (*m_ptr
!= 'e' && *m_ptr
!= 'E') && (m_ptr
- token
.start
) < 10) {
501 token
.type
= TokNumber
;
503 const CharType
* digit
= token
.start
;
510 while (digit
< m_ptr
)
511 result
= result
* 10 + (*digit
++) - '0';
513 token
.numberToken
= result
;
517 // ([eE][+-]? [0-9]+)?
518 if (m_ptr
< m_end
&& (*m_ptr
== 'e' || *m_ptr
== 'E')) { // [eE]
522 if (m_ptr
< m_end
&& (*m_ptr
== '-' || *m_ptr
== '+'))
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");
532 while (m_ptr
< m_end
&& isASCIIDigit(*m_ptr
))
536 token
.type
= TokNumber
;
539 token
.numberToken
= parseDouble(token
.start
, token
.end
- token
.start
, parsedLength
);
543 template <typename CharType
>
544 JSValue LiteralParser
<CharType
>::parse(ParserState initialState
)
546 ParserState state
= initialState
;
547 MarkedArgumentBuffer objectStack
;
549 Vector
<ParserState
, 16, UnsafeVectorOverflow
> stateStack
;
550 Vector
<Identifier
, 16, UnsafeVectorOverflow
> identifierStack
;
554 case StartParseArray
: {
555 JSArray
* array
= constructEmptyArray(m_exec
, 0);
556 objectStack
.append(array
);
558 doParseArrayStartExpression
:
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");
568 lastValue
= objectStack
.last();
569 objectStack
.removeLast();
573 stateStack
.append(DoParseArrayEndExpression
);
574 goto startParseExpression
;
576 case DoParseArrayEndExpression
: {
577 JSArray
* array
= asArray(objectStack
.last());
578 array
->putDirectIndex(m_exec
, array
->length(), lastValue
);
580 if (m_lexer
.currentToken().type
== TokComma
)
581 goto doParseArrayStartExpression
;
583 if (m_lexer
.currentToken().type
!= TokRBracket
) {
584 m_parseErrorMessage
= ASCIILiteral("Expected ']'");
589 lastValue
= objectStack
.last();
590 objectStack
.removeLast();
594 case StartParseObject
: {
595 JSObject
* object
= constructEmptyObject(m_exec
);
596 objectStack
.append(object
);
598 TokenType type
= m_lexer
.next();
599 if (type
== TokString
|| (m_mode
!= StrictJSON
&& type
== TokIdentifier
)) {
600 LiteralParserToken
<CharType
> identifierToken
= m_lexer
.currentToken();
603 if (m_lexer
.next() != TokColon
) {
604 m_parseErrorMessage
= ASCIILiteral("Expected ':' before value in object property definition");
609 if (identifierToken
.stringIs8Bit
)
610 identifierStack
.append(makeIdentifier(identifierToken
.stringToken8
, identifierToken
.stringLength
));
612 identifierStack
.append(makeIdentifier(identifierToken
.stringToken16
, identifierToken
.stringLength
));
613 stateStack
.append(DoParseObjectEndExpression
);
614 goto startParseExpression
;
616 if (type
!= TokRBrace
) {
617 m_parseErrorMessage
= ASCIILiteral("Expected '}'");
621 lastValue
= objectStack
.last();
622 objectStack
.removeLast();
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");
632 LiteralParserToken
<CharType
> identifierToken
= m_lexer
.currentToken();
635 if (m_lexer
.next() != TokColon
) {
636 m_parseErrorMessage
= ASCIILiteral("Expected ':'");
641 if (identifierToken
.stringIs8Bit
)
642 identifierStack
.append(makeIdentifier(identifierToken
.stringToken8
, identifierToken
.stringLength
));
644 identifierStack
.append(makeIdentifier(identifierToken
.stringToken16
, identifierToken
.stringLength
));
645 stateStack
.append(DoParseObjectEndExpression
);
646 goto startParseExpression
;
648 case DoParseObjectEndExpression
:
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
);
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 '}'");
665 lastValue
= objectStack
.last();
666 objectStack
.removeLast();
669 startParseExpression
:
670 case StartParseExpression
: {
671 switch (m_lexer
.currentToken().type
) {
673 goto startParseArray
;
675 goto startParseObject
;
677 LiteralParserToken
<CharType
> stringToken
= m_lexer
.currentToken();
679 if (stringToken
.stringIs8Bit
)
680 lastValue
= jsString(m_exec
, makeIdentifier(stringToken
.stringToken8
, stringToken
.stringLength
).string());
682 lastValue
= jsString(m_exec
, makeIdentifier(stringToken
.stringToken16
, stringToken
.stringLength
).string());
686 LiteralParserToken
<CharType
> numberToken
= m_lexer
.currentToken();
688 lastValue
= jsNumber(numberToken
.numberToken
);
693 lastValue
= jsNull();
698 lastValue
= jsBoolean(true);
703 lastValue
= jsBoolean(false);
706 m_parseErrorMessage
= ASCIILiteral("Unexpected token ']'");
709 m_parseErrorMessage
= ASCIILiteral("Unexpected token '}'");
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();
716 m_parseErrorMessage
= String::format("Unexpected identifier \"%s\"", String(m_lexer
.currentToken().stringToken16
, m_lexer
.currentToken().stringLength
).ascii().data()).impl();
720 m_parseErrorMessage
= ASCIILiteral("Unexpected token ':'");
723 m_parseErrorMessage
= ASCIILiteral("Unexpected token '('");
726 m_parseErrorMessage
= ASCIILiteral("Unexpected token ')'");
729 m_parseErrorMessage
= ASCIILiteral("Unexpected token ','");
732 m_parseErrorMessage
= ASCIILiteral("Unexpected token '.'");
735 m_parseErrorMessage
= ASCIILiteral("Unexpected token '='");
738 m_parseErrorMessage
= ASCIILiteral("Unexpected token ';'");
741 m_parseErrorMessage
= ASCIILiteral("Unexpected EOF");
746 m_parseErrorMessage
= ASCIILiteral("Could not parse value expression");
751 case StartParseStatement
: {
752 switch (m_lexer
.currentToken().type
) {
756 goto startParseExpression
;
760 stateStack
.append(StartParseStatementEndStatement
);
761 goto startParseExpression
;
764 m_parseErrorMessage
= ASCIILiteral("Unexpected token ']'");
767 m_parseErrorMessage
= ASCIILiteral("Unexpected token '{'");
770 m_parseErrorMessage
= ASCIILiteral("Unexpected token '}'");
773 m_parseErrorMessage
= ASCIILiteral("Unexpected identifier");
776 m_parseErrorMessage
= ASCIILiteral("Unexpected token ':'");
779 m_parseErrorMessage
= ASCIILiteral("Unexpected token ')'");
782 m_parseErrorMessage
= ASCIILiteral("Unexpected token ','");
785 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'true'");
788 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'false'");
791 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'null'");
794 m_parseErrorMessage
= ASCIILiteral("Unexpected EOF");
797 m_parseErrorMessage
= ASCIILiteral("Unexpected token '.'");
800 m_parseErrorMessage
= ASCIILiteral("Unexpected token '='");
803 m_parseErrorMessage
= ASCIILiteral("Unexpected token ';'");
807 m_parseErrorMessage
= ASCIILiteral("Could not parse statement");
811 case StartParseStatementEndStatement
: {
812 ASSERT(stateStack
.isEmpty());
813 if (m_lexer
.currentToken().type
!= TokRParen
)
815 if (m_lexer
.next() == TokEnd
)
817 m_parseErrorMessage
= ASCIILiteral("Unexpected content at end of JSON literal");
821 RELEASE_ASSERT_NOT_REACHED();
823 if (stateStack
.isEmpty())
825 state
= stateStack
.last();
826 stateStack
.removeLast();
831 // Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
832 template class LiteralParser
<LChar
>;
833 template class LiteralParser
<UChar
>;