From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: "enum class" supports for cc-mode Date: Wed, 29 Oct 2014 16:49:15 +0000 Message-ID: <20141029164915.GC2953@acm.acm> References: <544E9099.7030409@dancol.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1414601422 23284 80.91.229.3 (29 Oct 2014 16:50:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 29 Oct 2014 16:50:22 +0000 (UTC) Cc: Emacs developers To: Daniel Colascione Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Oct 29 17:50:15 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XjWRq-0005an-I3 for ged-emacs-devel@m.gmane.org; Wed, 29 Oct 2014 17:50:14 +0100 Original-Received: from localhost ([::1]:47509 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XjWRq-0000Vb-8D for ged-emacs-devel@m.gmane.org; Wed, 29 Oct 2014 12:50:14 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56891) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XjWRg-0000Rm-IK for emacs-devel@gnu.org; Wed, 29 Oct 2014 12:50:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XjWRY-00043q-NH for emacs-devel@gnu.org; Wed, 29 Oct 2014 12:50:04 -0400 Original-Received: from colin.muc.de ([193.149.48.1]:26553 helo=mail.muc.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XjWRY-00043Q-CZ for emacs-devel@gnu.org; Wed, 29 Oct 2014 12:49:56 -0400 Original-Received: (qmail 95194 invoked by uid 3782); 29 Oct 2014 16:49:55 -0000 Original-Received: from acm.muc.de (pD9519282.dip0.t-ipconnect.de [217.81.146.130]) by colin.muc.de (tmda-ofmipd) with ESMTP; Wed, 29 Oct 2014 17:49:53 +0100 Original-Received: (qmail 4475 invoked by uid 1000); 29 Oct 2014 16:49:15 -0000 Content-Disposition: inline In-Reply-To: <544E9099.7030409@dancol.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-detected-operating-system: by eggs.gnu.org: FreeBSD 8.x X-Received-From: 193.149.48.1 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:176020 Archived-At: Hi, Daniel. On Mon, Oct 27, 2014 at 06:36:09PM +0000, Daniel Colascione wrote: > Here's a small patch that teaches cc-mode about C++11 "enum class" syntax. > See http://msdn.microsoft.com/en-us/library/2dzy4k6e.aspx > Alan, can you take a look? Thanks for this, it looks good. I'll definitely install it (with proper attribution). Just one or two little details: (i) You've used `eql' rather than `eq' for comparing things in a few places. Is there any reason for this? (ii) c-after-brace-list-key will be "\\<\\>" (not nil) for non-C++ languages, I think. It's definition in cc-langs.el needs tweaking a bit to make it nil. (iii) There's a question as to whether the backward searching in c-backward-colon-prefixed-type should have an optional search limit. But the existing c-backward-over-enum-header doesn't, so that's something new to think about. Now, I'll go and try actually merging and running it. > === modified file 'lisp/progmodes/cc-engine.el' > --- lisp/progmodes/cc-engine.el 2014-10-18 10:02:59 +0000 > +++ lisp/progmodes/cc-engine.el 2014-10-27 18:00:51 +0000 > @@ -8460,28 +8460,41 @@ > (cond > ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t) > (goto-char (setq kwd-start (match-beginning 0))) > - (or > - > - ;; Found a keyword that can't be a type? > - (match-beginning 1) > - > - ;; Can be a type too, in which case it's the return type of a > - ;; function (under the assumption that no declaration level > - ;; block construct starts with a type). > - (not (c-forward-type)) > - > - ;; Jumped over a type, but it could be a declaration keyword > - ;; followed by the declared identifier that we've jumped over > - ;; instead (e.g. in "class Foo {"). If it indeed is a type > - ;; then we should be at the declarator now, so check for a > - ;; valid declarator start. > - ;; > - ;; Note: This doesn't cope with the case when a declared > - ;; identifier is followed by e.g. '(' in a language where '(' > - ;; also might be part of a declarator expression. Currently > - ;; there's no such language. > - (not (or (looking-at c-symbol-start) > - (looking-at c-type-decl-prefix-key))))) > + (and > + ;; Exclude cases where we matched what would ordinarily > + ;; be a block declaration keyword, except where it's not > + ;; legal because it's part of a "compound keyword" like > + ;; "enum class". Of course, if c-after-brace-list-key > + ;; is nil, we can skip the test. > + (or (null c-after-brace-list-key) > + (save-match-data > + (save-excursion > + (not > + (and > + (looking-at c-after-brace-list-key) > + (= (c-backward-token-2 1 t) 0) > + (looking-at c-brace-list-key)))))) > + (or > + ;; Found a keyword that can't be a type? > + (match-beginning 1) > + > + ;; Can be a type too, in which case it's the return type of a > + ;; function (under the assumption that no declaration level > + ;; block construct starts with a type). > + (not (c-forward-type)) > + > + ;; Jumped over a type, but it could be a declaration keyword > + ;; followed by the declared identifier that we've jumped over > + ;; instead (e.g. in "class Foo {"). If it indeed is a type > + ;; then we should be at the declarator now, so check for a > + ;; valid declarator start. > + ;; > + ;; Note: This doesn't cope with the case when a declared > + ;; identifier is followed by e.g. '(' in a language where '(' > + ;; also might be part of a declarator expression. Currently > + ;; there's no such language. > + (not (or (looking-at c-symbol-start) > + (looking-at c-type-decl-prefix-key)))))) > > ;; In Pike a list of modifiers may be followed by a brace > ;; to make them apply to many identifiers. Note that the > @@ -8586,9 +8599,35 @@ > (not (looking-at "="))))) > b-pos))) > > +(defun c-backward-colon-prefixed-type () > + ;; We're after what might be a type prefixed with a colon. Try > + ;; moving backward over this type and the colon. On success, return > + ;; t and leave point before colon, on falure, leave point unchanged. > + ;; Will clobber match data. > + (let ((colon-pos nil)) > + (save-excursion > + (while > + (and (eql (c-backward-token-2) 0) > + (or (not (looking-at "\\s)")) > + (c-go-up-list-backward)) > + (cond > + ((eql (char-after) ?:) > + (setq colon-pos (point)) > + nil) > + ((eql (char-after) ?\() > + t) > + ((looking-at c-symbol-key) > + t) > + (t nil))))) > + (when colon-pos > + (goto-char colon-pos) > + t))) > + > (defun c-backward-over-enum-header () > ;; We're at a "{". Move back to the enum-like keyword that starts this > ;; declaration and return t, otherwise don't move and return nil. > + (when c-recognize-post-brace-list-type-p > + (c-backward-colon-prefixed-type)) > (let ((here (point)) > up-sexp-pos before-identifier) > (while > @@ -8596,21 +8635,22 @@ > (eq (c-backward-token-2) 0) > (or (not (looking-at "\\s)")) > (c-go-up-list-backward)) > - (cond > - ((and (looking-at c-symbol-key) (c-on-identifier) > - (not before-identifier)) > - (setq before-identifier t)) > - ((and before-identifier > - (or (eq (char-after) ?,) > - (looking-at c-postfix-decl-spec-key))) > - (setq before-identifier nil) > - t) > - ((looking-at c-brace-list-key) nil) > - ((and c-recognize-<>-arglists > - (eq (char-after) ?<) > - (looking-at "\\s(")) > - t) > - (t nil)))) > + (cond > + ((and (looking-at c-symbol-key) (c-on-identifier) > + (not before-identifier)) > + (setq before-identifier t)) > + ((and before-identifier > + (or (eql (char-after) ?,) > + (looking-at c-postfix-decl-spec-key))) > + (setq before-identifier nil) > + t) > + ((looking-at c-after-brace-list-key) t) > + ((looking-at c-brace-list-key) nil) > + ((and c-recognize-<>-arglists > + (eq (char-after) ?<) > + (looking-at "\\s(")) > + t) > + (t nil)))) > (or (looking-at c-brace-list-key) > (progn (goto-char here) nil)))) > > > === modified file 'lisp/progmodes/cc-langs.el' > --- lisp/progmodes/cc-langs.el 2014-10-12 20:09:15 +0000 > +++ lisp/progmodes/cc-langs.el 2014-10-27 17:34:41 +0000 > @@ -1805,8 +1805,31 @@ > ;; Regexp matching the start of declarations where the following > ;; block is a brace list. > t (c-make-keywords-re t (c-lang-const c-brace-list-decl-kwds))) > + > (c-lang-defvar c-brace-list-key (c-lang-const c-brace-list-key)) > > +(c-lang-defconst c-after-brace-list-decl-kwds > + "Keywords that might follow keywords in `c-brace-list-decl-kwds' > +and precede the opening brace." > + t nil > + c++ '("class" "struct")) > + > +(c-lang-defconst c-after-brace-list-key > + ;; Regexp matching keywords that can fall between a brace-list > + ;; keyword and the associated brace list. > + t (c-make-keywords-re t (c-lang-const c-after-brace-list-decl-kwds))) > + > +(c-lang-defvar c-after-brace-list-key (c-lang-const c-after-brace-list-key)) > + > +(c-lang-defconst c-recognize-post-brace-list-type-p > + ;; Recognize a colon and then a type after an enum, e.g., > + ;; enum foo : int { A, B, C }; > + t nil > + c++ t) > + > +(c-lang-defvar c-recognize-post-brace-list-type-p > + (c-lang-const c-recognize-post-brace-list-type-p)) > + > (c-lang-defconst c-other-block-decl-kwds > "Keywords where the following block (if any) contains another > declaration level that should not be considered a class. For every > @@ -2000,6 +2023,7 @@ > ;; prefixes. > t (delete-duplicates (append (c-lang-const c-class-decl-kwds) > (c-lang-const c-brace-list-decl-kwds) > + (c-lang-const c-after-brace-list-decl-kwds) > (c-lang-const c-other-block-decl-kwds) > (c-lang-const c-typedef-decl-kwds) > (c-lang-const c-typeless-decl-kwds) -- Alan Mackenzie (Nuremberg, Germany).