Add a debug regex command to dump regex instructions

This commit is contained in:
Maxime Coste 2018-04-27 08:34:49 +10:00
parent f10eb9faa3
commit 8438b33175
5 changed files with 45 additions and 23 deletions

View File

@ -1143,7 +1143,7 @@ const CommandDesc debug_cmd = {
[](const Context& context, CompletionFlags flags, [](const Context& context, CompletionFlags flags,
const String& prefix, ByteCount cursor_pos) -> Completions { const String& prefix, ByteCount cursor_pos) -> Completions {
auto c = {"info", "buffers", "options", "memory", "shared-strings", auto c = {"info", "buffers", "options", "memory", "shared-strings",
"profile-hash-maps", "faces", "mappings"}; "profile-hash-maps", "faces", "mappings", "regex"};
return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) }; return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) };
}), }),
[](const ParametersParser& parser, Context& context, const ShellContext&) [](const ParametersParser& parser, Context& context, const ShellContext&)
@ -1216,6 +1216,14 @@ const CommandDesc debug_cmd = {
keymaps.get_mapping(key, m).docstring)); keymaps.get_mapping(key, m).docstring));
} }
} }
else if (parser[0] == "regex")
{
if (parser.positional_count() != 2)
throw runtime_error("expected a regex");
write_to_debug_buffer(format(" * {}:\n{}",
parser[1], dump_regex(compile_regex(parser[1], RegexCompileFlags::None))));
}
else else
throw runtime_error(format("no such debug command: '{}'", parser[0])); throw runtime_error(format("no such debug command: '{}'", parser[0]));
} }

View File

@ -992,60 +992,63 @@ private:
ParsedRegex& m_parsed_regex; ParsedRegex& m_parsed_regex;
}; };
void dump_regex(const CompiledRegex& program) String dump_regex(const CompiledRegex& program)
{ {
String res;
int count = 0; int count = 0;
for (auto& inst : program.instructions) for (auto& inst : program.instructions)
{ {
printf(" %03d ", count++); char buf[10];
sprintf(buf, " %03d ", count++);
res += buf;
switch (inst.op) switch (inst.op)
{ {
case CompiledRegex::Literal: case CompiledRegex::Literal:
printf("literal %lc\n", inst.param); res += format("literal {}\n", inst.param);
break; break;
case CompiledRegex::Literal_IgnoreCase: case CompiledRegex::Literal_IgnoreCase:
printf("literal (ignore case) %lc\n", inst.param); res += format("literal (ignore case) {}\n", inst.param);
break; break;
case CompiledRegex::AnyChar: case CompiledRegex::AnyChar:
printf("any char\n"); res += "any char\n";
break; break;
case CompiledRegex::Jump: case CompiledRegex::Jump:
printf("jump %u\n", inst.param); res += format("jump {}\n", inst.param);
break; break;
case CompiledRegex::Split_PrioritizeParent: case CompiledRegex::Split_PrioritizeParent:
case CompiledRegex::Split_PrioritizeChild: case CompiledRegex::Split_PrioritizeChild:
{ {
printf("split (prioritize %s) %u\n", res += format("split (prioritize {}) {}\n",
inst.op == CompiledRegex::Split_PrioritizeParent ? "parent" : "child", inst.op == CompiledRegex::Split_PrioritizeParent ? "parent" : "child",
inst.param); inst.param);
break; break;
} }
case CompiledRegex::Save: case CompiledRegex::Save:
printf("save %d\n", inst.param); res += format("save {}\n", inst.param);
break; break;
case CompiledRegex::Class: case CompiledRegex::Class:
printf("class %d\n", inst.param); res += format("class {}\n", inst.param);
break; break;
case CompiledRegex::CharacterType: case CompiledRegex::CharacterType:
printf("character type %d\n", inst.param); res += format("character type {}\n", inst.param);
break; break;
case CompiledRegex::LineStart: case CompiledRegex::LineStart:
printf("line start\n"); res += "line start\n";
break; break;
case CompiledRegex::LineEnd: case CompiledRegex::LineEnd:
printf("line end\n"); res += "line end\n";
break; break;
case CompiledRegex::WordBoundary: case CompiledRegex::WordBoundary:
printf("word boundary\n"); res += "word boundary\n";
break; break;
case CompiledRegex::NotWordBoundary: case CompiledRegex::NotWordBoundary:
printf("not word boundary\n"); res += "not word boundary\n";
break; break;
case CompiledRegex::SubjectBegin: case CompiledRegex::SubjectBegin:
printf("subject begin\n"); res += "subject begin\n";
break; break;
case CompiledRegex::SubjectEnd: case CompiledRegex::SubjectEnd:
printf("subject end\n"); res += "subject end\n";
break; break;
case CompiledRegex::LookAhead: case CompiledRegex::LookAhead:
case CompiledRegex::NegativeLookAhead: case CompiledRegex::NegativeLookAhead:
@ -1078,16 +1081,17 @@ void dump_regex(const CompiledRegex& program)
String str; String str;
for (auto it = program.lookarounds.begin() + inst.param; *it != -1; ++it) for (auto it = program.lookarounds.begin() + inst.param; *it != -1; ++it)
utf8::dump(std::back_inserter(str), *it); utf8::dump(std::back_inserter(str), *it);
printf("%s (%s)\n", name, str.c_str()); res += format("{} ({})\n", name, str);
break; break;
} }
case CompiledRegex::FindNextStart: case CompiledRegex::FindNextStart:
printf("find next start\n"); res += "find next start\n";
break; break;
case CompiledRegex::Match: case CompiledRegex::Match:
printf("match\n"); res += "match\n";
} }
} }
return res;
} }
CompiledRegex compile_regex(StringView re, RegexCompileFlags flags) CompiledRegex compile_regex(StringView re, RegexCompileFlags flags)
@ -1134,7 +1138,7 @@ struct TestVM : CompiledRegex, ThreadedRegexVM<const char*, dir>
: CompiledRegex{compile_regex(re, dir == MatchDirection::Forward ? : CompiledRegex{compile_regex(re, dir == MatchDirection::Forward ?
RegexCompileFlags::None : RegexCompileFlags::Backward)}, RegexCompileFlags::None : RegexCompileFlags::Backward)},
VMType{(const CompiledRegex&)*this} VMType{(const CompiledRegex&)*this}
{ if (dump) dump_regex(*this); } { if (dump) printf(dump_regex(*this).c_str()); }
bool exec(StringView re, RegexExecFlags flags = RegexExecFlags::AnyMatch) bool exec(StringView re, RegexExecFlags flags = RegexExecFlags::AnyMatch)
{ {

View File

@ -112,6 +112,8 @@ struct CompiledRegex : RefCountable, UseMemoryDomain<MemoryDomain::Regex>
std::unique_ptr<StartDesc> backward_start_desc; std::unique_ptr<StartDesc> backward_start_desc;
}; };
String dump_regex(const CompiledRegex& program);
enum class RegexCompileFlags enum class RegexCompileFlags
{ {
None = 0, None = 0,

View File

@ -125,6 +125,13 @@ InplaceString<15> to_string(int val)
return res; return res;
} }
InplaceString<15> to_string(unsigned val)
{
InplaceString<15> res;
res.m_length = sprintf(res.m_data, "%u", val);
return res;
}
InplaceString<23> to_string(long int val) InplaceString<23> to_string(long int val)
{ {
InplaceString<23> res; InplaceString<23> res;

View File

@ -72,6 +72,7 @@ struct Hex { size_t val; };
constexpr Hex hex(size_t val) { return {val}; } constexpr Hex hex(size_t val) { return {val}; }
InplaceString<15> to_string(int val); InplaceString<15> to_string(int val);
InplaceString<15> to_string(unsigned val);
InplaceString<23> to_string(long int val); InplaceString<23> to_string(long int val);
InplaceString<23> to_string(size_t val); InplaceString<23> to_string(size_t val);
InplaceString<23> to_string(long long int val); InplaceString<23> to_string(long long int val);