summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/syntax.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/syntax.el')
-rw-r--r--lisp/emacs-lisp/syntax.el136
1 files changed, 74 insertions, 62 deletions
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index f27596f77c7..6464e2a52db 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -176,7 +176,7 @@ Note: back-references in REGEXPs do not work."
(re
(mapconcat
(lambda (rule)
- (let* ((orig-re (eval (car rule)))
+ (let* ((orig-re (eval (car rule) t))
(re orig-re))
(when (and (assq 0 rule) (cdr rules))
;; If there's more than 1 rule, and the rule want to apply
@@ -190,7 +190,7 @@ Note: back-references in REGEXPs do not work."
(cond
((assq 0 rule) (if (zerop offset) t
`(match-beginning ,offset)))
- ((null (cddr rule))
+ ((and (cdr rule) (null (cddr rule)))
`(match-beginning ,(+ offset (car (cadr rule)))))
(t
`(or ,@(mapcar
@@ -283,10 +283,13 @@ END) suitable for `syntax-propertize-function'."
;; In case it was eval'd/compiled.
(setq keywords font-lock-syntactic-keywords)))))
+(defvar-local syntax-ppss-table nil
+ "Syntax-table to use during `syntax-ppss', if any.")
+
(defun syntax-propertize (pos)
"Ensure that syntax-table properties are set until POS (a buffer point)."
(when (< syntax-propertize--done pos)
- (if (null syntax-propertize-function)
+ (if (memq syntax-propertize-function '(nil ignore))
(setq syntax-propertize--done (max (point-max) pos))
;; (message "Needs to syntax-propertize from %s to %s"
;; syntax-propertize--done pos)
@@ -298,50 +301,51 @@ END) suitable for `syntax-propertize-function'."
;; between syntax-ppss and syntax-propertize, we also have to make
;; sure the flush function is installed here (bug#29767).
(add-hook 'before-change-functions
- #'syntax-ppss-flush-cache t t))
+ #'syntax-ppss-flush-cache 99 t))
(save-excursion
(with-silent-modifications
- (make-local-variable 'syntax-propertize--done) ;Just in case!
- (let* ((start (max (min syntax-propertize--done (point-max))
- (point-min)))
- (end (max pos
- (min (point-max)
- (+ start syntax-propertize-chunk-size))))
- (funs syntax-propertize-extend-region-functions))
- (while funs
- (let ((new (funcall (pop funs) start end))
- ;; Avoid recursion!
- (syntax-propertize--done most-positive-fixnum))
- (if (or (null new)
- (and (>= (car new) start) (<= (cdr new) end)))
- nil
- (setq start (car new))
- (setq end (cdr new))
- ;; If there's been a change, we should go through the
- ;; list again since this new position may
- ;; warrant a different answer from one of the funs we've
- ;; already seen.
- (unless (eq funs
- (cdr syntax-propertize-extend-region-functions))
- (setq funs syntax-propertize-extend-region-functions)))))
- ;; Flush ppss cache between the original value of `start' and that
- ;; set above by syntax-propertize-extend-region-functions.
- (syntax-ppss-flush-cache start)
- ;; Move the limit before calling the function, so the function
- ;; can use syntax-ppss.
- (setq syntax-propertize--done end)
- ;; (message "syntax-propertizing from %s to %s" start end)
- (remove-text-properties start end
- '(syntax-table nil syntax-multiline nil))
- ;; Avoid recursion!
- (let ((syntax-propertize--done most-positive-fixnum))
- (funcall syntax-propertize-function start end))))))))
+ (with-syntax-table (or syntax-ppss-table (syntax-table))
+ (make-local-variable 'syntax-propertize--done) ;Just in case!
+ (let* ((start (max (min syntax-propertize--done (point-max))
+ (point-min)))
+ (end (max pos
+ (min (point-max)
+ (+ start syntax-propertize-chunk-size))))
+ (funs syntax-propertize-extend-region-functions))
+ (while funs
+ (let ((new (funcall (pop funs) start end))
+ ;; Avoid recursion!
+ (syntax-propertize--done most-positive-fixnum))
+ (if (or (null new)
+ (and (>= (car new) start) (<= (cdr new) end)))
+ nil
+ (setq start (car new))
+ (setq end (cdr new))
+ ;; If there's been a change, we should go through the
+ ;; list again since this new position may
+ ;; warrant a different answer from one of the funs we've
+ ;; already seen.
+ (unless (eq funs
+ (cdr syntax-propertize-extend-region-functions))
+ (setq funs syntax-propertize-extend-region-functions)))))
+ ;; Flush ppss cache between the original value of `start' and that
+ ;; set above by syntax-propertize-extend-region-functions.
+ (syntax-ppss-flush-cache start)
+ ;; Move the limit before calling the function, so the function
+ ;; can use syntax-ppss.
+ (setq syntax-propertize--done end)
+ ;; (message "syntax-propertizing from %s to %s" start end)
+ (remove-text-properties start end
+ '(syntax-table nil syntax-multiline nil))
+ ;; Avoid recursion!
+ (let ((syntax-propertize--done most-positive-fixnum))
+ (funcall syntax-propertize-function start end)))))))))
;;; Link syntax-propertize with syntax.c.
(defvar syntax-propertize-chunks
;; We're not sure how far we'll go. In my tests, using chunks of 2000
- ;; brings to overhead to something negligible. Passing ‘charpos’ directly
+ ;; brings the overhead to something negligible. Passing ‘charpos’ directly
;; also works (basically works line-by-line) but results in an overhead which
;; I thought was a bit too high (like around 50%).
2000)
@@ -367,6 +371,10 @@ itself at the outermost level), return nil."
(nth 8 ppss)))
(defsubst syntax-ppss-context (ppss)
+ "Say whether PPSS is a string, a comment, or something else.
+If PPSS is a string, the symbol `string' is returned. If it's a
+comment, the symbol `comment' is returned. If it's something
+else, nil is returned."
(cond
((nth 3 ppss) 'string)
((nth 4 ppss) 'comment)
@@ -404,7 +412,8 @@ These are valid when the buffer has no restriction.")
(defvar-local syntax-ppss-narrow-start nil
"Start position of the narrowing for `syntax-ppss-narrow'.")
-(defalias 'syntax-ppss-after-change-function 'syntax-ppss-flush-cache)
+(define-obsolete-function-alias 'syntax-ppss-after-change-function
+ #'syntax-ppss-flush-cache "27.1")
(defun syntax-ppss-flush-cache (beg &rest ignored)
"Flush the cache of `syntax-ppss' starting at position BEG."
;; Set syntax-propertize to refontify anything past beg.
@@ -429,22 +438,25 @@ These are valid when the buffer has no restriction.")
;; Unregister if there's no cache left. Sadly this doesn't work
;; because `before-change-functions' is temporarily bound to nil here.
;; (unless cache
- ;; (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t))
+ ;; (remove-hook 'before-change-functions #'syntax-ppss-flush-cache t))
(setcar cell last)
(setcdr cell cache)))
))
+;;; FIXME: Explain this variable. Currently only its last (5th) slot is used.
+;;; Perhaps the other slots should be removed?
(defvar syntax-ppss-stats
- [(0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (1 . 2500.0)])
+ [(0 . 0) (0 . 0) (0 . 0) (0 . 0) (0 . 0) (2 . 2500)])
(defun syntax-ppss-stats ()
(mapcar (lambda (x)
(condition-case nil
- (cons (car x) (truncate (/ (cdr x) (car x))))
+ (cons (car x) (/ (cdr x) (car x)))
(error nil)))
syntax-ppss-stats))
-
-(defvar-local syntax-ppss-table nil
- "Syntax-table to use during `syntax-ppss', if any.")
+(defun syntax-ppss--update-stats (i old new)
+ (let ((pair (aref syntax-ppss-stats i)))
+ (cl-incf (car pair))
+ (cl-incf (cdr pair) (- new old))))
(defun syntax-ppss--data ()
(if (eq (point-min) 1)
@@ -486,11 +498,10 @@ running the hook."
(if (and old-pos (< (- pos old-pos)
;; The time to use syntax-begin-function and
;; find PPSS is assumed to be about 2 * distance.
- (* 2 (/ (cdr (aref syntax-ppss-stats 5))
- (1+ (car (aref syntax-ppss-stats 5)))))))
+ (let ((pair (aref syntax-ppss-stats 5)))
+ (/ (* 2 (cdr pair)) (car pair)))))
(progn
- (cl-incf (car (aref syntax-ppss-stats 0)))
- (cl-incf (cdr (aref syntax-ppss-stats 0)) (- pos old-pos))
+ (syntax-ppss--update-stats 0 old-pos pos)
(parse-partial-sexp old-pos pos nil nil old-ppss))
(cond
@@ -506,8 +517,7 @@ running the hook."
(setq pt-min (or (syntax-ppss-toplevel-pos old-ppss)
(nth 2 old-ppss)))
(<= pt-min pos) (< (- pos pt-min) syntax-ppss-max-span))
- (cl-incf (car (aref syntax-ppss-stats 1)))
- (cl-incf (cdr (aref syntax-ppss-stats 1)) (- pos pt-min))
+ (syntax-ppss--update-stats 1 pt-min pos)
(setq ppss (parse-partial-sexp pt-min pos)))
;; The OLD-* data can't be used. Consult the cache.
(t
@@ -529,14 +539,19 @@ running the hook."
;; Setup the before-change function if necessary.
(unless (or ppss-cache ppss-last)
+ ;; Note: combine-change-calls-1 needs to be kept in sync
+ ;; with this!
(add-hook 'before-change-functions
- 'syntax-ppss-flush-cache t t))
+ #'syntax-ppss-flush-cache
+ ;; We should be either the very last function on
+ ;; before-change-functions or the very first on
+ ;; after-change-functions.
+ 99 t))
;; Use the best of OLD-POS and CACHE.
(if (or (not old-pos) (< old-pos pt-min))
(setq pt-best pt-min ppss-best ppss)
- (cl-incf (car (aref syntax-ppss-stats 4)))
- (cl-incf (cdr (aref syntax-ppss-stats 4)) (- pos old-pos))
+ (syntax-ppss--update-stats 4 old-pos pos)
(setq pt-best old-pos ppss-best old-ppss))
;; Use the `syntax-begin-function' if available.
@@ -556,21 +571,18 @@ running the hook."
(not (memq (get-text-property (point) 'face)
'(font-lock-string-face font-lock-doc-face
font-lock-comment-face))))
- (cl-incf (car (aref syntax-ppss-stats 5)))
- (cl-incf (cdr (aref syntax-ppss-stats 5)) (- pos (point)))
+ (syntax-ppss--update-stats 5 (point) pos)
(setq pt-best (point) ppss-best nil))
(cond
;; Quick case when we found a nearby pos.
((< (- pos pt-best) syntax-ppss-max-span)
- (cl-incf (car (aref syntax-ppss-stats 2)))
- (cl-incf (cdr (aref syntax-ppss-stats 2)) (- pos pt-best))
+ (syntax-ppss--update-stats 2 pt-best pos)
(setq ppss (parse-partial-sexp pt-best pos nil nil ppss-best)))
;; Slow case: compute the state from some known position and
;; populate the cache so we won't need to do it again soon.
(t
- (cl-incf (car (aref syntax-ppss-stats 3)))
- (cl-incf (cdr (aref syntax-ppss-stats 3)) (- pos pt-min))
+ (syntax-ppss--update-stats 3 pt-min pos)
;; If `pt-min' is too far, add a few intermediate entries.
(while (> (- pos pt-min) (* 2 syntax-ppss-max-span))