! Copyright (C) 2005, 2006 Daniel Ehrenberg ! See http://factorcode.org/license.txt for BSD license. USING: kernel sequences sequences.private assocs arrays delegate.protocols delegate vectors accessors multiline macros words quotations combinators slots ; IN: xml.data TUPLE: name space main url ; C: name : ?= ( object/f object/f -- ? ) 2dup and [ = ] [ 2drop t ] if ; : names-match? ( name1 name2 -- ? ) [ [ space>> ] bi@ ?= ] [ [ url>> ] bi@ ?= ] [ [ main>> ] bi@ ?= ] 2tri and and ; : ( string -- name ) f swap f ; : assure-name ( string/name -- name ) dup name? [ ] unless ; TUPLE: opener name attrs ; C: opener TUPLE: closer name ; C: closer TUPLE: contained name attrs ; C: contained TUPLE: comment text ; C: comment TUPLE: directive text ; C: directive TUPLE: instruction text ; C: instruction TUPLE: prolog version encoding standalone ; C: prolog TUPLE: attrs alist ; C: attrs : attr@ ( key alist -- index {key,value} ) >r assure-name r> alist>> [ first names-match? ] with find ; M: attrs at* attr@ nip [ second t ] [ f f ] if* ; M: attrs set-at 2dup attr@ nip [ 2nip set-second ] [ >r assure-name swap 2array r> [ alist>> ?push ] keep (>>alist) ] if* ; M: attrs assoc-size alist>> length ; M: attrs new-assoc drop V{ } new-sequence ; M: attrs >alist alist>> ; : >attrs ( assoc -- attrs ) dup [ V{ } assoc-clone-like [ >r assure-name r> ] assoc-map ] when ; M: attrs assoc-like drop dup attrs? [ >attrs ] unless ; M: attrs clear-assoc f >>alist drop ; M: attrs delete-at tuck attr@ drop [ swap alist>> delete-nth ] [ drop ] if* ; M: attrs clone alist>> clone ; INSTANCE: attrs assoc TUPLE: tag name attrs children ; : ( name attrs children -- tag ) [ assure-name ] [ T{ attrs } assoc-like ] [ ] tri* tag boa ; ! For convenience, tags follow the assoc protocol too (for attrs) CONSULT: assoc-protocol tag attrs>> ; INSTANCE: tag assoc ! They also follow the sequence protocol (for children) CONSULT: sequence-protocol tag children>> ; INSTANCE: tag sequence CONSULT: name tag name>> ; M: tag like over tag? [ drop ] [ [ name>> ] keep attrs>> rot dup [ V{ } like ] when ] if ; MACRO: clone-slots ( class -- tuple ) [ "slots" word-prop [ name>> reader-word 1quotation [ clone ] compose ] map [ cleave ] curry ] [ [ boa ] curry ] bi compose ; M: tag clone tag clone-slots ; TUPLE: xml prolog before body after ; C: xml CONSULT: sequence-protocol xml body>> ; INSTANCE: xml sequence CONSULT: assoc-protocol xml body>> ; INSTANCE: xml assoc CONSULT: tag xml body>> ; CONSULT: name xml body>> ; xml ( xml tag -- newxml ) >r [ prolog>> ] [ before>> ] [ after>> ] tri r> swap ; : seq>xml ( xml seq -- newxml ) over body>> like tag>xml ; PRIVATE> M: xml clone xml clone-slots ; M: xml like swap dup xml? [ nip ] [ dup tag? [ tag>xml ] [ seq>xml ] if ] if ; ! tag with children=f is contained : ( name attrs -- tag ) f ; PREDICATE: contained-tag < tag children>> not ; PREDICATE: open-tag < tag children>> ;