20 val local_theory_to_proof': command_keyword -> string -> |
20 val local_theory_to_proof': command_keyword -> string -> |
21 (bool -> local_theory -> Proof.state) parser -> unit |
21 (bool -> local_theory -> Proof.state) parser -> unit |
22 val local_theory_to_proof: command_keyword -> string -> |
22 val local_theory_to_proof: command_keyword -> string -> |
23 (local_theory -> Proof.state) parser -> unit |
23 (local_theory -> Proof.state) parser -> unit |
24 val bootstrap: bool Config.T |
24 val bootstrap: bool Config.T |
25 val parse_tokens: theory -> Token.T list -> Toplevel.transition list |
|
26 val parse: theory -> Position.T -> string -> Toplevel.transition list |
|
27 val parse_spans: Token.T list -> Command_Span.span list |
25 val parse_spans: Token.T list -> Command_Span.span list |
28 val make_span: Token.T list -> Command_Span.span |
26 val make_span: Token.T list -> Command_Span.span |
|
27 val parse_span: theory -> (unit -> theory) -> Token.T list -> Toplevel.transition |
|
28 val parse_text: theory -> (unit -> theory) -> Position.T -> string -> Toplevel.transition list |
29 val command_reports: theory -> Token.T -> Position.report_text list |
29 val command_reports: theory -> Token.T -> Position.report_text list |
30 val check_command: Proof.context -> command_keyword -> string |
30 val check_command: Proof.context -> command_keyword -> string |
31 end; |
31 end; |
32 |
32 |
33 structure Outer_Syntax: OUTER_SYNTAX = |
33 structure Outer_Syntax: OUTER_SYNTAX = |
170 |
170 |
171 |
171 |
172 |
172 |
173 (** toplevel parsing **) |
173 (** toplevel parsing **) |
174 |
174 |
|
175 (* parse spans *) |
|
176 |
|
177 local |
|
178 |
|
179 fun ship span = |
|
180 let |
|
181 val kind = |
|
182 if forall Token.is_ignored span then Command_Span.Ignored_Span |
|
183 else if exists Token.is_error span then Command_Span.Malformed_Span |
|
184 else |
|
185 (case find_first Token.is_command span of |
|
186 NONE => Command_Span.Malformed_Span |
|
187 | SOME cmd => Command_Span.Command_Span (Token.content_of cmd, Token.pos_of cmd)); |
|
188 in cons (Command_Span.Span (kind, span)) end; |
|
189 |
|
190 fun flush (result, content, ignored) = |
|
191 result |
|
192 |> not (null content) ? ship (rev content) |
|
193 |> not (null ignored) ? ship (rev ignored); |
|
194 |
|
195 fun parse tok (result, content, ignored) = |
|
196 if Token.is_ignored tok then (result, content, tok :: ignored) |
|
197 else if Token.is_command_modifier tok orelse |
|
198 Token.is_command tok andalso |
|
199 (not (exists Token.is_command_modifier content) orelse exists Token.is_command content) |
|
200 then (flush (result, content, ignored), [tok], []) |
|
201 else (result, tok :: (ignored @ content), []); |
|
202 |
|
203 in |
|
204 |
|
205 fun parse_spans toks = |
|
206 fold parse toks ([], [], []) |> flush |> rev; |
|
207 |
|
208 end; |
|
209 |
|
210 fun make_span toks = |
|
211 (case parse_spans toks of |
|
212 [span] => span |
|
213 | _ => Command_Span.Span (Command_Span.Malformed_Span, toks)); |
|
214 |
|
215 |
175 (* parse commands *) |
216 (* parse commands *) |
176 |
217 |
177 val bootstrap = Config.declare_bool ("Outer_Syntax.bootstrap", \<^here>) (K true); |
218 val bootstrap = Config.declare_bool ("Outer_Syntax.bootstrap", \<^here>) (K true); |
178 |
219 |
179 local |
220 local |
180 |
221 |
181 val before_command = |
222 val before_command = |
182 Scan.option (Parse.position (Parse.private >> K true || Parse.qualified >> K false)); |
223 Scan.option (Parse.position (Parse.private >> K true || Parse.qualified >> K false)); |
183 |
224 |
184 fun parse_command thy = |
225 fun parse_command thy markers = |
185 Scan.ahead (before_command |-- Parse.position Parse.command) :|-- (fn (name, pos) => |
226 Scan.ahead (before_command |-- Parse.position Parse.command) :|-- (fn (name, pos) => |
186 let |
227 let |
187 val keywords = Thy_Header.get_keywords thy; |
228 val keywords = Thy_Header.get_keywords thy; |
188 val tr0 = |
229 val tr0 = |
189 Toplevel.empty |
230 Toplevel.empty |
190 |> Toplevel.name name |
231 |> Toplevel.name name |
191 |> Toplevel.position pos |
232 |> Toplevel.position pos |
192 |> Keyword.is_proof_open keywords name ? Toplevel.skip_proof_open |
233 |> Keyword.is_proof_open keywords name ? Toplevel.skip_proof_open |
193 |> Keyword.is_proof_close keywords name ? Toplevel.skip_proof_close; |
234 |> Keyword.is_proof_close keywords name ? Toplevel.skip_proof_close; |
194 val command_marker = |
235 val command_markers = |
195 Parse.command |-- Document_Source.annotation >> (fn markers => Toplevel.markers markers tr0); |
236 Parse.command |-- Document_Source.tags >> |
|
237 (fn tags => Toplevel.markers (map Document_Marker.legacy_tag tags @ markers) tr0); |
196 in |
238 in |
197 (case lookup_commands thy name of |
239 (case lookup_commands thy name of |
198 SOME (Command {command_parser = Parser parse, ...}) => |
240 SOME (Command {command_parser = Parser parse, ...}) => |
199 Parse.!!! (command_marker -- parse) >> (op |>) |
241 Parse.!!! (command_markers -- parse) >> (op |>) |
200 | SOME (Command {command_parser = Restricted_Parser parse, ...}) => |
242 | SOME (Command {command_parser = Restricted_Parser parse, ...}) => |
201 before_command :|-- (fn restricted => |
243 before_command :|-- (fn restricted => |
202 Parse.!!! (command_marker -- parse restricted)) >> (op |>) |
244 Parse.!!! (command_markers -- parse restricted)) >> (op |>) |
203 | NONE => |
245 | NONE => |
204 Scan.fail_with (fn _ => fn _ => |
246 Scan.fail_with (fn _ => fn _ => |
205 let |
247 let |
206 val msg = |
248 val msg = |
207 if Config.get_global thy bootstrap |
249 if Config.get_global thy bootstrap |
210 in msg ^ quote (Markup.markup Markup.keyword1 name) end)) |
252 in msg ^ quote (Markup.markup Markup.keyword1 name) end)) |
211 end); |
253 end); |
212 |
254 |
213 in |
255 in |
214 |
256 |
215 fun parse_tokens thy = |
257 fun parse_span thy init span = |
216 filter Token.is_proper |
258 let |
217 #> Source.of_list |
259 val range = Token.range_of span; |
218 #> Source.source Token.stopper (Scan.bulk (fn xs => Parse.!!! (parse_command thy) xs)) |
260 val core_range = Token.core_range_of span; |
219 #> Source.exhaust; |
261 |
220 |
262 val markers = map Token.input_of (filter Token.is_document_marker span); |
221 fun parse thy pos text = |
263 fun parse () = |
|
264 filter Token.is_proper span |
|
265 |> Source.of_list |
|
266 |> Source.source Token.stopper (Scan.bulk (fn xs => Parse.!!! (parse_command thy markers) xs)) |
|
267 |> Source.exhaust; |
|
268 in |
|
269 (case parse () of |
|
270 [tr] => Toplevel.modify_init init tr |
|
271 | [] => Toplevel.ignored (#1 range) |
|
272 | _ => Toplevel.malformed (#1 core_range) "Exactly one command expected") |
|
273 handle ERROR msg => Toplevel.malformed (#1 core_range) msg |
|
274 end; |
|
275 |
|
276 fun parse_text thy init pos text = |
222 Symbol_Pos.explode (text, pos) |
277 Symbol_Pos.explode (text, pos) |
223 |> Token.tokenize (Thy_Header.get_keywords thy) {strict = false} |
278 |> Token.tokenize (Thy_Header.get_keywords thy) {strict = false} |
224 |> parse_tokens thy; |
279 |> parse_spans |
|
280 |> map (Command_Span.content #> parse_span thy init); |
225 |
281 |
226 end; |
282 end; |
227 |
|
228 |
|
229 (* parse spans *) |
|
230 |
|
231 local |
|
232 |
|
233 fun ship span = |
|
234 let |
|
235 val kind = |
|
236 if forall Token.is_ignored span then Command_Span.Ignored_Span |
|
237 else if exists Token.is_error span then Command_Span.Malformed_Span |
|
238 else |
|
239 (case find_first Token.is_command span of |
|
240 NONE => Command_Span.Malformed_Span |
|
241 | SOME cmd => Command_Span.Command_Span (Token.content_of cmd, Token.pos_of cmd)); |
|
242 in cons (Command_Span.Span (kind, span)) end; |
|
243 |
|
244 fun flush (result, content, ignored) = |
|
245 result |
|
246 |> not (null content) ? ship (rev content) |
|
247 |> not (null ignored) ? ship (rev ignored); |
|
248 |
|
249 fun parse tok (result, content, ignored) = |
|
250 if Token.is_ignored tok then (result, content, tok :: ignored) |
|
251 else if Token.is_command_modifier tok orelse |
|
252 Token.is_command tok andalso |
|
253 (not (exists Token.is_command_modifier content) orelse exists Token.is_command content) |
|
254 then (flush (result, content, ignored), [tok], []) |
|
255 else (result, tok :: (ignored @ content), []); |
|
256 |
|
257 in |
|
258 |
|
259 fun parse_spans toks = |
|
260 fold parse toks ([], [], []) |> flush |> rev; |
|
261 |
|
262 end; |
|
263 |
|
264 fun make_span toks = |
|
265 (case parse_spans toks of |
|
266 [span] => span |
|
267 | _ => Command_Span.Span (Command_Span.Malformed_Span, toks)); |
|
268 |
283 |
269 |
284 |
270 (* check commands *) |
285 (* check commands *) |
271 |
286 |
272 fun command_reports thy tok = |
287 fun command_reports thy tok = |