This commit is contained in:
jzmaddock
2015-03-24 19:09:17 +00:00
parent 74d6318135
commit 297e87360c
4 changed files with 32 additions and 13 deletions

View File

@ -253,23 +253,40 @@ class repeater_count
int state_id;
std::size_t count; // the number of iterations so far
BidiIterator start_pos; // where the last repeat started
repeater_count* unwind_until(int n, repeater_count* p, int current_recursion_id)
{
while(p && (p->state_id != n))
{
if(-2 - current_recursion_id == p->state_id)
return 0;
p = p->next;
if(p && (p->state_id < 0))
{
p = unwind_until(p->state_id, p, current_recursion_id);
if(!p)
return p;
p = p->next;
}
}
return p;
}
public:
repeater_count(repeater_count** s) : stack(s), next(0), state_id(-1), count(0), start_pos() {}
repeater_count(int i, repeater_count** s, BidiIterator start)
repeater_count(int i, repeater_count** s, BidiIterator start, int current_recursion_id)
: start_pos(start)
{
state_id = i;
stack = s;
next = *stack;
*stack = this;
if(state_id > next->state_id)
if((state_id > next->state_id) && (next->state_id >= 0))
count = 0;
else
{
repeater_count* p = next;
while(p && (p->state_id != state_id))
p = p->next;
p = unwind_until(state_id, p, current_recursion_id);
if(p)
{
count = p->count;

View File

@ -87,8 +87,8 @@ template <class BidiIterator>
struct saved_repeater : public saved_state
{
repeater_count<BidiIterator> count;
saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start)
: saved_state(saved_state_repeater_count), count(i,s,start){}
saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
: saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
};
struct saved_extra_block : public saved_state
@ -309,7 +309,7 @@ inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(i
pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
--pmp;
}
(void) new (pmp)saved_repeater<BidiIterator>(i, s, position);
(void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : (INT_MIN + 3));
m_backup_state = pmp;
}
@ -923,12 +923,12 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
recursion_stack.push_back(recursion_info<results_type>());
recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack.back().results = *m_presult;
if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
}
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
//if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
}
return true;
}
@ -952,6 +952,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
*m_presult = recursion_stack.back().results;
push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
recursion_stack.pop_back();
push_repeater_count(-(2 + index), &next_count);
}
}
}

View File

@ -308,7 +308,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
// Always copy the repeat count, so that the state is restored
// when we exit this scope:
//
repeater_count<BidiIterator> r(rep->state_id, &next_count, position);
repeater_count<BidiIterator> r(rep->state_id, &next_count, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : INT_MIN + 3);
//
// If we've had at least one repeat already, and the last one
// matched the NULL string then set the repeat count to