174 groups: List[String], |
173 groups: List[String], |
175 dir: Path, |
174 dir: Path, |
176 parent: Option[String], |
175 parent: Option[String], |
177 description: String, |
176 description: String, |
178 options: Options, |
177 options: Options, |
179 theories: List[(Boolean, Options, List[Path])], |
178 theories: List[(Options, List[Path])], |
|
179 global_theories: List[String], |
180 files: List[Path], |
180 files: List[Path], |
181 document_files: List[(Path, Path)], |
181 document_files: List[(Path, Path)], |
182 meta_digest: SHA1.Digest) |
182 meta_digest: SHA1.Digest) |
183 { |
183 { |
184 def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale")) |
184 def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale")) |
185 |
|
186 def global_theories: List[String] = |
|
187 for { (global, _, paths) <- theories if global; path <- paths } |
|
188 yield { |
|
189 val name = path.base.implode |
|
190 if (Long_Name.is_qualified(name)) |
|
191 error("Bad qualified name for global theory " + quote(name)) |
|
192 else name |
|
193 } |
|
194 } |
185 } |
195 |
186 |
196 object Tree |
187 object Tree |
197 { |
188 { |
198 def apply(infos: Traversable[(String, Info)]): Tree = |
189 def apply(infos: Traversable[(String, Info)]): Tree = |
304 private val CHAPTER = "chapter" |
295 private val CHAPTER = "chapter" |
305 private val SESSION = "session" |
296 private val SESSION = "session" |
306 private val IN = "in" |
297 private val IN = "in" |
307 private val DESCRIPTION = "description" |
298 private val DESCRIPTION = "description" |
308 private val OPTIONS = "options" |
299 private val OPTIONS = "options" |
309 private val GLOBAL_THEORIES = "global_theories" |
|
310 private val THEORIES = "theories" |
300 private val THEORIES = "theories" |
|
301 private val GLOBAL = "global" |
311 private val FILES = "files" |
302 private val FILES = "files" |
312 private val DOCUMENT_FILES = "document_files" |
303 private val DOCUMENT_FILES = "document_files" |
313 |
304 |
314 lazy val root_syntax = |
305 lazy val root_syntax = |
315 Outer_Syntax.init() + "(" + ")" + "+" + "," + "=" + "[" + "]" + IN + |
306 Outer_Syntax.init() + "(" + ")" + "+" + "," + "=" + "[" + "]" + GLOBAL + IN + |
316 (CHAPTER, Keyword.THY_DECL) + |
307 (CHAPTER, Keyword.THY_DECL) + |
317 (SESSION, Keyword.THY_DECL) + |
308 (SESSION, Keyword.THY_DECL) + |
318 (DESCRIPTION, Keyword.QUASI_COMMAND) + |
309 (DESCRIPTION, Keyword.QUASI_COMMAND) + |
319 (OPTIONS, Keyword.QUASI_COMMAND) + |
310 (OPTIONS, Keyword.QUASI_COMMAND) + |
320 (GLOBAL_THEORIES, Keyword.QUASI_COMMAND) + |
|
321 (THEORIES, Keyword.QUASI_COMMAND) + |
311 (THEORIES, Keyword.QUASI_COMMAND) + |
322 (FILES, Keyword.QUASI_COMMAND) + |
312 (FILES, Keyword.QUASI_COMMAND) + |
323 (DOCUMENT_FILES, Keyword.QUASI_COMMAND) |
313 (DOCUMENT_FILES, Keyword.QUASI_COMMAND) |
324 |
314 |
325 private object Parser extends Parse.Parser with Options.Parser |
315 private object Parser extends Parse.Parser with Options.Parser |
332 groups: List[String], |
322 groups: List[String], |
333 path: String, |
323 path: String, |
334 parent: Option[String], |
324 parent: Option[String], |
335 description: String, |
325 description: String, |
336 options: List[Options.Spec], |
326 options: List[Options.Spec], |
337 theories: List[(Boolean, List[Options.Spec], List[String])], |
327 theories: List[(List[Options.Spec], List[(String, Boolean)])], |
338 files: List[String], |
328 files: List[String], |
339 document_files: List[(String, String)]) extends Entry |
329 document_files: List[(String, String)]) extends Entry |
340 |
330 |
341 private val chapter: Parser[Chapter] = |
331 private val chapter: Parser[Chapter] = |
342 { |
332 { |
352 val option = |
342 val option = |
353 option_name ~ opt($$$("=") ~! option_value ^^ |
343 option_name ~ opt($$$("=") ~! option_value ^^ |
354 { case _ ~ x => x }) ^^ { case x ~ y => (x, y) } |
344 { case _ ~ x => x }) ^^ { case x ~ y => (x, y) } |
355 val options = $$$("[") ~> rep1sep(option, $$$(",")) <~ $$$("]") |
345 val options = $$$("[") ~> rep1sep(option, $$$(",")) <~ $$$("]") |
356 |
346 |
|
347 val global = |
|
348 ($$$("(") ~! $$$(GLOBAL) ~ $$$(")")) ^^ { case _ => true } | success(false) |
|
349 |
|
350 val theory_entry = |
|
351 theory_name ~ global ^^ { case x ~ y => (x, y) } |
|
352 |
357 val theories = |
353 val theories = |
358 ($$$(GLOBAL_THEORIES) | $$$(THEORIES)) ~! |
354 $$$(THEORIES) ~! |
359 ((options | success(Nil)) ~ rep(theory_name)) ^^ |
355 ((options | success(Nil)) ~ rep(theory_entry)) ^^ |
360 { case x ~ (y ~ z) => (x == GLOBAL_THEORIES, y, z) } |
356 { case _ ~ (x ~ y) => (x, y) } |
361 |
357 |
362 val document_files = |
358 val document_files = |
363 $$$(DOCUMENT_FILES) ~! |
359 $$$(DOCUMENT_FILES) ~! |
364 (($$$("(") ~! ($$$(IN) ~! (path ~ $$$(")"))) ^^ |
360 (($$$("(") ~! ($$$(IN) ~! (path ~ $$$(")"))) ^^ |
365 { case _ ~ (_ ~ (x ~ _)) => x } | success("document")) ~ |
361 { case _ ~ (_ ~ (x ~ _)) => x } | success("document")) ~ |
392 if (!is_pure(name) && !entry.parent.isDefined) error("Missing parent session") |
388 if (!is_pure(name) && !entry.parent.isDefined) error("Missing parent session") |
393 |
389 |
394 val session_options = options ++ entry.options |
390 val session_options = options ++ entry.options |
395 |
391 |
396 val theories = |
392 val theories = |
397 entry.theories.map({ case (global, opts, thys) => |
393 entry.theories.map({ case (opts, thys) => |
398 (global, session_options ++ opts, thys.map(Path.explode(_))) }) |
394 (session_options ++ opts, thys.map(thy => Path.explode(thy._1))) }) |
|
395 |
|
396 val global_theories = |
|
397 for { (_, thys) <- entry.theories; (thy, global) <- thys if global } |
|
398 yield { |
|
399 val thy_name = Path.explode(thy).expand.base.implode |
|
400 if (Long_Name.is_qualified(thy_name)) |
|
401 error("Bad qualified name for global theory " + quote(thy_name)) |
|
402 else thy_name |
|
403 } |
|
404 |
399 val files = entry.files.map(Path.explode(_)) |
405 val files = entry.files.map(Path.explode(_)) |
400 val document_files = |
406 val document_files = |
401 entry.document_files.map({ case (s1, s2) => (Path.explode(s1), Path.explode(s2)) }) |
407 entry.document_files.map({ case (s1, s2) => (Path.explode(s1), Path.explode(s2)) }) |
402 |
408 |
403 val meta_digest = |
409 val meta_digest = |
404 SHA1.digest((entry_chapter, name, entry.parent, entry.options, |
410 SHA1.digest((entry_chapter, name, entry.parent, entry.options, |
405 entry.theories, entry.files, entry.document_files).toString) |
411 entry.theories, entry.files, entry.document_files).toString) |
406 |
412 |
407 val info = |
413 val info = |
408 Info(entry_chapter, select, entry.pos, entry.groups, dir + Path.explode(entry.path), |
414 Info(entry_chapter, select, entry.pos, entry.groups, dir + Path.explode(entry.path), |
409 entry.parent, entry.description, session_options, theories, files, |
415 entry.parent, entry.description, session_options, theories, global_theories, |
410 document_files, meta_digest) |
416 files, document_files, meta_digest) |
411 |
417 |
412 (name, info) |
418 (name, info) |
413 } |
419 } |
414 catch { |
420 catch { |
415 case ERROR(msg) => |
421 case ERROR(msg) => |