93 val string_of_term_global: theory -> term -> string |
93 val string_of_term_global: theory -> term -> string |
94 val string_of_typ_global: theory -> typ -> string |
94 val string_of_typ_global: theory -> typ -> string |
95 val string_of_sort_global: theory -> sort -> string |
95 val string_of_sort_global: theory -> sort -> string |
96 val pp: Proof.context -> Pretty.pp |
96 val pp: Proof.context -> Pretty.pp |
97 val pp_global: theory -> Pretty.pp |
97 val pp_global: theory -> Pretty.pp |
|
98 type ruletab |
98 type syntax |
99 type syntax |
|
100 val rep_syntax: syntax -> |
|
101 {input: Syn_Ext.xprod list, |
|
102 lexicon: Scan.lexicon, |
|
103 gram: Parser.gram, |
|
104 consts: string list, |
|
105 prmodes: string list, |
|
106 parse_ast_trtab: ((Proof.context -> Ast.ast list -> Ast.ast) * stamp) Symtab.table, |
|
107 parse_ruletab: ruletab, |
|
108 parse_trtab: ((Proof.context -> term list -> term) * stamp) Symtab.table, |
|
109 print_trtab: ((Proof.context -> bool -> typ -> term list -> term) * stamp) list Symtab.table, |
|
110 print_ruletab: ruletab, |
|
111 print_ast_trtab: ((Proof.context -> Ast.ast list -> Ast.ast) * stamp) list Symtab.table, |
|
112 tokentrtab: (string * (string * ((Proof.context -> string -> Pretty.T) * stamp)) list) list, |
|
113 prtabs: Printer.prtabs} |
99 val eq_syntax: syntax * syntax -> bool |
114 val eq_syntax: syntax * syntax -> bool |
100 val is_keyword: syntax -> string -> bool |
115 val is_keyword: syntax -> string -> bool |
101 type mode |
116 type mode |
102 val mode_default: mode |
117 val mode_default: mode |
103 val mode_input: mode |
118 val mode_input: mode |
112 val positions: bool Config.T |
127 val positions: bool Config.T |
113 val ambiguity_enabled: bool Config.T |
128 val ambiguity_enabled: bool Config.T |
114 val ambiguity_level_raw: Config.raw |
129 val ambiguity_level_raw: Config.raw |
115 val ambiguity_level: int Config.T |
130 val ambiguity_level: int Config.T |
116 val ambiguity_limit: int Config.T |
131 val ambiguity_limit: int Config.T |
117 val standard_parse_sort: Proof.context -> type_context -> syntax -> |
|
118 Symbol_Pos.T list * Position.T -> sort |
|
119 val standard_parse_typ: Proof.context -> type_context -> syntax -> |
|
120 ((indexname * sort) list -> indexname -> sort) -> Symbol_Pos.T list * Position.T -> typ |
|
121 val standard_parse_term: (term -> term Exn.result) -> |
|
122 Proof.context -> type_context -> term_context -> syntax -> |
|
123 string -> Symbol_Pos.T list * Position.T -> term |
|
124 datatype 'a trrule = |
132 datatype 'a trrule = |
125 Parse_Rule of 'a * 'a | |
133 Parse_Rule of 'a * 'a | |
126 Print_Rule of 'a * 'a | |
134 Print_Rule of 'a * 'a | |
127 Parse_Print_Rule of 'a * 'a |
135 Parse_Print_Rule of 'a * 'a |
128 val map_trrule: ('a -> 'b) -> 'a trrule -> 'b trrule |
136 val map_trrule: ('a -> 'b) -> 'a trrule -> 'b trrule |
129 val is_const: syntax -> string -> bool |
137 val is_const: syntax -> string -> bool |
130 val read_rule_pattern: Proof.context -> type_context -> syntax -> string * string -> Ast.ast |
|
131 val standard_unparse_sort: {extern_class: string -> xstring} -> |
138 val standard_unparse_sort: {extern_class: string -> xstring} -> |
132 Proof.context -> syntax -> sort -> Pretty.T |
139 Proof.context -> syntax -> sort -> Pretty.T |
133 val standard_unparse_typ: {extern_class: string -> xstring, extern_type: string -> xstring} -> |
140 val standard_unparse_typ: {extern_class: string -> xstring, extern_type: string -> xstring} -> |
134 Proof.context -> syntax -> typ -> Pretty.T |
141 Proof.context -> syntax -> typ -> Pretty.T |
135 val standard_unparse_term: {structs: string list, fixes: string list} -> |
142 val standard_unparse_term: {structs: string list, fixes: string list} -> |
482 print_ruletab: ruletab, |
487 print_ruletab: ruletab, |
483 print_ast_trtab: ((Proof.context -> Ast.ast list -> Ast.ast) * stamp) list Symtab.table, |
488 print_ast_trtab: ((Proof.context -> Ast.ast list -> Ast.ast) * stamp) list Symtab.table, |
484 tokentrtab: (string * (string * ((Proof.context -> string -> Pretty.T) * stamp)) list) list, |
489 tokentrtab: (string * (string * ((Proof.context -> string -> Pretty.T) * stamp)) list) list, |
485 prtabs: Printer.prtabs} * stamp; |
490 prtabs: Printer.prtabs} * stamp; |
486 |
491 |
|
492 fun rep_syntax (Syntax (tabs, _)) = tabs; |
487 fun eq_syntax (Syntax (_, s1), Syntax (_, s2)) = s1 = s2; |
493 fun eq_syntax (Syntax (_, s1), Syntax (_, s2)) = s1 = s2; |
488 |
494 |
489 fun is_keyword (Syntax ({lexicon, ...}, _)) = Scan.is_literal lexicon o Symbol.explode; |
495 fun is_keyword (Syntax ({lexicon, ...}, _)) = Scan.is_literal lexicon o Symbol.explode; |
490 |
496 |
491 type mode = string * bool; |
497 type mode = string * bool; |
698 val ambiguity_level = Config.int ambiguity_level_raw; |
704 val ambiguity_level = Config.int ambiguity_level_raw; |
699 |
705 |
700 val ambiguity_limit = |
706 val ambiguity_limit = |
701 Config.int (Config.declare "syntax_ambiguity_limit" (fn _ => Config.Int 10)); |
707 Config.int (Config.declare "syntax_ambiguity_limit" (fn _ => Config.Int 10)); |
702 |
708 |
703 fun ambiguity_msg pos = "Parse error: ambiguous syntax" ^ Position.str_of pos; |
|
704 |
|
705 |
|
706 (* results *) |
|
707 |
|
708 fun proper_results results = map_filter (fn (y, Exn.Result x) => SOME (y, x) | _ => NONE) results; |
|
709 fun failed_results results = map_filter (fn (y, Exn.Exn e) => SOME (y, e) | _ => NONE) results; |
|
710 |
|
711 fun report ctxt = List.app (fn (pos, m) => Context_Position.report ctxt pos m); |
|
712 |
|
713 fun report_result ctxt pos results = |
|
714 (case (proper_results results, failed_results results) of |
|
715 ([], (reports, exn) :: _) => (report ctxt reports; reraise exn) |
|
716 | ([(reports, x)], _) => (report ctxt reports; x) |
|
717 | _ => error (ambiguity_msg pos)); |
|
718 |
|
719 |
|
720 (* read_asts *) |
|
721 |
|
722 fun read_asts ctxt type_ctxt (Syntax (tabs, _)) raw root (syms, pos) = |
|
723 let |
|
724 val {lexicon, gram, parse_ast_trtab, ...} = tabs; |
|
725 val toks = Lexicon.tokenize lexicon raw syms; |
|
726 val _ = List.app (Lexicon.report_token ctxt) toks; |
|
727 |
|
728 val pts = Parser.parse ctxt gram root (filter Lexicon.is_proper toks) |
|
729 handle ERROR msg => |
|
730 error (msg ^ |
|
731 implode (map (Markup.markup Markup.report o Lexicon.reported_token_range ctxt) toks)); |
|
732 val len = length pts; |
|
733 |
|
734 val limit = Config.get ctxt ambiguity_limit; |
|
735 val _ = |
|
736 if len <= Config.get ctxt ambiguity_level then () |
|
737 else if not (Config.get ctxt ambiguity_enabled) then error (ambiguity_msg pos) |
|
738 else |
|
739 (Context_Position.if_visible ctxt warning (cat_lines |
|
740 (("Ambiguous input" ^ Position.str_of pos ^ |
|
741 "\nproduces " ^ string_of_int len ^ " parse trees" ^ |
|
742 (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") :: |
|
743 map (Pretty.string_of o Parser.pretty_parsetree) (take limit pts)))); |
|
744 |
|
745 val constrain_pos = not raw andalso Config.get ctxt positions; |
|
746 val parsetree_to_ast = |
|
747 Syn_Trans.parsetree_to_ast ctxt type_ctxt constrain_pos (lookup_tr parse_ast_trtab); |
|
748 in map parsetree_to_ast pts end; |
|
749 |
|
750 |
|
751 (* read_raw *) |
|
752 |
|
753 fun read_raw ctxt type_ctxt (syn as Syntax (tabs, _)) root input = |
|
754 let |
|
755 val {parse_ruletab, parse_trtab, ...} = tabs; |
|
756 val norm = Ast.normalize ctxt (Symtab.lookup_list parse_ruletab); |
|
757 val ast_to_term = Syn_Trans.ast_to_term ctxt (lookup_tr parse_trtab); |
|
758 in |
|
759 read_asts ctxt type_ctxt syn false root input |
|
760 |> (map o apsnd o Exn.maps_result) (norm #> Exn.interruptible_capture ast_to_term) |
|
761 end; |
|
762 |
|
763 |
|
764 (* read sorts *) |
|
765 |
|
766 fun standard_parse_sort ctxt type_ctxt syn (syms, pos) = |
|
767 read_raw ctxt type_ctxt syn (Syn_Ext.typ_to_nonterm Type_Ext.sortT) (syms, pos) |
|
768 |> report_result ctxt pos |
|
769 |> Type_Ext.sort_of_term; |
|
770 |
|
771 |
|
772 (* read types *) |
|
773 |
|
774 fun standard_parse_typ ctxt type_ctxt syn get_sort (syms, pos) = |
|
775 read_raw ctxt type_ctxt syn (Syn_Ext.typ_to_nonterm Syn_Ext.typeT) (syms, pos) |
|
776 |> report_result ctxt pos |
|
777 |> (fn t => Type_Ext.typ_of_term (get_sort (Type_Ext.term_sorts t)) t); |
|
778 |
|
779 |
|
780 (* read terms -- brute-force disambiguation via type-inference *) |
|
781 |
|
782 fun standard_parse_term check ctxt type_ctxt term_ctxt syn root (syms, pos) = |
|
783 let |
|
784 val results = |
|
785 read_raw ctxt type_ctxt syn root (syms, pos) |
|
786 |> map (Type_Ext.decode_term term_ctxt); |
|
787 |
|
788 val level = Config.get ctxt ambiguity_level; |
|
789 val limit = Config.get ctxt ambiguity_limit; |
|
790 |
|
791 val ambiguity = length (proper_results results); |
|
792 |
|
793 fun ambig_msg () = |
|
794 if ambiguity > 1 andalso ambiguity <= level then |
|
795 "Got more than one parse tree.\n\ |
|
796 \Retry with smaller syntax_ambiguity_level for more information." |
|
797 else ""; |
|
798 |
|
799 val results' = |
|
800 if ambiguity > 1 then |
|
801 (Par_List.map_name "Syntax.disambig" o apsnd o Exn.maps_result) check results |
|
802 else results; |
|
803 val reports' = fst (hd results'); |
|
804 |
|
805 val errs = map snd (failed_results results'); |
|
806 val checked = map snd (proper_results results'); |
|
807 val len = length checked; |
|
808 |
|
809 val show_term = string_of_term (Config.put Printer.show_brackets true ctxt); |
|
810 in |
|
811 if len = 0 then |
|
812 report_result ctxt pos |
|
813 [(reports', Exn.Exn (Exn.EXCEPTIONS (ERROR (ambig_msg ()) :: errs)))] |
|
814 else if len = 1 then |
|
815 (if ambiguity > level then |
|
816 Context_Position.if_visible ctxt warning |
|
817 "Fortunately, only one parse tree is type correct.\n\ |
|
818 \You may still want to disambiguate your grammar or your input." |
|
819 else (); report_result ctxt pos results') |
|
820 else |
|
821 report_result ctxt pos |
|
822 [(reports', Exn.Exn (ERROR (cat_lines (ambig_msg () :: |
|
823 (("Ambiguous input, " ^ string_of_int len ^ " terms are type correct" ^ |
|
824 (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") :: |
|
825 map show_term (take limit checked))))))] |
|
826 end; |
|
827 |
|
828 |
709 |
829 |
710 |
830 (** prepare translation rules **) |
711 (** prepare translation rules **) |
831 |
712 |
832 (* rules *) |
713 (* rules *) |
868 fun check_rules rules = |
749 fun check_rules rules = |
869 (map check_rule (map_filter parse_rule rules), |
750 (map check_rule (map_filter parse_rule rules), |
870 map check_rule (map_filter print_rule rules)); |
751 map check_rule (map_filter print_rule rules)); |
871 |
752 |
872 end; |
753 end; |
873 |
|
874 |
|
875 (* read_rule_pattern *) |
|
876 |
|
877 fun read_rule_pattern ctxt type_ctxt syn (root, str) = |
|
878 let |
|
879 fun constify (ast as Ast.Constant _) = ast |
|
880 | constify (ast as Ast.Variable x) = |
|
881 if is_const syn x orelse Long_Name.is_qualified x then Ast.Constant x |
|
882 else ast |
|
883 | constify (Ast.Appl asts) = Ast.Appl (map constify asts); |
|
884 |
|
885 val (syms, pos) = read_token str; |
|
886 in |
|
887 read_asts ctxt type_ctxt syn true root (syms, pos) |
|
888 |> report_result ctxt pos |
|
889 |> constify |
|
890 end; |
|
891 |
754 |
892 |
755 |
893 |
756 |
894 (** unparse terms, typs, sorts **) |
757 (** unparse terms, typs, sorts **) |
895 |
758 |