Mercurial > emacs
diff lisp/progmodes/cc-engine.el @ 26817:03befb219d03
Installed version 5.26
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Sun, 12 Dec 1999 18:24:19 +0000 |
parents | 1dc57e616e8d |
children | 68e734ab7d5d |
line wrap: on
line diff
--- a/lisp/progmodes/cc-engine.el Sun Dec 12 16:13:50 1999 +0000 +++ b/lisp/progmodes/cc-engine.el Sun Dec 12 18:24:19 1999 +0000 @@ -1,8 +1,8 @@ ;;; cc-engine.el --- core syntax guessing engine for CC mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-1999 Free Software Foundation, Inc. -;; Authors: 1998 Barry A. Warsaw and Martin Stjernholm +;; Authors: 1998-1999 Barry A. Warsaw and Martin Stjernholm ;; 1992-1997 Barry A. Warsaw ;; 1987 Dave Detlefs and Stewart Clamen ;; 1985 Richard M. Stallman @@ -28,10 +28,17 @@ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-current-file) + (stringp byte-compile-current-file)) + (cons (file-name-directory byte-compile-current-file) + load-path) + load-path))) + (load "cc-defs" nil t))) +(require 'cc-langs) + -(eval-when-compile - (require 'cc-defs)) - ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A ;; better way should be implemented, but this will at least shut up @@ -98,7 +105,7 @@ ;; CASE 2: some other kind of literal? ((c-in-literal lim)) ;; CASE 3: are we looking at a conditional keyword? - ((or (looking-at c-conditional-key) + ((or (and c-conditional-key (looking-at c-conditional-key)) (and (eq (char-after) ?\() (save-excursion (c-forward-sexp 1) @@ -112,6 +119,7 @@ (<= lim (point)) (not (c-in-literal lim)) (not (eq (char-before) ?_)) + c-conditional-key (looking-at c-conditional-key) )))) ;; did we find a conditional? @@ -144,8 +152,10 @@ (setq substmt-p nil)) (setq last-begin (point) donep substmt-p)) - ;; CASE 4: are we looking at a label? - ((looking-at c-label-key)) + ;; CASE 4: are we looking at a label? (But we handle + ;; switch labels later.) + ((and (looking-at c-label-key) + (not (looking-at "default\\>")))) ;; CASE 5: is this the first time we're checking? (firstp (setq firstp nil substmt-p (not (c-crosses-statement-barrier-p @@ -170,7 +180,7 @@ ;; `case' or `default' is first thing on line (let ((here (point))) (beginning-of-line) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws here) (if (looking-at c-switch-label-key) t (goto-char here) @@ -187,7 +197,7 @@ ;; We always want to skip over the non-whitespace modifier ;; characters that can start a statement. (let ((lim (point))) - (skip-chars-backward "-+!*&~@ \t\n" (c-point 'boi)) + (skip-chars-backward "-+!*&~@` \t\n" (c-point 'boi)) (skip-chars-forward " \t\n" lim)))) (defun c-end-of-statement-1 () @@ -254,7 +264,7 @@ (hugenum (point-max))) (while (/= here (point)) (setq here (point)) - (forward-comment hugenum) + (c-forward-comment hugenum) ;; skip preprocessor directives (when (and (eq (char-after) ?#) (= (c-point 'boi) (point))) @@ -264,28 +274,13 @@ ) (if lim (goto-char (min (point) lim))))) -(defsubst c-beginning-of-macro (&optional lim) - ;; Go to the beginning of a cpp macro definition. Leaves point at - ;; the beginning of the macro and returns t if in a cpp macro - ;; definition, otherwise returns nil and leaves point unchanged. - ;; `lim' is currently ignored, but the interface requires it. - (let ((here (point))) - (beginning-of-line) - (while (eq (char-before (1- (point))) ?\\) - (forward-line -1)) - (back-to-indentation) - (if (eq (char-after) ?#) - t - (goto-char here) - nil))) - (defun c-backward-syntactic-ws (&optional lim) ;; Backward skip over syntactic whitespace for Emacs 19. (let* ((here (point-min)) (hugenum (- (point-max)))) (while (/= here (point)) (setq here (point)) - (forward-comment hugenum) + (c-forward-comment hugenum) (c-beginning-of-macro)) (if lim (goto-char (max (point) lim))))) @@ -428,16 +423,18 @@ (if (fboundp 'buffer-syntactic-context) (defalias 'c-in-literal 'c-fast-in-literal)) -(defun c-literal-limits (&optional lim near) +(defun c-literal-limits (&optional lim near not-in-delimiter) ;; Returns a cons of the beginning and end positions of the comment ;; or string surrounding point (including both delimiters), or nil ;; if point isn't in one. If LIM is non-nil, it's used as the ;; "safe" position to start parsing from. If NEAR is non-nil, then ;; the limits of any literal next to point is returned. "Next to" ;; means there's only [ \t] between point and the literal. The - ;; search for such a literal is done first in forward direction. - ;; - ;; This is the Emacs 19 version. + ;; search for such a literal is done first in forward direction. If + ;; NOT-IN-DELIMITER is non-nil, the case when point is inside a + ;; starting delimiter won't be recognized. This only has effect for + ;; comments, which have starting delimiters with more than one + ;; character. (save-excursion (let* ((pos (point)) (lim (or lim (c-point 'bod))) @@ -460,18 +457,20 @@ lim (point) nil nil state) lim (point))) (backward-char 2) - (cons (point) (progn (forward-comment 1) (point)))) + (cons (point) (progn (c-forward-comment 1) (point)))) ((nth 4 state) ;; Block comment. Search backward for the comment starter. (while (nth 4 state) (search-backward "/*") ; Should never fail. (setq state (parse-partial-sexp lim (point)))) - (cons (point) (progn (forward-comment 1) (point)))) - ((c-safe (nth 4 (parse-partial-sexp ; Can't use prev state due - lim (1+ (point))))) ; to bug in Emacs 19.34. + (cons (point) (progn (c-forward-comment 1) (point)))) + ((and (not not-in-delimiter) + (not (nth 5 state)) + (eq (char-before) ?/) + (looking-at "[/*]")) ;; We're standing in a comment starter. - (backward-char 2) - (cons (point) (progn (forward-comment 1) (point)))) + (backward-char 1) + (cons (point) (progn (c-forward-comment 1) (point)))) (near (goto-char pos) ;; Search forward for a literal. @@ -481,7 +480,7 @@ (cons (point) (or (c-safe (c-forward-sexp 1) (point)) (point-max)))) ((looking-at "/[/*]") ; Line or block comment. - (cons (point) (progn (forward-comment 1) (point)))) + (cons (point) (progn (c-forward-comment 1) (point)))) (t ;; Search backward. (skip-chars-backward " \t") @@ -495,32 +494,65 @@ ;; comments, they will always be covered by the ;; normal case above. (goto-char end) - (forward-comment -1) + (c-forward-comment -1) ;; If LIM is bogus, beg will be bogus. (setq beg (point)))) (if beg (cons beg end)))))) )))) -(defun c-literal-limits-fast (&optional lim) +(defun c-literal-limits-fast (&optional lim near not-in-delimiter) ;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp' - ;; returns the pos of the comment start. FIXME: Add NEAR. + ;; returns the pos of the comment start. (save-excursion - (let ((state (parse-partial-sexp lim (point)))) + (let* ((pos (point)) + (lim (or lim (c-point 'bod))) + (state (parse-partial-sexp lim (point)))) (cond ((nth 3 state) ; String. (goto-char (nth 8 state)) (cons (point) (or (c-safe (c-forward-sexp 1) (point)) (point-max)))) ((nth 4 state) ; Comment. (goto-char (nth 8 state)) - (cons (point) (progn (forward-comment 1) (point)))) - ((c-safe - (nth 4 (parse-partial-sexp ; Works? - (point) (1+ (point)) nil nil state))) - ;; We're in a comment starter. - (backward-char 2) - (cons (point) (progn (forward-comment 1) (point)))) + (cons (point) (progn (c-forward-comment 1) (point)))) + ((and (not not-in-delimiter) + (not (nth 5 state)) + (eq (char-before) ?/) + (looking-at "[/*]")) + ;; We're standing in a comment starter. + (backward-char 1) + (cons (point) (progn (c-forward-comment 1) (point)))) + (near + (goto-char pos) + ;; Search forward for a literal. + (skip-chars-forward " \t") + (cond + ((eq (char-syntax (or (char-after) ?\ )) ?\") ; String. + (cons (point) (or (c-safe (c-forward-sexp 1) (point)) + (point-max)))) + ((looking-at "/[/*]") ; Line or block comment. + (cons (point) (progn (c-forward-comment 1) (point)))) + (t + ;; Search backward. + (skip-chars-backward " \t") + (let ((end (point)) beg) + (cond + ((eq (char-syntax (or (char-before) ?\ )) ?\") ; String. + (setq beg (c-safe (c-backward-sexp 1) (point)))) + ((and (c-safe (forward-char -2) t) + (looking-at "*/")) + ;; Block comment. Due to the nature of line + ;; comments, they will always be covered by the + ;; normal case above. + (goto-char end) + (c-forward-comment -1) + ;; If LIM is bogus, beg will be bogus. + (setq beg (point)))) + (if beg (cons beg end)))))) )))) +(if (c-safe (> (length (save-excursion (parse-partial-sexp 1 1))) 8)) + (defalias 'c-literal-limits 'c-literal-limits-fast)) + (defun c-collect-line-comments (range) ;; If the argument is a cons of two buffer positions (such as ;; returned by c-literal-limits), and that range contains a C++ @@ -536,18 +568,16 @@ (let ((col (current-column)) (beg (point)) (end (cdr range))) - (while (and (not (bobp)) - (forward-comment -1) + (while (and (c-forward-comment -1) (looking-at "//") (= col (current-column))) (setq beg (point))) (goto-char end) - (while (progn - (skip-chars-forward " \t") - (and (looking-at "//") - (= col (current-column)))) - (forward-comment 1) - (setq end (point))) + (while (and (progn (skip-chars-forward " \t") + (looking-at "//")) + (= col (current-column)) + (prog1 (zerop (forward-line 1)) + (setq end (point))))) (cons beg end)) range) (error range)))) @@ -558,11 +588,11 @@ ;; It's much faster than using c-in-literal and is intended to be ;; used when you need both the type of a literal and its limits. (if (consp range) - (save-excursion - (goto-char (car range)) - (cond ((eq (char-syntax (or (char-after) ?\ )) ?\") 'string) - ((looking-at "//") 'c++) - (t 'c))) ; Assuming the range is valid. + (save-excursion + (goto-char (car range)) + (cond ((eq (char-syntax (or (char-after) ?\ )) ?\") 'string) + ((looking-at "//") 'c++) + (t 'c))) ; Assuming the range is valid. range)) @@ -1230,28 +1260,32 @@ ;; backward search. (save-excursion (or lim (setq lim (point-min))) - (if (and (eq (char-after) ?{) - (progn (c-backward-syntactic-ws) (> (point) lim)) - (eq (char-before) ?\() - (not (and c-special-brace-lists - (c-looking-at-special-brace-list)))) - (cons 'inexpr-statement (point)) - (let (res) - (while (and (not res) - (= (c-backward-token-1 1 t lim) 0) - (>= (point) lim) - (looking-at "(\\|\\w\\|\\s_\\|\\.")) - (setq res - (cond ((and c-inexpr-class-key - (looking-at c-inexpr-class-key)) - (cons 'inexpr-class (point))) - ((and c-inexpr-block-key - (looking-at c-inexpr-block-key)) - (cons 'inexpr-statement (point))) - ((and c-lambda-key - (looking-at c-lambda-key)) - (cons 'inlambda (point)))))) - res)))) + (let ((block-follows (eq (char-after) ?{))) + ;; Look at the character after point only as a last resort when + ;; we can't disambiguate. + (if (and block-follows + (progn (c-backward-syntactic-ws) (> (point) lim)) + (eq (char-before) ?\() + (not (and c-special-brace-lists + (c-looking-at-special-brace-list)))) + (cons 'inexpr-statement (point)) + (let (res) + (while (and (not res) + (= (c-backward-token-1 1 t lim) 0) + (>= (point) lim) + (looking-at "(\\|\\w\\|\\s_\\|\\.")) + (setq res + (cond ((and block-follows + c-inexpr-class-key + (looking-at c-inexpr-class-key)) + (cons 'inexpr-class (point))) + ((and c-inexpr-block-key + (looking-at c-inexpr-block-key)) + (cons 'inexpr-statement (point))) + ((and c-lambda-key + (looking-at c-lambda-key)) + (cons 'inlambda (point)))))) + res))))) (defun c-looking-at-inexpr-block-backward (&optional lim) ;; Returns non-nil if we're looking at the end of an in-expression @@ -1323,19 +1357,6 @@ ;; return the class vector inclass-p)) -(defsubst c-add-class-syntax (symbol classkey) - ;; The inclass and class-close syntactic symbols are added in - ;; several places and some work is needed to fix everything. - ;; Therefore it's collected here. - (save-restriction - (widen) - (goto-char (aref classkey 1)) - (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) - (c-add-syntax symbol (point)) - (c-add-syntax symbol (aref classkey 0)) - (if (and c-inexpr-class-key (c-looking-at-inexpr-block)) - (c-add-syntax 'inexpr-class))))) - ;; This function implements the main decision tree for determining the ;; syntactic analysis of the current line of code. Yes, it's huge and @@ -1425,10 +1446,7 @@ (c-add-syntax 'string (c-point 'bopl))) ;; CASE 2: in a C or C++ style comment. ((memq literal '(c c++)) - ;; we need to catch multi-paragraph C comments - (while (and (zerop (forward-line -1)) - (looking-at "^[ \t]*$"))) - (c-add-syntax literal (c-point 'boi))) + (c-add-syntax literal (car (c-literal-limits lim)))) ;; CASE 3: in a cpp preprocessor macro ((eq literal 'pound) (let ((boi (c-point 'boi)) @@ -1638,9 +1656,16 @@ ;; don't add inclass symbol since relative point already ;; contains any class offset ))) - ;; CASE 5D: this could be a top-level compound statement or a - ;; member init list continuation - ((eq char-before-ip ?,) + ;; CASE 5D: this could be a top-level compound statement, a + ;; member init list continuation, or a template argument + ;; list continuation. + ((c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (save-excursion + (while (and (= (c-backward-token-1 1 t lim) 0) + (not (looking-at "[;{<,]")))) + (eq (char-after) ?,))) (goto-char indent-point) (c-backward-syntactic-ws lim) (while (and (< lim (point)) @@ -1659,7 +1684,6 @@ ;; for bogus matches on access specifiers inside classes. ((and (save-excursion ;; There might be member inits on the first line too. - (end-of-line) (while (and (> (point) lim) (eq (char-before) ?,) (= (c-backward-token-1 2 t lim) 0) @@ -1667,15 +1691,16 @@ (= (c-backward-token-1 1 t lim) 0)) (c-backward-syntactic-ws lim)) (setq placeholder (point)) - (c-backward-syntactic-ws lim) - (eq (char-before) ?:)) + (c-backward-token-1 1 t lim) + (and (eq (char-after) ?:) + (not (eq (char-before) ?:)))) (save-excursion (goto-char placeholder) (back-to-indentation) (and - c-access-key - (not (looking-at c-access-key)) - (not (looking-at c-class-key))) + (if c-access-key (not (looking-at c-access-key)) t) + (not (looking-at c-class-key)) + (if c-bitfield-key (not (looking-at c-bitfield-key)) t)) )) (goto-char placeholder) (c-forward-syntactic-ws) @@ -1708,7 +1733,7 @@ ;; we can probably indent it just like an arglist-cont (goto-char placeholder) (c-beginning-of-statement-1 lim) - (c-add-syntax 'template-args-cont (point))) + (c-add-syntax 'template-args-cont (c-point 'boi))) ;; CASE 5D.5: perhaps a top-level statement-cont (t (c-beginning-of-statement-1 lim) @@ -1821,7 +1846,13 @@ (beginning-of-line) (looking-at c-method-key))) (c-add-syntax 'objc-method-args-cont (point))) - ;; CASE 5K: we are at a topmost continuation line + ;; CASE 5K: we are at the first argument of a template + ;; arglist that begins on the previous line. + ((eq (char-before) ?<) + (c-beginning-of-statement-1 lim) + (c-forward-syntactic-ws) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5L: we are at a topmost continuation line (t (c-beginning-of-statement-1 lim) (c-forward-syntactic-ws) @@ -1839,12 +1870,9 @@ ;; It's a Pike lambda. Check whether we are between the ;; lambda keyword and the argument list or at the defun ;; opener. - (setq tmpsymbol - (if (save-excursion - (and (c-safe (c-forward-sexp -1) t) - (looking-at c-lambda-key))) - 'lambda-intro-cont - 'inline-open))) + (setq tmpsymbol (if (eq char-after-ip ?{) + 'inline-open + 'lambda-intro-cont))) (goto-char (cdr placeholder)) (c-add-syntax tmpsymbol (c-point 'boi)) (c-add-syntax (car placeholder))) @@ -1859,7 +1887,10 @@ (c-backward-syntactic-ws containing-sexp) (cond ;; CASE 7A: we are looking at the arglist closing paren - ((and (not (eq char-before-ip ?,)) + ((and (or (c-major-mode-is 'pike-mode) + ;; Don't check this in Pike since it allows a + ;; comma after the last arg. + (not (eq char-before-ip ?,))) (memq char-after-ip '(?\) ?\]))) (goto-char containing-sexp) (c-add-syntax 'arglist-close (c-point 'boi))) @@ -1961,10 +1992,13 @@ ((and (consp special-brace-list) (eq char-after-ip (car (cdr special-brace-list)))) (goto-char (car (car special-brace-list))) - (c-beginning-of-statement-1 lim) - (c-forward-token-1 0) - (if (looking-at "typedef\\>") (c-forward-token-1 1)) - (c-add-syntax 'brace-list-open (c-point 'boi))) + (skip-chars-backward " \t") + (if (bolp) + (setq syntax (c-guess-basic-syntax)) + (c-beginning-of-statement-1 lim) + (c-forward-token-1 0) + (if (looking-at "typedef\\>") (c-forward-token-1 1)) + (c-add-syntax 'brace-list-open (c-point 'boi)))) ;; CASE 9B: brace-list-close brace ((if (consp special-brace-list) ;; Check special brace list closer. @@ -2034,7 +2068,7 @@ (let ((after-cond-placeholder (save-excursion (goto-char placeholder) - (if (looking-at c-conditional-key) + (if (and c-conditional-key (looking-at c-conditional-key)) (progn (c-safe (c-skip-conditional)) (c-forward-syntactic-ws) @@ -2078,7 +2112,14 @@ (= (c-backward-token-1 1 t) 0) (/= (char-after) ?=))) (eq (char-after) ?=))) - (c-add-syntax 'brace-list-open placeholder)) + ;; The most semantically accurate symbol here is + ;; brace-list-open, but we report it simply as a + ;; statement-cont. The reason is that one normally + ;; adjusts brace-list-open for brace lists as + ;; top-level constructs, and brace lists inside + ;; statements is a completely different context. + (goto-char placeholder) + (c-add-syntax 'statement-cont (c-point 'boi))) ;; CASE 10B.3: catch-all for unknown construct. (t ;; Can and should I add an extensibility hook here? @@ -2131,7 +2172,8 @@ (setq placeholder (point)) (looking-at "do\\b[^_]")) )) - (c-add-syntax 'do-while-closure placeholder)) + (goto-char placeholder) + (c-add-syntax 'do-while-closure (c-point 'boi))) ;; CASE 13: A catch or finally clause? This case is simpler ;; than if-else and do-while, because a block is required ;; after every try, catch and finally. @@ -2405,6 +2447,17 @@ )) (c-keep-region-active)) +(defun c-syntactic-information-on-region (from to) + "Inserts a comment with the syntactic analysis on every line in the region." + (interactive "*r") + (save-excursion + (save-restriction + (narrow-to-region from to) + (goto-char (point-min)) + (while (not (eobp)) + (c-show-syntactic-information '(0)) + (forward-line))))) + (provide 'cc-engine) ;;; cc-engine.el ends here