--- /dev/null
+;;; 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)