;;; sax major mode for syntax highlighting only
;;;
;;; Add
;;;
;;; (setq snax-root "/Users/fp/programs/snax/src/")
;;; (load (concat sax-root "sax.el"))
;;; (setq auto-mode-alist (cons '("\\.sax$" . sax-mode) (cons '("\\.val$" . sax-mode) auto-mode-alist)))
;;;
;;; to your .emacs or Preferences.el file

(defvar sax-mode-syntax-table nil "syntax table for `sax-mode'.")

(setq sax-mode-syntax-table
      (let ((synTable (make-syntax-table)))
        (modify-syntax-entry ?\( "()" synTable)
        (modify-syntax-entry ?\) ")(" synTable)
        (modify-syntax-entry ?{ "(}" synTable)
        (modify-syntax-entry ?} "){" synTable)
        (modify-syntax-entry ?* ". 23bn" synTable) ; comment /* start, and */ end
        (modify-syntax-entry ?$ "w" synTable)      ; to simplify patterns
        (modify-syntax-entry ?' "w" synTable)      ; to simplify patterns
        (modify-syntax-entry ?: "." synTable)
        (modify-syntax-entry ?, "." synTable)
        (modify-syntax-entry ?+ "." synTable)
        ;; (modify-syntax-entry ?. "." synTable)
        ;; (modify-syntax-entry ?& "." synTable)
        ;; commented out the next two because of '->' and '=>'
        ;; (modify-syntax-entry ?< "(>" synTable)
        ;; (modify-syntax-entry ?> ")<" synTable)
        ;; see arrows-not-delimiter below
        ;; (modify-syntax-entry ?< "." synTable)
        ;; (modify-syntax-entry ?> "." synTable)
        ;; (modify-syntax-entry ?- "." synTable)
        (modify-syntax-entry ?= "." synTable)
        (modify-syntax-entry ?/ ". 124" synTable) ; comment start, in two ways
        (modify-syntax-entry ?\n ">" synTable)    ; single-line comment end
        (modify-syntax-entry ?_ "w" synTable)     ; purposely, to simplify highlight patterns
        ;; (modify-syntax-entry ?# "w" synTable) ; for pragma #use
        synTable))

;; currently not used
(defun all-type-names-regexp (limit)
  (let ((type-names nil))
    (while (re-search-forward "\\<\\(type\\)\\>\\s-+\\<\\(\\w+\\)\\>" limit t)
      (let ((type-name (match-string 2)))
        (setq type-names (cons type-name type-names))))
    (let ((type-names-regexp (concat "\\<\\(" (string-join fun-names "\\|") "\\)\\>")))
      type-names-regexp)))

(setq debug-info nil)

;; this doesn't seem to be working
(defun arrows-not-delimiters (start end)
  "Change syntax of characters ?< and ?> to symbol if part of an arrow"
  (save-excursion
    (goto-char start)
    (setq debug-info 0)
    (while (re-search-forward "->\\|=>" end t)
      (setq debug-info (buffer-substring (1- (point)) (point)))
      (put-text-property (1- (point)) (point)
                         'syntax-table (string-to-syntax ".")))))

(setq sax-highlights
      '(("\\<\\(type\\|proc\\|value\\|read\\|write\\|cut\\|id\\|call\\)\\>" . 'font-lock-keyword-face)
        ("\\(\\<'\\w+\\>\\)" . 'font-lock-constant-face)
        ("\\<\\(type\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-function-name-face)
        ("\\<\\(proc\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-function-name-face)
        ("\\<\\(value\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-function-name-face)
        ("\\<\\(call\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-function-name-face)
        ("\\<\\(write\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-variable-name-face)
        ("\\<\\(id\\)\\>\\s-+\\<\\(\\w+\\)\\>" 2 'font-lock-variable-name-face)
        ("\\<\\(call\\)\\>\\s-+\\<\\(\\w+\\)\\>\\s-+\\<\\(\\w+\\)\\>" 3 'font-lock-variable-name-face)
        ("\\<\\(proc\\)\\>\\s-+\\<\\(\\w+\\)\\>\\s-+\\(([^)]+)\\)" 3 'font-lock-variable-name-face)
        ("\\<fail\\>" . 'font-lock-warning-face)))

(define-derived-mode sax-mode fundamental-mode "sax"
  "major mode for editing sax code"
  (setq font-lock-defaults '(sax-highlights))
  (set-syntax-table sax-mode-syntax-table)
  ;; (arrows-not-delimiters (point-min) (point-max))
  )

(provide 'sax-mode)
