[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/forth-mode 50a7eb4bf1 094/153: Handle indentation of : and
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/forth-mode 50a7eb4bf1 094/153: Handle indentation of : and with smie instead of syntax-table. |
Date: |
Sat, 29 Jan 2022 08:02:21 -0500 (EST) |
branch: elpa/forth-mode
commit 50a7eb4bf1842c8f69af8fc8863384d1d1072f33
Author: Helmut Eller <eller.helmut@gmail.com>
Commit: Lars Brinkhoff <lars@nocrew.org>
Handle indentation of : and with smie instead of syntax-table.
---
forth-smie.el | 3 +-
forth-syntax.el | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 198 insertions(+), 1 deletion(-)
diff --git a/forth-smie.el b/forth-smie.el
index 94c17ea7be..bfe7086461 100644
--- a/forth-smie.el
+++ b/forth-smie.el
@@ -17,7 +17,8 @@
("do" words "loop")
("do" words "+loop")
("begin-structure" words "end-structure")
- ("{:" words ":}"))
+ ("{:" words ":}")
+ (":" words ";"))
(words)))))
(defvar forth-smie--basic-indent 2)
diff --git a/forth-syntax.el b/forth-syntax.el
new file mode 100644
index 0000000000..264ac11180
--- /dev/null
+++ b/forth-syntax.el
@@ -0,0 +1,196 @@
+;; forth-syntax.el -- syntax-propertize function for forth-mode
+
+;; This code mimics the Forth text interpreter and adds text
+;; properties as side effect.
+
+(require 'cl-lib)
+
+
+;;; Helpers
+
+(defvar forth-syntax--whitespace " \t\n\f\r")
+(defvar forth-syntax--non-whitespace (concat "^" forth-syntax--whitespace))
+
+;; Return the whitespace-delimited word at position POS.
+;; Return nil if POS is at end-of-buffer.
+(defun forth-syntax--word-at (pos)
+ (save-excursion
+ (goto-char pos)
+ (skip-chars-forward forth-syntax--whitespace)
+ (let ((start (point)))
+ (skip-chars-forward forth-syntax--non-whitespace)
+ (cond ((= start (point)) nil)
+ (t (buffer-substring-no-properties start (point)))))))
+
+
+
+;;; State functions
+
+;; The parser is a loop that calls "state-functions".
+;; A state function parses forward from point, adds text-properties as needed,
+;; and returns the next state-function.
+;;
+;; The naming convention for state-functions is forth-syntax--state-FOO.
+
+(defun forth-syntax--state-eob ()
+ (cl-assert (eobp))
+ (error "This state function should never be called"))
+
+;; One line strings
+(defun forth-syntax--state-string ()
+ (re-search-backward "\"\\=")
+ (put-text-property (point) (1+ (point))
+ 'syntax-table (string-to-syntax "\""))
+ (forward-char)
+ (cond ((re-search-forward "[\"\n]" nil t)
+ (put-text-property (1- (point)) (point)
+ 'syntax-table (string-to-syntax "\""))
+ #'forth-syntax--state-normal)
+ (t
+ (goto-char (point-max))
+ #'forth-syntax--state-normal)))
+
+(defun forth-syntax--state-s\\\" ()
+ (re-search-backward "\"\\=")
+ (put-text-property (point) (1+ (point))
+ 'syntax-table (string-to-syntax "\""))
+ (forward-char)
+ (while (and (re-search-forward "\\([\"\n]\\|\\\\\"\\)" nil t)
+ (cond ((= (char-after (match-beginning 0)) ?\\)
+ (put-text-property (match-beginning 0)
+ (1+ (match-beginning 0))
+ 'syntax-table (string-to-syntax "\\"))
+ t))))
+ (cond ((looking-back "[\"\n]" 1)
+ (put-text-property (1- (point)) (point)
+ 'syntax-table (string-to-syntax "\""))
+ #'forth-syntax--state-normal)
+ (t
+ (goto-char (point-max))
+ #'forth-syntax--state-normal)))
+
+;; State for words that parse the following word, e.g. POSTPONE S"
+;; where POSTPONE parses S".
+(defun forth-syntax--state-parsing-word ()
+ (skip-chars-forward forth-syntax--whitespace)
+ (let ((start (point)))
+ (skip-chars-forward forth-syntax--non-whitespace)
+ (cond ((= start (point)) #'forth-syntax--state-eob)
+ (t
+ (put-text-property start (point)
+ 'syntax-table (string-to-syntax "_"))
+ #'forth-syntax--state-normal))))
+
+(defun forth-syntax--parse-comment (backward-regexp forward-regexp)
+ (let ((pos (point)))
+ (re-search-backward backward-regexp)
+ (put-text-property (point) (1+ (point))
+ 'syntax-table (string-to-syntax "<"))
+ (goto-char pos)
+ (cond ((re-search-forward forward-regexp nil t)
+ (put-text-property (1- (point)) (point)
+ 'syntax-table (string-to-syntax ">"))
+ #'forth-syntax--state-normal)
+ (t
+ (goto-char (point-max))
+ #'forth-syntax--state-normal))))
+
+;; Define a state-function for comments. The comment starts with
+;; the string BEGIN and ends with the string END.
+(defmacro forth-syntax--define-comment-state (begin end)
+ (let ((fname (intern (concat "forth-syntax--state-" begin))))
+ `(defun ,fname ()
+ (forth-syntax--parse-comment ,(concat (regexp-quote begin) "\\=")
+ ,(regexp-quote end)))))
+
+(forth-syntax--define-comment-state "(" ")")
+(forth-syntax--define-comment-state "\\" "\n")
+(forth-syntax--define-comment-state ".(" ")")
+
+;; For now, treat locals like comments
+(forth-syntax--define-comment-state "{:" ":}")
+
+;; Hashtable that maps strings (word names) to parser functions.
+(defvar forth-syntax--parsers (make-hash-table :test 'equal))
+
+(defun forth-syntax--define (word parsing-function)
+ (setf (gethash (downcase word) forth-syntax--parsers) parsing-function))
+
+(forth-syntax--define "s\"" #'forth-syntax--state-string)
+(forth-syntax--define ".\"" #'forth-syntax--state-string)
+(forth-syntax--define "c\"" #'forth-syntax--state-string)
+(forth-syntax--define "abort\"" #'forth-syntax--state-string)
+
+(forth-syntax--define "s\\\"" #'forth-syntax--state-s\\\")
+
+(forth-syntax--define "(" #'forth-syntax--state-\()
+(forth-syntax--define "\\" #'forth-syntax--state-\\)
+(forth-syntax--define ".(" #'forth-syntax--state-.\()
+(forth-syntax--define "{:" #'forth-syntax--state-{:)
+
+(forth-syntax--define "postpone" #'forth-syntax--state-parsing-word)
+(forth-syntax--define "'" #'forth-syntax--state-parsing-word)
+(forth-syntax--define "[']" #'forth-syntax--state-parsing-word)
+(forth-syntax--define ":" #'forth-syntax--state-parsing-word)
+
+;; Find the parsing function for WORD.
+(defun forth-syntax--lookup (word)
+ (gethash (downcase word) forth-syntax--parsers))
+
+;; Look for the next whitespace delimited word; mark all its
+;; characters as "symbol constituents"; finally return state-function
+;; for the word.
+(defun forth-syntax--state-normal ()
+ (skip-chars-forward forth-syntax--whitespace)
+ (let ((start (point)))
+ (skip-chars-forward forth-syntax--non-whitespace)
+ (cond ((= start (point)) #'forth-syntax--state-eob)
+ (t
+ (put-text-property start (point)
+ 'syntax-table (string-to-syntax "_"))
+ (let ((word (buffer-substring-no-properties start (point))))
+ (cond ((forth-syntax--lookup word))
+ (t
+ #'forth-syntax--state-normal)))))))
+
+
+;;; Guess initial state
+
+;; Is it normal that `syntax-ppss' moves point or is that a bug?
+(defun forth-syntax--ppss (pos)
+ (save-excursion
+ (syntax-ppss pos)))
+
+(defun forth-syntax--in-comment-p (pos)
+ (not (null (elt (forth-syntax--ppss pos) 4))))
+
+(defun forth-syntax--comment-start-position (pos)
+ (elt (forth-syntax--ppss pos) 8))
+
+;; Make a guess for the syntax state at position POS.
+;; Return a pair (START . PARSING-FUNCTION).
+(defun forth-syntax--guess-state (pos)
+ (cond ((and (< (point-min) pos)
+ (forth-syntax--in-comment-p (1- pos)))
+ (cons (forth-syntax--comment-start-position (1- pos))
+ #'forth-syntax--state-normal))
+ (t
+ (cons pos #'forth-syntax--state-normal))))
+
+
+;;; Main entry point
+
+;; Guess a state for the position START, then call state-functions
+;; until the position END is reached.
+(defun forth-syntax-propertize (start end)
+ (save-excursion
+ (let* ((guess (forth-syntax--guess-state start))
+ (state (cdr guess)))
+ ;;(message "forth-syntax-propertize: %s %s %s" start end guess)
+ (goto-char (car guess))
+ (while (< (point) end)
+ (let ((start (point)))
+ (setq state (funcall state))
+ (cl-assert (< start (point))))))))
+
+(provide 'forth-syntax)
- [nongnu] elpa/forth-mode 5aa3a700b0 016/153: Improve killing an interactive Forth session., (continued)
- [nongnu] elpa/forth-mode 5aa3a700b0 016/153: Improve killing an interactive Forth session., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 2869bc25e4 085/153: Create a terminal personality for SwiftForth., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 8d1d8ea795 099/153: Re-add test for 'syntax-propertize-function., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 55de74bb4f 033/153: Query Forth session about defined words., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 44dd013096 059/153: Remove terminal escape sequences from strings returned from Forth., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 399fd00921 055/153: Fix killing interactive Forth., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 56bbc06a16 079/153: Error out if byte compilation fails in Emacs 23., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 531c9e11e2 023/153: Add autoload cookie to extension configuration, ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 847481f866 061/153: Tweak window handling., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 5a08c82adb 111/153: Improve word movement commands inside symbols., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 50a7eb4bf1 094/153: Handle indentation of : and with smie instead of syntax-table.,
ELPA Syncer <=
- [nongnu] elpa/forth-mode 45f3f20f18 104/153: Make indentation case-insensitive, ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode b8024ac331 088/153: Loading a Forth file provides some feedback., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 9eb3550cdc 045/153: Add imenu items to autocomplete candidates., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 350638bb0c 106/153: Make indentation case-insensitive, ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 039bf122ee 067/153: Document key bindings in the manual., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 1a05d27d82 077/153: Fix loading backend file., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode b95f1b8a02 146/153: Fix typos in doc, ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 2e75fb156f 081/153: Fix warning about defvar ignored., ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 96c20f03f5 128/153: Make completion-at-point test work with Emacs23, ELPA Syncer, 2022/01/29
- [nongnu] elpa/forth-mode 867922d61e 112/153: Handle string literals more correctly, ELPA Syncer, 2022/01/29