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 |