20 type Options = List[(String, Option[String])] |
20 type Options = List[(String, Option[String])] |
21 |
21 |
22 case class Session_Info( |
22 case class Session_Info( |
23 dir: Path, |
23 dir: Path, |
24 name: String, |
24 name: String, |
25 parent: String, |
25 parent: Option[String], |
26 description: String, |
26 description: String, |
27 options: Options, |
27 options: Options, |
28 theories: List[(Options, String)], |
28 theories: List[(Options, String)], |
29 files: List[String]) |
29 files: List[String]) |
30 |
|
31 private val pure_info = |
|
32 Session_Info(Path.current, "Pure", "", "", Nil, List((Nil, "Pure")), Nil) |
|
33 |
30 |
34 |
31 |
35 /* parsing */ |
32 /* parsing */ |
36 |
33 |
37 val ROOT_NAME = "ROOT" |
34 val ROOT_NAME = "ROOT" |
38 |
35 |
39 private case class Session_Entry( |
36 private case class Session_Entry( |
40 name: String, |
37 name: String, |
41 reset: Boolean, |
38 reset: Boolean, |
42 path: Option[String], |
39 path: Option[String], |
43 parent: String, |
40 parent: Option[String], |
44 description: String, |
41 description: String, |
45 options: Options, |
42 options: Options, |
46 theories: List[(Options, List[String])], |
43 theories: List[(Options, List[String])], |
47 files: List[String]) |
44 files: List[String]) |
48 |
45 |
73 { case _ ~ (x ~ y) => (x, y) } |
70 { case _ ~ (x ~ y) => (x, y) } |
74 |
71 |
75 ((keyword(SESSION) ~! session_name) ^^ { case _ ~ x => x }) ~ |
72 ((keyword(SESSION) ~! session_name) ^^ { case _ ~ x => x }) ~ |
76 (keyword("!") ^^^ true | success(false)) ~ |
73 (keyword("!") ^^^ true | success(false)) ~ |
77 (opt(keyword(IN) ~! string ^^ { case _ ~ x => x })) ~ |
74 (opt(keyword(IN) ~! string ^^ { case _ ~ x => x })) ~ |
78 (keyword("=") ~> session_name <~ keyword("+")) ~ |
75 (keyword("=") ~> opt(session_name <~ keyword("+"))) ~ |
79 (keyword(DESCRIPTION) ~! text ^^ { case _ ~ x => x } | success("")) ~ |
76 (keyword(DESCRIPTION) ~! text ^^ { case _ ~ x => x } | success("")) ~ |
80 (keyword(OPTIONS) ~! options ^^ { case _ ~ x => x } | success(Nil)) ~ |
77 (keyword(OPTIONS) ~! options ^^ { case _ ~ x => x } | success(Nil)) ~ |
81 rep1(theories) ~ |
78 rep(theories) ~ |
82 (keyword(FILES) ~! rep1(path) ^^ { case _ ~ x => x } | success(Nil)) ^^ |
79 (keyword(FILES) ~! rep1(path) ^^ { case _ ~ x => x } | success(Nil)) ^^ |
83 { case a ~ b ~ c ~ d ~ e ~ f ~ g ~ h => Session_Entry(a, b, c, d, e, f, g, h) } |
80 { case a ~ b ~ c ~ d ~ e ~ f ~ g ~ h => Session_Entry(a, b, c, d, e, f, g, h) } |
84 } |
81 } |
85 |
82 |
86 def parse_entries(root: File): List[Session_Entry] = |
83 def parse_entries(root: File): List[Session_Entry] = |
97 /* find sessions */ |
94 /* find sessions */ |
98 |
95 |
99 def find_sessions(more_dirs: List[Path]): List[Session_Info] = |
96 def find_sessions(more_dirs: List[Path]): List[Session_Info] = |
100 { |
97 { |
101 val infos = new mutable.ListBuffer[Session_Info] |
98 val infos = new mutable.ListBuffer[Session_Info] |
102 infos += pure_info |
|
103 |
99 |
104 for { |
100 for { |
105 (dir, strict) <- Isabelle_System.components().map((_, false)) ++ more_dirs.map((_, true)) |
101 (dir, strict) <- Isabelle_System.components().map((_, false)) ++ more_dirs.map((_, true)) |
106 root = Isabelle_System.platform_file(dir + Path.basic(ROOT_NAME)) |
102 root = Isabelle_System.platform_file(dir + Path.basic(ROOT_NAME)) |
107 _ = (strict && !root.isFile && error("Bad session root file: " + quote(root.toString))) |
103 _ = (strict && !root.isFile && error("Bad session root file: " + quote(root.toString))) |
108 if root.isFile |
104 if root.isFile |
109 entry <- Parser.parse_entries(root) |
105 entry <- Parser.parse_entries(root) |
110 } |
106 } |
111 { |
107 { |
112 try { |
108 try { |
113 val parent = |
109 if (entry.name == "") error("Bad session name") |
114 infos.find(_.name == entry.parent) getOrElse |
110 |
115 error("Unknown parent session: " + quote(entry.parent)) |
|
116 val full_name = |
111 val full_name = |
117 if (entry.reset) entry.name |
112 if (entry.name == "RAW" || entry.name == "Pure") { |
118 else parent.name + "-" + entry.name |
113 if (entry.parent.isDefined) error("Illegal parent session") |
119 |
114 else entry.name |
120 if (entry.name == "") error("Bad session name") |
115 } |
121 if (infos.exists(_.name == full_name)) |
116 else |
122 error("Duplicate session name: " + quote(full_name)) |
117 entry.parent match { |
|
118 case None => error("Missing parent session") |
|
119 case Some(parent) => |
|
120 val parent_info = |
|
121 infos.find(_.name == parent) getOrElse |
|
122 error("Undefined parent session: " + quote(parent)) |
|
123 if (entry.reset) entry.name |
|
124 else parent_info.name + "-" + entry.name |
|
125 } |
123 |
126 |
124 val path = |
127 val path = |
125 entry.path match { |
128 entry.path match { |
126 case Some(p) => Path.explode(p) |
129 case Some(p) => Path.explode(p) |
127 case None => Path.basic(entry.name) |
130 case None => Path.basic(entry.name) |
129 val thys = entry.theories.map({ case (x, ys) => ys.map(y => (x, y)) }).flatten |
132 val thys = entry.theories.map({ case (x, ys) => ys.map(y => (x, y)) }).flatten |
130 val info = |
133 val info = |
131 Session_Info(dir + path, full_name, entry.parent, entry.description, |
134 Session_Info(dir + path, full_name, entry.parent, entry.description, |
132 entry.options, thys, entry.files) |
135 entry.options, thys, entry.files) |
133 |
136 |
|
137 if (infos.exists(_.name == full_name)) |
|
138 error("Duplicate session: " + quote(full_name)) |
134 infos += info |
139 infos += info |
135 } |
140 } |
136 catch { |
141 catch { |
137 case ERROR(msg) => |
142 case ERROR(msg) => |
138 error(msg + "\nThe error(s) above occurred in session entry " + |
143 error(msg + "\nThe error(s) above occurred in session entry " + |