]> gitweb.factorcode.org Git - factor.git/blob - misc/fuel/fuel-syntax.el
Merge branch 'master' into experimental
[factor.git] / misc / fuel / fuel-syntax.el
1 ;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
2
3 ;; Copyright (C) 2008, 2009  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   (skip-syntax-backward "w_()"))
23
24 (defsubst fuel-syntax--beginning-of-symbol-pos ()
25   (save-excursion (fuel-syntax--beginning-of-symbol) (point)))
26
27 (defun fuel-syntax--end-of-symbol ()
28   "Move point to the end of the current symbol."
29   (skip-syntax-forward "w_()"))
30
31 (defsubst fuel-syntax--end-of-symbol-pos ()
32   (save-excursion (fuel-syntax--end-of-symbol) (point)))
33
34 (put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
35 (put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
36
37 (defsubst fuel-syntax-symbol-at-point ()
38   (let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
39     (and (> (length s) 0) s)))
40
41
42 \f
43 ;;; Regexps galore:
44
45 (defconst fuel-syntax--parsing-words
46   '(":" "::" ";" "&:" "<<" "<PRIVATE" ">>"
47     "ABOUT:" "ALIAS:" "ALIEN:" "ARTICLE:"
48     "B" "BIN:"
49     "C:" "C-ENUM:" "C-STRUCT:" "C-UNION:" "CHAR:" "CONSTANT:" "call-next-method"
50     "DEFER:"
51     "ERROR:" "EXCLUDE:"
52     "f" "FORGET:" "FROM:" "FUNCTION:"
53     "GENERIC#" "GENERIC:"
54     "HELP:" "HEX:" "HOOK:"
55     "IN:" "initial:" "INSTANCE:" "INTERSECTION:"
56     "LIBRARY:"
57     "M:" "MACRO:" "MACRO::" "MAIN:" "MATH:" "MEMO:" "MEMO:" "METHOD:" "MIXIN:"
58     "OCT:"
59     "POSTPONE:" "PREDICATE:" "PRIMITIVE:" "PRIVATE>" "PROVIDE:"
60     "QUALIFIED-WITH:" "QUALIFIED:"
61     "read-only" "RENAME:" "REQUIRE:"  "REQUIRES:"
62     "SINGLETON:" "SINGLETONS:" "SLOT:" "SYMBOL:" "SYMBOLS:"
63     "TUPLE:" "t" "t?" "TYPEDEF:"
64     "UNION:" "USE:" "USING:"
65     "VARS:"))
66
67 (defconst fuel-syntax--parsing-words-regex
68   (regexp-opt fuel-syntax--parsing-words 'words))
69
70 (defconst fuel-syntax--bracers
71   '("B" "BV" "C" "CS" "H" "T" "V" "W"))
72
73 (defconst fuel-syntax--brace-words-regex
74   (format "%s{" (regexp-opt fuel-syntax--bracers t)))
75
76 (defconst fuel-syntax--declaration-words
77   '("flushable" "foldable" "inline" "parsing" "recursive" "delimiter"))
78
79 (defconst fuel-syntax--declaration-words-regex
80   (regexp-opt fuel-syntax--declaration-words 'words))
81
82 (defsubst fuel-syntax--second-word-regex (prefixes)
83   (format "%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
84
85 (defconst fuel-syntax--method-definition-regex
86   "^M: +\\([^ ]+\\) +\\([^ ]+\\)")
87
88 (defconst fuel-syntax--integer-regex
89   "\\_<-?[0-9]+\\_>")
90
91 (defconst fuel-syntax--raw-float-regex
92   "[0-9]*\\.[0-9]*\\([eE][+-]?[0-9]+\\)?")
93
94 (defconst fuel-syntax--float-regex
95   (format "\\_<-?%s\\_>" fuel-syntax--raw-float-regex))
96
97 (defconst fuel-syntax--number-regex
98   (format "\\([0-9]+\\|%s\\)" fuel-syntax--raw-float-regex))
99
100 (defconst fuel-syntax--ratio-regex
101   (format "\\_<[+-]?%s/-?%s\\_>"
102           fuel-syntax--number-regex
103           fuel-syntax--number-regex))
104
105 (defconst fuel-syntax--bad-string-regex
106   "\\_<\"[^>]\\([^\"\n]\\|\\\\\"\\)*\n")
107
108 (defconst fuel-syntax--word-definition-regex
109   (fuel-syntax--second-word-regex
110    '(":" "::" "GENERIC:" "DEFER:" "HOOK:" "MAIN:" "MATH:" "POSTPONE:"
111      "SYMBOL:" "RENAME:")))
112
113 (defconst fuel-syntax--alias-definition-regex
114   "^ALIAS: +\\(\\_<.+?\\_>\\) +\\(\\_<.+?\\_>\\)")
115
116 (defconst fuel-syntax--vocab-ref-regexp
117   (fuel-syntax--second-word-regex
118    '("IN:" "USE:" "FROM:" "EXCLUDE:" "QUALIFIED:" "QUALIFIED-WITH:")))
119
120 (defconst fuel-syntax--int-constant-def-regex
121   (fuel-syntax--second-word-regex '("ALIEN:" "CHAR:" "BIN:" "HEX:" "OCT:")))
122
123 (defconst fuel-syntax--type-definition-regex
124   (fuel-syntax--second-word-regex
125    '("C-STRUCT:" "C-UNION:" "MIXIN:" "TUPLE:" "SINGLETON:" "UNION:")))
126
127 (defconst fuel-syntax--tuple-decl-regex
128   "^TUPLE: +\\([^ \n]+\\) +< +\\([^ \n]+\\)\\_>")
129
130 (defconst fuel-syntax--constructor-regex "<[^ >]+>")
131
132 (defconst fuel-syntax--getter-regex "\\(^\\|\\_<\\)[^ ]+?>>\\_>")
133 (defconst fuel-syntax--setter-regex "\\_<>>.+?\\_>")
134
135 (defconst fuel-syntax--symbol-definition-regex
136   (fuel-syntax--second-word-regex '("&:" "SYMBOL:" "VAR:")))
137
138 (defconst fuel-syntax--stack-effect-regex
139   "\\( ( .* )\\)\\|\\( (( .* ))\\)")
140
141 (defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
142
143 (defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
144
145 (defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
146
147 (defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
148
149 (defconst fuel-syntax--alien-function-regex
150   "\\_<FUNCTION: \\(\\w+\\) \\(\\w+\\)")
151
152 (defconst fuel-syntax--indent-def-starts '("" ":"
153                                            "C-ENUM" "C-STRUCT" "C-UNION"
154                                            "FROM" "FUNCTION:"
155                                            "INTERSECTION:"
156                                            "M" "MACRO" "MACRO:"
157                                            "MEMO" "MEMO:" "METHOD"
158                                            "PREDICATE" "PRIMITIVE"
159                                            "UNION"))
160
161 (defconst fuel-syntax--no-indent-def-starts '("SINGLETONS"
162                                               "SYMBOLS"
163                                               "TUPLE"
164                                               "VARS"))
165
166 (defconst fuel-syntax--indent-def-start-regex
167   (format "^\\(%s:\\)\\( \\|\n\\)" (regexp-opt fuel-syntax--indent-def-starts)))
168
169 (defconst fuel-syntax--no-indent-def-start-regex
170   (format "^\\(%s:\\) " (regexp-opt fuel-syntax--no-indent-def-starts)))
171
172 (defconst fuel-syntax--definition-start-regex
173   (format "^\\(%s:\\) " (regexp-opt (append fuel-syntax--no-indent-def-starts
174                                             fuel-syntax--indent-def-starts))))
175
176 (defconst fuel-syntax--definition-end-regex
177   (format "\\(\\(^\\| +\\);\\( *%s\\)*\\($\\| +\\)\\)"
178           fuel-syntax--declaration-words-regex))
179
180 (defconst fuel-syntax--single-liner-regex
181   (regexp-opt '("ABOUT:"
182                 "ARTICLE:"
183                 "ALIAS:"
184                 "CONSTANT:" "C:"
185                 "DEFER:"
186                 "FORGET:"
187                 "GENERIC:" "GENERIC#"
188                 "HELP:" "HEX:" "HOOK:"
189                 "IN:" "INSTANCE:"
190                 "LIBRARY:"
191                 "MAIN:" "MATH:" "MIXIN:"
192                 "OCT:"
193                 "POSTPONE:" "PRIVATE>" "<PRIVATE"
194                 "QUALIFIED-WITH:" "QUALIFIED:"
195                 "RENAME:"
196                 "SINGLETON:" "SLOT:" "SYMBOL:"
197                 "TYPEDEF:"
198                 "USE:"
199                 "VAR:")))
200
201 (defconst fuel-syntax--begin-of-def-regex
202   (format "^USING: \\|\\(%s\\)\\|\\(^%s .*\\)"
203           fuel-syntax--definition-start-regex
204           fuel-syntax--single-liner-regex))
205
206 (defconst fuel-syntax--end-of-def-line-regex
207   (format "^.*%s" fuel-syntax--definition-end-regex))
208
209 (defconst fuel-syntax--end-of-def-regex
210   (format "\\(%s\\)\\|\\(^%s .*\\)"
211           fuel-syntax--end-of-def-line-regex
212           fuel-syntax--single-liner-regex))
213
214 (defconst fuel-syntax--defun-signature-regex
215   (format "\\(%s\\|%s\\)"
216           (format ":[^ ]* [^ ]+\\(%s\\)*" fuel-syntax--stack-effect-regex)
217           "M[^:]*: [^ ]+ [^ ]+"))
218
219 (defconst fuel-syntax--constructor-decl-regex
220   "\\_<C: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
221
222 (defconst fuel-syntax--typedef-regex
223   "\\_<TYPEDEF: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
224
225 (defconst fuel-syntax--rename-regex
226   "\\_<RENAME: +\\(\\w+\\) +\\(\\w+\\) +=> +\\(\\w+\\)\\( .*\\)?$")
227
228 \f
229 ;;; Factor syntax table
230
231 (setq fuel-syntax--syntax-table
232   (let ((table (make-syntax-table)))
233     ;; Default is word constituent
234     (dotimes (i 256)
235       (modify-syntax-entry i "w" table))
236     ;; Whitespace (TAB is not whitespace)
237     (modify-syntax-entry ?\f " " table)
238     (modify-syntax-entry ?\r " " table)
239     (modify-syntax-entry ?\  " " table)
240     (modify-syntax-entry ?\n " " table)
241     table))
242
243 (defconst fuel-syntax--syntactic-keywords
244   `(;; CHARs:
245     ("\\(CHAR:\\|POSTPONE:\\|\\\\\\) \\(.\\)\\( \\|$\\)" (2 "w"))
246     ;; Comments:
247     ("\\_<\\(#?!\\) .*\\(\n\\|$\\)" (1 "<") (2 ">"))
248     ("\\_<\\(#?!\\)\\(\n\\|$\\)" (1 "<") (2 ">"))
249     (" \\((\\)( \\([^\n]*\\) )\\()\\)\\( \\|\n\\)" (1 "<b") (2 "w") (3 ">b"))
250     (" \\((\\) \\([^\n]*\\) \\()\\)\\( \\|\n\\)" (1 "<b") (2 "w") (3 ">b"))
251     ;; Strings
252     ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)"
253      (3 "\"") (5 "\""))
254     ("\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)" (1 "\"") (3 "\""))
255     ("\\_<<\\(\"\\)\\_>" (1 "<b"))
256     ("\\_<\\(\"\\)>\\_>" (1 ">b"))
257     ;; Multiline constructs
258     ("\\_<\\(U\\)SING: \\(;\\)" (1 "<b") (2 ">b"))
259     ("\\_<USING:\\( \\)" (1 "<b"))
260     ("\\_<\\(C\\)-ENUM: \\(;\\)" (1 "<b") (2 ">b"))
261     ("\\_<C-ENUM:\\( \\|\n\\)" (1 "<b"))
262     ("\\_<TUPLE: +\\w+? +< +\\w+? *\\( \\|\n\\)\\([^;]\\|$\\)" (1 "<b"))
263     ("\\_<\\(TUPLE\\|SYMBOLS\\|VARS\\): +\\w+? *\\( \\|\n\\)\\([^;<\n]\\|\\_>\\)"
264      (2 "<b"))
265     ("\\(\n\\| \\);\\_>" (1 ">b"))
266     ;; Let and lambda:
267     ("\\_<\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
268     ("\\(\\[\\)\\(let\\|wlet\\|let\\*\\)\\( \\|$\\)" (1 "(]"))
269     ("\\(\\[\\)\\(|\\) +[^|]* \\(|\\)" (1 "(]") (2 "(|") (3 ")|"))
270     (" \\(|\\) " (1 "(|"))
271     (" \\(|\\)$" (1 ")"))
272     ;; Opening brace words:
273     ("\\_<\\w*\\({\\)\\_>" (1 "(}"))
274     ("\\_<\\(}\\)\\_>" (1 "){"))
275     ;; Parenthesis:
276     ("\\_<\\((\\)\\_>" (1 "()"))
277     ("\\_<\\()\\)\\_>" (1 ")("))
278     ;; Quotations:
279     ("\\_<'\\(\\[\\)\\_>" (1 "(]"))      ; fried
280     ("\\_<\\(\\[\\)\\_>" (1 "(]"))
281     ("\\_<\\(\\]\\)\\_>" (1 ")["))))
282
283 \f
284 ;;; Source code analysis:
285
286 (defsubst fuel-syntax--brackets-depth ()
287   (nth 0 (syntax-ppss)))
288
289 (defsubst fuel-syntax--brackets-start ()
290   (nth 1 (syntax-ppss)))
291
292 (defun fuel-syntax--brackets-end ()
293   (save-excursion
294     (goto-char (fuel-syntax--brackets-start))
295     (condition-case nil
296         (progn (forward-sexp)
297                (1- (point)))
298       (error -1))))
299
300 (defsubst fuel-syntax--indentation-at (pos)
301   (save-excursion (goto-char pos) (current-indentation)))
302
303 (defsubst fuel-syntax--increased-indentation (&optional i)
304   (+ (or i (current-indentation)) factor-indent-width))
305 (defsubst fuel-syntax--decreased-indentation (&optional i)
306   (- (or i (current-indentation)) factor-indent-width))
307
308 (defsubst fuel-syntax--at-begin-of-def ()
309   (looking-at fuel-syntax--begin-of-def-regex))
310
311 (defsubst fuel-syntax--at-begin-of-indent-def ()
312   (looking-at fuel-syntax--indent-def-start-regex))
313
314 (defsubst fuel-syntax--at-end-of-def ()
315   (looking-at fuel-syntax--end-of-def-regex))
316
317 (defsubst fuel-syntax--looking-at-emptiness ()
318   (looking-at "^[ ]*$\\|$"))
319
320 (defsubst fuel-syntax--is-last-char (pos)
321   (save-excursion
322     (goto-char (1+ pos))
323     (fuel-syntax--looking-at-emptiness)))
324
325 (defsubst fuel-syntax--line-offset (pos)
326   (- pos (save-excursion
327            (goto-char pos)
328            (beginning-of-line)
329            (point))))
330
331 (defun fuel-syntax--previous-non-blank ()
332   (forward-line -1)
333   (while (and (not (bobp)) (fuel-syntax--looking-at-emptiness))
334     (forward-line -1)))
335
336 (defun fuel-syntax--beginning-of-block-pos ()
337   (save-excursion
338     (if (> (fuel-syntax--brackets-depth) 0)
339         (fuel-syntax--brackets-start)
340       (fuel-syntax--beginning-of-defun)
341       (point))))
342
343 (defun fuel-syntax--at-setter-line ()
344   (save-excursion
345     (beginning-of-line)
346     (when (re-search-forward fuel-syntax--setter-regex
347                              (line-end-position)
348                              t)
349       (let* ((to (match-beginning 0))
350              (from (fuel-syntax--beginning-of-block-pos)))
351         (goto-char from)
352         (let ((depth (fuel-syntax--brackets-depth)))
353           (and (or (re-search-forward fuel-syntax--constructor-regex to t)
354                    (re-search-forward fuel-syntax--setter-regex to t))
355                (= depth (fuel-syntax--brackets-depth))))))))
356
357 (defun fuel-syntax--at-constructor-line ()
358   (save-excursion
359     (beginning-of-line)
360     (re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
361
362 (defsubst fuel-syntax--at-using ()
363   (looking-at fuel-syntax--using-lines-regex))
364
365 (defun fuel-syntax--in-using ()
366   (let ((p (point)))
367     (save-excursion
368       (and (re-search-backward "^USING: " nil t)
369            (re-search-forward " ;" nil t)
370            (< p (match-end 0))))))
371
372 (defsubst fuel-syntax--beginning-of-defun (&optional times)
373   (re-search-backward fuel-syntax--begin-of-def-regex nil t times))
374
375 (defsubst fuel-syntax--end-of-defun ()
376   (re-search-forward fuel-syntax--end-of-def-regex nil t))
377
378 (defsubst fuel-syntax--end-of-defun-pos ()
379   (save-excursion
380     (re-search-forward fuel-syntax--end-of-def-regex nil t)
381     (point)))
382
383 (defun fuel-syntax--beginning-of-body ()
384   (let ((p (point)))
385     (and (fuel-syntax--beginning-of-defun)
386          (re-search-forward fuel-syntax--defun-signature-regex p t)
387          (not (re-search-forward fuel-syntax--end-of-def-regex p t)))))
388
389 (defun fuel-syntax--beginning-of-sexp ()
390   (if (> (fuel-syntax--brackets-depth) 0)
391       (goto-char (fuel-syntax--brackets-start))
392     (fuel-syntax--beginning-of-body)))
393
394 (defsubst fuel-syntax--beginning-of-sexp-pos ()
395   (save-excursion (fuel-syntax--beginning-of-sexp) (point)))
396
397 \f
398 ;;; USING/IN:
399
400 (make-variable-buffer-local
401  (defvar fuel-syntax--current-vocab-function 'fuel-syntax--find-in))
402
403 (defsubst fuel-syntax--current-vocab ()
404   (funcall fuel-syntax--current-vocab-function))
405
406 (defun fuel-syntax--find-in ()
407   (save-excursion
408     (when (re-search-backward fuel-syntax--current-vocab-regex nil t)
409       (match-string-no-properties 1))))
410
411 (make-variable-buffer-local
412  (defvar fuel-syntax--usings-function 'fuel-syntax--find-usings))
413
414 (defsubst fuel-syntax--usings ()
415   (funcall fuel-syntax--usings-function))
416
417 (defun fuel-syntax--file-has-private ()
418   (save-excursion
419     (goto-char (point-min))
420     (and (re-search-forward "\\_<<PRIVATE\\_>" nil t)
421          (re-search-forward "\\_<PRIVATE>\\_>" nil t))))
422
423 (defun fuel-syntax--find-usings (&optional no-private)
424   (save-excursion
425     (let ((usings))
426       (goto-char (point-max))
427       (while (re-search-backward fuel-syntax--using-lines-regex nil t)
428         (dolist (u (split-string (match-string-no-properties 1) nil t))
429           (push u usings)))
430       (when (and (not no-private) (fuel-syntax--file-has-private))
431         (goto-char (point-max))
432         (push (concat (fuel-syntax--find-in) ".private") usings))
433       usings)))
434
435 \f
436 (provide 'fuel-syntax)
437 ;;; fuel-syntax.el ends here