| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 to_(to) { | 145 to_(to) { |
| 146 } | 146 } |
| 147 static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges); | 147 static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges); |
| 148 static inline CharacterRange Singleton(uc16 value) { | 148 static inline CharacterRange Singleton(uc16 value) { |
| 149 return CharacterRange(value, value); | 149 return CharacterRange(value, value); |
| 150 } | 150 } |
| 151 static inline CharacterRange Range(uc16 from, uc16 to) { | 151 static inline CharacterRange Range(uc16 from, uc16 to) { |
| 152 ASSERT(from <= to); | 152 ASSERT(from <= to); |
| 153 return CharacterRange(from, to); | 153 return CharacterRange(from, to); |
| 154 } | 154 } |
| 155 uc16 from() { return from_; } | 155 bool Contains(uc16 i) { return from_ <= i && i <= to_; } |
| 156 uc16 from() const { return from_; } |
| 156 void set_from(uc16 value) { from_ = value; } | 157 void set_from(uc16 value) { from_ = value; } |
| 157 uc16 to() { return to_; } | 158 uc16 to() const { return to_; } |
| 158 void set_to(uc16 value) { to_ = value; } | 159 void set_to(uc16 value) { to_ = value; } |
| 159 bool is_valid() { return from_ <= to_; } | 160 bool is_valid() { return from_ <= to_; } |
| 160 bool IsSingleton() { return (from_ == to_); } | 161 bool IsSingleton() { return (from_ == to_); } |
| 161 private: | 162 private: |
| 162 uc16 from_; | 163 uc16 from_; |
| 163 uc16 to_; | 164 uc16 to_; |
| 164 }; | 165 }; |
| 165 | 166 |
| 166 | 167 |
| 167 template <typename Node, class Callback> | 168 template <typename Node, class Callback> |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 private: | 341 private: |
| 341 // There can't be a static empty set since it allocates its | 342 // There can't be a static empty set since it allocates its |
| 342 // successors in a zone and caches them. | 343 // successors in a zone and caches them. |
| 343 OutSet* empty() { return &empty_; } | 344 OutSet* empty() { return &empty_; } |
| 344 OutSet empty_; | 345 OutSet empty_; |
| 345 ZoneSplayTree<Config>* tree() { return &tree_; } | 346 ZoneSplayTree<Config>* tree() { return &tree_; } |
| 346 ZoneSplayTree<Config> tree_; | 347 ZoneSplayTree<Config> tree_; |
| 347 }; | 348 }; |
| 348 | 349 |
| 349 | 350 |
| 351 #define FOR_EACH_NODE_TYPE(VISIT) \ |
| 352 VISIT(End) \ |
| 353 VISIT(Atom) \ |
| 354 VISIT(Action) \ |
| 355 VISIT(Choice) \ |
| 356 VISIT(Backreference) \ |
| 357 VISIT(CharacterClass) |
| 358 |
| 359 |
| 360 class RegExpNode: public ZoneObject { |
| 361 public: |
| 362 virtual ~RegExpNode() { } |
| 363 virtual void Accept(NodeVisitor* visitor) = 0; |
| 364 // Generates a goto to this node or actually generates the code at this point. |
| 365 void GoTo(RegExpCompiler* compiler); |
| 366 void EmitAddress(RegExpCompiler* compiler); |
| 367 virtual void Emit(RegExpCompiler* compiler) = 0; |
| 368 private: |
| 369 Label label; |
| 370 }; |
| 371 |
| 372 |
| 373 class SeqRegExpNode: public RegExpNode { |
| 374 public: |
| 375 explicit SeqRegExpNode(RegExpNode* on_success) |
| 376 : on_success_(on_success) { } |
| 377 RegExpNode* on_success() { return on_success_; } |
| 378 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 379 private: |
| 380 RegExpNode* on_success_; |
| 381 }; |
| 382 |
| 383 |
| 384 class ActionNode: public SeqRegExpNode { |
| 385 public: |
| 386 enum Type { |
| 387 STORE_REGISTER, |
| 388 INCREMENT_REGISTER, |
| 389 STORE_POSITION, |
| 390 RESTORE_POSITION, |
| 391 BEGIN_SUBMATCH, |
| 392 ESCAPE_SUBMATCH, |
| 393 END_SUBMATCH |
| 394 }; |
| 395 static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success); |
| 396 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); |
| 397 static ActionNode* StorePosition(int reg, RegExpNode* on_success); |
| 398 static ActionNode* RestorePosition(int reg, RegExpNode* on_success); |
| 399 static ActionNode* BeginSubmatch(RegExpNode* on_success); |
| 400 static ActionNode* EscapeSubmatch(RegExpNode* on_success); |
| 401 static ActionNode* EndSubmatch(RegExpNode* on_success); |
| 402 virtual void Accept(NodeVisitor* visitor); |
| 403 virtual void Emit(RegExpCompiler* compiler); |
| 404 private: |
| 405 union { |
| 406 struct { |
| 407 int reg; |
| 408 int value; |
| 409 } u_store_register; |
| 410 struct { |
| 411 int reg; |
| 412 } u_increment_register; |
| 413 struct { |
| 414 int reg; |
| 415 } u_position_register; |
| 416 } data_; |
| 417 ActionNode(Type type, RegExpNode* on_success) |
| 418 : SeqRegExpNode(on_success), |
| 419 type_(type) { } |
| 420 Type type_; |
| 421 friend class DotPrinter; |
| 422 }; |
| 423 |
| 424 |
| 425 class AtomNode: public SeqRegExpNode { |
| 426 public: |
| 427 AtomNode(Vector<const uc16> data, |
| 428 RegExpNode* on_success, |
| 429 RegExpNode* on_failure) |
| 430 : SeqRegExpNode(on_success), |
| 431 on_failure_(on_failure), |
| 432 data_(data) { } |
| 433 virtual void Accept(NodeVisitor* visitor); |
| 434 Vector<const uc16> data() { return data_; } |
| 435 RegExpNode* on_failure() { return on_failure_; } |
| 436 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 437 private: |
| 438 RegExpNode* on_failure_; |
| 439 Vector<const uc16> data_; |
| 440 }; |
| 441 |
| 442 |
| 443 class BackreferenceNode: public SeqRegExpNode { |
| 444 public: |
| 445 BackreferenceNode(int start_reg, |
| 446 int end_reg, |
| 447 RegExpNode* on_success, |
| 448 RegExpNode* on_failure) |
| 449 : SeqRegExpNode(on_success), |
| 450 on_failure_(on_failure), |
| 451 start_reg_(start_reg), |
| 452 end_reg_(end_reg) { } |
| 453 virtual void Accept(NodeVisitor* visitor); |
| 454 RegExpNode* on_failure() { return on_failure_; } |
| 455 int start_register() { return start_reg_; } |
| 456 int end_register() { return end_reg_; } |
| 457 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 458 private: |
| 459 RegExpNode* on_failure_; |
| 460 int start_reg_; |
| 461 int end_reg_; |
| 462 }; |
| 463 |
| 464 |
| 465 class CharacterClassNode: public SeqRegExpNode { |
| 466 public: |
| 467 CharacterClassNode(ZoneList<CharacterRange>* ranges, |
| 468 bool is_negated, |
| 469 RegExpNode* on_success, |
| 470 RegExpNode* on_failure) |
| 471 : SeqRegExpNode(on_success), |
| 472 on_failure_(on_failure), |
| 473 ranges_(ranges), |
| 474 is_negated_(is_negated ) { } |
| 475 virtual void Accept(NodeVisitor* visitor); |
| 476 ZoneList<CharacterRange>* ranges() { return ranges_; } |
| 477 bool is_negated() { return is_negated_; } |
| 478 RegExpNode* on_failure() { return on_failure_; } |
| 479 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 480 static void AddInverseToTable(ZoneList<CharacterRange>* ranges, |
| 481 DispatchTable* table, |
| 482 int index); |
| 483 private: |
| 484 RegExpNode* on_failure_; |
| 485 ZoneList<CharacterRange>* ranges_; |
| 486 bool is_negated_; |
| 487 }; |
| 488 |
| 489 |
| 490 class EndNode: public RegExpNode { |
| 491 public: |
| 492 enum Action { ACCEPT, BACKTRACK }; |
| 493 virtual void Accept(NodeVisitor* visitor); |
| 494 static EndNode* GetAccept() { return &kAccept; } |
| 495 static EndNode* GetBacktrack() { return &kBacktrack; } |
| 496 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 497 private: |
| 498 explicit EndNode(Action action) : action_(action) { } |
| 499 Action action_; |
| 500 static EndNode kAccept; |
| 501 static EndNode kBacktrack; |
| 502 }; |
| 503 |
| 504 |
| 505 class Guard: public ZoneObject { |
| 506 public: |
| 507 enum Relation { LT, GEQ }; |
| 508 Guard(int reg, Relation op, int value) |
| 509 : reg_(reg), |
| 510 op_(op), |
| 511 value_(value) { } |
| 512 int reg() { return reg_; } |
| 513 Relation op() { return op_; } |
| 514 int value() { return value_; } |
| 515 private: |
| 516 int reg_; |
| 517 Relation op_; |
| 518 int value_; |
| 519 }; |
| 520 |
| 521 |
| 522 class GuardedAlternative { |
| 523 public: |
| 524 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { } |
| 525 void AddGuard(Guard* guard); |
| 526 RegExpNode* node() { return node_; } |
| 527 ZoneList<Guard*>* guards() { return guards_; } |
| 528 private: |
| 529 RegExpNode* node_; |
| 530 ZoneList<Guard*>* guards_; |
| 531 }; |
| 532 |
| 533 |
| 534 class ChoiceNode: public RegExpNode { |
| 535 public: |
| 536 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) |
| 537 : on_failure_(on_failure), |
| 538 choices_(new ZoneList<GuardedAlternative>(expected_size)), |
| 539 visited_(false) { } |
| 540 virtual void Accept(NodeVisitor* visitor); |
| 541 void AddChild(GuardedAlternative node) { choices()->Add(node); } |
| 542 ZoneList<GuardedAlternative>* choices() { return choices_; } |
| 543 DispatchTable* table() { return &table_; } |
| 544 RegExpNode* on_failure() { return on_failure_; } |
| 545 virtual void Emit(RegExpCompiler* compiler); |
| 546 bool visited() { return visited_; } |
| 547 void set_visited(bool value) { visited_ = value; } |
| 548 private: |
| 549 RegExpNode* on_failure_; |
| 550 ZoneList<GuardedAlternative>* choices_; |
| 551 DispatchTable table_; |
| 552 bool visited_; |
| 553 }; |
| 554 |
| 555 |
| 350 struct RegExpParseResult { | 556 struct RegExpParseResult { |
| 351 RegExpTree* tree; | 557 RegExpTree* tree; |
| 352 bool has_character_escapes; | 558 bool has_character_escapes; |
| 353 Handle<String> error; | 559 Handle<String> error; |
| 354 int capture_count; | 560 int capture_count; |
| 355 }; | 561 }; |
| 356 | 562 |
| 357 | 563 |
| 358 class RegExpEngine: public AllStatic { | 564 class RegExpEngine: public AllStatic { |
| 359 public: | 565 public: |
| 360 static RegExpNode* Compile(RegExpParseResult* input); | 566 static RegExpNode* Compile(RegExpParseResult* input); |
| 361 static void DotPrint(const char* label, RegExpNode* node); | 567 static void DotPrint(const char* label, RegExpNode* node); |
| 362 }; | 568 }; |
| 363 | 569 |
| 364 | 570 |
| 365 class RegExpCompiler; | 571 class RegExpCompiler; |
| 366 | 572 |
| 367 | 573 |
| 368 class RegExpNode: public ZoneObject { | |
| 369 public: | |
| 370 virtual ~RegExpNode() { } | |
| 371 virtual void Accept(NodeVisitor* visitor) = 0; | |
| 372 // Generates a goto to this node or actually generates the code at this point. | |
| 373 void GoTo(RegExpCompiler* compiler); | |
| 374 void EmitAddress(RegExpCompiler* compiler); | |
| 375 virtual void Emit(RegExpCompiler* compiler) = 0; | |
| 376 private: | |
| 377 Label label; | |
| 378 }; | |
| 379 | |
| 380 | |
| 381 } } // namespace v8::internal | 574 } } // namespace v8::internal |
| 382 | 575 |
| 383 #endif // V8_JSREGEXP_H_ | 576 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |