diff options
author | bptato <nincsnevem662@gmail.com> | 2023-07-25 22:10:28 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-07-25 22:10:28 +0200 |
commit | dcec174b2af3af816180772f948575f896d58d20 (patch) | |
tree | 72006d4d310f7f7411b9e684567786e9b634f902 /src/js | |
parent | 5153b064d59b627cd2ea061bf88078cbfddfafa6 (diff) | |
download | chawan-dcec174b2af3af816180772f948575f896d58d20.tar.gz |
Add compileMatchRegex
This makes it so that host = 'example\.org' mandates an exact match, but host = '^example' matches example.org, example.com, etc. (Previously, 'example\.org' would have matched exampleexample.org as well, which was quite counter-intuitive.)
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/regex.nim | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/js/regex.nim b/src/js/regex.nim index d1ec34a5..eb6ef80f 100644 --- a/src/js/regex.nim +++ b/src/js/regex.nim @@ -68,6 +68,41 @@ proc compileRegex*(buf: string, flags: int): Result[Regex, string] = regex.bytecode = bytecode return ok(regex) +func countBackslashes(buf: string, i: int): int = + var j = 0 + for i in countdown(i, 0): + if buf[i] != '\\': + break + inc j + return j + +# ^abcd -> ^abcd +# efgh$ -> efgh$ +# ^ijkl$ -> ^ijkl$ +# mnop -> ^mnop$ +proc compileMatchRegex*(buf: string): Result[Regex, string] = + if buf.len == 0: + return compileRegex(buf, 0) + if buf[0] == '^': + return compileRegex(buf, 0) + if buf[^1] == '$': + # Check whether the final dollar sign is escaped. + if buf.len == 1 or buf[^2] != '\\': + return compileRegex(buf, 0) + let j = buf.countBackslashes(buf.high - 2) + if j mod 2 == 1: # odd, because we do not count the last backslash + return compileRegex(buf, 0) + # escaped. proceed as if no dollar sign was at the end + if buf[^1] == '\\': + # Check if the regex contains an invalid trailing backslash. + let j = buf.countBackslashes(buf.high - 1) + if j mod 2 != 1: # odd, because we do not count the last backslash + return err("unexpected end") + var buf2 = "^" + buf2 &= buf + buf2 &= "$" + return compileRegex(buf2, 0) + proc compileSearchRegex*(str: string): Result[Regex, string] = # Parse any applicable flags in regex/<flags>. The last forward slash is # dropped when <flags> is empty, and interpreted as a character when the |