| author | wenzelm | 
| Thu, 02 Nov 2023 10:29:24 +0100 | |
| changeset 78875 | b7d355b2b176 | 
| parent 76798 | 69d8d16c5612 | 
| child 78912 | ff4496b25197 | 
| permissions | -rw-r--r-- | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/PIDE/command_span.scala | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 3 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 4 | Syntactic representation of command spans. | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 6 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 8 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 9 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 10 | import scala.collection.mutable | 
| 72946 | 11 | import scala.util.parsing.input.CharSequenceReader | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 12 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 13 | |
| 75393 | 14 | object Command_Span {
 | 
| 72743 | 15 | /* loaded files */ | 
| 16 | ||
| 75393 | 17 |   object Loaded_Files {
 | 
| 72757 | 18 | val none: Loaded_Files = Loaded_Files(Nil, -1) | 
| 19 | } | |
| 20 | sealed case class Loaded_Files(files: List[String], index: Int) | |
| 72743 | 21 | |
| 74671 | 22 | abstract class Load_Command(val name: String, val here: Scala_Project.Here) | 
| 75393 | 23 |   extends Isabelle_System.Service {
 | 
| 76798 | 24 |     override def toString: String = print("")
 | 
| 25 | ||
| 26 | def print(body: String): String = | |
| 27 |       if (body.nonEmpty) "Load_Command(" + body + ")"
 | |
| 28 |       else if (name.nonEmpty) print("name = " + quote(name))
 | |
| 29 | else "Load_Command" | |
| 30 | ||
| 31 | def print_extensions: String = | |
| 32 |       print("name = " + quote(name) + ", extensions = " + commas_quote(extensions))
 | |
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 33 | |
| 74671 | 34 | def position: Position.T = here.position | 
| 35 | ||
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 36 | def extensions: List[String] = Nil | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 37 | |
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 38 | def loaded_files(tokens: List[(Token, Int)]): Loaded_Files = | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 39 |       tokens.collectFirst({ case (t, i) if t.is_embedded => (t.content, i) }) match {
 | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 40 | case Some((file, i)) => | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 41 |           extensions match {
 | 
| 72757 | 42 | case Nil => Loaded_Files(List(file), i) | 
| 43 | case exts => Loaded_Files(exts.map(ext => file + "." + ext), i) | |
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 44 | } | 
| 72757 | 45 | case None => Loaded_Files.none | 
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 46 | } | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 47 | } | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 48 | |
| 76615 | 49 |   object Load_Default extends Load_Command("", Scala_Project.here)
 | 
| 74671 | 50 | |
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 51 | lazy val load_commands: List[Load_Command] = | 
| 76615 | 52 | Load_Default :: Isabelle_System.make_services(classOf[Load_Command]) | 
| 72743 | 53 | |
| 54 | ||
| 55 | /* span kind */ | |
| 56 | ||
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 57 |   sealed abstract class Kind {
 | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 58 | override def toString: String = | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 59 |       this match {
 | 
| 73115 
a8e5d7c9a834
discontinued odd absolute position (amending 85bcdd05c6d0, 1975f397eabb): it violates translation invariance of commands and may lead to redundant re-checking of PIDE document;
 wenzelm parents: 
72946diff
changeset | 60 | case Command_Span(name, _) => proper_string(name) getOrElse "<command>" | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 61 | case Ignored_Span => "<ignored>" | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 62 | case Malformed_Span => "<malformed>" | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 63 | case Theory_Span => "<theory>" | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 64 | } | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 65 | } | 
| 73115 
a8e5d7c9a834
discontinued odd absolute position (amending 85bcdd05c6d0, 1975f397eabb): it violates translation invariance of commands and may lead to redundant re-checking of PIDE document;
 wenzelm parents: 
72946diff
changeset | 66 | case class Command_Span(name: String, pos: Position.T) extends Kind | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 67 | case object Ignored_Span extends Kind | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 68 | case object Malformed_Span extends Kind | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 69 | case object Theory_Span extends Kind | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 70 | |
| 72743 | 71 | |
| 72 | /* span */ | |
| 73 | ||
| 75393 | 74 |   sealed case class Span(kind: Kind, content: List[Token]) {
 | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 75 | def is_theory: Boolean = kind == Theory_Span | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 76 | |
| 59735 | 77 | def name: String = | 
| 72800 | 78 |       kind match { case k: Command_Span => k.name case _ => "" }
 | 
| 58802 | 79 | |
| 59735 | 80 | def position: Position.T = | 
| 72800 | 81 |       kind match { case k: Command_Span => k.pos case _ => Position.none }
 | 
| 82 | ||
| 67895 | 83 | def keyword_pos(start: Token.Pos): Token.Pos = | 
| 84 |       kind match {
 | |
| 85 | case _: Command_Span => | |
| 73359 | 86 | content.iterator.takeWhile(tok => !tok.is_command).foldLeft(start)(_.advance(_)) | 
| 67895 | 87 | case _ => start | 
| 88 | } | |
| 89 | ||
| 68845 
3b2daa7bf9f4
support Thy_Element in Scala, following ML version;
 wenzelm parents: 
68840diff
changeset | 90 | def is_kind(keywords: Keyword.Keywords, pred: String => Boolean, other: Boolean): Boolean = | 
| 68840 | 91 |       keywords.kinds.get(name) match {
 | 
| 92 | case Some(k) => pred(k) | |
| 68845 
3b2daa7bf9f4
support Thy_Element in Scala, following ML version;
 wenzelm parents: 
68840diff
changeset | 93 | case None => other | 
| 68840 | 94 | } | 
| 95 | ||
| 63606 | 96 | def is_begin: Boolean = content.exists(_.is_begin) | 
| 97 | def is_end: Boolean = content.exists(_.is_end) | |
| 98 | ||
| 72946 | 99 | def content_reader: CharSequenceReader = Scan.char_reader(Token.implode(content)) | 
| 100 | ||
| 73359 | 101 | def length: Int = content.foldLeft(0)(_ + _.source.length) | 
| 59705 | 102 | |
| 75393 | 103 |     def compact_source: (String, Span) = {
 | 
| 59735 | 104 | val source = Token.implode(content) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 105 | val content1 = new mutable.ListBuffer[Token] | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 106 | var i = 0 | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 107 |       for (Token(kind, s) <- content) {
 | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 108 | val n = s.length | 
| 59735 | 109 | val s1 = source.substring(i, i + n) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 110 | content1 += Token(kind, s1) | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 111 | i += n | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 112 | } | 
| 59735 | 113 | (source, Span(kind, content1.toList)) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 114 | } | 
| 72742 | 115 | |
| 75393 | 116 |     def clean_arguments: List[(Token, Int)] = {
 | 
| 72743 | 117 |       if (name.nonEmpty) {
 | 
| 118 | def clean(toks: List[(Token, Int)]): List[(Token, Int)] = | |
| 119 |           toks match {
 | |
| 120 | case (t1, i1) :: (t2, i2) :: rest => | |
| 121 | if (t1.is_keyword && t1.source == "%" && t2.is_name) clean(rest) | |
| 122 | else (t1, i1) :: clean((t2, i2) :: rest) | |
| 123 | case _ => toks | |
| 124 | } | |
| 125 |         clean(content.zipWithIndex.filter({ case (t, _) => t.is_proper }))
 | |
| 126 |           .dropWhile({ case (t, _) => !t.is_command })
 | |
| 127 |           .dropWhile({ case (t, _) => t.is_command })
 | |
| 128 | } | |
| 129 | else Nil | |
| 130 | } | |
| 131 | ||
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 132 | def is_load_command(syntax: Outer_Syntax): Boolean = | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 133 | syntax.load_command(name).isDefined | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 134 | |
| 72743 | 135 | def loaded_files(syntax: Outer_Syntax): Loaded_Files = | 
| 72742 | 136 |       syntax.load_command(name) match {
 | 
| 72757 | 137 | case None => Loaded_Files.none | 
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 138 | case Some(a) => | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 139 |           load_commands.find(_.name == a) match {
 | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 140 | case Some(load_command) => load_command.loaded_files(clean_arguments) | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 141 |             case None => error("Undefined load command function: " + a)
 | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 142 | } | 
| 72742 | 143 | } | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 144 | } | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 145 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 146 | val empty: Span = Span(Ignored_Span, Nil) | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 147 | |
| 75393 | 148 |   def unparsed(source: String, theory: Boolean): Span = {
 | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 149 | val kind = if (theory) Theory_Span else Malformed_Span | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 150 | Span(kind, List(Token(Token.Kind.UNPARSED, source))) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 151 | } | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 152 | } |