mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 18:57:34 +00:00
LibRegex: Allow a '?' suffix for brace quantifiers
This fixes another compat point in #6042.
This commit is contained in:
parent
8d7bcc2476
commit
e9279d1790
3 changed files with 15 additions and 9 deletions
|
@ -119,3 +119,11 @@ test("named capture group with two '?' qualifiers", () => {
|
||||||
expect(res[1]).toBeUndefined();
|
expect(res[1]).toBeUndefined();
|
||||||
expect(res.groups.foo).toBeUndefined();
|
expect(res.groups.foo).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// #6042
|
||||||
|
test("non-greedy brace quantifier", () => {
|
||||||
|
let res = /a[a-z]{2,4}?/.exec("abcdefghi");
|
||||||
|
|
||||||
|
expect(res.length).toBe(1);
|
||||||
|
expect(res[0]).toBe("abc");
|
||||||
|
});
|
||||||
|
|
|
@ -362,26 +362,28 @@ public:
|
||||||
// LABEL _END = alterantive_bytecode.size
|
// LABEL _END = alterantive_bytecode.size
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert_bytecode_repetition_min_max(ByteCode& bytecode_to_repeat, size_t minimum, Optional<size_t> maximum)
|
void insert_bytecode_repetition_min_max(ByteCode& bytecode_to_repeat, size_t minimum, Optional<size_t> maximum, bool greedy = true)
|
||||||
{
|
{
|
||||||
ByteCode new_bytecode;
|
ByteCode new_bytecode;
|
||||||
new_bytecode.insert_bytecode_repetition_n(bytecode_to_repeat, minimum);
|
new_bytecode.insert_bytecode_repetition_n(bytecode_to_repeat, minimum);
|
||||||
|
|
||||||
if (maximum.has_value()) {
|
if (maximum.has_value()) {
|
||||||
|
auto jump_kind = static_cast<ByteCodeValueType>(greedy ? OpCodeId::ForkStay : OpCodeId::ForkJump);
|
||||||
if (maximum.value() > minimum) {
|
if (maximum.value() > minimum) {
|
||||||
auto diff = maximum.value() - minimum;
|
auto diff = maximum.value() - minimum;
|
||||||
new_bytecode.empend(static_cast<ByteCodeValueType>(OpCodeId::ForkStay));
|
new_bytecode.empend(jump_kind);
|
||||||
new_bytecode.empend(diff * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
new_bytecode.empend(diff * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
||||||
|
|
||||||
for (size_t i = 0; i < diff; ++i) {
|
for (size_t i = 0; i < diff; ++i) {
|
||||||
new_bytecode.append(bytecode_to_repeat);
|
new_bytecode.append(bytecode_to_repeat);
|
||||||
new_bytecode.empend(static_cast<ByteCodeValueType>(OpCodeId::ForkStay));
|
new_bytecode.empend(jump_kind);
|
||||||
new_bytecode.empend((diff - i - 1) * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
new_bytecode.empend((diff - i - 1) * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no maximum value set, repeat finding if possible
|
// no maximum value set, repeat finding if possible
|
||||||
new_bytecode.empend(static_cast<ByteCodeValueType>(OpCodeId::ForkJump));
|
auto jump_kind = static_cast<ByteCodeValueType>(greedy ? OpCodeId::ForkJump : OpCodeId::ForkStay);
|
||||||
|
new_bytecode.empend(jump_kind);
|
||||||
new_bytecode.empend(-bytecode_to_repeat.size() - 2); // Jump to the last iteration
|
new_bytecode.empend(-bytecode_to_repeat.size() - 2); // Jump to the last iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -968,10 +968,6 @@ bool ECMA262Parser::parse_quantifier(ByteCode& stack, size_t& match_length_minim
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match(TokenType::Questionmark)) {
|
if (match(TokenType::Questionmark)) {
|
||||||
if (repetition_mark == Repetition::Explicit) {
|
|
||||||
set_error(Error::InvalidRepetitionMarker);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
consume();
|
consume();
|
||||||
ungreedy = true;
|
ungreedy = true;
|
||||||
}
|
}
|
||||||
|
@ -990,7 +986,7 @@ bool ECMA262Parser::parse_quantifier(ByteCode& stack, size_t& match_length_minim
|
||||||
match_length_minimum = 0;
|
match_length_minimum = 0;
|
||||||
break;
|
break;
|
||||||
case Repetition::Explicit:
|
case Repetition::Explicit:
|
||||||
new_bytecode.insert_bytecode_repetition_min_max(stack, repeat_min.value(), repeat_max);
|
new_bytecode.insert_bytecode_repetition_min_max(stack, repeat_min.value(), repeat_max, !ungreedy);
|
||||||
match_length_minimum *= repeat_min.value();
|
match_length_minimum *= repeat_min.value();
|
||||||
break;
|
break;
|
||||||
case Repetition::None:
|
case Repetition::None:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue