@@@ yet more mess
[sod] / src / module-parse.lisp
index eff4af7..43a49ad 100644 (file)
 ;;; External files.
 
 (export 'read-module)
-(defun read-module (pathname &key (truename nil truep) location)
+(defun read-module (pathname &key (truename nil truep) location stream)
   "Parse the file at PATHNAME as a module, returning it.
 
    This is the main entry point for parsing module files.  You may well know
                                  (make-pathname :type "SOD" :case :common)))
   (unless truep (setf truename (truename pathname)))
   (define-module (pathname :location location :truename truename)
-    (with-open-file (f-stream pathname :direction :input)
-      (let* ((char-scanner (make-instance 'charbuf-scanner
-                                         :stream f-stream
-                                         :filename (namestring pathname)))
-            (scanner (make-instance 'sod-token-scanner
-                                    :char-scanner char-scanner)))
-       (with-default-error-location (scanner)
-         (with-parser-context (token-scanner-context :scanner scanner)
-           (multiple-value-bind (result winp consumedp)
-               (parse (skip-many ()
-                         (seq ((pset (parse-property-set scanner))
-                               (nil (error ()
-                                        (plug module scanner pset)
-                                      (skip-until (:keep-end nil)
-                                        #\; #\}))))
-                           (check-unused-properties pset))))
-             (declare (ignore consumedp))
-             (unless winp (syntax-error scanner result)))))))))
+    (flet ((parse (f-stream)
+            (let* ((char-scanner
+                    (make-instance 'charbuf-scanner
+                                   :stream f-stream
+                                   :filename (namestring pathname)))
+                   (scanner (make-instance 'sod-token-scanner
+                                           :char-scanner char-scanner)))
+              (with-default-error-location (scanner)
+                (with-parser-context
+                    (token-scanner-context :scanner scanner)
+                  (multiple-value-bind (result winp consumedp)
+                      (parse (skip-many ()
+                               (seq ((pset (parse-property-set scanner))
+                                     (nil (error ()
+                                            (plug module scanner pset)
+                                            (skip-until (:keep-end nil)
+                                                        #\; #\}))))
+                                    (check-unused-properties pset))))
+                    (declare (ignore consumedp))
+                    (unless winp (syntax-error scanner result))))))))
+      (if stream (parse stream)
+         (with-open-file (stream pathname :direction :input)
+           (parse stream))))))
 
 (define-pluggable-parser module file (scanner pset)
   ;; `import' string `;'
                           (lambda (path true)
                             (handler-case
                                 (let ((module (read-module path
-                                                           :truename true)))
+                                                           :truename true
+                                                           :location
+                                                             (file-location
+                                                              scanner))))
                                   (when module
                                     (module-import module)
                                     (pushnew path (module-files *module*))