|
|
|
@ -6,15 +6,15 @@
|
|
|
|
|
(define/contract (atomize qx)
|
|
|
|
|
;; normalize a qexpr by reducing it to one-character quads.
|
|
|
|
|
;; propagate attrs downward by appending to front of attrs list.
|
|
|
|
|
;; at then end, duplicates are removed, with frontmost attrs (= added later) given preference
|
|
|
|
|
;; ok to have duplicate attrs (leftmost attr takes precedence)
|
|
|
|
|
(qexpr? . -> . (listof qexpr?))
|
|
|
|
|
(let loop ([x qx][attrs null])
|
|
|
|
|
(match x
|
|
|
|
|
[(? string?) (for/list ([c (in-string x)]) ;; strings are exploded
|
|
|
|
|
(qexpr attrs (string c)))]
|
|
|
|
|
(qexpr attrs (string c)))]
|
|
|
|
|
[(list (? symbol?) (? txexpr-attrs? new-attrs) xs ...) ;; qexprs with attributes are recursed
|
|
|
|
|
(append* (for/list ([x (in-list xs)])
|
|
|
|
|
(loop x (append new-attrs attrs))))]
|
|
|
|
|
(loop x (append new-attrs attrs))))]
|
|
|
|
|
[(list (? symbol? tag) xs ...) (loop (list* tag null xs) attrs)] ;; qexprs without attributes get null attrs
|
|
|
|
|
[else (raise-argument-error 'atomize "valid item" x)])))
|
|
|
|
|
|
|
|
|
@ -34,9 +34,9 @@
|
|
|
|
|
(q ((k "v")) "o")
|
|
|
|
|
(q ((k "v")) "u")))
|
|
|
|
|
(check-equal? (atomize '(q ((k1 "v1")(k2 "42")) "Hi " (q ((k1 "v2")(k3 "foo")) "You")))
|
|
|
|
|
'((q ((k1 "v1")(k2 "42")) "H")
|
|
|
|
|
(q ((k1 "v1")(k2 "42")) "i")
|
|
|
|
|
(q ((k1 "v1")(k2 "42")) " ")
|
|
|
|
|
(q ((k1 "v2")(k3 "foo")(k2 "42")) "Y")
|
|
|
|
|
(q ((k1 "v2")(k3 "foo")(k2 "42")) "o")
|
|
|
|
|
(q ((k1 "v2")(k3 "foo")(k2 "42")) "u"))))
|
|
|
|
|
'((q ((k1 "v1") (k2 "42")) "H")
|
|
|
|
|
(q ((k1 "v1") (k2 "42")) "i")
|
|
|
|
|
(q ((k1 "v1") (k2 "42")) " ")
|
|
|
|
|
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "Y")
|
|
|
|
|
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "o")
|
|
|
|
|
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "u"))))
|