43 val empty = new Elements(Set.empty) |
43 val empty = new Elements(Set.empty) |
44 } |
44 } |
45 |
45 |
46 final class Elements private(private val rep: Set[String]) |
46 final class Elements private(private val rep: Set[String]) |
47 { |
47 { |
48 def contains(name: String): Boolean = rep.contains(name) |
48 def exists(pred: String => Boolean): Boolean = rep.exists(pred) |
49 |
49 |
50 def + (name: String): Elements = |
50 def + (name: String): Elements = |
51 if (contains(name)) this |
51 if (rep(name)) this |
52 else new Elements(rep + name) |
52 else new Elements(rep + name) |
53 |
53 |
54 def + (elem: XML.Elem): Elements = this + elem.markup.name |
54 def + (elem: XML.Elem): Elements = this + elem.markup.name |
55 def ++ (elems: Iterable[XML.Elem]): Elements = (this /: elems.iterator)(_ + _) |
55 def ++ (elems: Iterable[XML.Elem]): Elements = (this /: elems.iterator)(_ + _) |
56 |
56 |
220 } |
220 } |
221 |
221 |
222 def to_XML(text: CharSequence): XML.Body = |
222 def to_XML(text: CharSequence): XML.Body = |
223 to_XML(Text.Range(0, text.length), text, (_: XML.Elem) => true) |
223 to_XML(Text.Range(0, text.length), text, (_: XML.Elem) => true) |
224 |
224 |
225 def cumulate[A](root_range: Text.Range, root_info: A, result_elements: Option[Set[String]], |
225 def cumulate[A](root_range: Text.Range, root_info: A, elements: String => Boolean, |
226 result: (A, Text.Markup) => Option[A]): List[Text.Info[A]] = |
226 result: (A, Text.Markup) => Option[A]): List[Text.Info[A]] = |
227 { |
227 { |
228 val notable: Elements => Boolean = |
|
229 result_elements match { |
|
230 case Some(res) => (elements: Elements) => res.exists(elements.contains) |
|
231 case None => (elements: Elements) => true |
|
232 } |
|
233 |
|
234 def results(x: A, entry: Entry): Option[A] = |
228 def results(x: A, entry: Entry): Option[A] = |
235 { |
229 { |
236 var y = x |
230 var y = x |
237 var changed = false |
231 var changed = false |
238 for { |
232 for { |
239 info <- entry.rev_markup // FIXME proper cumulation order (including status markup) (!?) |
233 elem <- entry.rev_markup // FIXME proper cumulation order (including status markup) (!?) |
240 y1 <- result(y, Text.Info(entry.range, info)) |
234 if elements(elem.name) |
|
235 y1 <- result(y, Text.Info(entry.range, elem)) |
241 } { y = y1; changed = true } |
236 } { y = y1; changed = true } |
242 if (changed) Some(y) else None |
237 if (changed) Some(y) else None |
243 } |
238 } |
244 |
239 |
245 def traverse( |
240 def traverse( |
248 { |
243 { |
249 stack match { |
244 stack match { |
250 case (parent, (range, entry) :: more) :: rest => |
245 case (parent, (range, entry) :: more) :: rest => |
251 val subrange = range.restrict(root_range) |
246 val subrange = range.restrict(root_range) |
252 val subtree = |
247 val subtree = |
253 if (notable(entry.subtree_elements)) |
248 if (entry.subtree_elements.exists(elements)) |
254 entry.subtree.overlapping(subrange).toList |
249 entry.subtree.overlapping(subrange).toList |
255 else Nil |
250 else Nil |
256 val start = subrange.start |
251 val start = subrange.start |
257 |
252 |
258 (if (notable(entry.elements)) results(parent.info, entry) else None) match { |
253 (if (entry.elements.exists(elements)) results(parent.info, entry) else None) match { |
259 case Some(res) => |
254 case Some(res) => |
260 val next = Text.Info(subrange, res) |
255 val next = Text.Info(subrange, res) |
261 val nexts = traverse(start, (next, subtree) :: (parent, more) :: rest) |
256 val nexts = traverse(start, (next, subtree) :: (parent, more) :: rest) |
262 if (last < start) parent.restrict(Text.Range(last, start)) :: nexts |
257 if (last < start) parent.restrict(Text.Range(last, start)) :: nexts |
263 else nexts |
258 else nexts |