1 (* Title: Pure/Isar/args.ML |
1 (* Title: Pure/Isar/args.ML |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Markus Wenzel, TU Muenchen |
3 Author: Markus Wenzel, TU Muenchen |
4 |
4 |
5 Concrete argument syntax (for attributes, methods etc.). |
5 Concrete argument syntax (of attributes and methods). |
6 |
|
7 TODO: |
|
8 - sectioned: generalize sname to attributed thms; |
|
9 *) |
6 *) |
10 |
7 |
11 signature ARGS = |
8 signature ARGS = |
12 sig |
9 sig |
13 type T |
10 type T |
14 val val_of: T -> string |
11 val val_of: T -> string |
15 val ident: string -> T |
12 val pos_of: T -> Position.T |
16 val string: string -> T |
13 val str_of: T -> string |
17 val keyword: string -> T |
14 val ident: string * Position.T -> T |
|
15 val string: string * Position.T -> T |
|
16 val keyword: string * Position.T -> T |
18 val stopper: T * (T -> bool) |
17 val stopper: T * (T -> bool) |
19 val not_eof: T -> bool |
18 val not_eof: T -> bool |
|
19 val position: (T list -> 'a * 'b) -> T list -> ('a * Position.T) * 'b |
|
20 val !!! : (T list -> 'a) -> T list -> 'a |
20 val $$$ : string -> T list -> string * T list |
21 val $$$ : string -> T list -> string * T list |
21 val name: T list -> string * T list |
22 val name: T list -> string * T list |
22 val sectioned: string list -> T list -> (string list * (string * string list) list) * T list |
23 val nat: T list -> int * T list |
|
24 val var: T list -> indexname * T list |
|
25 val enum1: string -> (T list -> 'a * T list) -> T list -> 'a list * T list |
|
26 val enum: string -> (T list -> 'a * T list) -> T list -> 'a list * T list |
|
27 val list1: (T list -> 'a * T list) -> T list -> 'a list * T list |
|
28 val list: (T list -> 'a * T list) -> T list -> 'a list * T list |
|
29 val global_typ: theory * T list -> typ * (theory * T list) |
|
30 val global_term: theory * T list -> term * (theory * T list) |
|
31 val global_prop: theory * T list -> term * (theory * T list) |
|
32 val global_pat: theory * T list -> term * (theory * T list) |
|
33 val local_typ: Proof.context * T list -> typ * (Proof.context * T list) |
|
34 val local_term: Proof.context * T list -> term * (Proof.context * T list) |
|
35 val local_prop: Proof.context * T list -> term * (Proof.context * T list) |
|
36 val local_pat: Proof.context * T list -> term * (Proof.context * T list) |
23 type src |
37 type src |
24 val syntax: string -> (T list -> 'a * T list) -> ('a -> 'b) -> src -> 'b |
38 val src: (string * T list) * Position.T -> src |
|
39 val dest_src: src -> (string * T list) * Position.T |
|
40 val attribs: T list -> src list * T list |
|
41 val opt_attribs: T list -> src list * T list |
|
42 val syntax: string -> ('a * T list -> 'b * ('a * T list)) -> 'a -> src -> 'a * 'b |
25 end; |
43 end; |
26 |
44 |
27 structure Args: ARGS = |
45 structure Args: ARGS = |
28 struct |
46 struct |
29 |
47 |
30 |
48 |
31 (** datatype T **) |
49 (** datatype T **) |
32 |
50 |
33 datatype kind = Ident | String | Keyword | EOF; |
51 datatype kind = Ident | String | Keyword | EOF; |
34 datatype T = Arg of kind * string; |
52 datatype T = Arg of kind * (string * Position.T); |
35 |
53 |
36 fun val_of (Arg (_, x)) = x; |
54 fun val_of (Arg (_, (x, _))) = x; |
|
55 fun pos_of (Arg (_, (_, pos))) = pos; |
37 |
56 |
38 fun str_of (Arg (Ident, x)) = enclose "'" "'" x |
57 fun str_of (Arg (Ident, (x, _))) = enclose "'" "'" x |
39 | str_of (Arg (String, x)) = quote x |
58 | str_of (Arg (String, (x, _))) = quote x |
40 | str_of (Arg (Keyword, x)) = x; |
59 | str_of (Arg (Keyword, (x, _))) = x |
|
60 | str_of (Arg (EOF, _)) = "end-of-text"; |
41 |
61 |
42 fun arg kind x = Arg (kind, x); |
62 fun arg kind x_pos = Arg (kind, x_pos); |
43 val ident = arg Ident; |
63 val ident = arg Ident; |
44 val string = arg String; |
64 val string = arg String; |
45 val keyword = arg Keyword; |
65 val keyword = arg Keyword; |
46 |
66 |
47 |
67 |
48 (* eof *) |
68 (* eof *) |
49 |
69 |
50 val eof = arg EOF ""; |
70 val eof = arg EOF ("", Position.none); |
51 |
71 |
52 fun is_eof (Arg (EOF, _)) = true |
72 fun is_eof (Arg (EOF, _)) = true |
53 | is_eof _ = false; |
73 | is_eof _ = false; |
54 |
74 |
55 val stopper = (eof, is_eof); |
75 val stopper = (eof, is_eof); |
57 |
77 |
58 |
78 |
59 |
79 |
60 (** scanners **) |
80 (** scanners **) |
61 |
81 |
|
82 (* position *) |
|
83 |
|
84 fun position scan = (Scan.ahead (Scan.one not_eof) >> pos_of) -- scan >> Library.swap; |
|
85 |
|
86 |
|
87 (* cut *) |
|
88 |
|
89 fun !!! scan = |
|
90 let |
|
91 fun get_pos [] = " (past end-of-text!)" |
|
92 | get_pos (Arg (_, (_, pos)) :: _) = Position.str_of pos; |
|
93 |
|
94 fun err (args, None) = "Argument syntax error" ^ get_pos args |
|
95 | err (args, Some msg) = "Argument syntax error" ^ get_pos args ^ ": " ^ msg; |
|
96 in Scan.!! err scan end; |
|
97 |
|
98 |
62 (* basic *) |
99 (* basic *) |
63 |
100 |
64 fun $$$ x = Scan.one (fn Arg (k, y) => (k = Ident orelse k = Keyword) andalso x = y) >> val_of; |
101 fun $$$$ x = Scan.one (fn Arg (k, (y, _)) => (k = Ident orelse k = Keyword) andalso x = y); |
65 val name = Scan.one (fn (Arg (k, x)) => k = Ident orelse k = String) >> val_of; |
102 fun $$$ x = $$$$ x >> val_of; |
|
103 |
|
104 val name = Scan.one (fn Arg (k, (x, _)) => k = Ident orelse k = String) >> val_of; |
|
105 |
|
106 fun kind f = Scan.one (K true) :-- |
|
107 (fn Arg (Ident, (x, _)) => |
|
108 (case f x of Some y => Scan.succeed y | _ => Scan.fail) |
|
109 | _ => Scan.fail) >> #2; |
|
110 |
|
111 val nat = kind Syntax.read_nat; |
|
112 val var = kind (apsome #1 o try Term.dest_Var o Syntax.read_var); |
66 |
113 |
67 |
114 |
68 (* sections *) |
115 (* enumerations *) |
69 |
116 |
70 val no_colon = Scan.one (fn Arg (k, x) => k = String orelse x <> ":"); |
117 fun enum1 sep scan = scan -- Scan.repeat ($$$ sep |-- scan) >> op ::; |
71 val sname = name --| Scan.ahead no_colon; |
118 fun enum sep scan = enum1 sep scan || Scan.succeed []; |
72 |
119 |
73 fun sect s = ($$$ s --| $$$ ":") -- Scan.repeat sname; |
120 fun list1 scan = enum1 "," scan; |
|
121 fun list scan = enum "," scan; |
74 |
122 |
75 fun any_sect [] = Scan.fail |
|
76 | any_sect (s :: ss) = sect s || any_sect ss; |
|
77 |
123 |
78 fun sectioned ss = |
124 (* terms and types *) |
79 Scan.repeat sname -- Scan.repeat (any_sect ss); |
125 |
|
126 fun gen_item read = Scan.depend (fn st => name >> (pair st o read st)); |
|
127 |
|
128 val global_typ = gen_item (ProofContext.read_typ o ProofContext.init); |
|
129 val global_term = gen_item (ProofContext.read_term o ProofContext.init); |
|
130 val global_prop = gen_item (ProofContext.read_prop o ProofContext.init); |
|
131 val global_pat = gen_item (ProofContext.read_pat o ProofContext.init); |
|
132 |
|
133 val local_typ = gen_item ProofContext.read_typ; |
|
134 val local_term = gen_item ProofContext.read_term; |
|
135 val local_prop = gen_item ProofContext.read_prop; |
|
136 val local_pat = gen_item ProofContext.read_pat; |
|
137 |
|
138 |
|
139 (* args *) |
|
140 |
|
141 val exclude = explode "(){}[],"; |
|
142 |
|
143 fun atom_arg blk = Scan.one (fn Arg (k, (x, _)) => |
|
144 k <> Keyword orelse not (x mem exclude) orelse blk andalso x = ","); |
|
145 |
|
146 fun paren_args l r scan = $$$$ l -- !!! (scan true -- $$$$ r) |
|
147 >> (fn (x, (ys, z)) => x :: ys @ [z]); |
|
148 |
|
149 fun args blk x = Scan.optional (args1 blk) [] x |
|
150 and args1 blk x = |
|
151 ((Scan.repeat1 |
|
152 (Scan.repeat1 (atom_arg blk) || |
|
153 paren_args "(" ")" args || |
|
154 paren_args "{" "}" args || |
|
155 paren_args "[" "]" args)) >> flat) x; |
80 |
156 |
81 |
157 |
82 |
158 |
83 (** type src **) |
159 (** type src **) |
84 |
160 |
85 type src = (string * T list) * Position.T; |
161 datatype src = Src of (string * T list) * Position.T; |
86 |
162 |
87 fun err_in_src kind msg ((s, args), pos) = |
163 val src = Src; |
88 error (space_implode " " (kind :: s :: map str_of args) ^ Position.str_of pos ^ ": " ^ msg); |
164 fun dest_src (Src src) = src; |
|
165 |
|
166 fun err_in_src kind msg (Src ((s, args), pos)) = |
|
167 error (kind ^ " " ^ s ^ Position.str_of pos ^ ": " ^ msg ^ "\n " ^ |
|
168 space_implode " " (map str_of args)); |
89 |
169 |
90 |
170 |
91 (* argument syntax *) |
171 (* argument syntax *) |
92 |
172 |
93 fun syntax kind scan f (src as ((s, args), pos)) = |
173 (* FIXME *) |
94 (case handle_error (Scan.error (Scan.finite stopper scan)) args of |
174 fun trace_src kind (Src ((s, args), pos)) = |
95 OK (x, []) => f x |
175 warning ("TRACE: " ^ space_implode " " (kind :: s :: map str_of args) ^ Position.str_of pos); |
96 | OK (_, args') => err_in_src kind "bad arguments" ((s, args'), pos) |
176 |
97 | Error msg => err_in_src kind ("\n" ^ msg) src); |
177 fun syntax kind scan st (src as Src ((s, args), pos)) = |
|
178 (trace_src kind src; |
|
179 (case handle_error (Scan.error (Scan.finite' stopper (Scan.option scan))) (st, args) of |
|
180 OK (Some x, (st', [])) => (st', x) |
|
181 | OK (_, (_, args')) => err_in_src kind "bad arguments" (Src ((s, args'), pos)) |
|
182 | Error msg => err_in_src kind ("\n" ^ msg) src)); |
|
183 |
|
184 |
|
185 (* attribs *) |
|
186 |
|
187 val attrib = position (name -- !!! (args false)) >> src; |
|
188 val attribs = $$$ "[" |-- !!! (list attrib --| $$$ "]"); |
|
189 val opt_attribs = Scan.optional attribs []; |
98 |
190 |
99 |
191 |
100 end; |
192 end; |