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