lib/core/stream: LineIterator use CachedIterator
[nit.git] / lib / dom / xml_entities.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Basic blocks for DOM-XML representation
12 #
13 # DOM entities are defined in this module, specifically:
14 #
15 # * `XMLEntity`: Abstract kind of XML-related node
16 # * `XMLDocument`: A well-formed XML document, root of the tree
17 # * `PCDATA`: Raw XML-escaped character data
18 # * `CDATA`: Raw data, may contain invalid XML escape characters
19 # * `XMLTag`: Abstract XML tag element
20 # * `XMLAttrTag`: Abstract XML element, they may contain attributes
21 # * `XMLOnelinerTag`: Any tag contained on one-line only
22 # * `XMLStartTag`: A tag starting a new hierarchy level in the tree
23 # * `XMLPrologTag`: A tag containing meta-information on the document, must start with <?xml
24 # * `XMLProcessingInstructionTag`: Any XML tag starting with <? other than the prolog tag
25 # * `XMLEndTag`: A tag signaling the end of a block
26 # * `XMLCommentTag`: A comment tag
27 # * `XMLSpecialTag`: A special tag, which may contain meta-information
28 # * `XMLDoctypeTag`: A DOCTYPE tag, use to register a DTD
29 # * `XMLAttribute`: Any kind of attribute that may be attached to a tag
30 # * `XMLStringAttr`: An attribute containing a String
31 # * `XMLError`: Any kind of error thrown while parsing a document
32 module xml_entities
33
34 import parser_base
35
36 # Any kind of XML Entity
37 abstract class XMLEntity
38 # Optional parent of `self`
39 var parent: nullable XMLEntity = null is private writable(set_parent)
40
41 # Optional location of the entity in source
42 var location: nullable Location
43
44 # The children of `self`
45 var children: Sequence[XMLEntity] = new XMLEntities(self)
46
47 # Sets the parent of `self` to `e`
48 fun parent=(e: XMLEntity) do
49 var parent = self.parent
50 if parent != null then
51 parent.children.remove(self)
52 end
53 e.children.add(self)
54 end
55 end
56
57 # Proxy collection of XMLEntities, ordered, used for the children of an entity
58 private class XMLEntities
59 super Sequence[XMLEntity]
60
61 # The owner, aka, the parent
62 var owner: XMLEntity
63
64 var entities = new List[XMLEntity]
65
66 redef fun length do return entities.length
67
68 redef fun [](i) do return entities[i]
69
70 redef fun []=(index, el) do
71 var olde = self[index]
72 var olde_parent = olde.parent
73 if olde_parent != null then
74 olde_parent.children.remove(el)
75 end
76 entities[index] = el
77 el.set_parent owner
78 end
79
80 redef fun push(e) do
81 if not entities.has(e) then
82 entities.add e
83 e.parent = owner
84 end
85 end
86
87
88 redef fun remove(e) do
89 if e isa XMLEntity then
90 e.set_parent null
91 entities.remove(e)
92 end
93 end
94
95 redef fun has(e) do return entities.has(e)
96
97 redef fun iterator do return entities.iterator
98
99 redef fun reverse_iterator do return entities.reverse_iterator
100
101 redef fun pop do
102 var e = entities.pop
103 e.set_parent null
104 return e
105 end
106
107 redef fun unshift(e) do
108 entities.unshift e
109 e.set_parent owner
110 end
111
112 redef fun shift do
113 var e = entities.shift
114 e.set_parent null
115 return e
116 end
117
118 redef fun insert(it, index) do
119 entities.insert(it, index)
120 it.set_parent owner
121 end
122
123 redef fun remove_at(ind) do
124 var el = entities[ind]
125 entities.remove_at(ind)
126 el.set_parent null
127 end
128 end
129
130 # Top XML Document-Object Model element
131 class XMLDocument
132 super XMLEntity
133
134 redef fun to_s do return children.join
135 end
136
137 # PCDATA is any kind of non-xml formatted text
138 class PCDATA
139 super XMLEntity
140
141 # Any string containing non XML-reserved characters
142 var content: String
143
144 redef fun to_s do return content
145 end
146
147 # CDATA are regions in which no xml entity is parsed, all is ignored
148 class CDATA
149 super XMLEntity
150
151 # Any string contained within a CDATA block, may contain XML-reserved characters
152 var content: String
153
154 redef fun to_s do return "<![CDATA[{content}]]>"
155 end
156
157 # A Tag is a node in a DOM tree
158 abstract class XMLTag
159 super XMLEntity
160
161 # The name of the tag
162 var tag_name: String
163 end
164
165 # Any kind of XML tag with attributes
166 abstract class XMLAttrTag
167 super XMLTag
168
169 # List of attributes in a Tag
170 var attributes: Array[XMLAttribute]
171 end
172
173 # One-liner XML Tag (Ends with />)
174 class XMLOnelinerTag
175 super XMLAttrTag
176
177 redef fun to_s do
178 var s = "<{tag_name}"
179 if not attributes.is_empty then
180 s += " "
181 s += attributes.join(" ")
182 end
183 s += "/>"
184 return s
185 end
186 end
187
188 # A (potentially) multi-line spanning XML Tag start
189 class XMLStartTag
190 super XMLAttrTag
191
192 # Optional matching tag, must be matched for the document to be well-formed
193 var matching: nullable XMLEndTag
194
195 redef fun to_s do
196 var s = "<{tag_name}"
197 if not attributes.is_empty then
198 s += " "
199 s += attributes.join(" ")
200 end
201 s += ">"
202 for i in children do s += i.to_s
203 var matching = self.matching
204 if matching != null then s += matching.to_s
205 return s
206 end
207 end
208
209 # Any prolog style-Tag (starting with <?xml)
210 class XMLPrologTag
211 super XMLAttrTag
212
213 redef fun to_s do return """<?{{{tag_name}}} {{{attributes.join(" ")}}}?>"""
214 end
215
216 # Processing instructions start with <? and are to be read by a third-party application
217 class XMLProcessingInstructionTag
218 super XMLTag
219
220 # Raw content usable by the third-party application
221 var content: String
222
223 redef fun to_s do return "<?{tag_name} {content}?>"
224 end
225
226 # An end Tag (starting with </)
227 class XMLEndTag
228 super XMLTag
229
230 # Optional matching tag, must be matched for the document to be well-formed
231 var matching: nullable XMLStartTag
232
233 redef fun to_s do return "</{tag_name}>"
234 end
235
236 # An XML comment tag
237 class XMLCommentTag
238 super XMLTag
239
240 redef fun to_s do return "<!--{tag_name}-->"
241 end
242
243 # A DOCTYPE Tag
244 class XMLDoctypeTag
245 super XMLTag
246
247 # Raw content
248 var content: String
249
250 redef fun to_s do return "<!DOCTYPE {content}>"
251 end
252
253 # A Special Tag (starts with !)
254 #
255 # TODO: Support the remaining ! tags
256 class XMLSpecialTag
257 super XMLTag
258
259 redef fun to_s do return "<!{tag_name}>"
260 end
261
262 # Attributes are contained in tags, they provide meta-information on a tag
263 abstract class XMLAttribute
264 super XMLEntity
265
266 # Name of the attribute
267 var name: String
268 end
269
270 # An attribute with a String value
271 class XMLStringAttr
272 super XMLAttribute
273
274 # Value of the attribute without the double quotes
275 var value: String
276
277 # Type of delimiter (can be either " or ')
278 var delimiter: Char
279
280 redef fun to_s do return "{name}={delimiter}{value}{delimiter}"
281 end
282
283 # Badly formed XML attribute
284 class BadXMLAttribute
285 super XMLAttribute
286
287 redef fun to_s do return name
288 end
289
290 # Internal use only, shows the end of an attribute block
291 private class XMLAttributeEnd
292 super XMLAttribute
293 end
294
295 # Any XML Error that happens when parsing
296 class XMLError
297 super XMLEntity
298
299 # Error message reported by the parser
300 var message: String
301
302 redef fun to_s do
303 var l = self.location
304 if l == null then
305 return "XML Error: {message}"
306 else
307 return "XML Error: {message} at {l}"
308 end
309 end
310 end