|
@ -47,14 +47,6 @@ |
|
|
namespace v8 { |
|
|
namespace v8 { |
|
|
namespace internal { |
|
|
namespace internal { |
|
|
|
|
|
|
|
|
class ParserFactory; |
|
|
|
|
|
class ParserLog; |
|
|
|
|
|
class TemporaryScope; |
|
|
|
|
|
class Target; |
|
|
|
|
|
|
|
|
|
|
|
template <typename T> class ZoneListWrapper; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PositionStack is used for on-stack allocation of token positions for
|
|
|
// PositionStack is used for on-stack allocation of token positions for
|
|
|
// new expressions. Please look at ParseNewExpression.
|
|
|
// new expressions. Please look at ParseNewExpression.
|
|
|
|
|
|
|
|
@ -95,250 +87,6 @@ class PositionStack { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Parser { |
|
|
|
|
|
public: |
|
|
|
|
|
Parser(Handle<Script> script, bool allow_natives_syntax, |
|
|
|
|
|
v8::Extension* extension, ParserMode 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(Handle<String> source, 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, |
|
|
|
|
|
bool in_global_context); |
|
|
|
|
|
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info); |
|
|
|
|
|
FunctionLiteral* ParseJson(Handle<String> source); |
|
|
|
|
|
|
|
|
|
|
|
// The minimum number of contiguous assignment that will
|
|
|
|
|
|
// be treated as an initialization block. Benchmarks show that
|
|
|
|
|
|
// the overhead exceeds the savings below this limit.
|
|
|
|
|
|
static const int kMinInitializationBlock = 3; |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
enum Mode { |
|
|
|
|
|
PARSE_LAZILY, |
|
|
|
|
|
PARSE_EAGERLY |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Report syntax error
|
|
|
|
|
|
void ReportUnexpectedToken(Token::Value token); |
|
|
|
|
|
void ReportInvalidPreparseData(Handle<String> name, bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
Handle<Script> script_; |
|
|
|
|
|
Scanner scanner_; |
|
|
|
|
|
|
|
|
|
|
|
Scope* top_scope_; |
|
|
|
|
|
int with_nesting_level_; |
|
|
|
|
|
|
|
|
|
|
|
TemporaryScope* temp_scope_; |
|
|
|
|
|
Mode mode_; |
|
|
|
|
|
|
|
|
|
|
|
Target* target_stack_; // for break, continue statements
|
|
|
|
|
|
bool allow_natives_syntax_; |
|
|
|
|
|
v8::Extension* extension_; |
|
|
|
|
|
ParserFactory* factory_; |
|
|
|
|
|
ParserLog* log_; |
|
|
|
|
|
bool is_pre_parsing_; |
|
|
|
|
|
ScriptDataImpl* pre_data_; |
|
|
|
|
|
FuncNameInferrer* fni_; |
|
|
|
|
|
|
|
|
|
|
|
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 is_catch_block, |
|
|
|
|
|
bool* ok); |
|
|
|
|
|
Statement* ParseWithStatement(ZoneStringList* labels, bool* ok); |
|
|
|
|
|
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok); |
|
|
|
|
|
SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok); |
|
|
|
|
|
DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok); |
|
|
|
|
|
WhileStatement* 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* ParseNewPrefix(PositionStack* stack, bool* ok); |
|
|
|
|
|
Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
|
|
|
|
|
bool* ok); |
|
|
|
|
|
Expression* ParsePrimaryExpression(bool* ok); |
|
|
|
|
|
Expression* ParseArrayLiteral(bool* ok); |
|
|
|
|
|
Expression* ParseObjectLiteral(bool* ok); |
|
|
|
|
|
ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok); |
|
|
|
|
|
Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
Expression* NewCompareNode(Token::Value op, |
|
|
|
|
|
Expression* x, |
|
|
|
|
|
Expression* y, |
|
|
|
|
|
int position); |
|
|
|
|
|
|
|
|
|
|
|
// Populate the constant properties fixed array for a materialized object
|
|
|
|
|
|
// literal.
|
|
|
|
|
|
void BuildObjectLiteralConstantProperties( |
|
|
|
|
|
ZoneList<ObjectLiteral::Property*>* properties, |
|
|
|
|
|
Handle<FixedArray> constants, |
|
|
|
|
|
bool* is_simple, |
|
|
|
|
|
bool* fast_elements, |
|
|
|
|
|
int* depth); |
|
|
|
|
|
|
|
|
|
|
|
// Populate the literals fixed array for a materialized array literal.
|
|
|
|
|
|
void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties, |
|
|
|
|
|
Handle<FixedArray> constants, |
|
|
|
|
|
bool* is_simple, |
|
|
|
|
|
int* depth); |
|
|
|
|
|
|
|
|
|
|
|
// Decide if a property should be in the object boilerplate.
|
|
|
|
|
|
bool IsBoilerplateProperty(ObjectLiteral::Property* property); |
|
|
|
|
|
// If the expression is a literal, return the literal value;
|
|
|
|
|
|
// if the expression is a materialized literal and is simple return a
|
|
|
|
|
|
// compile time value as encoded by CompileTimeValue::GetValue().
|
|
|
|
|
|
// Otherwise, return undefined literal as the placeholder
|
|
|
|
|
|
// in the object literal boilerplate.
|
|
|
|
|
|
Handle<Object> GetBoilerplateValue(Expression* expression); |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
bool Check(Token::Value token); |
|
|
|
|
|
void ExpectSemicolon(bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
Handle<String> GetSymbol(bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
// Get odd-ball literals.
|
|
|
|
|
|
Literal* GetLiteralUndefined(); |
|
|
|
|
|
Literal* GetLiteralTheHole(); |
|
|
|
|
|
Literal* GetLiteralNumber(double value); |
|
|
|
|
|
|
|
|
|
|
|
Handle<String> ParseIdentifier(bool* ok); |
|
|
|
|
|
Handle<String> ParseIdentifierName(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 RegisterTargetUse(BreakTarget* target, Target* stop); |
|
|
|
|
|
|
|
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
|
|
// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
|
|
|
|
|
|
// specification section 15.12.1 (and appendix A.8).
|
|
|
|
|
|
// The grammar is given section 15.12.1.2 (and appendix A.8.2).
|
|
|
|
|
|
|
|
|
|
|
|
// Parse JSON input as a single JSON value.
|
|
|
|
|
|
Expression* ParseJson(bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
// Parse a single JSON value from input (grammar production JSONValue).
|
|
|
|
|
|
// A JSON value is either a (double-quoted) string literal, a number literal,
|
|
|
|
|
|
// one of "true", "false", or "null", or an object or array literal.
|
|
|
|
|
|
Expression* ParseJsonValue(bool* ok); |
|
|
|
|
|
// Parse a JSON object literal (grammar production JSONObject).
|
|
|
|
|
|
// An object literal is a squiggly-braced and comma separated sequence
|
|
|
|
|
|
// (possibly empty) of key/value pairs, where the key is a JSON string
|
|
|
|
|
|
// literal, the value is a JSON value, and the two are spearated by a colon.
|
|
|
|
|
|
// A JavaScript object also allows numbers and identifiers as keys.
|
|
|
|
|
|
Expression* ParseJsonObject(bool* ok); |
|
|
|
|
|
// Parses a JSON array literal (grammar production JSONArray). An array
|
|
|
|
|
|
// literal is a square-bracketed and comma separated sequence (possibly empty)
|
|
|
|
|
|
// of JSON values.
|
|
|
|
|
|
// A JavaScript array allows leaving out values from the sequence.
|
|
|
|
|
|
Expression* ParseJsonArray(bool* ok); |
|
|
|
|
|
|
|
|
|
|
|
friend class Target; |
|
|
|
|
|
friend class TargetScope; |
|
|
|
|
|
friend class LexicalScope; |
|
|
|
|
|
friend class TemporaryScope; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T, int initial_size> |
|
|
template <typename T, int initial_size> |
|
|
class BufferedZoneList { |
|
|
class BufferedZoneList { |
|
|
public: |
|
|
public: |
|
@ -5501,9 +5249,9 @@ bool ScriptDataImpl::HasError() { |
|
|
|
|
|
|
|
|
// Preparse, but only collect data that is immediately useful,
|
|
|
// Preparse, but only collect data that is immediately useful,
|
|
|
// even if the preparser data is only used once.
|
|
|
// even if the preparser data is only used once.
|
|
|
ScriptDataImpl* PartialPreParse(Handle<String> source, |
|
|
ScriptDataImpl* Parser::PartialPreParse(Handle<String> source, |
|
|
unibrow::CharacterStream* stream, |
|
|
unibrow::CharacterStream* stream, |
|
|
v8::Extension* extension) { |
|
|
v8::Extension* extension) { |
|
|
Handle<Script> no_script; |
|
|
Handle<Script> no_script; |
|
|
bool allow_natives_syntax = |
|
|
bool allow_natives_syntax = |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
@ -5559,9 +5307,9 @@ int ScriptDataImpl::ReadNumber(byte** source) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ScriptDataImpl* PreParse(Handle<String> source, |
|
|
ScriptDataImpl* Parser::PreParse(Handle<String> source, |
|
|
unibrow::CharacterStream* stream, |
|
|
unibrow::CharacterStream* stream, |
|
|
v8::Extension* extension) { |
|
|
v8::Extension* extension) { |
|
|
Handle<Script> no_script; |
|
|
Handle<Script> no_script; |
|
|
bool allow_natives_syntax = |
|
|
bool allow_natives_syntax = |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
@ -5574,9 +5322,9 @@ ScriptDataImpl* PreParse(Handle<String> source, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParseRegExp(FlatStringReader* input, |
|
|
bool Parser::ParseRegExp(FlatStringReader* input, |
|
|
bool multiline, |
|
|
bool multiline, |
|
|
RegExpCompileData* result) { |
|
|
RegExpCompileData* result) { |
|
|
ASSERT(result != NULL); |
|
|
ASSERT(result != NULL); |
|
|
RegExpParser parser(input, &result->error, multiline); |
|
|
RegExpParser parser(input, &result->error, multiline); |
|
|
RegExpTree* tree = parser.ParsePattern(); |
|
|
RegExpTree* tree = parser.ParsePattern(); |
|
@ -5596,13 +5344,11 @@ bool ParseRegExp(FlatStringReader* input, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MakeAST is just a wrapper for the corresponding Parser calls so we don't
|
|
|
FunctionLiteral* Parser::MakeAST(bool compile_in_global_context, |
|
|
// have to expose the entire Parser class in the .h file.
|
|
|
Handle<Script> script, |
|
|
FunctionLiteral* MakeAST(bool compile_in_global_context, |
|
|
v8::Extension* extension, |
|
|
Handle<Script> script, |
|
|
ScriptDataImpl* pre_data, |
|
|
v8::Extension* extension, |
|
|
bool is_json) { |
|
|
ScriptDataImpl* pre_data, |
|
|
|
|
|
bool is_json) { |
|
|
|
|
|
bool allow_natives_syntax = |
|
|
bool allow_natives_syntax = |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
|
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); |
|
|
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data); |
|
|
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data); |
|
@ -5630,7 +5376,7 @@ FunctionLiteral* MakeAST(bool compile_in_global_context, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info) { |
|
|
FunctionLiteral* Parser::MakeLazyAST(Handle<SharedFunctionInfo> info) { |
|
|
Handle<Script> script(Script::cast(info->script())); |
|
|
Handle<Script> script(Script::cast(info->script())); |
|
|
AstBuildingParser parser(script, true, NULL, NULL); |
|
|
AstBuildingParser parser(script, true, NULL, NULL); |
|
|
FunctionLiteral* result = parser.ParseLazy(info); |
|
|
FunctionLiteral* result = parser.ParseLazy(info); |
|
|