You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
6.3 KiB
147 lines
6.3 KiB
6 years ago
|
;;;; A syntax highlighting and indentation mode for the altarica language
|
||
|
|
||
|
(defvar altarica-mode-hook nil)
|
||
|
(add-to-list 'auto-mode-alist '("\\.alt\\'" . altarica-mode))
|
||
|
|
||
|
;; define keyword classes
|
||
|
(setq altarica-struct-regexp
|
||
|
(regexp-opt '("node" "edon" "domain" "const" "in" "out" "flow" "state"
|
||
|
"assert" "event" "trans" "extern" "init" "param" "param_set"
|
||
|
"sort" "sub" "struct" "tcurts" "sync")
|
||
|
'words))
|
||
|
(setq altarica-builtin-regexp
|
||
|
(regexp-opt '("and" "or" "not" "imply" "max" "min" "mod" "sig"
|
||
|
"if" "then" "else" "case" "esac" "law" "constant"
|
||
|
"exponential" "dirac")
|
||
|
'words))
|
||
|
(setq altarica-type-regexp (regexp-opt '("int" "integer" "bool") 'words))
|
||
|
(setq altarica-bconstants-regexp (regexp-opt '("true" "false") 'words))
|
||
|
(setq altarica-nconstants-regexp "[[:digit:]]+\\(.[[:digit:]]+\\)?")
|
||
|
|
||
|
(setq altarica-font-lock-keywords
|
||
|
`((,altarica-struct-regexp . font-lock-keyword-face)
|
||
|
(,altarica-builtin-regexp . font-lock-builtin-face)
|
||
|
(,altarica-type-regexp . font-lock-type-face)
|
||
|
(,altarica-bconstants-regexp . font-lock-constant-face)
|
||
|
(,altarica-nconstants-regexp . font-lock-constant-face)
|
||
|
;; highlight transition symbols
|
||
|
(,"\\(|-[^-]*->\\)" . font-lock-function-name-face)
|
||
|
;; bold assignments and question marks
|
||
|
(,"\\(\\?\\|:=\\)" (1 '(:weight bold)))
|
||
|
;; highlight types in domain declaration
|
||
|
(,"domain[ \t]+\\([[:alnum:]_]+\\)" (1 font-lock-type-face))
|
||
|
;; highlight types in node declaration
|
||
|
(,"node[ \t]+\\([[:alnum:]_]+\\)" (1 font-lock-type-face))
|
||
|
;; highlight types in state/sub declaration
|
||
|
(,(concat "^[ \t]*\\(sub\\|state\\)?"
|
||
|
"[ \t]*[[:alnum:]_]+[ \t]*:"
|
||
|
"[ \t]*\\([[:alnum:]_]+\\)[ \t]*;")
|
||
|
(2 font-lock-type-face))
|
||
|
;; highlight types in flow declaration
|
||
|
(,(concat "[ \t]*\\(flow\\)?"
|
||
|
"[ \t]*[[:alnum:]_]+[ \t]*:"
|
||
|
"[ \t]*\\([[:alnum:]_]+\\)[ \t]*:"
|
||
|
"[ \t]*\\(in\\|out\\)[ \t]*;")
|
||
|
(2 font-lock-type-face))))
|
||
|
|
||
|
(defvar altarica-basic-offset 2)
|
||
|
|
||
|
(defun altarica-indent-line ()
|
||
|
"Indent current line as altarica code"
|
||
|
(interactive)
|
||
|
;; without this indent-line-to moves the point to beginning of line
|
||
|
(let ((altarica-kw-main
|
||
|
"^[ \t]*\\(node\\|domain\\|const\\|edon\\)\\([^a-zA-Z_0-9].*\\)?$")
|
||
|
(altarica-kw-secondary
|
||
|
(concat "^[ \t]*\\(flow\\|state\\|assert\\|"
|
||
|
"event\\|trans\\|init\\|extern\\|sub\\|sync\\)"))
|
||
|
(indent-unit altarica-basic-offset)
|
||
|
next-indent)
|
||
|
(save-excursion
|
||
|
(beginning-of-line)
|
||
|
(setq next-indent
|
||
|
(cond ((bobp) 0)
|
||
|
((looking-at altarica-kw-main) 0)
|
||
|
((looking-at altarica-kw-secondary) indent-unit)
|
||
|
((looking-at "^[ \t]*|-") (* 3 indent-unit))
|
||
|
(t nil)))
|
||
|
(if (not next-indent)
|
||
|
(progn
|
||
|
(while (not next-indent)
|
||
|
(forward-line -1)
|
||
|
(setq next-indent
|
||
|
(cond ((bobp) 0)
|
||
|
;; previous line is primary keyword
|
||
|
((looking-at altarica-kw-main) indent-unit)
|
||
|
;; previous line is secondary keyword
|
||
|
((looking-at altarica-kw-secondary) (* 2 indent-unit))
|
||
|
;; previous line ends with semicolon
|
||
|
((looking-at ".*;[ \t]*$") (* 2 indent-unit))
|
||
|
;; previous line ends with "->"
|
||
|
((looking-at ".*->[ \t]*$") (* 4 indent-unit))
|
||
|
;; previous line contains "->"
|
||
|
((re-search-forward "->[ \t]*"
|
||
|
(line-end-position)
|
||
|
t)
|
||
|
(current-column))
|
||
|
;; previous line contains "|-"
|
||
|
((looking-at "^[ \t]*|-") (* 4 indent-unit))
|
||
|
;; previous line ends with "case { "
|
||
|
((re-search-forward "case[ \t]*{[ \t]*$"
|
||
|
(line-end-position)
|
||
|
t)
|
||
|
(+ 2 (- (match-beginning 0)
|
||
|
(line-beginning-position))))
|
||
|
;; previous line contains "case { "
|
||
|
((re-search-forward "case[ \t]*{[ \t]*"
|
||
|
(line-end-position)
|
||
|
t)
|
||
|
(current-column))
|
||
|
;; else look at previous previous line
|
||
|
(t nil)))))))
|
||
|
(setq offset (max 0 (- (current-column) (current-indentation))))
|
||
|
(indent-line-to next-indent)
|
||
|
(move-to-column (+ (current-indentation) offset))))
|
||
|
|
||
|
;; command to comment/uncomment text
|
||
|
(defun altarica-comment-dwim (arg)
|
||
|
"Comment or uncomment current line or region in a smart way.
|
||
|
For detail, see `comment-dwim'."
|
||
|
(interactive "*P")
|
||
|
(require 'newcomment)
|
||
|
(let ((comment-start "//") (comment-end ""))
|
||
|
(comment-dwim arg)))
|
||
|
|
||
|
;; Syntax table magic ... yadda yadda abracadabra ... COMMENTS !!
|
||
|
(defvar altarica-syntax-table nil "Syntax table for `altarica-mode'.")
|
||
|
(setq altarica-syntax-table
|
||
|
(let ((table (make-syntax-table)))
|
||
|
;; make underscore a word char
|
||
|
(modify-syntax-entry ?_ "w" table)
|
||
|
;; detect c++ comments
|
||
|
(modify-syntax-entry ?/ ". 124" table)
|
||
|
(modify-syntax-entry ?* ". 23b" table)
|
||
|
(modify-syntax-entry ?\n ">" table)
|
||
|
table))
|
||
|
|
||
|
;; define the mode
|
||
|
(define-derived-mode altarica-mode fundamental-mode
|
||
|
"Major mode for editing altarica"
|
||
|
(set-syntax-table altarica-syntax-table)
|
||
|
|
||
|
(setq font-lock-defaults '(altarica-font-lock-keywords))
|
||
|
(setq indent-line-function 'altarica-indent-line)
|
||
|
(setq mode-name "altarica mode")
|
||
|
|
||
|
;; modify the keymap
|
||
|
(define-key altarica-mode-map [remap comment-dwim] 'altarica-comment-dwim)
|
||
|
|
||
|
;; clear memory
|
||
|
(setq altarica-struct-regexp nil)
|
||
|
(setq altarica-func-regexp nil)
|
||
|
(setq altarica-builtin-regexp nil)
|
||
|
(setq altarica-type-regexp nil)
|
||
|
(setq altarica-constants-regexp nil)
|
||
|
(setq altarica-symbols-regexp nil)
|
||
|
)
|