(in-package #:oh-ducks) (defmethod unify ((a css-selector-template) (b css-selector-template) &optional (env (make-empty-environment)) &key) (declare (ignore env)) (error 'unification-failure :format-control "Do not know how to unify the two css-selector-templates ~S and ~S." :format-arguments (list a b))) (defmethod unify ((template css-selector-template) document &optional (env (make-empty-environment)) &key) (declare (optimize debug)) (loop :for (css-specifier . template) :in (specifiers template) :do (typecase template ;; CSS selectors work backwards, not forwards (css-selector-template (unify template document env)) (t (let* ((*implicit-element* document) ;; FIXME: this is UGLY! (val (cond ((terminating-implicit-sibling-combinator-p css-specifier) ;; search remaining siblings (subjects-in-list css-specifier (rest (member document (when-let* ((parent (element-parent document))) (element-children parent)) :test #'eq)))) ;; search subelements ;;; FIXME: this assumes if someone passes us a node they want to find ;;; subelements of that node. In the case of nested matches, that's probably ;;; true, but it hardly seems fair to assume it. Really we want some sort of ;;; descendant combinator to be sure, but the general one (#\Space) doesn't ;;; exactly show up all that well. Somebody might assume " b" was the same as ;;; "b" and get confused. ((element-parent document) (subjects-in-list css-specifier (element-children document))) ;; root element includes itself (t (subjects-of css-specifier document))))) (cond ((null val) (error 'unification-failure :format-control "Unable to unify ~s and ~s" :format-arguments (list css-specifier template))) ((unify::template-p template) (unify template val env)) ((unify::variablep template) (unify::var-unify template val env)) (t (error "Don't know what to do with selector ~s and template ~s." css-specifier template))))))) env) (defmethod unify (document (template css-selector-template) &optional (env (make-empty-environment)) &key) (unify template document env)) (defmethod unify ((template css-selector-template) (document string) &optional (env (make-empty-environment)) &key) (unify template (funcall (slot-value template 'parser) document) env)) (defmethod unify ((template css-selector-template) (document pathname) &optional (env (make-empty-environment)) &key) (unify template (funcall (slot-value template 'parser) document) env))