chiark / gitweb /
src/module-parse.lisp: Report an error if the top-level parse fails.
[sod] / src / module-parse.lisp
index f6d69eed1a51323c81bf6ae439d78b20c3225e22..9fa9a1fd1c3a5146e7f051bb25723f10f3fc10f0 100644 (file)
@@ -101,17 +101,21 @@ (defun read-module (pathname &key (truename nil truep) location)
   (define-module (pathname :location location :truename truename)
     (with-open-file (f-stream pathname :direction :input)
       (let* ((*readtable* (copy-readtable))
+            (*package* (find-package '#:sod-user))
             (char-scanner (make-instance 'charbuf-scanner
                                          :stream f-stream))
             (scanner (make-instance 'sod-token-scanner
                                     :char-scanner char-scanner)))
        (with-default-error-location (scanner)
          (with-parser-context (token-scanner-context :scanner scanner)
-           (parse (skip-many ()
-                    (seq ((pset (parse-property-set scanner))
-                          (nil (error ()
-                                 (plug module scanner pset))))
-                      (check-unused-properties pset))))))))))
+           (multiple-value-bind (result winp consumedp)
+               (parse (skip-many ()
+                         (seq ((pset (parse-property-set scanner))
+                               (nil (error ()
+                                      (plug module scanner pset))))
+                           (check-unused-properties pset))))
+             (declare (ignore consumedp))
+             (unless winp (syntax-error scanner result)))))))))
 
 (define-pluggable-parser module test (scanner pset)
   ;; `demo' string `;'
@@ -208,6 +212,25 @@ (define-pluggable-parser class-item initfrags (scanner class pset)
                 (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* `}'
   ;;
@@ -295,19 +318,22 @@ (defun parse-class-body (scanner pset name supers)
                                    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
@@ -347,16 +373,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 (#\{