Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 93a8a42feaca7b9c49d5e812017581177b07af85..241d81a01a00f4edf95887aa48a6c625babc916b 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -67,47 +67,217 @@ class PreParser { |
} |
private: |
+ // These types form an algebra over syntactic categories that is just |
+ // rich enough to let us recognize and propagate the constructs that |
+ // are either being counted in the preparser data, or is important |
+ // to throw the correct syntax error exceptions. |
+ |
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, |
- kStringLiteralExpressionStatement, |
- kUseStrictExpressionStatement |
+ class Expression; |
+ |
+ class Identifier { |
+ public: |
+ static Identifier Default() { |
+ return Identifier(kUnknownIdentifier); |
+ } |
+ static Identifier Eval() { |
+ return Identifier(kEvalIdentifier); |
+ } |
+ static Identifier Arguments() { |
+ return Identifier(kArgumentsIdentifier); |
+ } |
+ static Identifier FutureReserved() { |
+ return Identifier(kFutureReservedIdentifier); |
+ } |
+ bool IsEval() { return type_ == kEvalIdentifier; } |
+ bool IsArguments() { return type_ == kArgumentsIdentifier; } |
+ bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } |
+ bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } |
+ bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } |
+ private: |
+ enum Type { |
+ kUnknownIdentifier, |
+ kFutureReservedIdentifier, |
+ kEvalIdentifier, |
+ kArgumentsIdentifier |
+ }; |
+ explicit Identifier(Type type) : type_(type) { } |
+ Type type_; |
+ |
+ friend class Expression; |
}; |
- enum ExpressionType { |
- kUnknownExpression, |
- kIdentifierExpression, // Used to detect labels. |
- kThisExpression, |
- kThisPropertyExpression, |
- kStringLiteralExpression, |
- kUseStrictString |
+ // Bits 0 and 1 are used to identify the type of expression: |
+ // If bit 0 is set, it's an identifier. |
+ // if bit 1 is set, it's a string literal. |
+ // If neither is set, it's no particular type, and both set isn't |
+ // use yet. |
+ // Bit 2 is used to mark the expression as being parenthesized, |
+ // so "(foo)" isn't recognized as a pure identifier (and possible label). |
+ class Expression { |
+ public: |
+ static Expression Default() { |
+ return Expression(kUnknownExpression); |
+ } |
+ |
+ static Expression Identifier(Identifier id) { |
+ return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift)); |
+ } |
+ |
+ static Expression StringLiteral() { |
+ return Expression(kUnknownStringLiteral); |
+ } |
+ |
+ static Expression UseStrictStringLiteral() { |
+ return Expression(kUseStrictString); |
+ } |
+ |
+ static Expression This() { |
+ return Expression(kThisExpression); |
+ } |
+ |
+ static Expression ThisProperty() { |
+ return Expression(kThisPropertyExpression); |
+ } |
+ |
+ static Expression StrictFunction() { |
+ return Expression(kStrictFunctionExpression); |
+ } |
+ |
+ bool IsIdentifier() { |
+ return (code_ & kIdentifierFlag) != 0; |
+ } |
+ |
+ // Only works corretly if it is actually an identifier expression. |
+ PreParser::Identifier AsIdentifier() { |
+ return PreParser::Identifier( |
+ static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); |
+ } |
+ |
+ bool IsParenthesized() { |
+ // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized. |
+ return (code_ & 7) > 4; |
+ } |
+ |
+ bool IsRawIdentifier() { |
+ return !IsParenthesized() && IsIdentifier(); |
+ } |
+ |
+ bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } |
+ |
+ bool IsRawStringLiteral() { |
+ return !IsParenthesized() && IsStringLiteral(); |
+ } |
+ |
+ bool IsUseStrictLiteral() { |
+ return (code_ & kStringLiteralMask) == kUseStrictString; |
+ } |
+ |
+ bool IsThis() { |
+ return code_ == kThisExpression; |
+ } |
+ |
+ bool IsThisProperty() { |
+ return code_ == kThisPropertyExpression; |
+ } |
+ |
+ bool IsStrictFunction() { |
+ return code_ == kStrictFunctionExpression; |
+ } |
+ |
+ Expression Parenthesize() { |
+ int type = code_ & 3; |
+ if (type != 0) { |
+ // Identifiers and string literals can be parenthesized. |
+ // They no longer work as labels or directive prologues, |
+ // but are still recognized in other contexts. |
+ return Expression(code_ | kParentesizedExpressionFlag); |
+ } |
+ // For other types of expressions, it's not important to remember |
+ // the parentheses. |
+ return *this; |
+ } |
+ |
+ private: |
+ // First two/three bits are used as flags. |
+ // Bit 0 and 1 represent identifiers or strings literals, and are |
+ // mutually exclusive, but can both be absent. |
+ // If bit 0 or 1 are set, bit 2 marks that the expression has |
+ // been wrapped in parentheses (a string literal can no longer |
+ // be a directive prologue, and an identifier can no longer be |
+ // a label. |
+ enum { |
+ kUnknownExpression = 0, |
+ // Identifiers |
+ kIdentifierFlag = 1, // Used to detect labels. |
+ kIdentifierShift = 3, |
+ |
+ kStringLiteralFlag = 2, // Used to detect directive prologue. |
+ kUnknownStringLiteral = kStringLiteralFlag, |
+ kUseStrictString = kStringLiteralFlag | 8, |
+ kStringLiteralMask = kUseStrictString, |
+ |
+ kParentesizedExpressionFlag = 4, // Only if identifier or string literal. |
+ |
+ // Below here applies if neither identifier nor string literal. |
+ kThisExpression = 4, |
+ kThisPropertyExpression = 8, |
+ kStrictFunctionExpression = 12 |
+ }; |
+ |
+ explicit Expression(int expression_code) : code_(expression_code) { } |
+ |
+ int code_; |
}; |
- enum IdentifierType { |
- kUnknownIdentifier |
+ class Statement { |
+ public: |
+ static Statement Default() { |
+ return Statement(kUnknownStatement); |
+ } |
+ |
+ // Creates expression statement from expression. |
+ // Preserves being an unparenthesized string literal, possibly |
+ // "use strict". |
+ static Statement ExpressionStatement(Expression expression) { |
+ if (!expression.IsParenthesized()) { |
+ if (expression.IsUseStrictLiteral()) { |
+ return Statement(kUseStrictExpressionStatement); |
+ } |
+ if (expression.IsStringLiteral()) { |
+ return Statement(kStringLiteralExpressionStatement); |
+ } |
+ } |
+ return Default(); |
+ } |
+ |
+ bool IsStringLiteral() { |
+ return code_ != kUnknownStatement; |
+ } |
+ |
+ bool IsUseStrictLiteral() { |
+ return code_ == kUseStrictExpressionStatement; |
+ } |
+ |
+ private: |
+ enum Type { |
+ kUnknownStatement, |
+ kStringLiteralExpressionStatement, |
+ kUseStrictExpressionStatement |
+ }; |
+ |
+ explicit Statement(Type code) : code_(code) {} |
+ Type code_; |
}; |
- enum SourceElementTypes { |
- kUnknownSourceElements, |
- kDirectivePrologue, |
- kUseStrictDirective |
+ enum SourceElements { |
+ kUnknownSourceElements |
}; |
- typedef int SourceElements; |
- typedef int Expression; |
- typedef int Statement; |
- typedef int Identifier; |
typedef int Arguments; |
class Scope { |
@@ -153,6 +323,8 @@ class PreParser { |
log_(log), |
scope_(NULL), |
stack_limit_(stack_limit), |
+ strict_mode_violation_location_(i::Scanner::Location::invalid()), |
+ strict_mode_violation_type_(NULL), |
stack_overflow_(false), |
allow_lazy_(true), |
parenthesized_function_(false) { } |
@@ -264,7 +436,7 @@ class PreParser { |
scope_->set_strict(); |
} |
- bool is_strict_mode() { return scope_->is_strict(); } |
+ bool strict_mode() { return scope_->is_strict(); } |
void Consume(i::Token::Value token) { Next(); } |
@@ -286,10 +458,23 @@ class PreParser { |
static int Precedence(i::Token::Value tok, bool accept_IN); |
+ void SetStrictModeViolation(i::Scanner::Location, |
+ const char* type, |
+ bool *ok); |
+ |
+ void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); |
+ |
+ void StrictModeIdentifierViolation(i::Scanner::Location, |
+ const char* eval_args_type, |
+ Identifier identifier, |
+ bool* ok); |
+ |
i::JavaScriptScanner* scanner_; |
i::ParserRecorder* log_; |
Scope* scope_; |
uintptr_t stack_limit_; |
+ i::Scanner::Location strict_mode_violation_location_; |
+ const char* strict_mode_violation_type_; |
bool stack_overflow_; |
bool allow_lazy_; |
bool parenthesized_function_; |