src/Pure/PIDE/markup_tree.scala
changeset 50552 2b7fd8c9c4ac
parent 50551 67d934cdc9b9
child 50642 aca12f646772
equal deleted inserted replaced
50551:67d934cdc9b9 50552:2b7fd8c9c4ac
    41   /* tree building blocks */
    41   /* tree building blocks */
    42 
    42 
    43   object Elements
    43   object Elements
    44   {
    44   {
    45     val empty = new Elements(Set.empty)
    45     val empty = new Elements(Set.empty)
    46     def merge(es: Iterable[Elements]): Elements = (empty /: es.iterator)(_ ++ _)
       
    47   }
    46   }
    48 
    47 
    49   final class Elements private(private val rep: Set[String])
    48   final class Elements private(private val rep: Set[String])
    50   {
    49   {
    51     def contains(name: String): Boolean = rep.contains(name)
    50     def contains(name: String): Boolean = rep.contains(name)
    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