1 ! Copyright (C) 2009 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: xml xml.state kernel sequences fry assocs xml.data
4 accessors strings make multiline parser namespaces macros
5 sequences.deep generalizations locals words combinators
11 : string>chunk ( string -- chunk )
12 t interpolating? [ string>xml-chunk ] with-variable ;
14 : string>doc ( string -- xml )
15 t interpolating? [ string>xml ] with-variable ;
17 DEFER: interpolate-sequence
19 : interpolate-attrs ( table attrs -- attrs )
22 [ var>> _ at dup [ present ] when ] when
23 ] assoc-map [ nip ] assoc-filter ;
25 : interpolate-tag ( table tag -- tag )
27 [ attrs>> interpolate-attrs ]
28 [ children>> [ interpolate-sequence ] [ drop f ] if* ] 2tri
31 GENERIC: push-item ( item -- )
32 M: string push-item , ;
33 M: xml-data push-item , ;
34 M: object push-item present , ;
36 [ dup array? [ % ] [ , ] if ] each ;
38 GENERIC: interpolate-item ( table item -- )
39 M: object interpolate-item nip , ;
40 M: tag interpolate-item interpolate-tag , ;
41 M: interpolated interpolate-item
42 var>> swap at push-item ;
44 : interpolate-sequence ( table seq -- seq )
45 [ [ interpolate-item ] with each ] { } make ;
47 : interpolate-xml-doc ( table xml -- xml )
48 (clone) [ interpolate-tag ] change-body ;
50 GENERIC# (each-interpolated) 1 ( item quot -- ) inline
51 M: interpolated (each-interpolated) call ;
52 M: tag (each-interpolated)
54 [ interpolated? ] filter
56 M: xml (each-interpolated)
57 [ body>> ] dip (each-interpolated) ;
58 M: object (each-interpolated) 2drop ;
60 : each-interpolated ( xml quot -- )
61 '[ _ (each-interpolated) ] deep-each ; inline
63 :: number<-> ( doc -- doc )
65 dup var>> [ n >>var n 1+ n! ] unless drop
66 ] each-interpolated doc ;
68 MACRO: interpolate-xml ( string -- doc )
69 string>doc number<-> '[ _ interpolate-xml-doc ] ;
71 MACRO: interpolate-chunk ( string -- chunk )
72 string>chunk number<-> '[ _ interpolate-sequence ] ;
74 : >search-hash ( seq -- hash )
75 [ dup search ] H{ } map>assoc ;
77 : extract-variables ( xml -- seq )
78 [ [ var>> , ] each-interpolated ] { } make ;
80 : nenum ( ... n -- assoc )
81 narray <enum> ; inline
83 : collect ( accum seq -- accum )
85 { [ dup [ ] all? ] [ >search-hash parsed ] } ! locals
86 { [ dup [ not ] all? ] [ ! fry
87 length parsed \ nenum parsed
89 [ drop "XML interpolation contains both fry and locals" throw ] ! mixed
92 : parse-def ( accum delimiter word -- accum )
94 parse-multiline-string but-last
95 [ string>chunk extract-variables collect ] keep
102 "XML>" \ interpolate-xml parse-def ; parsing
105 "XML]" \ interpolate-chunk parse-def ; parsing