Generate different parse_quoted_balanced for each quote pair

This seems to slightly improve parse speed which is where kakoune
spends most of its time during startup.
This commit is contained in:
Maxime Coste 2021-07-20 19:53:06 +10:00
parent a4dd89f214
commit e3957bb24c

View File

@ -131,7 +131,8 @@ ParseResult parse_quoted(ParseState& state, Codepoint delimiter)
return {str, false}; return {str, false};
} }
ParseResult parse_quoted_balanced(ParseState& state, char opening_delimiter, char closing_delimiter) template<char opening_delimiter, char closing_delimiter>
ParseResult parse_quoted_balanced(ParseState& state)
{ {
int level = 1; int level = 1;
const char* pos = state.pos; const char* pos = state.pos;
@ -255,8 +256,11 @@ Token parse_percent_token(ParseState& state, bool throw_on_unterminated)
Token::Type type = token_type(type_name, throw_on_unterminated); Token::Type type = token_type(type_name, throw_on_unterminated);
constexpr struct CharPair { char opening; char closing; } matching_pairs[] = { constexpr struct CharPair { char opening; char closing; ParseResult (*parse_func)(ParseState&); } matching_pairs[] = {
{ '(', ')' }, { '[', ']' }, { '{', '}' }, { '<', '>' } { '(', ')', parse_quoted_balanced<'(', ')'> },
{ '[', ']', parse_quoted_balanced<'[', ']'> },
{ '{', '}', parse_quoted_balanced<'{', '}'> },
{ '<', '>', parse_quoted_balanced<'<', '>'> }
}; };
auto start = state.pos; auto start = state.pos;
@ -265,14 +269,13 @@ Token parse_percent_token(ParseState& state, bool throw_on_unterminated)
if (auto it = find_if(matching_pairs, [=](const CharPair& cp) { return opening_delimiter == cp.opening; }); if (auto it = find_if(matching_pairs, [=](const CharPair& cp) { return opening_delimiter == cp.opening; });
it != std::end(matching_pairs)) it != std::end(matching_pairs))
{ {
const Codepoint closing_delimiter = it->closing; auto quoted = it->parse_func(state);
auto quoted = parse_quoted_balanced(state, opening_delimiter, closing_delimiter);
if (throw_on_unterminated and not quoted.terminated) if (throw_on_unterminated and not quoted.terminated)
{ {
auto coord = compute_coord({state.str.begin(), start}); auto coord = compute_coord({state.str.begin(), start});
throw parse_error{format("{}:{}: unterminated string '%{}{}...{}'", throw parse_error{format("{}:{}: unterminated string '%{}{}...{}'",
coord.line+1, coord.column+1, type_name, coord.line+1, coord.column+1, type_name,
opening_delimiter, closing_delimiter)}; it->opening, it->closing)};
} }
return {type, byte_pos, std::move(quoted.content), quoted.terminated}; return {type, byte_pos, std::move(quoted.content), quoted.terminated};
@ -801,16 +804,16 @@ UnitTest test_command_parsing{[]
check_quoted("'abc''def", false, "abc'def"); check_quoted("'abc''def", false, "abc'def");
check_quoted("'abc''def'''", true, "abc'def'"); check_quoted("'abc''def'''", true, "abc'def'");
auto check_balanced = [](StringView str, Codepoint opening, Codepoint closing, bool terminated, StringView content) auto check_balanced = [](StringView str, bool terminated, StringView content)
{ {
ParseState state{str, str.begin()+1}; ParseState state{str, str.begin()+1};
auto quoted = parse_quoted_balanced(state, opening, closing); auto quoted = parse_quoted_balanced<'{', '}'>(state);
kak_assert(quoted.terminated == terminated); kak_assert(quoted.terminated == terminated);
kak_assert(quoted.content == content); kak_assert(quoted.content == content);
}; };
check_balanced("{abc}", '{', '}', true, "abc"); check_balanced("{abc}", true, "abc");
check_balanced("{abc{def}}", '{', '}', true, "abc{def}"); check_balanced("{abc{def}}", true, "abc{def}");
check_balanced("{{abc}{def}", '{', '}', false, "{abc}{def}"); check_balanced("{{abc}{def}", false, "{abc}{def}");
auto check_unquoted = [](StringView str, StringView content) auto check_unquoted = [](StringView str, StringView content)
{ {