1/*
2 * Copyright (C) 2010 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 <yarr/YarrSyntaxChecker.h>
30
31namespace JSC {
32class SyntaxChecker {
33public:
34    struct BinaryExprContext {
35        BinaryExprContext(SyntaxChecker& context)
36            : m_context(&context)
37        {
38            m_context->m_topBinaryExprs.append(m_context->m_topBinaryExpr);
39            m_context->m_topBinaryExpr = 0;
40        }
41        ~BinaryExprContext()
42        {
43            m_context->m_topBinaryExpr = m_context->m_topBinaryExprs.last();
44            m_context->m_topBinaryExprs.removeLast();
45        }
46    private:
47        SyntaxChecker* m_context;
48    };
49    struct UnaryExprContext {
50        UnaryExprContext(SyntaxChecker& context)
51            : m_context(&context)
52        {
53            m_context->m_topUnaryTokens.append(m_context->m_topUnaryToken);
54            m_context->m_topUnaryToken = 0;
55        }
56        ~UnaryExprContext()
57        {
58            m_context->m_topUnaryToken = m_context->m_topUnaryTokens.last();
59            m_context->m_topUnaryTokens.removeLast();
60        }
61    private:
62        SyntaxChecker* m_context;
63    };
64
65    SyntaxChecker(JSGlobalData* , Lexer*)
66    {
67    }
68
69    typedef SyntaxChecker FunctionBodyBuilder;
70    enum { NoneExpr = 0,
71        ResolveEvalExpr, ResolveExpr, NumberExpr, StringExpr,
72        ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
73        FunctionExpr, BracketExpr, DotExpr, CallExpr,
74        NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
75        ConditionalExpr, AssignmentExpr, TypeofExpr,
76        DeleteExpr, ArrayLiteralExpr };
77    typedef int ExpressionType;
78
79    typedef ExpressionType Expression;
80    typedef int SourceElements;
81    typedef int Arguments;
82    typedef ExpressionType Comma;
83    struct Property {
84        ALWAYS_INLINE Property(void* = 0)
85            : type((PropertyNode::Type)0)
86        {
87        }
88        ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
89        : name(ident)
90        , type(ty)
91        {
92        }
93        ALWAYS_INLINE Property(PropertyNode::Type ty)
94            : name(0)
95            , type(ty)
96        {
97        }
98        ALWAYS_INLINE bool operator!() { return !type; }
99        const Identifier* name;
100        PropertyNode::Type type;
101    };
102    typedef int PropertyList;
103    typedef int ElementList;
104    typedef int ArgumentsList;
105    typedef int FormalParameterList;
106    typedef int FunctionBody;
107    typedef int Statement;
108    typedef int ClauseList;
109    typedef int Clause;
110    typedef int ConstDeclList;
111    typedef int BinaryOperand;
112
113    static const bool CreatesAST = false;
114    static const bool NeedsFreeVariableInfo = false;
115    static const bool CanUseFunctionCache = true;
116
117    int createSourceElements() { return 1; }
118    ExpressionType makeFunctionCallNode(int, int, int, int, int) { return CallExpr; }
119    void appendToComma(ExpressionType& base, ExpressionType right) { base = right; }
120    ExpressionType createCommaExpr(ExpressionType, ExpressionType right) { return right; }
121    ExpressionType makeAssignNode(ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; }
122    ExpressionType makePrefixNode(ExpressionType, Operator, int, int, int) { return PreExpr; }
123    ExpressionType makePostfixNode(ExpressionType, Operator, int, int, int) { return PostExpr; }
124    ExpressionType makeTypeOfNode(ExpressionType) { return TypeofExpr; }
125    ExpressionType makeDeleteNode(ExpressionType, int, int, int) { return DeleteExpr; }
126    ExpressionType makeNegateNode(ExpressionType) { return UnaryExpr; }
127    ExpressionType makeBitwiseNotNode(ExpressionType) { return UnaryExpr; }
128    ExpressionType createLogicalNot(ExpressionType) { return UnaryExpr; }
129    ExpressionType createUnaryPlus(ExpressionType) { return UnaryExpr; }
130    ExpressionType createVoid(ExpressionType) { return UnaryExpr; }
131    ExpressionType thisExpr() { return ThisExpr; }
132    ExpressionType createResolve(const Identifier*, int) { return ResolveExpr; }
133    ExpressionType createObjectLiteral() { return ObjectLiteralExpr; }
134    ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; }
135    ExpressionType createArray(int) { return ArrayLiteralExpr; }
136    ExpressionType createArray(int, int) { return ArrayLiteralExpr; }
137    ExpressionType createNumberExpr(double) { return NumberExpr; }
138    ExpressionType createString(const Identifier*) { return StringExpr; }
139    ExpressionType createBoolean(bool) { return BoolExpr; }
140    ExpressionType createNull() { return NullExpr; }
141    ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
142    ExpressionType createDotAccess(ExpressionType, const Identifier&, int, int, int) { return DotExpr; }
143    ExpressionType createRegExp(const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; }
144    ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; }
145    ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; }
146    ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
147    ExpressionType createAssignResolve(const Identifier&, ExpressionType, bool, int, int, int) { return AssignmentExpr; }
148    ExpressionType createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return FunctionExpr; }
149    int createFunctionBody(bool) { return 1; }
150    int createArguments() { return 1; }
151    int createArguments(int) { return 1; }
152    int createArgumentsList(int) { return 1; }
153    int createArgumentsList(int, int) { return 1; }
154    template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
155    {
156        ASSERT(name);
157        if (!complete)
158            return Property(type);
159        return Property(name, type);
160    }
161    template <bool complete> Property createProperty(JSGlobalData* globalData, double name, int, PropertyNode::Type type)
162    {
163        if (!complete)
164            return Property(type);
165        return Property(&globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name), type);
166    }
167    int createPropertyList(Property) { return 1; }
168    int createPropertyList(Property, int) { return 1; }
169    int createElementList(int, int) { return 1; }
170    int createElementList(int, int, int) { return 1; }
171    int createFormalParameterList(const Identifier&) { return 1; }
172    int createFormalParameterList(int, const Identifier&) { return 1; }
173    int createClause(int, int) { return 1; }
174    int createClauseList(int) { return 1; }
175    int createClauseList(int, int) { return 1; }
176    void setUsesArguments(int) { }
177    int createFuncDeclStatement(const Identifier*, int, int, int, int, int, int) { return 1; }
178    int createBlockStatement(int, int, int) { return 1; }
179    int createExprStatement(int, int, int) { return 1; }
180    int createIfStatement(int, int, int, int) { return 1; }
181    int createIfStatement(int, int, int, int, int) { return 1; }
182    int createForLoop(int, int, int, int, bool, int, int) { return 1; }
183    int createForInLoop(const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; }
184    int createForInLoop(int, int, int, int, int, int, int, int) { return 1; }
185    int createEmptyStatement() { return 1; }
186    int createVarStatement(int, int, int) { return 1; }
187    int createReturnStatement(int, int, int, int, int) { return 1; }
188    int createBreakStatement(int, int, int, int) { return 1; }
189    int createBreakStatement(const Identifier*, int, int, int, int) { return 1; }
190    int createContinueStatement(int, int, int, int) { return 1; }
191    int createContinueStatement(const Identifier*, int, int, int, int) { return 1; }
192    int createTryStatement(int, const Identifier*, bool, int, int, int, int) { return 1; }
193    int createSwitchStatement(int, int, int, int, int, int) { return 1; }
194    int createWhileStatement(int, int, int, int) { return 1; }
195    int createWithStatement(int, int, int, int, int, int) { return 1; }
196    int createDoWhileStatement(int, int, int, int) { return 1; }
197    int createLabelStatement(const Identifier*, int, int, int) { return 1; }
198    int createThrowStatement(int, int, int, int, int) { return 1; }
199    int createDebugger(int, int) { return 1; }
200    int createConstStatement(int, int, int) { return 1; }
201    int appendConstDecl(int, const Identifier*, int) { return 1; }
202    template <bool strict> Property createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int)
203    {
204        ASSERT(name);
205        if (!strict)
206            return Property(type);
207        return Property(name, type);
208    }
209
210    void appendStatement(int, int) { }
211    void addVar(const Identifier*, bool) { }
212    int combineCommaNodes(int, int) { return 1; }
213    int evalCount() const { return 0; }
214    void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
215    {
216        if (!m_topBinaryExpr)
217            m_topBinaryExpr = expr;
218        else
219            m_topBinaryExpr = BinaryExpr;
220        operandStackDepth++;
221    }
222
223    // Logic to handle datastructures used during parsing of binary expressions
224    void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
225    bool operatorStackHasHigherPrecedence(int&, int) { return true; }
226    BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
227    void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
228    void appendBinaryOperation(int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
229    void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
230    int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; }
231
232    void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; }
233    int unaryTokenStackLastType(int&) { return m_topUnaryToken; }
234    int unaryTokenStackLastStart(int&) { return 0; }
235    void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; }
236
237    void assignmentStackAppend(int, int, int, int, int, Operator) { }
238    int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; }
239    const Identifier& getName(const Property& property) const { ASSERT(property.name); return *property.name; }
240    PropertyNode::Type getType(const Property& property) const { return property.type; }
241    bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; }
242
243private:
244    int m_topBinaryExpr;
245    int m_topUnaryToken;
246    Vector<int, 8> m_topBinaryExprs;
247    Vector<int, 8> m_topUnaryTokens;
248};
249
250}
251
252#endif
253