diff options
Diffstat (limited to 'src/3rdparty/v8/src/preparser.h')
-rw-r--r-- | src/3rdparty/v8/src/preparser.h | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/3rdparty/v8/src/preparser.h b/src/3rdparty/v8/src/preparser.h new file mode 100644 index 0000000..b7fa6c7 --- /dev/null +++ b/src/3rdparty/v8/src/preparser.h @@ -0,0 +1,278 @@ +// Copyright 2010 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. + +#ifndef V8_PREPARSER_H +#define V8_PREPARSER_H + +namespace v8 { +namespace preparser { + +// Preparsing checks a JavaScript program and emits preparse-data that helps +// a later parsing to be faster. +// See preparse-data.h for the data. + +// The PreParser checks that the syntax follows the grammar for JavaScript, +// and collects some information about the program along the way. +// The grammar check is only performed in order to understand the program +// sufficiently to deduce some information about it, that can be used +// to speed up later parsing. Finding errors is not the goal of pre-parsing, +// rather it is to speed up properly written and correct programs. +// That means that contextual checks (like a label being declared where +// it is used) are generally omitted. + +namespace i = v8::internal; + +class PreParser { + public: + enum PreParseResult { + kPreParseStackOverflow, + kPreParseSuccess + }; + + ~PreParser() { } + + // Pre-parse the program from the character stream; returns true on + // success (even if parsing failed, the pre-parse data successfully + // captured the syntax error), and false if a stack-overflow happened + // during parsing. + static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, + i::ParserRecorder* log, + bool allow_lazy, + uintptr_t stack_limit) { + return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); + } + + private: + enum ScopeType { + kTopLevelScope, + kFunctionScope + }; + + // Types that allow us to recognize simple this-property assignments. + // A simple this-property assignment is a statement on the form + // "this.propertyName = {primitive constant or function parameter name);" + // where propertyName isn't "__proto__". + // The result is only relevant if the function body contains only + // simple this-property assignments. + + enum StatementType { + kUnknownStatement + }; + + enum ExpressionType { + kUnknownExpression, + kIdentifierExpression, // Used to detect labels. + kThisExpression, + kThisPropertyExpression + }; + + enum IdentifierType { + kUnknownIdentifier + }; + + enum SourceElementTypes { + kUnknownSourceElements + }; + + typedef int SourceElements; + typedef int Expression; + typedef int Statement; + typedef int Identifier; + typedef int Arguments; + + class Scope { + public: + Scope(Scope** variable, ScopeType type) + : variable_(variable), + prev_(*variable), + type_(type), + materialized_literal_count_(0), + expected_properties_(0), + with_nesting_count_(0) { + *variable = this; + } + ~Scope() { *variable_ = prev_; } + void NextMaterializedLiteralIndex() { materialized_literal_count_++; } + void AddProperty() { expected_properties_++; } + ScopeType type() { return type_; } + int expected_properties() { return expected_properties_; } + int materialized_literal_count() { return materialized_literal_count_; } + bool IsInsideWith() { return with_nesting_count_ != 0; } + void EnterWith() { with_nesting_count_++; } + void LeaveWith() { with_nesting_count_--; } + + private: + Scope** const variable_; + Scope* const prev_; + const ScopeType type_; + int materialized_literal_count_; + int expected_properties_; + int with_nesting_count_; + }; + + // Private constructor only used in PreParseProgram. + PreParser(i::JavaScriptScanner* scanner, + i::ParserRecorder* log, + uintptr_t stack_limit, + bool allow_lazy) + : scanner_(scanner), + log_(log), + scope_(NULL), + stack_limit_(stack_limit), + stack_overflow_(false), + allow_lazy_(true), + parenthesized_function_(false) { } + + // Preparse the program. Only called in PreParseProgram after creating + // the instance. + PreParseResult PreParse() { + Scope top_scope(&scope_, kTopLevelScope); + bool ok = true; + ParseSourceElements(i::Token::EOS, &ok); + if (stack_overflow_) return kPreParseStackOverflow; + if (!ok) { + ReportUnexpectedToken(scanner_->current_token()); + } + return kPreParseSuccess; + } + + // Report syntax error + void ReportUnexpectedToken(i::Token::Value token); + void ReportMessageAt(int start_pos, + int end_pos, + const char* type, + const char* name_opt) { + log_->LogMessage(start_pos, end_pos, type, name_opt); + } + + // 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. + SourceElements ParseSourceElements(int end_token, bool* ok); + Statement ParseStatement(bool* ok); + Statement ParseFunctionDeclaration(bool* ok); + Statement ParseNativeDeclaration(bool* ok); + Statement ParseBlock(bool* ok); + Statement ParseVariableStatement(bool* ok); + Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok); + Statement ParseExpressionOrLabelledStatement(bool* ok); + Statement ParseIfStatement(bool* ok); + Statement ParseContinueStatement(bool* ok); + Statement ParseBreakStatement(bool* ok); + Statement ParseReturnStatement(bool* ok); + Statement ParseWithStatement(bool* ok); + Statement ParseSwitchStatement(bool* ok); + Statement ParseDoWhileStatement(bool* ok); + Statement ParseWhileStatement(bool* ok); + Statement ParseForStatement(bool* ok); + Statement ParseThrowStatement(bool* ok); + Statement ParseTryStatement(bool* ok); + Statement 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(unsigned new_count, bool* ok); + Expression ParsePrimaryExpression(bool* ok); + Expression ParseArrayLiteral(bool* ok); + Expression ParseObjectLiteral(bool* ok); + Expression ParseRegExpLiteral(bool seen_equal, bool* ok); + Expression ParseV8Intrinsic(bool* ok); + + Arguments ParseArguments(bool* ok); + Expression ParseFunctionLiteral(bool* ok); + + Identifier ParseIdentifier(bool* ok); + Identifier ParseIdentifierName(bool* ok); + Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); + + // Logs the currently parsed literal as a symbol in the preparser data. + void LogSymbol(); + // Log the currently parsed identifier. + Identifier GetIdentifierSymbol(); + // Log the currently parsed string literal. + Expression GetStringSymbol(); + + i::Token::Value peek() { + if (stack_overflow_) return i::Token::ILLEGAL; + return scanner_->peek(); + } + + i::Token::Value Next() { + if (stack_overflow_) return i::Token::ILLEGAL; + { + int marker; + if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { + // Further calls to peek/Next will return illegal token. + // The current one will still be returned. It might already + // have been seen using peek. + stack_overflow_ = true; + } + } + return scanner_->Next(); + } + + bool peek_any_identifier(); + + void Consume(i::Token::Value token) { Next(); } + + void Expect(i::Token::Value token, bool* ok) { + if (Next() != token) { + *ok = false; + } + } + + bool Check(i::Token::Value token) { + i::Token::Value next = peek(); + if (next == token) { + Consume(next); + return true; + } + return false; + } + void ExpectSemicolon(bool* ok); + + static int Precedence(i::Token::Value tok, bool accept_IN); + + i::JavaScriptScanner* scanner_; + i::ParserRecorder* log_; + Scope* scope_; + uintptr_t stack_limit_; + bool stack_overflow_; + bool allow_lazy_; + bool parenthesized_function_; +}; +} } // v8::preparser + +#endif // V8_PREPARSER_H |