Author: [EMAIL PROTECTED]
Date: Fri Nov 14 04:45:27 2008
New Revision: 755

Modified:
    branches/experimental/regexp2000/src/ast.cc
    branches/experimental/regexp2000/src/ast.h
    branches/experimental/regexp2000/src/jsregexp-inl.h
    branches/experimental/regexp2000/src/jsregexp.cc
    branches/experimental/regexp2000/src/jsregexp.h
    branches/experimental/regexp2000/src/string-stream.cc
    branches/experimental/regexp2000/src/string-stream.h
    branches/experimental/regexp2000/test/cctest/test-regexp.cc

Log:
- Split analysis into two separate visitors, one for filling out
   dispatch tables and one for propagating information about nodes.
- Integrated dispatch table layout in dot graphs.
- Renamed choice/child nodes of disjunctions to alternatives, for
   uniformity.


Modified: branches/experimental/regexp2000/src/ast.cc
==============================================================================
--- branches/experimental/regexp2000/src/ast.cc (original)
+++ branches/experimental/regexp2000/src/ast.cc Fri Nov 14 04:45:27 2008
@@ -233,9 +233,9 @@

  void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void*  
data) {
    stream()->Add("(|");
-  for (int i = 0; i <  that->nodes()->length(); i++) {
+  for (int i = 0; i <  that->alternatives()->length(); i++) {
      stream()->Add(" ");
-    that->nodes()->at(i)->Accept(this, data);
+    that->alternatives()->at(i)->Accept(this, data);
    }
    stream()->Add(")");
    return NULL;

Modified: branches/experimental/regexp2000/src/ast.h
==============================================================================
--- branches/experimental/regexp2000/src/ast.h  (original)
+++ branches/experimental/regexp2000/src/ast.h  Fri Nov 14 04:45:27 2008
@@ -1225,15 +1225,16 @@

  class RegExpDisjunction: public RegExpTree {
   public:
-  explicit RegExpDisjunction(ZoneList<RegExpTree*>* nodes) : nodes_(nodes)  
{ }
+  explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
+    : alternatives_(alternatives) { }
    virtual void* Accept(RegExpVisitor* visitor, void* data);
    virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                               RegExpNode* on_success,
                               RegExpNode* on_failure);
    virtual RegExpDisjunction* AsDisjunction();
-  ZoneList<RegExpTree*>* nodes() { return nodes_; }
+  ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
   private:
-  ZoneList<RegExpTree*>* nodes_;
+  ZoneList<RegExpTree*>* alternatives_;
  };


@@ -1274,7 +1275,7 @@
    RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated)
      : ranges_(ranges),
        is_negated_(is_negated) { }
-  RegExpCharacterClass(uc16 type)
+  explicit RegExpCharacterClass(uc16 type)
      : ranges_(new ZoneList<CharacterRange>(2)),
        is_negated_(false) {
      CharacterRange::AddClassEscape(type, ranges_);

Modified: branches/experimental/regexp2000/src/jsregexp-inl.h
==============================================================================
--- branches/experimental/regexp2000/src/jsregexp-inl.h (original)
+++ branches/experimental/regexp2000/src/jsregexp-inl.h Fri Nov 14 04:45:27  
2008
@@ -245,10 +245,10 @@


  template <typename Node, class Callback>
-static void DoForEach(Node* node, Callback callback) {
+static void DoForEach(Node* node, Callback* callback) {
    if (node == NULL) return;
    DoForEach<Node, Callback>(node->left(), callback);
-  callback.Call(node->key(), node->value());
+  callback->Call(node->key(), node->value());
    DoForEach<Node, Callback>(node->right(), callback);
  }


Modified: branches/experimental/regexp2000/src/jsregexp.cc
==============================================================================
--- branches/experimental/regexp2000/src/jsregexp.cc    (original)
+++ branches/experimental/regexp2000/src/jsregexp.cc    Fri Nov 14 04:45:27  
2008
@@ -788,14 +788,9 @@
  // New regular expression engine


-class DotPrinter;
-
-
  class RegExpCompiler {
   public:
-  explicit RegExpCompiler(int capture_count)
-    : next_register_(2 * capture_count),
-      work_list_(NULL) { }
+  explicit RegExpCompiler(int capture_count);

    int AllocateRegister() { return next_register_++; }

@@ -806,10 +801,17 @@

    inline void AddWork(RegExpNode* node) { work_list_->Add(node); }

-  RegExpMacroAssembler* macro_assembler() {
-    return macro_assembler_;
-  }
+  static const int kImplementationOffset = 0;
+  static const int kNumberOfRegistersOffset = 0;
+  static const int kCodeOffset = 1;
+
+  RegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
+  EndNode* accept() { return accept_; }
+  EndNode* backtrack() { return backtrack_; }
+
   private:
+  EndNode* accept_;
+  EndNode* backtrack_;
    int next_register_;
    List<RegExpNode*>* work_list_;
    RegExpMacroAssembler* macro_assembler_;
@@ -818,6 +820,14 @@

  // Attempts to compile the regexp using a Regexp2000 code generator.   
Returns
  // a fixed array or a null handle depending on whether it succeeded.
+RegExpCompiler::RegExpCompiler(int capture_count)
+  : next_register_(2 * capture_count),
+    work_list_(NULL) {
+  accept_ = new EndNode(EndNode::ACCEPT);
+  backtrack_ = new EndNode(EndNode::BACKTRACK);
+}
+
+
  Handle<FixedArray> RegExpCompiler::Assemble(
      RegExpMacroAssembler* macro_assembler,
      RegExpNode* start,
@@ -871,10 +881,6 @@
  }


-EndNode EndNode::kAccept(ACCEPT);
-EndNode EndNode::kBacktrack(BACKTRACK);
-
-
  bool EndNode::Emit(RegExpCompiler* compiler) {
    switch (action_) {
      case ACCEPT:
@@ -941,16 +947,6 @@
  }


-class NodeVisitor {
- public:
-  virtual ~NodeVisitor() { }
-#define DECLARE_VISIT(Type)                                          \
-  virtual void Visit##Type(Type##Node* that) = 0;
-FOR_EACH_NODE_TYPE(DECLARE_VISIT)
-#undef DECLARE_VISIT
-};
-
-
  #define DEFINE_ACCEPT(Type)                                          \
    void Type##Node::Accept(NodeVisitor* visitor) {                    \
      visitor->Visit##Type(this);                                      \
@@ -1043,7 +1039,7 @@
          break;
      }
    }
-  stream()->Add("\"]; \n");
+  stream()->Add("\"];\n");
    Visit(node);
    stream()->Add("}\n");
    printf("%s", *(stream()->ToCString()));
@@ -1059,42 +1055,77 @@


  void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
-  if (on_failure == EndNode::GetBacktrack()) return;
+  if (on_failure->IsBacktrack()) return;
    stream()->Add("  n%p -> n%p [style=dotted];\n", from, on_failure);
    Visit(on_failure);
  }


-void DotPrinter::VisitChoice(ChoiceNode* that) {
-  stream()->Add("  n%p [label=\"? (%p)\"];\n", that, that);
-  PrintOnFailure(that, that->on_failure());
-  for (int i = 0; i < that->choices()->length(); i++) {
-    GuardedAlternative alt = that->choices()->at(i);
-    stream()->Add("  n%p -> n%p [label=\"%i",
-                       that,
-                       alt.node(),
-                       i);
-    if (alt.guards() != NULL) {
-      stream()->Add(" [");
-      for (int j = 0; j < alt.guards()->length(); j++) {
-        if (j > 0) stream()->Add(" ");
-        Guard* guard = alt.guards()->at(j);
-        switch (guard->op()) {
-          case Guard::GEQ:
-            stream()->Add("$%i &#8805; %i", guard->reg(), guard->value());
-            break;
-          case Guard::LT:
-            stream()->Add("$%i < %i", guard->reg(), guard->value());
-            break;
-        }
+class TableEntryBodyPrinter {
+ public:
+  TableEntryBodyPrinter(StringStream* stream, ChoiceNode* choice)
+    : stream_(stream), choice_(choice) { }
+  void Call(uc16 from, DispatchTable::Entry entry) {
+    OutSet* out_set = entry.out_set();
+    for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
+      if (out_set->Get(i)) {
+        stream()->Add("    n%p:s%io%i -> n%p;\n",
+                      choice(),
+                      from,
+                      i,
+                      choice()->alternatives()->at(i).node());
        }
-      stream()->Add("]");
      }
-    stream()->Add("\"];\n");
-    that->choices()->at(i).node()->Accept(this);
    }
-  OS::PrintError("--- %p ---\n", static_cast<void*>(that));
-  that->table()->Dump();
+ private:
+  StringStream* stream() { return stream_; }
+  ChoiceNode* choice() { return choice_; }
+  StringStream* stream_;
+  ChoiceNode* choice_;
+};
+
+
+class TableEntryHeaderPrinter {
+ public:
+  explicit TableEntryHeaderPrinter(StringStream* stream)
+    : first_(true), stream_(stream) { }
+  void Call(uc16 from, DispatchTable::Entry entry) {
+    if (first_) {
+      first_ = false;
+    } else {
+      stream()->Add("|");
+    }
+    stream()->Add("{%k-%k|{", from, from, entry.to());
+    OutSet* out_set = entry.out_set();
+    int priority = 0;
+    for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
+      if (out_set->Get(i)) {
+        if (priority > 0) stream()->Add("|");
+        stream()->Add("<s%io%i> %i", from, i, priority);
+        priority++;
+      }
+    }
+    stream()->Add("}}");
+  }
+ private:
+  bool first_;
+  StringStream* stream() { return stream_; }
+  StringStream* stream_;
+};
+
+
+void DotPrinter::VisitChoice(ChoiceNode* that) {
+  stream()->Add("  n%p [shape=Mrecord, label=\"", that);
+  TableEntryHeaderPrinter header_printer(stream());
+  that->table()->ForEach(&header_printer);
+  stream()->Add("\"]\n", that);
+  TableEntryBodyPrinter body_printer(stream(), that);
+  that->table()->ForEach(&body_printer);
+  PrintOnFailure(that, that->on_failure());
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    GuardedAlternative alt = that->alternatives()->at(i);
+    alt.node()->Accept(this);
+  }
  }


@@ -1206,7 +1237,8 @@
  void DispatchTable::Dump() {
    HeapStringAllocator alloc;
    StringStream stream(&alloc);
-  tree()->ForEach(DispatchTableDumper(&stream));
+  DispatchTableDumper dumper(&stream);
+  tree()->ForEach(&dumper);
    OS::PrintError("%s", *stream.ToCString());
  }

@@ -1244,14 +1276,14 @@
  RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
                                        RegExpNode* on_success,
                                        RegExpNode* on_failure) {
-  ZoneList<RegExpTree*>* children = nodes();
-  int length = children->length();
+  ZoneList<RegExpTree*>* alternatives = this->alternatives();
+  int length = alternatives->length();
    ChoiceNode* result = new ChoiceNode(length, on_failure);
    for (int i = 0; i < length; i++) {
-    GuardedAlternative child(children->at(i)->ToNode(compiler,
-                                                     on_success,
-                                                     on_failure));
-    result->AddChild(child);
+    GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler,
+                                                               on_success,
+                                                                
on_failure));
+    result->AddAlternative(alternative);
    }
    return result;
  }
@@ -1310,11 +1342,11 @@
      rest_alt.AddGuard(rest_guard);
    }
    if (is_greedy) {
-    center->AddChild(body_alt);
-    center->AddChild(rest_alt);
+    center->AddAlternative(body_alt);
+    center->AddAlternative(rest_alt);
    } else {
-    center->AddChild(rest_alt);
-    center->AddChild(body_alt);
+    center->AddAlternative(rest_alt);
+    center->AddAlternative(body_alt);
    }
    if (needs_counter) {
      return ActionNode::StoreRegister(reg_ctr, 0, center);
@@ -1385,9 +1417,9 @@
          new ChoiceNode(1, ActionNode::EndSubmatch(on_success));
      RegExpNode* body_node = body()->ToNode(compiler,
          ActionNode::EscapeSubmatch(on_failure),
-        EndNode::GetBacktrack());
+        compiler->backtrack());
      GuardedAlternative body_alt(body_node);
-    try_node->AddChild(body_alt);
+    try_node->AddAlternative(body_alt);
      return ActionNode::BeginSubmatch(try_node);
    }
  }
@@ -1654,78 +1686,115 @@
  // Analysis


-class Analysis: public NodeVisitor {
- public:
-  explicit Analysis(RegExpCompiler* compiler)
-    : compiler_(compiler),
-      table_(NULL),
-      choice_index_(-1) { }
-  DispatchTable* table() { return table_; }
-  RegExpCompiler* compiler() { return compiler_; }
-  int choice_index() { return choice_index_; }
-  void Analyze(RegExpNode* node) { node->Accept(this); }
-#define DECLARE_VISIT(Type)                                          \
-  virtual void Visit##Type(Type##Node* that);
-FOR_EACH_NODE_TYPE(DECLARE_VISIT)
-#undef DECLARE_VISIT
- protected:
-  explicit Analysis(Analysis* prev) { *this = *prev; }
-  RegExpCompiler* compiler_;
-  DispatchTable *table_;
-  int choice_index_;
-};
+void Analysis::EnsureAnalyzed(RegExpNode* that) {
+  if (that->info()->been_analyzed || that->info()->being_analyzed)
+    return;
+  that->info()->being_analyzed = true;
+  that->Accept(this);
+  that->info()->being_analyzed = false;
+  that->info()->been_analyzed = true;
+}


-// A subclass of analysis data that allows fields to be set.  Anyone
-// who needs to create new analysis data creates an instance of this
-// class, configures it, and then passes it on as an AnalysisData
-// which doesn't allow its fields to be changed.
-class AnalysisBuilder: public Analysis {
- public:
-  explicit AnalysisBuilder(Analysis* prev) : Analysis(prev) { }
-  void set_table(DispatchTable* value) { table_ = value; }
-  void set_choice_index(int value) { choice_index_ = value; }
-};
+void Analysis::VisitEnd(EndNode* that) {
+  // nothing to do
+}


-void Analysis::VisitEnd(EndNode* that) {
+void Analysis::VisitAtom(AtomNode* that) {
+  EnsureAnalyzed(that->on_success());
+  EnsureAnalyzed(that->on_failure());
+}
+
+
+void Analysis::VisitAction(ActionNode* that) {
+  RegExpNode* next = that->on_success();
+  EnsureAnalyzed(next);
+  that->info()->propagate_line = next->info()->propagate_line;
+  that->info()->propagate_word = next->info()->propagate_word;
+}
+
+
+void Analysis::VisitChoice(ChoiceNode* that) {
+  NodeInfo* info = that->info();
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    RegExpNode* node = that->alternatives()->at(i).node();
+    EnsureAnalyzed(node);
+    info->propagate_line |= node->info()->propagate_line;
+    info->propagate_word |= node->info()->propagate_word;
+  }
+  if (!that->table_calculated()) {
+    DispatchTableConstructor cons(that->table());
+    cons.BuildTable(that);
+  }
+  EnsureAnalyzed(that->on_failure());
+}
+
+
+void Analysis::VisitBackreference(BackreferenceNode* that) {
+  EnsureAnalyzed(that->on_success());
+  EnsureAnalyzed(that->on_failure());
+}
+
+
+void Analysis::VisitCharacterClass(CharacterClassNode* that) {
+  EnsureAnalyzed(that->on_success());
+  EnsureAnalyzed(that->on_failure());
+}
+
+
+// -------------------------------------------------------------------
+// Dispatch table construction
+
+
+void DispatchTableConstructor::VisitEnd(EndNode* that) {
    // nothing to do
  }


+void DispatchTableConstructor::BuildTable(ChoiceNode* node) {
+  ASSERT(!node->table_calculated());
+  node->set_being_calculated(true);
+  ZoneList<GuardedAlternative>* alternatives = node->alternatives();
+  for (int i = 0; i < alternatives->length(); i++) {
+    set_choice_index(i);
+    alternatives->at(i).node()->Accept(this);
+  }
+  node->set_being_calculated(false);
+  node->set_table_calculated(true);
+}
+
+
  class AddDispatchRange {
   public:
-  explicit AddDispatchRange(Analysis* analysis) : analysis_(analysis) { }
+  explicit AddDispatchRange(DispatchTableConstructor* constructor)
+    : constructor_(constructor) { }
    void Call(uc32 from, DispatchTable::Entry entry);
   private:
-  Analysis* analysis_;
+  DispatchTableConstructor* constructor_;
  };


  void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) {
    CharacterRange range(from, entry.to());
-  analysis_->table()->AddRange(range, analysis_->choice_index());
+  constructor_->AddRange(range);
  }


-void Analysis::VisitChoice(ChoiceNode* node) {
-  if (node->visited()) return;
-  node->set_visited(true);
-  ZoneList<GuardedAlternative>* choices = node->choices();
-  AnalysisBuilder data(this);
-  data.set_table(node->table());
-  for (int i = 0; i < choices->length(); i++) {
-    data.set_choice_index(i);
-    data.Analyze(choices->at(i).node());
-  }
-  node->set_visited(false);
-  if (table() != NULL) {
-    data.table()->ForEach(AddDispatchRange(this));
+void DispatchTableConstructor::VisitChoice(ChoiceNode* node) {
+  if (node->being_calculated())
+    return;
+  if (!node->table_calculated()) {
+    DispatchTableConstructor constructor(node->table());
+    constructor.BuildTable(node);
    }
+  ASSERT(node->table_calculated());
+  AddDispatchRange adder(this);
+  node->table()->ForEach(&adder);
  }


-void Analysis::VisitBackreference(BackreferenceNode* that) {
+void DispatchTableConstructor::VisitBackreference(BackreferenceNode* that)  
{
    UNIMPLEMENTED();
  }

@@ -1737,15 +1806,13 @@
  }


-void CharacterClassNode::AddInverseToTable(ZoneList<CharacterRange>*  
ranges,
-                                           DispatchTable* table,
-                                           int index) {
+void DispatchTableConstructor::AddInverse(ZoneList<CharacterRange>*  
ranges) {
    ranges->Sort(CompareRangeByFrom);
    uc16 last = 0;
    for (int i = 0; i < ranges->length(); i++) {
      CharacterRange range = ranges->at(i);
      if (last < range.from())
-      table->AddRange(CharacterRange(last, range.from() - 1), index);
+      AddRange(CharacterRange(last, range.from() - 1));
      if (range.to() >= last) {
        if (range.to() == 0xFFFF) {
          return;
@@ -1754,42 +1821,30 @@
        }
      }
    }
-  table->AddRange(CharacterRange(last, 0xFFFF), index);
+  AddRange(CharacterRange(last, 0xFFFF));
  }


-void Analysis::VisitCharacterClass(CharacterClassNode* that) {
-  if (table() != NULL) {
-    int index = choice_index();
-    ZoneList<CharacterRange>* ranges = that->ranges();
-    if (that->is_negated()) {
-      CharacterClassNode::AddInverseToTable(ranges, table(), index);
-    } else {
-      for (int i = 0; i < ranges->length(); i++) {
-        CharacterRange range = ranges->at(i);
-        table()->AddRange(range, index);
-      }
+void DispatchTableConstructor::VisitCharacterClass(CharacterClassNode*  
that) {
+  ZoneList<CharacterRange>* ranges = that->ranges();
+  if (that->is_negated()) {
+    AddInverse(ranges);
+  } else {
+    for (int i = 0; i < ranges->length(); i++) {
+      AddRange(ranges->at(i));
      }
    }
-  AnalysisBuilder outgoing(this);
-  outgoing.set_table(NULL);
-  outgoing.Analyze(that->on_success());
  }


-void Analysis::VisitAtom(AtomNode* that) {
-  if (table() != NULL) {
-    uc16 c = that->data()[0];
-    table()->AddRange(CharacterRange(c, c), choice_index());
-  }
-  AnalysisBuilder outgoing(this);
-  outgoing.set_table(NULL);
-  outgoing.Analyze(that->on_success());
+void DispatchTableConstructor::VisitAtom(AtomNode* that) {
+  uc16 c = that->data()[0];
+  AddRange(CharacterRange(c, c));
  }


-void Analysis::VisitAction(ActionNode* that) {
-  Analyze(that->on_success());
+void DispatchTableConstructor::VisitAction(ActionNode* that) {
+  that->on_success()->Accept(this);
  }


@@ -1801,8 +1856,8 @@
    RegExpNode* captured_body = RegExpCapture::ToNode(input->tree,
                                                      0,
                                                      &compiler,
-                                                    EndNode::GetAccept(),
-                                                     
EndNode::GetBacktrack());
+                                                    compiler.accept(),
+                                                    compiler.backtrack());
    // Add a .*? at the beginning, outside the body capture.
    // Note: We could choose to not add this if the regexp is anchored at
    //   the start of the input but I'm not sure how best to do that and
@@ -1814,10 +1869,10 @@
                                                new  
RegExpCharacterClass('.'),
                                                &compiler,
                                                captured_body,
-                                              EndNode::GetBacktrack());
+                                              compiler.backtrack());
    if (node_return != NULL) *node_return = node;
-  Analysis analysis(&compiler);
-  analysis.Analyze(node);
+  Analysis analysis;
+  analysis.EnsureAnalyzed(node);
    byte codes[10240];
    Re2kAssembler assembler(Vector<byte>(codes, 1024));
    RegExpMacroAssemblerRe2k macro_assembler(&assembler);

Modified: branches/experimental/regexp2000/src/jsregexp.h
==============================================================================
--- branches/experimental/regexp2000/src/jsregexp.h     (original)
+++ branches/experimental/regexp2000/src/jsregexp.h     Fri Nov 14 04:45:27 2008
@@ -205,7 +205,7 @@


  template <typename Node, class Callback>
-static void DoForEach(Node* node, Callback callback);
+static void DoForEach(Node* node, Callback* callback);


  // A zone splay tree.  The config type parameter encapsulates the
@@ -297,7 +297,7 @@
    };

    template <class Callback>
-  void ForEach(Callback c) {
+  void ForEach(Callback* c) {
      DoForEach<typename ZoneSplayTree<Config>::Node, Callback>(root_, c);
    }

@@ -376,7 +376,7 @@
    void Dump();

    template <typename Callback>
-  void ForEach(Callback callback) { return tree()->ForEach(callback); }
+  void ForEach(Callback* callback) { return tree()->ForEach(callback); }
   private:
    // There can't be a static empty set since it allocates its
    // successors in a zone and caches them.
@@ -396,6 +396,23 @@
    VISIT(CharacterClass)


+class NodeInfo {
+ public:
+  NodeInfo()
+    : being_analyzed(false),
+      been_analyzed(false),
+      propagate_word(false),
+      propagate_line(false) { }
+  bool being_analyzed: 1;
+  bool been_analyzed: 1;
+  bool propagate_word: 1;
+  bool propagate_line: 1;
+};
+
+
+STATIC_CHECK(sizeof(NodeInfo) <= sizeof(int));  // NOLINT
+
+
  class RegExpNode: public ZoneObject {
   public:
    virtual ~RegExpNode() { }
@@ -405,11 +422,15 @@
    // false for failure.
    bool GoTo(RegExpCompiler* compiler);
    void EmitAddress(RegExpCompiler* compiler);
+
    // Until the implementation is complete we will return true for success  
and
    // false for failure.
    virtual bool Emit(RegExpCompiler* compiler) = 0;
+  NodeInfo* info() { return &info_; }
+  virtual bool IsBacktrack() { return false; }
   private:
    Label label;
+  NodeInfo info_;
  };


@@ -533,15 +554,12 @@
  class EndNode: public RegExpNode {
   public:
    enum Action { ACCEPT, BACKTRACK };
+  explicit EndNode(Action action) : action_(action) { }
    virtual void Accept(NodeVisitor* visitor);
-  static EndNode* GetAccept() { return &kAccept; }
-  static EndNode* GetBacktrack() { return &kBacktrack; }
    virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool IsBacktrack() { return action_ == BACKTRACK; }
   private:
-  explicit EndNode(Action action) : action_(action) { }
    Action action_;
-  static EndNode kAccept;
-  static EndNode kBacktrack;
  };


@@ -578,21 +596,76 @@
   public:
    explicit ChoiceNode(int expected_size, RegExpNode* on_failure)
      : on_failure_(on_failure),
-      choices_(new ZoneList<GuardedAlternative>(expected_size)),
-      visited_(false) { }
+      alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
+      table_calculated_(false),
+      being_calculated_(false) { }
    virtual void Accept(NodeVisitor* visitor);
-  void AddChild(GuardedAlternative node) { choices()->Add(node); }
-  ZoneList<GuardedAlternative>* choices() { return choices_; }
+  void AddAlternative(GuardedAlternative node) {  
alternatives()->Add(node); }
+  ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
    DispatchTable* table() { return &table_; }
    RegExpNode* on_failure() { return on_failure_; }
    virtual bool Emit(RegExpCompiler* compiler);
-  bool visited() { return visited_; }
-  void set_visited(bool value) { visited_ = value; }
+  bool table_calculated() { return table_calculated_; }
+  void set_table_calculated(bool b) { table_calculated_ = b; }
+  bool being_calculated() { return being_calculated_; }
+  void set_being_calculated(bool b) { being_calculated_ = b; }
   private:
    RegExpNode* on_failure_;
-  ZoneList<GuardedAlternative>* choices_;
+  ZoneList<GuardedAlternative>* alternatives_;
    DispatchTable table_;
-  bool visited_;
+  bool table_calculated_;
+  bool being_calculated_;
+};
+
+
+class NodeVisitor {
+ public:
+  virtual ~NodeVisitor() { }
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that) = 0;
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+};
+
+
+// Node visitor used to add the start set of the alternatives to the
+// dispatch table of a choice node.
+class DispatchTableConstructor: public NodeVisitor {
+ public:
+  explicit DispatchTableConstructor(DispatchTable* table)
+    : table_(table),
+      choice_index_(-1) { }
+
+  void BuildTable(ChoiceNode* node);
+
+  void AddRange(CharacterRange range) {
+    table()->AddRange(range, choice_index_);
+  }
+
+  void AddInverse(ZoneList<CharacterRange>* ranges);
+
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  DispatchTable* table() { return table_; }
+  void set_choice_index(int value) { choice_index_ = value; }
+
+ protected:
+  DispatchTable *table_;
+  int choice_index_;
+};
+
+
+class Analysis: public NodeVisitor {
+ public:
+  void EnsureAnalyzed(RegExpNode* node);
+
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
  };


@@ -611,9 +684,6 @@
                                      bool ignore_case);
    static void DotPrint(const char* label, RegExpNode* node);
  };
-
-
-class RegExpCompiler;


  } }  // namespace v8::internal

Modified: branches/experimental/regexp2000/src/string-stream.cc
==============================================================================
--- branches/experimental/regexp2000/src/string-stream.cc       (original)
+++ branches/experimental/regexp2000/src/string-stream.cc       Fri Nov 14  
04:45:27 2008
@@ -233,6 +233,14 @@
  }


+void StringStream::Add(const char* format, FmtElm arg0, FmtElm arg1,
+                       FmtElm arg2, FmtElm arg3) {
+  const char argc = 4;
+  FmtElm argv[argc] = { arg0, arg1, arg2, arg3 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
  SmartPointer<const char> StringStream::ToCString() {
    char* str = NewArray<char>(length_ + 1);
    memcpy(str, buffer_, length_);

Modified: branches/experimental/regexp2000/src/string-stream.h
==============================================================================
--- branches/experimental/regexp2000/src/string-stream.h        (original)
+++ branches/experimental/regexp2000/src/string-stream.h        Fri Nov 14  
04:45:27 2008
@@ -116,6 +116,11 @@
    void Add(const char* format, FmtElm arg0);
    void Add(const char* format, FmtElm arg0, FmtElm arg1);
    void Add(const char* format, FmtElm arg0, FmtElm arg1, FmtElm arg2);
+  void Add(const char* format,
+           FmtElm arg0,
+           FmtElm arg1,
+           FmtElm arg2,
+           FmtElm arg3);

    // Getting the message out.
    void OutputToStdOut();

Modified: branches/experimental/regexp2000/test/cctest/test-regexp.cc
==============================================================================
--- branches/experimental/regexp2000/test/cctest/test-regexp.cc (original)
+++ branches/experimental/regexp2000/test/cctest/test-regexp.cc Fri Nov 14  
04:45:27 2008
@@ -679,7 +679,9 @@
        ranges->Add(CharacterRange(from, to));
      }
      DispatchTable table;
-    CharacterClassNode::AddInverseToTable(ranges, &table, 0);
+    DispatchTableConstructor cons(&table);
+    cons.set_choice_index(0);
+    cons.AddInverse(ranges);
      for (int i = 0; i < kLimit; i++) {
        bool is_on = false;
        for (int j = 0; !is_on && j < kRangeCount; j++)
@@ -693,7 +695,9 @@
            new ZoneList<CharacterRange>(1);
    ranges->Add(CharacterRange(0xFFF0, 0xFFFE));
    DispatchTable table;
-  CharacterClassNode::AddInverseToTable(ranges, &table, 0);
+  DispatchTableConstructor cons(&table);
+  cons.set_choice_index(0);
+  cons.AddInverse(ranges);
    CHECK(!table.Get(0xFFFE)->Get(0));
    CHECK(table.Get(0xFFFF)->Get(0));
  }

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to