Commit Graph

234 Commits

Author SHA1 Message Date
Ali Mohammad Pur
4be7239626 LibRegex: Make parse_disjunction() consume all disjunctions in one frame
This helps us not blow up when too many disjunctions are chained togther
in the regex we're parsing.
Fixes #12615.
2022-02-20 11:53:59 +01:00
Ali Mohammad Pur
627bbee055 LibRegex: Allow quantifiers after quantifiable assertions
While quantifying assertions is very much meaningless, the specification
allows them with annex B's extended grammar for browsers, so read and
apply the quantifiers.
Fixes #12373.
2022-02-20 11:53:59 +01:00
Ali Mohammad Pur
3b0943d24c LibRegex: Correct the alternative matching order when one is empty
Previously we were compiling `/a|/` into what effectively would be
`/|a`, which is clearly incorrect.
2022-02-14 11:30:50 +01:00
Ali Mohammad Pur
6a4c8a66ae LibRegex: Only skip full instructions when optimizing alternations
It makes no sense to skip half of an instruction, so make sure to skip
only full instructions!
2022-02-09 21:02:24 +00:00
Timothy Flynn
2212aa2388 LibRegex: Support non-ASCII whitespace characters when matching \s or \S
ECMA-262 defines \s as:

    Return the CharSet containing all characters corresponding to a code
    point on the right-hand side of the WhiteSpace or LineTerminator
    productions.

The LineTerminator production is simply: U+000A, U+000D, U+2028, or
U+2029. Unfortunately there isn't a Unicode property that covers just
those code points.

The WhiteSpace production is: U+0009, U+000B, U+000C, U+FEFF, or any
code point with the Space_Separator general category.

If the Unicode generators are disabled, this will fall back to ASCII
space code points.
2022-02-05 22:30:10 +03:30
Timothy Flynn
3729fd06fa LibRegex: Do not return an Optional from Regex::Matcher::execute
The code path that could return an optional no longer exists as of
commit: a962ee020a
2022-02-05 19:06:50 +03:30
Timothy Flynn
27d3de1f17 LibRegex: Do not continue searching input when the sticky bit is set
This partially reverts commit a962ee020a.

When the sticky bit is set, the global bit should basically be ignored
except by external callers who want their own special behavior. For
example, RegExp.prototype [ @@match ] will use the global flag to
accumulate consecutive matches. But on the first failure, the regex
loop should break.
2022-02-05 19:06:50 +03:30
Ali Mohammad Pur
a962ee020a LibJS+LibRegex: Don't repeat regex match in regexp_exec()
LibRegex already implements this loop in a more performant way, so all
LibJS has to do here is to return things in the right shape, and not
loop over the input string.
Previously this was a quadratic operation on string length, which lead
to crazy execution times on failing regexps - now it's nice and fast :^)

Note that a Regex test has to be updated to remove the stateful flag as
it repeats matching on multiple strings.
2022-02-05 00:09:32 +01:00
Ali Mohammad Pur
2b028f6faa LibRegex+LibJS: Avoid searching for more than one match in JS RegExps
All of JS's regular expression APIs only want a single match, so avoid
trying to produce more (which will be discarded anyway).
2022-02-05 00:09:32 +01:00
Ali Mohammad Pur
5fac41f733 LibRegex: Implement ECMA262 multiline matching without splitting lines
As ECMA262 regex allows `[^]` and literal newlines to match newlines in
the input string, we shouldn't split the input string into lines, rather
simply make boundaries and catchall patterns capable of checking for
these conditions specifically.
2022-01-26 00:53:09 +03:30
Ali Mohammad Pur
aa20210119 LibRegex: Don't return empty vectors from RegexStringView::lines()
Instead, return a vector of one empty string.
2022-01-26 00:53:09 +03:30
Ali Mohammad Pur
cd83325c7c LibRegex: Preserve capture groups and matches across ForkReplace
This makes the (flawed) ForkStay inserted as a loop header unnecessary,
and finally fixes LibRegex rewriting weird loops in weird ways.
2022-01-22 00:35:49 +00:00
Ali Mohammad Pur
bc20e4f71d LibRegex: Add some more information to Compare::Reference debug output 2022-01-22 00:35:49 +00:00
Ali Mohammad Pur
97dde09170 LibRegex: Allow ClearCaptureGroup to create new groups
Instead of leaking all capture groups and selectively clearing some,
simply avoid leaking things and only "define" the ones that need to
exist.
This *actually* implements the capture groups ECMA262 quirk.
Also adds the test removed in the previous commit (to avoid messing up
test runs across bisects).
2022-01-22 00:35:49 +00:00
Ali Mohammad Pur
704e0654b3 Revert "LibRegex: Implement an ECMA262 Regex quirk with negative loo..."
This partially reverts commit c11be92e23.
That commit fixes one thing and breaks many more, a next commit will
implement this quirk in a more sane way.
2022-01-22 00:35:49 +00:00
Ali Mohammad Pur
9eccd4c56e LibRegex: Allow the pattern to match the zero-length end of the string
...only if Multiline is not enabled.
Fixes #11940.
2022-01-21 18:14:08 +03:30
Ali Mohammad Pur
c11be92e23 LibRegex: Implement an ECMA262 Regex quirk with negative lookarounds
This implements the quirk defined by "Note 3" in section "Canonicalize"
(https://tc39.es/ecma262/#sec-runtime-semantics-canonicalize-ch).

Crosses off another quirk from #6042.
2022-01-21 18:14:08 +03:30
Ali Mohammad Pur
bfe8f312f3 LibRegex: Correct jump offset to the start of the loop block
Previously we were jumping to the new end of the previous block (created
by the newly inserted ForkStay), correct the offset to jump to the
correct block as shown in the comments.
Fixes #12033.
2022-01-21 18:14:08 +03:30
Ali Mohammad Pur
9de33629da AK+Everywhere: Make Variant::visit() respect the Variant's constness
...and fix all the instances of visit() taking non-const arguments.
2022-01-14 11:35:40 +03:30
Ali Mohammad Pur
1a35e27490 LibRegex: Make FailForks fail all forks up to the last save point
This makes negative lookarounds with more than one fork behave
correctly.
Fixes #11350.
2021-12-25 18:41:10 +01:00
Hendiadyoin1
27a967371b LibRegex: Remove duplicate declaration of execution_result_name(...) 2021-12-21 18:17:28 -08:00
Hendiadyoin1
303af07df8 LibRegex: Use AK::any_of in Parser::lookahead_any
Equivalent to std::ranges::any_of, which clang-tidy suggests.
2021-12-21 18:17:28 -08:00
Hendiadyoin1
0f4a79a24d LibRegex: Capture this explicitly in RegexStringView::equals lambda
This stops clang-tidy from suggesting that this function can be made
static, although accessing `this->operator==` in the lambda function.
2021-12-21 18:17:28 -08:00
Hendiadyoin1
5885e70df7 LibRegex: Remove some meaningless/useless const-qualifiers
Also replace String creation from `""` with `String::empty()`
2021-12-21 18:17:28 -08:00
Hendiadyoin1
ca69ded9a5 LibRegex: Collapse some if(...) return true; else return false; blocks 2021-12-21 18:17:28 -08:00
Hendiadyoin1
a2563496f5 LibRegex: Remove some else-after-returns 2021-12-21 18:17:28 -08:00
Hendiadyoin1
b674de6957 LibRegex: Add some implied auto qualifiers 2021-12-21 18:17:28 -08:00
Ali Mohammad Pur
b8f03bb072 LibRegex: Make append_alternation() significantly faster
...by flattening the underlying bytecode chunks first.
Also avoid calling DisjointChunks::size() inside a loop.
This is a very significant improvement in performance, making the
compilation of a large regex with lots of alternatives take only ~100ms
instead of many minutes (I ran out of patience waiting for it) :^)
2021-12-21 22:10:07 +01:00
Ali Mohammad Pur
66249612d6 LibRegex: Avoid calling DisjointChunks::size() in get_opcode()
That method is O(n), and should generally be avoided.
2021-12-21 22:10:07 +01:00
davidot
154ed3994c LibRegex: Parse capture group names according to the ECMA262 spec 2021-12-21 14:04:23 +01:00
davidot
733a70671b LibRegex: Disallow duplicate named capture groups in ECMA262 parser 2021-12-21 14:04:23 +01:00
Ali Mohammad Pur
d2e51fafa9 LibRegex: Merge alternations based on blocks and not instructions
The instructions can have dependencies (e.g. Repeat), so only unify
equal blocks instead of consecutive instructions.
Fixes #11247.

Also adds the minimal test case(s) from that issue.
2021-12-15 19:36:45 +03:30
Ali Mohammad Pur
387df06385 LibRegex: Avoid rewriting a+ as a* as part of atomic rewriting
The initial `ForkStay` is only needed if the looping block has a
following block, if there's no following block or the following block
does not attempt to match anything, we should not insert the ForkStay,
otherwise we would be rewriting `a+` as `a*` by allowing the 'end' to be
executed.
Fixes #10952.
2021-11-18 09:09:22 +01:00
Andreas Kling
216e21a1fa AK: Convert AK::Format formatting helpers to returning ErrorOr<void>
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
2021-11-17 00:21:13 +01:00
Tim Schumacher
ff38062318 LibRegex: Correctly translate BRE pattern end anchors
Previously we were always choosing the "nothing special" code path, even
if the dollar symbol was at the end of the pattern (and therefore should
have been considered special).

Fix that by actually checking if the pattern end follows, and emitting
the correct instruction if necessary.
2021-11-13 15:06:52 +03:30
Andreas Kling
8b1108e485 Everywhere: Pass AK::StringView by value 2021-11-11 01:27:46 +01:00
Andreas Kling
a54be656ae LibRegex: Don't push LibRegex's "Error" into the global namespace 2021-11-08 00:35:27 +01:00
Ali Mohammad Pur
ac856cb965 LibRegex: Don't ignore empty alternatives in append_alternation()
Doing so would cause patterns like `(a|)` to not match the empty string.
2021-10-29 15:57:59 +02:00
Ben Wiederhake
50698a0db4 AK: Prevent accidental misuse of BumpAllocator
In particular, we implicitly required that the caller initializes the
returned instances themselves (solved by making
UniformBumpAllocator::allocate call the constructor), and BumpAllocator
itself cannot handle classes that are not trivially deconstructible
(solved by deleting the method).

Co-authored-by: Ali Mohammad Pur <ali.mpfard@gmail.com>
2021-10-23 19:02:54 +01:00
Ali Mohammad Pur
b9ffa0ad2e LibRegex: Transform 0,1 min/unbounded max repetitions to * or +
The implementation of transform_bytecode_repetition_min_max expects at
least min=1, so let's also optimise on our way out of a bug where
'x{0,}' would cause a crash.
2021-10-09 15:57:05 +02:00
Ali Mohammad Pur
8f722302d9 LibRegex: Use a match table for character classes
Generate a sorted, compressed series of ranges in a match table for
character classes, and use a binary search to find the matches.
This is about a 3-4x speedup for character class match performance. :^)
2021-10-03 19:16:36 +02:00
Ali Mohammad Pur
c80b65b827 LibRegex: Avoid creating a new temporary RegexStringView in Char compare
Instead of making a new string to compare against, simply grab the first
code unit of the input and compare against that.
2021-10-03 01:15:17 +02:00
Andreas Kling
024367d82e LibJS+AK: Use Vector<u16, 1> for UTF-16 string storage
It's very common to encounter single-character strings in JavaScript on
the web. We can make such strings significantly lighter by having a
1-character inline capacity on the Vectors.
2021-10-02 17:39:38 +02:00
Andreas Kling
bb6634b024 LibRegex: Don't emit signpost events for every regular expression
The time we were spending on these signposts was adding up to way too
much, so let's not do it automatically.
2021-10-02 16:53:03 +02:00
Nico Weber
de72332920 Libraries: Fix typos 2021-10-01 01:06:40 +01:00
Andreas Kling
2758d99bbc LibRegex: Flatten bytecode before performing optimizations
This avoids doing DisjointChunks traversal for every bytecode access,
significantly reducing startup time for large regular expressions.
2021-09-29 18:45:26 +02:00
Ben Wiederhake
32e98d0924 Libraries: Use AK::Variant default initialization where appropriate 2021-09-21 04:22:52 +04:30
Brian Gianforcaro
fdea5e1628 LibRegex: Pass RegexStringView and Vector<RegexStringView> by reference
Flagged by pvs-studio, it looks like these were intended to be passed by
reference originally, but it was missed. This avoids excessive argument
copy when searching / matching in the regex API.

Before:

    Command: /usr/Tests/LibRegex/Regex --bench
    Average time: 5998.29 ms (median: 5991, stddev: 102.18)

After:

    Command: /usr/Tests/LibRegex/Regex --bench
    Average time: 5623.2 ms (median: 5623, stddev: 86.25)
2021-09-16 17:17:13 +02:00
Ali Mohammad Pur
741886a4c4 LibRegex: Make the optimizer understand references and capture groups
Otherwise the fork in patterns like `(1+)\1` would be (incorrectly)
optimized away.
2021-09-15 15:52:28 +04:30
Ali Mohammad Pur
8e3fe80c06 LibRegex: Avoid using GenericLexer::consume() when at eof
Fixes #10027.
2021-09-14 22:02:25 +02:00
Ali Mohammad Pur
bf0315ff8f LibRegex: Avoid excessive Vector copy when compiling regexps
Previously we would've copied the bytecode instead of moving the chunks
around, use the fancy new DisjointChunks<T> abstraction to make that
happen automagically.
This decreases vector copies and uses of memmove() by nearly 10x :^)
2021-09-14 21:33:15 +04:30
Ali Mohammad Pur
e4b1c0b8b1 LibRegex: Set a signpost on every executed regular expression 2021-09-13 14:38:53 +04:30
Ali Mohammad Pur
246ab432ff LibRegex: Add a basic optimization pass
This currently tries to convert forking loops to atomic groups, and
unify the left side of alternations.
2021-09-13 14:38:53 +04:30
Ali Mohammad Pur
7fefb8148b LibRegex: Use the correct capture group index in ERE bytecode generation
Otherwise the left and right capture instructions wouldn't point to the
same capture group if there was another nested group there.
2021-09-07 20:01:58 +02:00
Andreas Kling
6ad427993a Everywhere: Behaviour => Behavior 2021-09-07 13:53:14 +02:00
Ali Mohammad Pur
88d148b46a LibRegex: Avoid keeping track of checkpoints across forks
Doing so would increase memory consumption by quite a bit, since many
useless copies of the checkpoints hashmap would be created and later
thrown away.
2021-09-06 18:21:13 +04:30
Ali Mohammad Pur
abbe9da255 LibRegex: Make infinite repetitions short-circuit on empty matches
This makes (addmittedly weird) patterns like `(a*)*` work correctly
without going into an infinite fork loop.
2021-09-06 13:51:30 +04:30
Idan Horowitz
e8f6840471 AK+LibRegex: Disable construction of views from temporary Strings 2021-09-04 21:01:15 +02:00
Ali Mohammad Pur
9b2f0613ef LibRegex: Correctly advance string positions in Compare::compare_string
Fixes a bug where backreferences could cause desync between the
code point index and regular index, making comparison off-by-N.
2021-09-01 13:36:53 +02:00
Ali Mohammad Pur
dd82c2e9b4 LibRegex: Correctly handle failing in the middle of explicit repeats
- Make sure that all the Repeat ops are reset (otherwise the operation
  would not be correct when going over the Repeat op a second time)
- Make sure that all matches that are allowed to fail are backed by a
  fork, otherwise the last failing fork would not have anywhere to
  return to.
Fixes #9707.
2021-09-01 13:36:53 +02:00
Ali Mohammad Pur
98624fe03f LibRegex: Implement min/max repetition using the Repeat bytecode
This makes repetitions with large max bounds work correctly.
Also fixes an OOM issue found by OSS-Fuzz:
https://oss-fuzz.com/testcase?key=4725721980338176
2021-08-31 16:37:49 +02:00
Ali Mohammad Pur
05c65f9b5d LibRegex: Limit the number of nested capture groups allowed in BRE
Found by OSS-Fuzz: https://oss-fuzz.com/testcase?key=4869334212673536
2021-08-31 16:37:49 +02:00
Ali Mohammad Pur
206bc01f81 LibRegex: Allow null bytes in pattern
That check was rather pointless as the input is a StringView which knows
its own bounds.
Fixes #9686.
2021-08-30 18:43:09 +02:00
Timothy Flynn
562d4e497b LibRegex: Treat pattern string characters as unsigned
For example, consider the following pattern:

    new RegExp('\ud834\udf06', 'u')

With this pattern, the regex parser should insert the UTF-8 encoded
bytes 0xf0, 0x9d, 0x8c, and 0x86. However, because these characters are
currently treated as normal char types, they have a negative value since
they are all > 0x7f. Then, due to sign extension, when these characters
are cast to u64, the sign bit is preserved. The result is that these
bytes are inserted as 0xfffffffffffffff0, 0xffffffffffffff9d, etc.

Fortunately, there are only a few places where we insert bytecode with
the raw characters. In these places, be sure to treat the bytes as u8
before they are cast to u64.
2021-08-20 19:16:33 +02:00
Timothy Flynn
c5b5c779ff LibRegex+LibJS: Change capture group names from a String to a FlyString
The parser now stores this as a FlyString everywhere, so consumers can
also use it as a FlyString.
2021-08-19 23:49:25 +02:00
Timothy Flynn
4f2cbe119b LibRegex: Allow Unicode escape sequences in capture group names
Unfortunately, this requires a slight divergence in the way the capture
group names are stored. Previously, the generated byte code would simply
store a view into the regex pattern string, so no string copying was
required.

Now, the escape sequences are decoded into a new string, and a vector
of all parsed capture group names are stored in a vector in the parser
result structure. The byte code then stores a view into the
corresponding string in that vector.
2021-08-19 23:49:25 +02:00
Timothy Flynn
6131c0485e LibRegex: Use GenericLexer to consume escaped code points 2021-08-19 23:49:25 +02:00
Timothy Flynn
5ff9596678 LibRegex: Convert regex::Lexer to inherit from GenericLexer
This will allow regex::Lexer users to invoke GenericLexer consumption
methods, such as GenericLexer::consume_escaped_codepoint().

This also allows for de-duplicating common methods between the lexers.
2021-08-19 23:49:25 +02:00
Timothy Flynn
02e3633b7f AK: Move FormatParser definition from header to implementation file
This is primarily to be able to remove the GenericLexer include out of
Format.h as well. A subsequent commit will add AK::Result to
GenericLexer, which will cause naming conflicts with other structures
named Result. This can be avoided (for now) by preventing nearly every
file in the system from implicitly including GenericLexer.

Other changes in this commit are to add the GenericLexer include to
files where it is missing.
2021-08-19 23:49:25 +02:00
Timothy Flynn
325eabc770 LibRegex: Ensure the GoBack operation decrements the code unit index
This was missed in commit 27d555bab0.
2021-08-18 09:47:09 +04:30
Timothy Flynn
a9716ad44e LibRegex: In non-Unicode mode, parse \u{4} as a repetition pattern 2021-08-18 09:47:09 +04:30
Timothy Flynn
9509433e25 LibRegex: Implement and use a REPEAT operation for bytecode repetition
Currently, when we need to repeat an instruction N times, we simply add
that instruction N times in a for-loop. This doesn't scale well with
extremely large values of N, and ECMA-262 allows up to N = 2^53 - 1.

Instead, add a new REPEAT bytecode operation to defer this loop from the
parser to the runtime executor. This allows the parser to complete sans
any loops (for this instruction), and allows the executor to bail early
if the repeated bytecode fails.

Note: The templated ByteCode methods are to allow the Posix parsers to
continue using u32 because they are limited to N = 2^20.
2021-08-15 11:43:45 +01:00
Timothy Flynn
a0b72f5ad3 LibRegex: Remove (mostly) unused regex::MatchOutput
This struct holds a counter for the number of executed operations, and
vectors for matches, captures groups, and named capture groups. Each of
the vectors is unused. Remove the struct and just keep a separate
counter for the executed operations.
2021-08-15 11:43:45 +01:00
Timothy Flynn
f1ce998d73 LibRegex+LibJS: Combine named and unnamed capture groups in MatchState
Combining these into one list helps reduce the size of MatchState, and
as a result, reduces the amount of memory consumed during execution of
very large regex matches.

Doing this also allows us to remove a few regex byte code instructions:
ClearNamedCaptureGroup, SaveLeftNamedCaptureGroup, and NamedReference.
Named groups now behave the same as unnamed groups for these operations.
Note that SaveRightNamedCaptureGroup still exists to cache the matched
group name.

This also removes the recursion level from the MatchState, as it can
exist as a local variable in Matcher::execute instead.
2021-08-15 11:43:45 +01:00
Timothy Flynn
fea181bde3 LibRegex: Reduce RegexMatcher's BumpAllocator chunk size
Before the BumpAllocator OOB access issue was understood and fixed, the
chunk size was increased to 8MiB as a workaround in commit:
27d555bab0.

The issue is now resolved by: 0f1425c895.

We can reduce the chunk size to 2MiB, which has the added benefit of
reducing runtime of the RegExp.prototype.exec test.
2021-08-15 11:43:45 +01:00
Timothy Flynn
1a173be29d LibRegex: Disallow unescaped quantifiers in Unicode mode 2021-08-15 11:43:45 +01:00
Timothy Flynn
c3e1f1f687 LibRegex: Use correct source characters for Unicode identity escapes 2021-08-15 11:43:45 +01:00
Timothy Flynn
6a485f612f LibRegex: Implement legacy octal escape parsing closer to the spec
The grammar for the ECMA-262 CharacterEscape is:

  CharacterEscape[U, N] ::
    ControlEscape
    c ControlLetter
    0 [lookahead ∉ DecimalDigit]
    HexEscapeSequence
    RegExpUnicodeEscapeSequence[?U]
    [~U]LegacyOctalEscapeSequence
    IdentityEscape[?U, ?N]

It's important to parse the standalone "\0 [lookahead ∉ DecimalDigit]"
before parsing LegacyOctalEscapeSequence. Otherwise, all standalone "\0"
patterns are parsed as octal, which are disallowed in Unicode mode.

Further, LegacyOctalEscapeSequence should also be parsed while parsing
character classes.
2021-08-15 11:43:45 +01:00
Timothy Flynn
0c8f2f5aca LibRegex: Ensure escaped hexadecimals are exactly 2 digits in length 2021-08-15 11:43:45 +01:00
Timothy Flynn
2e4b6fd1ac LibRegex: Ensure escaped code points are exactly 4 digits in length 2021-08-15 11:43:45 +01:00
Timothy Flynn
e887314472 LibRegex: Fix ECMA-262 parsing of invalid identity escapes
* Only alphabetic (A-Z, a-z) characters may be escaped with \c. The loop
  currently parsing \c includes code points between the upper/lower case
  groups.
* In Unicode mode, all invalid identity escapes should cause a parser
  error, even in browser-extended mode.
* Avoid an infinite loop when parsing the pattern "\c" on its own.
2021-08-15 11:43:45 +01:00
Ali Mohammad Pur
15f95220ae AK+Everywhere: Delete Variant's default constructor
This was exposed to the user by mistake, and even accumulated a bunch of
users that didn't blow up out of sheer luck.
2021-08-13 17:31:39 +04:30
Timothy Flynn
df14d11a11 LibRegex: Disallow invalid interval qualifiers in Unicode mode
Fixes all remaining 'built-ins/RegExp/property-escapes' test262 tests.
2021-08-11 13:11:01 +02:00
Timothy Flynn
484ccfadc3 LibRegex: Support property escapes of Unicode script extensions 2021-08-04 13:50:32 +01:00
Timothy Flynn
06088df729 LibRegex: Support property escapes of the Unicode script property
Note that unlike binary properties and general categories, scripts must
be specified in the non-binary (Script=Value) form.
2021-08-04 13:50:32 +01:00
Timothy Flynn
27d555bab0 LibRegex: Track string position in both code units and code points
In non-Unicode mode, the existing MatchState::string_position is tracked
in code units; in Unicode mode, it is tracked in code points.

In order for some RegexStringView operations to be performant, it is
useful for the MatchState to have a field to always track the position
in code units. This will allow RegexStringView methods (e.g. operator[])
to perform lookups based on code unit offsets, rather than needing to
iterate over the entire string to find a code point offset.
2021-08-04 11:18:24 +02:00
Timothy Flynn
510bbcd8e0 AK+LibRegex: Add Utf16View::code_point_at and use it in RegexStringView
The current method of iterating through the string to access a code
point hurts performance quite badly for very large strings. The test262
test "RegExp/property-escapes/generated/Any.js" previously took 3 hours
to complete; this one change brings it down to under 10 seconds.
2021-08-04 11:18:24 +02:00
Timothy Flynn
dc9f516339 LibRegex: Generate negated property escapes as a single instruction
These were previously generated as two instructions, Compare [Inverse]
and Compare [Property].
2021-08-02 21:02:09 +04:30
Timothy Flynn
4de4312827 LibRegex: Support property escapes of the form \p{Type=Value}
Before now, only binary properties could be parsed. Non-binary props are
of the form "Type=Value", where "Type" may be General_Category, Script,
or Script_Extension (or their aliases). Of these, LibUnicode currently
supports General_Category, so LibRegex can parse only that type.
2021-08-02 21:02:09 +04:30
Timothy Flynn
1e10d6d7ce LibRegex: Support property escapes of Unicode General Categories
This changes LibRegex to parse the property escape as a Variant of
Unicode Property & General Category values. A byte code instruction is
added to perform matching based on General Category values.
2021-08-02 21:02:09 +04:30
Ali Mohammad Pur
d5984d296f LibRegex: Make Matcher<>::match(Vector<>) take a reference to the vector
It was previously copying the entire vector every time, which is not a
nice thing to do. :^)
2021-08-02 17:22:50 +04:30
Ali Mohammad Pur
a7653e6a05 LibRegex: Use a bump-allocated linked list for fork save states
This makes it avoid the excessively high malloc() traffic.
2021-08-02 17:22:50 +04:30
Ali Mohammad Pur
5f342e4fa9 LibRegex: Make Fork{Jump,Stay} non-recursive
This makes very fork-heavy expressions (like `(aa)*`) not run out of
stack space when matching very long strings.
2021-08-02 17:22:50 +04:30
Brian Gianforcaro
18d6f9ed5c Libraries: Remove unused header includes 2021-08-01 08:10:16 +02:00
Timothy Flynn
d485cf29d7 LibRegex+LibUnicode: Begin implementing Unicode property escapes
This supports some binary property matching. It does not support any
properties not yet parsed by LibUnicode, nor does it support value
matching (such as Script_Extensions=Latin).
2021-07-30 21:26:31 +01:00
Timothy Flynn
1400e3cf58 LibRegex: Allow separately parsing patterns and creating Regex objects
Adds a static method to parse a regex pattern and return the result, and
a constructor to accept a parse result. This is to allow LibJS to parse
the pattern string of a RegExpLiteral once and hand off regex objects
any number of times thereafter.
2021-07-30 21:26:31 +01:00
Timothy Flynn
b162517065 LibRegex: Take ownership of pattern string and fix move operations
The Regex object created a copy of the pattern string anyways, so tweak
the constructor to allow callers to move() pattern strings into the
regex.

The Regex move constructor and assignment operator currently result in
memory corruption. The Regex object stores a Matcher object, which holds
a reference to the Regex object. So when the Regex object is moved, that
reference is no longer valid. To fix this, the reference stored in the
Matcher must be updated when the Regex is moved.
2021-07-30 21:26:31 +01:00
Timothy Flynn
4a72b2c879 LibRegex: Allow RegexOptions to be declared at compile time 2021-07-30 21:26:31 +01:00
Ali Mohammad Pur
faef523567 LibRegex: Make unclosed-at-eof brace quantifiers an error
Otherwise we'd just loop trying to parse it over and over again, for
instance in `/a{/` or `/a{1,/`.
Unless we're parsing in Annex B mode, which allows `{` as a normal
ExtendedSourceCharacter.
2021-07-24 20:52:43 +04:30
Ali Mohammad Pur
1dd1378159 LibRegex: Preserve the type of the match when clearing capture groups
Even though the contents are supposed to be reset, the type should stay
unchanged, as that's an assumption the engine is making.
2021-07-24 20:52:43 +04:30