src/Pure/PIDE/xml.scala
changeset 80430 89cd8fedefa7
parent 80429 6f4d5d922da7
child 80431 c748adebc67f
equal deleted inserted replaced
80429:6f4d5d922da7 80430:89cd8fedefa7
     4 Untyped XML trees and basic data representation.
     4 Untyped XML trees and basic data representation.
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
       
     9 import scala.annotation.tailrec
       
    10 
     9 
    11 
    10 object XML {
    12 object XML {
    11   /** XML trees **/
    13   /** XML trees **/
    12 
    14 
    13   /* datatype representation */
    15   /* datatype representation */
    14 
    16 
    15   type Attribute = Properties.Entry
    17   type Attribute = Properties.Entry
    16   type Attributes = Properties.T
    18   type Attributes = Properties.T
    17 
    19 
    18   sealed abstract class Tree { override def toString: String = string_of_tree(this) }
    20   trait Trav
       
    21   case class End(name: String) extends Trav
       
    22 
       
    23   sealed abstract class Tree extends Trav {
       
    24     override def toString: String = string_of_tree(this)
       
    25   }
    19   type Body = List[Tree]
    26   type Body = List[Tree]
    20   case class Elem(markup: Markup, body: Body) extends Tree {
    27   case class Elem(markup: Markup, body: Body) extends Tree with Trav {
    21     private lazy val hash: Int = (markup, body).hashCode()
    28     private lazy val hash: Int = (markup, body).hashCode()
    22     override def hashCode(): Int = hash
    29     override def hashCode(): Int = hash
    23 
    30 
    24     def name: String = markup.name
    31     def name: String = markup.name
    25 
    32 
    27       if (more_attributes.isEmpty) this
    34       if (more_attributes.isEmpty) this
    28       else Elem(markup.update_properties(more_attributes), body)
    35       else Elem(markup.update_properties(more_attributes), body)
    29 
    36 
    30     def + (att: Attribute): Elem = Elem(markup + att, body)
    37     def + (att: Attribute): Elem = Elem(markup + att, body)
    31   }
    38   }
    32   case class Text(content: String) extends Tree {
    39   case class Text(content: String) extends Tree with Trav {
    33     private lazy val hash: Int = content.hashCode()
    40     private lazy val hash: Int = content.hashCode()
    34     override def hashCode(): Int = hash
    41     override def hashCode(): Int = hash
    35   }
    42   }
    36 
    43 
    37   def elem(markup: Markup): XML.Elem = XML.Elem(markup, Nil)
    44   def elem(markup: Markup): XML.Elem = XML.Elem(markup, Nil)
    49   trait Traversal {
    56   trait Traversal {
    50     def text(s: String): Unit
    57     def text(s: String): Unit
    51     def elem(markup: Markup, end: Boolean = false): Unit
    58     def elem(markup: Markup, end: Boolean = false): Unit
    52     def end_elem(name: String): Unit
    59     def end_elem(name: String): Unit
    53 
    60 
    54     def tree(t: Tree): Unit =
    61     def traverse(trees: List[Tree]): Unit = {
    55       t match {
    62       @tailrec def trav(list: List[Trav]): Unit =
    56         case Text(s) => text(s)
    63         list match {
    57         case Elem(markup, Nil) => elem(markup, end = true)
    64           case Nil =>
    58         case Elem(markup, ts) => elem(markup); trees(ts); end_elem(markup.name)
    65           case Text(s) :: rest => text(s); trav(rest)
    59       }
    66           case Elem(markup, Nil) :: rest => elem(markup, end = true); trav(rest)
    60     def trees(ts: Iterable[Tree]): Unit = ts.foreach(tree)
    67           case Elem(markup, body) :: rest => elem(markup); trav(body ::: End(markup.name) :: rest)
       
    68           case End(name) :: rest => end_elem(name); trav(rest)
       
    69           case _ :: _ => ???
       
    70         }
       
    71       trav(trees)
       
    72     }
    61   }
    73   }
    62 
    74 
    63 
    75 
    64   /* name space */
    76   /* name space */
    65 
    77 
   178       builder += '/'
   190       builder += '/'
   179       builder ++= name
   191       builder ++= name
   180       builder += '>'
   192       builder += '>'
   181     }
   193     }
   182 
   194 
   183     def result(ts: Iterable[Tree]): String = { trees(ts); builder.toString }
   195     def result(ts: List[Tree]): String = { traverse(ts); builder.toString }
   184     def result(t: Tree): String = { tree(t); builder.toString }
       
   185   }
   196   }
   186 
   197 
   187   def string_of_body(body: Body): String =
   198   def string_of_body(body: Body): String =
   188     if (body.isEmpty) ""
   199     if (body.isEmpty) ""
   189     else new Output(new StringBuilder).result(body)
   200     else new Output(new StringBuilder).result(body)