[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/wisi 8bdcee1 11/35: publish ada-mode 5.1.6, wisi 1.0.6,
From: |
Stefan Monnier |
Subject: |
[elpa] externals/wisi 8bdcee1 11/35: publish ada-mode 5.1.6, wisi 1.0.6, new package ada-ref-man |
Date: |
Sat, 28 Nov 2020 14:47:51 -0500 (EST) |
branch: externals/wisi
commit 8bdcee1fa6adaef1ccdc411b444b4236923bd94f
Author: Stephen Leake <stephen_leake@stephe-leake.org>
Commit: Stephen Leake <stephen_leake@stephe-leake.org>
publish ada-mode 5.1.6, wisi 1.0.6, new package ada-ref-man
* admin/archive-contents.el (archive--metadata): include 'dir' in files,
for doc-only packages
(archive--metadata): fix typo in error message
* packages/ada-mode/ada-ref-man.el: New file.
* packages/ada-mode/*: version 5.1.6
* packages/ada-ref-man/: New directory.
* packages/wisi/*: version 1.0.6
* packages/wisi/README: New file.
---
README | 14 +++
wisi-compile.el | 7 +-
wisi-parse.el | 126 +++++++++++++------
wisi.el | 383 +++++++++++++++++++++++++++++++++++++-------------------
4 files changed, 362 insertions(+), 168 deletions(-)
diff --git a/README b/README
new file mode 100755
index 0000000..cbf97c9
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
+Emacs wisi package 1.0.6
+
+The wisi package provides utilities for using generalized LALR parsers
+to do indentation and navigation. See ada-mode for an example of its
+use.
+
+It is provided as a Gnu ELPA package; to install the package, add to
+~./emacs:
+
+(package-initialize)
+
+then invoke M-x list-packages, install wisi.
+
+(end of file)
diff --git a/wisi-compile.el b/wisi-compile.el
index 39ed689..a17b7f6 100755
--- a/wisi-compile.el
+++ b/wisi-compile.el
@@ -49,8 +49,11 @@
(eval-when-compile
;; can't just 'require'; `wisent-with-context' doesn't work.
- ;; also can't load .elc; must load .el
- (load (locate-library "semantic/wisent/comp.el")))
+ ;; also can't load .elc; must load .el or .el.gz
+ (let ((file (locate-library "semantic/wisent/comp.el")))
+ (if file
+ (load file)
+ (error "source library semantic/wisent/comp.el not installed; install
emacs lisp sources"))))
(eval-and-compile
(require 'semantic/wisent/comp))
diff --git a/wisi-parse.el b/wisi-parse.el
index bd7ce7e..e3b3da6 100755
--- a/wisi-parse.el
+++ b/wisi-parse.el
@@ -29,6 +29,28 @@
(require 'cl-lib)
(require 'semantic/wisent)
+;; WORKAROUND: for some reason, this condition doesn't work in batch mode!
+;; (when (and (= emacs-major-version 24)
+;; (= emacs-minor-version 2))
+ (require 'wisi-compat-24.2)
+;;)
+
+(defvar wisi-parse-max-parallel 15
+ "Maximum number of parallel parsers for acceptable performance.
+If a file needs more than this, it's probably an indication that
+the grammar is excessively redundant.")
+
+(defvar wisi-parse-max-parallel-current (cons 0 0)
+ "Cons (count . point); Maximum number of parallel parsers used in most
recent parse,
+point at which that max was spawned.")
+
+(defvar wisi-debug 0
+ "wisi debug mode:
+0 : normal - ignore parse errors, for indenting new code
+1 : report parse errors (for running tests)
+2 : show parse states, position point at parse errors, debug-on-error works in
parser
+3 : also show top 10 items of parser stack.")
+
(cl-defstruct (wisi-parser-state
(:copier nil))
label ;; integer identifying parser for debug
@@ -70,31 +92,19 @@
'error-message
"wisi parse error")
-(defvar wisi-parse-max-parallel 15
- "Maximum number of parallel parsers for acceptable performance.
-If a file needs more than this, it's probably an indication that
-the grammar is excessively redundant.")
-
-(defvar wisi-parse-max-parallel-current (cons 0 0)
- "Cons (count . point); Maximum number of parallel parsers used in most
recent parse,
-point at which that max was spawned.")
-
-(defvar wisi-debug 0
- "wisi debug mode:
-0 : normal - ignore parse errors, for indenting new code
-1 : report parse errors (for running tests)
-2 : show parse states, position point at parse errors, debug-on-error works in
parser
-3 : also show top 10 items of parser stack.")
+(defvar-local wisi-cache-max 0
+ "Maximimum position in buffer where wisi-cache text properties are valid.")
(defun wisi-parse (automaton lexer)
- "Parse input using the automaton specified in AUTOMATON.
+ "Parse current buffer from bob using the automaton specified in AUTOMATON.
- AUTOMATON is the parse table generated by `wisi-compile-grammar'.
- LEXER is a function with no argument called by the parser to
- obtain the next token in input, as a list (symbol text start
- . end), where `symbol' is the terminal symbol, `text' is the
- token string, `start . end' is the range in the buffer."
+ obtain the next token from the current buffer after point, as a
+ list (symbol text start . end), where `symbol' is the terminal
+ symbol, `text' is the token string, `start . end' is the range
+ in the buffer."
(let* ((actions (aref automaton 0))
(gotos (aref automaton 1))
(parser-states ;; vector of parallel parser states
@@ -108,12 +118,15 @@ point at which that max was spawned.")
(active-parser-count 1)
active-parser-count-prev
(active 'shift)
- (token (funcall lexer))
- some-pending)
+ (token nil)
+ some-pending
+ )
- (setq wisi-parse-max-parallel-current (cons 0 0))
+ (goto-char (point-min))
+ (aset (wisi-parser-state-stack (aref parser-states 0)) 0 0)
- (aset (wisi-parser-state-stack (aref parser-states 0)) 0 0) ;; Initial
state
+ (setq token (funcall lexer))
+ (setq wisi-parse-max-parallel-current (cons 0 0))
(while (not (eq active 'accept))
(setq active-parser-count-prev active-parser-count)
@@ -126,8 +139,12 @@ point at which that max was spawned.")
;; spawn a new parser
(when (= active-parser-count wisi-parse-max-parallel)
(signal 'wisi-parse-error
- (wisi-error-msg (concat "too many parallel parsers
required;"
- " simplify grammar, or increase
`wisi-parse-max-parallel'"))))
+ (let ((state (aref (wisi-parser-state-stack
parser-state)
+ (wisi-parser-state-sp
parser-state))))
+ (wisi-error-msg (concat "too many parallel parsers
required in grammar state %d;"
+ " simplify grammar, or
increase `wisi-parse-max-parallel'"
+ state)))))
+
(let ((j (wisi-free-parser parser-states)))
(cond
((= j -1)
@@ -223,11 +240,23 @@ point at which that max was spawned.")
(when (eq active 'shift)
(when (> active-parser-count 1)
(setq active-parser-count (wisi-parse-elim-identical parser-states
active-parser-count)))
+
(setq token (funcall lexer)))
)
(when (> active-parser-count 1)
(error "ambiguous parse result"))))
+(defun wisi-parsers-active-index (parser-states)
+ ;; only called when active-parser-count = 1
+ (let ((result nil)
+ (i 0))
+ (while (and (not result)
+ (< i (length parser-states)))
+ (when (wisi-parser-state-active (aref parser-states i))
+ (setq result i))
+ (setq i (1+ i)))
+ result))
+
(defun wisi-parsers-active (parser-states active-count)
"Return the type of parser cycle to execute.
PARSER-STATES[*].active is the last action a parser took. If it
@@ -235,6 +264,8 @@ was 'shift, that parser used the input token, and should
not be
executed again until another input token is available, after all
parsers have shifted the current token or terminated.
+Returns one of:
+
'accept : all PARSER-STATES have active set to nil or 'accept -
done parsing
@@ -264,7 +295,9 @@ token, execute 'reduce parsers."
'accept)
((= (+ shift-count accept-count) active-count)
'shift)
- (t (error "unexpected result in wisi-parsers-active"))
+ (t
+ ;; all parsers in error state; should not get here
+ (error "all parsers in error state; programmer error"))
)))
(defun wisi-free-parser (parser-states)
@@ -332,19 +365,37 @@ nil, 'shift, or 'accept."
)))
active-parser-count)
+(defun wisi-parse-max-pos (tokens)
+ "Return max position in tokens, or point if tokens nil."
+ (let ((result (if tokens 0 (point))))
+ (mapc
+ (lambda (token)
+ (when (cl-cdddr token)
+ (setq result (max (cl-cdddr token) result))))
+ tokens)
+ result)
+ )
+
+(defun wisi-parse-exec-action (func tokens)
+ "Execute action if all tokens past wisi-cache-max."
+ ;; We don't execute actions if all tokens are before wisi-cache-max,
+ ;; because later actions can update existing caches, and if the
+ ;; parse fails that won't happen. It also saves time.
+ (if (>= (wisi-parse-max-pos tokens) wisi-cache-max)
+
+ (funcall func tokens)
+
+ (when (> wisi-debug 1)
+ (message "... action skipped"))
+ ))
+
(defun wisi-execute-pending (pending)
(while pending
(when (> wisi-debug 1) (message "%s" (car pending)))
- (cond
- ((and (>= emacs-major-version 24)
- (>= emacs-minor-version 3))
- (apply (pop pending)))
-
- (t
- (let ((func-args (pop pending)))
- (apply (car func-args) (cdr func-args))))
- )))
+ (let ((func-args (pop pending)))
+ (wisi-parse-exec-action (car func-args) (cadr func-args)))
+ ))
(defun wisi-parse-1 (token parser-state pendingp actions gotos)
"Perform one shift or reduce on PARSER-STATE.
@@ -468,7 +519,10 @@ the first and last tokens of the nonterminal."
(list (list (nth 1 action) tokens))))
(setf (wisi-parser-state-pending parser-state)
(list (list (nth 1 action) tokens))))
- (funcall (nth 1 action) tokens))
+
+ ;; Not pending.
+ (wisi-parse-exec-action (nth 1 action) tokens)
+ )
))
(provide 'wisi-parse)
diff --git a/wisi.el b/wisi.el
index d4cd8e6..509e6ba 100755
--- a/wisi.el
+++ b/wisi.el
@@ -3,7 +3,11 @@
;; Copyright (C) 2012 - 2014 Free Software Foundation, Inc.
;;
;; Author: Stephen Leake <stephen_leake@member.fsf.org>
-;; Version: 1.0.5
+;; Maintainer: Stephen Leake <stephen_leake@member.fsf.org>
+;; Keywords: parser
+;; indentation
+;; navigation
+;; Version: 1.0.6
;; package-requires: ((cl-lib "0.4") (emacs "24.2"))
;; URL: http://stephe-leake.org/emacs/ada-mode/emacs-ada-mode.html
;;
@@ -25,7 +29,7 @@
;;; Commentary:
-;;;; History: first experimental version Oct 2012
+;;;; History: see NEWS-wisi.text
;;
;;;; indentation algorithm overview
;;
@@ -131,6 +135,15 @@
;; that in functions that return tokens in the form wisi-parse
;; expects.
;;
+;;;; lexer
+;;
+;; The lexer is `wisi-forward-token'. It relies on syntax properties,
+;; so syntax-propertize must be called on the text to be lexed before
+;; wisi-forward-token is called. In general, it is hard to determine
+;; an appropriate end-point for syntax-propertize, other than
+;; point-max. So we call (syntax-propertize point-max) in wisi-setup,
+;; and also call syntax-propertize in wisi-after-change.
+;;
;;;; code style
;;
;; 'wisi' was originally short for "wisent indentation engine", but
@@ -218,19 +231,28 @@ If at end of buffer, returns `wisent-eoi-term'."
(setq token-id (symbol-value (intern-soft token-text
wisi-keyword-table))))
((eq syntax 7)
- ;; string quote, either single or double. we assume point is before the
start quote, not the end quote
+ ;; string quote, either single or double. we assume point is
+ ;; before the start quote, not the end quote
(let ((delim (char-after (point)))
(forward-sexp-function nil))
- (forward-sexp)
- ;; point is now after the end quote; check for an escaped quote
- (while (or
- (and wisi-string-quote-escape-doubled
- (eq (char-after (point)) delim))
- (and (eq delim (car wisi-string-quote-escape))
- (eq (char-before (1- (point))) (cdr
wisi-string-quote-escape))))
- (forward-sexp))
- (setq token-text (buffer-substring-no-properties start (point)))
- (setq token-id (if (= delim ?\") wisi-string-double-term
wisi-string-single-term))))
+ (condition-case err
+ (progn
+ (forward-sexp)
+
+ ;; point is now after the end quote; check for an escaped quote
+ (while (or
+ (and wisi-string-quote-escape-doubled
+ (eq (char-after (point)) delim))
+ (and (eq delim (car wisi-string-quote-escape))
+ (eq (char-before (1- (point))) (cdr
wisi-string-quote-escape))))
+ (forward-sexp))
+ (setq token-text (buffer-substring-no-properties start (point)))
+ (setq token-id (if (= delim ?\") wisi-string-double-term
wisi-string-single-term)))
+ (scan-error
+ ;; Something screwed up; we should not get here if
+ ;; syntax-propertize works properly.
+ (error "wisi-forward-token: forward-sexp failed %s" err)
+ ))))
(t ;; assuming word syntax
(skip-syntax-forward "w_'")
@@ -241,7 +263,8 @@ If at end of buffer, returns `wisent-eoi-term'."
);; cond
(unless token-id
- (error (wisi-error-msg "unrecognized token '%s'"
(buffer-substring-no-properties start (point)))))
+ (signal 'wisi-parse-error
+ (wisi-error-msg "unrecognized token '%s'"
(buffer-substring-no-properties start (point)))))
(if text-only
token-text
@@ -317,12 +340,10 @@ wisi-forward-token, but does not look up symbol."
prev ;; marker at previous motion token in statement; nil if none
next ;; marker at next motion token in statement; nil if none
- end ;; marker at token at end of current statement
+ end ;; marker at token at end of current statement
+ face ;; for font-lock. only set when regexp font-lock can't handle it
)
-(defvar-local wisi-cache-max 0
- "Maximimum position in buffer where wisi token cache is valid.")
-
(defvar-local wisi-parse-table nil)
(defvar-local wisi-parse-failed nil
@@ -331,21 +352,29 @@ wisi-forward-token, but does not look up symbol."
(defvar-local wisi-parse-try nil
"Non-nil when parse is needed - cleared when parse succeeds.")
-(defvar-local wisi-change-need-invalidate nil)
+(defvar-local wisi-change-need-invalidate nil
+ "When non-nil, buffer position to invalidate from.
+Used in before/after change functions.")
-(defvar wisi-end-caches nil
+(defvar-local wisi-end-caches nil
"List of buffer positions of caches in current statement that need
wisi-cache-end set.")
-(defun wisi-invalidate-cache()
- "Invalidate the wisi token cache for the current buffer.
-Also invalidate the Emacs syntax cache."
+(defun wisi-invalidate-cache(&optional after)
+ "Invalidate parsing caches for the current buffer from AFTER to end of
buffer.
+Caches are the Emacs syntax cache, the wisi token cache, and the wisi parser
cache."
(interactive)
- (setq wisi-cache-max 0)
+ (if (not after)
+ (setq after (point-min))
+ (setq after
+ (save-excursion
+ (goto-char after)
+ (line-beginning-position))))
+ (when (> wisi-debug 0) (message "wisi-invalidate %s:%d" (current-buffer)
after))
+ (setq wisi-cache-max after)
(setq wisi-parse-try t)
- (setq wisi-end-caches nil)
- (syntax-ppss-flush-cache (point-min))
+ (syntax-ppss-flush-cache after)
(with-silent-modifications
- (remove-text-properties (point-min) (point-max) '(wisi-cache))))
+ (remove-text-properties after (point-max) '(wisi-cache nil))))
(defun wisi-before-change (begin end)
"For `before-change-functions'."
@@ -363,49 +392,64 @@ Also invalidate the Emacs syntax cache."
(add-hook 'after-change-functions 'wisi-after-change nil t))
)
- (save-excursion
- ;; don't invalidate parse for whitespace, string, or comment changes
- (let (;; (info "(elisp)Parser State")
- (state (syntax-ppss begin)))
- ;; syntax-ppss has moved point to "begin".
- (cond
- ((or
- (nth 3 state); in string
- (nth 4 state)); in comment
- ;; FIXME: check that entire range is in comment or string
- (setq wisi-change-need-invalidate nil))
-
- ((progn
- (skip-syntax-forward " " end);; does not skip newline
- (eq (point) end))
- (setq wisi-change-need-invalidate nil))
-
- (t (setq wisi-change-need-invalidate t))
- ))))
+ (setq wisi-change-need-invalidate nil)
+
+ (when (and (> end begin)
+ (>= wisi-cache-max begin))
+
+ (when wisi-parse-failed
+ ;; The parse was failing, probably due to bad syntax; this change
+ ;; may have fixed it, so try reparse.
+ (setq wisi-parse-try t))
+
+ (save-excursion
+ ;; don't invalidate parse for whitespace, string, or comment changes
+ (let (;; (info "(elisp)Parser State")
+ (state (syntax-ppss begin)))
+ ;; syntax-ppss has moved point to "begin".
+ (cond
+ ((or
+ (nth 3 state); in string
+ (nth 4 state)); in comment
+ ;; FIXME: check that entire range is in comment or string
+ )
+
+ ((progn
+ (skip-syntax-forward " " end);; does not skip newline
+ (eq (point) end)))
+
+ (t
+ (setq wisi-change-need-invalidate
+ (progn
+ (wisi-goto-statement-start)
+ (point))))
+ ))))
+ )
(defun wisi-after-change (begin end length)
"For `after-change-functions'."
- ;; begin . end is range of text being inserted (may be empty)
+ ;; begin . end is range of text being inserted (empty if equal)
;; (syntax-ppss-flush-cache begin) is in before-change-functions
- (cond
- (wisi-parse-failed
- ;; The parse was failing, probably due to bad syntax; this change
- ;; may have fixed it, so try reparse.
- (setq wisi-parse-try t)
+ (syntax-propertize end) ;; see comments above on "lexer" re syntax-propertize
- ;; remove 'wisi-cache on inserted text, which could have caches
- ;; from before the failed parse, and are in any case invalid.
- (with-silent-modifications
- (remove-text-properties begin end '(wisi-cache)))
- )
+ ;; The parse was failing, probably due to bad syntax; this change
+ ;; may have fixed it, so try reparse.
+ (setq wisi-parse-try t)
+ ;; remove 'wisi-cache on inserted text, which could have caches
+ ;; from before the failed parse (or another buffer), and are in
+ ;; any case invalid.
+ (with-silent-modifications
+ (remove-text-properties begin end '(wisi-cache)))
+
+ (cond
((>= wisi-cache-max begin)
;; The parse had succeeded past the start of the inserted
;; text.
(save-excursion
- (let ((need-invalidate t)
+ (let (need-invalidate
;; (info "(elisp)Parser State")
(state (syntax-ppss begin)))
;; syntax-ppss has moved point to "begin".
@@ -413,7 +457,10 @@ Also invalidate the Emacs syntax cache."
(wisi-change-need-invalidate
;; wisi-before change determined the removed text alters the
;; parse
- nil)
+ (setq need-invalidate wisi-change-need-invalidate))
+
+ ((= end begin)
+ (setq need-invalidate nil))
((or
(nth 3 state); in string
@@ -430,17 +477,16 @@ Also invalidate the Emacs syntax cache."
(eq (point) end))
(setq need-invalidate nil))
- (t nil)
+ (t
+ (setq need-invalidate begin))
)
(if need-invalidate
;; The inserted or deleted text could alter the parse;
;; wisi-invalidate-cache removes all 'wisi-cache.
- (wisi-invalidate-cache)
+ (wisi-invalidate-cache need-invalidate)
- ;; else move cache-max by the net change length. We don't
- ;; need to delete 'wisi-cache in the inserted text, because
- ;; if there were any it would not pass the above.
+ ;; else move cache-max by the net change length.
(setq wisi-cache-max
(+ wisi-cache-max (- end begin length))))
)
@@ -448,7 +494,7 @@ Also invalidate the Emacs syntax cache."
(t
;; parse never attempted, or only done to before BEGIN. Just
- ;; remove 'wisi-cache
+ ;; remove caches
(with-silent-modifications
(remove-text-properties begin end '(wisi-cache)))
)
@@ -473,15 +519,24 @@ If accessing cache at a marker for a token as set by
`wisi-cache-tokens', POS mu
(defun wisi-show-parse-error ()
"Show last wisi-parse error."
(interactive)
- (if wisi-parse-failed
- (progn
- (message wisi-parse-error-msg)
- (wisi-goto-error))
- (message "parse succeeded")))
+ (cond
+ (wisi-parse-failed
+ (message wisi-parse-error-msg)
+ (wisi-goto-error))
+
+ (wisi-parse-try
+ (message "need parse"))
+
+ (t
+ (message "parse succeeded"))
+ ))
+
+(defvar wisi-post-parse-succeed-hook nil
+ "Hook run after parse succeeds.")
(defun wisi-validate-cache (pos)
"Ensure cached data is valid at least up to POS in current buffer."
- (let ((msg (format "wisi: parsing %s:%d ..." (buffer-name)
(line-number-at-pos))))
+ (let ((msg (when (> wisi-debug 0) (format "wisi: parsing %s:%d ..."
(buffer-name) (line-number-at-pos pos)))))
(when (and wisi-parse-try
(< wisi-cache-max pos))
(when (> wisi-debug 0)
@@ -489,20 +544,26 @@ If accessing cache at a marker for a token as set by
`wisi-cache-tokens', POS mu
(setq wisi-parse-try nil)
(setq wisi-parse-error-msg nil)
+ (setq wisi-end-caches nil)
+
(save-excursion
- (goto-char wisi-cache-max)
(if (> wisi-debug 1)
;; let debugger stop in wisi-parse
(progn
(wisi-parse wisi-parse-table 'wisi-forward-token)
(setq wisi-cache-max (point))
- (setq wisi-parse-failed nil))
- ;; else capture errors from bad syntax, so higher level functions can
try to continue
+ (setq wisi-parse-failed nil)
+ (run-hooks 'wisi-post-parse-succeed-hook))
+
+ ;; else capture errors from bad syntax, so higher level
+ ;; functions can try to continue and/or we don't bother the
+ ;; user.
(condition-case err
(progn
(wisi-parse wisi-parse-table 'wisi-forward-token)
(setq wisi-cache-max (point))
- (setq wisi-parse-failed nil))
+ (setq wisi-parse-failed nil)
+ (run-hooks 'wisi-post-parse-succeed-hook))
(wisi-parse-error
(setq wisi-parse-failed t)
(setq wisi-parse-error-msg (cdr err)))
@@ -524,6 +585,11 @@ If accessing cache at a marker for a token as set by
`wisi-cache-tokens', POS mu
(and containing
(wisi-get-cache (1- containing)))))
+(defun wisi-cache-region (cache)
+ "Return region designated by cache.
+Point must be at cache."
+ (cons (point) (+ (point) (wisi-cache-last cache))))
+
(defun wisi-cache-text (cache)
"Return property-less buffer substring designated by cache.
Point must be at cache."
@@ -592,7 +658,8 @@ that token. Use in a grammar action as:
;;
;; statement : label_opt simple_statement
;;
- ;; override nonterm, class and containing
+ ;; override nonterm, class, containing
+ ;; set end only if not set yet (due to failed parse)
(progn
(cl-case (wisi-cache-class cache)
(block-start
@@ -611,7 +678,13 @@ that token. Use in a grammar action as:
(setf (wisi-cache-class cache) (or override-start
class)))
)
(setf (wisi-cache-nonterm cache) $nterm)
- (setf (wisi-cache-containing cache) first-keyword-mark))
+ (setf (wisi-cache-containing cache) first-keyword-mark)
+ (unless (wisi-cache-end cache)
+ (if wisi-end-caches
+ (push (car region) wisi-end-caches)
+ (setq wisi-end-caches (list (car region)))
+ ))
+ )
;; else create new cache
(with-silent-modifications
@@ -706,9 +779,9 @@ Each TOKEN-NUMBERS is one of:
number: the token number; mark that token
-list (number token_id):
-list (number (token_id token_id)):
- mark all tokens with token_id in the nonterminal given by the number."
+list (number class token_id):
+list (number class token_id class token_id ...):
+ mark all tokens in number nonterminal matching (class token_id) with nil
prev/next."
(save-excursion
(let (prev-keyword-mark
prev-cache
@@ -716,11 +789,10 @@ list (number (token_id token_id)):
mark)
(while token-numbers
(let ((token-number (pop token-numbers))
- target-token
+ class-tokens target-class target-token
region)
(cond
((numberp token-number)
- (setq target-token nil)
(setq region (cddr (nth (1- token-number) wisi-tokens)))
(when region
(setq cache (wisi-get-cache (car region)))
@@ -737,29 +809,30 @@ list (number (token_id token_id)):
))
((listp token-number)
- ;; token-number may contain 0, 1, or more token_id; token_id may be
a list
+ ;; token-number may contain 0, 1, or more 'class token_id' pairs
;; the corresponding region may be empty
;; there must have been a prev keyword
- (setq target-token (cadr token-number))
- (when (not (listp target-token))
- (setq target-token (list target-token)))
+ (setq class-tokens (cdr token-number))
(setq token-number (car token-number))
(setq region (cddr (nth (1- token-number) wisi-tokens)))
(when region ;; not an empty token
- (goto-char (car region))
- (while (wisi-forward-find-token target-token (cdr region) t)
- (setq cache (wisi-get-cache (point)))
- (setq mark (copy-marker (1+ (point))))
-
- (when (null (wisi-cache-prev cache))
- (setf (wisi-cache-prev cache) prev-keyword-mark)
- (setf (wisi-cache-next prev-cache) mark)
- (setq prev-keyword-mark mark)
- (setq prev-cache cache))
-
- (wisi-forward-token);; don't find same token again
+ (while class-tokens
+ (setq target-class (pop class-tokens))
+ (setq target-token (list (pop class-tokens)))
+ (goto-char (car region))
+ (while (setq cache (wisi-forward-find-token target-token (cdr
region) t))
+ (when (eq target-class (wisi-cache-class cache))
+ (when (null (wisi-cache-prev cache))
+ (setf (wisi-cache-prev cache) prev-keyword-mark))
+ (when (null (wisi-cache-next cache))
+ (setq mark (copy-marker (1+ (point))))
+ (setf (wisi-cache-next prev-cache) mark)
+ (setq prev-keyword-mark mark)
+ (setq prev-cache cache)))
+
+ (wisi-forward-token);; don't find same token again
))
- )
+ ))
(t
(error "unexpected token-number %s" token-number))
@@ -768,6 +841,41 @@ list (number (token_id token_id)):
))
)))
+(defun wisi-extend-action (number)
+ "Extend text of cache at token NUMBER to cover all of token NUMBER.
+Also override token with new token."
+ (let* ((token-region (nth (1- number) wisi-tokens));; wisi-tokens is
let-bound in wisi-parse-reduce
+ (token (car token-region))
+ (region (cddr token-region))
+ cache)
+
+ (when region
+ (setq cache (wisi-get-cache (car region)))
+ (setf (wisi-cache-last cache) (- (cdr region) (car region)))
+ (setf (wisi-cache-token cache) token)
+ )
+ ))
+
+(defun wisi-face-action (&rest pairs)
+ "Cache face information in text properties of tokens.
+Intended as a grammar non-terminal action.
+
+PAIRS is of the form [TOKEN-NUMBER fase] ..."
+ (while pairs
+ (let* ((number (1- (pop pairs)))
+ (region (cddr (nth number wisi-tokens)));; wisi-tokens is let-bound
in wisi-parse-reduce
+ (face (pop pairs))
+ cache)
+
+ (when region
+ (setq cache (wisi-get-cache (car region)))
+ (unless cache
+ (error "wisi-face-action on non-cache"))
+ (setf (wisi-cache-face cache) face)
+ (when (boundp 'jit-lock-mode)
+ (jit-lock-refontify (car region) (cdr region))))
+ )))
+
;;;; motion
(defun wisi-backward-cache ()
"Move point backward to the beginning of the first token preceding point
that has a cache.
@@ -882,7 +990,7 @@ If LIMIT (a buffer position) is reached, throw an error."
"If not at a cached token, move forward to next
cache. Otherwise move to cache-next, or next cache if nil.
Return cache found."
- (wisi-validate-cache (point-max))
+ (wisi-validate-cache (point-max)) ;; ensure there is a next cache to move to
(let ((cache (wisi-get-cache (point))))
(if cache
(let ((next (wisi-cache-next cache)))
@@ -898,7 +1006,7 @@ Return cache found."
(defun wisi-backward-statement-keyword ()
"If not at a cached token, move backward to prev
cache. Otherwise move to cache-prev, or prev cache if nil."
- (wisi-validate-cache (point-max))
+ (wisi-validate-cache (point))
(let ((cache (wisi-get-cache (point))))
(if cache
(let ((prev (wisi-cache-prev cache)))
@@ -909,7 +1017,8 @@ cache. Otherwise move to cache-prev, or prev cache if nil."
))
(defun wisi-goto-containing (cache &optional error)
- "Move point to containing token for CACHE, return cache at that point."
+ "Move point to containing token for CACHE, return cache at that point.
+If ERROR, throw error when CACHE has no container; else return nil."
(cond
((markerp (wisi-cache-containing cache))
(goto-char (1- (wisi-cache-containing cache)))
@@ -943,10 +1052,20 @@ Return start cache."
(defun wisi-goto-end-1 (cache)
(goto-char (1- (wisi-cache-end cache))))
-(defun wisi-goto-end ()
+(defun wisi-goto-statement-start ()
+ "Move point to token at start of statement point is in or after.
+Return start cache."
+ (interactive)
+ (wisi-validate-cache (point))
+ (let ((cache (wisi-get-cache (point))))
+ (unless cache
+ (setq cache (wisi-backward-cache)))
+ (wisi-goto-start cache)))
+
+(defun wisi-goto-statement-end ()
"Move point to token at end of statement point is in or before."
(interactive)
- (wisi-validate-cache (point-max))
+ (wisi-validate-cache (point))
(let ((cache (or (wisi-get-cache (point))
(wisi-forward-cache))))
(when (wisi-cache-end cache)
@@ -1001,9 +1120,7 @@ of CACHE with class statement-start or block-start."
(defun wisi-indent-statement ()
"Indent region given by `wisi-goto-start' on cache at or before point, then
wisi-cache-end."
- ;; force reparse, in case parser got confused
- (let ((wisi-parse-try t))
- (wisi-validate-cache (point)))
+ (wisi-validate-cache (point))
(save-excursion
(let ((cache (or (wisi-get-cache (point))
@@ -1040,27 +1157,34 @@ correct. Must leave point at indentation of current
line.")
"Indent current line using the wisi indentation engine."
(interactive)
- (let* ((savep (point))
- (indent
- (or (save-excursion
- (wisi-validate-cache (point))
- (back-to-indentation)
- (when (>= (point) savep) (setq savep nil))
- (if wisi-parse-failed
- (progn
- ;; parse failed. Assume user is editing; indent to
previous line, fix it after parse succeeds
- (setq wisi-indent-failed t)
- (forward-line -1);; safe at bob
- (back-to-indentation)
- (current-column))
-
- ;; else parse succeeded
- (when wisi-indent-failed
- (setq wisi-indent-failed nil)
- (run-hooks 'wisi-post-parse-fail-hook))
- (with-demoted-errors
- (or (run-hook-with-args-until-success
'wisi-indent-calculate-functions) 0))
- )))))
+ (let ((savep (point))
+ indent)
+ (save-excursion
+ (back-to-indentation)
+ (when (>= (point) savep) (setq savep nil))
+
+ (when (> (point) wisi-cache-max)
+ (wisi-validate-cache (point))
+ (when (and (not wisi-parse-failed)
+ wisi-indent-failed)
+ (setq wisi-indent-failed nil)
+ (run-hooks 'wisi-post-parse-fail-hook)))
+
+ (if (> (point) wisi-cache-max)
+ (progn
+ ;; no indent info at point. Assume user is
+ ;; editing; indent to previous line, fix it
+ ;; after parse succeeds
+ (setq wisi-indent-failed t)
+ (forward-line -1);; safe at bob
+ (back-to-indentation)
+ (setq indent (current-column)))
+
+ (setq indent
+ (with-demoted-errors
+ (or (run-hook-with-args-until-success
'wisi-indent-calculate-functions) 0))
+ )))
+
(if savep
;; point was inside line text; leave it there
(save-excursion (indent-line-to indent))
@@ -1135,8 +1259,7 @@ correct. Must leave point at indentation of current
line.")
(add-hook 'before-change-functions 'wisi-before-change nil t)
(add-hook 'after-change-functions 'wisi-after-change nil t)
- ;; WORKAROUND: sometimes the first time font-lock is run,
- ;; syntax-propertize is not run properly, so we run it here
+ ;; see comments on "lexer" above re syntax-propertize
(syntax-propertize (point-max))
(wisi-invalidate-cache)
- [elpa] externals/wisi 931fc16 16/35: * packages/gnome-c-style/gnome-c-tests.el: Add copyright blurb, (continued)
- [elpa] externals/wisi 931fc16 16/35: * packages/gnome-c-style/gnome-c-tests.el: Add copyright blurb, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 2f33bf8 21/35: Release Ada mode 5.3.1, wisi 1.1.6, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi e91f482 03/35: * wisi: Fix up dependency and sectioning style., Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 60b8ef1 15/35: Update ada-mode, wisi, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi d10db37 22/35: Release ada-mode version 6.0. Release wisi version 2.0, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi a4e4907 01/35: Add ada-mode, wisi packages, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 922e27f 04/35: * wisi: Fix warnings and a few 80-columns overruns, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 0635f1a 14/35: * packages/wisi: Use lexical binding. Fix dos EOL. Fix EOB markers, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 7cb03cb 10/35: * packages/ada-mode/* : version 5.1.5, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi cb45dd5 07/35: * packages/ada-mode: version 5.1.1: fix wisi packaging bug, add -a in gnat-find, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 8bdcee1 11/35: publish ada-mode 5.1.6, wisi 1.0.6, new package ada-ref-man,
Stefan Monnier <=
- [elpa] externals/wisi 364da46 20/35: Update ada-mode to version 5.2.2, wisi to version 1.1.5, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 89eee25 23/35: Release ada-mode 6.0.1, wisi 2.0.1; fix copyright, packaging bugs, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi d0eac6a 34/35: Forgot some new files in wisi, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi a6b3115 24/35: * ada-mode, wisi: Fix file access rights, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi bd1884c 02/35: Fix up copyright notices., Stefan Monnier, 2020/11/28
- [elpa] externals/wisi c282a4b 13/35: update ada-mode, wisi, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 27db81d 17/35: Fix some quoting problems in doc strings, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 724a763 31/35: In wisi sal-gen_unbounded_definite_red_black_trees.adb, correct WORKAROUND, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi abbb0c2 19/35: Release wisi 1.1.4, ada-mode 5.2.1, Stefan Monnier, 2020/11/28
- [elpa] externals/wisi 5becb56 29/35: Release ada-mode 7.0.1, wisi 3.0.1, Stefan Monnier, 2020/11/28