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 |