src/Pure/Isar/outer_syntax.ML
changeset 69891 def3ec9cdb7e
parent 69887 b9985133805d
child 70134 e69f00f4b897
equal deleted inserted replaced
69890:cb643a1a5313 69891:def3ec9cdb7e
    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 =