summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/syntax.el
diff options
context:
space:
mode:
authorTassilo Horn <tsdh@gnu.org>2020-05-16 10:05:12 +0200
committerTassilo Horn <tsdh@gnu.org>2020-05-19 20:50:14 +0200
commit5af991872d5024b69272588772961bafef5a35bb (patch)
treeb0da97f1d2888441e5c1bbf807e42277227ae105 /lisp/emacs-lisp/syntax.el
parent659ed857c04936140fea847795f8b85c5dcc3920 (diff)
downloademacs-5af991872d5024b69272588772961bafef5a35bb.tar.gz
Allow back-references in syntax-propertize-rules.
* lisp/emacs-lisp/syntax.el (syntax-propertize--shift-groups-and-backrefs): Renamed from syntax-propertize--shift-groups, and also shift back-references. (syntax-propertize-rules): Adapt docstring and use renamed function. * test/lisp/emacs-lisp/syntax-tests.el: New test. (syntax-propertize--shift-groups-and-backrefs): New ERT test.
Diffstat (limited to 'lisp/emacs-lisp/syntax.el')
-rw-r--r--lisp/emacs-lisp/syntax.el35
1 files changed, 25 insertions, 10 deletions
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index 46dc8d9ade8..ce495af95bc 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -139,14 +139,28 @@ delimiter or an Escaped or Char-quoted character."))
(point-max))))
(cons beg end))
-(defun syntax-propertize--shift-groups (re n)
- (replace-regexp-in-string
- "\\\\(\\?\\([0-9]+\\):"
- (lambda (s)
- (replace-match
- (number-to-string (+ n (string-to-number (match-string 1 s))))
- t t s 1))
- re t t))
+(defun syntax-propertize--shift-groups-and-backrefs (re n)
+ (let ((new-re (replace-regexp-in-string
+ "\\\\(\\?\\([0-9]+\\):"
+ (lambda (s)
+ (replace-match
+ (number-to-string
+ (+ n (string-to-number (match-string 1 s))))
+ t t s 1))
+ re t t))
+ (pos 0))
+ (while (string-match "\\\\\\([0-9]+\\)" new-re pos)
+ (setq pos (+ 1 (match-beginning 1)))
+ (when (save-match-data
+ ;; With \N, the \ must be in a subregexp context, i.e.,
+ ;; not in a character class or in a \{\} repetition.
+ (subregexp-context-p new-re (match-beginning 0)))
+ (let ((shifted (+ n (string-to-number (match-string 1 new-re)))))
+ (when (> shifted 9)
+ (error "There may be at most nine back-references"))
+ (setq new-re (replace-match (number-to-string shifted)
+ t t new-re 1)))))
+ new-re))
(defmacro syntax-propertize-precompile-rules (&rest rules)
"Return a precompiled form of RULES to pass to `syntax-propertize-rules'.
@@ -190,7 +204,8 @@ for subsequent HIGHLIGHTs.
Also SYNTAX is free to move point, in which case RULES may not be applied to
some parts of the text or may be applied several times to other parts.
-Note: back-references in REGEXPs do not work."
+Note: There may be at most nine back-references in the REGEXPs of
+all RULES in total."
(declare (debug (&rest &or symbolp ;FIXME: edebug this eval step.
(form &rest
(numberp
@@ -219,7 +234,7 @@ Note: back-references in REGEXPs do not work."
;; tell when *this* match 0 has succeeded.
(cl-incf offset)
(setq re (concat "\\(" re "\\)")))
- (setq re (syntax-propertize--shift-groups re offset))
+ (setq re (syntax-propertize--shift-groups-and-backrefs re offset))
(let ((code '())
(condition
(cond