1 ! Copyright (C) 2005, 2009 Daniel Ehrenberg
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: namespaces xml.state kernel sequences accessors
4 xml.char-classes xml.errors math io sbufs fry strings ascii
5 circular xml.entities assocs make splitting math.parser
6 locals combinators arrays ;
9 : version=1.0? ( -- ? )
10 prolog-data get [ version>> "1.0" = ] [ t ] if* ;
12 : assure-good-char ( ch -- ch )
14 version=1.0? over text? not get-check and
15 [ disallowed-char ] when
18 ! * Basic utility words
22 [ 0 get-line 1+ set-line ] [ get-column 1+ ] if
25 ! (next) normalizes \r\n and \r
28 2dup swap CHAR: \r = [
30 [ nip read1 ] [ nip CHAR: \n swap ] if
32 set-next dup set-char assure-good-char ;
36 get-char [ unexpected-end ] unless (next) record ;
39 0 1 0 f f <spot> spot set
42 : with-state ( stream quot -- )
43 ! with-input-stream implicitly creates a new scope which we use
44 swap [ init-parser call ] with-input-stream ; inline
46 : skip-until ( quot: ( -- ? ) -- )
48 [ call ] keep swap [ drop ] [
51 ] [ drop ] if ; inline recursive
53 : take-until ( quot -- string )
54 #! Take the substring of a string starting at spot
55 #! from code until the quotation given is true and
56 #! advance spot to after the substring.
58 '[ @ [ t ] [ get-char _ push f ] if ] skip-until
59 ] keep >string ; inline
61 : take-to ( seq -- string )
62 '[ get-char _ member? ] take-until ;
65 #! Advance code past any whitespace, including newlines
66 [ get-char blank? not ] skip-until ;
68 : string-matches? ( string circular -- ? )
69 get-char over push-circular
72 : take-string ( match -- string )
73 dup length <circular-string>
74 [ 2dup string-matches? ] take-until nip
75 dup length rot length 1- - head
76 get-char [ missing-close ] unless next ;
78 : expect ( string -- )
79 dup [ get-char next ] replicate 2dup =
80 [ 2drop ] [ expected ] if ;
82 ! Suddenly XML-specific
84 : parse-named-entity ( string -- )
85 dup entities at [ , ] [
86 dup extra-entities get at
87 [ % ] [ no-entity ] ?if
90 : take-; ( -- string )
91 next ";" take-to next ;
95 "x" ?head 16 10 ? base> ,
96 ] [ parse-named-entity ] if ;
99 take-; dup pe-table get at
100 [ % ] [ no-entity ] ?if ;
102 :: (parse-char) ( quot: ( ch -- ? ) -- )
106 { [ char quot call ] [ next ] }
107 { [ char CHAR: & = ] [ parse-entity quot (parse-char) ] }
108 { [ in-dtd? get char CHAR: % = and ] [ parse-pe quot (parse-char) ] }
109 [ char , next quot (parse-char) ]
110 } cond ; inline recursive
112 : parse-char ( quot: ( ch -- ? ) -- seq )
113 [ (parse-char) ] "" make ; inline
115 : assure-no-]]> ( circular -- )
116 "]]>" sequence= [ text-w/]]> ] when ;
118 :: parse-text ( -- string )
119 3 f <array> <circular> :> circ
120 depth get zero? :> no-text [| char |
121 char circ push-circular
123 no-text [ char blank? char CHAR: < = or [
124 char 1string t pre/post-content
130 pass-blank ">" expect ;
132 : normalize-quote ( str -- str )
133 [ dup "\t\r\n" member? [ drop CHAR: \s ] when ] map ;
135 : (parse-quote) ( <-disallowed? ch -- string )
138 [ CHAR: < = _ and [ attr-w/< ] [ f ] if ] if
139 ] parse-char normalize-quote get-char
140 [ unclosed-quote ] unless ; inline
142 : parse-quote* ( <-disallowed? -- seq )
143 pass-blank get-char dup "'\"" member?
144 [ next (parse-quote) ] [ quoteless-attr ] if ; inline
146 : parse-quote ( -- seq )