src/Pure/General/toml.scala
changeset 79007 eed4ca224c9c
parent 79006 dad92daaf73a
child 80058 68f6b29ae066
equal deleted inserted replaced
79006:dad92daaf73a 79007:eed4ca224c9c
   270     case class File(elems: List[(Keys, V)], defs: List[Def])
   270     case class File(elems: List[(Keys, V)], defs: List[Def])
   271 
   271 
   272 
   272 
   273     /* top-level syntax structure */
   273     /* top-level syntax structure */
   274 
   274 
   275     def key: Parser[Keys] = positioned(rep1sep(keys, $$$(".")) ^^ (_.reduce(_ + _)))
   275     def key: Parser[Keys] = positioned(rep1sep(keys, $$$(".")) ^^ (_.reduce(_ ++ _)))
   276 
   276 
   277     def string: Parser[String] =
   277     def string: Parser[String] =
   278       elem("string", e => e.is_string || e.is_multiline_string) ^^ (s => String(s.text))
   278       elem("string", e => e.is_string || e.is_multiline_string) ^^ (s => String(s.text))
   279     def integer: Parser[Integer] =
   279     def integer: Parser[Integer] =
   280       (decimal_int | binary_int | octal_int | hexadecimal_int) ^^ Integer.apply
   280       (decimal_int | binary_int | octal_int | hexadecimal_int) ^^ Integer.apply
   395         case other: Keys => rep == other.rep
   395         case other: Keys => rep == other.rep
   396         case _ => false
   396         case _ => false
   397       }
   397       }
   398     override def toString: Str = rep.mkString("Keys(", ".", ")")
   398     override def toString: Str = rep.mkString("Keys(", ".", ")")
   399 
   399 
   400     def head: Keys = new Keys(rep.take(1))
   400     def first: Keys = new Keys(rep.take(1))
   401     def last: Keys = new Keys(rep.takeRight(1))
   401     def last: Keys = new Keys(rep.takeRight(1))
   402     def next: Keys = new Keys(rep.drop(1))
   402     def next: Keys = new Keys(rep.drop(1))
   403     def parent: Keys = new Keys(rep.dropRight(1))
   403     def parent: Keys = new Keys(rep.dropRight(1))
   404 
   404 
   405     def the_last: Key = rep.last
       
   406     def the_head: Key = rep.head
       
   407     def the_key: Key = Library.the_single(rep)
   405     def the_key: Key = Library.the_single(rep)
   408 
   406 
   409     def length: Int = rep.length
   407     def length: Int = rep.length
   410 
   408 
   411     def +(other: Keys): Keys = new Keys(rep ::: other.rep)
   409     def ++(other: Keys): Keys = new Keys(rep ::: other.rep)
   412 
   410 
   413     def prefixes: Set[Keys] = splits.map(_._1).toSet
   411     def prefixes: Set[Keys] = splits.map(_._1).toSet
   414     def splits: List[(Keys, Keys)] = Range.inclusive(0, length).toList.map(split).reverse
   412     def splits: List[(Keys, Keys)] = Range.inclusive(0, length).toList.map(split).reverse
   415     def split(i: Int): (Keys, Keys) = {
   413     def split(i: Int): (Keys, Keys) = {
   416       val (rep0, rep1) = rep.splitAt(i)
   414       val (rep0, rep1) = rep.splitAt(i)
   432     private def check_add(start: Int, ks: Keys, elem: Parsers.Def | Parsers.V): Unit = {
   430     private def check_add(start: Int, ks: Keys, elem: Parsers.Def | Parsers.V): Unit = {
   433       val (to, seen, rest, split) =
   431       val (to, seen, rest, split) =
   434         elem match {
   432         elem match {
   435           case _: Parsers.Array_Of_Tables =>
   433           case _: Parsers.Array_Of_Tables =>
   436             val (_, seen, rest) = recent_array(ks.parent)
   434             val (_, seen, rest) = recent_array(ks.parent)
   437             (ks, seen, rest + ks.last, 0)
   435             (ks, seen, rest ++ ks.last, 0)
   438           case _ =>
   436           case _ =>
   439             val (to, seen, rest) = recent_array(ks)
   437             val (to, seen, rest) = recent_array(ks)
   440             (to, seen, rest, start - to.length)
   438             (to, seen, rest, start - to.length)
   441         }
   439         }
   442       val (rest0, rest1) = rest.split(split)
   440       val (rest0, rest1) = rest.split(split)
   443       val implicitly_seen = rest1.parent.prefixes.map(rest0 + _)
   441       val implicitly_seen = rest1.parent.prefixes.map(rest0 ++ _)
   444 
   442 
   445       def error[A](s: Str): A = this.error(s, elem.pos, Some(ks))
   443       def error[A](s: Str): A = this.error(s, elem.pos, Some(ks))
   446   
   444 
   447       seen.inlines.find(rest.is_child_of).foreach(ks =>
   445       seen.inlines.find(rest.is_child_of).foreach(ks =>
   448         error("Attempting to update an inline value"))
   446         error("Attempting to update an inline value"))
   449 
   447 
   450       val (inlines, tables) =
   448       val (inlines, tables) =
   451         elem match {
   449         elem match {
   477       isabelle.error(s + key_msg + " at line " + pos.line + file_msg)
   475       isabelle.error(s + key_msg + " at line " + pos.line + file_msg)
   478     }
   476     }
   479 
   477 
   480     def check_add_def(ks: Keys, defn: Parsers.Def): Unit = check_add(0, ks, defn)
   478     def check_add_def(ks: Keys, defn: Parsers.Def): Unit = check_add(0, ks, defn)
   481     def check_add_value(ks0: Keys, ks1: Keys, v: Parsers.V): Unit =
   479     def check_add_value(ks0: Keys, ks1: Keys, v: Parsers.V): Unit =
   482       check_add(ks0.length - 1, ks0 + ks1, v)
   480       check_add(ks0.length - 1, ks0 ++ ks1, v)
   483   }
   481   }
   484 
   482 
   485   object Parse_Context {
   483   object Parse_Context {
   486     case class Seen(inlines: Set[Keys], tables: Set[Keys])
   484     case class Seen(inlines: Set[Keys], tables: Set[Keys])
   487 
   485 
   498           context.error("Malformed TOML input: " + msg, next.pos)
   496           context.error("Malformed TOML input: " + msg, next.pos)
   499       }
   497       }
   500 
   498 
   501     def convert(ks0: Keys, ks1: Keys, v: Parsers.V): T = {
   499     def convert(ks0: Keys, ks1: Keys, v: Parsers.V): T = {
   502       def to_table(ks: Keys, t: T): Table =
   500       def to_table(ks: Keys, t: T): Table =
   503         if (ks.length == 1) Table(ks.head.the_key -> t)
   501         if (ks.length == 1) Table(ks.first.the_key -> t)
   504         else Table(ks.head.the_key -> to_table(ks.next, t))
   502         else Table(ks.first.the_key -> to_table(ks.next, t))
   505 
   503 
   506       def to_toml(v: Parsers.V): (T, Set[Keys]) = v match {
   504       def to_toml(v: Parsers.V): (T, Set[Keys]) = v match {
   507         case Parsers.Primitive(t) => (t, Set.empty)
   505         case Parsers.Primitive(t) => (t, Set.empty)
   508         case Parsers.Array(rep) => (Array(rep.map(to_toml(_)._1)), Set.empty)
   506         case Parsers.Array(rep) => (Array(rep.map(to_toml(_)._1)), Set.empty)
   509         case Parsers.Inline_Table(elems) =>
   507         case Parsers.Inline_Table(elems) =>
   510           elems.find(e => elems.count(_._1 == e._1) > 1).foreach((ks, _) =>
   508           elems.find(e => elems.count(_._1 == e._1) > 1).foreach((ks, _) =>
   511             context.error(
   509             context.error(
   512               "Duplicate " + ks + " in inline table", v.pos, Some(ks0 + ks1)))
   510               "Duplicate " + ks + " in inline table", v.pos, Some(ks0 ++ ks1)))
   513 
   511 
   514           val (tables, pfxs, key_spaces) =
   512           val (tables, pfxs, key_spaces) =
   515             elems.map { (ks, v) =>
   513             elems.map { (ks, v) =>
   516               val (t, keys) = to_toml(v)
   514               val (t, keys) = to_toml(v)
   517               (to_table(ks, t), ks.prefixes, keys.map(ks + _) + ks)
   515               (to_table(ks, t), ks.prefixes, keys.map(ks ++ _) + ks)
   518             }.unzip3
   516             }.unzip3
   519 
   517 
   520           for {
   518           for {
   521             pfx <- pfxs
   519             pfx <- pfxs
   522             if key_spaces.count(pfx.intersect(_).nonEmpty) > 1
   520             if key_spaces.count(pfx.intersect(_).nonEmpty) > 1
   523           } context.error("Inline table not self-contained", v.pos, Some(ks0 + ks1))
   521           } context.error("Inline table not self-contained", v.pos, Some(ks0 ++ ks1))
   524 
   522 
   525           (tables.foldLeft(Table())(_ ++ _), pfxs.toSet.flatten ++ key_spaces.toSet.flatten)
   523           (tables.foldLeft(Table())(_ ++ _), pfxs.toSet.flatten ++ key_spaces.toSet.flatten)
   526       }
   524       }
   527       context.check_add_value(ks0, ks1, v)
   525       context.check_add_value(ks0, ks1, v)
   528       to_toml(v)._1
   526       to_toml(v)._1
   532       def error[A](s: Str): A = context.error(s, ks0.pos, Some(ks0))
   530       def error[A](s: Str): A = context.error(s, ks0.pos, Some(ks0))
   533 
   531 
   534       def update_rec(hd: Keys, map: Table, ks: Keys): Table = {
   532       def update_rec(hd: Keys, map: Table, ks: Keys): Table = {
   535         val updated =
   533         val updated =
   536           if (ks.length == 1) {
   534           if (ks.length == 1) {
   537             map.any.get(ks.head.the_key) match {
   535             map.any.get(ks.first.the_key) match {
   538               case Some(a: Array) =>
   536               case Some(a: Array) =>
   539                 value match {
   537                 value match {
   540                   case a2: Array => a ++ a2
   538                   case a2: Array => a ++ a2
   541                   case _ => error("Table conflicts with previous array of tables")
   539                   case _ => error("Table conflicts with previous array of tables")
   542                 }
   540                 }
   550               case Some(_) => error("Attempting to redefine a value")
   548               case Some(_) => error("Attempting to redefine a value")
   551               case None => value
   549               case None => value
   552             }
   550             }
   553           }
   551           }
   554           else {
   552           else {
   555             val hd1 = hd + ks.head
   553             val hd1 = hd ++ ks.first
   556             map.any.get(ks.head.the_key) match {
   554             map.any.get(ks.first.the_key) match {
   557               case Some(t: Table) => update_rec(hd1, t, ks.next)
   555               case Some(t: Table) => update_rec(hd1, t, ks.next)
   558               case Some(a: Array) =>
   556               case Some(a: Array) =>
   559                 Array(a.table.values.dropRight(1) :+ update_rec(hd1, a.table.values.last, ks.next))
   557                 Array(a.table.values.dropRight(1) :+ update_rec(hd1, a.table.values.last, ks.next))
   560               case Some(_) => error("Attempting to redefine a value")
   558               case Some(_) => error("Attempting to redefine a value")
   561               case None => update_rec(hd1, Table(), ks.next)
   559               case None => update_rec(hd1, Table(), ks.next)
   562             }
   560             }
   563           }
   561           }
   564         (map - ks.head.the_key) + (ks.head.the_key -> updated)
   562         (map - ks.first.the_key) + (ks.first.the_key -> updated)
   565       }
   563       }
   566 
   564 
   567       update_rec(Keys.empty, map, ks0)
   565       update_rec(Keys.empty, map, ks0)
   568     }
   566     }
   569 
   567