2 ;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
\r
4 ;; Copyright (C) 2008, 2009 Jose Antonio Ortega Ruiz
\r
5 ;; See http://factorcode.org/license.txt for BSD license.
\r
7 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
\r
8 ;; Keywords: languages
\r
12 ;; Auxiliar constants and functions to parse factor code.
\r
16 (require 'thingatpt)
\r
19 ;;; Thing-at-point support for factor symbols:
\r
21 (defun fuel-syntax--beginning-of-symbol ()
\r
22 "Move point to the beginning of the current symbol."
\r
23 (skip-syntax-backward "w_()"))
\r
25 (defsubst fuel-syntax--beginning-of-symbol-pos ()
\r
26 (save-excursion (fuel-syntax--beginning-of-symbol) (point)))
\r
28 (defun fuel-syntax--end-of-symbol ()
\r
29 "Move point to the end of the current symbol."
\r
30 (skip-syntax-forward "w_()"))
\r
32 (defsubst fuel-syntax--end-of-symbol-pos ()
\r
33 (save-excursion (fuel-syntax--end-of-symbol) (point)))
\r
35 (put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
\r
36 (put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
\r
38 (defsubst fuel-syntax-symbol-at-point ()
\r
39 (let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
\r
40 (and (> (length s) 0) s)))
\r
46 (defconst fuel-syntax--parsing-words
\r
47 '(":" "::" ";" "&:" "<<" "<PRIVATE" ">>"
\r
48 "ABOUT:" "AFTER:" "ALIAS:" "ALIEN:" "ARTICLE:"
\r
50 "C:" "CALLBACK:" "C-GLOBAL:" "C-TYPE:" "CHAR:" "COM-INTERFACE:" "CONSTANT:" "CONSULT:" "call-next-method"
\r
51 "DEFER:" "DESTRUCTOR:"
\r
52 "EBNF:" ";EBNF" "ENUM:" "ERROR:" "EXCLUDE:"
\r
53 "f" "FORGET:" "FROM:" "FUNCTION:" "FUNCTION-ALIAS:"
\r
54 "GAME:" "GENERIC#" "GENERIC:"
\r
55 "GLSL-SHADER:" "GLSL-PROGRAM:"
\r
57 "IN:" "initial:" "INSTANCE:" "INTERSECTION:"
\r
59 "M:" "M::" "MACRO:" "MACRO::" "MAIN:" "MATH:"
\r
60 "MEMO:" "MEMO:" "METHOD:" "MIXIN:"
\r
62 "POSTPONE:" "PREDICATE:" "PRIMITIVE:" "PRIVATE>" "PROTOCOL:" "PROVIDE:"
\r
63 "QUALIFIED-WITH:" "QUALIFIED:"
\r
64 "read-only" "RENAME:" "REQUIRE:" "REQUIRES:"
\r
65 "SINGLETON:" "SINGLETONS:" "SLOT:" "SPECIALIZED-ARRAY:" "SPECIALIZED-ARRAYS:" "STRING:" "STRUCT:" "SYMBOL:" "SYMBOLS:" "SYNTAX:"
\r
66 "TUPLE:" "t" "t?" "TYPEDEF:" "TYPED:" "TYPED::"
\r
67 "UNIFORM-TUPLE:" "UNION:" "UNION-STRUCT:" "USE:" "USING:"
\r
68 "VARIANT:" "VERTEX-FORMAT:"))
\r
70 (defconst fuel-syntax--parsing-words-regex
\r
71 (regexp-opt fuel-syntax--parsing-words 'words))
\r
73 (defconst fuel-syntax--bracers
\r
74 '("B" "BV" "C" "CS" "H" "T" "V" "W"))
\r
76 (defconst fuel-syntax--brace-words-regex
\r
77 (format "%s{" (regexp-opt fuel-syntax--bracers t)))
\r
79 (defconst fuel-syntax--declaration-words
\r
80 '("flushable" "foldable" "inline" "parsing" "recursive" "delimiter"))
\r
82 (defconst fuel-syntax--declaration-words-regex
\r
83 (regexp-opt fuel-syntax--declaration-words 'words))
\r
85 (defsubst fuel-syntax--second-word-regex (prefixes)
\r
86 (format "%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
\r
88 (defconst fuel-syntax--method-definition-regex
\r
89 "^M::? +\\([^ ]+\\) +\\([^ ]+\\)")
\r
91 (defconst fuel-syntax--before-definition-regex
\r
92 "^BEFORE: +\\([^ ]+\\) +\\([^ ]+\\)")
\r
94 (defconst fuel-syntax--after-definition-regex
\r
95 "^AFTER: +\\([^ ]+\\) +\\([^ ]+\\)")
\r
97 (defconst fuel-syntax--integer-regex
\r
100 (defconst fuel-syntax--raw-float-regex
\r
101 "[0-9]*\\.[0-9]*\\([eEpP][+-]?[0-9]+\\)?")
\r
103 (defconst fuel-syntax--float-regex
\r
104 (format "\\_<-?%s\\_>" fuel-syntax--raw-float-regex))
\r
106 (defconst fuel-syntax--number-regex
\r
107 (format "\\([0-9]+\\|%s\\)" fuel-syntax--raw-float-regex))
\r
109 (defconst fuel-syntax--ratio-regex
\r
110 (format "\\_<[+-]?%s/-?%s\\_>"
\r
111 fuel-syntax--number-regex
\r
112 fuel-syntax--number-regex))
\r
114 (defconst fuel-syntax--bad-string-regex
\r
115 "\\_<\"[^>]\\([^\"\n]\\|\\\\\"\\)*\n")
\r
117 (defconst fuel-syntax--word-definition-regex
\r
118 (format "\\_<\\(%s\\)?: +\\_<\\(\\w+\\)\\_>"
\r
120 '(":" "GENERIC" "DEFER" "HOOK" "MAIN" "MATH" "POSTPONE"
\r
121 "SYMBOL" "SYNTAX" "TYPED" "TYPED:" "RENAME"))))
\r
123 (defconst fuel-syntax--alias-definition-regex
\r
124 "^ALIAS: +\\(\\_<.+?\\_>\\) +\\(\\_<.+?\\_>\\)")
\r
126 (defconst fuel-syntax--vocab-ref-regexp
\r
127 (fuel-syntax--second-word-regex
\r
128 '("IN:" "USE:" "FROM:" "EXCLUDE:" "QUALIFIED:" "QUALIFIED-WITH:")))
\r
130 (defconst fuel-syntax--int-constant-def-regex
\r
131 (fuel-syntax--second-word-regex '("ALIEN:" "CHAR:" "NAN:")))
\r
133 (defconst fuel-syntax--type-definition-regex
\r
134 (fuel-syntax--second-word-regex
\r
135 '("C-STRUCT:" "C-UNION:" "COM-INTERFACE:" "MIXIN:" "TUPLE:" "SINGLETON:" "SPECIALIZED-ARRAY:" "STRUCT:" "UNION:" "UNION-STRUCT:")))
\r
137 (defconst fuel-syntax--error-regex
\r
138 (fuel-syntax--second-word-regex '("ERROR:")))
\r
140 (defconst fuel-syntax--tuple-decl-regex
\r
141 "^TUPLE: +\\([^ \n]+\\) +< +\\([^ \n]+\\)\\_>")
\r
143 (defconst fuel-syntax--constructor-regex "<[^ >]+>")
\r
145 (defconst fuel-syntax--getter-regex "\\(^\\|\\_<\\)[^ ]+?>>\\_>")
\r
146 (defconst fuel-syntax--setter-regex "\\_<>>.+?\\_>")
\r
148 (defconst fuel-syntax--symbol-definition-regex
\r
149 (fuel-syntax--second-word-regex '("&:" "SYMBOL:" "VAR:")))
\r
151 (defconst fuel-syntax--stack-effect-regex
\r
152 "\\( ( [^\n]* )\\)\\|\\( (( [^\n]* ))\\)")
\r
154 (defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
\r
156 (defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
\r
158 (defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
\r
160 (defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
\r
162 (defconst fuel-syntax--alien-function-regex
\r
163 "\\_<FUNCTION: +\\(\\w+\\)[\n ]+\\(\\w+\\)")
\r
165 (defconst fuel-syntax--alien-function-alias-regex
\r
166 "\\_<FUNCTION-ALIAS: +\\(\\w+\\)[\n ]+\\(\\w+\\)[\n ]+\\(\\w+\\)")
\r
168 (defconst fuel-syntax--alien-callback-regex
\r
169 "\\_<CALLBACK: +\\(\\w+\\) +\\(\\w+\\)")
\r
171 (defconst fuel-syntax--indent-def-starts '("" ":"
\r
173 "COM-INTERFACE" "CONSULT"
\r
175 "FROM" "FUNCTION:" "FUNCTION-ALIAS:"
\r
177 "M" "M:" "MACRO" "MACRO:"
\r
178 "MEMO" "MEMO:" "METHOD"
\r
180 "PREDICATE" "PRIMITIVE" "PROTOCOL"
\r
182 "STRUCT" "SYMBOLS" "TAG" "TUPLE"
\r
185 "UNION-STRUCT" "UNION"
\r
186 "VARIANT" "VERTEX-FORMAT"))
\r
188 (defconst fuel-syntax--no-indent-def-starts '("ARTICLE"
\r
190 "SPECIALIZED-ARRAYS"))
\r
192 (defconst fuel-syntax--indent-def-start-regex
\r
193 (format "^\\(%s:\\)\\( \\|\n\\)" (regexp-opt fuel-syntax--indent-def-starts)))
\r
195 (defconst fuel-syntax--definition-start-regex
\r
196 (format "^\\(%s:\\) " (regexp-opt (append fuel-syntax--no-indent-def-starts
\r
197 fuel-syntax--indent-def-starts))))
\r
199 (defconst fuel-syntax--definition-end-regex
\r
200 (format "\\(\\(^\\| +\\);\\( *%s\\)*\\($\\| +\\)\\)"
\r
201 fuel-syntax--declaration-words-regex))
\r
203 (defconst fuel-syntax--single-liner-regex
\r
204 (regexp-opt '("ABOUT:"
\r
206 "CONSTANT:" "C:" "C-GLOBAL:" "C-TYPE:"
\r
207 "DEFER:" "DESTRUCTOR:"
\r
209 "GAME:" "GENERIC:" "GENERIC#" "GLSL-PROGRAM:"
\r
213 "MAIN:" "MATH:" "MIXIN:"
\r
215 "POSTPONE:" "PRIVATE>" "<PRIVATE"
\r
216 "QUALIFIED-WITH:" "QUALIFIED:"
\r
218 "SINGLETON:" "SLOT:" "SPECIALIZED-ARRAY:" "SYMBOL:"
\r
223 (defconst fuel-syntax--begin-of-def-regex
\r
224 (format "^USING: \\|\\(%s\\)\\|\\(^%s .*\\)"
\r
225 fuel-syntax--definition-start-regex
\r
226 fuel-syntax--single-liner-regex))
\r
228 (defconst fuel-syntax--end-of-def-line-regex
\r
229 (format "^.*%s" fuel-syntax--definition-end-regex))
\r
231 (defconst fuel-syntax--end-of-def-regex
\r
232 (format "\\(%s\\)\\|\\(^%s .*\\)"
\r
233 fuel-syntax--end-of-def-line-regex
\r
234 fuel-syntax--single-liner-regex))
\r
236 (defconst fuel-syntax--word-signature-regex
\r
237 (format ":[^ ]* \\([^ ]+\\)\\(%s\\)*" fuel-syntax--stack-effect-regex))
\r
239 (defconst fuel-syntax--defun-signature-regex
\r
240 (format "\\(%s\\|%s\\)"
\r
241 fuel-syntax--word-signature-regex
\r
242 "M[^:]*: [^ ]+ [^ ]+"))
\r
244 (defconst fuel-syntax--constructor-decl-regex
\r
245 "\\_<C: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
\r
247 (defconst fuel-syntax--typedef-regex
\r
248 "\\_<TYPEDEF: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
\r
250 (defconst fuel-syntax--c-global-regex
\r
251 "\\_<C-GLOBAL: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
\r
253 (defconst fuel-syntax--c-type-regex
\r
254 "\\_<C-TYPE: +\\(\\w+\\)\\( .*\\)?$")
\r
256 (defconst fuel-syntax--rename-regex
\r
257 "\\_<RENAME: +\\(\\w+\\) +\\(\\w+\\) +=> +\\(\\w+\\)\\( .*\\)?$")
\r
260 ;;; Factor syntax table
\r
262 (setq fuel-syntax--syntax-table
\r
263 (let ((table (make-syntax-table)))
\r
264 ;; Default is word constituent
\r
266 (modify-syntax-entry i "w" table))
\r
267 ;; Whitespace (TAB is not whitespace)
\r
268 (modify-syntax-entry ?\f " " table)
\r
269 (modify-syntax-entry ?\r " " table)
\r
270 (modify-syntax-entry ?\ " " table)
\r
271 (modify-syntax-entry ?\n " " table)
\r
274 (defconst fuel-syntax--syntactic-keywords
\r
275 `(;; Strings and chars
\r
276 ("\\_<<\\(\"\\)\\_>" (1 "<b"))
\r
277 ("\\_<\\(\"\\)>\\_>" (1 ">b"))
\r
278 ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)?\\(\"\\)\\(\\([^\n\r\f\"\\]\\|\\\\.\\)*\\)\\(\"\\)"
\r
280 ("CHAR: \\(\"\\) [^\\\"]*?\\(\"\\)\\([^\\\"]\\|\\\\.\\)*?\\(\"\\)"
\r
281 (1 "w") (2 "<b") (4 ">b"))
\r
282 ("\\(CHAR:\\|\\\\\\) \\(\\w\\|!\\)\\( \\|$\\)" (2 "w"))
\r
284 ("\\_<\\(#?!\\) .*\\(\n\\|$\\)" (1 "<") (2 ">"))
\r
285 ("\\_<\\(#?!\\)\\(\n\\|$\\)" (1 "<") (2 ">"))
\r
287 ("\\_<POSTPONE:\\( \\).*\\(\n\\)" (1 "<b") (2 ">b"))
\r
288 ;; Multiline constructs
\r
289 ("\\_<\\(E\\)BNF:\\( \\|\n\\)" (1 "<b"))
\r
290 ("\\_<;EBN\\(F\\)\\_>" (1 ">b"))
\r
291 ("\\_<\\(U\\)SING: \\(;\\)" (1 "<b") (2 ">b"))
\r
292 ("\\_<USING:\\( \\)" (1 "<b"))
\r
293 ("\\_<\\(C\\)-ENUM: \\(;\\)" (1 "<b") (2 ">b"))
\r
294 ("\\_<ENUM:\\( \\|\n\\)" (1 "<b"))
\r
295 ("\\_<TUPLE: +\\w+? +< +\\w+? *\\( \\|\n\\)\\([^;]\\|$\\)" (1 "<b"))
\r
296 ("\\_<TUPLE: +\\w+? *\\( \\|\n\\)\\([^;<\n]\\|\\_>\\)" (1 "<b"))
\r
297 ("\\_<\\(SYMBOLS\\|SPECIALIZED-ARRAYS\\|SINGLETONS\\|VARIANT\\): *?\\( \\|\n\\)\\([^;\n]\\|\\_>\\)"
\r
299 ("\\(\n\\| \\);\\_>" (1 ">b"))
\r
301 ("\\_<\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
\r
302 ("\\(\\[\\)\\(let\\|let\\*\\)\\( \\|$\\)" (1 "(]"))
\r
303 ("\\(\\[\\)\\(|\\) +[^|]* \\(|\\)" (1 "(]") (2 "(|") (3 ")|"))
\r
304 (" \\(|\\) " (1 "(|"))
\r
305 (" \\(|\\)$" (1 ")"))
\r
306 ;; Opening brace words:
\r
307 ("\\_<\\w*\\({\\)\\_>" (1 "(}"))
\r
308 ("\\_<\\(}\\)\\_>" (1 "){"))
\r
310 ("\\_<\\((\\)\\_>" (1 "()"))
\r
311 ("\\_<\\w*\\((\\)\\_>" (1 "()"))
\r
312 ("\\_<\\()\\)\\_>" (1 ")("))
\r
313 ("\\_<(\\((\\)\\_>" (1 "()"))
\r
314 ("\\_<\\()\\))\\_>" (1 ")("))
\r
316 ("\\_<'\\(\\[\\)\\_>" (1 "(]")) ; fried
\r
317 ("\\_<$\\(\\[\\)\\_>" (1 "(]")) ; parse-time
\r
318 ("\\_<\\(\\[\\)\\_>" (1 "(]"))
\r
319 ("\\_<\\(\\]\\)\\_>" (1 ")["))))
\r
322 ;;; Source code analysis:
\r
324 (defsubst fuel-syntax--brackets-depth ()
\r
325 (nth 0 (syntax-ppss)))
\r
327 (defsubst fuel-syntax--brackets-start ()
\r
328 (nth 1 (syntax-ppss)))
\r
330 (defun fuel-syntax--brackets-end ()
\r
332 (goto-char (fuel-syntax--brackets-start))
\r
333 (condition-case nil
\r
334 (progn (forward-sexp)
\r
338 (defsubst fuel-syntax--indentation-at (pos)
\r
339 (save-excursion (goto-char pos) (current-indentation)))
\r
341 (defsubst fuel-syntax--increased-indentation (&optional i)
\r
342 (+ (or i (current-indentation)) factor-indent-width))
\r
343 (defsubst fuel-syntax--decreased-indentation (&optional i)
\r
344 (- (or i (current-indentation)) factor-indent-width))
\r
346 (defsubst fuel-syntax--at-begin-of-def ()
\r
347 (looking-at fuel-syntax--begin-of-def-regex))
\r
349 (defsubst fuel-syntax--at-begin-of-indent-def ()
\r
350 (looking-at fuel-syntax--indent-def-start-regex))
\r
352 (defsubst fuel-syntax--at-end-of-def ()
\r
353 (looking-at fuel-syntax--end-of-def-regex))
\r
355 (defsubst fuel-syntax--looking-at-emptiness ()
\r
356 (looking-at "^[ ]*$\\|$"))
\r
358 (defsubst fuel-syntax--is-last-char (pos)
\r
360 (goto-char (1+ pos))
\r
361 (looking-at-p "[ ]*$")))
\r
363 (defsubst fuel-syntax--line-offset (pos)
\r
364 (- pos (save-excursion
\r
366 (beginning-of-line)
\r
369 (defun fuel-syntax--previous-non-blank ()
\r
371 (while (and (not (bobp)) (fuel-syntax--looking-at-emptiness))
\r
372 (forward-line -1)))
\r
374 (defun fuel-syntax--beginning-of-block-pos ()
\r
376 (if (> (fuel-syntax--brackets-depth) 0)
\r
377 (fuel-syntax--brackets-start)
\r
378 (fuel-syntax--beginning-of-defun)
\r
381 (defun fuel-syntax--at-setter-line ()
\r
383 (beginning-of-line)
\r
384 (when (re-search-forward fuel-syntax--setter-regex
\r
385 (line-end-position)
\r
387 (let* ((to (match-beginning 0))
\r
388 (from (fuel-syntax--beginning-of-block-pos)))
\r
390 (let ((depth (fuel-syntax--brackets-depth)))
\r
391 (and (or (re-search-forward fuel-syntax--constructor-regex to t)
\r
392 (re-search-forward fuel-syntax--setter-regex to t))
\r
393 (= depth (fuel-syntax--brackets-depth))))))))
\r
395 (defun fuel-syntax--at-constructor-line ()
\r
397 (beginning-of-line)
\r
398 (re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
\r
400 (defsubst fuel-syntax--at-using ()
\r
401 (looking-at fuel-syntax--using-lines-regex))
\r
403 (defun fuel-syntax--in-using ()
\r
406 (and (re-search-backward "^USING: " nil t)
\r
407 (re-search-forward " ;" nil t)
\r
408 (< p (match-end 0))))))
\r
410 (defsubst fuel-syntax--beginning-of-defun (&optional times)
\r
411 (re-search-backward fuel-syntax--begin-of-def-regex nil t times))
\r
413 (defsubst fuel-syntax--end-of-defun ()
\r
414 (re-search-forward fuel-syntax--end-of-def-regex nil t))
\r
416 (defsubst fuel-syntax--end-of-defun-pos ()
\r
418 (re-search-forward fuel-syntax--end-of-def-regex nil t)
\r
421 (defun fuel-syntax--beginning-of-body ()
\r
423 (and (fuel-syntax--beginning-of-defun)
\r
424 (re-search-forward fuel-syntax--defun-signature-regex p t)
\r
425 (not (re-search-forward fuel-syntax--end-of-def-regex p t)))))
\r
427 (defun fuel-syntax--beginning-of-sexp ()
\r
428 (if (> (fuel-syntax--brackets-depth) 0)
\r
429 (goto-char (fuel-syntax--brackets-start))
\r
430 (fuel-syntax--beginning-of-body)))
\r
432 (defsubst fuel-syntax--beginning-of-sexp-pos ()
\r
433 (save-excursion (fuel-syntax--beginning-of-sexp) (point)))
\r
438 (make-variable-buffer-local
\r
439 (defvar fuel-syntax--current-vocab-function 'fuel-syntax--find-in))
\r
441 (defsubst fuel-syntax--current-vocab ()
\r
442 (funcall fuel-syntax--current-vocab-function))
\r
444 (defun fuel-syntax--find-in ()
\r
446 (when (re-search-backward fuel-syntax--current-vocab-regex nil t)
\r
447 (match-string-no-properties 1))))
\r
449 (make-variable-buffer-local
\r
450 (defvar fuel-syntax--usings-function 'fuel-syntax--find-usings))
\r
452 (defsubst fuel-syntax--usings ()
\r
453 (funcall fuel-syntax--usings-function))
\r
455 (defun fuel-syntax--file-has-private ()
\r
457 (goto-char (point-min))
\r
458 (and (re-search-forward "\\_<<PRIVATE\\_>" nil t)
\r
459 (re-search-forward "\\_<PRIVATE>\\_>" nil t))))
\r
461 (defun fuel-syntax--find-usings (&optional no-private)
\r
464 (goto-char (point-max))
\r
465 (while (re-search-backward fuel-syntax--using-lines-regex nil t)
\r
466 (dolist (u (split-string (match-string-no-properties 1) nil t))
\r
468 (when (and (not no-private) (fuel-syntax--file-has-private))
\r
469 (goto-char (point-max))
\r
470 (push (concat (fuel-syntax--find-in) ".private") usings))
\r
474 (provide 'fuel-syntax)
\r
475 ;;; fuel-syntax.el ends here
\r