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::fromString(&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::fromString(&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::fromString(&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::fromString(&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::fromString(&m_exec
->vm(), characters
, length
);
141 if (!m_shortIdentifiers
[characters
[0]].isNull())
142 return m_shortIdentifiers
[characters
[0]];
143 m_shortIdentifiers
[characters
[0]] = Identifier::fromString(&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::fromString(&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::fromString(&m_exec
->vm(), characters
, length
);
161 if (!m_shortIdentifiers
[characters
[0]].isNull())
162 return m_shortIdentifiers
[characters
[0]];
163 m_shortIdentifiers
[characters
[0]] = Identifier::fromString(&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::fromString(&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
);
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());
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
);
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
;
551 HashSet
<JSObject
*> visitedUnderscoreProto
;
555 case StartParseArray
: {
556 JSArray
* array
= constructEmptyArray(m_exec
, 0);
557 objectStack
.append(array
);
559 doParseArrayStartExpression
:
561 case DoParseArrayStartExpression
: {
562 TokenType lastToken
= m_lexer
.currentToken().type
;
563 if (m_lexer
.next() == TokRBracket
) {
564 if (lastToken
== TokComma
) {
565 m_parseErrorMessage
= ASCIILiteral("Unexpected comma at the end of array expression");
569 lastValue
= objectStack
.last();
570 objectStack
.removeLast();
574 stateStack
.append(DoParseArrayEndExpression
);
575 goto startParseExpression
;
577 case DoParseArrayEndExpression
: {
578 JSArray
* array
= asArray(objectStack
.last());
579 array
->putDirectIndex(m_exec
, array
->length(), lastValue
);
581 if (m_lexer
.currentToken().type
== TokComma
)
582 goto doParseArrayStartExpression
;
584 if (m_lexer
.currentToken().type
!= TokRBracket
) {
585 m_parseErrorMessage
= ASCIILiteral("Expected ']'");
590 lastValue
= objectStack
.last();
591 objectStack
.removeLast();
595 case StartParseObject
: {
596 JSObject
* object
= constructEmptyObject(m_exec
);
597 objectStack
.append(object
);
599 TokenType type
= m_lexer
.next();
600 if (type
== TokString
|| (m_mode
!= StrictJSON
&& type
== TokIdentifier
)) {
601 LiteralParserToken
<CharType
> identifierToken
= m_lexer
.currentToken();
604 if (m_lexer
.next() != TokColon
) {
605 m_parseErrorMessage
= ASCIILiteral("Expected ':' before value in object property definition");
610 if (identifierToken
.stringIs8Bit
)
611 identifierStack
.append(makeIdentifier(identifierToken
.stringToken8
, identifierToken
.stringLength
));
613 identifierStack
.append(makeIdentifier(identifierToken
.stringToken16
, identifierToken
.stringLength
));
614 stateStack
.append(DoParseObjectEndExpression
);
615 goto startParseExpression
;
617 if (type
!= TokRBrace
) {
618 m_parseErrorMessage
= ASCIILiteral("Expected '}'");
622 lastValue
= objectStack
.last();
623 objectStack
.removeLast();
626 doParseObjectStartExpression
:
627 case DoParseObjectStartExpression
: {
628 TokenType type
= m_lexer
.next();
629 if (type
!= TokString
&& (m_mode
== StrictJSON
|| type
!= TokIdentifier
)) {
630 m_parseErrorMessage
= ASCIILiteral("Property name must be a string literal");
633 LiteralParserToken
<CharType
> identifierToken
= m_lexer
.currentToken();
636 if (m_lexer
.next() != TokColon
) {
637 m_parseErrorMessage
= ASCIILiteral("Expected ':'");
642 if (identifierToken
.stringIs8Bit
)
643 identifierStack
.append(makeIdentifier(identifierToken
.stringToken8
, identifierToken
.stringLength
));
645 identifierStack
.append(makeIdentifier(identifierToken
.stringToken16
, identifierToken
.stringLength
));
646 stateStack
.append(DoParseObjectEndExpression
);
647 goto startParseExpression
;
649 case DoParseObjectEndExpression
:
651 JSObject
* object
= asObject(objectStack
.last());
652 PropertyName ident
= identifierStack
.last();
653 if (m_mode
!= StrictJSON
&& ident
== m_exec
->vm().propertyNames
->underscoreProto
) {
654 if (!visitedUnderscoreProto
.add(object
).isNewEntry
) {
655 m_parseErrorMessage
= ASCIILiteral("Attempted to redefine __proto__ property");
658 CodeBlock
* codeBlock
= m_exec
->codeBlock();
659 PutPropertySlot
slot(object
, codeBlock
? codeBlock
->isStrictMode() : false);
660 objectStack
.last().put(m_exec
, ident
, lastValue
, slot
);
662 if (Optional
<uint32_t> index
= parseIndex(ident
))
663 object
->putDirectIndex(m_exec
, index
.value(), lastValue
);
665 object
->putDirect(m_exec
->vm(), ident
, lastValue
);
667 identifierStack
.removeLast();
668 if (m_lexer
.currentToken().type
== TokComma
)
669 goto doParseObjectStartExpression
;
670 if (m_lexer
.currentToken().type
!= TokRBrace
) {
671 m_parseErrorMessage
= ASCIILiteral("Expected '}'");
675 lastValue
= objectStack
.last();
676 objectStack
.removeLast();
679 startParseExpression
:
680 case StartParseExpression
: {
681 switch (m_lexer
.currentToken().type
) {
683 goto startParseArray
;
685 goto startParseObject
;
687 LiteralParserToken
<CharType
> stringToken
= m_lexer
.currentToken();
689 if (stringToken
.stringIs8Bit
)
690 lastValue
= jsString(m_exec
, makeIdentifier(stringToken
.stringToken8
, stringToken
.stringLength
).string());
692 lastValue
= jsString(m_exec
, makeIdentifier(stringToken
.stringToken16
, stringToken
.stringLength
).string());
696 LiteralParserToken
<CharType
> numberToken
= m_lexer
.currentToken();
698 lastValue
= jsNumber(numberToken
.numberToken
);
703 lastValue
= jsNull();
708 lastValue
= jsBoolean(true);
713 lastValue
= jsBoolean(false);
716 m_parseErrorMessage
= ASCIILiteral("Unexpected token ']'");
719 m_parseErrorMessage
= ASCIILiteral("Unexpected token '}'");
721 case TokIdentifier
: {
722 const LiteralParserToken
<CharType
>& token
= m_lexer
.currentToken();
723 if (token
.stringIs8Bit
)
724 m_parseErrorMessage
= String::format("Unexpected identifier \"%s\"", String(m_lexer
.currentToken().stringToken8
, m_lexer
.currentToken().stringLength
).ascii().data());
726 m_parseErrorMessage
= String::format("Unexpected identifier \"%s\"", String(m_lexer
.currentToken().stringToken16
, m_lexer
.currentToken().stringLength
).ascii().data());
730 m_parseErrorMessage
= ASCIILiteral("Unexpected token ':'");
733 m_parseErrorMessage
= ASCIILiteral("Unexpected token '('");
736 m_parseErrorMessage
= ASCIILiteral("Unexpected token ')'");
739 m_parseErrorMessage
= ASCIILiteral("Unexpected token ','");
742 m_parseErrorMessage
= ASCIILiteral("Unexpected token '.'");
745 m_parseErrorMessage
= ASCIILiteral("Unexpected token '='");
748 m_parseErrorMessage
= ASCIILiteral("Unexpected token ';'");
751 m_parseErrorMessage
= ASCIILiteral("Unexpected EOF");
756 m_parseErrorMessage
= ASCIILiteral("Could not parse value expression");
761 case StartParseStatement
: {
762 switch (m_lexer
.currentToken().type
) {
766 goto startParseExpression
;
770 stateStack
.append(StartParseStatementEndStatement
);
771 goto startParseExpression
;
774 m_parseErrorMessage
= ASCIILiteral("Unexpected token ']'");
777 m_parseErrorMessage
= ASCIILiteral("Unexpected token '{'");
780 m_parseErrorMessage
= ASCIILiteral("Unexpected token '}'");
783 m_parseErrorMessage
= ASCIILiteral("Unexpected identifier");
786 m_parseErrorMessage
= ASCIILiteral("Unexpected token ':'");
789 m_parseErrorMessage
= ASCIILiteral("Unexpected token ')'");
792 m_parseErrorMessage
= ASCIILiteral("Unexpected token ','");
795 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'true'");
798 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'false'");
801 m_parseErrorMessage
= ASCIILiteral("Unexpected token 'null'");
804 m_parseErrorMessage
= ASCIILiteral("Unexpected EOF");
807 m_parseErrorMessage
= ASCIILiteral("Unexpected token '.'");
810 m_parseErrorMessage
= ASCIILiteral("Unexpected token '='");
813 m_parseErrorMessage
= ASCIILiteral("Unexpected token ';'");
817 m_parseErrorMessage
= ASCIILiteral("Could not parse statement");
821 case StartParseStatementEndStatement
: {
822 ASSERT(stateStack
.isEmpty());
823 if (m_lexer
.currentToken().type
!= TokRParen
)
825 if (m_lexer
.next() == TokEnd
)
827 m_parseErrorMessage
= ASCIILiteral("Unexpected content at end of JSON literal");
831 RELEASE_ASSERT_NOT_REACHED();
833 if (stateStack
.isEmpty())
835 state
= stateStack
.last();
836 stateStack
.removeLast();
841 // Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
842 template class LiteralParser
<LChar
>;
843 template class LiteralParser
<UChar
>;