#undef DEFINE_ACCEPT
+void LoopChoiceNode::Accept(NodeVisitor* visitor) {
+ visitor->VisitLoopChoice(this);
+}
+
+
// -------------------------------------------------------------------
// Emit code.
}
+void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
+ ASSERT_EQ(loop_node_, NULL);
+ AddAlternative(alt);
+ loop_node_ = alt.node();
+}
+
+
+void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
+ ASSERT_EQ(continue_node_, NULL);
+ AddAlternative(alt);
+ continue_node_ = alt.node();
+}
+
+
bool LoopChoiceNode::Emit(RegExpCompiler* compiler,
GenerationVariant* variant) {
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
bool has_max = max < RegExpTree::kInfinity;
bool needs_counter = has_min || has_max;
int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1;
- ChoiceNode* center = new LoopChoiceNode(2);
+ LoopChoiceNode* center = new LoopChoiceNode();
RegExpNode* loop_return = needs_counter
? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
: static_cast<RegExpNode*>(center);
rest_alt.AddGuard(rest_guard);
}
if (is_greedy) {
- center->AddAlternative(body_alt);
- center->AddAlternative(rest_alt);
+ center->AddLoopAlternative(body_alt);
+ center->AddContinueAlternative(rest_alt);
} else {
- center->AddAlternative(rest_alt);
- center->AddAlternative(body_alt);
+ center->AddContinueAlternative(rest_alt);
+ center->AddLoopAlternative(body_alt);
}
if (needs_counter) {
return ActionNode::SetRegister(reg_ctr, 0, center);
}
+void AssertionPropagation::VisitLoopChoice(LoopChoiceNode* that) {
+ NodeInfo* info = that->info();
+ for (int i = 0; i < that->alternatives()->length(); i++) {
+ RegExpNode* node = that->alternatives()->at(i).node();
+ if (node != that->loop_node()) {
+ EnsureAnalyzed(node);
+ info->AddFromFollowing(node->info());
+ }
+ }
+ // Check the loop last since it may need the value of this node
+ // to get a correct result.
+ EnsureAnalyzed(that->loop_node());
+ info->AddFromFollowing(that->loop_node()->info());
+}
+
+
void AssertionPropagation::VisitBackReference(BackReferenceNode* that) {
EnsureAnalyzed(that->on_success());
}
class LoopChoiceNode: public ChoiceNode {
public:
- explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { }
+ explicit LoopChoiceNode()
+ : ChoiceNode(2),
+ loop_node_(NULL),
+ continue_node_(NULL) { }
+ void AddLoopAlternative(GuardedAlternative alt);
+ void AddContinueAlternative(GuardedAlternative alt);
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
+ RegExpNode* loop_node() { return loop_node_; }
+ RegExpNode* continue_node() { return continue_node_; }
+ virtual void Accept(NodeVisitor* visitor);
+
+ private:
+ // AddAlternative is made private for loop nodes because alternatives
+ // should not be added freely, we need to keep track of which node
+ // goes back to the node itself.
+ void AddAlternative(GuardedAlternative node) {
+ ChoiceNode::AddAlternative(node);
+ }
+
+ RegExpNode* loop_node_;
+ RegExpNode* continue_node_;
};
virtual void Visit##Type(Type##Node* that) = 0;
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
+ virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
};
virtual void Visit##Type(Type##Node* that);
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
+ virtual void VisitLoopChoice(LoopChoiceNode* that);
private:
bool ignore_case_;