src/Pure/Thy/bibtex.scala
changeset 77016 a19ea85409cd
parent 77015 87552565d1a5
child 77017 05219e08c3e9
--- a/src/Pure/Thy/bibtex.scala	Thu Jan 19 14:57:25 2023 +0100
+++ b/src/Pure/Thy/bibtex.scala	Thu Jan 19 15:51:09 2023 +0100
@@ -783,6 +783,44 @@
   /* parse within raw source */
 
   object Cite {
+    def unapply(tree: XML.Tree): Option[Inner] =
+      tree match {
+        case XML.Elem(Markup(Markup.Latex_Cite.name, props), body) =>
+          val kind = Markup.Kind.unapply(props).getOrElse(CITE)
+          val citations = Markup.Citations.get(props)
+          val pos = props.filter(Markup.position_property)
+          Some(Inner(kind, citations, body, pos))
+        case _ => None
+      }
+
+    sealed case class Inner(kind: String, citation: String, location: XML.Body, pos: Position.T) {
+      def nocite: Inner = copy(kind = NOCITE, location = Nil)
+
+      override def toString: String = citation
+    }
+
+    sealed case class Outer(kind: String, body: String, start: Isar_Token.Pos) {
+      def pos: Position.T = start.position()
+
+      def parse: Option[Inner] = {
+        val tokens = Isar_Token.explode(Parsers.keywords, body)
+        Parsers.parse_all(Parsers.inner(pos), Isar_Token.reader(tokens, start)) match {
+          case Parsers.Success(res, _) => Some(res)
+          case _ => None
+        }
+      }
+
+      def errors: List[String] =
+        if (parse.isDefined) Nil
+        else List("Malformed citation" + Position.here(pos))
+
+      override def toString: String =
+        parse match {
+          case Some(inner) => inner.toString
+          case None => "<malformed>"
+        }
+    }
+
     object Parsers extends Parse.Parsers {
       val keywords: Keyword.Keywords = Thy_Header.bootstrap_keywords + "in" + "and" + "using"
 
@@ -790,17 +828,16 @@
       val citations: Parser[String] = rep1sep(name, $$$("and")) ^^ (x => x.mkString(","))
       val kind: Parser[String] = $$$("using") ~! name ^^ { case _ ~ x => x } | success(CITE)
 
-      val nocite: Parser[Latex.Text] =
-        location ~ citations ~ kind ^^ { case _ ~ x ~ _ =>
-          List(XML.elem(Markup.Latex_Cite(Markup.Kind(NOCITE) ::: Markup.Citations(x))))
-        }
+      def inner(pos: Position.T): Parser[Inner] =
+        location ~ citations ~ kind ^^
+          { case x ~ y ~ z => Inner(z, y, XML.string(x), pos) }
     }
 
     def parse(
       cite_commands: List[String],
       text: String,
       start: Isar_Token.Pos = Isar_Token.Pos.start
-    ): List[Cite] = {
+    ): List[Outer] = {
       val controls = cite_commands.map(s => Symbol.control_prefix + s + Symbol.control_suffix)
       val special = (controls ::: controls.map(Symbol.decode)).toSet
 
@@ -808,7 +845,7 @@
       Parsers.parseAll(Parsers.rep(Parsers.antiquote_special(special)), text) match {
         case Parsers.Success(ants, _) =>
           var pos = start
-          val result = new mutable.ListBuffer[Cite]
+          val result = new mutable.ListBuffer[Outer]
           for (ant <- ants) {
             ant match {
               case Antiquote.Control(source) =>
@@ -820,7 +857,7 @@
                   val (body, pos1) =
                     if (rest.isEmpty) (rest, pos)
                     else (Scan.Parsers.cartouche_content(rest), pos.advance(Symbol.open))
-                  result += Cite(kind, body, pos1)
+                  result += Outer(kind, body, pos1)
                 }
               case _ =>
             }
@@ -830,28 +867,5 @@
         case _ => error("Unexpected failure parsing special antiquotations:\n" + text)
       }
     }
-
-    def parse_latex(
-      cite_commands: List[String],
-      text: String,
-      start: Isar_Token.Pos = Isar_Token.Pos.start
-    ): Latex.Text = parse(cite_commands, text, start = start).flatMap(_.nocite_latex)
-  }
-
-  sealed case class Cite(kind: String, body: String, pos: Isar_Token.Pos) {
-    def position: Position.T = pos.position()
-
-    def nocite_latex: Latex.Text = {
-      val Parsers = Cite.Parsers
-      val tokens = Isar_Token.explode(Parsers.keywords, body)
-      Parsers.parse_all(Parsers.nocite, Isar_Token.reader(tokens, pos)) match {
-        case Parsers.Success(nocite, _) => List(XML.Elem(Markup.Latex_Output(position), nocite))
-        case _ => Nil
-      }
-    }
-
-    def errors: List[String] =
-      if (nocite_latex.nonEmpty) Nil
-      else List("Malformed citation" + Position.here(position))
   }
 }