New feature: initialization keyword arguments.
[sod] / src / module-parse.lisp
index f6d69ee..35e07ea 100644 (file)
                 (frag (parse-delimited-fragment scanner #\{ #\})))
             (funcall make class frag pset scanner)))))
 
+(define-pluggable-parser class-item initargs (scanner class pset)
+  ;; initarg-item ::= `initarg' declspec+ init-declarator-list
+  ;; init-declarator ::= declarator [`=' initializer]
+  (with-parser-context (token-scanner-context :scanner scanner)
+    (parse (seq ("initarg"
+                (base-type (parse-c-type scanner))
+                (nil (skip-many (:min 1)
+                       (seq ((declarator (parse-declarator scanner
+                                                           base-type))
+                             (init (? (parse-delimited-fragment
+                                       scanner #\= (list #\; #\,)
+                                       :keep-end t))))
+                         (make-sod-user-initarg class
+                                                (cdr declarator)
+                                                (car declarator)
+                                                pset init scanner))
+                       #\,))
+                  #\;)))))
+
 (defun parse-class-body (scanner pset name supers)
   ;; class-body ::= `{' class-item* `}'
   ;;
                                    sub-pset scanner))))
                             #\;)))
 
-              (parse-initializer-item (sub-pset constructor)
+              (parse-initializer-item (sub-pset must-init-p constructor)
                 ;; initializer-item ::=
                 ;;     [`class'] -!- slot-initializer-list `;'
                 ;;
-                ;; slot-initializer ::= id `.' id initializer
-                (parse (and (skip-many ()
-                              (seq ((name-a :id) #\. (name-b :id)
-                                    (init (parse-initializer)))
-                                (funcall constructor class
-                                         name-a name-b init
-                                         sub-pset scanner))
-                              #\,)
-                            #\;)))
+                ;; slot-initializer ::= id `.' id [initializer]
+                (let ((parse-init (if must-init-p
+                                      #'parse-initializer
+                                      (parser () (? (parse-initializer))))))
+                  (parse (and (skip-many ()
+                                (seq ((name-a :id) #\. (name-b :id)
+                                      (init (funcall parse-init)))
+                                  (funcall constructor class
+                                           name-a name-b init
+                                           sub-pset scanner))
+                                #\,)
+                              #\;))))
 
               (class-item-dispatch (sub-pset base-type type name)
                 ;; Logically part of `parse-raw-class-item', but the
                                                             (cdr dc))))))
                            (and "class"
                                 (parse-initializer-item
-                                 sub-pset
+                                 sub-pset t
                                  #'make-sod-class-initializer))
                            (parse-initializer-item
-                            sub-pset
+                            sub-pset nil
                             #'make-sod-instance-initializer)))))
 
        (parse (seq (#\{