1 (* ========================================================================= *)
2 (* Lexical analyzer, type and preterm parsers. *)
4 (* John Harrison, University of Cambridge Computer Laboratory *)
6 (* (c) Copyright, University of Cambridge 1998 *)
7 (* (c) Copyright, John Harrison 1998-2007 *)
8 (* ========================================================================= *)
11 Slightly more verbose error messages added by thales, July 2010
16 module Parser_verbose = struct
18 let string_of_lexcode = function
22 let string_of_lexcodel r = itlist (fun a b -> string_of_lexcode a^" "^b) r "";;
24 let err_lex_rest prs i =
26 Failure s -> failwith (s^ "\n unread tokens:\n"^string_of_lexcodel i);;
28 let parse_pretype_verbose =
29 let btyop n n' x y = Ptycon(n,[x;y])
33 | (tys,[c]) -> Ptycon(c,tys)
34 | _ -> failwith "Bad type construction"
38 (try pretype_of_type(assoc s (type_abbrevs())) with Failure _ ->
39 if try get_type_arity s = 0 with Failure _ -> false
40 then Ptycon(s,[]) else Utv(s)),rest
42 and type_constructor input =
44 (Ident s)::rest -> if try get_type_arity s > 0 with Failure _ -> false
45 then s,rest else raise Noparse
46 | _ -> raise Noparse in
47 let rec pretype i = rightbin sumtype (a (Resword "->")) (btyop "fun") "proper use of type operator (->)" i
48 and sumtype i = rightbin prodtype (a (Ident "+")) (btyop "sum") "proper use of type operator (+)" i
49 and prodtype i = rightbin carttype (a (Ident "#")) (btyop "prod") "proper use of type operator (#)" i
50 and carttype i = leftbin apptype (a (Ident "^")) (btyop "cart") " proper use of type operator (^) " i
51 and apptype i = (atomictypes ++ (type_constructor >> (fun x -> [x])
52 || nothing) >> mk_apptype) i
54 (((a (Resword "(")) ++ typelist ++ a (Resword ")") >> (snd o fst))
55 || type_atom >> (fun x -> [x])) i
56 and typelist i = listof pretype (a (Ident ",")) "comma separated list for type constructor" i in
59 let parse_preterm_verbose =
60 let rec pfrees ptm acc =
63 if v = "" & pty = dpty then acc
64 else if can get_const_type v or can num_of_string v
65 or exists (fun (w,_) -> v = w) (!the_interface) then acc
68 | Combp(p1,p2) -> pfrees p1 (pfrees p2 acc)
69 | Absp(p1,p2) -> subtract (pfrees p2 acc) (pfrees p1 [])
70 | Typing(p,_) -> pfrees p acc in
71 let pdest_eq (Combp(Combp(Varp(("="|"<=>"),_),l),r)) = l,r in
72 let pmk_let (letbindings,body) =
73 let vars,tms = unzip (map pdest_eq letbindings) in
74 let lend = Combp(Varp("LET_END",dpty),body) in
75 let abs = itlist (fun v t -> Absp(v,t)) vars lend in
76 let labs = Combp(Varp("LET",dpty),abs) in
77 rev_itlist (fun x f -> Combp(f,x)) tms labs in
78 let pmk_vbinder(n,v,bod) =
79 if n = "\\" then Absp(v,bod)
80 else Combp(Varp(n,dpty),Absp(v,bod)) in
81 let pmk_binder(n,vs,bod) =
82 itlist (fun v b -> pmk_vbinder(n,v,b)) vs bod in
83 let pmk_set_enum ptms =
84 itlist (fun x t -> Combp(Combp(Varp("INSERT",dpty),x),t)) ptms
85 (Varp("EMPTY",dpty)) in
87 let gcounter = ref 0 in
88 fun () -> let count = !gcounter in
89 (gcounter := count + 1;
90 Varp("GEN%PVAR%"^(string_of_int count),dpty)) in
91 let pmk_exists(v,ptm) = Combp(Varp("?",dpty),Absp(v,ptm)) in
93 itlist (fun x y -> Combp(Combp(Varp("CONS",dpty),x),y))
94 els (Varp("NIL",dpty)) in
96 let tt = Varp("T",dpty) and ff = Varp("F",dpty) in
97 fun b -> if b then tt else ff in
99 let lis = map (fun i -> pmk_bool((c / (1 lsl i)) mod 2 = 1)) (0--7) in
100 itlist (fun x y -> Combp(y,x)) lis (Varp("ASCII",dpty)) in
102 let ns = map (fun i -> Char.code(String.get s i))
103 (0--(String.length s - 1)) in
104 pmk_list(map pmk_char ns) in
105 let pmk_setcompr (fabs,bvs,babs) =
107 let bod = itlist (curry pmk_exists) bvs
108 (Combp(Combp(Combp(Varp("SETSPEC",dpty),v),babs),fabs)) in
109 Combp(Varp("GSPEC",dpty),Absp(v,bod)) in
110 let pmk_setabs (fabs,babs) =
112 let fvs = pfrees fabs []
113 and bvs = pfrees babs [] in
114 if length fvs <= 1 or bvs = [] then fvs
115 else intersect fvs bvs in
116 pmk_setcompr (fabs,evs,babs) in
117 let rec mk_precedence infxs prs inp =
120 let topins,rest = partition (fun (s',pat') -> pat' = (p,at)) infxs in
121 (if at = "right" then rightbin else leftbin)
122 (mk_precedence rest prs)
123 (end_itlist (||) (map (fun (s,_) -> a (Ident s)) topins))
124 (fun (Ident op) x y -> Combp(Combp(Varp(op,dpty),x),y))
125 ("preterm after binary operator ("^s^")")
128 let pmk_geq s t = Combp(Combp(Varp("GEQ",dpty),s),t) in
129 let pmk_pattern ((pat,guards),res) =
130 let x = pgenvar() and y = pgenvar() in
131 let vs = pfrees pat []
134 Combp(Combp(Varp("_UNGUARDED_PATTERN",dpty),pmk_geq pat x),
137 Combp(Combp(Combp(Varp("_GUARDED_PATTERN",dpty),pmk_geq pat x),
140 Absp(x,Absp(y,itlist (curry pmk_exists) vs bod)) in
141 let pretype = parse_pretype_verbose
144 Ident s::rst when String.length s >= 2 &
145 String.sub s 0 1 = "\"" &
146 String.sub s (String.length s - 1) 1 = "\""
147 -> String.sub s 1 (String.length s - 2),rst
149 and singleton1 x = [x]
150 and lmk_ite (((((_,b),_),l),_),r) =
151 Combp(Combp(Combp(Varp("COND",dpty),b),l),r)
153 function (p,[]) -> p | (p,[ty]) -> Typing(p,ty) | _ -> fail()
154 and lmk_let (((_,bnds),_),ptm) = pmk_let (bnds,ptm)
155 and lmk_binder ((((s,h),t),_),p) = pmk_binder(s,h::t,p)
156 and lmk_setenum(l,_) = pmk_set_enum l
157 and lmk_setabs(((l,_),r),_) = pmk_setabs(l,r)
158 and lmk_setcompr(((((f,_),vs),_),b),_) =
159 pmk_setcompr(f,pfrees vs [],b)
160 and lmk_decimal ((_,l0),ropt) =
161 let l,r = if ropt = [] then l0,"1" else
163 let n_l = num_of_string l0
164 and n_r = num_of_string r0 in
165 let n_d = power_num (Int 10) (Int (String.length r0)) in
166 let n_n = n_l */ n_d +/ n_r in
167 string_of_num n_n,string_of_num n_d in
168 Combp(Combp(Varp("DECIMAL",dpty),Varp(l,dpty)),Varp(r,dpty))
169 and lmk_univ((_,pty),_) =
170 Typing(Varp("UNIV",dpty),Ptycon("fun",[pty;Ptycon("bool",[])]))
173 ((Ident s):: rest) -> s,rest
177 ((Ident s):: rest) ->
178 if can get_infix_status s or is_prefix s or parses_as_binder s
179 then raise Noparse else s,rest
183 ((Ident s):: rest) ->
184 if parses_as_binder s then s,rest else raise Noparse
188 ((Ident s):: rest) ->
189 if is_prefix s then s,rest else raise Noparse
190 | _ -> raise Noparse in
192 mk_precedence (infixes()) (typed_appl_preterm) i
193 and nocommapreterm i =
194 let infs = filter (fun (s,_) -> s <> ",") (infixes()) in
195 mk_precedence infs typed_appl_preterm i
196 and typed_appl_preterm i =
198 possibly (a (Resword ":") ++ pretype >> snd)
201 (pre_fix ++ appl_preterm
202 >> (fun (x,y) -> Combp(Varp(x,dpty),y))
203 || binder_preterm ++ many binder_preterm >>
204 (fun (h,t) -> itlist (fun x y -> Combp(y,x)) (rev t) h)) i
205 and binder_preterm i =
206 (a (Resword "let") ++
207 leftbin (preterm >> singleton1) (a (Resword "and")) (K (@)) "binding" ++
213 many typed_apreterm ++
218 and typed_apreterm i =
220 possibly (a (Resword ":") ++ pretype >> snd)
222 and atomic_preterm i =
224 || (a (Resword "(") ++ a (Resword ":")) ++ pretype ++ a (Resword ")")
226 || (a (Resword "(") ++ a (Resword ":")) ++ pretype
227 >>(fun _ -> failwith "closing right parenthesis on universe expected")
228 || (a (Resword "(") ++ a (Resword ":"))
229 >>(fun _ -> failwith "pretype in universe construction expected")
232 || a (Resword "(") ++
233 (any_identifier >> (fun s -> Varp(s,dpty))) ++
236 || a (Resword "(") ++
240 (* || a (Resword "(") ++
241 preterm >> (fun _ -> failwith "closing right parenthesis expected")
242 || a (Resword "(") >> (fun _ -> failwith "preterm following left parenthesis expected") *)
243 || a (Resword "if") ++
245 a (Resword "then") ++
247 a (Resword "else") ++
250 || (a (Resword "if") ) ++ preterm ++ a (Resword "then") ++ preterm ++ a (Resword "else") >> (fun _ -> failwith "malformed else clause")
251 || (a (Resword "if") ) ++ preterm ++ a (Resword "then") ++ preterm >> (fun _ -> failwith "missing else following then clause")
252 || (a (Resword "if") ) ++ preterm ++ a (Resword "then") >> (fun _ -> failwith "malformed then clause in if-then-else statement")
253 || (a (Resword "if") ) ++ preterm >> (fun _ -> failwith "missing 'then' reserved word if-then-else statement")
254 || (a (Resword "if") ) >> (fun _ -> failwith "malformed if-then-else")
255 || a (Resword "[") ++
256 elistof preterm (a (Resword ";")) "semicolon separated list of preterms" ++
258 >> (pmk_list o snd o fst)
259 || a (Resword "[") ++
260 elistof preterm (a (Resword ";")) "semicolon separated list of preterms"
261 >> (fun _ -> failwith "closing square bracket on list expected")
262 || a (Resword "{") ++
263 (elistof nocommapreterm (a (Ident ",")) "comma separated list of preterms" ++ a (Resword "}")
265 || preterm ++ a (Resword "|") ++ preterm ++ a (Resword "}")
267 || preterm ++ a (Resword "|") ++ preterm ++
268 a (Resword "|") ++ preterm ++ a (Resword "}")
271 || a (Resword "{") >> (fun _ -> failwith "malformed set {}")
272 || a (Resword "match") ++ preterm ++ a (Resword "with") ++ clauses
273 >> (fun (((_,e),_),c) -> Combp(Combp(Varp("_MATCH",dpty),e),c))
274 || a (Resword "match") >> (fun _ -> failwith "malformed match-with statement")
275 || a (Resword "function") ++ clauses
276 >> (fun (_,c) -> Combp(Varp("_FUNCTION",dpty),c))
277 || a (Resword "function") >> (fun _ -> failwith "malformed function and pattern clauses")
278 || a (Ident "#") ++ identifier ++
279 possibly (a (Resword ".") ++ identifier >> snd)
281 || a (Ident "#") >> (fun _ -> failwith "malformed numerical # identifier")
283 >> (fun s -> Varp(s,dpty))) i
285 (preterm ++ possibly (a (Resword "when") ++ preterm >> snd)) i
287 ((pattern ++ (a (Resword "->") ++ preterm >> snd)) >> pmk_pattern) i
289 ((possibly (a (Resword "|")) ++
290 listof clause (a (Resword "|")) "pattern-match clause" >> snd)
291 >> end_itlist (fun s t -> Combp(Combp(Varp("_SEQPATTERN",dpty),s),t))) i in
294 [Ident s] -> Varp(s,dpty),[]
295 | _ -> preterm inp);;