src/Pure/PIDE/xml.scala
changeset 75393 87ebf5a50283
parent 74789 a5c23da73fca
child 75436 40630fec3b5d
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 object XML
    10 object XML {
    11 {
       
    12   /** XML trees **/
    11   /** XML trees **/
    13 
    12 
    14   /* datatype representation */
    13   /* datatype representation */
    15 
    14 
    16   type Attribute = Properties.Entry
    15   type Attribute = Properties.Entry
    17   type Attributes = Properties.T
    16   type Attributes = Properties.T
    18 
    17 
    19   sealed abstract class Tree { override def toString: String = string_of_tree(this) }
    18   sealed abstract class Tree { override def toString: String = string_of_tree(this) }
    20   type Body = List[Tree]
    19   type Body = List[Tree]
    21   case class Elem(markup: Markup, body: Body) extends Tree
    20   case class Elem(markup: Markup, body: Body) extends Tree {
    22   {
       
    23     private lazy val hash: Int = (markup, body).hashCode()
    21     private lazy val hash: Int = (markup, body).hashCode()
    24     override def hashCode(): Int = hash
    22     override def hashCode(): Int = hash
    25 
    23 
    26     def name: String = markup.name
    24     def name: String = markup.name
    27 
    25 
    29       if (more_attributes.isEmpty) this
    27       if (more_attributes.isEmpty) this
    30       else Elem(markup.update_properties(more_attributes), body)
    28       else Elem(markup.update_properties(more_attributes), body)
    31 
    29 
    32     def + (att: Attribute): Elem = Elem(markup + att, body)
    30     def + (att: Attribute): Elem = Elem(markup + att, body)
    33   }
    31   }
    34   case class Text(content: String) extends Tree
    32   case class Text(content: String) extends Tree {
    35   {
       
    36     private lazy val hash: Int = content.hashCode()
    33     private lazy val hash: Int = content.hashCode()
    37     override def hashCode(): Int = hash
    34     override def hashCode(): Int = hash
    38   }
    35   }
    39 
    36 
    40   def elem(markup: Markup): XML.Elem = XML.Elem(markup, Nil)
    37   def elem(markup: Markup): XML.Elem = XML.Elem(markup, Nil)
    50     string(bg) ::: body ::: string(en)
    47     string(bg) ::: body ::: string(en)
    51 
    48 
    52 
    49 
    53   /* name space */
    50   /* name space */
    54 
    51 
    55   object Namespace
    52   object Namespace {
    56   {
       
    57     def apply(prefix: String, target: String): Namespace =
    53     def apply(prefix: String, target: String): Namespace =
    58       new Namespace(prefix, target)
    54       new Namespace(prefix, target)
    59   }
    55   }
    60 
    56 
    61   final class Namespace private(prefix: String, target: String)
    57   final class Namespace private(prefix: String, target: String) {
    62   {
       
    63     def apply(name: String): String = prefix + ":" + name
    58     def apply(name: String): String = prefix + ":" + name
    64     val attribute: XML.Attribute = ("xmlns:" + prefix, target)
    59     val attribute: XML.Attribute = ("xmlns:" + prefix, target)
    65 
    60 
    66     override def toString: String = attribute.toString
    61     override def toString: String = attribute.toString
    67   }
    62   }
    71 
    66 
    72   val XML_ELEM = "xml_elem"
    67   val XML_ELEM = "xml_elem"
    73   val XML_NAME = "xml_name"
    68   val XML_NAME = "xml_name"
    74   val XML_BODY = "xml_body"
    69   val XML_BODY = "xml_body"
    75 
    70 
    76   object Wrapped_Elem
    71   object Wrapped_Elem {
    77   {
       
    78     def apply(markup: Markup, body1: Body, body2: Body): XML.Elem =
    72     def apply(markup: Markup, body1: Body, body2: Body): XML.Elem =
    79       XML.Elem(Markup(XML_ELEM, (XML_NAME, markup.name) :: markup.properties),
    73       XML.Elem(Markup(XML_ELEM, (XML_NAME, markup.name) :: markup.properties),
    80         XML.Elem(Markup(XML_BODY, Nil), body1) :: body2)
    74         XML.Elem(Markup(XML_BODY, Nil), body1) :: body2)
    81 
    75 
    82     def unapply(tree: Tree): Option[(Markup, Body, Body)] =
    76     def unapply(tree: Tree): Option[(Markup, Body, Body)] =
    87           Some(Markup(name, props), body1, body2)
    81           Some(Markup(name, props), body1, body2)
    88         case _ => None
    82         case _ => None
    89       }
    83       }
    90   }
    84   }
    91 
    85 
    92   object Root_Elem
    86   object Root_Elem {
    93   {
       
    94     def apply(body: Body): XML.Elem = XML.Elem(Markup(XML_ELEM, Nil), body)
    87     def apply(body: Body): XML.Elem = XML.Elem(Markup(XML_ELEM, Nil), body)
    95     def unapply(tree: Tree): Option[Body] =
    88     def unapply(tree: Tree): Option[Body] =
    96       tree match {
    89       tree match {
    97         case XML.Elem(Markup(XML_ELEM, Nil), body) => Some(body)
    90         case XML.Elem(Markup(XML_ELEM, Nil), body) => Some(body)
    98         case _ => None
    91         case _ => None
   100   }
    93   }
   101 
    94 
   102 
    95 
   103   /* traverse text */
    96   /* traverse text */
   104 
    97 
   105   def traverse_text[A](body: Body)(a: A)(op: (A, String) => A): A =
    98   def traverse_text[A](body: Body)(a: A)(op: (A, String) => A): A = {
   106   {
       
   107     def traverse(x: A, t: Tree): A =
    99     def traverse(x: A, t: Tree): A =
   108       t match {
   100       t match {
   109         case XML.Wrapped_Elem(_, _, ts) => ts.foldLeft(x)(traverse)
   101         case XML.Wrapped_Elem(_, _, ts) => ts.foldLeft(x)(traverse)
   110         case XML.Elem(_, ts) => ts.foldLeft(x)(traverse)
   102         case XML.Elem(_, ts) => ts.foldLeft(x)(traverse)
   111         case XML.Text(s) => op(x, s)
   103         case XML.Text(s) => op(x, s)
   117   def symbol_length(body: Body): Int = traverse_text(body)(0) { case (n, s) => n + Symbol.length(s) }
   109   def symbol_length(body: Body): Int = traverse_text(body)(0) { case (n, s) => n + Symbol.length(s) }
   118 
   110 
   119 
   111 
   120   /* text content */
   112   /* text content */
   121 
   113 
   122   def content(body: Body): String =
   114   def content(body: Body): String = {
   123   {
       
   124     val text = new StringBuilder(text_length(body))
   115     val text = new StringBuilder(text_length(body))
   125     traverse_text(body)(()) { case (_, s) => text.append(s) }
   116     traverse_text(body)(()) { case (_, s) => text.append(s) }
   126     text.toString
   117     text.toString
   127   }
   118   }
   128 
   119 
   132 
   123 
   133   /** string representation **/
   124   /** string representation **/
   134 
   125 
   135   val header: String = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
   126   val header: String = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
   136 
   127 
   137   def output_char(s: StringBuilder, c: Char, permissive: Boolean = false): Unit =
   128   def output_char(s: StringBuilder, c: Char, permissive: Boolean = false): Unit = {
   138   {
       
   139     c match {
   129     c match {
   140       case '<' => s ++= "&lt;"
   130       case '<' => s ++= "&lt;"
   141       case '>' => s ++= "&gt;"
   131       case '>' => s ++= "&gt;"
   142       case '&' => s ++= "&amp;"
   132       case '&' => s ++= "&amp;"
   143       case '"' if !permissive => s ++= "&quot;"
   133       case '"' if !permissive => s ++= "&quot;"
   144       case '\'' if !permissive => s ++= "&apos;"
   134       case '\'' if !permissive => s ++= "&apos;"
   145       case _ => s += c
   135       case _ => s += c
   146     }
   136     }
   147   }
   137   }
   148 
   138 
   149   def output_string(s: StringBuilder, str: String, permissive: Boolean = false): Unit =
   139   def output_string(s: StringBuilder, str: String, permissive: Boolean = false): Unit = {
   150   {
       
   151     if (str == null) s ++= str
   140     if (str == null) s ++= str
   152     else str.iterator.foreach(output_char(s, _, permissive = permissive))
   141     else str.iterator.foreach(output_char(s, _, permissive = permissive))
   153   }
   142   }
   154 
   143 
   155   def output_elem(s: StringBuilder, markup: Markup, end: Boolean = false): Unit =
   144   def output_elem(s: StringBuilder, markup: Markup, end: Boolean = false): Unit = {
   156   {
       
   157     s += '<'
   145     s += '<'
   158     s ++= markup.name
   146     s ++= markup.name
   159     for ((a, b) <- markup.properties) {
   147     for ((a, b) <- markup.properties) {
   160       s += ' '
   148       s += ' '
   161       s ++= a
   149       s ++= a
   166     }
   154     }
   167     if (end) s += '/'
   155     if (end) s += '/'
   168     s += '>'
   156     s += '>'
   169   }
   157   }
   170 
   158 
   171   def output_elem_end(s: StringBuilder, name: String): Unit =
   159   def output_elem_end(s: StringBuilder, name: String): Unit = {
   172   {
       
   173     s += '<'
   160     s += '<'
   174     s += '/'
   161     s += '/'
   175     s ++= name
   162     s ++= name
   176     s += '>'
   163     s += '>'
   177   }
   164   }
   178 
   165 
   179   def string_of_body(body: Body): String =
   166   def string_of_body(body: Body): String = {
   180   {
       
   181     val s = new StringBuilder
   167     val s = new StringBuilder
   182 
   168 
   183     def tree(t: Tree): Unit =
   169     def tree(t: Tree): Unit =
   184       t match {
   170       t match {
   185         case XML.Elem(markup, Nil) =>
   171         case XML.Elem(markup, Nil) =>
   199   def text(s: String): String = string_of_tree(XML.Text(s))
   185   def text(s: String): String = string_of_tree(XML.Text(s))
   200 
   186 
   201 
   187 
   202   /** cache **/
   188   /** cache **/
   203 
   189 
   204   object Cache
   190   object Cache {
   205   {
       
   206     def make(
   191     def make(
   207         xz: XZ.Cache = XZ.Cache.make(),
   192         xz: XZ.Cache = XZ.Cache.make(),
   208         max_string: Int = isabelle.Cache.default_max_string,
   193         max_string: Int = isabelle.Cache.default_max_string,
   209         initial_size: Int = isabelle.Cache.default_initial_size): Cache =
   194         initial_size: Int = isabelle.Cache.default_initial_size): Cache =
   210       new Cache(xz, max_string, initial_size)
   195       new Cache(xz, max_string, initial_size)
   211 
   196 
   212     val none: Cache = make(XZ.Cache.none, max_string = 0)
   197     val none: Cache = make(XZ.Cache.none, max_string = 0)
   213   }
   198   }
   214 
   199 
   215   class Cache(val xz: XZ.Cache, max_string: Int, initial_size: Int)
   200   class Cache(val xz: XZ.Cache, max_string: Int, initial_size: Int)
   216     extends isabelle.Cache(max_string, initial_size)
   201   extends isabelle.Cache(max_string, initial_size) {
   217   {
   202     protected def cache_props(x: Properties.T): Properties.T = {
   218     protected def cache_props(x: Properties.T): Properties.T =
       
   219     {
       
   220       if (x.isEmpty) x
   203       if (x.isEmpty) x
   221       else
   204       else
   222         lookup(x) match {
   205         lookup(x) match {
   223           case Some(y) => y
   206           case Some(y) => y
   224           case None => store(x.map(p => (Library.isolate_substring(p._1).intern, cache_string(p._2))))
   207           case None => store(x.map(p => (Library.isolate_substring(p._1).intern, cache_string(p._2))))
   225         }
   208         }
   226     }
   209     }
   227 
   210 
   228     protected def cache_markup(x: Markup): Markup =
   211     protected def cache_markup(x: Markup): Markup = {
   229     {
       
   230       lookup(x) match {
   212       lookup(x) match {
   231         case Some(y) => y
   213         case Some(y) => y
   232         case None =>
   214         case None =>
   233           x match {
   215           x match {
   234             case Markup(name, props) =>
   216             case Markup(name, props) =>
   235               store(Markup(cache_string(name), cache_props(props)))
   217               store(Markup(cache_string(name), cache_props(props)))
   236           }
   218           }
   237       }
   219       }
   238     }
   220     }
   239 
   221 
   240     protected def cache_tree(x: XML.Tree): XML.Tree =
   222     protected def cache_tree(x: XML.Tree): XML.Tree = {
   241     {
       
   242       lookup(x) match {
   223       lookup(x) match {
   243         case Some(y) => y
   224         case Some(y) => y
   244         case None =>
   225         case None =>
   245           x match {
   226           x match {
   246             case XML.Elem(markup, body) =>
   227             case XML.Elem(markup, body) =>
   248             case XML.Text(text) => store(XML.Text(cache_string(text)))
   229             case XML.Text(text) => store(XML.Text(cache_string(text)))
   249           }
   230           }
   250       }
   231       }
   251     }
   232     }
   252 
   233 
   253     protected def cache_body(x: XML.Body): XML.Body =
   234     protected def cache_body(x: XML.Body): XML.Body = {
   254     {
       
   255       if (x.isEmpty) x
   235       if (x.isEmpty) x
   256       else
   236       else
   257         lookup(x) match {
   237         lookup(x) match {
   258           case Some(y) => y
   238           case Some(y) => y
   259           case None => x.map(cache_tree)
   239           case None => x.map(cache_tree)
   283 
   263 
   284   abstract class Error(s: String) extends Exception(s)
   264   abstract class Error(s: String) extends Exception(s)
   285   class XML_Atom(s: String) extends Error(s)
   265   class XML_Atom(s: String) extends Error(s)
   286   class XML_Body(body: XML.Body) extends Error("")
   266   class XML_Body(body: XML.Body) extends Error("")
   287 
   267 
   288   object Encode
   268   object Encode {
   289   {
       
   290     type T[A] = A => XML.Body
   269     type T[A] = A => XML.Body
   291     type V[A] = PartialFunction[A, (List[String], XML.Body)]
   270     type V[A] = PartialFunction[A, (List[String], XML.Body)]
   292     type P[A] = PartialFunction[A, List[String]]
   271     type P[A] = PartialFunction[A, List[String]]
   293 
   272 
   294 
   273 
   338       (x => List(node(f(x._1)), node(g(x._2)), node(h(x._3))))
   317       (x => List(node(f(x._1)), node(g(x._2)), node(h(x._3))))
   339 
   318 
   340     def list[A](f: T[A]): T[List[A]] =
   319     def list[A](f: T[A]): T[List[A]] =
   341       (xs => xs.map((x: A) => node(f(x))))
   320       (xs => xs.map((x: A) => node(f(x))))
   342 
   321 
   343     def option[A](f: T[A]): T[Option[A]] =
   322     def option[A](f: T[A]): T[Option[A]] = {
   344     {
       
   345       case None => Nil
   323       case None => Nil
   346       case Some(x) => List(node(f(x)))
   324       case Some(x) => List(node(f(x)))
   347     }
   325     }
   348 
   326 
   349     def variant[A](fs: List[V[A]]): T[A] =
   327     def variant[A](fs: List[V[A]]): T[A] = {
   350     {
       
   351       case x =>
   328       case x =>
   352         val (f, tag) = fs.iterator.zipWithIndex.find(p => p._1.isDefinedAt(x)).get
   329         val (f, tag) = fs.iterator.zipWithIndex.find(p => p._1.isDefinedAt(x)).get
   353         List(tagged(tag, f(x)))
   330         List(tagged(tag, f(x)))
   354     }
   331     }
   355   }
   332   }
   356 
   333 
   357   object Decode
   334   object Decode {
   358   {
       
   359     type T[A] = XML.Body => A
   335     type T[A] = XML.Body => A
   360     type V[A] = (List[String], XML.Body) => A
   336     type V[A] = (List[String], XML.Body) => A
   361     type P[A] = PartialFunction[List[String], A]
   337     type P[A] = PartialFunction[List[String], A]
   362 
   338 
   363 
   339 
   399       }
   375       }
   400 
   376 
   401 
   377 
   402     /* representation of standard types */
   378     /* representation of standard types */
   403 
   379 
   404     val tree: T[XML.Tree] =
   380     val tree: T[XML.Tree] = {
   405     {
       
   406       case List(t) => t
   381       case List(t) => t
   407       case ts => throw new XML_Body(ts)
   382       case ts => throw new XML_Body(ts)
   408     }
   383     }
   409 
   384 
   410     val properties: T[Properties.T] =
   385     val properties: T[Properties.T] = {
   411     {
       
   412       case List(XML.Elem(Markup(":", props), Nil)) => props
   386       case List(XML.Elem(Markup(":", props), Nil)) => props
   413       case ts => throw new XML_Body(ts)
   387       case ts => throw new XML_Body(ts)
   414     }
   388     }
   415 
   389 
   416     val string: T[String] =
   390     val string: T[String] = {
   417     {
       
   418       case Nil => ""
   391       case Nil => ""
   419       case List(XML.Text(s)) => s
   392       case List(XML.Text(s)) => s
   420       case ts => throw new XML_Body(ts)
   393       case ts => throw new XML_Body(ts)
   421     }
   394     }
   422 
   395 
   426 
   399 
   427     val bool: T[Boolean] = (x => bool_atom(string(x)))
   400     val bool: T[Boolean] = (x => bool_atom(string(x)))
   428 
   401 
   429     val unit: T[Unit] = (x => unit_atom(string(x)))
   402     val unit: T[Unit] = (x => unit_atom(string(x)))
   430 
   403 
   431     def pair[A, B](f: T[A], g: T[B]): T[(A, B)] =
   404     def pair[A, B](f: T[A], g: T[B]): T[(A, B)] = {
   432     {
       
   433       case List(t1, t2) => (f(node(t1)), g(node(t2)))
   405       case List(t1, t2) => (f(node(t1)), g(node(t2)))
   434       case ts => throw new XML_Body(ts)
   406       case ts => throw new XML_Body(ts)
   435     }
   407     }
   436 
   408 
   437     def triple[A, B, C](f: T[A], g: T[B], h: T[C]): T[(A, B, C)] =
   409     def triple[A, B, C](f: T[A], g: T[B], h: T[C]): T[(A, B, C)] = {
   438     {
       
   439       case List(t1, t2, t3) => (f(node(t1)), g(node(t2)), h(node(t3)))
   410       case List(t1, t2, t3) => (f(node(t1)), g(node(t2)), h(node(t3)))
   440       case ts => throw new XML_Body(ts)
   411       case ts => throw new XML_Body(ts)
   441     }
   412     }
   442 
   413 
   443     def list[A](f: T[A]): T[List[A]] =
   414     def list[A](f: T[A]): T[List[A]] =
   444       (ts => ts.map(t => f(node(t))))
   415       (ts => ts.map(t => f(node(t))))
   445 
   416 
   446     def option[A](f: T[A]): T[Option[A]] =
   417     def option[A](f: T[A]): T[Option[A]] = {
   447     {
       
   448       case Nil => None
   418       case Nil => None
   449       case List(t) => Some(f(node(t)))
   419       case List(t) => Some(f(node(t)))
   450       case ts => throw new XML_Body(ts)
   420       case ts => throw new XML_Body(ts)
   451     }
   421     }
   452 
   422 
   453     def variant[A](fs: List[V[A]]): T[A] =
   423     def variant[A](fs: List[V[A]]): T[A] = {
   454     {
       
   455       case List(t) =>
   424       case List(t) =>
   456         val (tag, (xs, ts)) = tagged(t)
   425         val (tag, (xs, ts)) = tagged(t)
   457         val f =
   426         val f =
   458           try { fs(tag) }
   427           try { fs(tag) }
   459           catch { case _: IndexOutOfBoundsException => throw new XML_Body(List(t)) }
   428           catch { case _: IndexOutOfBoundsException => throw new XML_Body(List(t)) }