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)))))))