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