26de0d2f44a61296ec37af8c9ccb443f012f303c
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Basic SAX listeners.
16 module doxml
::listener
20 import language_specific
22 # Common abstractions for SAX listeners reading XML documents generated by Doxygen.
23 abstract class DoxmlListener
26 # The locator setted by calling `document_locator=`.
27 protected var locator
: nullable SAXLocator = null
30 fun graph
: ProjectGraph is abstract
32 # The language-specific strategies to use.
33 fun source_language
: SourceLanguage is abstract
35 redef fun document_locator
=(locator
: SAXLocator) do
36 self.locator
= locator
39 protected fun dox_uri
: String do return ""
41 redef fun start_element
(uri
: String, local_name
: String, qname
: String,
44 if uri
!= dox_uri
then return # None of our business.
45 start_dox_element
(local_name
, atts
)
48 # Process the start of an element in the Doxygen’s namespace.
50 # See `ContentHandler.start_element` for the description of the parameters.
51 protected fun start_dox_element
(local_name
: String, atts
: Attributes) do end
53 redef fun end_element
(uri
: String, local_name
: String, qname
: String) do
55 if uri
!= dox_uri
then return # None of our business.
56 end_dox_element
(local_name
)
59 # Process the end of an element in the Doxygen’s namespace.
61 # See `ContentHandler.start_element` for the description of the parameters.
62 protected fun end_dox_element
(local_name
: String) do end
64 protected fun get_bool
(atts
: Attributes, local_name
: String): Bool do
65 return get_optional
(atts
, local_name
, "no") == "yes"
68 # Get the value of an optional attribute.
72 # * `atts`: attribute list.
73 # * `local_name`: local name of the attribute.
74 # * `default`: value to return when the specified attribute is not found.
75 protected fun get_optional
(atts
: Attributes, local_name
: String,
76 default
: String): String do
77 return atts
.value_ns
(dox_uri
, local_name
) or else default
80 # Get the value of an required attribute.
84 # * `atts`: attribute list.
85 # * `local_name`: local name of the attribute.
86 protected fun get_required
(atts
: Attributes, local_name
: String): String do
87 var value
= atts
.value_ns
(dox_uri
, local_name
)
89 throw_error
("The `{local_name}` attribute is required.")
96 redef fun end_document
do
100 # Throw an error with the specified message by prepending the current location.
101 protected fun throw_error
(message
: String) do
102 var e
: SAXParseException
104 if locator
!= null then
105 e
= new SAXParseException.with_locator
(message
, locator
.as(not null))
107 e
= new SAXParseException(message
)
113 # A `DoxmlListener` that read only a part of a document.
115 # Temporary redirect events to itself until it ends processing its part.
116 abstract class StackableListener
119 # The associated reader.
120 var reader
: XMLReader
122 # The parent listener.
123 var parent
: DoxmlListener
125 # Namespace’s IRI of the element at the root of the part to process.
126 private var root_uri
: String = ""
128 # Local name of the element at the root of the part to process.
129 private var root_local_name
: String = ""
131 # The number of open element of the same type than the root of the part to process.
132 private var depth
= 0
135 private var p_graph
: ProjectGraph is noinit
137 # The language-specific strategies to use.
138 private var p_source
: SourceLanguage is noinit
143 p_graph
= parent
.graph
144 p_source
= parent
.source_language
147 redef fun graph
do return p_graph
148 redef fun source_language
do return p_source
150 # Temporary redirect events to itself until the end of the specified element.
151 fun listen_until
(uri
: String, local_name
: String) do
153 root_local_name
= local_name
155 reader
.content_handler
= self
156 locator
= parent
.locator
159 redef fun start_element
(uri
: String, local_name
: String, qname
: String,
162 if uri
== root_uri
and local_name
== root_local_name
then
167 redef fun end_element
(uri
: String, local_name
: String, qname
: String) do
169 if uri
== root_uri
and local_name
== root_local_name
then
173 parent
.end_element
(uri
, local_name
, qname
)
178 # Reset the reader’s listener to the parent.
180 reader
.content_handler
= parent
184 redef fun end_document
do
189 # A SAX listener that skips any event except the end of the part to process.
191 # Used to skip an entire element.
193 super StackableListener
196 # Concatenates any text node found.
198 super StackableListener
200 protected var buffer
: Buffer = new FlatBuffer
201 private var sp
: Bool = false
203 redef fun listen_until
(uri
: String, local_name
: String) do
209 redef fun characters
(str
: String) do
211 if buffer
.length
> 0 then buffer
.append
(" ")
217 redef fun ignorable_whitespace
(str
: String) do
222 protected fun flush_buffer
: String do
230 redef fun to_s
do return buffer
.to_s
233 # Processes a content of type `linkedTextType`.
234 abstract class LinkedTextListener[T
: LinkedText]
238 var linked_text
: T
is noinit
240 private var refid
= ""
242 # Create a new instance of `T`.
243 protected fun create_linked_text
: T
is abstract
245 redef fun listen_until
(uri
: String, local_name
: String) do
246 linked_text
= create_linked_text
251 redef fun start_dox_element
(local_name
: String, atts
: Attributes) do
254 if "ref" == local_name
then refid
= get_required
(atts
, "refid")
257 redef fun end_dox_element
(local_name
: String) do
260 if "ref" == local_name
then refid
= ""
263 private fun push_part
do
266 if not s
.is_empty
then
267 linked_text
.add_part
(s
, refid
)
271 redef fun to_s
do return linked_text
.to_s
274 # Processes the content of a `<type>` element.
276 super LinkedTextListener[RawType]
278 private var raw_type
: RawType is noinit
280 redef fun create_linked_text
do return new RawType(graph
)