From c358df6de43e7f68c232c53afb070015eb2bb10a Mon Sep 17 00:00:00 2001 From: Jon Zeppieri Date: Mon, 3 Feb 2020 18:21:16 -0500 Subject: [PATCH] [CS] regexp-replace: handle #f submatches A regexp can match while having sub-patterns that are not used in the match. In regexp-replace, the "insert" argument can refer to these unused sub-matches. If a function is given for the "insert" argument, it will receive these unused submatches as #f values. If a string or byte-string is given, then any reference to an unused sub-match (by means of a back-reference) is treated as the empty string or byte-string. Fixes #3032. --- pkgs/racket-test-core/tests/racket/rx.rktl | 15 +++++++++++++++ racket/src/regexp/replace/main.rkt | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkgs/racket-test-core/tests/racket/rx.rktl b/pkgs/racket-test-core/tests/racket/rx.rktl index 749efd5c65..5629d09395 100644 --- a/pkgs/racket-test-core/tests/racket/rx.rktl +++ b/pkgs/racket-test-core/tests/racket/rx.rktl @@ -1835,6 +1835,21 @@ (test #f 'optimized (regexp-match #px"a*(?=bc)" (make-bytes 100024 (char->integer #\a)))) (test #f 'optimized (regexp-match #px"a*(?<=bc)" (make-bytes 100024 (char->integer #\a)))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Ensure that regexp-replace can handle sub-matches that are #f +;; (https://github.com/racket/racket/issues/3032) +;; +(test "" regexp-replace "(x)?" "" (lambda a "")) +(test "" regexp-replace "(x)?" "" "\\1") + +(test "x" regexp-replace "x(y)?(z)?" "x" "&\\1\\2") +(test "xyy" regexp-replace "x(y)?(z)?" "xy" "&\\1\\2") + +(test "xyy[z]" regexp-replace "x(y)?(z)?" "xy" (lambda (x y z) + (string-append x + (or y "[y]") + (or z "[z]")))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/regexp/replace/main.rkt b/racket/src/regexp/replace/main.rkt index 7cb91de523..bdcab43a9a 100644 --- a/racket/src/regexp/replace/main.rkt +++ b/racket/src/regexp/replace/main.rkt @@ -80,7 +80,8 @@ [(procedure? insert) (define a (apply insert (for/list ([pos (in-list poss)]) - (subchytes in (car pos) (cdr pos))))) + (and pos + (subchytes in (car pos) (cdr pos)))))) (unless (chytes? in a) (raise-result-error who (if (bytes? in) "bytes?" "string?") a)) a] @@ -92,7 +93,10 @@ (cond [(n . < . count) (define pos (list-ref poss n)) - (subchytes in (car pos) (cdr pos))] + + (if pos + (subchytes in (car pos) (cdr pos)) + (subchytes in 0 0))] [else (subchytes in 0 0)])) (define (cons-chytes since pos l)