/* Title: Pure/Tools/check_keywords.scala
Author: Makarius
Check theory sources for conflicts with proposed keywords.
*/
package isabelle
object Check_Keywords {
/* session theories for keyword conflicts */
def check_keywords(
options: Options,
check: Set[String],
dirs: List[Path] = Nil,
progress: Progress,
): Unit = {
val deps = Sessions.deps(Sessions.load_structure(options, dirs = dirs), progress = progress)
val bad =
Par_List.maps[(Keyword.Keywords, String, Token.Pos), (Token, Position.T)](
{ case (keywords, input, start) =>
progress.expose_interrupt()
object Parsers extends Parse.Parsers {
private val conflict =
position(token("token", tok => !(tok.is_command || tok.is_keyword) && check(tok.source)))
private val other = token("token", _ => true)
private val item = conflict ^^ (x => Some(x)) | other ^^ (_ => None)
val result: List[(Token, Position.T)] =
parse_all(rep(item), Token.reader(Token.explode(keywords, input), start)) match {
case Success(res, _) => for (case Some(x) <- res) yield x
case bad => error(bad.toString)
}
}
Parsers.result
},
List.from(
for {
session <- deps.sessions_structure.imports_topological_order.iterator
base = deps(session)
node_name <- base.proper_session_theories
} yield {
val path = node_name.path
val input = File.read(path)
val start = Token.Pos.file(File.standard_path(path))
(base.overall_syntax.keywords, input, start)
})
)
for ((tok, pos) <- bad) {
progress.echo_warning(
"keyword conflict: " + tok.kind.toString + " " + quote(tok.content) + Position.here(pos))
}
}
/* Isabelle tool wrapper */
val isabelle_tool =
Isabelle_Tool("check_keywords", "check theory sources for conflicts with proposed keywords",
Scala_Project.here,
{ args =>
var dirs: List[Path] = Nil
var options = Options.init()
var verbose = false
val getopts = Getopts("""
Usage: isabelle check_keywords [OPTIONS] KEYWORDS
Options are:
-d DIR include session directory
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME)
-v verbose
Check theory sources from all session directories for conflicts with
newly proposed keywords (outer syntax). This reveals occurrences of
identifiers that would have to be quoted.
""",
"d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),
"o:" -> (arg => options = options + arg),
"v" -> (_ => verbose = true))
val keywords = getopts(args)
if (keywords.isEmpty) getopts.usage()
val progress = new Console_Progress(verbose = verbose)
progress.interrupt_handler {
check_keywords(options, keywords.toSet, dirs = dirs, progress = progress)
}
})
}