1 (* Title: Pure/ProofGeneral/pgip_parser.ML
2 Author: David Aspinall and Makarius
4 Parsing theory sources without execution (via keyword classification).
7 signature PGIP_PARSER =
9 val pgip_parser: Position.T -> string -> PgipMarkup.pgipdocument
12 structure PgipParser: PGIP_PARSER =
15 structure D = PgipMarkup;
16 structure I = PgipIsabelle;
19 fun badcmd text = [D.Badcmd {text = text}];
22 (case try (Thy_Header.read Position.none) (Source.of_string text) of
23 NONE => D.Opentheory {thyname = NONE, parentnames = [], text = text}
24 | SOME (name, imports, _) =>
25 D.Opentheory {thyname = SOME name, parentnames = imports, text = text})
26 :: [D.Openblock {metavarid = NONE, name = NONE, objtype = SOME I.ObjTheoryBody}];
28 fun thy_heading text =
30 D.Doccomment {text = text},
31 D.Openblock {metavarid = NONE, name = NONE, objtype = SOME I.ObjTheoryBody}];
34 [D.Theoryitem {name = NONE, objtype = SOME I.ObjTheoryDecl, text = text}];
37 [D.Opengoal {thmname = NONE, text = text},
38 D.Openblock {metavarid = NONE, name = NONE, objtype = SOME I.ObjProofBody}];
42 D.Proofstep {text = text},
43 D.Openblock {metavarid = NONE, name = NONE, objtype = SOME I.ObjProofBody}];
46 [D.Openblock {metavarid = NONE, name = NONE, objtype = SOME I.ObjProofBody},
47 D.Proofstep {text = text}];
49 fun proofstep text = [D.Proofstep {text = text}];
50 fun closegoal text = [D.Closegoal {text = text}, D.Closeblock {}];
53 fun command k f = Symtab.update_new (Keyword.kind_of k, f);
55 val command_keywords = Symtab.empty
56 |> command Keyword.control badcmd
57 |> command Keyword.diag (fn text => [D.Spuriouscmd {text = text}])
58 |> command Keyword.thy_begin thy_begin
59 |> command Keyword.thy_switch badcmd
60 |> command Keyword.thy_end (fn text => [D.Closeblock {}, D.Closetheory {text = text}])
61 |> command Keyword.thy_heading thy_heading
62 |> command Keyword.thy_decl thy_decl
63 |> command Keyword.thy_script thy_decl
64 |> command Keyword.thy_goal goal
65 |> command Keyword.thy_schematic_goal goal
66 |> command Keyword.qed closegoal
67 |> command Keyword.qed_block closegoal
68 |> command Keyword.qed_global (fn text => [D.Giveupgoal {text = text}])
69 |> command Keyword.prf_heading (fn text => [D.Doccomment {text = text}])
70 |> command Keyword.prf_goal goal
71 |> command Keyword.prf_block prf_block
72 |> command Keyword.prf_open prf_open
73 |> command Keyword.prf_close (fn text => [D.Proofstep {text = text}, D.Closeblock {}])
74 |> command Keyword.prf_chain proofstep
75 |> command Keyword.prf_decl proofstep
76 |> command Keyword.prf_asm proofstep
77 |> command Keyword.prf_asm_goal goal
78 |> command Keyword.prf_script proofstep;
80 val _ = subset (op =) (Keyword.kinds, Symtab.keys command_keywords)
81 orelse sys_error "Incomplete coverage of command keywords";
83 fun parse_command "sorry" text = [D.Postponegoal {text = text}, D.Closeblock {}]
84 | parse_command name text =
85 (case Keyword.command_keyword name of
86 NONE => [D.Unparseable {text = text}]
88 (case Symtab.lookup command_keywords (Keyword.kind_of k) of
89 NONE => [D.Unparseable {text = text}]
94 val kind = Thy_Syntax.span_kind span;
95 val toks = Thy_Syntax.span_content span;
96 val text = implode (map (Print_Mode.setmp [] Thy_Syntax.present_token) toks);
99 Thy_Syntax.Command name => parse_command name text
100 | Thy_Syntax.Ignored => [D.Whitespace {text = text}]
101 | Thy_Syntax.Malformed => [D.Unparseable {text = text}])
105 fun pgip_parser pos str =
106 maps parse_span (Thy_Syntax.parse_spans (Keyword.get_lexicons ()) pos str);