]> gitweb.factorcode.org Git - factor.git/blob - misc/fuel/fuel-syntax.el
Merge branch 'master' into experimental (untested!)
[factor.git] / misc / fuel / fuel-syntax.el
1 ;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
2
3 ;; Copyright (C) 2008  Jose Antonio Ortega Ruiz
4 ;; See http://factorcode.org/license.txt for BSD license.
5
6 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
7 ;; Keywords: languages
8
9 ;;; Commentary:
10
11 ;; Auxiliar constants and functions to parse factor code.
12
13 ;;; Code:
14
15 (require 'thingatpt)
16
17 \f
18 ;;; Thing-at-point support for factor symbols:
19
20 (defun fuel-syntax--beginning-of-symbol ()
21   "Move point to the beginning of the current symbol."
22   (while (eq (char-before) ?:) (backward-char))
23   (skip-syntax-backward "w_"))
24
25 (defun fuel-syntax--end-of-symbol ()
26   "Move point to the end of the current symbol."
27   (skip-syntax-forward "w_")
28   (while (looking-at ":") (forward-char)))
29
30 (put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
31 (put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
32
33 (defsubst fuel-syntax-symbol-at-point ()
34   (let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
35     (and (> (length s) 0) s)))
36
37 \f
38 ;;; Regexps galore:
39
40 (defconst fuel-syntax--parsing-words
41   '("{" "}" "^:" "^::" ";" "<<" "<PRIVATE" ">>"
42     "BIN:" "BV{" "B{" "C:" "C-STRUCT:" "C-UNION:" "CHAR:" "CS{" "C{"
43     "DEFER:" "ERROR:" "EXCLUDE:" "FORGET:"
44     "GENERIC#" "GENERIC:" "HEX:" "HOOK:" "H{"
45     "IN:" "INSTANCE:" "INTERSECTION:"
46     "M:" "MACRO:" "MACRO::" "MAIN:" "MATH:" "METHOD:" "MIXIN:"
47     "OCT:" "POSTPONE:" "PREDICATE:" "PRIMITIVE:" "PRIVATE>" "PROVIDE:"
48     "REQUIRE:"  "REQUIRES:" "SINGLETON:" "SLOT:" "SYMBOL:" "SYMBOLS:"
49     "TUPLE:" "T{" "t\\??" "TYPEDEF:"
50     "UNION:" "USE:" "USING:" "V{" "VARS:" "W{"))
51
52 (defconst fuel-syntax--parsing-words-ext-regex
53   (regexp-opt '("B" "call-next-method" "delimiter" "f" "initial:" "read-only")
54               'words))
55
56 (defconst fuel-syntax--declaration-words
57   '("flushable" "foldable" "inline" "parsing" "recursive"))
58
59 (defconst fuel-syntax--declaration-words-regex
60   (regexp-opt fuel-syntax--declaration-words 'words))
61
62 (defsubst fuel-syntax--second-word-regex (prefixes)
63   (format "^%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
64
65 (defconst fuel-syntax--method-definition-regex
66   "^M: +\\([^ ]+\\) +\\([^ ]+\\)")
67
68 (defconst fuel-syntax--word-definition-regex
69   (fuel-syntax--second-word-regex '(":" "::" "GENERIC:")))
70
71 (defconst fuel-syntax--type-definition-regex
72   (fuel-syntax--second-word-regex '("TUPLE:" "SINGLETON:")))
73
74 (defconst fuel-syntax--parent-type-regex "^TUPLE: +[^ ]+ +< +\\([^ ]+\\)")
75
76 (defconst fuel-syntax--constructor-regex "<[^ >]+>")
77
78 (defconst fuel-syntax--setter-regex "\\W>>[^ ]+\\b")
79
80 (defconst fuel-syntax--symbol-definition-regex
81   (fuel-syntax--second-word-regex '("SYMBOL:" "VAR:")))
82
83 (defconst fuel-syntax--stack-effect-regex " ( .* )")
84
85 (defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
86
87 (defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
88
89 (defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
90
91 (defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
92
93 (defconst fuel-syntax--definition-starters-regex
94   (regexp-opt '("VARS" "TUPLE" "MACRO" "MACRO:" "M" ":" "")))
95
96 (defconst fuel-syntax--definition-start-regex
97   (format "^\\(%s:\\) " fuel-syntax--definition-starters-regex))
98
99 (defconst fuel-syntax--definition-end-regex
100   (format "\\(\\(^\\| +\\);\\( +%s\\)*\\($\\| +\\)\\)"
101           fuel-syntax--declaration-words-regex))
102
103 (defconst fuel-syntax--single-liner-regex
104   (format "^%s" (regexp-opt '("DEFER:" "GENERIC:" "IN:"
105                               "PRIVATE>" "<PRIVATE"
106                               "SINGLETON:" "SYMBOL:" "USE:" "VAR:"))))
107
108 (defconst fuel-syntax--begin-of-def-regex
109   (format "^USING: \\|\\(%s\\)\\|\\(%s .*\\)"
110           fuel-syntax--definition-start-regex
111           fuel-syntax--single-liner-regex))
112
113 (defconst fuel-syntax--end-of-def-line-regex
114   (format "^.*%s" fuel-syntax--definition-end-regex))
115
116 (defconst fuel-syntax--end-of-def-regex
117   (format "\\(%s\\)\\|\\(%s .*\\)"
118           fuel-syntax--end-of-def-line-regex
119           fuel-syntax--single-liner-regex))
120 \f
121 ;;; Factor syntax table
122
123 (defvar fuel-syntax--syntax-table
124   (let ((i 0)
125         (table (make-syntax-table)))
126     ;; Default is atom-constituent
127     (while (< i 256)
128       (modify-syntax-entry i "_   " table)
129       (setq i (1+ i)))
130
131     ;; Word components.
132     (setq i ?0)
133     (while (<= i ?9)
134       (modify-syntax-entry i "w   " table)
135       (setq i (1+ i)))
136     (setq i ?A)
137     (while (<= i ?Z)
138       (modify-syntax-entry i "w   " table)
139       (setq i (1+ i)))
140     (setq i ?a)
141     (while (<= i ?z)
142       (modify-syntax-entry i "w   " table)
143       (setq i (1+ i)))
144
145     ;; Whitespace
146     (modify-syntax-entry ?\t " " table)
147     (modify-syntax-entry ?\f " " table)
148     (modify-syntax-entry ?\r " " table)
149     (modify-syntax-entry ?  " " table)
150
151     ;; (end of) Comments
152     (modify-syntax-entry ?\n ">" table)
153
154     ;; Parenthesis
155     (modify-syntax-entry ?\[ "(]  " table)
156     (modify-syntax-entry ?\] ")[  " table)
157     (modify-syntax-entry ?{ "(}  " table)
158     (modify-syntax-entry ?} "){  " table)
159
160     (modify-syntax-entry ?\( "()" table)
161     (modify-syntax-entry ?\) ")(" table)
162
163     ;; Strings
164     (modify-syntax-entry ?\" "\"" table)
165     (modify-syntax-entry ?\\ "/" table)
166     table)
167   "Syntax table used while in Factor mode.")
168
169 (defconst fuel-syntax--syntactic-keywords
170   `(("\\(#!\\)" (1 "<"))
171     (" \\(!\\)" (1 "<"))
172     ("^\\(!\\)" (1 "<"))
173     ("\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
174     ("\\([[({]\\)\\([^ \"\n]\\)" (1 "_") (2 "_"))
175     ("\\([^ \"\n]\\)\\([])}]\\)" (1 "_") (2 "_"))))
176
177 \f
178 ;;; Source code analysis:
179
180 (defsubst fuel-syntax--brackets-depth ()
181   (nth 0 (syntax-ppss)))
182
183 (defsubst fuel-syntax--brackets-start ()
184   (nth 1 (syntax-ppss)))
185
186 (defun fuel-syntax--brackets-end ()
187   (save-excursion
188     (goto-char (fuel-syntax--brackets-start))
189     (condition-case nil
190         (progn (forward-sexp)
191                (1- (point)))
192       (error -1))))
193
194 (defsubst fuel-syntax--indentation-at (pos)
195   (save-excursion (goto-char pos) (current-indentation)))
196
197 (defsubst fuel-syntax--increased-indentation (&optional i)
198   (+ (or i (current-indentation)) factor-indent-width))
199 (defsubst fuel-syntax--decreased-indentation (&optional i)
200   (- (or i (current-indentation)) factor-indent-width))
201
202 (defsubst fuel-syntax--at-begin-of-def ()
203   (looking-at fuel-syntax--begin-of-def-regex))
204
205 (defsubst fuel-syntax--at-end-of-def ()
206   (looking-at fuel-syntax--end-of-def-regex))
207
208 (defsubst fuel-syntax--looking-at-emptiness ()
209   (looking-at "^[ \t]*$"))
210
211 (defun fuel-syntax--at-setter-line ()
212   (save-excursion
213     (beginning-of-line)
214     (if (not (fuel-syntax--looking-at-emptiness))
215         (re-search-forward fuel-syntax--setter-regex (line-end-position) t)
216       (forward-line -1)
217       (or (fuel-syntax--at-constructor-line)
218           (fuel-syntax--at-setter-line)))))
219
220 (defun fuel-syntax--at-constructor-line ()
221   (save-excursion
222     (beginning-of-line)
223     (re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
224
225 (defsubst fuel-syntax--at-using ()
226   (looking-at fuel-syntax--using-lines-regex))
227
228 (defsubst fuel-syntax--beginning-of-defun (&optional times)
229   (re-search-backward fuel-syntax--begin-of-def-regex nil t times))
230
231 (defsubst fuel-syntax--end-of-defun ()
232   (re-search-forward fuel-syntax--end-of-def-regex nil t))
233
234 \f
235 ;;; USING/IN:
236
237 (make-variable-buffer-local
238  (defvar fuel-syntax--current-vocab nil))
239
240 (make-variable-buffer-local
241  (defvar fuel-syntax--usings nil))
242
243 (defun fuel-syntax--current-vocab ()
244   (let ((ip
245          (save-excursion
246            (when (re-search-backward fuel-syntax--current-vocab-regex nil t)
247              (setq fuel-syntax--current-vocab (match-string-no-properties 1))
248              (point)))))
249     (when ip
250       (let ((pp (save-excursion
251                   (when (re-search-backward fuel-syntax--sub-vocab-regex ip t)
252                     (point)))))
253         (when (and pp (> pp ip))
254           (let ((sub (match-string-no-properties 1)))
255             (unless (save-excursion (search-backward (format "%s>" sub) pp t))
256               (setq fuel-syntax--current-vocab
257                     (format "%s.%s" fuel-syntax--current-vocab (downcase sub)))))))))
258   fuel-syntax--current-vocab)
259
260 (defun fuel-syntax--usings-update ()
261   (save-excursion
262     (setq fuel-syntax--usings (list (fuel-syntax--current-vocab)))
263     (while (re-search-backward fuel-syntax--using-lines-regex nil t)
264       (dolist (u (split-string (match-string-no-properties 1) nil t))
265         (push u fuel-syntax--usings)))
266     fuel-syntax--usings))
267
268 (defsubst fuel-syntax--usings-update-hook ()
269   (fuel-syntax--usings-update)
270   nil)
271
272 (defun fuel-syntax--enable-usings ()
273   (add-hook 'before-save-hook 'fuel-syntax--usings-update-hook nil t)
274   (fuel-syntax--usings-update))
275
276 (defsubst fuel-syntax--usings ()
277   (or fuel-syntax--usings (fuel-syntax--usings-update)))
278
279 \f
280 (provide 'fuel-syntax)
281 ;;; fuel-syntax.el ends here