forked from boostorg/regex
Added support for conditional expressions.
[SVN r22744]
This commit is contained in:
1 parent
d2c3ec6d57
commit
b5cf51fbc6
9 files changed
+201
-16
No files matched your search
@@ -1127,6 +1127,7 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
std::ptrdiff_t last_alt_point = m_alt_insert_point;
|
||||
this->m_pdata->m_data.align();
|
||||
m_alt_insert_point = this->m_pdata->m_data.size();
|
||||
std::ptrdiff_t expected_alt_point = m_alt_insert_point;
|
||||
//
|
||||
// select the actual extension used:
|
||||
//
|
||||
@@ -1191,6 +1192,48 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
this->m_pdata->m_data.align();
|
||||
m_alt_insert_point = this->m_pdata->m_data.size();
|
||||
break;
|
||||
case regex_constants::syntax_open_mark:
|
||||
{
|
||||
// a conditional expression:
|
||||
pb->index = markid = -4;
|
||||
if(++m_position == m_end)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
int v = this->m_traits.toi(m_position, m_end, 10);
|
||||
if(v > 0)
|
||||
{
|
||||
re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
|
||||
br->index = v;
|
||||
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
if(++m_position == m_end)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
}
|
||||
else
|
||||
{
|
||||
// verify that we have a lookahead or lookbehind assert:
|
||||
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
if(++m_position == m_end)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word)
|
||||
{
|
||||
if(++m_position == m_end)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
|
||||
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
m_position -= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
|
||||
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
m_position -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
}
|
||||
@@ -1221,6 +1264,19 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
}
|
||||
}
|
||||
//
|
||||
// verify that if this is conditional expression, that we do have
|
||||
// an alternative, if not add one:
|
||||
//
|
||||
if(markid == -4)
|
||||
{
|
||||
re_syntax_base* b = this->getaddress(expected_alt_point);
|
||||
if(b->type != syntax_element_alt)
|
||||
{
|
||||
re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt)));
|
||||
alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt);
|
||||
}
|
||||
}
|
||||
//
|
||||
// append closing parenthesis state:
|
||||
//
|
||||
pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
|
||||
|
||||
@@ -334,6 +334,7 @@ private:
|
||||
bool match_dot_repeat_fast();
|
||||
bool match_dot_repeat_slow();
|
||||
bool match_backstep();
|
||||
bool match_assert_backref();
|
||||
bool backtrack_till_match(unsigned count);
|
||||
|
||||
// find procs stored in s_find_vtable:
|
||||
|
||||
@@ -81,11 +81,11 @@ void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std
|
||||
difference_type dist = boost::re_detail::distance(base, last);
|
||||
traits_size_type states = static_cast<traits_size_type>(re.size());
|
||||
states *= states;
|
||||
difference_type lim = (std::numeric_limits<difference_type>::max)() - 1000 - states;
|
||||
difference_type lim = (std::numeric_limits<difference_type>::max)() - 100000 - states;
|
||||
if(dist > (difference_type)(lim / states))
|
||||
max_state_count = lim;
|
||||
else
|
||||
max_state_count = 1000 + states * dist;
|
||||
max_state_count = 100000 + states * dist;
|
||||
}
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*)
|
||||
@@ -294,7 +294,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
|
||||
if((m_match_flags & match_nosubs) == 0)
|
||||
m_presult->set_second(position, index);
|
||||
}
|
||||
else if(index < 0)
|
||||
else if((index < 0) && (index != -4))
|
||||
{
|
||||
// matched forward lookahead:
|
||||
pstate = 0;
|
||||
@@ -670,6 +670,14 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep()
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
|
||||
{
|
||||
// return true if marked sub-expression N has been matched:
|
||||
pstate = pstate->next.p;
|
||||
return (*m_presult)[static_cast<const re_brace*>(pstate)->index].matched;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ struct saved_single_repeat : public saved_state
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
{
|
||||
static matcher_proc_type const s_match_vtable[27] =
|
||||
static matcher_proc_type const s_match_vtable[28] =
|
||||
{
|
||||
(&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
||||
@@ -142,6 +142,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
||||
};
|
||||
|
||||
push_recursion_stopper();
|
||||
@@ -344,6 +345,37 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
case -4:
|
||||
{
|
||||
// conditional expression:
|
||||
const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
|
||||
BOOST_ASSERT(alt->type == syntax_element_alt);
|
||||
pstate = alt->next.p;
|
||||
if(pstate->type == syntax_element_assert_backref)
|
||||
{
|
||||
if(!match_assert_backref())
|
||||
pstate = alt->alt.p;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// zero width assertion, have to match this recursively:
|
||||
BOOST_ASSERT(pstate->type == syntax_element_startmark);
|
||||
bool negated = static_cast<const re_brace*>(pstate)->index == -2;
|
||||
BidiIterator saved_position = position;
|
||||
const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
||||
pstate = pstate->next.p->next.p;
|
||||
bool r = match_all_states();
|
||||
position = saved_position;
|
||||
if(negated)
|
||||
r = !r;
|
||||
if(r)
|
||||
pstate = next_pstate;
|
||||
else
|
||||
pstate = alt->alt.p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(index > 0);
|
||||
@@ -929,8 +961,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
std::size_t count = pmp->count;
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
assert(rep->next.p != 0);
|
||||
assert(rep->alt.p != 0);
|
||||
|
||||
count -= rep->min;
|
||||
|
||||
@@ -979,8 +1011,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool
|
||||
const re_repeat* rep = pmp->rep;
|
||||
std::size_t count = pmp->count;
|
||||
assert(rep->type == syntax_element_dot_rep);
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
assert(rep->next.p != 0);
|
||||
assert(rep->alt.p != 0);
|
||||
assert(rep->next.p->type == syntax_element_wild);
|
||||
|
||||
assert(count < rep->max);
|
||||
@@ -1097,8 +1129,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
|
||||
position = pmp->last_position;
|
||||
|
||||
assert(rep->type == syntax_element_char_rep);
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
assert(rep->next.p != 0);
|
||||
assert(rep->alt.p != 0);
|
||||
assert(rep->next.p->type == syntax_element_literal);
|
||||
assert(count < rep->max);
|
||||
|
||||
@@ -1161,8 +1193,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool
|
||||
position = pmp->last_position;
|
||||
|
||||
assert(rep->type == syntax_element_short_set_rep);
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
assert(rep->next.p != 0);
|
||||
assert(rep->alt.p != 0);
|
||||
assert(rep->next.p->type == syntax_element_set);
|
||||
assert(count < rep->max);
|
||||
|
||||
@@ -1226,8 +1258,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool
|
||||
position = pmp->last_position;
|
||||
|
||||
assert(rep->type == syntax_element_long_set_rep);
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
assert(rep->next.p != 0);
|
||||
assert(rep->alt.p != 0);
|
||||
assert(rep->next.p->type == syntax_element_long_set);
|
||||
assert(position != last);
|
||||
assert(count < rep->max);
|
||||
|
||||
@@ -48,7 +48,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[27] =
|
||||
static matcher_proc_type const s_match_vtable[28] =
|
||||
{
|
||||
(&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
||||
@@ -77,6 +77,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
||||
};
|
||||
|
||||
if(state_count > max_state_count)
|
||||
@@ -157,6 +158,37 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case -4:
|
||||
{
|
||||
// conditional expression:
|
||||
const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
|
||||
BOOST_ASSERT(alt->type == syntax_element_alt);
|
||||
pstate = alt->next.p;
|
||||
if(pstate->type == syntax_element_assert_backref)
|
||||
{
|
||||
if(!match_assert_backref())
|
||||
pstate = alt->alt.p;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// zero width assertion, have to match this recursively:
|
||||
BOOST_ASSERT(pstate->type == syntax_element_startmark);
|
||||
bool negated = static_cast<const re_brace*>(pstate)->index == -2;
|
||||
BidiIterator saved_position = position;
|
||||
const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
||||
pstate = pstate->next.p->next.p;
|
||||
bool r = match_all_states();
|
||||
position = saved_position;
|
||||
if(negated)
|
||||
r = !r;
|
||||
if(r)
|
||||
pstate = next_pstate;
|
||||
else
|
||||
pstate = alt->alt.p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(index > 0);
|
||||
|
||||
@@ -108,7 +108,9 @@ enum syntax_element_type
|
||||
syntax_element_short_set_rep = syntax_element_char_rep + 1,
|
||||
syntax_element_long_set_rep = syntax_element_short_set_rep + 1,
|
||||
// a backstep for lookbehind repeats:
|
||||
syntax_element_backstep = syntax_element_long_set_rep + 1
|
||||
syntax_element_backstep = syntax_element_long_set_rep + 1,
|
||||
// an assertion that a mark was matched:
|
||||
syntax_element_assert_backref = syntax_element_backstep +1
|
||||
};
|
||||
|
||||
#ifdef BOOST_REGEX_DEBUG
|
||||
|
||||
Reference in new issue
Block a user