Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 // captured the syntax error), and false if a stack-overflow happened | 60 // captured the syntax error), and false if a stack-overflow happened |
| 61 // during parsing. | 61 // during parsing. |
| 62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, | 62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, |
| 63 i::ParserRecorder* log, | 63 i::ParserRecorder* log, |
| 64 bool allow_lazy, | 64 bool allow_lazy, |
| 65 uintptr_t stack_limit) { | 65 uintptr_t stack_limit) { |
| 66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); | 66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 private: | 69 private: |
| 70 // These types form an algebra over syntactic categories that is just | |
| 71 // rich enough to let us recognize and propagate the constructs that | |
| 72 // are either being counted in the preparser data, or is important | |
| 73 // to throw the correct syntax error exceptions. | |
| 74 | |
| 70 enum ScopeType { | 75 enum ScopeType { |
| 71 kTopLevelScope, | 76 kTopLevelScope, |
| 72 kFunctionScope | 77 kFunctionScope |
| 73 }; | 78 }; |
| 74 | 79 |
| 75 // Types that allow us to recognize simple this-property assignments. | 80 class Expression; |
| 76 // A simple this-property assignment is a statement on the form | 81 |
| 77 // "this.propertyName = {primitive constant or function parameter name);" | 82 class Identifier { |
| 78 // where propertyName isn't "__proto__". | 83 public: |
| 79 // The result is only relevant if the function body contains only | 84 static Identifier Default() { |
| 80 // simple this-property assignments. | 85 return Identifier(kUnknownIdentifier); |
| 81 | 86 } |
| 82 enum StatementType { | 87 static Identifier Eval() { |
| 83 kUnknownStatement, | 88 return Identifier(kEvalIdentifier); |
| 84 kStringLiteralExpressionStatement, | 89 } |
| 85 kUseStrictExpressionStatement | 90 static Identifier Arguments() { |
| 86 }; | 91 return Identifier(kArgumentsIdentifier); |
| 87 | 92 } |
| 88 enum ExpressionType { | 93 static Identifier FutureReserved() { |
| 89 kUnknownExpression, | 94 return Identifier(kFutureReservedIdentifier); |
| 90 kIdentifierExpression, // Used to detect labels. | 95 } |
| 91 kThisExpression, | 96 bool IsEval() { return type_ == kEvalIdentifier; } |
| 92 kThisPropertyExpression, | 97 bool IsArguments() { return type_ == kArgumentsIdentifier; } |
| 93 kStringLiteralExpression, | 98 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } |
| 94 kUseStrictString | 99 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } |
| 95 }; | 100 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } |
| 96 | 101 private: |
| 97 enum IdentifierType { | 102 enum Type { |
| 98 kUnknownIdentifier | 103 kUnknownIdentifier, |
| 99 }; | 104 kFutureReservedIdentifier, |
| 100 | 105 kEvalIdentifier, |
| 101 enum SourceElementTypes { | 106 kArgumentsIdentifier |
| 102 kUnknownSourceElements, | 107 }; |
| 103 kDirectivePrologue, | 108 explicit Identifier(Type type) : type_(type) { } |
| 104 kUseStrictDirective | 109 Type type_; |
| 105 }; | 110 |
| 106 | 111 friend class Expression; |
| 107 typedef int SourceElements; | 112 }; |
| 108 typedef int Expression; | 113 |
| 109 typedef int Statement; | 114 // Bits 0 and 1 are used to identify the type of expression: |
| 110 typedef int Identifier; | 115 // If bit 0 is set, it's an identifier. |
| 116 // if bit 1 is set, it's a string literal. | |
| 117 // If neither is set, it's no particular type, and both set isn't | |
| 118 // use yet. | |
| 119 // Bit 2 is used to mark the expression as being parenthesized, | |
| 120 // so "(foo)" isn't recognized as a pure identifier (and possible label). | |
| 121 class Expression { | |
| 122 public: | |
| 123 static Expression Default() { | |
| 124 return Expression(kUnknownExpression); | |
| 125 } | |
| 126 | |
| 127 static Expression Identifier(Identifier id) { | |
| 128 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift)); | |
| 129 } | |
| 130 | |
| 131 static Expression StringLiteral() { | |
| 132 return Expression(kUnknownStringLiteral); | |
| 133 } | |
| 134 | |
| 135 static Expression UseStrictStringLiteral() { | |
| 136 return Expression(kUseStrictString); | |
| 137 } | |
| 138 | |
| 139 static Expression This() { | |
| 140 return Expression(kThisExpression); | |
| 141 } | |
| 142 | |
| 143 static Expression ThisProperty() { | |
| 144 return Expression(kThisPropertyExpression); | |
| 145 } | |
| 146 | |
| 147 static Expression StrictFunction() { | |
| 148 return Expression(kStrictFunctionExpression); | |
| 149 } | |
| 150 | |
| 151 bool IsIdentifier() { | |
| 152 return (code_ & kIdentifierFlag) != 0; | |
| 153 } | |
| 154 | |
| 155 // Only works corretly if it is actually an identifier expression. | |
| 156 PreParser::Identifier AsIdentifier() { | |
| 157 return PreParser::Identifier( | |
| 158 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); | |
| 159 } | |
| 160 | |
| 161 bool IsParenthesized() { | |
| 162 // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized. | |
| 163 return (code_ & 7) > 4; | |
| 164 } | |
| 165 | |
| 166 bool IsRawIdentifier() { | |
| 167 return !IsParenthesized() && IsIdentifier(); | |
| 168 } | |
| 169 | |
| 170 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } | |
| 171 | |
| 172 bool IsRawStringLiteral() { | |
| 173 return !IsParenthesized() && IsStringLiteral(); | |
| 174 } | |
| 175 | |
| 176 bool IsUseStrictLiteral() { | |
| 177 return (code_ & kStringLiteralMask) == kUseStrictString; | |
| 178 } | |
| 179 | |
| 180 bool IsThis() { | |
| 181 return code_ == kThisExpression; | |
| 182 } | |
| 183 | |
| 184 bool IsThisProperty() { | |
| 185 return code_ == kThisPropertyExpression; | |
| 186 } | |
| 187 | |
| 188 bool IsStrictFunction() { | |
| 189 return code_ == kStrictFunctionExpression; | |
| 190 } | |
| 191 | |
| 192 Expression Parenthesize() { | |
| 193 int type = code_ & 3; | |
| 194 if (type != 0) { | |
| 195 // Identifiers and string literals can be parenthesized. | |
| 196 // They no longer work as lables or directive prologues, | |
|
Mads Ager (chromium)
2011/05/18 13:20:48
lables -> labels
Lasse Reichstein
2011/05/19 09:00:31
Done.
| |
| 197 // but are still recognized in other contexts. | |
| 198 return Expression(code_ | kParentesizedExpressionFlag); | |
| 199 } | |
| 200 // For other types of expressions, it's not important to remember | |
| 201 // the parentheses. | |
| 202 return *this; | |
| 203 } | |
| 204 | |
| 205 private: | |
| 206 // First two/three bits are used as flags. | |
| 207 // Bit 0 and 1 represent identifiers or strings literals, and are | |
| 208 // mutually exclusive, but can both be absent. | |
| 209 // If bit 0 or 1 are set, bit 2 marks that the expression has | |
| 210 // been wrapped in parentheses (a string literal can no longer | |
| 211 // be a directive prologue, and an identifier can no longer be | |
| 212 // a label. | |
| 213 enum { | |
| 214 kUnknownExpression = 0, | |
| 215 // Identifiers | |
| 216 kIdentifierFlag = 1, // Used to detect labels. | |
| 217 kIdentifierShift = 3, | |
| 218 | |
| 219 kStringLiteralFlag = 2, // Used to detect directive prologue. | |
| 220 kUnknownStringLiteral = kStringLiteralFlag, | |
| 221 kUseStrictString = kStringLiteralFlag | 8, | |
| 222 kStringLiteralMask = kUseStrictString, | |
| 223 | |
| 224 kParentesizedExpressionFlag = 4, // Only if identifier or string literal. | |
| 225 | |
| 226 // Below here applies if neither identifier nor string literal. | |
| 227 kThisExpression = 4, | |
| 228 kThisPropertyExpression = 8, | |
| 229 kStrictFunctionExpression = 12 | |
| 230 }; | |
| 231 | |
| 232 explicit Expression(int expression_code) : code_(expression_code) { } | |
| 233 | |
| 234 int code_; | |
| 235 }; | |
| 236 | |
| 237 class Statement { | |
| 238 public: | |
| 239 static Statement Default() { | |
| 240 return Statement(kUnknownStatement); | |
| 241 } | |
| 242 | |
| 243 // Creates expression statement from expression. | |
| 244 // Preserves being an unparenthesized string literal, possibly | |
| 245 // "use strict". | |
| 246 static Statement ExpressionStatement(Expression expression) { | |
| 247 if (!expression.IsParenthesized()) { | |
| 248 if (expression.IsUseStrictLiteral()) { | |
| 249 return Statement(kUseStrictExpressionStatement); | |
| 250 } | |
| 251 if (expression.IsStringLiteral()) { | |
| 252 return Statement(kStringLiteralExpressionStatement); | |
| 253 } | |
| 254 } | |
| 255 return Default(); | |
| 256 } | |
| 257 | |
| 258 bool IsStringLiteral() { | |
| 259 return code_ != kUnknownStatement; | |
| 260 } | |
| 261 | |
| 262 bool IsUseStrictLiteral() { | |
| 263 return code_ == kUseStrictExpressionStatement; | |
| 264 } | |
| 265 | |
| 266 private: | |
| 267 enum Type { | |
| 268 kUnknownStatement, | |
| 269 kStringLiteralExpressionStatement, | |
| 270 kUseStrictExpressionStatement | |
| 271 }; | |
| 272 | |
| 273 explicit Statement(Type code) : code_(code) {} | |
| 274 Type code_; | |
| 275 }; | |
| 276 | |
| 277 enum SourceElements { | |
| 278 kUnknownSourceElements | |
| 279 }; | |
| 280 | |
| 111 typedef int Arguments; | 281 typedef int Arguments; |
| 112 | 282 |
| 113 class Scope { | 283 class Scope { |
| 114 public: | 284 public: |
| 115 Scope(Scope** variable, ScopeType type) | 285 Scope(Scope** variable, ScopeType type) |
| 116 : variable_(variable), | 286 : variable_(variable), |
| 117 prev_(*variable), | 287 prev_(*variable), |
| 118 type_(type), | 288 type_(type), |
| 119 materialized_literal_count_(0), | 289 materialized_literal_count_(0), |
| 120 expected_properties_(0), | 290 expected_properties_(0), |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 146 | 316 |
| 147 // Private constructor only used in PreParseProgram. | 317 // Private constructor only used in PreParseProgram. |
| 148 PreParser(i::JavaScriptScanner* scanner, | 318 PreParser(i::JavaScriptScanner* scanner, |
| 149 i::ParserRecorder* log, | 319 i::ParserRecorder* log, |
| 150 uintptr_t stack_limit, | 320 uintptr_t stack_limit, |
| 151 bool allow_lazy) | 321 bool allow_lazy) |
| 152 : scanner_(scanner), | 322 : scanner_(scanner), |
| 153 log_(log), | 323 log_(log), |
| 154 scope_(NULL), | 324 scope_(NULL), |
| 155 stack_limit_(stack_limit), | 325 stack_limit_(stack_limit), |
| 326 strict_mode_violation_location_(i::Scanner::Location::invalid()), | |
| 327 strict_mode_violation_type_(NULL), | |
| 156 stack_overflow_(false), | 328 stack_overflow_(false), |
| 157 allow_lazy_(true), | 329 allow_lazy_(true), |
| 158 parenthesized_function_(false) { } | 330 parenthesized_function_(false) { } |
| 159 | 331 |
| 160 // Preparse the program. Only called in PreParseProgram after creating | 332 // Preparse the program. Only called in PreParseProgram after creating |
| 161 // the instance. | 333 // the instance. |
| 162 PreParseResult PreParse() { | 334 PreParseResult PreParse() { |
| 163 Scope top_scope(&scope_, kTopLevelScope); | 335 Scope top_scope(&scope_, kTopLevelScope); |
| 164 bool ok = true; | 336 bool ok = true; |
| 165 int start_position = scanner_->peek_location().beg_pos; | 337 int start_position = scanner_->peek_location().beg_pos; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 } | 429 } |
| 258 return scanner_->Next(); | 430 return scanner_->Next(); |
| 259 } | 431 } |
| 260 | 432 |
| 261 bool peek_any_identifier(); | 433 bool peek_any_identifier(); |
| 262 | 434 |
| 263 void set_strict_mode() { | 435 void set_strict_mode() { |
| 264 scope_->set_strict(); | 436 scope_->set_strict(); |
| 265 } | 437 } |
| 266 | 438 |
| 267 bool is_strict_mode() { return scope_->is_strict(); } | 439 bool strict_mode() { return scope_->is_strict(); } |
| 268 | 440 |
| 269 void Consume(i::Token::Value token) { Next(); } | 441 void Consume(i::Token::Value token) { Next(); } |
| 270 | 442 |
| 271 void Expect(i::Token::Value token, bool* ok) { | 443 void Expect(i::Token::Value token, bool* ok) { |
| 272 if (Next() != token) { | 444 if (Next() != token) { |
| 273 *ok = false; | 445 *ok = false; |
| 274 } | 446 } |
| 275 } | 447 } |
| 276 | 448 |
| 277 bool Check(i::Token::Value token) { | 449 bool Check(i::Token::Value token) { |
| 278 i::Token::Value next = peek(); | 450 i::Token::Value next = peek(); |
| 279 if (next == token) { | 451 if (next == token) { |
| 280 Consume(next); | 452 Consume(next); |
| 281 return true; | 453 return true; |
| 282 } | 454 } |
| 283 return false; | 455 return false; |
| 284 } | 456 } |
| 285 void ExpectSemicolon(bool* ok); | 457 void ExpectSemicolon(bool* ok); |
| 286 | 458 |
| 287 static int Precedence(i::Token::Value tok, bool accept_IN); | 459 static int Precedence(i::Token::Value tok, bool accept_IN); |
| 288 | 460 |
| 461 void SetStrictModeViolation(i::Scanner::Location, | |
| 462 const char* type, | |
| 463 bool *ok); | |
| 464 | |
| 465 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); | |
| 466 | |
| 467 void StrictModeIdentifierViolation(i::Scanner::Location, | |
| 468 const char* eval_args_type, | |
| 469 Identifier identifier, | |
| 470 bool* ok); | |
| 471 | |
| 289 i::JavaScriptScanner* scanner_; | 472 i::JavaScriptScanner* scanner_; |
| 290 i::ParserRecorder* log_; | 473 i::ParserRecorder* log_; |
| 291 Scope* scope_; | 474 Scope* scope_; |
| 292 uintptr_t stack_limit_; | 475 uintptr_t stack_limit_; |
| 476 i::Scanner::Location strict_mode_violation_location_; | |
| 477 const char* strict_mode_violation_type_; | |
| 293 bool stack_overflow_; | 478 bool stack_overflow_; |
| 294 bool allow_lazy_; | 479 bool allow_lazy_; |
| 295 bool parenthesized_function_; | 480 bool parenthesized_function_; |
| 296 }; | 481 }; |
| 297 } } // v8::preparser | 482 } } // v8::preparser |
| 298 | 483 |
| 299 #endif // V8_PREPARSER_H | 484 #endif // V8_PREPARSER_H |
| OLD | NEW |