Userland: Add support for 'match' in 'expr'

This commit is contained in:
AnotherTest 2020-11-16 21:43:24 +03:30 committed by Andreas Kling
parent 6add8b9c05
commit 45e5661296
Notes: sideshowbarker 2024-07-19 01:14:57 +09:00
2 changed files with 45 additions and 4 deletions

View file

@ -20,6 +20,7 @@ target_link_libraries(avol LibAudio)
target_link_libraries(checksum LibCrypto)
target_link_libraries(copy LibGUI)
target_link_libraries(disasm LibX86)
target_link_libraries(expr LibRegex)
target_link_libraries(functrace LibDebug LibX86)
target_link_libraries(html LibWeb)
target_link_libraries(js LibJS LibLine)

View file

@ -31,6 +31,7 @@
#include <AK/Queue.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <LibRegex/Regex.h>
#include <stdio.h>
#include <unistd.h>
@ -381,7 +382,7 @@ private:
virtual bool truth() const override { return integer() != 0; }
virtual int integer() const override
{
if (m_op == StringOperation::Substring) {
if (m_op == StringOperation::Substring || m_op == StringOperation::Match) {
auto substr = string();
if (auto integer = substr.to_int(); integer.has_value())
return integer.value();
@ -389,9 +390,6 @@ private:
fail("Not an integer: '{}'", substr);
}
if (m_op == StringOperation::Match)
fail("Unimplemented operation 'match'");
if (m_op == StringOperation::Index) {
if (auto idx = m_str->string().index_of(m_pos_or_chars->string()); idx.has_value())
return idx.value() + 1;
@ -417,18 +415,60 @@ private:
if (m_op == StringOperation::Substring)
return safe_substring(m_str->string(), m_pos_or_chars->integer(), m_length->integer());
if (m_op == StringOperation::Match) {
auto match = m_compiled_regex->match(m_str->string(), PosixFlags::Global);
if (m_compiled_regex->parser_result.capture_groups_count == 0) {
if (!match.success)
return "0";
size_t count = 0;
for (auto& m : match.matches)
count += m.view.length();
return String::number(count);
} else {
if (!match.success)
return "";
StringBuilder result;
for (auto& m : match.capture_group_matches) {
for (auto& e : m)
result.append(e.view.to_string());
}
return result.build();
}
}
return String::number(integer());
}
virtual Type type() const override
{
if (m_op == StringOperation::Substring)
return Type::String;
if (m_op == StringOperation::Match) {
if (!m_pos_or_chars)
fail("'match' expects a string pattern");
ensure_regex();
if (m_compiled_regex->parser_result.capture_groups_count == 0)
return Type::Integer;
return Type::String;
}
return Type::Integer;
}
void ensure_regex() const
{
if (!m_compiled_regex)
m_compiled_regex = make<regex::Regex<PosixExtended>>(m_pos_or_chars->string());
}
StringOperation m_op { StringOperation::Substring };
NonnullOwnPtr<Expression> m_str;
OwnPtr<Expression> m_pos_or_chars, m_length;
mutable OwnPtr<regex::Regex<PosixExtended>> m_compiled_regex;
};
NonnullOwnPtr<Expression> Expression::parse(Queue<StringView>& args, Precedence prec)