1 ! Copyright (C) 2005, 2009 Daniel Ehrenberg
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences sequences.private assocs arrays
4 delegate.protocols delegate vectors accessors multiline
5 macros words quotations combinators slots fry strings
6 combinators.short-circuit ;
9 TUPLE: interpolated var ;
10 C: <interpolated> interpolated
13 { space maybe{ string } }
15 { url maybe{ string } } ;
18 : ?= ( object/f object/f -- ? )
19 2dup and [ = ] [ 2drop t ] if ;
21 : names-match? ( name1 name2 -- ? )
23 [ [ space>> ] bi@ ?= ]
28 : <simple-name> ( string -- name )
31 : <null-name> ( string -- name )
34 : assure-name ( string/name -- name )
35 dup name? [ <null-name> ] unless ;
37 TUPLE: attrs { alist sequence } ;
40 : attr@ ( key alist -- index {key,value} )
41 [ assure-name ] dip alist>>
42 [ first names-match? ] with find ;
45 attr@ nip [ second t ] [ f f ] if* ;
50 [ assure-name swap 2array ] dip
51 [ alist>> ?push ] keep alist<<
54 M: attrs assoc-size alist>> length ;
55 M: attrs new-assoc drop V{ } new-sequence <attrs> ;
56 M: attrs >alist alist>> ;
58 : >attrs ( assoc -- attrs )
61 [ [ assure-name ] dip ] assoc-map
64 drop dup attrs? [ >attrs ] unless ;
69 [ nip ] [ attr@ drop ] 2bi
70 [ swap alist>> remove-nth! drop ] [ drop ] if* ;
73 alist>> clone <attrs> ;
77 TUPLE: opener { name name } { attrs attrs } ;
80 TUPLE: closer { name name } ;
83 TUPLE: contained { name name } { attrs attrs } ;
84 C: <contained> contained
86 TUPLE: comment { text string } ;
91 TUPLE: element-decl < directive
93 { content-spec string } ;
94 C: <element-decl> element-decl
96 TUPLE: attlist-decl < directive
99 C: <attlist-decl> attlist-decl
101 TUPLE: entity-decl < directive
105 C: <entity-decl> entity-decl
107 TUPLE: system-id { system-literal string } ;
108 C: <system-id> system-id
110 TUPLE: public-id { pubid-literal string } { system-literal string } ;
111 C: <public-id> public-id
113 UNION: id system-id public-id ;
116 { directives sequence }
118 { parameter-entities assoc } ;
121 TUPLE: doctype-decl < directive
123 { external-id maybe{ id } }
124 { internal-subset maybe{ dtd } } ;
125 C: <doctype-decl> doctype-decl
127 TUPLE: notation-decl < directive
130 C: <notation-decl> notation-decl
132 TUPLE: instruction { text string } ;
133 C: <instruction> instruction
138 { standalone boolean } ;
144 { children sequence } ;
146 : <tag> ( name attrs children -- tag )
147 [ assure-name ] [ T{ attrs } assoc-like ] [ ] tri*
150 : attr ( tag/xml name -- string )
153 : set-attr ( tag/xml value name -- )
156 ! They also follow the sequence protocol (for children)
157 CONSULT: sequence-protocol tag children>> ;
158 INSTANCE: tag sequence
160 CONSULT: name tag name>> ;
164 [ name>> ] keep attrs>>
165 rot dup [ V{ } like ] when <tag>
168 MACRO: clone-slots ( class -- tuple )
171 [ name>> reader-word '[ _ execute clone ] ] map
173 ] [ '[ _ boa ] ] bi compose ;
185 CONSULT: sequence-protocol xml body>> ;
186 INSTANCE: xml sequence
188 CONSULT: tag xml body>> ;
190 CONSULT: name xml body>> ;
193 : tag>xml ( xml tag -- newxml )
194 [ [ prolog>> ] [ before>> ] [ after>> ] tri ] dip
197 : sequence>xml ( xml seq -- newxml )
198 over body>> like tag>xml ;
205 swap dup xml? [ nip ] [
206 dup tag? [ tag>xml ] [ sequence>xml ] if
209 ! tag with children=f is contained
210 : <contained-tag> ( name attrs -- tag )
213 PREDICATE: contained-tag < tag children>> not ;
214 PREDICATE: open-tag < tag children>> ;
216 TUPLE: unescaped string ;
217 C: <unescaped> unescaped
220 tag comment string directive instruction unescaped ;
222 TUPLE: xml-chunk seq ;
223 C: <xml-chunk> xml-chunk
225 CONSULT: sequence-protocol xml-chunk seq>> ;
226 INSTANCE: xml-chunk sequence