mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:07:46 +00:00
Userland: Add support for 'match' in 'expr'
This commit is contained in:
parent
6add8b9c05
commit
45e5661296
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(checksum LibCrypto)
|
||||||
target_link_libraries(copy LibGUI)
|
target_link_libraries(copy LibGUI)
|
||||||
target_link_libraries(disasm LibX86)
|
target_link_libraries(disasm LibX86)
|
||||||
|
target_link_libraries(expr LibRegex)
|
||||||
target_link_libraries(functrace LibDebug LibX86)
|
target_link_libraries(functrace LibDebug LibX86)
|
||||||
target_link_libraries(html LibWeb)
|
target_link_libraries(html LibWeb)
|
||||||
target_link_libraries(js LibJS LibLine)
|
target_link_libraries(js LibJS LibLine)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <AK/Queue.h>
|
#include <AK/Queue.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
|
#include <LibRegex/Regex.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -381,7 +382,7 @@ private:
|
||||||
virtual bool truth() const override { return integer() != 0; }
|
virtual bool truth() const override { return integer() != 0; }
|
||||||
virtual int integer() const override
|
virtual int integer() const override
|
||||||
{
|
{
|
||||||
if (m_op == StringOperation::Substring) {
|
if (m_op == StringOperation::Substring || m_op == StringOperation::Match) {
|
||||||
auto substr = string();
|
auto substr = string();
|
||||||
if (auto integer = substr.to_int(); integer.has_value())
|
if (auto integer = substr.to_int(); integer.has_value())
|
||||||
return integer.value();
|
return integer.value();
|
||||||
|
@ -389,9 +390,6 @@ private:
|
||||||
fail("Not an integer: '{}'", substr);
|
fail("Not an integer: '{}'", substr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_op == StringOperation::Match)
|
|
||||||
fail("Unimplemented operation 'match'");
|
|
||||||
|
|
||||||
if (m_op == StringOperation::Index) {
|
if (m_op == StringOperation::Index) {
|
||||||
if (auto idx = m_str->string().index_of(m_pos_or_chars->string()); idx.has_value())
|
if (auto idx = m_str->string().index_of(m_pos_or_chars->string()); idx.has_value())
|
||||||
return idx.value() + 1;
|
return idx.value() + 1;
|
||||||
|
@ -417,18 +415,60 @@ private:
|
||||||
if (m_op == StringOperation::Substring)
|
if (m_op == StringOperation::Substring)
|
||||||
return safe_substring(m_str->string(), m_pos_or_chars->integer(), m_length->integer());
|
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());
|
return String::number(integer());
|
||||||
}
|
}
|
||||||
virtual Type type() const override
|
virtual Type type() const override
|
||||||
{
|
{
|
||||||
if (m_op == StringOperation::Substring)
|
if (m_op == StringOperation::Substring)
|
||||||
return Type::String;
|
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;
|
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 };
|
StringOperation m_op { StringOperation::Substring };
|
||||||
NonnullOwnPtr<Expression> m_str;
|
NonnullOwnPtr<Expression> m_str;
|
||||||
OwnPtr<Expression> m_pos_or_chars, m_length;
|
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)
|
NonnullOwnPtr<Expression> Expression::parse(Queue<StringView>& args, Precedence prec)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue