chiark / gitweb /
debian/libsod-dev.install: Fix name of manpage.
[sod] / src / module-parse.lisp
index a45892216da5c362beb0b2493576078e30f7ac16..15a7d8f8ffd78e8fde8db41dc73e55c963486339 100644 (file)
@@ -199,6 +199,34 @@ (define-pluggable-parser module lisp (scanner pset)
 
 (export 'class-item)
 
+(define-pluggable-parser class-item initfrags (scanner class pset)
+  ;; raw-class-item ::= frag-keyword `{' c-fragment `}'
+  ;; frag-keyword ::= `init' | `teardown'
+  (with-parser-context (token-scanner-context :scanner scanner)
+    (parse (seq ((make (or (seq ("init") #'make-sod-class-initfrag)
+                          (seq ("teardown") #'make-sod-class-tearfrag)))
+                (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* `}'
   ;;
@@ -253,50 +281,12 @@ (defun parse-class-body (scanner pset name supers)
                                           body sub-pset scanner))))
 
               (parse-initializer ()
-                ;; initializer ::= `=' c-fragment | `=' `{' c-fragment `}'
+                ;; initializer ::= `=' c-fragment
                 ;;
-                ;; Return (VALUE-KIND . VALUE-FORM), ready for passing to a
-                ;; `sod-initializer' constructor.
-
-                ;; This is kind of tricky because we have to juggle both
-                ;; layers of the parsing machinery.  The character scanner
-                ;; will already have consumed the lookahead token (which, if
-                ;; we're going to do anything, is `=').
-                (let ((char-scanner (token-scanner-char-scanner scanner)))
-
-                  ;; First, skip the character-scanner past any whitespace.
-                  ;; We don't record this consumption, which is a bit
-                  ;; naughty, but nobody will actually mind.
-                  (loop
-                    (when (or (scanner-at-eof-p char-scanner)
-                              (not (whitespace-char-p
-                                    (scanner-current-char char-scanner))))
-                      (return))
-                    (scanner-step char-scanner))
-
-                  ;; Now maybe read an initializer.
-                  (cond ((not (eql (token-type scanner) #\=))
-                         ;; It's not an `=' after all.  There's no
-                         ;; initializer.
-                         (values '(#\=) nil nil))
-
-                        ((and (not (scanner-at-eof-p char-scanner))
-                              (char= (scanner-current-char char-scanner)
-                                     #\{))
-                         ;; There's a brace after the `=', so we should
-                         ;; consume the `=' here, and read a compound
-                         ;; initializer enclosed in braces.
-                         (parse (seq (#\= (frag (parse-delimited-fragment
-                                                 scanner #\{ #\})))
-                                  (cons :compound frag))))
-
-                        (t
-                         ;; No brace, so read from the `=' up to, but not
-                         ;; including, the trailing `,' or `;' delimiter.
-                         (parse (seq ((frag (parse-delimited-fragment
-                                             scanner #\= '(#\; #\,)
-                                             :keep-end t)))
-                                  (cons :simple frag)))))))
+                ;; Return a VALUE, ready for passing to a `sod-initializer'
+                ;; constructor.
+                (parse-delimited-fragment scanner #\= (list #\, #\;)
+                                          :keep-end t))
 
               (parse-slot-item (sub-pset base-type type name)
                 ;; slot-item ::=
@@ -310,8 +300,7 @@ (defun parse-class-body (scanner pset name supers)
                                              sub-pset scanner)
                               (when init
                                 (make-sod-instance-initializer
-                                 class nick name (car init) (cdr init)
-                                 sub-pset scanner)))
+                                 class nick name init sub-pset scanner)))
                             (skip-many ()
                               (seq (#\,
                                     (ds (parse-declarator scanner
@@ -321,25 +310,26 @@ (defun parse-class-body (scanner pset name supers)
                                                sub-pset scanner)
                                 (when init
                                   (make-sod-instance-initializer
-                                   class nick (cdr ds)
-                                   (car init) (cdr init)
+                                   class nick (cdr ds) init
                                    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
-                                         (car init) (cdr 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
@@ -370,6 +360,7 @@ (defun parse-class-body (scanner pset name supers)
                 ;;   | method-item
                 ;;   | slot-item
                 ;;   | initializer-item
+                ;;   | initfrag-item
                 ;;
                 ;; Most of the above begin with declspecs and a declarator
                 ;; (which might be dotted).  So we parse that here and
@@ -378,16 +369,17 @@ (defun parse-class-body (scanner pset name supers)
                            (peek
                             (seq ((ds (parse-c-type scanner))
                                   (dc (parse-maybe-dotted-declarator ds))
+                                  (nil (commit))
                                   (nil (class-item-dispatch sub-pset
                                                             ds
                                                             (car dc)
                                                             (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 (#\{