+ (kw-argument ()
+ ;; kw-argument ::= type declspec [= c-fragment]
+
+ (parse (seq ((dtor (arg-decl nil))
+ (dflt (? (when (eq (token-type scanner) #\=)
+ (parse-delimited-fragment
+ scanner #\= '(#\, #\))
+ :keep-end t)))))
+ (make-argument (cdr dtor) (car dtor) dflt))))
+
+ (argument-list ()
+ ;; argument-list ::=
+ ;; [argument [`,' argument]* [`,' argument-tail]]
+ ;; | argument-tail
+ ;;
+ ;; argument-tail ::= `...' | keyword-tail
+ ;;
+ ;; keyword-tail ::= `?' [kw-argument [`,' kw-argument]*]
+ ;;
+ ;; kw-argument ::= argument [= c-fragment]
+ ;;
+ ;; The possibility of a trailing `,' `...' means that we
+ ;; can't use the standard `list' parser. Note that, unlike
+ ;; `real' C, we allow an ellipsis even if there are no
+ ;; explicit arguments.
+
+ (let ((args nil)
+ (keys nil)
+ (keysp nil))
+ (loop
+ (when (eq (token-type scanner) :ellipsis)
+ (push :ellipsis args)
+ (scanner-step scanner)
+ (return))
+ (when (and keywordp (eq (token-type scanner) #\?))
+ (setf keysp t)
+ (scanner-step scanner)
+ (multiple-value-bind (arg winp consumedp)
+ (parse (list (:min 0) (kw-argument) #\,))
+ (declare (ignore consumedp))
+ (unless winp
+ (return-from argument-list (values arg nil t)))
+ (setf keys arg)
+ (return)))
+ (multiple-value-bind (arg winp consumedp)
+ (argument)
+ (unless winp
+ (if (or consumedp args)
+ (return-from argument-list (values arg nil t))
+ (return)))
+ (push arg args))
+ (unless (eq (token-type scanner) #\,)
+ (return))
+ (scanner-step scanner))
+ (values (let ((rargs (nreverse args))
+ (rkeys (nreverse keys)))
+ (if keysp
+ (lambda (ret)
+ (make-keyword-function-type
+ ret rargs rkeys))
+ (lambda (ret)
+ (make-function-type ret rargs))))
+ t
+ (or args keysp))))