64 } |
63 } |
65 |
64 |
66 object Entry |
65 object Entry |
67 { |
66 { |
68 def apply(markup: Text.Markup, subtree: Markup_Tree): Entry = |
67 def apply(markup: Text.Markup, subtree: Markup_Tree): Entry = |
69 Entry(markup.range, List(markup.info), Elements.empty + markup.info, subtree) |
68 Entry(markup.range, List(markup.info), Elements.empty + markup.info, |
|
69 subtree, subtree.make_elements) |
70 |
70 |
71 def apply(range: Text.Range, rev_markups: List[XML.Elem], subtree: Markup_Tree): Entry = |
71 def apply(range: Text.Range, rev_markups: List[XML.Elem], subtree: Markup_Tree): Entry = |
72 Entry(range, rev_markups, Elements.empty ++ rev_markups, subtree) |
72 Entry(range, rev_markups, Elements.empty ++ rev_markups, |
|
73 subtree, subtree.make_elements) |
73 } |
74 } |
74 |
75 |
75 sealed case class Entry( |
76 sealed case class Entry( |
76 range: Text.Range, |
77 range: Text.Range, |
77 rev_markup: List[XML.Elem], |
78 rev_markup: List[XML.Elem], |
78 elements: Elements, |
79 elements: Elements, |
79 subtree: Markup_Tree) |
80 subtree: Markup_Tree, |
80 { |
81 subtree_elements: Elements) |
81 def + (info: XML.Elem): Entry = |
82 { |
82 copy(rev_markup = info :: rev_markup, elements = elements + info) |
|
83 |
|
84 def markup: List[XML.Elem] = rev_markup.reverse |
83 def markup: List[XML.Elem] = rev_markup.reverse |
|
84 |
|
85 def + (markup: Text.Markup): Entry = |
|
86 copy(rev_markup = markup.info :: rev_markup, elements = elements + markup.info) |
|
87 |
|
88 def \ (markup: Text.Markup): Entry = |
|
89 copy(subtree = subtree + markup, subtree_elements = subtree_elements + markup.info) |
85 } |
90 } |
86 |
91 |
87 object Branches |
92 object Branches |
88 { |
93 { |
89 type T = SortedMap[Text.Range, Entry] |
94 type T = SortedMap[Text.Range, Entry] |
146 case Some(end) if range overlaps end.range => bs + (end.range -> end) |
151 case Some(end) if range overlaps end.range => bs + (end.range -> end) |
147 case _ => bs |
152 case _ => bs |
148 } |
153 } |
149 } |
154 } |
150 |
155 |
|
156 def make_elements: Elements = |
|
157 (Elements.empty /: branches)( |
|
158 { case (elements, (_, entry)) => elements ++ entry.subtree_elements ++ entry.elements }) |
|
159 |
151 def + (new_markup: Text.Markup): Markup_Tree = |
160 def + (new_markup: Text.Markup): Markup_Tree = |
152 { |
161 { |
153 val new_range = new_markup.range |
162 val new_range = new_markup.range |
154 |
163 |
155 branches.get(new_range) match { |
164 branches.get(new_range) match { |
156 case None => new Markup_Tree(branches, Entry(new_markup, empty)) |
165 case None => new Markup_Tree(branches, Entry(new_markup, empty)) |
157 case Some(entry) => |
166 case Some(entry) => |
158 if (entry.range == new_range) |
167 if (entry.range == new_range) |
159 new Markup_Tree(branches, entry + new_markup.info) |
168 new Markup_Tree(branches, entry + new_markup) |
160 else if (entry.range.contains(new_range)) |
169 else if (entry.range.contains(new_range)) |
161 new Markup_Tree(branches, entry.copy(subtree = entry.subtree + new_markup)) |
170 new Markup_Tree(branches, entry \ new_markup) |
162 else if (new_range.contains(branches.head._1) && new_range.contains(branches.last._1)) |
171 else if (new_range.contains(branches.head._1) && new_range.contains(branches.last._1)) |
163 new Markup_Tree(Branches.empty, Entry(new_markup, this)) |
172 new Markup_Tree(Branches.empty, Entry(new_markup, this)) |
164 else { |
173 else { |
165 val body = overlapping(new_range) |
174 val body = overlapping(new_range) |
166 if (body.forall(e => new_range.contains(e._1))) |
175 if (body.forall(e => new_range.contains(e._1))) |
216 case Some(res) => (elements: Elements) => res.exists(elements.contains) |
225 case Some(res) => (elements: Elements) => res.exists(elements.contains) |
217 case None => (elements: Elements) => true |
226 case None => (elements: Elements) => true |
218 } |
227 } |
219 |
228 |
220 def results(x: A, entry: Entry): Option[A] = |
229 def results(x: A, entry: Entry): Option[A] = |
221 if (notable(entry.elements)) { |
230 { |
222 val (y, changed) = |
231 val (y, changed) = |
223 // FIXME proper cumulation order (including status markup) (!?) |
232 // FIXME proper cumulation order (including status markup) (!?) |
224 ((x, false) /: entry.rev_markup)((res, info) => |
233 ((x, false) /: entry.rev_markup)((res, info) => |
225 { |
234 { |
226 val (y, changed) = res |
235 val (y, changed) = res |
227 val arg = (y, Text.Info(entry.range, info)) |
236 val arg = (y, Text.Info(entry.range, info)) |
228 if (result.isDefinedAt(arg)) (result(arg), true) |
237 if (result.isDefinedAt(arg)) (result(arg), true) |
229 else res |
238 else res |
230 }) |
239 }) |
231 if (changed) Some(y) else None |
240 if (changed) Some(y) else None |
232 } |
241 } |
233 else None |
|
234 |
242 |
235 def stream( |
243 def stream( |
236 last: Text.Offset, |
244 last: Text.Offset, |
237 stack: List[(Text.Info[A], Stream[(Text.Range, Entry)])]): Stream[Text.Info[A]] = |
245 stack: List[(Text.Info[A], Stream[(Text.Range, Entry)])]): Stream[Text.Info[A]] = |
238 { |
246 { |
239 stack match { |
247 stack match { |
240 case (parent, (range, entry) #:: more) :: rest => |
248 case (parent, (range, entry) #:: more) :: rest => |
241 val subrange = range.restrict(root_range) |
249 val subrange = range.restrict(root_range) |
242 val subtree = entry.subtree.overlapping(subrange).toStream |
250 val subtree = |
|
251 if (notable(entry.subtree_elements)) |
|
252 entry.subtree.overlapping(subrange).toStream |
|
253 else Stream.empty |
243 val start = subrange.start |
254 val start = subrange.start |
244 |
255 |
245 results(parent.info, entry) match { |
256 (if (notable(entry.elements)) results(parent.info, entry) else None) match { |
246 case Some(res) => |
257 case Some(res) => |
247 val next = Text.Info(subrange, res) |
258 val next = Text.Info(subrange, res) |
248 val nexts = stream(start, (next, subtree) :: (parent, more) :: rest) |
259 val nexts = stream(start, (next, subtree) :: (parent, more) :: rest) |
249 if (last < start) parent.restrict(Text.Range(last, start)) #:: nexts |
260 if (last < start) parent.restrict(Text.Range(last, start)) #:: nexts |
250 else nexts |
261 else nexts |