Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1653)

Side by Side Diff: src/jsregexp.cc

Issue 10682: Inverted character classes (Closed)
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/jsregexp.h ('k') | src/list.h » ('j') | src/utils.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 SKIP_WRITE_BARRIER); 684 SKIP_WRITE_BARRIER);
685 array->set(kNumberOfRegistersOffset, 685 array->set(kNumberOfRegistersOffset,
686 Smi::FromInt(next_register_), 686 Smi::FromInt(next_register_),
687 SKIP_WRITE_BARRIER); 687 SKIP_WRITE_BARRIER);
688 Handle<Object> code = macro_assembler->GetCode(); 688 Handle<Object> code = macro_assembler->GetCode();
689 work_list_ = NULL; 689 work_list_ = NULL;
690 return array; 690 return array;
691 } 691 }
692 692
693 693
694 #define FOR_EACH_NODE_TYPE(VISIT) \
695 VISIT(End) \
696 VISIT(Atom) \
697 VISIT(Action) \
698 VISIT(Choice) \
699 VISIT(Backreference) \
700 VISIT(CharacterClass)
701
702
703 void RegExpNode::GoTo(RegExpCompiler* compiler) { 694 void RegExpNode::GoTo(RegExpCompiler* compiler) {
704 if (label.is_bound()) { 695 if (label.is_bound()) {
705 compiler->macro_assembler()->GoTo(&label); 696 compiler->macro_assembler()->GoTo(&label);
706 } else { 697 } else {
707 Emit(compiler); 698 Emit(compiler);
708 } 699 }
709 } 700 }
710 701
711 702
712 void RegExpNode::EmitAddress(RegExpCompiler* compiler) { 703 void RegExpNode::EmitAddress(RegExpCompiler* compiler) {
713 compiler->macro_assembler()->EmitOrLink(&label); 704 compiler->macro_assembler()->EmitOrLink(&label);
714 } 705 }
715 706
716 707
717 class SeqRegExpNode: public RegExpNode {
718 public:
719 explicit SeqRegExpNode(RegExpNode* on_success)
720 : on_success_(on_success) { }
721 RegExpNode* on_success() { return on_success_; }
722 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); }
723 private:
724 RegExpNode* on_success_;
725 };
726
727
728 class EndNode: public RegExpNode {
729 public:
730 enum Action { ACCEPT, BACKTRACK };
731 virtual void Accept(NodeVisitor* visitor);
732 static EndNode* GetAccept() { return &kAccept; }
733 static EndNode* GetBacktrack() { return &kBacktrack; }
734 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); }
735 private:
736 explicit EndNode(Action action) : action_(action) { }
737 Action action_;
738 static EndNode kAccept;
739 static EndNode kBacktrack;
740 };
741
742
743 EndNode EndNode::kAccept(ACCEPT); 708 EndNode EndNode::kAccept(ACCEPT);
744 EndNode EndNode::kBacktrack(BACKTRACK); 709 EndNode EndNode::kBacktrack(BACKTRACK);
745 710
746 711
747 class AtomNode: public SeqRegExpNode {
748 public:
749 AtomNode(Vector<const uc16> data,
750 RegExpNode* on_success,
751 RegExpNode* on_failure)
752 : SeqRegExpNode(on_success),
753 on_failure_(on_failure),
754 data_(data) { }
755 virtual void Accept(NodeVisitor* visitor);
756 Vector<const uc16> data() { return data_; }
757 RegExpNode* on_failure() { return on_failure_; }
758 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); }
759 private:
760 RegExpNode* on_failure_;
761 Vector<const uc16> data_;
762 };
763
764
765 class BackreferenceNode: public SeqRegExpNode {
766 public:
767 BackreferenceNode(int start_reg,
768 int end_reg,
769 RegExpNode* on_success,
770 RegExpNode* on_failure)
771 : SeqRegExpNode(on_success),
772 on_failure_(on_failure),
773 start_reg_(start_reg),
774 end_reg_(end_reg) { }
775 virtual void Accept(NodeVisitor* visitor);
776 RegExpNode* on_failure() { return on_failure_; }
777 int start_register() { return start_reg_; }
778 int end_register() { return end_reg_; }
779 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); }
780 private:
781 RegExpNode* on_failure_;
782 int start_reg_;
783 int end_reg_;
784 };
785
786
787 class CharacterClassNode: public SeqRegExpNode {
788 public:
789 CharacterClassNode(ZoneList<CharacterRange>* ranges,
790 bool is_negated,
791 RegExpNode* on_success,
792 RegExpNode* on_failure)
793 : SeqRegExpNode(on_success),
794 on_failure_(on_failure),
795 ranges_(ranges),
796 is_negated_(is_negated ) { }
797 virtual void Accept(NodeVisitor* visitor);
798 ZoneList<CharacterRange>* ranges() { return ranges_; }
799 bool is_negated() { return is_negated_; }
800 RegExpNode* on_failure() { return on_failure_; }
801 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); }
802 static void AddInverseToTable(List<CharacterRange> ranges,
803 DispatchTable* table,
804 int index);
805 private:
806 RegExpNode* on_failure_;
807 ZoneList<CharacterRange>* ranges_;
808 bool is_negated_;
809 };
810
811
812 class Guard: public ZoneObject {
813 public:
814 enum Relation { LT, GEQ };
815 Guard(int reg, Relation op, int value)
816 : reg_(reg),
817 op_(op),
818 value_(value) { }
819 int reg() { return reg_; }
820 Relation op() { return op_; }
821 int value() { return value_; }
822 private:
823 int reg_;
824 Relation op_;
825 int value_;
826 };
827
828
829 class GuardedAlternative {
830 public:
831 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { }
832 void AddGuard(Guard* guard);
833 RegExpNode* node() { return node_; }
834 ZoneList<Guard*>* guards() { return guards_; }
835 private:
836 RegExpNode* node_;
837 ZoneList<Guard*>* guards_;
838 };
839
840
841 void GuardedAlternative::AddGuard(Guard* guard) { 712 void GuardedAlternative::AddGuard(Guard* guard) {
842 if (guards_ == NULL) 713 if (guards_ == NULL)
843 guards_ = new ZoneList<Guard*>(1); 714 guards_ = new ZoneList<Guard*>(1);
844 guards_->Add(guard); 715 guards_->Add(guard);
845 } 716 }
846 717
847 718
848 class ChoiceNode: public RegExpNode {
849 public:
850 explicit ChoiceNode(int expected_size, RegExpNode* on_failure)
851 : on_failure_(on_failure),
852 choices_(new ZoneList<GuardedAlternative>(expected_size)),
853 visited_(false) { }
854 virtual void Accept(NodeVisitor* visitor);
855 void AddChild(GuardedAlternative node) { choices()->Add(node); }
856 ZoneList<GuardedAlternative>* choices() { return choices_; }
857 DispatchTable* table() { return &table_; }
858 RegExpNode* on_failure() { return on_failure_; }
859 virtual void Emit(RegExpCompiler* compiler);
860 bool visited() { return visited_; }
861 void set_visited(bool value) { visited_ = value; }
862 private:
863 RegExpNode* on_failure_;
864 ZoneList<GuardedAlternative>* choices_;
865 DispatchTable table_;
866 bool visited_;
867 };
868
869
870 class ActionNode: public SeqRegExpNode {
871 public:
872 enum Type {
873 STORE_REGISTER,
874 INCREMENT_REGISTER,
875 STORE_POSITION,
876 RESTORE_POSITION,
877 BEGIN_SUBMATCH,
878 ESCAPE_SUBMATCH,
879 END_SUBMATCH
880 };
881 static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success);
882 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
883 static ActionNode* StorePosition(int reg, RegExpNode* on_success);
884 static ActionNode* RestorePosition(int reg, RegExpNode* on_success);
885 static ActionNode* BeginSubmatch(RegExpNode* on_success);
886 static ActionNode* EscapeSubmatch(RegExpNode* on_success);
887 static ActionNode* EndSubmatch(RegExpNode* on_success);
888 virtual void Accept(NodeVisitor* visitor);
889 virtual void Emit(RegExpCompiler* compiler);
890 private:
891 union {
892 struct {
893 int reg;
894 int value;
895 } u_store_register;
896 struct {
897 int reg;
898 } u_increment_register;
899 struct {
900 int reg;
901 } u_position_register;
902 } data_;
903 ActionNode(Type type, RegExpNode* on_success)
904 : SeqRegExpNode(on_success),
905 type_(type) { }
906 Type type_;
907 friend class DotPrinter;
908 };
909
910
911 ActionNode* ActionNode::StoreRegister(int reg, 719 ActionNode* ActionNode::StoreRegister(int reg,
912 int val, 720 int val,
913 RegExpNode* on_success) { 721 RegExpNode* on_success) {
914 ActionNode* result = new ActionNode(STORE_REGISTER, on_success); 722 ActionNode* result = new ActionNode(STORE_REGISTER, on_success);
915 result->data_.u_store_register.reg = reg; 723 result->data_.u_store_register.reg = reg;
916 result->data_.u_store_register.value = val; 724 result->data_.u_store_register.value = val;
917 return result; 725 return result;
918 } 726 }
919 727
920 728
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
1701 data.table()->ForEach(AddDispatchRange(this)); 1509 data.table()->ForEach(AddDispatchRange(this));
1702 } 1510 }
1703 } 1511 }
1704 1512
1705 1513
1706 void Analysis::VisitBackreference(BackreferenceNode* that) { 1514 void Analysis::VisitBackreference(BackreferenceNode* that) {
1707 UNIMPLEMENTED(); 1515 UNIMPLEMENTED();
1708 } 1516 }
1709 1517
1710 1518
1519
1520 static int CompareRangeByFrom(const CharacterRange* a,
1521 const CharacterRange* b) {
1522 return Spaceship<uc16>(a->from(), b->from());
1523 }
1524
1525
1526 void CharacterClassNode::AddInverseToTable(ZoneList<CharacterRange>* ranges,
1527 DispatchTable* table,
1528 int index) {
1529 ranges->Sort(CompareRangeByFrom);
1530 uc16 last = 0;
1531 for (int i = 0; i < ranges->length(); i++) {
1532 CharacterRange range = ranges->at(i);
1533 if (last < range.from())
1534 table->AddRange(CharacterRange(last, range.from() - 1), index);
1535 if (range.to() >= last) {
1536 if (range.to() == 0xFFFF) {
1537 last = 0xFFFF;
1538 break;
1539 } else {
1540 last = range.to() + 1;
1541 }
1542 }
1543 }
1544 if (last < 0xFFFF)
1545 table->AddRange(CharacterRange(last, 0xFFFF), index);
Erik Corry 2008/11/13 11:45:43 I think this goes wrong if range.to() for the last
Christian Plesner Hansen 2008/11/13 11:58:37 Good point. I've fixed it and added a test.
1546 }
1547
1548
1711 void Analysis::VisitCharacterClass(CharacterClassNode* that) { 1549 void Analysis::VisitCharacterClass(CharacterClassNode* that) {
1712 if (table() != NULL) { 1550 if (table() != NULL) {
1713 int index = choice_index(); 1551 int index = choice_index();
1714 ZoneList<CharacterRange>* ranges = that->ranges(); 1552 ZoneList<CharacterRange>* ranges = that->ranges();
1715 for (int i = 0; i < ranges->length(); i++) { 1553 if (that->is_negated()) {
1716 CharacterRange range = ranges->at(i); 1554 CharacterClassNode::AddInverseToTable(ranges, table(), index);
1717 table()->AddRange(range, index); 1555 } else {
1556 for (int i = 0; i < ranges->length(); i++) {
1557 CharacterRange range = ranges->at(i);
1558 table()->AddRange(range, index);
1559 }
1718 } 1560 }
1719 } 1561 }
1720 AnalysisBuilder outgoing(this); 1562 AnalysisBuilder outgoing(this);
1721 outgoing.set_table(NULL); 1563 outgoing.set_table(NULL);
1722 outgoing.Analyze(that->on_success()); 1564 outgoing.Analyze(that->on_success());
1723 } 1565 }
1724 1566
1725 1567
1726 void Analysis::VisitAtom(AtomNode* that) { 1568 void Analysis::VisitAtom(AtomNode* that) {
1727 if (table() != NULL) { 1569 if (table() != NULL) {
(...skipping 27 matching lines...) Expand all
1755 analysis.Analyze(node); 1597 analysis.Analyze(node);
1756 return node; 1598 return node;
1757 } 1599 }
1758 1600
1759 1601
1760 RegExpMacroAssembler::~RegExpMacroAssembler() { 1602 RegExpMacroAssembler::~RegExpMacroAssembler() {
1761 } 1603 }
1762 1604
1763 1605
1764 }} // namespace v8::internal 1606 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/list.h » ('j') | src/utils.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698