mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Userland: Add support for 'match' in 'expr'
This commit is contained in:
parent
6add8b9c05
commit
45e5661296
Notes:
sideshowbarker
2024-07-19 01:14:57 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/45e5661296c Pull-request: https://github.com/SerenityOS/serenity/pull/4103 Reviewed-by: https://github.com/linusg ✅
2 changed files with 45 additions and 4 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue