diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2023-06-20 12:12:50 +0200 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2023-06-21 18:00:26 +0200 |
commit | be91192ecb1e0dff794582cd463f0a6480d160ef (patch) | |
tree | 156031723d39088ce4e2dd52a3a7b7068fbc5880 /test/src | |
parent | dae8aab52874441a70a94435d50f25b27301d9b0 (diff) |
Straighten regexp postfix operator after zero-width assertion parse
The zero-width assertions \` \' \b \B were parsed in a sloppy way so
that a following postfix repetition operator could yield surprising
results. For instance, "\\b*" would act as "\\b\\*", and "xy\\b*"
would act as "\\(?:xy\\b\\)*".
Except for \` and ^, any following postfix operator now applies to the
zero-width assertion itself only, which is predictable and consistent
with other assertions, if useless in practice.
For historical compatibility, an operator character following \` and ^
always becomes a literal. (Bug#64128)
* src/regex-emacs.c (regex_compile):
Set `laststart` appropriately for each zero-width assertion instead
of leaving it with whatever value it had before.
Remove a redundant condition.
* test/src/regex-emacs-tests.el
(regexp-tests-zero-width-assertion-repetition): New test.
* doc/lispref/searching.texi (Regexp Special):
Say that repetition operators are not special after \`,
and that they work as expected after other backslash escapes.
* etc/NEWS: Announce.
Diffstat (limited to 'test/src')
-rw-r--r-- | test/src/regex-emacs-tests.el | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el index 52d43775b8e..08a93dbf30e 100644 --- a/test/src/regex-emacs-tests.el +++ b/test/src/regex-emacs-tests.el @@ -883,4 +883,70 @@ This evaluates the TESTS test cases from glibc." (should (looking-at "x*\\(=\\|:\\)*")) (should (looking-at "x*=*?")))) +(ert-deftest regexp-tests-zero-width-assertion-repetition () + ;; Check compatibility behaviour with repetition operators after + ;; certain zero-width assertions (bug#64128). + + ;; This function is just to hide ugly regexps from relint so that it + ;; doesn't complain about them. + (cl-flet ((smatch (re str) (string-match re str))) + ;; Postfix operators after ^ and \` become literals, for historical + ;; compatibility. Only the first character of a lazy operator (like *?) + ;; becomes a literal. + (should (equal (smatch "^*a" "x\n*a") 2)) + (should (equal (smatch "^*?a" "x\n*a") 2)) + (should (equal (smatch "^*?a" "x\na") 2)) + (should (equal (smatch "^*?a" "x\n**a") nil)) + + (should (equal (smatch "\\`*a" "*a") 0)) + (should (equal (smatch "\\`*?a" "*a") 0)) + (should (equal (smatch "\\`*?a" "a") 0)) + (should (equal (smatch "\\`*?a" "**a") nil)) + + ;; Other zero-width assertions are treated as normal elements, so postfix + ;; operators apply to them alone (which is pointless but valid). + (should (equal (smatch "\\b*!" "*!") 1)) + (should (equal (smatch "!\\b+;" "!;") nil)) + (should (equal (smatch "!\\b+a" "!a") 0)) + + (should (equal (smatch "\\B*!" "*!") 1)) + (should (equal (smatch "!\\B+;" "!;") 0)) + (should (equal (smatch "!\\B+a" "!a") nil)) + + (should (equal (smatch "\\<*b" "*b") 1)) + (should (equal (smatch "a\\<*b" "ab") 0)) + (should (equal (smatch ";\\<*b" ";b") 0)) + (should (equal (smatch "a\\<+b" "ab") nil)) + (should (equal (smatch ";\\<+b" ";b") 0)) + + (should (equal (smatch "\\>*;" "*;") 1)) + (should (equal (smatch "a\\>*b" "ab") 0)) + (should (equal (smatch "a\\>*;" "a;") 0)) + (should (equal (smatch "a\\>+b" "ab") nil)) + (should (equal (smatch "a\\>+;" "a;") 0)) + + (should (equal (smatch "a\\'" "ab") nil)) + (should (equal (smatch "b\\'" "ab") 1)) + (should (equal (smatch "a\\'*b" "ab") 0)) + (should (equal (smatch "a\\'+" "ab") nil)) + (should (equal (smatch "b\\'+" "ab") 1)) + (should (equal (smatch "\\'+" "+") 1)) + + (should (equal (smatch "\\_<*b" "*b") 1)) + (should (equal (smatch "a\\_<*b" "ab") 0)) + (should (equal (smatch " \\_<*b" " b") 0)) + (should (equal (smatch "a\\_<+b" "ab") nil)) + (should (equal (smatch " \\_<+b" " b") 0)) + + (should (equal (smatch "\\_>*;" "*;") 1)) + (should (equal (smatch "a\\_>*b" "ab") 0)) + (should (equal (smatch "a\\_>* " "a ") 0)) + (should (equal (smatch "a\\_>+b" "ab") nil)) + (should (equal (smatch "a\\_>+ " "a ") 0)) + + (should (equal (smatch "\\=*b" "*b") 1)) + (should (equal (smatch "a\\=*b" "a*b") nil)) + (should (equal (smatch "a\\=*b" "ab") 0)) + )) + ;;; regex-emacs-tests.el ends here |