chiark / gitweb /
src/module-parse.lisp: Catch errors during class-item construction.
[sod] / src / module-parse.lisp
index b72d7c80a25638cafbdbc8ade61dd0096962956c..15bfe87161fc113df1256ada44388f9a4fa86142 100644 (file)
@@ -36,14 +36,17 @@ (define-pluggable-parser module typename (scanner pset)
   (with-parser-context (token-scanner-context :scanner scanner)
     (parse (and "typename"
                (skip-many ()
-                 (seq ((id :id))
-                   (if (gethash id *module-type-map*)
-                       (cerror* "Type `~A' already defined" id)
-                       (add-to-module *module*
-                                      (make-instance 'type-item
-                                                     :name id))))
+                 (error ()
+                     (seq ((id :id))
+                       (if (or (gethash id *module-type-map*)
+                               (find-simple-c-type id))
+                           (cerror* "Type `~A' already defined" id)
+                           (add-to-module *module*
+                                          (make-instance 'type-item
+                                                         :name id))))
+                   (skip-until () #\, #\;))
                  #\,)
-               #\;))))
+               (must #\;)))))
 
 ;;; Fragments.
 
@@ -63,23 +66,28 @@ (define-pluggable-parser module code (scanner pset)
                          (seq (#\( (names (list (:min 1) (kw))) #\))
                            names)))))
       (parse (seq ("code"
-                  (reason (kw))
-                  #\:
-                  (name (item))
+                  (reason (must (kw)))
+                  (nil (must #\:))
+                  (name (must (item)))
                   (constraints (? (seq (#\[
-                                        (constraints (list (:min 1)
-                                                       (list (:min 1)
-                                                         (item))
-                                                       #\,))
+                                        (constraints
+                                         (list ()
+                                           (list (:min 1)
+                                             (error (:ignore-unconsumed t)
+                                                 (item)
+                                               (skip-until ()
+                                                 :id #\( #\, #\])))
+                                           #\,))
                                         #\])
                                     constraints)))
                   (fragment (parse-delimited-fragment scanner #\{ #\})))
-              (add-to-module *module*
-                             (make-instance 'code-fragment-item
-                                            :fragment fragment
-                                            :constraints constraints
-                                            :reason reason
-                                            :name name)))))))
+              (when name
+                (add-to-module *module*
+                               (make-instance 'code-fragment-item
+                                              :fragment fragment
+                                              :constraints constraints
+                                              :reason reason
+                                              :name name))))))))
 
 ;;; External files.
 
@@ -124,7 +132,7 @@ (define-pluggable-parser module test (scanner pset)
   ;; `demo' string `;'
   (declare (ignore pset))
   (with-parser-context (token-scanner-context :scanner scanner)
-    (parse (seq ("demo" (string :string) #\;)
+    (parse (seq ("demo" (string (must :string)) (nil (must #\;)))
             (format t ";; DEMO ~S~%" string)))))
 
 (define-pluggable-parser module file (scanner pset)
@@ -132,14 +140,15 @@ (define-pluggable-parser module file (scanner pset)
   ;; `load' string `;'
   (declare (ignore pset))
   (flet ((common (name type what thunk)
-          (find-file scanner
-                     (merge-pathnames name
-                                      (make-pathname :type type
-                                                     :case :common))
-                     what
-                     thunk)))
+          (when name
+            (find-file scanner
+                       (merge-pathnames name
+                                        (make-pathname :type type
+                                                       :case :common))
+                       what
+                       thunk))))
     (with-parser-context (token-scanner-context :scanner scanner)
-      (parse (or (seq ("import" (name :string) #\;)
+      (parse (or (seq ("import" (name (must :string)) (nil (must #\;)))
                   (common name "SOD" "module"
                           (lambda (path true)
                             (handler-case
@@ -152,8 +161,12 @@ (define-pluggable-parser module file (scanner pset)
                                               *module*))))
                               (file-error (error)
                                 (cerror* "Error reading module ~S: ~A"
+                                         path error))
+                              (error (error)
+                                (cerror* "Unexpected error reading ~
+                                          module ~S: ~A"
                                          path error))))))
-                (seq ("load" (name :string) #\;)
+                (seq ("load" (name (must :string)) (nil (must #\;)))
                   (common name "LISP" "Lisp file"
                           (lambda (path true)
                             (handler-case
@@ -198,7 +211,7 @@ (define-pluggable-parser module lisp (scanner pset)
                             (scanner-step scanner)
                             (values sexp t t))
                           (values '((:id "lisp")) nil nil)))
-                #\;)
+                (nil (must #\;)))
             (eval sexp)))))
 
 ;;;--------------------------------------------------------------------------
@@ -232,18 +245,32 @@ (define-pluggable-parser class-item initargs (scanner class pset)
                                                 (car declarator)
                                                 pset init scanner))
                        #\,))
-                  #\;)))))
+                (nil (must #\;)))))))
+
+(defun synthetic-name ()
+  "Return an obviously bogus synthetic not-identifier."
+  (let ((ix *temporary-index*))
+    (incf *temporary-index*)
+    (make-instance 'temporary-variable :tag (format nil "%%#~A" ix))))
 
 (defun parse-class-body (scanner pset name supers)
   ;; class-body ::= `{' class-item* `}'
   ;;
   ;; class-item ::= property-set raw-class-item
   (with-parser-context (token-scanner-context :scanner scanner)
-    (make-class-type name)
-    (let* ((duff nil)
-          (class (make-sod-class name
+    (when name (make-class-type name))
+    (let* ((duff (null name))
+          (synthetic-name (or name
+                              (let ((var (synthetic-name)))
+                                (unless pset
+                                  (setf pset (make-property-set)))
+                                (unless (pset-get pset "nick")
+                                  (add-property pset "nick" var :type :id))
+                                var)))
+          (class (make-sod-class synthetic-name
                                  (restart-case
-                                     (mapcar #'find-sod-class supers)
+                                     (mapcar #'find-sod-class
+                                             (or supers (list "SodObject")))
                                    (continue ()
                                      (setf duff t)
                                      (list (find-sod-class "SodObject"))))
@@ -290,8 +317,10 @@ (defun parse-class-body (scanner pset name supers)
                 (parse (seq ((body (or (seq ("extern" #\;) nil)
                                        (parse-delimited-fragment
                                         scanner #\{ #\}))))
-                         (make-sod-method class sub-nick name type
-                                          body sub-pset scanner))))
+                         (restart-case
+                             (make-sod-method class sub-nick name type
+                                              body sub-pset scanner)
+                           (continue () :report "Continue")))))
 
               (parse-initializer ()
                 ;; initializer ::= `=' c-fragment
@@ -307,24 +336,27 @@ (defun parse-class-body (scanner pset name supers)
                 ;;             [`,' list[init-declarator]] `;'
                 ;;
                 ;; init-declarator ::= declarator [initializer]
-                (parse (and (seq ((init (? (parse-initializer))))
-                              (make-sod-slot class name type
-                                             sub-pset scanner)
-                              (when init
-                                (make-sod-instance-initializer
-                                 class nick name init sub-pset scanner)))
-                            (skip-many ()
-                              (seq (#\,
-                                    (ds (parse-declarator scanner
-                                                          base-type))
-                                    (init (? (parse-initializer))))
-                                (make-sod-slot class (cdr ds) (car ds)
-                                               sub-pset scanner)
-                                (when init
-                                  (make-sod-instance-initializer
-                                   class nick (cdr ds) init
-                                   sub-pset scanner))))
-                            #\;)))
+                (flet ((make-it (name type init)
+                         (restart-case
+                             (progn
+                               (make-sod-slot class name type
+                                              sub-pset scanner)
+                               (when init
+                                 (make-sod-instance-initializer class
+                                                                nick name
+                                                                init
+                                                                sub-pset
+                                                                scanner)))
+                           (continue () :report "Continue"))))
+                  (parse (and (seq ((init (? (parse-initializer))))
+                                (make-it name type init))
+                              (skip-many ()
+                                (seq (#\,
+                                      (ds (parse-declarator scanner
+                                                            base-type))
+                                      (init (? (parse-initializer))))
+                                  (make-it (cdr ds) (car ds) init)))
+                              #\;))))
 
               (parse-initializer-item (sub-pset must-init-p constructor)
                 ;; initializer-item ::=
@@ -336,9 +368,11 @@ (defun parse-class-body (scanner pset name supers)
                   (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))
+                                  (restart-case
+                                      (funcall constructor class
+                                               name-a name-b init
+                                               sub-pset scanner)
+                                    (continue () :report "Continue")))
                                 #\,)
                               #\;))))
 
@@ -406,11 +440,12 @@ (define-pluggable-parser module class (scanner pset)
   ;; `class' id `;'
   (with-parser-context (token-scanner-context :scanner scanner)
     (parse (seq ("class"
-                (name :id)
+                (name (must :id))
                 (nil (or (seq (#\;)
-                           (make-class-type name))
-                         (seq ((supers (seq (#\: (ids (list () :id #\,)))
-                                         ids))
+                           (when name (make-class-type name)))
+                         (seq ((supers (must (seq (#\:
+                                                   (ids (list () :id #\,)))
+                                               ids)))
                                (nil (parse-class-body
                                      scanner
                                      pset name supers)))))))))))