--- 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))
}
}
--- a/src/Pure/Thy/latex.scala Thu Jan 19 14:57:25 2023 +0100
+++ b/src/Pure/Thy/latex.scala Thu Jan 19 15:51:09 2023 +0100
@@ -46,21 +46,6 @@
else name
- /* cite: references to bibliography */
-
- object Cite {
- sealed case class Value(kind: String, citation: String, location: XML.Body)
- def unapply(tree: XML.Tree): Option[Value] =
- tree match {
- case XML.Elem(Markup(Markup.Latex_Cite.name, props), body) =>
- val kind = Markup.Kind.unapply(props).getOrElse(Bibtex.CITE)
- val citations = Markup.Citations.get(props)
- Some(Value(kind, citations, body))
- case _ => None
- }
- }
-
-
/* index entries */
def index_escape(str: String): String = {
@@ -235,11 +220,15 @@
}
}
- def cite(value: Cite.Value): Text = {
- latex_macro0(value.kind) :::
- (if (value.location.isEmpty) Nil
- else XML.string("[") ::: value.location ::: XML.string("]")) :::
- XML.string("{" + value.citation + "}")
+ def cite(inner: Bibtex.Cite.Inner): Text = {
+ val body =
+ latex_macro0(inner.kind) :::
+ (if (inner.location.isEmpty) Nil
+ else XML.string("[") ::: inner.location ::: XML.string("]")) :::
+ XML.string("{" + inner.citation + "}")
+
+ if (inner.pos.isEmpty) body
+ else List(XML.Elem(Markup.Latex_Output(inner.pos), body))
}
def index_item(item: Index_Item.Value): String = {
@@ -299,7 +288,7 @@
case Markup.Latex_Tag(name) => latex_tag(name, body)
case Markup.Latex_Cite(_) =>
elem match {
- case Cite(value) => cite(value)
+ case Bibtex.Cite(inner) => cite(inner)
case _ => unknown_elem(elem, file_position)
}
case Markup.Latex_Index_Entry(_) =>