1 ;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
3 ;; Copyright (C) 2008, 2009 Jose Antonio Ortega Ruiz
4 ;; See http://factorcode.org/license.txt for BSD license.
6 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
11 ;; Auxiliar constants and functions to parse factor code.
18 ;;; Thing-at-point support for factor symbols:
20 (defun fuel-syntax--beginning-of-symbol ()
21 "Move point to the beginning of the current symbol."
22 (skip-syntax-backward "w_()"))
24 (defsubst fuel-syntax--beginning-of-symbol-pos ()
25 (save-excursion (fuel-syntax--beginning-of-symbol) (point)))
27 (defun fuel-syntax--end-of-symbol ()
28 "Move point to the end of the current symbol."
29 (skip-syntax-forward "w_()"))
31 (defsubst fuel-syntax--end-of-symbol-pos ()
32 (save-excursion (fuel-syntax--end-of-symbol) (point)))
34 (put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
35 (put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
37 (defsubst fuel-syntax-symbol-at-point ()
38 (let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
39 (and (> (length s) 0) s)))
45 (defconst fuel-syntax--parsing-words
46 '(":" "::" ";" "&:" "<<" "<PRIVATE" ">>"
47 "ABOUT:" "ALIAS:" "ALIEN:" "ARTICLE:"
49 "C:" "C-ENUM:" "C-STRUCT:" "C-UNION:" "CHAR:" "CONSTANT:" "call-next-method"
52 "f" "FORGET:" "FROM:" "FUNCTION:"
54 "HELP:" "HEX:" "HOOK:"
55 "IN:" "initial:" "INSTANCE:" "INTERSECTION:"
57 "M:" "MACRO:" "MACRO::" "MAIN:" "MATH:" "MEMO:" "MEMO:" "METHOD:" "MIXIN:"
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:"
67 (defconst fuel-syntax--parsing-words-regex
68 (regexp-opt fuel-syntax--parsing-words 'words))
70 (defconst fuel-syntax--bracers
71 '("B" "BV" "C" "CS" "H" "T" "V" "W"))
73 (defconst fuel-syntax--brace-words-regex
74 (format "%s{" (regexp-opt fuel-syntax--bracers t)))
76 (defconst fuel-syntax--declaration-words
77 '("flushable" "foldable" "inline" "parsing" "recursive" "delimiter"))
79 (defconst fuel-syntax--declaration-words-regex
80 (regexp-opt fuel-syntax--declaration-words 'words))
82 (defsubst fuel-syntax--second-word-regex (prefixes)
83 (format "%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
85 (defconst fuel-syntax--method-definition-regex
86 "^M: +\\([^ ]+\\) +\\([^ ]+\\)")
88 (defconst fuel-syntax--integer-regex
91 (defconst fuel-syntax--raw-float-regex
92 "[0-9]*\\.[0-9]*\\([eE][+-]?[0-9]+\\)?")
94 (defconst fuel-syntax--float-regex
95 (format "\\_<-?%s\\_>" fuel-syntax--raw-float-regex))
97 (defconst fuel-syntax--number-regex
98 (format "\\([0-9]+\\|%s\\)" fuel-syntax--raw-float-regex))
100 (defconst fuel-syntax--ratio-regex
101 (format "\\_<[+-]?%s/-?%s\\_>"
102 fuel-syntax--number-regex
103 fuel-syntax--number-regex))
105 (defconst fuel-syntax--bad-string-regex
106 "\\_<\"[^>]\\([^\"\n]\\|\\\\\"\\)*\n")
108 (defconst fuel-syntax--word-definition-regex
109 (fuel-syntax--second-word-regex
110 '(":" "::" "GENERIC:" "DEFER:" "HOOK:" "MAIN:" "MATH:" "POSTPONE:"
111 "SYMBOL:" "RENAME:")))
113 (defconst fuel-syntax--alias-definition-regex
114 "^ALIAS: +\\(\\_<.+?\\_>\\) +\\(\\_<.+?\\_>\\)")
116 (defconst fuel-syntax--vocab-ref-regexp
117 (fuel-syntax--second-word-regex
118 '("IN:" "USE:" "FROM:" "EXCLUDE:" "QUALIFIED:" "QUALIFIED-WITH:")))
120 (defconst fuel-syntax--int-constant-def-regex
121 (fuel-syntax--second-word-regex '("ALIEN:" "CHAR:" "BIN:" "HEX:" "OCT:")))
123 (defconst fuel-syntax--type-definition-regex
124 (fuel-syntax--second-word-regex
125 '("C-STRUCT:" "C-UNION:" "MIXIN:" "TUPLE:" "SINGLETON:" "UNION:")))
127 (defconst fuel-syntax--tuple-decl-regex
128 "^TUPLE: +\\([^ \n]+\\) +< +\\([^ \n]+\\)\\_>")
130 (defconst fuel-syntax--constructor-regex "<[^ >]+>")
132 (defconst fuel-syntax--getter-regex "\\(^\\|\\_<\\)[^ ]+?>>\\_>")
133 (defconst fuel-syntax--setter-regex "\\_<>>.+?\\_>")
135 (defconst fuel-syntax--symbol-definition-regex
136 (fuel-syntax--second-word-regex '("&:" "SYMBOL:" "VAR:")))
138 (defconst fuel-syntax--stack-effect-regex
139 "\\( ( .* )\\)\\|\\( (( .* ))\\)")
141 (defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
143 (defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
145 (defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
147 (defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
149 (defconst fuel-syntax--alien-function-regex
150 "\\_<FUNCTION: \\(\\w+\\) \\(\\w+\\)")
152 (defconst fuel-syntax--indent-def-starts '("" ":"
153 "C-ENUM" "C-STRUCT" "C-UNION"
157 "MEMO" "MEMO:" "METHOD"
158 "PREDICATE" "PRIMITIVE"
161 (defconst fuel-syntax--no-indent-def-starts '("SINGLETONS"
166 (defconst fuel-syntax--indent-def-start-regex
167 (format "^\\(%s:\\)\\( \\|\n\\)" (regexp-opt fuel-syntax--indent-def-starts)))
169 (defconst fuel-syntax--no-indent-def-start-regex
170 (format "^\\(%s:\\) " (regexp-opt fuel-syntax--no-indent-def-starts)))
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))))
176 (defconst fuel-syntax--definition-end-regex
177 (format "\\(\\(^\\| +\\);\\( *%s\\)*\\($\\| +\\)\\)"
178 fuel-syntax--declaration-words-regex))
180 (defconst fuel-syntax--single-liner-regex
181 (regexp-opt '("ABOUT:"
187 "GENERIC:" "GENERIC#"
188 "HELP:" "HEX:" "HOOK:"
191 "MAIN:" "MATH:" "MIXIN:"
193 "POSTPONE:" "PRIVATE>" "<PRIVATE"
194 "QUALIFIED-WITH:" "QUALIFIED:"
196 "SINGLETON:" "SLOT:" "SYMBOL:"
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))
206 (defconst fuel-syntax--end-of-def-line-regex
207 (format "^.*%s" fuel-syntax--definition-end-regex))
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))
214 (defconst fuel-syntax--defun-signature-regex
215 (format "\\(%s\\|%s\\)"
216 (format ":[^ ]* [^ ]+\\(%s\\)*" fuel-syntax--stack-effect-regex)
217 "M[^:]*: [^ ]+ [^ ]+"))
219 (defconst fuel-syntax--constructor-decl-regex
220 "\\_<C: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
222 (defconst fuel-syntax--typedef-regex
223 "\\_<TYPEDEF: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
225 (defconst fuel-syntax--rename-regex
226 "\\_<RENAME: +\\(\\w+\\) +\\(\\w+\\) +=> +\\(\\w+\\)\\( .*\\)?$")
229 ;;; Factor syntax table
231 (setq fuel-syntax--syntax-table
232 (let ((table (make-syntax-table)))
233 ;; Default is word constituent
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)
243 (defconst fuel-syntax--syntactic-keywords
245 ("\\(CHAR:\\|POSTPONE:\\|\\\\\\) \\(.\\)\\( \\|$\\)" (2 "w"))
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"))
252 ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)"
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]\\|\\_>\\)"
265 ("\\(\n\\| \\);\\_>" (1 ">b"))
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 "){"))
276 ("\\_<\\((\\)\\_>" (1 "()"))
277 ("\\_<\\()\\)\\_>" (1 ")("))
279 ("\\_<'\\(\\[\\)\\_>" (1 "(]")) ; fried
280 ("\\_<\\(\\[\\)\\_>" (1 "(]"))
281 ("\\_<\\(\\]\\)\\_>" (1 ")["))))
284 ;;; Source code analysis:
286 (defsubst fuel-syntax--brackets-depth ()
287 (nth 0 (syntax-ppss)))
289 (defsubst fuel-syntax--brackets-start ()
290 (nth 1 (syntax-ppss)))
292 (defun fuel-syntax--brackets-end ()
294 (goto-char (fuel-syntax--brackets-start))
296 (progn (forward-sexp)
300 (defsubst fuel-syntax--indentation-at (pos)
301 (save-excursion (goto-char pos) (current-indentation)))
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))
308 (defsubst fuel-syntax--at-begin-of-def ()
309 (looking-at fuel-syntax--begin-of-def-regex))
311 (defsubst fuel-syntax--at-begin-of-indent-def ()
312 (looking-at fuel-syntax--indent-def-start-regex))
314 (defsubst fuel-syntax--at-end-of-def ()
315 (looking-at fuel-syntax--end-of-def-regex))
317 (defsubst fuel-syntax--looking-at-emptiness ()
318 (looking-at "^[ ]*$\\|$"))
320 (defsubst fuel-syntax--is-last-char (pos)
323 (fuel-syntax--looking-at-emptiness)))
325 (defsubst fuel-syntax--line-offset (pos)
326 (- pos (save-excursion
331 (defun fuel-syntax--previous-non-blank ()
333 (while (and (not (bobp)) (fuel-syntax--looking-at-emptiness))
336 (defun fuel-syntax--beginning-of-block-pos ()
338 (if (> (fuel-syntax--brackets-depth) 0)
339 (fuel-syntax--brackets-start)
340 (fuel-syntax--beginning-of-defun)
343 (defun fuel-syntax--at-setter-line ()
346 (when (re-search-forward fuel-syntax--setter-regex
349 (let* ((to (match-beginning 0))
350 (from (fuel-syntax--beginning-of-block-pos)))
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))))))))
357 (defun fuel-syntax--at-constructor-line ()
360 (re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
362 (defsubst fuel-syntax--at-using ()
363 (looking-at fuel-syntax--using-lines-regex))
365 (defun fuel-syntax--in-using ()
368 (and (re-search-backward "^USING: " nil t)
369 (re-search-forward " ;" nil t)
370 (< p (match-end 0))))))
372 (defsubst fuel-syntax--beginning-of-defun (&optional times)
373 (re-search-backward fuel-syntax--begin-of-def-regex nil t times))
375 (defsubst fuel-syntax--end-of-defun ()
376 (re-search-forward fuel-syntax--end-of-def-regex nil t))
378 (defsubst fuel-syntax--end-of-defun-pos ()
380 (re-search-forward fuel-syntax--end-of-def-regex nil t)
383 (defun fuel-syntax--beginning-of-body ()
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)))))
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)))
394 (defsubst fuel-syntax--beginning-of-sexp-pos ()
395 (save-excursion (fuel-syntax--beginning-of-sexp) (point)))
400 (make-variable-buffer-local
401 (defvar fuel-syntax--current-vocab-function 'fuel-syntax--find-in))
403 (defsubst fuel-syntax--current-vocab ()
404 (funcall fuel-syntax--current-vocab-function))
406 (defun fuel-syntax--find-in ()
408 (when (re-search-backward fuel-syntax--current-vocab-regex nil t)
409 (match-string-no-properties 1))))
411 (make-variable-buffer-local
412 (defvar fuel-syntax--usings-function 'fuel-syntax--find-usings))
414 (defsubst fuel-syntax--usings ()
415 (funcall fuel-syntax--usings-function))
417 (defun fuel-syntax--file-has-private ()
419 (goto-char (point-min))
420 (and (re-search-forward "\\_<<PRIVATE\\_>" nil t)
421 (re-search-forward "\\_<PRIVATE>\\_>" nil t))))
423 (defun fuel-syntax--find-usings (&optional no-private)
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))
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))
436 (provide 'fuel-syntax)
437 ;;; fuel-syntax.el ends here