1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:47:34 +00:00

LibRegex: Clear previous capture group contents in ECMA262 mode

ECMA262 requires that the capture groups only contain the values from
the last iteration, e.g. `((c)(a)?(b))` should _not_ contain 'a' in the
second capture group when matching "cabcb".
This commit is contained in:
Ali Mohammad Pur 2021-07-23 19:37:18 +04:30 committed by Ali Mohammad Pur
parent 34ec0fa8ad
commit c8b2199251
4 changed files with 109 additions and 1 deletions

View file

@ -39,6 +39,8 @@ using ByteCodeValueType = u64;
__ENUMERATE_OPCODE(Save) \
__ENUMERATE_OPCODE(Restore) \
__ENUMERATE_OPCODE(GoBack) \
__ENUMERATE_OPCODE(ClearCaptureGroup) \
__ENUMERATE_OPCODE(ClearNamedCaptureGroup) \
__ENUMERATE_OPCODE(Exit)
// clang-format off
@ -174,6 +176,19 @@ public:
extend(move(bytecode));
}
void insert_bytecode_clear_capture_group(size_t index)
{
empend(static_cast<ByteCodeValueType>(OpCodeId::ClearCaptureGroup));
empend(index);
}
void insert_bytecode_clear_named_capture_group(StringView name)
{
empend(static_cast<ByteCodeValueType>(OpCodeId::ClearNamedCaptureGroup));
empend(reinterpret_cast<ByteCodeValueType>(name.characters_without_null_termination()));
empend(name.length());
}
void insert_bytecode_compare_string(StringView view)
{
ByteCode bytecode;
@ -626,6 +641,28 @@ public:
const String arguments_string() const override { return String::formatted("kind={} ({})", (long unsigned int)argument(0), boundary_check_type_name(type())); }
};
class OpCode_ClearCaptureGroup final : public OpCode {
public:
ExecutionResult execute(const MatchInput& input, MatchState& state, MatchOutput& output) const override;
ALWAYS_INLINE OpCodeId opcode_id() const override { return OpCodeId::ClearCaptureGroup; }
ALWAYS_INLINE size_t size() const override { return 2; }
ALWAYS_INLINE size_t id() const { return argument(0); }
const String arguments_string() const override { return String::formatted("id={}", id()); }
};
class OpCode_ClearNamedCaptureGroup final : public OpCode {
public:
ExecutionResult execute(const MatchInput& input, MatchState& state, MatchOutput& output) const override;
ALWAYS_INLINE OpCodeId opcode_id() const override { return OpCodeId::ClearNamedCaptureGroup; }
ALWAYS_INLINE size_t size() const override { return 3; }
ALWAYS_INLINE StringView name() const { return { reinterpret_cast<char*>(argument(0)), length() }; }
ALWAYS_INLINE size_t length() const { return argument(1); }
const String arguments_string() const override
{
return String::formatted("name={}, length={}", name(), length());
}
};
class OpCode_SaveLeftCaptureGroup final : public OpCode {
public:
ExecutionResult execute(const MatchInput& input, MatchState& state, MatchOutput& output) const override;