| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | ! Copyright (C) 2005, 2009 Daniel Ehrenberg | 
					
						
							| 
									
										
										
										
											2009-01-19 23:25:15 -05:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2009-05-15 00:23:06 -04:00
										 |  |  | USING: words assocs kernel accessors parser vocabs.parser effects.parser | 
					
						
							|  |  |  | sequences summary lexer splitting combinators locals | 
					
						
							| 
									
										
										
										
											2009-03-22 22:38:06 -04:00
										 |  |  | memoize sequences.deep xml.data xml.state xml namespaces present | 
					
						
							|  |  |  | arrays generalizations strings make math macros multiline | 
					
						
							|  |  |  | inverse combinators.short-circuit sorting fry unicode.categories | 
					
						
							|  |  |  | effects ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | IN: xml.syntax | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: no-tag name word ;
 | 
					
						
							|  |  |  | M: no-tag summary | 
					
						
							|  |  |  |     drop "The tag-dispatching word has no method for the given tag name" ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compile-tags ( word xtable -- quot )
 | 
					
						
							|  |  |  |     >alist swap '[ _ no-tag boa throw ] suffix
 | 
					
						
							|  |  |  |     '[ dup main>> _ case ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-22 19:37:28 -04:00
										 |  |  | : define-tags ( word effect -- )
 | 
					
						
							|  |  |  |     [ dup dup "xtable" word-prop compile-tags ] dip define-declared ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | :: define-tag ( string word quot -- )
 | 
					
						
							|  |  |  |     quot string word "xtable" word-prop set-at
 | 
					
						
							| 
									
										
										
										
											2009-03-22 22:38:06 -04:00
										 |  |  |     word word stack-effect define-tags ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: TAGS: | 
					
						
							| 
									
										
										
										
											2009-03-22 22:38:06 -04:00
										 |  |  |     CREATE-WORD complete-effect | 
					
						
							| 
									
										
										
										
											2009-03-22 19:37:28 -04:00
										 |  |  |     [ drop H{ } clone "xtable" set-word-prop ] | 
					
						
							|  |  |  |     [ define-tags ] | 
					
						
							|  |  |  |     2bi ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: TAG: | 
					
						
							|  |  |  |     scan scan-word parse-definition define-tag ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 22:17:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: XML-NS: | 
					
						
							| 
									
										
										
										
											2009-03-22 19:37:28 -04:00
										 |  |  |     CREATE-WORD scan '[ f swap _ <name> ] (( string -- name )) define-memoized ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | : each-attrs ( attrs quot -- )
 | 
					
						
							|  |  |  |     [ values [ interpolated? ] filter ] dip each ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (each-interpolated) ( item quot: ( interpolated -- ) -- )
 | 
					
						
							|  |  |  |      { | 
					
						
							|  |  |  |         { [ over interpolated? ] [ call ] } | 
					
						
							|  |  |  |         { [ over tag? ] [ [ attrs>> ] dip each-attrs ] } | 
					
						
							|  |  |  |         { [ over attrs? ] [ each-attrs ] } | 
					
						
							|  |  |  |         { [ over xml? ] [ [ body>> ] dip (each-interpolated) ] } | 
					
						
							|  |  |  |         [ 2drop ] | 
					
						
							|  |  |  |      } cond ; inline recursive
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : each-interpolated ( xml quot -- )
 | 
					
						
							|  |  |  |     '[ _ (each-interpolated) ] deep-each ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : has-interpolated? ( xml -- ? )
 | 
					
						
							|  |  |  |     ! If this becomes a performance problem, it can be improved | 
					
						
							|  |  |  |     f swap [ 2drop t ] each-interpolated ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : when-interpolated ( xml quot -- genquot )
 | 
					
						
							|  |  |  |     [ dup has-interpolated? ] dip [ '[ _ swap ] ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-26 17:11:30 -05:00
										 |  |  | : string>chunk ( string -- chunk )
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  |     t interpolating? [ string>xml-chunk ] with-variable ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-26 17:11:30 -05:00
										 |  |  | : string>doc ( string -- xml )
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  |     t interpolating? [ string>xml ] with-variable ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFER: interpolate-sequence | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | : get-interpolated ( interpolated -- quot )
 | 
					
						
							|  |  |  |     var>> '[ [ _ swap at ] keep ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ?present ( object -- string )
 | 
					
						
							|  |  |  |     dup [ present ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : interpolate-attr ( key value -- quot )
 | 
					
						
							|  |  |  |     dup interpolated? | 
					
						
							|  |  |  |     [ get-interpolated '[ _ swap @ [ ?present 2array ] dip ] ] | 
					
						
							|  |  |  |     [ 2array '[ _ swap ] ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | : filter-nulls ( assoc -- newassoc )
 | 
					
						
							|  |  |  |     [ nip ] assoc-filter ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : interpolate-attrs ( attrs -- quot )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ [ interpolate-attr ] { } assoc>map [ ] join ] | 
					
						
							|  |  |  |         [ assoc-size ] bi
 | 
					
						
							|  |  |  |         '[ @ _ swap [ narray filter-nulls <attrs> ] dip ] | 
					
						
							|  |  |  |     ] when-interpolated ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : interpolate-tag ( tag -- quot )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ name>> ] | 
					
						
							|  |  |  |         [ attrs>> interpolate-attrs ] | 
					
						
							|  |  |  |         [ children>> interpolate-sequence ] tri
 | 
					
						
							|  |  |  |         '[ _ swap @ @ [ <tag> ] dip ] | 
					
						
							|  |  |  |     ] when-interpolated ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | GENERIC: push-item ( item -- )
 | 
					
						
							|  |  |  | M: string push-item , ;
 | 
					
						
							| 
									
										
										
										
											2009-01-27 01:03:42 -05:00
										 |  |  | M: xml-data push-item , ;
 | 
					
						
							|  |  |  | M: object push-item present , ;
 | 
					
						
							| 
									
										
										
										
											2009-01-26 17:48:14 -05:00
										 |  |  | M: sequence push-item | 
					
						
							| 
									
										
										
										
											2009-01-28 15:33:33 -05:00
										 |  |  |     dup xml-data? [ , ] [ [ push-item ] each ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-01-27 14:34:14 -05:00
										 |  |  | M: number push-item present , ;
 | 
					
						
							| 
									
										
										
										
											2009-01-28 15:33:33 -05:00
										 |  |  | M: xml-chunk push-item % ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | : concat-interpolate ( array -- newarray )
 | 
					
						
							|  |  |  |     [ [ push-item ] each ] { } make ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | GENERIC: interpolate-item ( item -- quot )
 | 
					
						
							|  |  |  | M: object interpolate-item [ swap ] curry ;
 | 
					
						
							|  |  |  | M: tag interpolate-item interpolate-tag ;
 | 
					
						
							|  |  |  | M: interpolated interpolate-item get-interpolated ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | : interpolate-sequence ( seq -- quot )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ [ interpolate-item ] map concat ] | 
					
						
							|  |  |  |         [ length ] bi
 | 
					
						
							|  |  |  |         '[ @ _ swap [ narray concat-interpolate ] dip ] | 
					
						
							|  |  |  |     ] when-interpolated ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | GENERIC: [interpolate-xml] ( xml -- quot )
 | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 18:29:35 -05:00
										 |  |  | M: xml [interpolate-xml] | 
					
						
							|  |  |  |     dup body>> interpolate-tag | 
					
						
							|  |  |  |     '[ _ (clone) swap @ drop >>body ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: xml-chunk [interpolate-xml] | 
					
						
							|  |  |  |     interpolate-sequence | 
					
						
							|  |  |  |     '[ @ drop <xml-chunk> ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MACRO: interpolate-xml ( xml -- quot )
 | 
					
						
							|  |  |  |     [interpolate-xml] ;
 | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-27 15:33:43 -05:00
										 |  |  | : number<-> ( doc -- dup )
 | 
					
						
							|  |  |  |     0 over [ | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  |         dup var>> [ | 
					
						
							| 
									
										
										
										
											2009-08-13 20:21:44 -04:00
										 |  |  |             over >>var [ 1 + ] dip
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  |         ] unless drop
 | 
					
						
							| 
									
										
										
										
											2009-01-27 15:33:43 -05:00
										 |  |  |     ] each-interpolated drop ;
 | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | : >search-hash ( seq -- hash )
 | 
					
						
							|  |  |  |     [ dup search ] H{ } map>assoc ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : extract-variables ( xml -- seq )
 | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  |     [ [ var>> , ] each-interpolated ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-26 17:11:30 -05:00
										 |  |  | : nenum ( ... n -- assoc )
 | 
					
						
							|  |  |  |     narray <enum> ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  | : collect ( accum variables -- accum ? )
 | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  |         { [ dup empty? ] [ drop f ] } ! Just a literal | 
					
						
							|  |  |  |         { [ dup [ ] all? ] [ >search-hash parsed t ] } ! locals | 
					
						
							|  |  |  |         { [ dup [ not ] all? ] [ length parsed \ nenum parsed t ] } ! fry | 
					
						
							| 
									
										
										
										
											2009-01-26 00:52:25 -05:00
										 |  |  |         [ drop "XML interpolation contains both fry and locals" throw ] ! mixed | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  | : parse-def ( accum delimiter quot -- accum )
 | 
					
						
							| 
									
										
										
										
											2009-01-29 14:33:04 -05:00
										 |  |  |     [ parse-multiline-string [ blank? ] trim ] dip call
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:17:20 -05:00
										 |  |  |     [ extract-variables collect ] keep swap
 | 
					
						
							|  |  |  |     [ number<-> parsed ] dip
 | 
					
						
							|  |  |  |     [ \ interpolate-xml parsed ] when ; inline
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: <XML | 
					
						
							|  |  |  |     "XML>" [ string>doc ] parse-def ;
 | 
					
						
							| 
									
										
										
										
											2009-01-25 22:06:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: [XML | 
					
						
							|  |  |  |     "XML]" [ string>chunk ] parse-def ;
 | 
					
						
							| 
									
										
										
										
											2009-02-05 15:21:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-13 16:10:34 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-05 15:21:36 -05:00
										 |  |  | : remove-blanks ( seq -- newseq )
 | 
					
						
							|  |  |  |     [ { [ string? not ] [ [ blank? ] all? not ] } 1|| ] filter ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: >xml ( xml -- tag )
 | 
					
						
							|  |  |  | M: xml >xml body>> ;
 | 
					
						
							|  |  |  | M: tag >xml ;
 | 
					
						
							|  |  |  | M: xml-chunk >xml | 
					
						
							|  |  |  |     remove-blanks | 
					
						
							|  |  |  |     [ length 1 =/fail ] | 
					
						
							|  |  |  |     [ first dup tag? [ fail ] unless ] bi ;
 | 
					
						
							|  |  |  | M: object >xml fail ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : 1chunk ( object -- xml-chunk )
 | 
					
						
							|  |  |  |     1array <xml-chunk> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: >xml-chunk ( xml -- chunk )
 | 
					
						
							|  |  |  | M: xml >xml-chunk body>> 1chunk ;
 | 
					
						
							|  |  |  | M: xml-chunk >xml-chunk ;
 | 
					
						
							|  |  |  | M: object >xml-chunk 1chunk ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: [undo-xml] ( xml -- quot )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: xml [undo-xml] | 
					
						
							|  |  |  |     body>> [undo-xml] '[ >xml @ ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: xml-chunk [undo-xml] | 
					
						
							|  |  |  |     seq>> [undo-xml] '[ >xml-chunk @ ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : undo-attrs ( attrs -- quot: ( attrs -- ) )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ main>> ] dip dup interpolated? | 
					
						
							|  |  |  |         [ var>> '[ _ attr _ set ] ] | 
					
						
							|  |  |  |         [ '[ _ attr _ =/fail ] ] if
 | 
					
						
							|  |  |  |     ] { } assoc>map '[ _ cleave ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: tag [undo-xml] ( tag -- quot: ( tag -- ) )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [ name>> main>> '[ name>> main>> _ =/fail ] ] | 
					
						
							|  |  |  |         [ attrs>> undo-attrs ]  | 
					
						
							|  |  |  |         [ children>> [undo-xml] '[ children>> @ ] ] | 
					
						
							|  |  |  |     } cleave '[ _ _ _ tri ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : firstn-strong ( seq n -- ... )
 | 
					
						
							|  |  |  |     [ swap length =/fail ] | 
					
						
							|  |  |  |     [ firstn ] 2bi ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: sequence [undo-xml] ( sequence -- quot: ( seq -- ) )
 | 
					
						
							|  |  |  |     remove-blanks [ length ] [ [ [undo-xml] ] { } map-as ] bi
 | 
					
						
							|  |  |  |     '[ remove-blanks _ firstn-strong _ spread ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: string [undo-xml] ( string -- quot: ( string -- ) )
 | 
					
						
							|  |  |  |     '[ _ =/fail ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: xml-data [undo-xml] ( datum -- quot: ( datum -- ) )
 | 
					
						
							|  |  |  |     '[ _ =/fail ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: interpolated [undo-xml] | 
					
						
							|  |  |  |     var>> '[ _ set ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : >enum ( assoc -- enum )
 | 
					
						
							|  |  |  |     ! Assumes keys are 0..n | 
					
						
							|  |  |  |     >alist sort-keys values <enum> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : undo-xml ( xml -- quot )
 | 
					
						
							|  |  |  |     [undo-xml] '[ H{ } clone [ _ bind ] keep >enum ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \ interpolate-xml 1 [ undo-xml ] define-pop-inverse | 
					
						
							| 
									
										
										
										
											2009-02-13 16:10:34 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 |