| author | wenzelm | 
| Sun, 09 Jun 2024 21:16:38 +0200 | |
| changeset 80313 | a828e47c867c | 
| parent 78913 | ecb02f288636 | 
| child 82952 | 430dcd883bbc | 
| 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 {
 | 
| 78912 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 58 | def keyword_kind: Option[String] = None | 
| 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 59 | |
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 60 | override def toString: String = | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 61 |       this match {
 | 
| 78912 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 62 | case command: Command_Span => proper_string(command.name) getOrElse "<command>" | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 63 | case Ignored_Span => "<ignored>" | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 64 | case Malformed_Span => "<malformed>" | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 65 | case Theory_Span => "<theory>" | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 66 | } | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 67 | } | 
| 78912 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 68 | case class Command_Span(override val keyword_kind: Option[String], name: String, pos: Position.T) | 
| 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 69 | extends Kind | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 70 | case object Ignored_Span extends Kind | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 71 | 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 | 72 | case object Theory_Span extends Kind | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 73 | |
| 72743 | 74 | |
| 75 | /* span */ | |
| 76 | ||
| 75393 | 77 |   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 | 78 | 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 | 79 | |
| 59735 | 80 | def name: String = | 
| 72800 | 81 |       kind match { case k: Command_Span => k.name case _ => "" }
 | 
| 58802 | 82 | |
| 59735 | 83 | def position: Position.T = | 
| 72800 | 84 |       kind match { case k: Command_Span => k.pos case _ => Position.none }
 | 
| 85 | ||
| 67895 | 86 | def keyword_pos(start: Token.Pos): Token.Pos = | 
| 87 |       kind match {
 | |
| 88 | case _: Command_Span => | |
| 73359 | 89 | content.iterator.takeWhile(tok => !tok.is_command).foldLeft(start)(_.advance(_)) | 
| 67895 | 90 | case _ => start | 
| 91 | } | |
| 92 | ||
| 78912 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 93 | def is_keyword_kind(pred: String => Boolean, other: Boolean = false): Boolean = | 
| 
ff4496b25197
clarified signature: Command_Span.Kind already contains keyword_kind, so parsing document structure no longer requires Keyword.Keywords;
 wenzelm parents: 
76798diff
changeset | 94 |       kind.keyword_kind match {
 | 
| 68840 | 95 | case Some(k) => pred(k) | 
| 68845 
3b2daa7bf9f4
support Thy_Element in Scala, following ML version;
 wenzelm parents: 
68840diff
changeset | 96 | case None => other | 
| 68840 | 97 | } | 
| 98 | ||
| 63606 | 99 | def is_begin: Boolean = content.exists(_.is_begin) | 
| 100 | def is_end: Boolean = content.exists(_.is_end) | |
| 101 | ||
| 72946 | 102 | def content_reader: CharSequenceReader = Scan.char_reader(Token.implode(content)) | 
| 103 | ||
| 73359 | 104 | def length: Int = content.foldLeft(0)(_ + _.source.length) | 
| 59705 | 105 | |
| 75393 | 106 |     def compact_source: (String, Span) = {
 | 
| 59735 | 107 | val source = Token.implode(content) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 108 | val content1 = new mutable.ListBuffer[Token] | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 109 | var i = 0 | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 110 |       for (Token(kind, s) <- content) {
 | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 111 | val n = s.length | 
| 59735 | 112 | val s1 = source.substring(i, i + n) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 113 | content1 += Token(kind, s1) | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 114 | i += n | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 115 | } | 
| 59735 | 116 | (source, Span(kind, content1.toList)) | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 117 | } | 
| 72742 | 118 | |
| 75393 | 119 |     def clean_arguments: List[(Token, Int)] = {
 | 
| 72743 | 120 |       if (name.nonEmpty) {
 | 
| 121 | def clean(toks: List[(Token, Int)]): List[(Token, Int)] = | |
| 122 |           toks match {
 | |
| 123 | case (t1, i1) :: (t2, i2) :: rest => | |
| 124 | if (t1.is_keyword && t1.source == "%" && t2.is_name) clean(rest) | |
| 125 | else (t1, i1) :: clean((t2, i2) :: rest) | |
| 126 | case _ => toks | |
| 127 | } | |
| 128 |         clean(content.zipWithIndex.filter({ case (t, _) => t.is_proper }))
 | |
| 129 |           .dropWhile({ case (t, _) => !t.is_command })
 | |
| 130 |           .dropWhile({ case (t, _) => t.is_command })
 | |
| 131 | } | |
| 132 | else Nil | |
| 133 | } | |
| 134 | ||
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 135 | def is_load_command(syntax: Outer_Syntax): Boolean = | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 136 | syntax.load_command(name).isDefined | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72800diff
changeset | 137 | |
| 72743 | 138 | def loaded_files(syntax: Outer_Syntax): Loaded_Files = | 
| 72742 | 139 |       syntax.load_command(name) match {
 | 
| 72757 | 140 | case None => Loaded_Files.none | 
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 141 | case Some(a) => | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 142 |           load_commands.find(_.name == a) match {
 | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 143 | 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 | 144 |             case None => error("Undefined load command function: " + a)
 | 
| 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72744diff
changeset | 145 | } | 
| 72742 | 146 | } | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 147 | } | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 148 | |
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 149 | val empty: Span = Span(Ignored_Span, Nil) | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 150 | |
| 78913 | 151 |   def unparsed(source: String, theory: Boolean = false): Span = {
 | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
68845diff
changeset | 152 | 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 | 153 | 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 | 154 | } | 
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: diff
changeset | 155 | } |