mirror of
https://github.com/boostorg/regex.git
synced 2025-07-18 14:52:08 +02:00
Added initial support for recursive expressions.
Updated docs and tests accordingly. [SVN r54994]
This commit is contained in:
@ -60,7 +60,7 @@ public:
|
||||
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,
|
||||
@ -95,6 +95,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,
|
||||
};
|
||||
|
||||
if(state_count > max_state_count)
|
||||
@ -117,6 +118,7 @@ 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;
|
||||
bool r = true;
|
||||
switch(index)
|
||||
{
|
||||
@ -848,6 +850,127 @@ bool perl_matcher<BidiIterator, Allocator, traits>::backtrack_till_match(std::si
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
|
||||
{
|
||||
BOOST_ASSERT(pstate->type == syntax_element_recurse);
|
||||
//
|
||||
// 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;
|
||||
recursion_stack[recursion_stack_position].repeater_stack = next_count;
|
||||
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;
|
||||
|
||||
repeater_count<BidiIterator>* saved = next_count;
|
||||
repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those
|
||||
next_count = &r;
|
||||
bool result = match_all_states();
|
||||
next_count = saved;
|
||||
|
||||
if(!result)
|
||||
{
|
||||
--recursion_stack_position;
|
||||
next_count = recursion_stack[recursion_stack_position].repeater_stack;
|
||||
*m_presult = recursion_stack[recursion_stack_position].results;
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
recursion_info<results_type> saved = recursion_stack[recursion_stack_position];
|
||||
const re_syntax_base* saved_state = pstate = saved.preturn_address;
|
||||
repeater_count<BidiIterator>* saved_count = next_count;
|
||||
next_count = saved.repeater_stack;
|
||||
*m_presult = saved.results;
|
||||
if(!match_all_states())
|
||||
{
|
||||
recursion_stack[recursion_stack_position] = saved;
|
||||
++recursion_stack_position;
|
||||
next_count = saved_count;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((index < 0) && (index != -4))
|
||||
{
|
||||
// matched forward lookahead:
|
||||
pstate = 0;
|
||||
return true;
|
||||
}
|
||||
pstate = pstate ? pstate->next.p : 0;
|
||||
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;
|
||||
const re_syntax_base* saved_state = pstate = recursion_stack[recursion_stack_position].preturn_address;
|
||||
*m_presult = recursion_stack[recursion_stack_position].results;
|
||||
if(!match_all_states())
|
||||
{
|
||||
recursion_stack[recursion_stack_position].preturn_address = saved_state;
|
||||
recursion_stack[recursion_stack_position].results = *m_presult;
|
||||
++recursion_stack_position;
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace re_detail
|
||||
} // namespace boost
|
||||
#ifdef BOOST_MSVC
|
||||
|
Reference in New Issue
Block a user