Static instance support.
[sod] / src / module-parse.lisp
index fed98f8..eff4af7 100644 (file)
@@ -52,6 +52,7 @@
 
 (define-pluggable-parser module code (scanner pset)
   ;; `code' id `:' item-name [constraints] `{' c-fragment `}'
+  ;; `code' id `:' constraints `;'
   ;;
   ;; constraints ::= `[' list[constraint] `]'
   ;; constraint ::= item-name+
             (item ()
               (parse (or (kw)
                          (seq (#\( (names (list (:min 1) (kw))) #\))
-                           names)))))
+                           names))))
+            (constraints ()
+              (parse (seq (#\[
+                           (constraints
+                            (list ()
+                              (list (:min 1)
+                                (error (:ignore-unconsumed t) (item)
+                                  (skip-until () :id #\( #\, #\])))
+                              #\,))
+                           #\])
+                       constraints)))
+            (fragment ()
+              (parse-delimited-fragment scanner #\{ #\})))
       (parse (seq ("code"
                   (reason (must (kw)))
                   (nil (must #\:))
-                  (name (must (item)))
-                  (constraints (? (seq (#\[
-                                        (constraints
-                                         (list ()
-                                           (list (:min 1)
-                                             (error (:ignore-unconsumed t)
-                                                 (item)
-                                               (skip-until ()
-                                                 :id #\( #\, #\])))
-                                           #\,))
-                                        #\])
-                                    constraints)))
-                  (fragment (parse-delimited-fragment scanner #\{ #\})))
-              (when name
-                (add-to-module *module*
-                               (make-instance 'code-fragment-item
-                                              :fragment fragment
-                                              :constraints constraints
-                                              :reason reason
-                                              :name name))))))))
+                  (item (or (seq ((constraints (constraints))
+                                  (nil (must #\;)))
+                              (make-instance 'code-fragment-item
+                                             :reason reason
+                                             :constraints constraints))
+                            (seq ((name (must (item)))
+                                  (constraints (? (constraints)))
+                                  (fragment (fragment)))
+                              (and name
+                                   (make-instance 'code-fragment-item
+                                                  :reason reason
+                                                  :constraints constraints
+                                                  :name name
+                                                  :fragment fragment))))))
+              (when item (add-to-module *module* item)))))))
 
 ;;; External files.
 
             (eval sexp)))))
 
 ;;;--------------------------------------------------------------------------
+;;; Static instances.
+
+(define-pluggable-parser module instance (scanner pset)
+  ;; `instance' id id list[slot-initializer] `;'
+  (with-parser-context (token-scanner-context :scanner scanner)
+    (let ((duff nil)
+         (floc nil)
+         (empty-pset (make-property-set)))
+      (parse (seq ("instance"
+                  (class (seq ((class-name (must :id)))
+                           (setf floc (file-location scanner))
+                           (restart-case (find-sod-class class-name)
+                             (continue ()
+                               (setf duff t)
+                               nil))))
+                  (name (must :id))
+                  (inits (? (seq (#\:
+                                  (inits (list (:min 0)
+                                           (seq ((nick (must :id))
+                                                 #\.
+                                                 (name (must :id))
+                                                 (value
+                                                  (parse-delimited-fragment
+                                                   scanner #\= '(#\, #\;)
+                                                   :keep-end t)))
+                                             (make-sod-instance-initializer
+                                              class nick name value
+                                              empty-pset
+                                              :add-to-class nil
+                                              :location scanner))
+                                           #\,)))
+                              inits)))
+                  #\;)
+              (unless duff
+                (acond ((find-if (lambda (item)
+                                   (and (typep item 'static-instance)
+                                        (string= (static-instance-name item)
+                                                 name)))
+                                 (module-items *module*))
+                        (cerror*-with-location floc
+                                               "Instance with name `~A' ~
+                                                already defined."
+                                               name)
+                        (info-with-location (file-location it)
+                                            "Previous definition was ~
+                                             here."))
+                       (t
+                        (add-to-module *module*
+                                       (make-static-instance class name
+                                                             inits
+                                                             pset
+                                                             floc))))))))))
+
+;;;--------------------------------------------------------------------------
 ;;; Class declarations.
 
 (export 'class-item)