📄 parser.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "api.h"#include "ast.h"#include "bootstrapper.h"#include "platform.h"#include "runtime.h"#include "parser.h"#include "scopes.h"namespace v8 { namespace internal {class ParserFactory;class ParserLog;class TemporaryScope;template <typename T> class ZoneListWrapper;class Parser { public: Parser(Handle<Script> script, bool allow_natives_syntax, v8::Extension* extension, bool is_pre_parsing, ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data); virtual ~Parser() { } // Pre-parse the program from the character stream; returns true on // success, false if a stack-overflow happened during parsing. bool PreParseProgram(unibrow::CharacterStream* stream); void ReportMessage(const char* message, Vector<const char*> args); virtual void ReportMessageAt(Scanner::Location loc, const char* message, Vector<const char*> args) = 0; // Returns NULL if parsing failed. FunctionLiteral* ParseProgram(Handle<String> source, unibrow::CharacterStream* stream, bool in_global_context); FunctionLiteral* ParseLazy(Handle<String> source, Handle<String> name, int start_position, bool is_expression); protected: enum Mode { PARSE_LAZILY, PARSE_EAGERLY }; // Report syntax error void ReportUnexpectedToken(Token::Value token); Handle<Script> script_; Scanner scanner_; Scope* top_scope_; int with_nesting_level_; TemporaryScope* temp_scope_; Mode mode_; List<Node*>* target_stack_; // for break, continue statements bool allow_natives_syntax_; v8::Extension* extension_; ParserFactory* factory_; ParserLog* log_; bool is_pre_parsing_; ScriptDataImpl* pre_data_; bool inside_with() const { return with_nesting_level_ > 0; } ParserFactory* factory() const { return factory_; } ParserLog* log() const { return log_; } Scanner& scanner() { return scanner_; } Mode mode() const { return mode_; } ScriptDataImpl* pre_data() const { return pre_data_; } // All ParseXXX functions take as the last argument an *ok parameter // which is set to false if parsing failed; it is unchanged otherwise. // By making the 'exception handling' explicit, we are forced to check // for failure at the call sites. void* ParseSourceElements(ZoneListWrapper<Statement>* processor, int end_token, bool* ok); Statement* ParseStatement(ZoneStringList* labels, bool* ok); Statement* ParseFunctionDeclaration(bool* ok); Statement* ParseNativeDeclaration(bool* ok); Block* ParseBlock(ZoneStringList* labels, bool* ok); Block* ParseVariableStatement(bool* ok); Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok); Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels, bool* ok); IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok); Statement* ParseContinueStatement(bool* ok); Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok); Statement* ParseReturnStatement(bool* ok); Block* WithHelper(Expression* obj, ZoneStringList* labels, bool* ok); Statement* ParseWithStatement(ZoneStringList* labels, bool* ok); CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok); SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok); LoopStatement* ParseDoStatement(ZoneStringList* labels, bool* ok); LoopStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok); Statement* ParseForStatement(ZoneStringList* labels, bool* ok); Statement* ParseThrowStatement(bool* ok); Expression* MakeCatchContext(Handle<String> id, VariableProxy* value); TryStatement* ParseTryStatement(bool* ok); DebuggerStatement* ParseDebuggerStatement(bool* ok); Expression* ParseExpression(bool accept_IN, bool* ok); Expression* ParseAssignmentExpression(bool accept_IN, bool* ok); Expression* ParseConditionalExpression(bool accept_IN, bool* ok); Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok); Expression* ParseUnaryExpression(bool* ok); Expression* ParsePostfixExpression(bool* ok); Expression* ParseLeftHandSideExpression(bool* ok); Expression* ParseNewExpression(bool* ok); Expression* ParseMemberExpression(bool* ok); Expression* ParseMemberWithNewPrefixesExpression(List<int>* new_prefixes, bool* ok); Expression* ParsePrimaryExpression(bool* ok); Expression* ParseArrayLiteral(bool* ok); Expression* ParseObjectLiteral(bool* ok); Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); // Decide if a property should be the object boilerplate. bool IsBoilerplateProperty(ObjectLiteral::Property* property); // If the property is CONSTANT type, it returns the literal value, // otherwise, it return undefined literal as the placeholder // in the object literal boilerplate. Literal* GetBoilerplateValue(ObjectLiteral::Property* property); enum FunctionLiteralType { EXPRESSION, DECLARATION, NESTED }; ZoneList<Expression*>* ParseArguments(bool* ok); FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name, int function_token_position, FunctionLiteralType type, bool* ok); // Magical syntax support. Expression* ParseV8Intrinsic(bool* ok); INLINE(Token::Value peek()) { return scanner_.peek(); } INLINE(Token::Value Next()) { return scanner_.Next(); } INLINE(void Consume(Token::Value token)); void Expect(Token::Value token, bool* ok); void ExpectSemicolon(bool* ok); // Get odd-ball literals. Literal* GetLiteralUndefined(); Literal* GetLiteralTheHole(); Literal* GetLiteralNumber(double value); Handle<String> ParseIdentifier(bool* ok); Handle<String> ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); // Parser support virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode, FunctionLiteral* fun, bool resolve, bool* ok) = 0; bool TargetStackContainsLabel(Handle<String> label); BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok); IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok); void RegisterLabelUse(Label* label, int index); // Create a number literal. Literal* NewNumberLiteral(double value); // Generate AST node that throw a ReferenceError with the given type. Expression* NewThrowReferenceError(Handle<String> type); // Generate AST node that throw a SyntaxError with the given // type. The first argument may be null (in the handle sense) in // which case no arguments are passed to the constructor. Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first); // Generate AST node that throw a TypeError with the given // type. Both arguments must be non-null (in the handle sense). Expression* NewThrowTypeError(Handle<String> type, Handle<Object> first, Handle<Object> second); // Generic AST generator for throwing errors from compiled code. Expression* NewThrowError(Handle<String> constructor, Handle<String> type, Vector< Handle<Object> > arguments); friend class Target; friend class TargetScope; friend class LexicalScope; friend class TemporaryScope;};// A temporary scope stores information during parsing, just like// a plain scope. However, temporary scopes are not kept around// after parsing or referenced by syntax trees so they can be stack-// allocated and hence used by the pre-parser.class TemporaryScope BASE_EMBEDDED { public: explicit TemporaryScope(Parser* parser); ~TemporaryScope(); int NextMaterializedLiteralIndex() { int next_index = materialized_literal_count_ + JSFunction::kLiteralsPrefixSize; materialized_literal_count_++; return next_index; } int materialized_literal_count() { return materialized_literal_count_; } void set_contains_array_literal() { contains_array_literal_ = true; } bool contains_array_literal() { return contains_array_literal_; } void AddProperty() { expected_property_count_++; } int expected_property_count() { return expected_property_count_; } private: // Captures the number of nodes that need materialization in the // function. regexp literals, and boilerplate for object literals. int materialized_literal_count_; // Captures whether or not the function contains array literals. If // the function contains array literals, we have to allocate space // for the array constructor in the literals array of the function. // This array constructor is used when creating the actual array // literals. bool contains_array_literal_; // Properties count estimation. int expected_property_count_; // Bookkeeping Parser* parser_; TemporaryScope* parent_; friend class Parser;};TemporaryScope::TemporaryScope(Parser* parser) : materialized_literal_count_(0), contains_array_literal_(false), expected_property_count_(0), parser_(parser), parent_(parser->temp_scope_) { parser->temp_scope_ = this;}TemporaryScope::~TemporaryScope() { parser_->temp_scope_ = parent_;}// A zone list wrapper lets code either access a access a zone list// or appear to do so while actually ignoring all operations.template <typename T>class ZoneListWrapper { public: ZoneListWrapper() : list_(NULL) { } explicit ZoneListWrapper(int size) : list_(new ZoneList<T*>(size)) { } void Add(T* that) { if (list_) list_->Add(that); } int length() { return list_->length(); } ZoneList<T*>* elements() { return list_; } T* at(int index) { return list_->at(index); } private: ZoneList<T*>* list_;};// Allocation macro that should be used to allocate objects that must// only be allocated in real parsing mode. Note that in preparse mode// not only is the syntax tree not created but the constructor// arguments are not evaulated.#define NEW(expr) (is_pre_parsing_ ? NULL : new expr)class ParserFactory BASE_EMBEDDED { public: explicit ParserFactory(bool is_pre_parsing) : is_pre_parsing_(is_pre_parsing) { } virtual ~ParserFactory() { } virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); virtual Handle<String> LookupSymbol(const char* string, int length) { return Handle<String>(); } virtual Handle<String> EmptySymbol() { return Handle<String>(); } virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { if (obj == VariableProxySentinel::this_proxy()) { return Property::this_property(); } else { return ValidLeftHandSideSentinel::instance(); } } virtual Expression* NewCall(Expression* expression, ZoneList<Expression*>* arguments, bool is_eval, int pos) { return Call::sentinel(); } virtual Statement* EmptyStatement() { return NULL; } template <typename T> ZoneListWrapper<T> NewList(int size) { return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(size); } private: bool is_pre_parsing_;};class ParserLog BASE_EMBEDDED { public: virtual ~ParserLog() { } // Records the occurrence of a function. The returned object is // only guaranteed to be valid until the next function has been // logged. virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); } virtual void LogError() { }};class AstBuildingParserFactory : public ParserFactory { public: AstBuildingParserFactory() : ParserFactory(false) { } virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); virtual Handle<String> LookupSymbol(const char* string, int length) { return Factory::LookupSymbol(Vector<const char>(string, length)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -