Added support for \g \K and \R.

[SVN r52592]
This commit is contained in:
John Maddock
2009-04-25 17:32:49 +00:00
parent 7b10b5dac5
commit 30941e330d
42 changed files with 795 additions and 519 deletions

View File

@ -720,7 +720,89 @@ escape_type_class_jump:
return true;
}
fail(regex_constants::error_ctype, m_position - m_base);
return false;
}
case regex_constants::escape_type_reset_start_mark:
if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
{
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
pb->index = -5;
this->m_pdata->m_data.align();
++m_position;
return true;
}
goto escape_type_class_jump;
case regex_constants::escape_type_line_ending:
if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
{
const charT* e = get_escape_R_string<charT>();
const charT* old_position = m_position;
const charT* old_end = m_end;
const charT* old_base = m_base;
m_position = e;
m_base = e;
m_end = e + traits::length(e);
bool r = parse_all();
m_position = ++old_position;
m_end = old_end;
m_base = old_base;
return r;
}
goto escape_type_class_jump;
case regex_constants::escape_type_extended_backref:
if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
{
bool have_brace = false;
bool negative = false;
if(++m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
// maybe have \g{ddd}
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
{
if(++m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
have_brace = true;
}
negative = (*m_position == static_cast<charT>('-'));
if((negative) && (++m_position == m_end))
{
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
const charT* pc = m_position;
int i = this->m_traits.toi(pc, m_end, 10);
if(negative)
i = 1 + m_mark_count - i;
if((i > 0) && (this->m_backrefs & (1u << (i-1))))
{
m_position = pc;
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
pb->index = i;
}
else
{
fail(regex_constants::error_backref, m_position - m_end);
return false;
}
m_position = pc;
if(have_brace)
{
if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
{
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
++m_position;
}
return true;
}
goto escape_type_class_jump;
case regex_constants::escape_type_control_v:
if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
goto escape_type_class_jump;
@ -1499,7 +1581,7 @@ charT basic_regex_parser<charT, traits>::unescape_character()
int i = this->m_traits.toi(m_position, m_end, 16);
if((m_position == m_end)
|| (i < 0)
|| ((std::numeric_limits<charT>::is_specialized) && (charT(i) > (std::numeric_limits<charT>::max)()))
|| ((std::numeric_limits<charT>::is_specialized) && (i > (int)(std::numeric_limits<charT>::max)()))
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
{
fail(regex_constants::error_badbrace, m_position - m_base);

View File

@ -230,13 +230,13 @@ public:
m_null.matched = false;
}
void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true)
void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
{
pos += 2;
BOOST_ASSERT(m_subs.size() > pos);
m_subs[pos].second = i;
m_subs[pos].matched = m;
if(pos == 2)
if((pos == 2) && !escape_k)
{
m_subs[0].first = i;
m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
@ -284,11 +284,18 @@ public:
m_subs[n].matched = false;
}
}
void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos)
void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos, bool escape_k = false)
{
BOOST_ASSERT(pos+2 < m_subs.size());
if(pos)
if(pos || escape_k)
{
m_subs[pos+2].first = i;
if(escape_k)
{
m_subs[1].second = i;
m_subs[1].matched = (m_subs[1].first != m_subs[1].second);
}
}
else
set_first(i);
}

View File

@ -205,7 +205,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
verify_options(re.flags(), m_match_flags);
if(0 == match_prefix())
return false;
return m_result[0].second == last;
return (m_result[0].second == last) && (m_result[0].first == base);
#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS)
}

View File

@ -213,7 +213,7 @@ void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
template <class BidiIterator, class Allocator, class traits>
inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
{
BOOST_ASSERT(index);
//BOOST_ASSERT(index);
saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
@ -404,6 +404,13 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
break;
}
}
case -5:
{
push_matched_paren(0, (*m_presult)[0]);
m_presult->set_first(position, 0, true);
pstate = pstate->next.p;
break;
}
default:
{
BOOST_ASSERT(index > 0);
@ -911,8 +918,8 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match
// restore previous values if no match was found:
if(have_match == false)
{
m_presult->set_first(pmp->sub.first, pmp->index);
m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched);
m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
}
#ifdef BOOST_REGEX_MATCH_EXTRA
//

View File

@ -51,8 +51,8 @@ public:
template <class A>
void restore(match_results<BidiIterator, A>& w)
{
w.set_first(sub.first, index);
w.set_second(sub.second, index, sub.matched);
w.set_first(sub.first, index, index == 0);
w.set_second(sub.second, index, sub.matched, index == 0);
}
const sub_match<BidiIterator>& get() { return sub; }
};
@ -209,6 +209,17 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
break;
}
}
case -5:
{
// Reset start of $0, since we have a \K escape
backup_subex<BidiIterator> sub(*m_presult, 0);
m_presult->set_first(position, 0, true);
pstate = pstate->next.p;
r = match_all_states();
if(r == false)
sub.restore(*m_presult);
break;
}
default:
{
BOOST_ASSERT(index > 0);

View File

@ -317,6 +317,28 @@ int global_toi(const charT*& p1, const charT* p2, int radix, const traits& t)
return result;
}
template <class charT>
inline const charT* get_escape_R_string()
{
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4309)
#endif
static const charT e1[] = { '(', '?', '>', '\x0D', '\x0A', '?',
'|', '[', '\x0A', '\x0B', '\x0C', '\x85', '\\', 'x', '{', '2', '0', '2', '8', '}',
'\\', 'x', '{', '2', '0', '2', '9', '}', ']', ')' };
static const charT e2[] = { '(', '?', '>', '\x0D', '\x0A', '?',
'|', '[', '\x0A', '\x0B', '\x0C', '\x85', ']', ')' };
charT c = static_cast<charT>(0x2029u);
bool b = (static_cast<unsigned>(c) == 0x2029u);
return (b ? e1 : e2);
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}
} // re_detail
} // boost

View File

@ -92,8 +92,11 @@ static const escape_syntax_type escape_type_G = 52; /
static const escape_syntax_type escape_type_property = 54; // for \p
static const escape_syntax_type escape_type_not_property = 55; // for \P
static const escape_syntax_type escape_type_named_char = 56; // for \N
static const escape_syntax_type escape_type_extended_backref = 57; // for \g
static const escape_syntax_type escape_type_reset_start_mark = 58; // for \K
static const escape_syntax_type escape_type_line_ending = 59; // for \R
static const escape_syntax_type syntax_max = 57;
static const escape_syntax_type syntax_max = 60;
}
}