1/*
2 * Copyright (C) 2010, 2013 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef SyntaxChecker_h
27#define SyntaxChecker_h
28
29#include "Lexer.h"
30#include "YarrSyntaxChecker.h"
31
32namespace JSC {
33
34class SyntaxChecker {
35public:
36    struct BinaryExprContext {
37        BinaryExprContext(SyntaxChecker& context)
38            : m_context(&context)
39        {
40            m_context->m_topBinaryExprs.append(m_context->m_topBinaryExpr);
41            m_context->m_topBinaryExpr = 0;
42        }
43        ~BinaryExprContext()
44        {
45            m_context->m_topBinaryExpr = m_context->m_topBinaryExprs.last();
46            m_context->m_topBinaryExprs.removeLast();
47        }
48    private:
49        SyntaxChecker* m_context;
50    };
51    struct UnaryExprContext {
52        UnaryExprContext(SyntaxChecker& context)
53            : m_context(&context)
54        {
55            m_context->m_topUnaryTokens.append(m_context->m_topUnaryToken);
56            m_context->m_topUnaryToken = 0;
57        }
58        ~UnaryExprContext()
59        {
60            m_context->m_topUnaryToken = m_context->m_topUnaryTokens.last();
61            m_context->m_topUnaryTokens.removeLast();
62        }
63    private:
64        SyntaxChecker* m_context;
65    };
66
67    SyntaxChecker(VM* , void*)
68    {
69    }
70
71    typedef SyntaxChecker FunctionBodyBuilder;
72    enum { NoneExpr = 0,
73        ResolveEvalExpr, ResolveExpr, NumberExpr, StringExpr,
74        ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
75        FunctionExpr, BracketExpr, DotExpr, CallExpr,
76        NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
77        ConditionalExpr, AssignmentExpr, TypeofExpr,
78        DeleteExpr, ArrayLiteralExpr, BindingDeconstruction,
79        ArrayDeconstruction, ObjectDeconstruction, SourceElementsResult,
80        FunctionBodyResult, SpreadExpr, ArgumentsResult,
81        PropertyListResult, ArgumentsListResult, ElementsListResult,
82        StatementResult, FormalParameterListResult, ClauseResult,
83        ClauseListResult, CommaExpr, DeconstructingAssignment
84    };
85    typedef int ExpressionType;
86
87    typedef ExpressionType Expression;
88    typedef int SourceElements;
89    typedef int Arguments;
90    typedef ExpressionType Comma;
91    struct Property {
92        ALWAYS_INLINE Property(void* = 0)
93            : type((PropertyNode::Type)0)
94        {
95        }
96        ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
97            : name(ident)
98            , type(ty)
99        {
100        }
101        ALWAYS_INLINE Property(PropertyNode::Type ty)
102            : name(0)
103            , type(ty)
104        {
105        }
106        ALWAYS_INLINE bool operator!() { return !type; }
107        const Identifier* name;
108        PropertyNode::Type type;
109    };
110    typedef int PropertyList;
111    typedef int ElementList;
112    typedef int ArgumentsList;
113    typedef int FormalParameterList;
114    typedef int FunctionBody;
115    typedef int Statement;
116    typedef int ClauseList;
117    typedef int Clause;
118    typedef int ConstDeclList;
119    typedef int BinaryOperand;
120    typedef int DeconstructionPattern;
121    typedef DeconstructionPattern ArrayPattern;
122    typedef DeconstructionPattern ObjectPattern;
123
124    static const bool CreatesAST = false;
125    static const bool NeedsFreeVariableInfo = false;
126    static const bool CanUseFunctionCache = true;
127    static const unsigned DontBuildKeywords = LexexFlagsDontBuildKeywords;
128    static const unsigned DontBuildStrings = LexerFlagsDontBuildStrings;
129
130    int createSourceElements() { return SourceElementsResult; }
131    ExpressionType makeFunctionCallNode(const JSTokenLocation&, int, int, int, int, int) { return CallExpr; }
132    void appendToComma(ExpressionType& base, ExpressionType right) { base = right; }
133    ExpressionType createCommaExpr(const JSTokenLocation&, ExpressionType, ExpressionType right) { return right; }
134    ExpressionType makeAssignNode(const JSTokenLocation&, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; }
135    ExpressionType makePrefixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PreExpr; }
136    ExpressionType makePostfixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PostExpr; }
137    ExpressionType makeTypeOfNode(const JSTokenLocation&, ExpressionType) { return TypeofExpr; }
138    ExpressionType makeDeleteNode(const JSTokenLocation&, ExpressionType, int, int, int) { return DeleteExpr; }
139    ExpressionType makeNegateNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
140    ExpressionType makeBitwiseNotNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
141    ExpressionType createLogicalNot(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
142    ExpressionType createUnaryPlus(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
143    ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
144    ExpressionType thisExpr(const JSTokenLocation&) { return ThisExpr; }
145    ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int) { return ResolveExpr; }
146    ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; }
147    ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; }
148    ExpressionType createArray(const JSTokenLocation&, int) { return ArrayLiteralExpr; }
149    ExpressionType createArray(const JSTokenLocation&, int, int) { return ArrayLiteralExpr; }
150    ExpressionType createNumberExpr(const JSTokenLocation&, double) { return NumberExpr; }
151    ExpressionType createString(const JSTokenLocation&, const Identifier*) { return StringExpr; }
152    ExpressionType createBoolean(const JSTokenLocation&, bool) { return BoolExpr; }
153    ExpressionType createNull(const JSTokenLocation&) { return NullExpr; }
154    ExpressionType createBracketAccess(const JSTokenLocation&, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
155    ExpressionType createDotAccess(const JSTokenLocation&, ExpressionType, const Identifier*, int, int, int) { return DotExpr; }
156    ExpressionType createRegExp(const JSTokenLocation&, const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.string()) ? 0 : RegExpExpr; }
157    ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int, int, int) { return NewExpr; }
158    ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int) { return NewExpr; }
159    ExpressionType createConditionalExpr(const JSTokenLocation&, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
160    ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; }
161    ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return FunctionExpr; }
162    int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool) { return FunctionBodyResult; }
163    void setFunctionNameStart(int, int) { }
164    int createArguments() { return ArgumentsResult; }
165    int createArguments(int) { return ArgumentsResult; }
166    ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; }
167    int createArgumentsList(const JSTokenLocation&, int) { return ArgumentsListResult; }
168    int createArgumentsList(const JSTokenLocation&, int, int) { return ArgumentsListResult; }
169    Property createProperty(const Identifier* name, int, PropertyNode::Type type, bool complete)
170    {
171        if (!complete)
172            return Property(type);
173        ASSERT(name);
174        return Property(name, type);
175    }
176    Property createProperty(VM* vm, double name, int, PropertyNode::Type type, bool complete)
177    {
178        if (!complete)
179            return Property(type);
180        return Property(&vm->parserArena->identifierArena().makeNumericIdentifier(vm, name), type);
181    }
182    Property createProperty(VM*, ExpressionNode*, int, PropertyNode::Type type, bool)
183    {
184        return Property(type);
185    }
186    int createPropertyList(const JSTokenLocation&, Property) { return PropertyListResult; }
187    int createPropertyList(const JSTokenLocation&, Property, int) { return PropertyListResult; }
188    int createElementList(int, int) { return ElementsListResult; }
189    int createElementList(int, int, int) { return ElementsListResult; }
190    int createFormalParameterList(DeconstructionPattern) { return FormalParameterListResult; }
191    int createFormalParameterList(int, DeconstructionPattern) { return FormalParameterListResult; }
192    int createClause(int, int) { return ClauseResult; }
193    int createClauseList(int) { return ClauseListResult; }
194    int createClauseList(int, int) { return ClauseListResult; }
195    void setUsesArguments(int) { }
196    int createFuncDeclStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return StatementResult; }
197    int createBlockStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
198    int createExprStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
199    int createIfStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
200    int createIfStatement(const JSTokenLocation&, int, int, int, int, int) { return StatementResult; }
201    int createForLoop(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
202    int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return StatementResult; }
203    int createForOfLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return StatementResult; }
204    int createEmptyStatement(const JSTokenLocation&) { return StatementResult; }
205    int createVarStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
206    int createReturnStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
207    int createBreakStatement(const JSTokenLocation&, int, int) { return StatementResult; }
208    int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
209    int createContinueStatement(const JSTokenLocation&, int, int) { return StatementResult; }
210    int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
211    int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int) { return StatementResult; }
212    int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
213    int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
214    int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
215    int createDoWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
216    int createLabelStatement(const JSTokenLocation&, const Identifier*, int, int, int) { return StatementResult; }
217    int createThrowStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
218    int createDebugger(const JSTokenLocation&, int, int) { return StatementResult; }
219    int createConstStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
220    int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return StatementResult; }
221    Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, int, int, int, int, int, int, int)
222    {
223        ASSERT(name);
224        if (!strict)
225            return Property(type);
226        return Property(name, type);
227    }
228    Property createGetterOrSetterProperty(VM* vm, const JSTokenLocation&, PropertyNode::Type type, bool strict, double name, int, int, int, int, int, int, int)
229    {
230        if (!strict)
231            return Property(type);
232        return Property(&vm->parserArena->identifierArena().makeNumericIdentifier(vm, name), type);
233    }
234
235    void appendStatement(int, int) { }
236    void addVar(const Identifier*, bool) { }
237    int combineCommaNodes(const JSTokenLocation&, int, int) { return CommaExpr; }
238    int evalCount() const { return 0; }
239    void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
240    {
241        if (!m_topBinaryExpr)
242            m_topBinaryExpr = expr;
243        else
244            m_topBinaryExpr = BinaryExpr;
245        operandStackDepth++;
246    }
247
248    // Logic to handle datastructures used during parsing of binary expressions
249    void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
250    bool operatorStackHasHigherPrecedence(int&, int) { return true; }
251    BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
252    void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
253    void appendBinaryOperation(const JSTokenLocation&, int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
254    void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
255    int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; }
256
257    void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; }
258    int unaryTokenStackLastType(int&) { return m_topUnaryToken; }
259    JSTextPosition unaryTokenStackLastStart(int&) { return JSTextPosition(0, 0, 0); }
260    void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; }
261
262    void assignmentStackAppend(int, int, int, int, int, Operator) { }
263    int createAssignment(const JSTokenLocation&, int, int, int, int, int) { RELEASE_ASSERT_NOT_REACHED(); return AssignmentExpr; }
264    const Identifier* getName(const Property& property) const { ASSERT(property.name); return property.name; }
265    PropertyNode::Type getType(const Property& property) const { return property.type; }
266    bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; }
267    ExpressionType createDeconstructingAssignment(const JSTokenLocation&, int, ExpressionType)
268    {
269        return DeconstructingAssignment;
270    }
271
272    ArrayPattern createArrayPattern(const JSTokenLocation&)
273    {
274        return ArrayDeconstruction;
275    }
276    void appendArrayPatternSkipEntry(ArrayPattern, const JSTokenLocation&)
277    {
278    }
279    void appendArrayPatternEntry(ArrayPattern, const JSTokenLocation&, DeconstructionPattern)
280    {
281    }
282    ObjectPattern createObjectPattern(const JSTokenLocation&)
283    {
284        return ObjectDeconstruction;
285    }
286    void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, bool, const Identifier&, DeconstructionPattern)
287    {
288    }
289    DeconstructionPattern createBindingLocation(const JSTokenLocation&, const Identifier&, const JSTextPosition&, const JSTextPosition&)
290    {
291        return BindingDeconstruction;
292    }
293
294    bool isBindingNode(DeconstructionPattern pattern)
295    {
296        return pattern == BindingDeconstruction;
297    }
298
299private:
300    int m_topBinaryExpr;
301    int m_topUnaryToken;
302    Vector<int, 8> m_topBinaryExprs;
303    Vector<int, 8> m_topUnaryTokens;
304};
305
306}
307
308#endif
309