src/Pure/PIDE/markup_tree.scala
changeset 50551 67d934cdc9b9
parent 49650 9fad6480300d
child 50552 2b7fd8c9c4ac
equal deleted inserted replaced
50550:8c3c7f158861 50551:67d934cdc9b9
    16 import scala.annotation.tailrec
    16 import scala.annotation.tailrec
    17 
    17 
    18 
    18 
    19 object Markup_Tree
    19 object Markup_Tree
    20 {
    20 {
       
    21   /* construct trees */
       
    22 
    21   val empty: Markup_Tree = new Markup_Tree(Branches.empty)
    23   val empty: Markup_Tree = new Markup_Tree(Branches.empty)
    22 
    24 
    23   def merge_disjoint(trees: List[Markup_Tree]): Markup_Tree =
    25   def merge_disjoint(trees: List[Markup_Tree]): Markup_Tree =
    24     trees match {
    26     trees match {
    25       case Nil => empty
    27       case Nil => empty
    33                   bs + (r -> entry)
    35                   bs + (r -> entry)
    34               }
    36               }
    35           })
    37           })
    36     }
    38     }
    37 
    39 
       
    40 
       
    41   /* tree building blocks */
       
    42 
       
    43   object Elements
       
    44   {
       
    45     val empty = new Elements(Set.empty)
       
    46     def merge(es: Iterable[Elements]): Elements = (empty /: es.iterator)(_ ++ _)
       
    47   }
       
    48 
       
    49   final class Elements private(private val rep: Set[String])
       
    50   {
       
    51     def contains(name: String): Boolean = rep.contains(name)
       
    52 
       
    53     def + (name: String): Elements =
       
    54       if (contains(name)) this
       
    55       else new Elements(rep + name)
       
    56 
       
    57     def + (elem: XML.Elem): Elements = this + elem.markup.name
       
    58     def ++ (elems: Iterable[XML.Elem]): Elements = (this /: elems.iterator)(_ + _)
       
    59 
       
    60     def ++ (other: Elements): Elements =
       
    61       if (this eq other) this
       
    62       else if (rep.isEmpty) other
       
    63       else (this /: other.rep)(_ + _)
       
    64   }
       
    65 
    38   object Entry
    66   object Entry
    39   {
    67   {
    40     def apply(markup: Text.Markup, subtree: Markup_Tree): Entry =
    68     def apply(markup: Text.Markup, subtree: Markup_Tree): Entry =
    41       Entry(markup.range, List(markup.info), Set(markup.info.markup.name), subtree)
    69       Entry(markup.range, List(markup.info), Elements.empty + markup.info, subtree)
    42 
    70 
    43     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 =
    44       Entry(range, rev_markups, Set.empty ++ rev_markups.iterator.map(_.markup.name), subtree)
    72       Entry(range, rev_markups, Elements.empty ++ rev_markups, subtree)
    45   }
    73   }
    46 
    74 
    47   sealed case class Entry(
    75   sealed case class Entry(
    48     range: Text.Range,
    76     range: Text.Range,
    49     rev_markup: List[XML.Elem],
    77     rev_markup: List[XML.Elem],
    50     elements: Set[String],
    78     elements: Elements,
    51     subtree: Markup_Tree)
    79     subtree: Markup_Tree)
    52   {
    80   {
    53     def + (info: XML.Elem): Entry =
    81     def + (info: XML.Elem): Entry =
    54       if (elements(info.markup.name)) copy(rev_markup = info :: rev_markup)
    82       copy(rev_markup = info :: rev_markup, elements = elements + info)
    55       else copy(rev_markup = info :: rev_markup, elements = elements + info.markup.name)
       
    56 
    83 
    57     def markup: List[XML.Elem] = rev_markup.reverse
    84     def markup: List[XML.Elem] = rev_markup.reverse
    58   }
    85   }
    59 
    86 
    60   object Branches
    87   object Branches
   182     to_XML(Text.Range(0, text.length), text, (_: XML.Elem) => true)
   209     to_XML(Text.Range(0, text.length), text, (_: XML.Elem) => true)
   183 
   210 
   184   def cumulate[A](root_range: Text.Range, root_info: A, result_elements: Option[Set[String]],
   211   def cumulate[A](root_range: Text.Range, root_info: A, result_elements: Option[Set[String]],
   185     result: PartialFunction[(A, Text.Markup), A]): Stream[Text.Info[A]] =
   212     result: PartialFunction[(A, Text.Markup), A]): Stream[Text.Info[A]] =
   186   {
   213   {
       
   214     val notable: Elements => Boolean =
       
   215       result_elements match {
       
   216         case Some(res) => (elements: Elements) => res.exists(elements.contains)
       
   217         case None => (elements: Elements) => true
       
   218       }
       
   219 
   187     def results(x: A, entry: Entry): Option[A] =
   220     def results(x: A, entry: Entry): Option[A] =
   188       if (result_elements match { case Some(es) => es.exists(entry.elements) case None => true }) {
   221       if (notable(entry.elements)) {
   189         val (y, changed) =
   222         val (y, changed) =
   190           ((x, false) /: entry.rev_markup)((res, info) =>  // FIXME proper order!?
   223           // FIXME proper cumulation order (including status markup) (!?)
       
   224           ((x, false) /: entry.rev_markup)((res, info) =>
   191             {
   225             {
   192               val (y, changed) = res
   226               val (y, changed) = res
   193               val arg = (y, Text.Info(entry.range, info))
   227               val arg = (y, Text.Info(entry.range, info))
   194               if (result.isDefinedAt(arg)) (result(arg), true)
   228               if (result.isDefinedAt(arg)) (result(arg), true)
   195               else res
   229               else res