emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/d-mode bdd5d78 281/346: Replace d-forward-decl-or-cast-1 i


From: ELPA Syncer
Subject: [nongnu] elpa/d-mode bdd5d78 281/346: Replace d-forward-decl-or-cast-1 implementation with a custom one
Date: Sun, 29 Aug 2021 11:00:46 -0400 (EDT)

branch: elpa/d-mode
commit bdd5d78d6bfe84cdfd087fc77b12f740314d09eb
Author: Vladimir Panteleev <git@thecybershadow.net>
Commit: Vladimir Panteleev <git@thecybershadow.net>

    Replace d-forward-decl-or-cast-1 implementation with a custom one
    
    Throw away the cc-mode infernal contraption and replace it with an
    implementation describing the relevant D syntax, and nothing more.
---
 d-mode.el          | 1294 +++++++++-------------------------------------------
 tests/I0095.d.html |    2 +-
 tests/fonts.d      |    3 +
 tests/fonts.d.html |    3 +
 4 files changed, 230 insertions(+), 1072 deletions(-)

diff --git a/d-mode.el b/d-mode.el
index d93e884..115d090 100644
--- a/d-mode.el
+++ b/d-mode.el
@@ -7,7 +7,7 @@
 ;; Maintainer:  Russel Winder <russel@winder.org.uk>
 ;;              Vladimir Panteleev <vladimir@thecybershadow.net>
 ;; Created:  March 2007
-;; Version:  201911081553
+;; Version:  201911082245
 ;; Keywords:  D programming language emacs cc-mode
 ;; Package-Requires: ((emacs "25.1"))
 
@@ -139,6 +139,9 @@
   d "[[:alpha:]_@~]")
   ;; d "[[:alpha:]_@]")
 
+(c-lang-defconst d-decl-end-re
+  d "[,;=(]")
+
 ;; D has fixed arrays
 (c-lang-defconst c-opt-type-suffix-key
   d "\\(\\[[^]]*\\]\\|\\.\\.\\.\\|\\*\\)")
@@ -208,14 +211,20 @@ operators."
   d '("bool" "byte" "ubyte" "char" "delegate" "double" "float"
       "function" "int" "long" "short" "uint" "ulong" "ushort"
       "cent" "ucent" "real" "ireal" "idouble" "ifloat" "creal" "cfloat" 
"cdouble"
-      "wchar" "dchar" "void" "string" "wstring" "dstring"))
-
-;; Keywords that can prefix normal declarations of identifiers
+      "wchar" "dchar" "void" "string" "wstring" "dstring" "__vector"))
+
+;; Keywords that can prefix normal declarations of identifiers.
+;; Union of StorageClass, Attribute, and ParameterAttributes in D grammar.
+;; References:
+;; - https://dlang.org/spec/grammar.html#Attribute
+;; - https://dlang.org/spec/declaration.html#StorageClass
+;; - https://dlang.org/spec/grammar.html#ParameterAttributes
 (c-lang-defconst c-modifier-kwds
-  d '("abstract" "deprecated" "extern"
-      "final" "out" "lazy" "mixin" "override" "private"
-      "protected" "package" "public" "ref" "scope" "static" "synchronized"
-      "volatile" "__vector"))
+  d '("__gshared" "abstract" "align" "auto" "const" "deprecated"
+      "enum" "export" "extern" "final" "immutable" "in" "inout" "lazy"
+      "nothrow" "out" "override" "package" "pragma" "private"
+      "protected" "public" "pure" "ref" "return" "scope" "shared"
+      "static" "synchronized"))
 
 (c-lang-defconst c-class-decl-kwds
   ;; Keywords introducing declarations where the following block (if any)
@@ -392,7 +401,7 @@ operators."
   d (c-lang-const d-storage-class-kwds))
 
 (c-lang-defconst c-decl-start-kwds
-  d '("else"))
+  d '("debug" "else"))
 
 (c-lang-defconst c-other-kwds
   ;; Keywords not accounted for by any other `*-kwds' language constant.
@@ -449,1087 +458,223 @@ operators."
 (advice-add 'c-add-stmt-syntax :around #'d-around--c-add-stmt-syntax)
 
 ;;----------------------------------------------------------------------------
-;;; Implements handling of D constructors
-;;; Fixes e.g. indentation of contracts on constructors.
-
-;; Make it so that inside c-forward-decl-or-cast-1,
-;; "this" looks like a function identifier but not a type identifier.
-
-(defun d-forward-name ()
-  "Wraps `c-forward-name' for d-mode.
-
-Fixes cc-mode handling of D constructors."
-  (if (not (looking-at (d-make-keywords-re t '("this" "~this"))))
-      (c-forward-name)
-    (goto-char (match-end 1))
-    t))
-
-;;----------------------------------------------------------------------------
 
 (defun d-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
-  "Modified version of `c-forward-decl-or-cast-1' for d-mode." ;; 
checkdoc-params: (preceding-token-end context last-cast-end)
-  ;; Move forward over a declaration or a cast if at the start of one.
-  ;; The point is assumed to be at the start of some token.  Nil is
-  ;; returned if no declaration or cast is recognized, and the point
-  ;; is clobbered in that case.
-  ;;
-  ;; If a declaration is parsed:
-  ;;
-  ;;   The point is left at the first token after the first complete
-  ;;   declarator, if there is one.  The return value is a list of 5 elements,
-  ;;   where the first is the position of the first token in the declarator.
-  ;;   (See below for the other four.)
-  ;;   Some examples:
-  ;;
-  ;;    void foo (int a, char *b) stuff ...
-  ;;     car ^                    ^ point
-  ;;    float (*a)[], b;
-  ;;      car ^     ^ point
-  ;;    unsigned int a = c_style_initializer, b;
-  ;;             car ^ ^ point
-  ;;    unsigned int a (cplusplus_style_initializer), b;
-  ;;             car ^                              ^ point (might change)
-  ;;    class Foo : public Bar {}
-  ;;      car ^   ^ point
-  ;;    class PikeClass (int a, string b) stuff ...
-  ;;      car ^                           ^ point
-  ;;    enum bool;
-  ;;     car ^   ^ point
-  ;;    enum bool flag;
-  ;;          car ^   ^ point
-  ;;     void cplusplus_function (int x) throw (Bad);
-  ;;      car ^                                     ^ point
-  ;;     Foo::Foo (int b) : Base (b) {}
-  ;; car ^                ^ point
-  ;;
-  ;;     auto foo = 5;
-  ;;      car ^   ^ point
-  ;;     auto cplusplus_11 (int a, char *b) -> decltype (bar):
-  ;;      car ^                             ^ point
-  ;;
-  ;;
-  ;;
-  ;;   The second element of the return value is non-nil when a
-  ;;   `c-typedef-decl-kwds' specifier is found in the declaration.
-  ;;   Specifically it is a dotted pair (A . B) where B is t when a
-  ;;   `c-typedef-kwds' ("typedef") is present, and A is t when some
-  ;;   other `c-typedef-decl-kwds' (e.g. class, struct, enum)
-  ;;   specifier is present.  I.e., (some of) the declared
-  ;;   identifier(s) are types.
-  ;;
-  ;;   The third element of the return value is non-nil when the declaration
-  ;;   parsed might be an expression.  The fourth element is the position of
-  ;;   the start of the type identifier.  The fifth element is t if either
-  ;;   CONTEXT was 'top, or the declaration is detected to be treated as top
-  ;;   level (e.g. with the keyword "extern").
-  ;;
-  ;; If a cast is parsed:
-  ;;
-  ;;   The point is left at the first token after the closing paren of
-  ;;   the cast.  The return value is `cast'.  Note that the start
-  ;;   position must be at the first token inside the cast parenthesis
-  ;;   to recognize it.
-  ;;
-  ;; PRECEDING-TOKEN-END is the first position after the preceding
-  ;; token, i.e. on the other side of the syntactic ws from the point.
-  ;; Use a value less than or equal to (point-min) if the point is at
-  ;; the first token in (the visible part of) the buffer.
-  ;;
-  ;; CONTEXT is a symbol that describes the context at the point:
-  ;; 'decl     In a comma-separated declaration context (typically
-  ;;           inside a function declaration arglist).
-  ;; '<>       In an angle bracket arglist.
-  ;; 'arglist  Some other type of arglist.
-  ;; 'top      Some other context and point is at the top-level (either
-  ;;           outside any braces or directly inside a class or namespace,
-  ;;           etc.)
-  ;; nil       Some other context or unknown context.  Includes
-  ;;           within the parens of an if, for, ... construct.
-  ;; 'not-decl This value is never supplied to this function.  It
-  ;;           would mean we're definitely not in a declaration.
-  ;;
-  ;; LAST-CAST-END is the first token after the closing paren of a
-  ;; preceding cast, or nil if none is known.  If
-  ;; `c-forward-decl-or-cast-1' is used in succession, it should be
-  ;; the position after the closest preceding call where a cast was
-  ;; matched.  In that case it's used to discover chains of casts like
-  ;; "(a) (b) c".
-  ;;
-  ;; This function records identifier ranges on
-  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
-  ;; `c-record-type-identifiers' is non-nil.
-  ;;
-  ;; This function might do hidden buffer changes.
-
-  ;; D: The "else" following a "version" or "static if" can start a
-  ;; declaration even without a { } block. For this reason, "else" is
-  ;; in `c-decl-start-kwds'.
-  ;; However, cc-mode invokes `c-forward-decl-or-cast-1' with point
-  ;; at the "else" keyword, which, when followed by a function call,
-  ;; is mis-parsed as a function declaration.
-  ;; Fix this by moving point forward, past the "else" keyword, to
-  ;; put cc-mode on the right track.
-  (when (looking-at (d-make-keywords-re t '("else")))
+  "D version of `c-forward-decl-or-cast-1'." ;; checkdoc-params: 
(preceding-token-end context last-cast-end)
+
+  ;; D: Handle conditional compilation.
+  ;; The "debug" keyword, as well as the "else" keyword following a
+  ;; "version" or "static if", can start a declaration even without a
+  ;; { } block.
+  ;; For this reason, these keywords are in `c-decl-start-kwds'.
+  ;; However, `c-decl-start-kwds' are considered as part of the
+  ;; declaration, so `c-forward-decl-or-cast-1' will be invoked with
+  ;; point at the keyword.  Handle this case here.
+  ;; Note that other cases (e.g. static if) are handled implicitly by
+  ;; their requirement of a parenthesis (')' is in `c-decl-prefix-re').
+  (while (looking-at (d-make-keywords-re t (c-lang-const c-decl-start-kwds d)))
     (goto-char (match-end 1))
     (c-forward-syntactic-ws))
 
-  ;; D: Work around a cc-mode bug(?) in which the c-forward-annotation
-  ;; calls in c-forward-decl-or-cast-1 do not advance the start
-  ;; position, causing the annotation to be fontified as the function
-  ;; name.
-  (while (c-forward-annotation)
-    (c-forward-syntactic-ws))
-
-  (let (;; `start-pos' is used below to point to the start of the
-       ;; first type, i.e. after any leading specifiers.  It might
-       ;; also point at the beginning of the preceding syntactic
-       ;; whitespace.
-       (start-pos (point))
-       ;; Set to the result of `c-forward-type'.
-       at-type
-       ;; The position of the first token in what we currently
-       ;; believe is the type in the declaration or cast, after any
-       ;; specifiers and their associated clauses.
-       type-start
-       ;; The position of the first token in what we currently
-       ;; believe is the declarator for the first identifier.  Set
-       ;; when the type is found, and moved forward over any
-       ;; `c-decl-hangon-kwds' and their associated clauses that
-       ;; occurs after the type.
-       id-start
-       ;; These store `at-type', `type-start' and `id-start' of the
-       ;; identifier before the one in those variables.  The previous
-       ;; identifier might turn out to be the real type in a
-       ;; declaration if the last one has to be the declarator in it.
-       ;; If `backup-at-type' is nil then the other variables have
-       ;; undefined values.
-       backup-at-type backup-type-start backup-id-start
-       ;; Set if we've found a specifier (apart from "typedef") that makes
-       ;; the defined identifier(s) types.
-       at-type-decl
-       ;; Set if we've a "typedef" keyword.
-       at-typedef
-       ;; Set if we've found a specifier that can start a declaration
-       ;; where there's no type.
-       maybe-typeless
-       ;; Save the value of kwd-sym between loops of the "Check for a
-       ;; type" loop.  Needed to distinguish a C++11 "auto" from a pre
-       ;; C++11 one.
-       prev-kwd-sym
-       ;; If a specifier is found that also can be a type prefix,
-       ;; these flags are set instead of those above.  If we need to
-       ;; back up an identifier, they are copied to the real flag
-       ;; variables.  Thus they only take effect if we fail to
-       ;; interpret it as a type.
-       backup-at-type-decl backup-maybe-typeless
-       ;; Whether we've found a declaration or a cast.  We might know
-       ;; this before we've found the type in it.  It's 'ids if we've
-       ;; found two consecutive identifiers (usually a sure sign, but
-       ;; we should allow that in labels too), and t if we've found a
-       ;; specifier keyword (a 100% sure sign).
-       at-decl-or-cast
-       ;; Set when we need to back up to parse this as a declaration
-       ;; but not as a cast.
-       backup-if-not-cast
-       ;; For casts, the return position.
-       cast-end
-       ;; Have we got a new-style C++11 "auto"?
-       new-style-auto
-       ;; Set when the symbol before `preceding-token-end' is known to
-       ;; terminate the previous construct, or when we're at point-min.
-       at-decl-start
-       ;; Set when we have encountered a keyword (e.g. "extern") which
-       ;; causes the following declaration to be treated as though top-level.
-       make-top
-       ;; Save `c-record-type-identifiers' and
-       ;; `c-record-ref-identifiers' since ranges are recorded
-       ;; speculatively and should be thrown away if it turns out
-       ;; that it isn't a declaration or cast.
-       (save-rec-type-ids c-record-type-identifiers)
-       (save-rec-ref-ids c-record-ref-identifiers)
-       ;; Set when we parse a declaration which might also be an expression,
-       ;; such as "a *b".  See CASE 16 and CASE 17.
-       maybe-expression)
-
-    (save-excursion
-      (goto-char preceding-token-end)
-      (setq at-decl-start
-           (or (bobp)
-               (let ((tok-end (point)))
-                 (c-backward-token-2)
-                 (member (buffer-substring-no-properties (point) tok-end)
-                         c-pre-start-tokens)))))
-
-    ;; Check for a type.  Unknown symbols are treated as possible
-    ;; types, but they could also be specifiers disguised through
-    ;; macros like __INLINE__, so we recognize both types and known
-    ;; specifiers after them too.
-    (while
-       (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
-
-         (cond
-         ;; Look for a specifier keyword clause.
-          ((or (and (looking-at c-make-top-level-key)
-                    (setq make-top t))
-               (looking-at c-prefix-spec-kwds-re)
-               (and (c-major-mode-is 'java-mode)
-                (looking-at "@[A-Za-z0-9]+")))
-           (save-match-data
-             (if (looking-at c-typedef-key)
-                 (setq at-typedef t)))
-           (setq kwd-sym (c-keyword-sym (match-string 1)))
-           (save-excursion
-             (c-forward-keyword-clause 1)
-             (setq kwd-clause-end (point))))
-          ((and c-opt-cpp-prefix
-                (looking-at c-noise-macro-with-parens-name-re))
-           (setq noise-start (point))
-           (c-forward-noise-clause)
-           (setq kwd-clause-end (point))))
-
-         (when (setq found-type (c-forward-type t)) ; brace-block-too
-           ;; Found a known or possible type or a prefix of a known type.
-           (when (and (c-major-mode-is 'c++-mode) ; C++11 style "auto"?
-                      (eq prev-kwd-sym (c-keyword-sym "auto"))
-                      (looking-at "[=(]")) ; FIXME!!! proper regexp.
-             (setq new-style-auto t)
-             (setq found-type nil)
-             (goto-char start))        ; position of foo in "auto foo"
-
-           (when at-type
-             ;; Got two identifiers with nothing but whitespace
-             ;; between them.  That can only happen in declarations.
-             (setq at-decl-or-cast 'ids)
-
-             (when (eq at-type 'found)
-               ;; If the previous identifier is a found type we
-               ;; record it as a real one; it might be some sort of
-               ;; alias for a prefix like "unsigned".
-               (save-excursion
-                 (goto-char type-start)
-                 (let ((c-promote-possible-types t))
-                   (c-forward-type)))))
-
-           (setq backup-at-type at-type
-                 backup-type-start type-start
-                 backup-id-start id-start
-                 at-type found-type
-                 type-start start
-                 id-start (point)
-                 ;; The previous ambiguous specifier/type turned out
-                 ;; to be a type since we've parsed another one after
-                 ;; it, so clear these backup flags.
-                 backup-at-type-decl nil
-                 backup-maybe-typeless nil))
-
-         (if (or kwd-sym noise-start)
-             (progn
-               ;; Handle known specifier keywords and
-               ;; `c-decl-hangon-kwds' which can occur after known
-               ;; types.
-
-               (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
-                       noise-start)
-                   ;; It's a hang-on keyword or noise clause that can occur
-                   ;; anywhere.
-                   (progn
-                     (if at-type
-                         ;; Move the identifier start position if
-                         ;; we've passed a type.
-                         (setq id-start kwd-clause-end)
-                       ;; Otherwise treat this as a specifier and
-                       ;; move the fallback position.
-                       (setq start-pos kwd-clause-end))
-                     (goto-char kwd-clause-end))
-
-                 ;; It's an ordinary specifier so we know that
-                 ;; anything before this can't be the type.
-                 (setq backup-at-type nil
-                       start-pos kwd-clause-end)
-
-                 (if found-type
-                     ;; It's ambiguous whether this keyword is a
-                     ;; specifier or a type prefix, so set the backup
-                     ;; flags.  (It's assumed that `c-forward-type'
-                     ;; moved further than `c-forward-keyword-clause'.)
-                     (progn
-                       (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
-                         (setq backup-at-type-decl t))
-                       (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
-                         (setq backup-maybe-typeless t)))
-
-                   (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
-                     ;; This test only happens after we've scanned a type.
-                     ;; So, with valid syntax, kwd-sym can't be 'typedef.
-                     (setq at-type-decl t))
-                   (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
-                     (setq maybe-typeless t))
-
-                   ;; Haven't matched a type so it's an unambiguous
-                   ;; specifier keyword and we know we're in a
-                   ;; declaration.
-                   (setq at-decl-or-cast t)
-                   (setq prev-kwd-sym kwd-sym)
-
-                   (goto-char kwd-clause-end))))
-
-           ;; If the type isn't known we continue so that we'll jump
-           ;; over all specifiers and type identifiers.  The reason
-           ;; to do this for a known type prefix is to make things
-           ;; like "unsigned INT16" work.
-           (and found-type (not (eq found-type t))))))
+  (let (maybe-auto enum decl-start type-start id-start make-top)
+
+    (let (kind)
+      (while (setq kind (d-forward-attribute-or-storage-class))
+       (setq maybe-auto t
+             enum (eq kind 'enum))
+       ;; Skip over "public:" and similar specifiers.
+       ;; For some reason cc-mode wants us to do it here.
+       (when (looking-at ":")
+         (forward-char)
+         (c-forward-syntactic-ws))))
+
+    (setq decl-start (point))
+
+    ;; Discover what kind of enum declaration this is.
+    ;; (t if this is an actual list of enumerated values)
+    (setq enum
+         (and enum
+              (memq context '(top nil))
+              (save-excursion
+                (and
+                 (d-forward-type)
+                 (or (looking-at "[:{;]")
+                     (and
+                      (d-forward-identifier)
+                      (progn
+                        (c-forward-syntactic-ws)
+                        (looking-at "[:{;]"))))))))
 
-    (cond
-     ((eq at-type t)
-      ;; If a known type was found, we still need to skip over any
-      ;; hangon keyword clauses after it.  Otherwise it has already
-      ;; been done in the loop above.
-      (while
-         (cond ((looking-at c-decl-hangon-key)
-                (c-forward-keyword-clause 1))
-               ((and c-opt-cpp-prefix
-                     (looking-at c-noise-macro-with-parens-name-re))
-                (c-forward-noise-clause))))
-      (setq id-start (point)))
-
-     ((eq at-type 'prefix)
-      ;; A prefix type is itself a primitive type when it's not
-      ;; followed by another type.
-      (setq at-type t))
-
-     ((not at-type)
-      ;; Got no type but set things up to continue anyway to handle
-      ;; the various cases when a declaration doesn't start with a
-      ;; type.
-      (setq id-start start-pos))
-
-     ((and (eq at-type 'maybe)
-          (c-major-mode-is 'c++-mode))
-      ;; If it's C++ then check if the last "type" ends on the form
-      ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a
-      ;; (con|de)structor.
-      (save-excursion
-       (let (name end-2 end-1)
-         (goto-char id-start)
-         (c-backward-syntactic-ws)
-         (setq end-2 (point))
-         (when (and
-                (c-simple-skip-symbol-backward)
-                (progn
-                  (setq name
-                        (buffer-substring-no-properties (point) end-2))
-                  ;; Cheating in the handling of syntactic ws below.
-                  (< (skip-chars-backward ":~ \t\n\r\v\f") 0))
-                (progn
-                  (setq end-1 (point))
-                  (c-simple-skip-symbol-backward))
-                (>= (point) type-start)
-                (equal (buffer-substring-no-properties (point) end-1)
-                       name)
-                (goto-char end-2)
-                (progn
-                  (c-forward-syntactic-ws)
-                  (eq (char-after) ?\()))
-           ;; It is a (con|de)structor name.  In that case the
-           ;; declaration is typeless so zap out any preceding
-           ;; identifier(s) that we might have taken as types.
-           (goto-char type-start)
-           (setq at-type nil
-                 backup-at-type nil
-                 id-start type-start))))))
-
-    ;; Check for and step over a type decl expression after the thing
-    ;; that is or might be a type.  This can't be skipped since we
-    ;; need the correct end position of the declarator for
-    ;; `max-type-decl-end-*'.
-    (let ((start (point)) (paren-depth 0) pos
-         ;; True if there's a non-open-paren match of
-         ;; `c-type-decl-prefix-key'.
-         got-prefix
-         ;; True if the declarator is surrounded by a parenthesis pair.
-         got-parens
-         ;; True if there is an identifier in the declarator.
-         got-identifier
-         ;; True if we find a number where an identifier was expected.
-         got-number
-         ;; True if there's a non-close-paren match of
-         ;; `c-type-decl-suffix-key'.
-         got-suffix
-         ;; True if there's a prefix match outside the outermost
-         ;; paren pair that surrounds the declarator.
-         got-prefix-before-parens
-         ;; True if there's a suffix match outside the outermost
-         ;; paren pair that surrounds the declarator.  The value is
-         ;; the position of the first suffix match.
-         got-suffix-after-parens
-         ;; True if we've parsed the type decl to a token that is
-         ;; known to end declarations in this context.
-         at-decl-end
-         ;; The earlier values of `at-type' and `type-start' if we've
-         ;; shifted the type backwards.
-         identifier-type identifier-start
-         ;; If `c-parse-and-markup-<>-arglists' is set we need to
-         ;; turn it off during the name skipping below to avoid
-         ;; getting `c-type' properties that might be bogus.  That
-         ;; can happen since we don't know if
-         ;; `c-restricted-<>-arglists' will be correct inside the
-         ;; arglist paren that gets entered.
-         c-parse-and-markup-<>-arglists
-         ;; Start of the identifier for which `got-identifier' was set.
-         name-start
-         ;; Position after (innermost) open parenthesis encountered in the
-         ;; prefix operators.
-         after-paren-pos)
-
-      (goto-char id-start)
-
-      ;; Skip over type decl prefix operators.  (Note similar code in
-      ;; `c-forward-declarator'.)
-      (if (and c-recognize-typeless-decls
-              (equal c-type-decl-prefix-key "\\<\\>"))
-         (when (eq (char-after) ?\()
-           (progn
-             (setq paren-depth (1+ paren-depth))
-             (forward-char)
-             (setq after-paren-pos (point))))
-       (while (and (looking-at c-type-decl-prefix-key)
-                   (if (and (c-major-mode-is 'c++-mode)
-                            (match-beginning 3))
-                       ;; If the third submatch matches in C++ then
-                       ;; we're looking at an identifier that's a
-                       ;; prefix only if it specifies a member pointer.
-                       (when (progn (setq pos (point))
-                                    (setq got-identifier (d-forward-name)))
-                         (setq name-start pos)
-                         (if (looking-at "\\(::\\)")
-                             ;; We only check for a trailing "::" and
-                             ;; let the "*" that should follow be
-                             ;; matched in the next round.
-                             (progn (setq got-identifier nil) t)
-                           ;; It turned out to be the real identifier,
-                           ;; so stop.
-                           nil))
-                     t))
-
-         (if (eq (char-after) ?\()
-             (progn
-               (setq paren-depth (1+ paren-depth))
-               (forward-char)
-               (setq after-paren-pos (point)))
-           (unless got-prefix-before-parens
-             (setq got-prefix-before-parens (= paren-depth 0)))
-           (setq got-prefix t)
-           (goto-char (match-end 1)))
-         (c-forward-syntactic-ws)))
+    (when
+       ;; The various kinds of declarations are handled here:
+       (cond
 
-      (setq got-parens (> paren-depth 0))
+        ;; Aggregate declaration (class/struct ...)
+        ;; Handle enumerations here too.
+        ((and (memq context '(top nil))
+              (or enum
+                  (looking-at (d-make-keywords-re t (c-lang-const 
c-class-decl-kwds d)))))
 
-      ;; Try to skip over an identifier.
-      (or got-identifier
-         (and (looking-at c-identifier-start)
-              (setq pos (point))
-              (setq got-identifier (d-forward-name))
-              (setq name-start pos))
-         (when (looking-at "[0-9]")
-           (setq got-number t))) ; We've probably got an arithmetic expression.
+         (unless enum
+           (goto-char (match-end 1))
+           (c-forward-syntactic-ws))
+         (setq type-start (point))
+         (setq id-start type-start)
 
-      ;; Skip over type decl suffix operators and trailing noise macros.
-      (while
-         (cond
-          ((and c-opt-cpp-prefix
-                (looking-at c-noise-macro-with-parens-name-re))
-           (c-forward-noise-clause))
-
-          ((and (looking-at c-type-decl-suffix-key)
-                ;; We avoid recognizing foo(bar) or foo() at top level as a
-                ;; construct here in C, since we want to recognize this as a
-                ;; typeless function declaration.
-                (not (and (c-major-mode-is 'c-mode)
-                          (or (eq context 'top) make-top)
-                          (eq (char-after) ?\)))))
-           (if (eq (char-after) ?\))
-               (when (> paren-depth 0)
-                 (setq paren-depth (1- paren-depth))
-                 (forward-char)
-                 t)
-             (when (if (save-match-data (looking-at "\\s("))
-                       (c-safe (c-forward-sexp 1) t)
-                     (goto-char (match-end 1))
-                     t)
-               (when (and (not got-suffix-after-parens)
-                          (= paren-depth 0))
-                 (setq got-suffix-after-parens (match-beginning 0)))
-               (setq got-suffix t))))
+         (and
+          (d-forward-identifier)
+          (progn
+            (c-forward-syntactic-ws)
+            (looking-at "[:({;]"))))
 
-          (t
-           ;; No suffix matched.  We might have matched the
-           ;; identifier as a type and the open paren of a
-           ;; function arglist as a type decl prefix.  In that
-           ;; case we should "backtrack": Reinterpret the last
-           ;; type as the identifier, move out of the arglist and
-           ;; continue searching for suffix operators.
-           ;;
-           ;; Do this even if there's no preceding type, to cope
-           ;; with old style function declarations in K&R C,
-           ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
-           ;; style declarations.  That isn't applicable in an
-           ;; arglist context, though.
-           (when (and (= paren-depth 1)
-                         (not got-prefix-before-parens)
-                         (not (eq at-type t))
-                         (or backup-at-type
-                             maybe-typeless
-                             backup-maybe-typeless
-                             (when c-recognize-typeless-decls
-                               (and (memq context '(nil top))
-                                    ;; Deal with C++11's "copy-initialization"
-                                    ;; where we have <type>(<constant>), by
-                                    ;; contrasting with a typeless
-                                    ;; <name>(<type><parameter>, ...).
-                                    (save-excursion
-                                      (goto-char after-paren-pos)
-                                      (c-forward-syntactic-ws)
-                                      (or (c-forward-type)
-                                          ;; Recognize a top-level typeless
-                                          ;; function declaration in C.
-                                          (and (c-major-mode-is 'c-mode)
-                                               (or (eq context 'top) make-top)
-                                               (eq (char-after) ?\))))))))
-                         (setq pos (c-up-list-forward (point)))
-                         (eq (char-before pos) ?\)))
-                (c-fdoc-shift-type-backward)
-                (goto-char pos)
-                t)))
+        ;; Mixin templates
+        ((and (memq context '(top nil))
+              (looking-at (d-make-keywords-re t '("mixin"))))
+         (goto-char (match-end 1))
+         (c-forward-syntactic-ws)
+         (and
+          (looking-at (d-make-keywords-re t '("template")))
+          (progn
+            (goto-char (match-end 1))
+            (c-forward-syntactic-ws)
+            (setq type-start (point))
+            (setq id-start type-start)
+            (d-forward-identifier))
+          (progn
+            (c-forward-syntactic-ws)
+            (looking-at "("))))
 
-       (c-forward-syntactic-ws))
+        ;; Constructors/destructors
+        ((and (eq context 'top)
+              (looking-at (d-make-keywords-re t '("this" "~this"))))
+         (setq id-start decl-start)
+         (goto-char (match-end 1))
+         t)
 
-      (when (or (and new-style-auto
-                    (looking-at c-auto-ops-re))
-               (and (or maybe-typeless backup-maybe-typeless)
-                    (not got-identifier)
-                    (not got-prefix)
-                    at-type))
-       ;; Have found no identifier but `c-typeless-decl-kwds' has
-       ;; matched so we know we're inside a declaration.  The
-       ;; preceding type must be the identifier instead.
-       (c-fdoc-shift-type-backward))
-
-      ;; Prepare the "-> type;" for fontification later on.
-      (when (and new-style-auto
-                (looking-at c-haskell-op-re))
-       (save-excursion
-         (goto-char (match-end 0))
+        ;; Alias declarations
+        ((and (memq context '(top nil))
+              (looking-at (d-make-keywords-re t '("alias"))))
+         (setq type-start decl-start)  ; indicate declaration type for e.g. 
imenu
+         (goto-char (match-end 1))
          (c-forward-syntactic-ws)
-         (setq type-start (point))
-         (setq at-type (c-forward-type))))
+         (setq id-start (point))
+         (d-forward-type) ; alias name or value
+         (cond
+          ;; New style (alias name = value)
+          ((memq (char-after) '(?= ?\())
+           t)
+          ;; Old style (alias value name)
+          ((looking-at c-symbol-key)
+           (setq id-start (point))
+           t)))
+
+        ;; Function / variable / constant declaration, i.e. an
+        ;; (optional) type followed by an identifier.
+        ((and (memq context '(top nil))
+              ;; Declaration type, or identifier for auto
+              ;; declarations.  Note that all identifiers
+              ;; are also valid types.
+              (d-forward-type))
+
+         (setq type-start decl-start)
+         (setq id-start (point))
 
-      ;; Move forward over any "WS" ids (like "final" or "override" in C++)
-      (while (looking-at c-type-decl-suffix-ws-ids-key)
-       (goto-char (match-end 1))
-       (c-forward-syntactic-ws))
+         (cond
+          ;; auto-declaration
+          ((and maybe-auto
+                (looking-at (c-lang-const d-decl-end-re)))
+           (setq id-start type-start)
+           (setq type-start nil)
+           t)
+          ;; regular declaration
+          ((and (d-forward-identifier)
+                (progn
+                  (c-forward-syntactic-ws)
+                  (looking-at (c-lang-const d-decl-end-re))))
+           t)))
+
+        ;; Function parameter list.
+        ;; Note: single (type-less) identifiers in parameter lists
+        ;; mean different things for function and lambda parameter
+        ;; lists.  For functions, they indicate the type of an
+        ;; anonymous parameter; for lambdas, they indicate the name
+        ;; of a parameter with an inferred type.
+        ;; Currently we don't fontify them as either.
+        ((and (eq context 'arglist)
+              (d-forward-type))
+         (setq type-start decl-start)
+         (setq id-start (point))
+         (and (d-forward-identifier)   ; parameter name
+                (progn
+                  (c-forward-syntactic-ws)
+                  (looking-at "[,=)]")))))
 
-      (setq
-       at-decl-or-cast
-       (catch 'at-decl-or-cast
-
-        ;; CASE 1
-        (when (> paren-depth 0)
-          ;; Encountered something inside parens that isn't matched by
-          ;; the `c-type-decl-*' regexps, so it's not a type decl
-          ;; expression.  Try to skip out to the same paren depth to
-          ;; not confuse the cast check below.  If we don't manage this and
-          ;; `at-decl-or-cast' is 'ids we might have an expression like
-          ;; "foo bar ({ ..." which is a valid C++11 initialization.
-          (if (and (not (c-safe (goto-char (scan-lists (point) 1 
paren-depth))))
-                   (eq at-decl-or-cast 'ids))
-              (c-fdoc-shift-type-backward))
-          ;; If we've found a specifier keyword then it's a
-          ;; declaration regardless.
-          (throw 'at-decl-or-cast (memq at-decl-or-cast '(t ids))))
-
-        (setq at-decl-end
-              (looking-at (cond ((eq context '<>) "[,>]")
-                                ((not (memq context '(nil top))) "[,\)]")
-                                (t "[,;]"))))
-
-        ;; Now we've collected info about various characteristics of
-        ;; the construct we're looking at.  Below follows a decision
-        ;; tree based on that.  It's ordered to check more certain
-        ;; signs before less certain ones.
-
-        (if got-identifier
-            (progn
-
-              ;; CASE 2
-              (when (and (or at-type maybe-typeless)
-                         (not (or got-prefix got-parens)))
-                ;; Got another identifier directly after the type, so it's a
-                ;; declaration.
-                (throw 'at-decl-or-cast t))
-
-              (when (and got-parens
-                         (not got-prefix)
-                         ;; (not got-suffix-after-parens)
-                         (or backup-at-type
-                             maybe-typeless
-                             backup-maybe-typeless
-                             (eq at-decl-or-cast t)
-                             ;; Check whether we have "bar (gnu);" where we
-                             ;; are directly inside a class (etc.) called 
"bar".
-                             (save-excursion
-                               (and
-                                (progn
-                                  (goto-char name-start)
-                                  (not (memq (c-forward-type) '(nil maybe))))
-                                (progn
-                                 (goto-char id-start)
-                                 (c-directly-in-class-called-p
-                                  (buffer-substring
-                                   type-start
-                                   (progn
-                                     (goto-char type-start)
-                                     (c-forward-type)
-                                     (c-backward-syntactic-ws)
-                                     (point)))))))))
-                ;; Got a declaration of the form "foo bar (gnu);" or "bar
-                ;; (gnu);" where we've recognized "bar" as the type and "gnu"
-                ;; as the declarator, and in the latter case, checked that
-                ;; "bar (gnu)" appears directly inside the class "bar".  In
-                ;; this case it's however more likely that "bar" is the
-                ;; declarator and "gnu" a function argument or initializer
-                ;; (if `c-recognize-paren-inits' is set), since the parens
-                ;; around "gnu" would be superfluous if it's a declarator.
-                ;; Shift the type one step backward.
-                (c-fdoc-shift-type-backward)))
-
-          ;; Found no identifier.
-
-          (if backup-at-type
-              (progn
-
-                ;; CASE 3
-                (when (= (point) start)
-                  ;; Got a plain list of identifiers. If a colon follows it's
-                  ;; a valid label, or maybe a bitfield.  Otherwise the last
-                  ;; one probably is the declared identifier and we should
-                  ;; back up to the previous type, providing it isn't a cast.
-                  (if (and (eq (char-after) ?:)
-                           (not (c-major-mode-is 'java-mode)))
-                      (cond
-                       ;; If we've found a specifier keyword then it's a
-                       ;; declaration regardless.
-                       ((eq at-decl-or-cast t)
-                        (throw 'at-decl-or-cast t))
-                       ((and c-has-bitfields
-                             (eq at-decl-or-cast 'ids)) ; bitfield.
-                        (setq backup-if-not-cast t)
-                        (throw 'at-decl-or-cast t)))
-
-                    (setq backup-if-not-cast t)
-                    (throw 'at-decl-or-cast t)))
-
-                ;; CASE 4
-                (when (and got-suffix
-                           (not got-prefix)
-                           (not got-parens))
-                  ;; Got a plain list of identifiers followed by some suffix.
-                  ;; If this isn't a cast then the last identifier probably is
-                  ;; the declared one and we should back up to the previous
-                  ;; type.
-                  (setq backup-if-not-cast t)
-                  (throw 'at-decl-or-cast t)))
-
-            ;; CASE 5
-            (when (eq at-type t)
-              ;; If the type is known we know that there can't be any
-              ;; identifier somewhere else, and it's only in declarations in
-              ;; e.g. function prototypes and in casts that the identifier may
-              ;; be left out.
-              (throw 'at-decl-or-cast t))
-
-            (when (= (point) start)
-              ;; Only got a single identifier (parsed as a type so far).
-              ;; CASE 6
-              (if (and
-                   ;; Check that the identifier isn't at the start of an
-                   ;; expression.
-                   at-decl-end
-                   (cond
-                    ((eq context 'decl)
-                     ;; Inside an arglist that contains declarations.  If K&R
-                     ;; style declarations and parenthesis style initializers
-                     ;; aren't allowed then the single identifier must be a
-                     ;; type, else we require that it's known or found
-                     ;; (primitive types are handled above).
-                     (or (and (not c-recognize-knr-p)
-                              (not c-recognize-paren-inits))
-                         (memq at-type '(known found))))
-                    ((eq context '<>)
-                     ;; Inside a template arglist.  Accept known and found
-                     ;; types; other identifiers could just as well be
-                     ;; constants in C++.
-                     (memq at-type '(known found)))))
-                  (throw 'at-decl-or-cast t)
-                ;; CASE 7
-                ;; Can't be a valid declaration or cast, but if we've found a
-                ;; specifier it can't be anything else either, so treat it as
-                ;; an invalid/unfinished declaration or cast.
-                (throw 'at-decl-or-cast at-decl-or-cast))))
-
-          (if (and got-parens
-                   (not got-prefix)
-                   (memq context '(nil top))
-                   (not (eq at-type t))
-                   (or backup-at-type
-                       maybe-typeless
-                       backup-maybe-typeless
-                       (when c-recognize-typeless-decls
-                         (or (not got-suffix)
-                             (not (looking-at
-                                   c-after-suffixed-type-maybe-decl-key))))))
-              ;; Got an empty paren pair and a preceding type that probably
-              ;; really is the identifier.  Shift the type backwards to make
-              ;; the last one the identifier.  This is analogous to the
-              ;; "backtracking" done inside the `c-type-decl-suffix-key' loop
-              ;; above.
-              ;;
-              ;; Exception: In addition to the conditions in that
-              ;; "backtracking" code, do not shift backward if we're not
-              ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]".
-              ;; Since there's no preceding type, the shift would mean that
-              ;; the declaration is typeless.  But if the regexp doesn't match
-              ;; then we will simply fall through in the tests below and not
-              ;; recognize it at all, so it's better to try it as an abstract
-              ;; declarator instead.
-              (c-fdoc-shift-type-backward)
-
-            ;; Still no identifier.
-            ;; CASE 8
-            (when (and got-prefix (or got-parens got-suffix))
-              ;; Require `got-prefix' together with either `got-parens' or
-              ;; `got-suffix' to recognize it as an abstract declarator:
-              ;; `got-parens' only is probably an empty function call.
-              ;; `got-suffix' only can build an ordinary expression together
-              ;; with the preceding identifier which we've taken as a type.
-              ;; We could actually accept on `got-prefix' only, but that can
-              ;; easily occur temporarily while writing an expression so we
-              ;; avoid that case anyway.  We could do a better job if we knew
-              ;; the point when the fontification was invoked.
-              (throw 'at-decl-or-cast t))
-
-            ;; CASE 9
-            (when (and at-type
-                       (not got-prefix)
-                       (not got-parens)
-                       got-suffix-after-parens
-                       (eq (char-after got-suffix-after-parens) ?\())
-              ;; Got a type, no declarator but a paren suffix. I.e. it's a
-              ;; normal function call after all (or perhaps a C++ style object
-              ;; instantiation expression).
-              (throw 'at-decl-or-cast nil))))
-
-        ;; CASE 9.5
-        (when (and (not context)       ; i.e. not at top level.
-                   (c-major-mode-is 'c++-mode)
-                   (eq at-decl-or-cast 'ids)
-                   after-paren-pos)
-          ;; We've got something like "foo bar (...)" in C++ which isn't at
-          ;; the top level.  This is probably a uniform initialization of bar
-          ;; to the contents of the parens.  In this case the declarator ends
-          ;; at the open paren.
-          (goto-char (1- after-paren-pos))
-          (throw 'at-decl-or-cast t))
-
-        ;; CASE 10
-        (when at-decl-or-cast
-          ;; By now we've located the type in the declaration that we know
-          ;; we're in.
-          (throw 'at-decl-or-cast t))
-
-        ;; CASE 11
-        (when (and got-identifier
-                   (looking-at c-after-suffixed-type-decl-key)
-                   (or (eq context 'top)
-                       make-top
-                       (and (eq context nil)
-                            (match-beginning 1)))
-                   (if (and got-parens
-                            (not got-prefix)
-                            (not got-suffix)
-                            (not (eq at-type t)))
-                       ;; Shift the type backward in the case that there's a
-                       ;; single identifier inside parens.  That can only
-                       ;; occur in K&R style function declarations so it's
-                       ;; more likely that it really is a function call.
-                       ;; Therefore we only do this after
-                       ;; `c-after-suffixed-type-decl-key' has matched.
-                       (progn (c-fdoc-shift-type-backward) t)
-                     got-suffix-after-parens))
-          ;; A declaration according to `c-after-suffixed-type-decl-key'.
-          (throw 'at-decl-or-cast t))
-
-        ;; CASE 12
-        (when (and (or got-prefix (not got-parens))
-                   (memq at-type '(t known)))
-          ;; It's a declaration if a known type precedes it and it can't be a
-          ;; function call.
-          (throw 'at-decl-or-cast t))
-
-        ;; If we get here we can't tell if this is a type decl or a normal
-        ;; expression by looking at it alone.  (That's under the assumption
-        ;; that normal expressions always can look like type decl expressions,
-        ;; which isn't really true but the cases where it doesn't hold are so
-        ;; uncommon (e.g. some placements of "const" in C++) it's not worth
-        ;; the effort to look for them.)
-
-;;;  2008-04-16: commented out the next form, to allow the function to 
recognize
-;;;  "foo (int bar)" in CC (an implicit type (in class foo) without a 
semicolon)
-;;;  as a(n almost complete) declaration, enabling it to be fontified.
-        ;; CASE 13
-        ;;     (unless (or at-decl-end (looking-at "=[^=]"))
-        ;; If this is a declaration it should end here or its initializer(*)
-        ;; should start here, so check for allowed separation tokens.  Note
-        ;; that this rule doesn't work e.g. with a K&R arglist after a
-        ;; function header.
-        ;;
-        ;; *) Don't check for C++ style initializers using parens
-        ;; since those already have been matched as suffixes.
-        ;;
-        ;; If `at-decl-or-cast' is then we've found some other sign that
-        ;; it's a declaration or cast, so then it's probably an
-        ;; invalid/unfinished one.
-        ;;       (throw 'at-decl-or-cast at-decl-or-cast))
-
-        ;; Below are tests that only should be applied when we're certain to
-        ;; not have parsed halfway through an expression.
-
-        ;; CASE 14
-        (when (memq at-type '(t known))
-          ;; The expression starts with a known type so treat it as a
-          ;; declaration.
-          (throw 'at-decl-or-cast t))
-
-        ;; CASE 15
-        (when (and (c-major-mode-is 'c++-mode)
-                   ;; In C++ we check if the identifier is a known type, since
-                   ;; (con|de)structors use the class name as identifier.
-                   ;; We've always shifted over the identifier as a type and
-                   ;; then backed up again in this case.
-                   identifier-type
-                   (or (memq identifier-type '(found known))
-                       (and (eq (char-after identifier-start) ?~)
-                            ;; `at-type' probably won't be 'found for
-                            ;; destructors since the "~" is then part of the
-                            ;; type name being checked against the list of
-                            ;; known types, so do a check without that
-                            ;; operator.
-                            (or (save-excursion
-                                  (goto-char (1+ identifier-start))
-                                  (c-forward-syntactic-ws)
-                                  (c-with-syntax-table
-                                      c-identifier-syntax-table
-                                    (looking-at c-known-type-key)))
-                                (save-excursion
-                                  (goto-char (1+ identifier-start))
-                                  ;; We have already parsed the type earlier,
-                                  ;; so it'd be possible to cache the end
-                                  ;; position instead of redoing it here, but
-                                  ;; then we'd need to keep track of another
-                                  ;; position everywhere.
-                                  (c-check-type (point)
-                                                (progn (c-forward-type)
-                                                       (point))))))))
-          (throw 'at-decl-or-cast t))
-
-        (if got-identifier
-            (progn
-              ;; CASE 16
-              (when (and got-prefix-before-parens
-                         at-type
-                         (or at-decl-end (looking-at "=[^=]"))
-                         (memq context '(nil top))
-                         (or (not got-suffix)
-                             at-decl-start))
-                ;; Got something like "foo * bar;".  Since we're not inside
-                ;; an arglist it would be a meaningless expression because
-                ;; the result isn't used.  We therefore choose to recognize
-                ;; it as a declaration.  We only allow a suffix (which makes
-                ;; the construct look like a function call) when
-                ;; `at-decl-start' provides additional evidence that we do
-                ;; have a declaration.
-                (setq maybe-expression t)
-                (throw 'at-decl-or-cast t))
-
-              ;; CASE 17
-              (when (and (or got-suffix-after-parens
-                             (looking-at "=[^=]"))
-                         (eq at-type 'found)
-                         (not (eq context 'arglist)))
-                ;; Got something like "a (*b) (c);" or "a (b) = c;".  It could
-                ;; be an odd expression or it could be a declaration.  Treat
-                ;; it as a declaration if "a" has been used as a type
-                ;; somewhere else (if it's a known type we won't get here).
-                (setq maybe-expression t)
-                (throw 'at-decl-or-cast t))
-
-              ;; CASE 17.5
-              (when (and c-asymmetry-fontification-flag
-                         got-prefix-before-parens
-                         at-type
-                         (or (not got-suffix)
-                             at-decl-start))
-                (let ((space-before-id
-                       (save-excursion
-                         (goto-char name-start)
-                         (or (bolp) (memq (char-before) '(?\  ?\t)))))
-                      (space-after-type
-                       (save-excursion
-                         (goto-char type-start)
-                         (and (c-forward-type)
-                              (progn (c-backward-syntactic-ws) t)
-                              (or (eolp)
-                                  (memq (char-after) '(?\  ?\t)))))))
-                  (when (not (eq (not space-before-id)
-                                 (not space-after-type)))
-                    (setq maybe-expression t)
-                    (throw 'at-decl-or-cast t)))))
-
-          ;; CASE 18
-          (when (and (not (memq context '(nil top)))
-                     (or (and got-prefix (not got-number))
-                         (and (eq context 'decl)
-                              (not c-recognize-paren-inits)
-                              (or got-parens got-suffix))))
-            ;; Got a type followed by an abstract declarator.  If `got-prefix'
-            ;; is set it's something like "a *" without anything after it.  If
-            ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]",
-            ;; or similar, which we accept only if the context rules out
-            ;; expressions.
-            (throw 'at-decl-or-cast t)))
-
-        ;; If we had a complete symbol table here (which rules out
-        ;; `c-found-types') we should return t due to the disambiguation rule
-        ;; (in at least C++) that anything that can be parsed as a declaration
-        ;; is a declaration.  Now we're being more defensive and prefer to
-        ;; highlight things like "foo (bar);" as a declaration only if we're
-        ;; inside an arglist that contains declarations.  Update (2017-09): We
-        ;; now recognize a top-level "foo(bar);" as a declaration in C.
-        ;; CASE 19
-        (or (eq context 'decl)
-            (and (c-major-mode-is 'c-mode)
-                 (or (eq context 'top) make-top))))))
-
-    ;; The point is now after the type decl expression.
+      ;; Valid declaration, process it.
 
-    (cond
-     ;; Check for a cast.
-     ((save-excursion
-       (and
-        c-cast-parens
-
-        ;; Should be the first type/identifier in a cast paren.
-        (> preceding-token-end (point-min))
-        (memq (char-before preceding-token-end) c-cast-parens)
-
-        ;; The closing paren should follow.
-        (progn
-          (c-forward-syntactic-ws)
-          (looking-at "\\s)"))
-
-        ;; There should be a primary expression after it.
-        (let (pos)
-          (forward-char)
-          (c-forward-syntactic-ws)
-          (setq cast-end (point))
-          (and (looking-at c-primary-expr-regexp)
-               (progn
-                 (setq pos (match-end 0))
-                 (or
-                  ;; Check if the expression begins with a prefix keyword.
-                  (match-beginning 2)
-                  (if (match-beginning 1)
-                      ;; Expression begins with an ambiguous operator.  Treat
-                      ;; it as a cast if it's a type decl or if we've
-                      ;; recognized the type somewhere else.
-                      (or at-decl-or-cast
-                          (memq at-type '(t known found)))
-                    ;; Unless it's a keyword, it's the beginning of a primary
-                    ;; expression.
-                    (not (looking-at c-keywords-regexp)))))
-               ;; If `c-primary-expr-regexp' matched a nonsymbol token, check
-               ;; that it matched a whole one so that we don't e.g. confuse
-               ;; the operator '-' with '->'.  It's ok if it matches further,
-               ;; though, since it e.g. can match the float '.5' while the
-               ;; operator regexp only matches '.'.
-               (or (not (looking-at c-nonsymbol-token-regexp))
-                   (<= (match-end 0) pos))))
-
-        ;; There should either be a cast before it or something that isn't an
-        ;; identifier or close paren.
-        (> preceding-token-end (point-min))
-        (progn
-          (goto-char (1- preceding-token-end))
-          (or (eq (point) last-cast-end)
-              (progn
-                (c-backward-syntactic-ws)
-                (if (< (skip-syntax-backward "w_") 0)
-                    ;; It's a symbol.  Accept it only if it's one of the
-                    ;; keywords that can precede an expression (without
-                    ;; surrounding parens).
-                    (looking-at c-simple-stmt-key)
-                  (and
-                   ;; Check that it isn't a close paren (block close is ok,
-                   ;; though).
-                   (not (memq (char-before) '(?\) ?\])))
-                   ;; Check that it isn't a nonsymbol identifier.
-                   (not (c-on-identifier)))))))))
-
-      ;; Handle the cast.
-      (when (and c-record-type-identifiers at-type (not (eq at-type t)))
-       (let ((c-promote-possible-types t))
-         (goto-char type-start)
-         (c-forward-type)))
-
-      (goto-char cast-end)
-      'cast)
-
-     (at-decl-or-cast
-      ;; We're at a declaration.  Highlight the type and the following
-      ;; declarators.
-
-      (when backup-if-not-cast
-       (c-fdoc-shift-type-backward t))
-
-      (when (and (eq context 'decl) (looking-at ","))
-       ;; Make sure to propagate the `c-decl-arg-start' property to
-       ;; the next argument if it's set in this one, to cope with
-       ;; interactive refontification.
-       (c-put-c-type-property (point) 'c-decl-arg-start))
-
-      ;; Record the type's coordinates in `c-record-type-identifiers' for
-      ;; later fontification.
-      (when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
-                ;; There seems no reason to exclude a token from
-                ;; fontification just because it's "a known type that can't
-                ;; be a name or other expression".  2013-09-18.
-                )
+      (when (and c-record-type-identifiers type-start)
        (let ((c-promote-possible-types t))
          (save-excursion
            (goto-char type-start)
-           (c-forward-type))))
+           (d-forward-type))))
 
       (list id-start
-           (and (or at-type-decl at-typedef)
-                (cons at-type-decl at-typedef))
-           maybe-expression
+           nil
+           nil
            type-start
-           (or (eq context 'top) make-top)))
+           (or (eq context 'top) make-top)))))
+      
+
+(defun d-forward-identifier ()
+  "Advance point by one D identifier."
+  (when (and (not (looking-at c-keywords-regexp))
+            (looking-at c-symbol-key))
+    (goto-char (match-end 0))
+    t))
+
+
+(defun d-forward-attribute-or-storage-class ()
+  "Handle D attributes and storage classes in declarations.
 
-     (t
-      ;; False alarm.  Restore the recorded ranges.
-      (setq c-record-type-identifiers save-rec-type-ids
-           c-record-ref-identifiers save-rec-ref-ids)
-      nil))))
+Advance point and return non-nil if looking at something that may prefix a
+declaration (or follow the argument list, in case of functions)."
+  ;; Note that this includes UDAs.
+  (let ((start (point))
+       (kind t)
+       match-index)
+    (when
+       (cond
+        ((looking-at (d-make-keywords-re t '("enum")))
+         (setq match-index 1
+               kind 'enum))
+        ((looking-at (d-make-keywords-re t (c-lang-const d-type-modifier-kwds 
d)))
+         (setq match-index 1
+               kind 'type-modifier))
+        ((looking-at (d-make-keywords-re t (c-lang-const c-modifier-kwds d)))
+         (setq match-index 1))
+        ((and (eq (char-after) ?@)
+              (looking-at c-symbol-key))
+         (setq match-index 0)))
+      (goto-char (match-end match-index))
+      (c-forward-syntactic-ws)
+      ;; Skip parameters, such as:
+      ;; - extern(C)
+      ;; - deprecated("...")
+      ;; - package(std)
+      ;; - @SomeUDA(...)
+      (if (looking-at "(")
+         ;; Distinguish between "const x" and "const(x)".  In the
+         ;; former, "const" is an attribute, but in the latter it is
+         ;; part of a type.  This distinction is important when parsing
+         ;; constructs where a type is required; a greedy attribute
+         ;; match would leave only "(x)" which will not make sense.
+         (if (eq kind 'type-modifier)
+             (progn
+               (goto-char start)
+               nil)
+           (c-go-list-forward)
+           (c-forward-syntactic-ws)
+           kind)
+       kind))))
 
 ;;----------------------------------------------------------------------------
 
@@ -2451,9 +1596,11 @@ The expression is added to 
`compilation-error-regexp-alist' and
                                (point)))
                    (id-end (progn
                              (goto-char id-start)
-                             (when (d-forward-name)
-                               (c-backward-syntactic-ws)
-                               (point))))
+                             (cond
+                              ((d-forward-identifier)
+                               (point))
+                              ((looking-at (d-make-keywords-re t '("this" 
"~this")))
+                               (match-end 1)))))
                    (name (when id-end
                            (buffer-substring-no-properties id-start id-end)))
                    (id-prev-token (progn
@@ -2463,6 +1610,11 @@ The expression is added to 
`compilation-error-regexp-alist' and
                                       (when (c-simple-skip-symbol-backward)
                                         (buffer-substring-no-properties 
(point) end)))))
                    (type-start (cadddr decl-or-cast))
+                   (type-token (and type-start
+                                    (progn
+                                      (goto-char type-start)
+                                      (looking-at c-symbol-key))
+                                    (match-string-no-properties 0)))
                    (type-prev-token (when type-start
                                       (goto-char type-start)
                                       (c-backward-syntactic-ws)
@@ -2490,7 +1642,7 @@ The expression is added to 
`compilation-error-regexp-alist' and
                           '("Templates" t))
                          ((equal id-prev-token "alias")
                           '("Aliases" nil))
-                         ((equal type-prev-token "alias")
+                         ((equal type-token "alias")
                           '("Aliases" nil)) ; old-style alias
                          ((memq next-char '(?\; ?= ?,))
                           nil) ; '("variable" nil))
diff --git a/tests/I0095.d.html b/tests/I0095.d.html
index c9ac7cf..a9f7452 100644
--- a/tests/I0095.d.html
+++ b/tests/I0095.d.html
@@ -1,6 +1,6 @@
 <span class="comment-delimiter">// </span><span class="comment">#run: 
(d-test-fontification)
 </span>
-<span class="keyword">alias</span> <span class="type">Type</span> = <span 
class="type">int</span>;
+<span class="keyword">alias</span> <span class="variable-name">Type</span> = 
<span class="type">int</span>;
 
 <span class="type">void</span> <span class="function-name">foo</span>(<span 
class="keyword">const</span>(<span class="type">Type</span>) <span 
class="variable-name">param</span>);
 
diff --git a/tests/fonts.d b/tests/fonts.d
index d93595f..26e320b 100644
--- a/tests/fonts.d
+++ b/tests/fonts.d
@@ -27,3 +27,6 @@ auto s = "enum Type {}";
 assert(a !in b);
 
 invariant {}
+
+class Foo : Bar {}
+enum Foo : Bar {}
diff --git a/tests/fonts.d.html b/tests/fonts.d.html
index 9d82476..51a0e36 100644
--- a/tests/fonts.d.html
+++ b/tests/fonts.d.html
@@ -27,3 +27,6 @@
 <span class="keyword">assert</span>(a <span 
class="negation-char">!</span><span class="keyword">in</span> b);
 
 <span class="keyword">invariant</span> {}
+
+<span class="keyword">class</span> <span class="type">Foo</span> : <span 
class="type">Bar</span> {}
+<span class="keyword">enum</span> <span class="type">Foo</span> : <span 
class="type">Bar</span> {}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]