Function: antlr-indent-line
antlr-indent-line is a byte-compiled function defined in
antlr-mode.el.gz.
Signature
(antlr-indent-line)
Documentation
Indent the current line as ANTLR grammar code.
The default indentation of grammar lines are calculated by
c-basic-offset, multiplied by:
- the level of the paren/brace/bracket depth,
- plus 0/2/1, depending on the position inside the rule: header, body,
exception part, customized by antlr-base-offset-alist,
- minus 1 if antlr-indent-item-regexp matches the beginning of the
line starting from the first non-whitespace.
Lines inside block comments are indented by c-indent-line according to
antlr-indent-comment.
Lines in actions except top level actions in a header part or an option
area are indented by c-indent-line.
Lines in header actions are indented at column 0 if antlr-language
equals to a key in antlr-indent-at-bol-alist and the line starting at
the first non-whitespace is matched by the corresponding value.
For the initialization of c-basic-offset, see antlr-indent-style and,
to a lesser extent, antlr-tab-offset-alist.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/antlr-mode.el.gz
;;;===========================================================================
;;; Indentation
;;;===========================================================================
(defun antlr-indent-line ()
"Indent the current line as ANTLR grammar code.
The default indentation of grammar lines are calculated by
`c-basic-offset', multiplied by:
- the level of the paren/brace/bracket depth,
- plus 0/2/1, depending on the position inside the rule: header, body,
exception part, customized by `antlr-base-offset-alist',
- minus 1 if `antlr-indent-item-regexp' matches the beginning of the
line starting from the first non-whitespace.
Lines inside block comments are indented by `c-indent-line' according to
`antlr-indent-comment'.
Lines in actions except top level actions in a header part or an option
area are indented by `c-indent-line'.
Lines in header actions are indented at column 0 if `antlr-language'
equals to a key in `antlr-indent-at-bol-alist' and the line starting at
the first non-whitespace is matched by the corresponding value.
For the initialization of `c-basic-offset', see `antlr-indent-style' and,
to a lesser extent, `antlr-tab-offset-alist'."
;; TODO: this function needs to be rewritten
(save-restriction
(let ((orig (point))
(min0 (point-min))
bol boi indent syntax cc-syntax boa pdepth)
(widen)
(beginning-of-line)
(setq bol (point))
(if (< bol min0)
(error "Beginning of current line not visible"))
(skip-chars-forward " \t")
(setq boi (point))
;; check syntax at beginning of indentation ----------------------------
(let* ((ppss (syntax-ppss))
(context (antlr-syntactic-context ppss))
(open (nth 9 ppss))) ; TODO Emacs: syntax-ppss-open-positions
(setq syntax (or context 0))
(setq pdepth (car ppss))
;; TODO: should boa = first non-?\( in (nth 9 ppss) ?
(when (numberp context) ; boa = beginning of action
(setq boa (nth (- (length open) context) open))))
(cond ((symbolp syntax)
(setq indent nil)) ; block-comments, strings, (comments) -> cc engine
((progn
(antlr-next-rule -1 t) ; to start of rule
(= (point) boi))
(setq indent 0)) ; rule start always at 0
;; TODO: use antlr-skip-to-colon-or-semi
((if (let ((r (antlr-search-forward antlr-rule-body-start-op)))
(while (and r (eq (char-after) ?:)) ; skip double-colon
(forward-char)
(setq r (antlr-search-forward antlr-rule-body-start-op)))
r)
(< boi (1- (point)))
t)
(setq indent
(or (cdr (assq :header antlr-base-offset-alist)) 0)))
((eq (char-after boi) ?:)
(setq indent
(or (cdr (assq :colon antlr-base-offset-alist))
(cdr (assq :body antlr-base-offset-alist))
2)))
((if (antlr-search-forward ";" antlr-skip-line-regexp)
(< boi (point))
t)
(setq indent
(or (cdr (assq :body antlr-base-offset-alist)) 2)))
(t
(forward-char)
(antlr-skip-rule-postlude nil)
(setq indent
(if (> (point) boi)
(or (cdr (assq :exception antlr-base-offset-alist)) 1)
0)))) ; in exception part?
;; check whether to use indentation engine of cc-mode ------------------
(goto-char boi)
(when (and indent (> syntax 0))
(cond ((> syntax 1) ; block in action => use cc-mode (or nothing)
(setq indent nil)
(when antlr-indent-action-line
(setq syntax 'non-cc)))
((and (= indent 0) ; TODO: recheck
(assq antlr-action-mode antlr-indent-at-bol-alist)
(looking-at (cdr (assq antlr-action-mode
antlr-indent-at-bol-alist))))
(setq syntax 'bol))
((memq (char-after) '(?\} ?\]))) ; close the block -> usual grammar indent
(antlr-indent-action-line
;; TODO: parameters, and mode-specific - should we handle options{} and tokens{} extra?
(setq indent nil syntax 'non-cc))
((setq cc-syntax (c-guess-basic-syntax))
(let ((cc cc-syntax) symbol)
(while (setq symbol (pop cc))
(when (cdr symbol)
(or (memq (car symbol)
antlr-disabling-cc-syntactic-symbols)
(setq indent nil))
(setq cc nil)))))))
;; compute the corresponding indentation and indent --------------------
(if (null indent)
;; Use the indentation engine of cc-mode
(progn
(goto-char orig)
(cond ((eq syntax 'non-cc)
;; TODO: we might check whether the current line is the
;; first code in the action -> then we simply indent
;; according to indent-level (then we do not have to check
;; whether the LANGUAGE indents at col 0 (and use C indent)
(funcall antlr-indent-action-line boa))
((or (numberp syntax)
(if (eq syntax 'string) nil (eq antlr-indent-comment t)))
(c-indent-line cc-syntax))))
;; do it ourselves
(goto-char boi)
(unless (symbolp syntax) ; direct indentation
(cl-incf indent pdepth)
(and (> indent 0) (looking-at antlr-indent-item-regexp)
(cl-decf indent))
(setq indent (* indent c-basic-offset)))
;; the usual major-mode indent stuff ---------------------------------
;; TODO: use `indent-line-to' instead?
(setq orig (- (point-max) orig))
(unless (= (current-column) indent)
(delete-region bol boi)
(beginning-of-line)
(indent-to indent))
;; If initial point was within line's indentation,
;; position after the indentation. Else stay at same point in text.
(if (> (- (point-max) orig) (point))
(goto-char (- (point-max) orig)))))))