Added initial support for recursive expressions.

Updated docs and tests accordingly.

[SVN r54994]
This commit is contained in:
John Maddock
2009-07-17 10:23:50 +00:00
parent 02a629baf7
commit 5a6bc29d7c
44 changed files with 1013 additions and 264 deletions

View File

@ -127,10 +127,21 @@ struct saved_single_repeat : public saved_state
: saved_state(arg_id), count(c), rep(r), last_position(lp){}
};
template <class Results>
struct saved_recursion : public saved_state
{
saved_recursion(int id, const re_syntax_base* p, Results* pr)
: saved_state(14), recursion_id(id), preturn_address(p), results(*pr)
{}
int recursion_id;
const re_syntax_base* preturn_address;
Results results;
};
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
{
static matcher_proc_type const s_match_vtable[29] =
static matcher_proc_type const s_match_vtable[30] =
{
(&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
&perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
@ -165,6 +176,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
&perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
&perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
&perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
&perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
};
push_recursion_stopper();
@ -316,10 +328,26 @@ inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(st
m_backup_state = pmp;
}
template <class BidiIterator, class Allocator, class traits>
inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int id, const re_syntax_base* p, results_type* presults)
{
saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
{
extend_stack();
pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
--pmp;
}
(void) new (pmp)saved_recursion<results_type>(id, p, presults);
m_backup_state = pmp;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
{
int index = static_cast<const re_brace*>(pstate)->index;
icase = static_cast<const re_brace*>(pstate)->icase;
switch(index)
{
case 0:
@ -859,6 +887,100 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
#endif
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{
BOOST_ASSERT(pstate->type == syntax_element_recurse);
//
// Backup call stack:
//
push_recursion_pop();
//
// Set new call stack:
//
if(recursion_stack_position >= static_cast<int>(sizeof(recursion_stack)/sizeof(recursion_stack[0])))
{
return false;
}
recursion_stack[recursion_stack_position].preturn_address = pstate->next.p;
recursion_stack[recursion_stack_position].results = *m_presult;
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index;
++recursion_stack_position;
//BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id);
return true;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
{
int index = static_cast<const re_brace*>(pstate)->index;
icase = static_cast<const re_brace*>(pstate)->icase;
if(index > 0)
{
if((m_match_flags & match_nosubs) == 0)
{
m_presult->set_second(position, index);
}
if(recursion_stack_position)
{
if(index == recursion_stack[recursion_stack_position-1].id)
{
--recursion_stack_position;
pstate = recursion_stack[recursion_stack_position].preturn_address;
*m_presult = recursion_stack[recursion_stack_position].results;
push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results);
}
}
}
else if((index < 0) && (index != -4))
{
// matched forward lookahead:
pstate = 0;
return true;
}
pstate = pstate->next.p;
return true;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
{
if(recursion_stack_position)
{
BOOST_ASSERT(0 == recursion_stack[recursion_stack_position-1].id);
--recursion_stack_position;
pstate = recursion_stack[recursion_stack_position].preturn_address;
*m_presult = recursion_stack[recursion_stack_position].results;
push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results);
return true;
}
if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
return false;
if((m_match_flags & match_all) && (position != last))
return false;
if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
return false;
m_presult->set_second(position);
pstate = 0;
m_has_found_match = true;
if((m_match_flags & match_posix) == match_posix)
{
m_result.maybe_assign(*m_presult);
if((m_match_flags & match_any) == 0)
return false;
}
#ifdef BOOST_REGEX_MATCH_EXTRA
if(match_extra & m_match_flags)
{
for(unsigned i = 0; i < m_presult->size(); ++i)
if((*m_presult)[i].matched)
((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
}
#endif
return true;
}
/****************************************************************************
Unwind and associated proceedures follow, these perform what normal stack
@ -869,7 +991,7 @@ unwinding does in the recursive implementation.
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
{
static unwind_proc_type const s_unwind_table[14] =
static unwind_proc_type const s_unwind_table[18] =
{
&perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
@ -885,6 +1007,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
&perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
};
m_recursive_result = have_match;
@ -1388,6 +1512,106 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(boo
return r;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
{
saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
if(!r)
{
recursion_stack[recursion_stack_position].id = pmp->recursion_id;
recursion_stack[recursion_stack_position].preturn_address = pmp->preturn_address;
recursion_stack[recursion_stack_position].results = pmp->results;
++recursion_stack_position;
}
boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp;
return true;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
{
saved_state* pmp = static_cast<saved_state*>(m_backup_state);
if(!r)
{
--recursion_stack_position;
}
boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp;
return true;
}
template <class BidiIterator, class Allocator, class traits>
void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
{
saved_state* pmp = static_cast<saved_state*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
{
extend_stack();
pmp = static_cast<saved_state*>(m_backup_state);
--pmp;
}
(void) new (pmp)saved_state(15);
m_backup_state = pmp;
}
/*
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
{
saved_state* pmp = static_cast<saved_state*>(m_backup_state);
if(!r)
{
--parenthesis_stack_position;
}
boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp;
return true;
}
template <class BidiIterator, class Allocator, class traits>
void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
{
saved_state* pmp = static_cast<saved_state*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
{
extend_stack();
pmp = static_cast<saved_state*>(m_backup_state);
--pmp;
}
(void) new (pmp)saved_state(16);
m_backup_state = pmp;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
{
saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
if(!r)
{
parenthesis_stack[parenthesis_stack_position++] = pmp->position;
}
boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp;
return true;
}
template <class BidiIterator, class Allocator, class traits>
inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
{
saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
{
extend_stack();
pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
--pmp;
}
(void) new (pmp)saved_position<BidiIterator>(0, p, 17);
m_backup_state = pmp;
}
*/
} // namespace re_detail
} // namespace boost