/* Title: Pure/General/antiquote.scala Author: Makarius Antiquotations within plain text. */ package isabelle object Antiquote { sealed abstract class Antiquote { def source: String } case class Text(source: String) extends Antiquote case class Control(source: String) extends Antiquote case class Antiq(source: String) extends Antiquote /* parsers */ object Parsers extends Parsers trait Parsers extends Scan.Parsers { private val txt: Parser[String] = rep1(many1(s => !Symbol.is_control(s) && !Symbol.is_open(s) && s != "@") | "@" <~ guard(opt_term(one(s => s != "{")))) ^^ (x => x.mkString) val control: Parser[String] = opt(one(Symbol.is_control)) ~ cartouche ^^ { case Some(x) ~ y => x + y case None ~ x => x } | one(Symbol.is_control) val antiq_other: Parser[String] = many1(s => s != "\"" && s != "`" && s != "}" && !Symbol.is_open(s) && !Symbol.is_close(s)) private val antiq_body: Parser[String] = quoted("\"") | (quoted("`") | (cartouche | antiq_other)) val antiq: Parser[String] = "@{" ~ rep(antiq_body) ~ "}" ^^ { case x ~ y ~ z => x + y.mkString + z } val antiquote: Parser[Antiquote] = txt ^^ (x => Text(x)) | (control ^^ (x => Control(x)) | antiq ^^ (x => Antiq(x))) } /* read */ def read(input: CharSequence): List[Antiquote] = { Parsers.parseAll(Parsers.rep(Parsers.antiquote), Scan.char_reader(input)) match { case Parsers.Success(xs, _) => xs case Parsers.NoSuccess(_, next) => error("Malformed quotation/antiquotation source" + Position.here(Position.Line(next.pos.line))) } } def read_antiq_body(input: CharSequence): Option[String] = { read(input) match { case List(Antiq(source)) => Some(source.substring(2, source.length - 1)) case _ => None } } }