From: g0dil Date: Thu, 9 Aug 2007 12:13:35 +0000 (+0000) Subject: Emacs/cc-ide: More flexible ccide-all-includes implementation X-Git-Url: http://g0dil.de/git?p=emacsstuff.git;a=commitdiff_plain;h=0b379d5468d6ac8bec3f984bf8f3a236f26d0b1a Emacs/cc-ide: More flexible ccide-all-includes implementation Emacs/cc-ide: Add interactive 'description' argument to ccide-gen-exception Emacs/cc-ide: Implement C++ argument-declaration parser (recursive descent) --- diff --git a/cc-ide/cc-ide.el b/cc-ide/cc-ide.el index 67b7a44..50c1778 100644 --- a/cc-ide/cc-ide.el +++ b/cc-ide/cc-ide.el @@ -31,7 +31,10 @@ (defvar ccide-default-author "") (defvar ccide-default-copyright "") -(defvar ccide-all-includes-guard nil) +(defvar ccide-all-includes nil + "*If non-nil, this is the name of a file to include to fetch all +includes of a project. This is used if single include files cannot be +correctly included.") (defvar ccide-corba-skel-dir "") (defvar ccide-corba-idl-dir "") @@ -208,7 +211,9 @@ point add-file-vars) (push-mark) (goto-char (point-min)) - (insert "// Copyright (C) " (number-to-string (nth 5 (decode-time))) + (insert "// $Id$\n" + "//\n" + "// Copyright (C) " (number-to-string (nth 5 (decode-time))) " " ccide-default-author "\n" ccide-default-copyright "\n") @@ -217,16 +222,22 @@ (insert "/** \\file\n" " \\brief " (ccide-file-name) " public header */\n\n" "#ifndef " (ccide-file-macro-name) "\n" - "#define " (ccide-file-macro-name) " 1\n\n" - "// Custom includes\n\n" + "#define " (ccide-file-macro-name) " 1\n\n") + (if ccide-all-includes + (insert "#ifndef " (ccide-file-macro-name ccide-all-includes) "\n" + "#error \"Don't include '" (file-name-nondirectory (buffer-file-name)) "'" + " directly, include '" ccide-all-includes "'\"\n" + "#endif\n\n")) + (insert "// Custom includes\n\n" "//#include \"" (ccide-file-name ".mpp") "\"\n" "///////////////////////////////hh.p////////////////////////////////////////\n\n") (setq point (point)) (goto-char (point-max)) (insert "\n\n///////////////////////////////hh.e////////////////////////////////////////\n") - (if ccide-all-includes-guard + (if ccide-all-includes (insert "#endif\n" - "#if !defined(" ccide-all-includes-guard ") && !defined(" (ccide-file-macro-name) "i_)\n" + "#if !defined(" (ccide-file-macro-name ccide-all-includes) "_decls_) " + "&& !defined(" (ccide-file-macro-name) "i_)\n" "#define " (ccide-file-macro-name) "i_\n")) (insert "//#include \"" (ccide-file-name ".cci") "\"\n" "//#include \"" (ccide-file-name ".ct") "\"\n" @@ -277,7 +288,8 @@ "//#include \"" (ccide-file-name ".hh") "\"\n" "//#include \"" (ccide-file-name ".ih") "\"\n\n" "// Custom includes\n" - "#include \"" (ccide-file-name ".hh" (ccide-file-name)) "\"\n\n" + "#include \"" (or ccide-all-includes + (ccide-file-name ".hh" (ccide-file-name))) "\"\n\n" "#include \n" "#include \n\n" "#define prefix_\n" @@ -291,7 +303,8 @@ (string-match "\\.cpp$" (buffer-file-name))) (insert "/** \\file\n" " \\brief " (ccide-file-name) " non-inline non-template implementation */\n\n" - "//#include \"" (ccide-file-name ".hh") "\"\n" + (if ccide-all-includes "" "//") + "#include \"" (or ccide-all-includes (ccide-file-name ".hh")) "\"\n" "//#include \"" (ccide-file-name ".ih") "\"\n\n" "// Custom includes\n\n" "//#include \"" (ccide-file-name ".mpp") "\"\n" @@ -650,7 +663,7 @@ copy constructor, assignment operator and destructor." (message name))) (defun ccide-gen-exception (class &optional description) - (interactive "sException name: ") + (interactive "sException name: \nsDescription (defaults to full class name): ") (beginning-of-line) (open-line 1) (indent-according-to-mode) @@ -662,7 +675,11 @@ copy constructor, assignment operator and destructor." (insert "struct " class " : public std::exception\n" ofs "{ virtual char const * what() const throw() ") (setq p (point)) - (insert "{ return \"" prefix "::" class "\"; } };") + (insert "{ return \"" + (if (and description (> (length description) 0)) + description + (concat prefix "::" class)) + "\"; } };") (if (> (current-column) fill-column) (save-excursion (goto-char p) @@ -679,7 +696,8 @@ copy constructor, assignment operator and destructor." (progn (c-forward-out-of-comment) (c-backward-syntactic-ws) - (c-backward-sexp))) + (c-backward-sexp)) + (beginning-of-line)) (c-beginning-of-defun-or-decl) (let ((defun (c-get-defun-state)) (indent (make-string comment-column ? )) diff --git a/cc-ide/cc-parse.el b/cc-ide/cc-parse.el new file mode 100644 index 0000000..529eb56 --- /dev/null +++ b/cc-ide/cc-parse.el @@ -0,0 +1,135 @@ +;;; cc-parse.el --- Generator for recursive-descent parsers +;; +;; Copyright (C) 2007 Stefan Bund + +;; cc-parse.el is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2, or (at +;; your option) any later version. + +;; cc-parse.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; This is a very rudimentary parser to parse a single C++ argument +;; declaration. The goal of this parser is, given an argument +;; declaration find the name of the argument and the position of that +;; name within the declaration. +;; +;; The current version does not support string- or charachter literals +;; and comments within an argument declaration. + +;;;; Code: + +(require 'recdesc) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun cc-parse-arg (arg) + ;; Returns a cons ( POSITION . NAME ) where POSITION is the position + ;; of the argument in ARG and NAME is the name of that + ;; argument. Will return 'nil, if the argument name is omitted in + ;; the declaration. + (recdesc-scan-string 'decl arg)) + +(recdesc-declare + + (term optional-whitespace () + (match "[ \t\n\r]*")) + + (term word () + (match optional-whitespace) + (collect (match "\\w+\\b")) + (return (cons (- position (length (car elements))) + (car elements)))) + + (term symbol () + (match optional-whitespace) + (match word) + (maybe (repeat (match optional-whitespace) + (match "::") + (match optional-whitespace) + (match word))) + (match optional-whitespace) + (maybe (match "<") + (match tokens) + (match optional-whitespace) + (match ">"))) + + (term tokens () + (match optional-whitespace) + (or (and (match "(") (commit) (match tokens) (match ")")) + (and (match "\\[") (commit) (match tokens) (match "\\]")) + (and (match "{") (commit) (match tokens) (match "}")) + (and (match "<") (commit) (match tokens) (match ">")) + (match "[^][(){}<>]*"))) + + (term decl () + (match optional-whitespace) + (collect (or (match primary) + (match group) + (match member-pointer) + (match modifier) + (match word))) + (maybe (match arglist)) + (maybe (repeat (match array))) + (match optional-whitespace) + (return (car elements))) + + (term primary () + (match optional-whitespace) + (match symbol) + (match optional-whitespace) + (collect (match decl)) + (return (car elements))) + + (term group () + (match optional-whitespace) + (match "(") + (collect (match decl)) + (match optional-whitespace) + (match ")") + (return (car elements))) + + (term member-pointer () + (match optional-whitespace) + (match symbol) + (match optional-whitespace) + (match "::") + (match optional-whitespace) + (match "*") + (commit) + (match decl)) + + (term modifier () + (match optional-whitespace) + (match "const\\|volatile\\|\\*\\|&") + (commit) + (collect (match decl)) + (return (car elements))) + + (term array () + (match optional-whitespace) + (match "\\[") + (commit) + (match tokens) + (match optional-whitespace) + (match "\\]") + (return (car elements))) + + (term arglist () + (match optional-whitespace) + (match "(") + (commit) + (match tokens) + (match optional-whitespace) + (match ")"))) + +;; To debug a term, place the name of the term's function into 'fn', +;; place the curor at the end of the line and presse C-x C-e. You may +;; then use 'edebug-defun' on the declaration produced by this. +;; +;; (let ((fn 'recdesc@@decl)) (save-excursion (insert (prin1-to-string (symbol-function fn)))) (insert "\n\n") (forward-char 1) (delete-char 6) (insert "defun " (symbol-name fn)) (forward-sexp) (insert "\n") (let ((start (point))) (forward-line 1) (replace-string ")" ")\n" nil start (point)) (indent-region (save-excursion (goto-char start) (forward-line -1) (point)) (point) nil))) + +(provide cc-parse) diff --git a/cc-ide/recdesc.el b/cc-ide/recdesc.el new file mode 100644 index 0000000..90b4c04 --- /dev/null +++ b/cc-ide/recdesc.el @@ -0,0 +1,271 @@ +;;; recdesc.el --- Generator for recursive-descent parsers +;; +;; Copyright (C) 2000,2007 Stefan Bund + +;; recdesc.el is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2, or (at +;; your option) any later version. + +;; recdesc.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;;; Commentary: + +;; Der Syntax einer term deklaration ist: + +;; := (term ...) +;; +;; := +;; | (collect ) +;; | (return
) +;; +;; := | +;; +;; := (match [...]) +;; | (or ...) +;; | (and ...) +;; | (maybe ...) +;; | (repeat ...) +;; | (commit) +;; | (fail) +;; | (progn ...) +;; +;; := | + +;; +;; + +;;; Change-Log: + +;; $Log: recdesc.el,v $ +;; Revision 1.3 2000/02/13 21:19:56 bund +;; Erste vollständige version von SqIV2 +;; +;; Revision 1.2 2000/02/03 10:15:19 bund +;; *** empty log message *** +;; +;; Revision 1.1 2000/02/01 13:26:03 bund +;; *** empty log message *** +;; +;; + +;;; Variables: + +;;; Code: + +(require 'cl) + +(declaim (special position)) +(declaim (special string)) +(declaim (special commit-flag)) +(declaim (special saved-position)) +(declaim (special saved-elements)) +(declaim (special elements)) +(declaim (special return-form)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Zunächst der Parser/Scanner zur deklaration von Termen + +(defmacro recdesc-deferror (name message &rest classes) + `(progn + (put ',name 'error-conditions '(error sqi-error ,@classes ,name)) + (put ',name 'error-message ,message))) + +(defmacro recdesc-declare (&rest forms) + (cons 'progn + (loop for form in forms + collect (if (and (consp form) + (eq (car form) 'term) + (consp (cdr form)) + (symbolp (cadr form)) + (consp (cddr form)) + (listp (caddr form))) + (recdesc-declare-term (cadr form) + (caddr form) + (cdddr form)) + (signal 'recdesc-invalid-decl-component + (list form)))))) + +(recdesc-deferror recdesc-invalid-decl-component + "Invalid component in recdesc-declare" recdesc-error) + +(defun recdesc-declare-term (name arglist body) + (let (return-form) + `(defun ,(intern (concat "recdesc@@" (symbol-name name))) ,arglist + (let (elements) + (or (and ,(recdesc-parse-directive/and body) + ,(if return-form + return-form + '(or elements t)))))))) + +(defun recdesc-parse-command (command) + (if (not (consp command)) + (signal 'recdesc-invalid-command + (list command))) + (cond ((eq (car command) 'return) + (if (not (consp (cdr command))) + (signal 'recdesc-invalid-command + (list command))) + (setq return-form (cadr command)) + t) + ((eq (car command) 'collect) + (if (not (consp (cdr command))) + (signal 'recdesc-invalid-command (list command))) + `(recdesc-collect ,(recdesc-parse-directive-or-form (cadr command)))) + (t (recdesc-parse-directive command)))) + +(recdesc-deferror recdesc-invalid-command + "Invalid scanner command" recdesc-error) + +(defun recdesc-parse-directive-or-form (directive-or-form) + (or (recdesc-parse-directive directive-or-form t) + directive-or-form)) + +(defun recdesc-parse-directive (directive &optional nosignal) + (if (not (consp directive)) + (if (not nosignal) + (signal 'recdesc-invalid-directive + (list directive))) + (cond ((eq (car directive) 'match) (recdesc-parse-directive/match (cdr directive))) + ((eq (car directive) 'or) (recdesc-parse-directive/or (cdr directive))) + ((eq (car directive) 'and) (recdesc-parse-directive/and (cdr directive))) + ((eq (car directive) 'maybe) (recdesc-parse-directive/maybe (cdr directive))) + ((eq (car directive) 'repeat) (recdesc-parse-directive/repeat (cdr directive))) + ((eq (car directive) 'commit) (recdesc-parse-directive/commit (cdr directive))) + ((eq (car directive) 'fail) (recdesc-parse-directive/fail (cdr directive))) + ((eq (car directive) 'progn) (recdesc-parse-directive/progn (cdr directive))) + (t (if (not nosignal) + (signal 'recdesc-invalid-directive + (list directive))))))) + +(recdesc-deferror recdesc-invalid-directive + "Invalid scanner directive" recdesc-error) + +(defun recdesc-parse-directive/match (args) + (if (not (consp args)) + (signal 'recdesc-invalid-match-arguments + (list args))) + (if (symbolp (car args)) + (cons (intern (concat "recdesc@@" (symbol-name (car args)))) + (cdr args)) + (if (not (null (cdr args))) + (signal 'recdesc-invalid-match-arguments + (list args))) + (list 'recdesc-match-regexp (car args)))) + +(recdesc-deferror recdesc-invalid-match-arguments + "Invalid arguments to match directive" recdesc-error) + +(defun recdesc-parse-directive/or (args) + (if (not (consp args)) + (signal 'recdesc-invalid-or-arguments + (list args))) + (cons 'or + (loop for command in args + collect (recdesc-parse-directive/and (list command))))) + +(recdesc-deferror recdesc-invalid-or-arguments + "Invalid arguments to or directive" recdesc-error) + +(defun recdesc-parse-directive/and (args) + (if (not (consp args)) + (signal 'recdesc-invalid-and-arguments + (list args))) + `(let ((saved-position position) + (saved-elements elements) + commit-flag) + (or (and ,@(loop for command in args + collect (recdesc-parse-command command))) + (recdesc-backtrack)))) + +(recdesc-deferror recdesc-invalid-and-arguments + "Invalid arguments to and directive" recdesc-error) + +(defun recdesc-parse-directive/maybe (args) + (if (not (consp args)) + (signal 'recdesc-invalid-maybe-arguments + (list args))) + `(or ,(recdesc-parse-directive/and args) t)) + +(defun recdesc-parse-directive/repeat (args) + `(loop for repeat-item = ,(recdesc-parse-directive/and args) + while repeat-item + collect repeat-item)) + +(defun recdesc-parse-directive/commit (args) + (if args + (signal 'recdesc-invalid-commit-arguments + (list args))) + `(setq commit-flag t)) + +(recdesc-deferror recdesc-invalid-commit-arguments + "Invalid arguments to commit directive" recdesc-error) + +(defun recdesc-parse-directive/fail (args) + (if args + (signal 'recdesc-invalid-fail-arguments + (list args))) + '(throw 'recdesc-failed nil)) + +(recdesc-deferror recdesc-invalid-fail-arguments + "Invalid arguments to fail directive" recdesc-error) + +(defun recdesc-parse-directive/progn (args) + `(progn ,@args)) + +(put 'term 'lisp-indent-function 'defun) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Die folgenden Funktionen werden von den durch recdesc-declare +;; erzeugten termen benötigt + +(defun recdesc-backtrack () + (progn + (if commit-flag + (throw 'recdesc-failed nil)) + (setq position saved-position + elements saved-elements) + nil)) + +(defun recdesc-collect (value) + (if value + (progn + (setq elements (nconc elements + (list value))) + value))) + +(defun recdesc-match-regexp (regexp) + (if (string-match (concat "^" regexp) (substring string position)) + (let ((start position)) + (setq position (+ position (match-end 0))) + (substring string start position)))) + +(defun recdesc-match (term &rest args) + (apply (intern (concat "recdesc@@" (symbol-name term))) args)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Toplevel calls to generated scanners + +(defun recdesc-scan-string (term string &rest args) + (let ((scanner (intern (concat "recdesc@@" + (symbol-name term)))) + (position 0) + rv) + (setq rv (catch 'recdesc-failed + (apply scanner args))) + (if (not (string-match "^[ \t\n\r]*$" (substring string position))) + nil + rv))) + +(provide 'recdesc) + + +;;; Local Variables: +;;; elisp-project-autoload-file-name: "sqi-autoload.el" +;;; End: