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.
146 lines
6.3 KiB
146 lines
6.3 KiB
;;;; 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) |
|
)
|
|
|