src/Pure/Syntax/syntax_phases.ML
changeset 46512 4f9f61f9b535
parent 46506 c7faa011bfa7
child 46989 88b0a8052c75
equal deleted inserted replaced
46511:fbb3c68a8d3c 46512:4f9f61f9b535
   260 (* results *)
   260 (* results *)
   261 
   261 
   262 fun proper_results results = map_filter (fn (y, Exn.Res x) => SOME (y, x) | _ => NONE) results;
   262 fun proper_results results = map_filter (fn (y, Exn.Res x) => SOME (y, x) | _ => NONE) results;
   263 fun failed_results results = map_filter (fn (y, Exn.Exn e) => SOME (y, e) | _ => NONE) results;
   263 fun failed_results results = map_filter (fn (y, Exn.Exn e) => SOME (y, e) | _ => NONE) results;
   264 
   264 
   265 fun report_result ctxt pos results =
   265 fun report_result ctxt pos ambig_msgs results =
   266   (case (proper_results results, failed_results results) of
   266   (case (proper_results results, failed_results results) of
   267     ([], (reports, exn) :: _) => (Context_Position.reports ctxt reports; reraise exn)
   267     ([], (reports, exn) :: _) => (Context_Position.reports ctxt reports; reraise exn)
   268   | ([(reports, x)], _) => (Context_Position.reports ctxt reports; x)
   268   | ([(reports, x)], _) => (Context_Position.reports ctxt reports; x)
   269   | _ => error ("Parse error: ambiguous syntax" ^ Position.str_of pos));
   269   | _ =>
       
   270       if null ambig_msgs then
       
   271         error ("Parse error: ambiguous syntax" ^ Position.str_of pos)
       
   272       else error (cat_lines ambig_msgs));
   270 
   273 
   271 
   274 
   272 (* parse raw asts *)
   275 (* parse raw asts *)
   273 
   276 
   274 fun parse_asts ctxt raw root (syms, pos) =
   277 fun parse_asts ctxt raw root (syms, pos) =
   284         error (msg ^
   287         error (msg ^
   285           implode
   288           implode
   286             (map (Markup.markup Isabelle_Markup.report o Lexicon.reported_token_range ctxt) toks));
   289             (map (Markup.markup Isabelle_Markup.report o Lexicon.reported_token_range ctxt) toks));
   287     val len = length pts;
   290     val len = length pts;
   288 
   291 
   289     val ambiguity = Config.get ctxt Syntax.ambiguity;
       
   290     val _ =
       
   291       member (op =) ["ignore", "warning", "error"] ambiguity orelse
       
   292         error ("Bad value for syntax_ambiguity: " ^ quote ambiguity);
       
   293 
       
   294     val limit = Config.get ctxt Syntax.ambiguity_limit;
   292     val limit = Config.get ctxt Syntax.ambiguity_limit;
   295 
   293     val ambig_msgs =
   296     val _ =
   294       if len <= 1 then []
   297       if len <= 1 orelse ambiguity = "ignore" then ()
       
   298       else
   295       else
   299         (if ambiguity = "error" then error else Context_Position.if_visible ctxt warning)
   296         [cat_lines
   300           (cat_lines
   297           (("Ambiguous input" ^ Position.str_of (Position.reset_range pos) ^
   301             (("Ambiguous input" ^ Position.str_of (Position.reset_range pos) ^
   298             "\nproduces " ^ string_of_int len ^ " parse trees" ^
   302               "\nproduces " ^ string_of_int len ^ " parse trees" ^
   299             (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") ::
   303               (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") ::
   300             map (Pretty.string_of o Parser.pretty_parsetree) (take limit pts))];
   304               map (Pretty.string_of o Parser.pretty_parsetree) (take limit pts)));
   301 
   305   in
   302   in (ambig_msgs, map (parsetree_to_ast ctxt raw ast_tr) pts) end;
   306     map (parsetree_to_ast ctxt raw ast_tr) pts
       
   307   end;
       
   308 
   303 
   309 fun parse_tree ctxt root input =
   304 fun parse_tree ctxt root input =
   310   let
   305   let
   311     val syn = Proof_Context.syn_of ctxt;
   306     val syn = Proof_Context.syn_of ctxt;
   312     val tr = Syntax.parse_translation syn;
   307     val tr = Syntax.parse_translation syn;
   313     val parse_rules = Syntax.parse_rules syn;
   308     val parse_rules = Syntax.parse_rules syn;
   314   in
   309     val (ambig_msgs, asts) = parse_asts ctxt false root input;
   315     parse_asts ctxt false root input
   310     val results =
   316     |> (map o apsnd o Exn.maps_result)
   311       (map o apsnd o Exn.maps_result)
   317         (Ast.normalize ctxt parse_rules #> Exn.interruptible_capture (ast_to_term ctxt tr))
   312         (Ast.normalize ctxt parse_rules #> Exn.interruptible_capture (ast_to_term ctxt tr)) asts;
   318   end;
   313   in (ambig_msgs, results) end;
   319 
   314 
   320 
   315 
   321 (* parse logical entities *)
   316 (* parse logical entities *)
   322 
   317 
   323 fun parse_failed ctxt pos msg kind =
   318 fun parse_failed ctxt pos msg kind =
   327 
   322 
   328 fun parse_sort ctxt =
   323 fun parse_sort ctxt =
   329   Syntax.parse_token ctxt Term_XML.Decode.sort Isabelle_Markup.sort
   324   Syntax.parse_token ctxt Term_XML.Decode.sort Isabelle_Markup.sort
   330     (fn (syms, pos) =>
   325     (fn (syms, pos) =>
   331       parse_tree ctxt "sort" (syms, pos)
   326       parse_tree ctxt "sort" (syms, pos)
   332       |> report_result ctxt pos
   327       |> uncurry (report_result ctxt pos)
   333       |> decode_sort
   328       |> decode_sort
   334       |> Type.minimize_sort (Proof_Context.tsig_of ctxt)
   329       |> Type.minimize_sort (Proof_Context.tsig_of ctxt)
   335       handle ERROR msg => parse_failed ctxt pos msg "sort");
   330       handle ERROR msg => parse_failed ctxt pos msg "sort");
   336 
   331 
   337 fun parse_typ ctxt =
   332 fun parse_typ ctxt =
   338   Syntax.parse_token ctxt Term_XML.Decode.typ Isabelle_Markup.typ
   333   Syntax.parse_token ctxt Term_XML.Decode.typ Isabelle_Markup.typ
   339     (fn (syms, pos) =>
   334     (fn (syms, pos) =>
   340       parse_tree ctxt "type" (syms, pos)
   335       parse_tree ctxt "type" (syms, pos)
   341       |> report_result ctxt pos
   336       |> uncurry (report_result ctxt pos)
   342       |> decode_typ
   337       |> decode_typ
   343       handle ERROR msg => parse_failed ctxt pos msg "type");
   338       handle ERROR msg => parse_failed ctxt pos msg "type");
   344 
   339 
   345 fun parse_term is_prop ctxt =
   340 fun parse_term is_prop ctxt =
   346   let
   341   let
   351     val decode = constrain o Term_XML.Decode.term;
   346     val decode = constrain o Term_XML.Decode.term;
   352   in
   347   in
   353     Syntax.parse_token ctxt decode markup
   348     Syntax.parse_token ctxt decode markup
   354       (fn (syms, pos) =>
   349       (fn (syms, pos) =>
   355         let
   350         let
   356           val results = parse_tree ctxt root (syms, pos) |> map (decode_term ctxt);
   351           val (ambig_msgs, results) = parse_tree ctxt root (syms, pos) ||> map (decode_term ctxt);
   357           val parsed_len = length (proper_results results);
   352           val parsed_len = length (proper_results results);
   358 
   353 
   359           val ambiguity = Config.get ctxt Syntax.ambiguity;
   354           val ambiguity_warning = Config.get ctxt Syntax.ambiguity_warning;
   360           val limit = Config.get ctxt Syntax.ambiguity_limit;
   355           val limit = Config.get ctxt Syntax.ambiguity_limit;
   361 
       
   362           val ambig_msg =
       
   363             if parsed_len > 1 andalso ambiguity = "ignore" then
       
   364               ["Got more than one parse tree.\n\
       
   365               \Retry with syntax_ambiguity = \"warning\" for more information."]
       
   366             else [];
       
   367 
   356 
   368           (*brute-force disambiguation via type-inference*)
   357           (*brute-force disambiguation via type-inference*)
   369           fun check t = (Syntax.check_term ctxt (constrain t); Exn.Res t)
   358           fun check t = (Syntax.check_term ctxt (constrain t); Exn.Res t)
   370             handle exn as ERROR _ => Exn.Exn exn;
   359             handle exn as ERROR _ => Exn.Exn exn;
   371 
   360 
   381           val checked_len = length checked;
   370           val checked_len = length checked;
   382 
   371 
   383           val show_term = Syntax.string_of_term (Config.put Printer.show_brackets true ctxt);
   372           val show_term = Syntax.string_of_term (Config.put Printer.show_brackets true ctxt);
   384         in
   373         in
   385           if checked_len = 0 then
   374           if checked_len = 0 then
   386             report_result ctxt pos
   375             report_result ctxt pos []
   387               [(reports', Exn.Exn (Exn.EXCEPTIONS (map ERROR ambig_msg @ errs)))]
   376               [(reports', Exn.Exn (Exn.EXCEPTIONS (map ERROR ambig_msgs @ errs)))]
   388           else if checked_len = 1 then
   377           else if checked_len = 1 then
   389             (if parsed_len > 1 andalso ambiguity <> "ignore" then
   378             (if parsed_len > 1 andalso ambiguity_warning then
   390               Context_Position.if_visible ctxt warning
   379               Context_Position.if_visible ctxt warning
   391                 ("Fortunately, only one parse tree is type correct" ^
   380                 (cat_lines (ambig_msgs @
   392                 Position.str_of (Position.reset_range pos) ^
   381                   ["Fortunately, only one parse tree is type correct" ^
   393                 ",\nbut you may still want to disambiguate your grammar or your input.")
   382                   Position.str_of (Position.reset_range pos) ^
   394             else (); report_result ctxt pos results')
   383                   ",\nbut you may still want to disambiguate your grammar or your input."]))
       
   384              else (); report_result ctxt pos [] results')
   395           else
   385           else
   396             report_result ctxt pos
   386             report_result ctxt pos []
   397               [(reports', Exn.Exn (ERROR (cat_lines (ambig_msg @
   387               [(reports', Exn.Exn (ERROR (cat_lines (ambig_msgs @
   398                 (("Ambiguous input, " ^ string_of_int checked_len ^ " terms are type correct" ^
   388                 (("Ambiguous input\n" ^ string_of_int checked_len ^ " terms are type correct" ^
   399                   (if checked_len <= limit then ""
   389                   (if checked_len <= limit then ""
   400                    else " (" ^ string_of_int limit ^ " displayed)") ^ ":") ::
   390                    else " (" ^ string_of_int limit ^ " displayed)") ^ ":") ::
   401                   map show_term (take limit checked))))))]
   391                   map show_term (take limit checked))))))]
   402         end handle ERROR msg => parse_failed ctxt pos msg kind)
   392         end handle ERROR msg => parse_failed ctxt pos msg kind)
   403   end;
   393   end;
   417       | constify (Ast.Appl asts) = Ast.Appl (map constify asts);
   407       | constify (Ast.Appl asts) = Ast.Appl (map constify asts);
   418 
   408 
   419     val (syms, pos) = Syntax.read_token str;
   409     val (syms, pos) = Syntax.read_token str;
   420   in
   410   in
   421     parse_asts ctxt true root (syms, pos)
   411     parse_asts ctxt true root (syms, pos)
   422     |> report_result ctxt pos
   412     |> uncurry (report_result ctxt pos)
   423     |> constify
   413     |> constify
   424   end;
   414   end;
   425 
   415 
   426 
   416 
   427 
   417