#ifndef _IV_AST_FACTORY_H_ #define _IV_AST_FACTORY_H_ #include #include "functor.h" #include "location.h" #include "ast.h" #include "alloc.h" #include "static_assert.h" #include "ustringpiece.h" namespace iv { namespace core { namespace ast { template class BasicAstFactory { public: typedef BasicAstFactory this_type; #define V(AST) typedef typename ast::AST AST; AST_NODE_LIST(V) #undef V #define V(XS) typedef typename ast::AstNode::XS XS; AST_LIST_LIST(V) #undef V #define V(S) typedef typename SpaceUString::type S; AST_STRING(V) #undef V BasicAstFactory() : empty_statement_instance_( new(static_cast(this))EmptyStatement()), debugger_statement_instance_( new(static_cast(this))DebuggerStatement()), this_instance_( new(static_cast(this))ThisLiteral()), null_instance_( new(static_cast(this))NullLiteral()), true_instance_( new(static_cast(this))TrueLiteral()), false_instance_( new(static_cast(this))FalseLiteral()) { typedef std::tr1::is_convertible is_convertible_to_this; typedef std::tr1::is_base_of is_base_of_factory; IV_STATIC_ASSERT(is_convertible_to_this::value || is_base_of_factory::value); } template Identifier* NewIdentifier(Token::Type token, const Range& range, std::size_t begin, std::size_t end) { return new (static_cast(this)) Identifier(range, static_cast(this)); } NumberLiteral* NewReducedNumberLiteral(const double& val) { return new (static_cast(this)) NumberLiteral(val); } NumberLiteral* NewNumberLiteral(const double& val, std::size_t begin, std::size_t end) { return new (static_cast(this)) NumberLiteral(val); } StringLiteral* NewStringLiteral(const std::vector& buffer, std::size_t begin, std::size_t end) { return new (static_cast(this)) StringLiteral(buffer, static_cast(this)); } Directivable* NewDirectivable(const std::vector& buffer, std::size_t begin, std::size_t end) { return new (static_cast(this)) Directivable(buffer, static_cast(this)); } RegExpLiteral* NewRegExpLiteral(const std::vector& content, const std::vector& flags, std::size_t begin, std::size_t end) { return new (static_cast(this)) RegExpLiteral(content, flags, static_cast(this)); } FunctionLiteral* NewFunctionLiteral(typename FunctionLiteral::DeclType type, Maybe name, Identifiers* params, Statements* body, Scope* scope, bool strict, std::size_t begin_block_position, std::size_t end_block_position, std::size_t begin, std::size_t end) { return new (static_cast(this)) FunctionLiteral(type, name, params, body, scope, strict, begin_block_position, end_block_position); } ArrayLiteral* NewArrayLiteral(MaybeExpressions* items, std::size_t begin, std::size_t end) { return new (static_cast(this)) ArrayLiteral(items); } ObjectLiteral* NewObjectLiteral(typename ObjectLiteral::Properties* properties, std::size_t begin, std::size_t end) { return new (static_cast(this)) ObjectLiteral(properties); } template T** NewPtr() { return new (static_cast(this)->New(sizeof(T*))) T*(NULL); // NOLINT } template typename SpaceVector::type* NewVector() { typedef typename SpaceVector::type Vector; return new (static_cast(this)->New(sizeof(Vector))) Vector(typename Vector::allocator_type(static_cast(this))); } Scope* NewScope(typename FunctionLiteral::DeclType type) { return new (static_cast(this)) Scope(static_cast(this), type == FunctionLiteral::GLOBAL); } NullLiteral* NewNullLiteral(std::size_t begin, std::size_t end) { return null_instance_; } ThisLiteral* NewThisLiteral(std::size_t begin, std::size_t end) { return this_instance_; } TrueLiteral* NewTrueLiteral(std::size_t begin, std::size_t end) { return true_instance_; } FalseLiteral* NewFalseLiteral(std::size_t begin, std::size_t end) { return false_instance_; } EmptyStatement* NewEmptyStatement(std::size_t begin, std::size_t end) { return empty_statement_instance_; } DebuggerStatement* NewDebuggerStatement(std::size_t begin, std::size_t end) { return debugger_statement_instance_; } // if you want begin / end position, // set position to FunctionLiteral in NewFunctionLiteral and use it FunctionStatement* NewFunctionStatement(FunctionLiteral* func) { return new (static_cast(this)) FunctionStatement(func); } // if you want begin / end position, // set position to FunctionLiteral in NewFunctionLiteral and use it FunctionDeclaration* NewFunctionDeclaration(FunctionLiteral* func) { return new (static_cast(this)) FunctionDeclaration(func); } Block* NewBlock(Statements* body, std::size_t begin, std::size_t end) { return new (static_cast(this)) Block(body); } VariableStatement* NewVariableStatement(Token::Type token, Declarations* decls, std::size_t begin, std::size_t end) { return new (static_cast(this)) VariableStatement(token, decls); } // if you want begin / end position, // set position to Identifier / Expression and use it Declaration* NewDeclaration(Identifier* name, Maybe expr) { return new (static_cast(this)) Declaration(name, expr); } // if you want end position, // set position to Statement and use it IfStatement* NewIfStatement(Expression* cond, Statement* then_statement, Maybe else_statement, std::size_t begin) { return new (static_cast(this)) IfStatement(cond, then_statement, else_statement); } DoWhileStatement* NewDoWhileStatement(Statement* body, Expression* cond, std::size_t begin, std::size_t end) { return new (static_cast(this)) DoWhileStatement(body, cond); } // if you want end position, // set position to Statement and use it WhileStatement* NewWhileStatement(Statement* body, Expression* cond, std::size_t begin) { return new (static_cast(this)) WhileStatement(body, cond); } // if you want end position, // set position to Statement and use it ForInStatement* NewForInStatement(Statement* body, Statement* each, Expression* enumerable, std::size_t begin) { return new (static_cast(this)) ForInStatement(body, each, enumerable); } // if you want end position, // set position to Statement and use it ForStatement* NewForStatement(Statement* body, Maybe init, Maybe cond, Maybe next, std::size_t begin) { return new (static_cast(this)) ForStatement(body, init, cond, next); } ExpressionStatement* NewExpressionStatement(Expression* expr, std::size_t end) { return new (static_cast(this)) ExpressionStatement(expr); } ContinueStatement* NewContinueStatement(Maybe label, IterationStatement** target, std::size_t begin, std::size_t end) { return new (static_cast(this)) ContinueStatement(label, target); } BreakStatement* NewBreakStatement(Maybe label, BreakableStatement** target, std::size_t begin, std::size_t end) { return new (static_cast(this)) BreakStatement(label, target); } ReturnStatement* NewReturnStatement(Maybe expr, std::size_t begin, std::size_t end) { return new (static_cast(this)) ReturnStatement(expr); } // if you want end position, // set position to Expression and use it WithStatement* NewWithStatement(Expression* expr, Statement* stmt, std::size_t begin) { return new (static_cast(this)) WithStatement(expr, stmt); } SwitchStatement* NewSwitchStatement(Expression* expr, CaseClauses* clauses, std::size_t begin, std::size_t end) { return new (static_cast(this)) SwitchStatement(expr, clauses); } // !!! if body is empty, end_position is end. CaseClause* NewCaseClause(bool is_default, Maybe expr, Statements* body, std::size_t begin, std::size_t end) { return new (static_cast(this)) CaseClause(is_default, expr, body); } ThrowStatement* NewThrowStatement(Expression* expr, std::size_t begin, std::size_t end) { return new (static_cast(this)) ThrowStatement(expr); } // if you want end position, // set position to Block and use it TryStatement* NewTryStatement(Block* try_block, Maybe catch_name, Maybe catch_block, Maybe finally_block, std::size_t begin) { return new (static_cast(this)) TryStatement(try_block, catch_name, catch_block, finally_block); } // if you want begin / end position, // set position to Expression and use it LabelledStatement* NewLabelledStatement(Expression* expr, Statement* stmt) { return new (static_cast(this)) LabelledStatement(expr, stmt); } // if you want begin / end position, // set position to Expression and use it BinaryOperation* NewBinaryOperation(Token::Type op, Expression* result, Expression* right) { return new (static_cast(this)) BinaryOperation(op, result, right); } // if you want begin / end position, // set position to Expression and use it Assignment* NewAssignment(Token::Type op, Expression* left, Expression* right) { return new (static_cast(this)) Assignment(op, left, right); } // if you want begin / end position, // set position to Expression and use it ConditionalExpression* NewConditionalExpression(Expression* cond, Expression* left, Expression* right) { return new (static_cast(this)) ConditionalExpression(cond, left, right); } // if you want end position, // set position to Expression and use it UnaryOperation* NewUnaryOperation(Token::Type op, Expression* expr, std::size_t begin) { return new (static_cast(this)) UnaryOperation(op, expr); } // if you want begin position, // set position to Expression and use it PostfixExpression* NewPostfixExpression(Token::Type op, Expression* expr, std::size_t end) { return new (static_cast(this)) PostfixExpression(op, expr); } // if you want begin position, // set position to Expression and use it FunctionCall* NewFunctionCall(Expression* expr, Expressions* args, std::size_t end) { return new (static_cast(this)) FunctionCall(expr, args); } // if you want begin position, // set position to Expression and use it // !!! CAUTION !!! // if not right paren (like new Array), end is 0 ConstructorCall* NewConstructorCall(Expression* target, Expressions* args, std::size_t end) { return new (static_cast(this)) ConstructorCall(target, args); } // if you want begin / end position, // set position to Expression / Identifier and use it IndexAccess* NewIndexAccess(Expression* expr, Expression* index) { return new (static_cast(this)) IndexAccess(expr, index); } // if you want begin / end position, // set position to Expression / Identifier and use it IdentifierAccess* NewIdentifierAccess(Expression* expr, Identifier* ident) { return new (static_cast(this)) IdentifierAccess(expr, ident); } private: EmptyStatement* empty_statement_instance_; DebuggerStatement* debugger_statement_instance_; ThisLiteral* this_instance_; NullLiteral* null_instance_; TrueLiteral* true_instance_; FalseLiteral* false_instance_; }; } } } // namespace iv::core::ast #endif // _IV_AST_FACTORY_H_