Function: vhdl-get-syntactic-context
vhdl-get-syntactic-context is a byte-compiled function defined in
vhdl-mode.el.gz.
Signature
(vhdl-get-syntactic-context)
Documentation
Guess the syntactic description of the current line of VHDL code.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/vhdl-mode.el.gz
(defun vhdl-get-syntactic-context ()
"Guess the syntactic description of the current line of VHDL code."
(save-excursion
(save-restriction
(beginning-of-line)
(let* ((indent-point (point))
(case-fold-search t)
vec literal containing-sexp preceding-sexp
containing-begin containing-mid containing-leader
char-before-ip char-after-ip begin-after-ip end-after-ip
placeholder lim library-unit
)
;; Reset the syntactic context
(setq vhdl-syntactic-context nil)
(save-excursion
;; Move to the start of the previous library unit, and
;; record the position of the "begin" keyword.
(setq placeholder (vhdl-beginning-of-libunit))
;; The position of the "libunit" keyword gives us a gross
;; limit point.
(setq lim (point))
)
;; If there is a previous library unit, and we are enclosed by
;; it, then set the syntax accordingly.
(and placeholder
(setq library-unit (vhdl-get-library-unit lim placeholder))
(vhdl-add-syntax library-unit lim))
;; Find the surrounding state.
(if (setq vec (vhdl-get-block-state lim))
(progn
(setq containing-sexp (aref vec 0))
(setq preceding-sexp (aref vec 1))
(setq containing-begin (aref vec 2))
(setq containing-mid (aref vec 3))
))
;; set the limit on the farthest back we need to search
(setq lim (if containing-sexp
(save-excursion
(goto-char containing-sexp)
;; set containing-leader if required
(if (looking-at vhdl-leader-re)
(setq containing-leader (vhdl-end-of-leader)))
(vhdl-point 'bol))
(point-min)))
;; cache char before and after indent point, and move point to
;; the most likely position to perform the majority of tests
(goto-char indent-point)
(skip-chars-forward " \t")
(setq literal (vhdl-in-literal))
(setq char-after-ip (following-char))
(setq begin-after-ip (and
(not literal)
(looking-at vhdl-begin-fwd-re)
(or (not (looking-at "\\<use\\>"))
(save-excursion
(back-to-indentation)
(looking-at "\\(\\w+\\s-*:\\s-*\\)?\\<\\(case\\|elsif\\|if\\)\\>")))
(vhdl-begin-p)))
(setq end-after-ip (and
(not literal)
(looking-at vhdl-end-fwd-re)
(vhdl-end-p)))
(vhdl-backward-syntactic-ws lim)
(setq char-before-ip (preceding-char))
(goto-char indent-point)
(skip-chars-forward " \t")
;; now figure out syntactic qualities of the current line
(cond
;; CASE 1: in a string or comment.
((memq literal '(string comment))
(vhdl-add-syntax literal (vhdl-point 'bopl)))
;; CASE 2: Line is at top level.
((null containing-sexp)
;; Find the point to which indentation will be relative
(save-excursion
(if (null preceding-sexp)
;; CASE 2X.1
;; no preceding-sexp -> use the preceding statement
(vhdl-beginning-of-statement-1 lim)
;; CASE 2X.2
;; if there is a preceding-sexp then indent relative to it
(goto-char preceding-sexp)
;; if not at boi, then the block-opening keyword is
;; probably following a label, so we need a different
;; relpos
(if (/= (point) (vhdl-point 'boi))
;; CASE 2X.3
(vhdl-beginning-of-statement-1 lim)))
;; v-b-o-s could have left us at point-min
(and (bobp)
;; CASE 2X.4
(vhdl-forward-syntactic-ws indent-point))
(setq placeholder (point)))
(cond
;; CASE 2A : we are looking at a block-open
(begin-after-ip
(vhdl-add-syntax 'block-open placeholder))
;; CASE 2B: we are looking at a block-close
(end-after-ip
(vhdl-add-syntax 'block-close placeholder))
;; CASE 2C: we are looking at a top-level statement
((progn
(vhdl-backward-syntactic-ws lim)
(or (bobp)
(and (= (preceding-char) ?\;)
(not (vhdl-in-quote-p)))))
(vhdl-add-syntax 'statement placeholder))
;; CASE 2D: we are looking at a top-level statement-cont
(t
(vhdl-beginning-of-statement-1 lim)
;; v-b-o-s could have left us at point-min
(and (bobp)
;; CASE 2D.1
(vhdl-forward-syntactic-ws indent-point))
(vhdl-add-syntax 'statement-cont (point)))
)) ; end CASE 2
;; CASE 3: line is inside parentheses. Most likely we are
;; either in a subprogram argument (interface) list, or a
;; continued expression containing parentheses.
((null containing-begin)
(vhdl-backward-syntactic-ws containing-sexp)
(cond
;; CASE 3A: we are looking at the arglist closing paren
((eq char-after-ip ?\))
(goto-char containing-sexp)
(vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
;; CASE 3B: we are looking at the first argument in an empty
;; argument list.
((eq char-before-ip ?\()
(goto-char containing-sexp)
(vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
;; CASE 3C: we are looking at an arglist continuation line,
;; but the preceding argument is on the same line as the
;; opening paren. This case includes multi-line
;; expression paren groupings.
((and (save-excursion
(goto-char (1+ containing-sexp))
(skip-chars-forward " \t")
(not (eolp))
(not (looking-at "--\\|`")))
(save-excursion
(vhdl-beginning-of-statement-1 containing-sexp)
(skip-chars-backward " \t(")
(while (and (= (preceding-char) ?\;)
(not (vhdl-in-quote-p)))
(vhdl-beginning-of-statement-1 containing-sexp)
(skip-chars-backward " \t("))
(<= (point) containing-sexp)))
(goto-char containing-sexp)
(vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
;; CASE 3D: we are looking at just a normal arglist
;; continuation line
(t (vhdl-beginning-of-statement-1 containing-sexp)
(vhdl-forward-syntactic-ws indent-point)
(vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
))
;; CASE 4: A block mid open
((and begin-after-ip
(looking-at containing-mid))
(goto-char containing-sexp)
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
(if (looking-at vhdl-trailer-re)
;; CASE 4.1
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
(vhdl-backward-skip-label (vhdl-point 'boi))
(vhdl-add-syntax 'block-open (point)))
;; CASE 5: block close brace
(end-after-ip
(goto-char containing-sexp)
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
(if (looking-at vhdl-trailer-re)
;; CASE 5.1
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
(vhdl-backward-skip-label (vhdl-point 'boi))
(vhdl-add-syntax 'block-close (point)))
;; CASE 6: A continued statement
((and (/= char-before-ip ?\;)
;; check it's not a trailer begin keyword, or a begin
;; keyword immediately following a label.
(not (and begin-after-ip
(or (looking-at vhdl-trailer-re)
(save-excursion
(vhdl-backward-skip-label containing-sexp)))))
;; check it's not a statement keyword
(not (and (looking-at vhdl-statement-fwd-re)
(vhdl-statement-p)))
;; see if the b-o-s is before the indent point
(> indent-point
(save-excursion
(vhdl-beginning-of-statement-1 containing-sexp)
;; If we ended up after a leader, then this will
;; move us forward to the start of the first
;; statement. Note that a containing sexp here is
;; always a keyword, not a paren, so this will
;; have no effect if we hit the containing-sexp.
(vhdl-forward-syntactic-ws indent-point)
(setq placeholder (point))))
;; check it's not a block-intro
(/= placeholder containing-sexp)
;; check it's not a case block-intro
(save-excursion
(goto-char placeholder)
(or (not (looking-at vhdl-case-alternative-re))
(> (match-end 0) indent-point))))
;; Make placeholder skip a label, but only if it puts us
;; before the indent point at the start of a line.
(let ((new placeholder))
(if (and (> indent-point
(save-excursion
(goto-char placeholder)
(vhdl-forward-skip-label indent-point)
(setq new (point))))
(save-excursion
(goto-char new)
(eq new (progn (back-to-indentation) (point)))))
(setq placeholder new)))
(vhdl-add-syntax 'statement-cont placeholder)
(if begin-after-ip
(vhdl-add-syntax 'block-open)))
;; Statement. But what kind?
;; CASE 7: A case alternative key
((and (looking-at vhdl-case-alternative-re)
(vhdl-case-alternative-p containing-sexp))
;; for a case alternative key, we set relpos to the first
;; non-whitespace char on the line containing the "case"
;; keyword.
(goto-char containing-sexp)
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
(if (looking-at vhdl-trailer-re)
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
(vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
;; CASE 8: statement catchall
(t
;; we know its a statement, but we need to find out if it is
;; the first statement in a block
(if containing-leader
(goto-char containing-leader)
(goto-char containing-sexp)
;; Note that a containing sexp here is always a keyword,
;; not a paren, so skip over the keyword.
(forward-sexp))
;; move to the start of the first statement
(vhdl-forward-syntactic-ws indent-point)
(setq placeholder (point))
;; we want to ignore case alternatives keys when skipping forward
(let (incase-p)
(while (looking-at vhdl-case-alternative-re)
(setq incase-p (point))
;; we also want to skip over the body of the
;; case/when statement if that doesn't put us at
;; after the indent-point
(while (vhdl-skip-case-alternative indent-point))
;; set up the match end
(looking-at vhdl-case-alternative-re)
(goto-char (match-end 0))
;; move to the start of the first case alternative statement
(vhdl-forward-syntactic-ws indent-point)
(setq placeholder (point)))
(cond
;; CASE 8A: we saw a case/when statement so we must be
;; in a switch statement. find out if we are at the
;; statement just after a case alternative key
((and incase-p
(= (point) indent-point))
;; relpos is the "when" keyword
(vhdl-add-syntax 'statement-case-intro incase-p))
;; CASE 8B: any old statement
((< (point) indent-point)
;; relpos is the first statement of the block
(vhdl-add-syntax 'statement placeholder)
(if begin-after-ip
(vhdl-add-syntax 'block-open)))
;; CASE 8C: first statement in a block
(t
(goto-char containing-sexp)
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
(if (looking-at vhdl-trailer-re)
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
(vhdl-backward-skip-label (vhdl-point 'boi))
(vhdl-add-syntax 'statement-block-intro (point))
(if begin-after-ip
(vhdl-add-syntax 'block-open)))
)))
)
;; now we need to look at any modifiers
(goto-char indent-point)
(skip-chars-forward " \t")
(if (or (looking-at "--") (looking-at "/\\*"))
(vhdl-add-syntax 'comment))
(if (looking-at "`")
(vhdl-add-syntax 'directive))
(if (eq literal 'pound)
(vhdl-add-syntax 'cpp-macro))
;; return the syntax
vhdl-syntactic-context))))