diff options
| author | Maxime Coste <mawww@kakoune.org> | 2017-11-30 14:32:29 +0800 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2017-11-30 14:32:29 +0800 |
| commit | b91f43b031320ceae1fef489b30bee6ef68a2c8e (patch) | |
| tree | 34f98e632fcd5f6bc864c40d3f7c099242315408 /src/regex_impl.cc | |
| parent | c1f0efa3f424317a85ede4100136caf7d330f8e2 (diff) | |
Regex: optimize parsing a bit
Diffstat (limited to 'src/regex_impl.cc')
| -rw-r--r-- | src/regex_impl.cc | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 80243608..77f1bd2e 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -189,28 +189,16 @@ private: return {}; } - bool accept(StringView expected) + bool modifiers() { auto it = m_pos.base(); - for (auto expected_it = expected.begin(); expected_it != expected.end(); ++expected_it) + if (m_regex.end() - it >= 4 and *it++ == '(' and *it++ == '?') { - if (it == m_regex.end() or *it++ != *expected_it) + auto m = *it++; + if ((m != 'i' and m != 'I') or *it++ != ')') return false; - } - m_pos = Iterator{it, m_regex}; - return true; - } - - bool modifiers() - { - if (accept("(?i)")) - { - m_ignore_case = true; - return true; - } - if (accept("(?I)")) - { - m_ignore_case = false; + m_ignore_case = (m == 'i'); + m_pos = Iterator{it, m_regex}; return true; } return false; @@ -239,25 +227,29 @@ private: break; case '(': { - Optional<ParsedRegex::Op> lookaround_op; - constexpr struct { StringView prefix; ParsedRegex::Op op; } lookarounds[] = { - { "(?=", ParsedRegex::LookAhead }, - { "(?!", ParsedRegex::NegativeLookAhead }, - { "(?<=", ParsedRegex::LookBehind }, - { "(?<!", ParsedRegex::NegativeLookBehind } - }; - for (auto& lookaround : lookarounds) + auto it = m_pos.base()+1; + if (m_regex.end() - it <= 2 or *it++ != '?') + return {}; + + ParsedRegex::Op op; + switch (*it++) { - if (accept(lookaround.prefix)) + case '=': op = ParsedRegex::LookAhead; break; + case '!': op = ParsedRegex::NegativeLookAhead; break; + case '<': { - lookaround_op = lookaround.op; + switch (*it++) + { + case '=': op = ParsedRegex::LookBehind; break; + case '!': op = ParsedRegex::NegativeLookBehind; break; + default: return {}; + } break; } + default: return {}; } - if (not lookaround_op) - return {}; - - NodeIndex lookaround = alternative(*lookaround_op); + m_pos = Iterator{it, m_regex}; + NodeIndex lookaround = alternative(op); if (at_end() or *m_pos++ != ')') parse_error("unclosed parenthesis"); @@ -273,15 +265,20 @@ private: if (at_end()) return {}; - const Codepoint cp = *m_pos; - switch (cp) + switch (const Codepoint cp = *m_pos) { case '.': ++m_pos; return new_node(ParsedRegex::AnyChar); case '(': { - ++m_pos; - const bool capture = not accept("?:"); - NodeIndex content = disjunction(capture ? m_parsed_regex.capture_count++ : -1); + auto captures = [this, it = (++m_pos).base()]() mutable { + if (m_regex.end() - it >= 2 and *it++ == '?' and *it++ == ':') + { + m_pos = Iterator{it, m_regex}; + return false; + } + return true; + }; + NodeIndex content = disjunction(captures() ? m_parsed_regex.capture_count++ : -1); if (at_end() or *m_pos++ != ')') parse_error("unclosed parenthesis"); return content; |
