fac97571c885fd7464f2ea84e681d75f43756768
[WebKit-https.git] / Source / JavaScriptCore / runtime / LiteralParser.h
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 #ifndef LiteralParser_h
27 #define LiteralParser_h
28
29 #include "Identifier.h"
30 #include "JSCJSValue.h"
31 #include "JSGlobalObjectFunctions.h"
32 #include <wtf/text/WTFString.h>
33
34 namespace JSC {
35
36 typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
37
38 enum JSONPPathEntryType {
39     JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
40     JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
41     JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON
42     JSONPPathEntryTypeCall // <prior entries>(JSON)
43 };
44
45 enum ParserState { StartParseObject, StartParseArray, StartParseExpression, 
46                    StartParseStatement, StartParseStatementEndStatement, 
47                    DoParseObjectStartExpression, DoParseObjectEndExpression,
48                    DoParseArrayStartExpression, DoParseArrayEndExpression };
49 enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 
50                  TokString, TokIdentifier, TokNumber, TokColon, 
51                  TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
52                  TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
53     
54 struct JSONPPathEntry {
55     JSONPPathEntryType m_type;
56     Identifier m_pathEntryName;
57     int m_pathIndex;
58 };
59
60 struct JSONPData {
61     Vector<JSONPPathEntry> m_path;
62     Strong<Unknown> m_value;
63 };
64
65 template <typename CharType>
66 struct LiteralParserToken {
67     TokenType type;
68     const CharType* start;
69     const CharType* end;
70     String stringBuffer;
71     union {
72         double numberToken;
73         struct {
74             union {
75                 const LChar* stringToken8;
76                 const UChar* stringToken16;
77             };
78             unsigned stringIs8Bit : 1;
79             unsigned stringLength : 31;
80         };
81     };
82 };
83
84 template <typename CharType>
85 ALWAYS_INLINE void setParserTokenString(LiteralParserToken<CharType>&, const CharType* string);
86
87 template <typename CharType>
88 class LiteralParser {
89 public:
90     LiteralParser(ExecState* exec, const CharType* characters, unsigned length, ParserMode mode)
91         : m_exec(exec)
92         , m_lexer(characters, length, mode)
93         , m_mode(mode)
94     {
95     }
96     
97     String getErrorMessage()
98     { 
99         if (!m_lexer.getErrorMessage().isEmpty())
100             return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl();
101         if (!m_parseErrorMessage.isEmpty())
102             return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl();
103         return ASCIILiteral("JSON Parse error: Unable to parse JSON string");
104     }
105     
106     JSValue tryLiteralParse()
107     {
108         m_lexer.next();
109         JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
110         if (m_lexer.currentToken().type == TokSemi)
111             m_lexer.next();
112         if (m_lexer.currentToken().type != TokEnd)
113             return JSValue();
114         return result;
115     }
116     
117     bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo);
118
119 private:
120     class Lexer {
121     public:
122         Lexer(const CharType* characters, unsigned length, ParserMode mode)
123             : m_mode(mode)
124             , m_ptr(characters)
125             , m_end(characters + length)
126         {
127         }
128         
129         TokenType next();
130         
131         const LiteralParserToken<CharType>& currentToken()
132         {
133             return m_currentToken;
134         }
135         
136         String getErrorMessage() { return m_lexErrorMessage; }
137         
138     private:
139         String m_lexErrorMessage;
140         template <ParserMode mode> TokenType lex(LiteralParserToken<CharType>&);
141         ALWAYS_INLINE TokenType lexIdentifier(LiteralParserToken<CharType>&);
142         template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken<CharType>&);
143         ALWAYS_INLINE TokenType lexNumber(LiteralParserToken<CharType>&);
144         LiteralParserToken<CharType> m_currentToken;
145         ParserMode m_mode;
146         const CharType* m_ptr;
147         const CharType* m_end;
148     };
149     
150     class StackGuard;
151     JSValue parse(ParserState);
152
153     ExecState* m_exec;
154     typename LiteralParser<CharType>::Lexer m_lexer;
155     ParserMode m_mode;
156     String m_parseErrorMessage;
157     static unsigned const MaximumCachableCharacter = 128;
158     FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
159     FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
160     ALWAYS_INLINE const Identifier makeIdentifier(const LChar* characters, size_t length);
161     ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
162     };
163
164 }
165
166 #endif