diff options
Diffstat (limited to 'gramlib')
| -rw-r--r-- | gramlib/gramext.ml | 67 | ||||
| -rw-r--r-- | gramlib/gramext.mli | 5 | ||||
| -rw-r--r-- | gramlib/grammar.ml | 271 | ||||
| -rw-r--r-- | gramlib/grammar.mli | 76 | ||||
| -rw-r--r-- | gramlib/plexing.ml | 198 | ||||
| -rw-r--r-- | gramlib/plexing.mli | 71 | ||||
| -rw-r--r-- | gramlib/ploc.ml | 113 | ||||
| -rw-r--r-- | gramlib/ploc.mli | 36 |
8 files changed, 24 insertions, 813 deletions
diff --git a/gramlib/gramext.ml b/gramlib/gramext.ml index 8960d4f257..72468b540e 100644 --- a/gramlib/gramext.ml +++ b/gramlib/gramext.ml @@ -27,8 +27,6 @@ and 'te g_level = lprefix : 'te g_tree } and g_assoc = NonA | RightA | LeftA and 'te g_symbol = - Sfacto of 'te g_symbol - | Smeta of string * 'te g_symbol list * Obj.t | Snterm of 'te g_entry | Snterml of 'te g_entry * string | Slist0 of 'te g_symbol @@ -36,13 +34,10 @@ and 'te g_symbol = | Slist1 of 'te g_symbol | Slist1sep of 'te g_symbol * 'te g_symbol * bool | Sopt of 'te g_symbol - | Sflag of 'te g_symbol | Sself | Snext - | Scut | Stoken of Plexing.pattern | Stree of 'te g_tree - | Svala of string list * 'te g_symbol and g_action = Obj.t and 'te g_tree = Node of 'te g_node @@ -66,12 +61,10 @@ let rec derive_eps = function Slist0 _ -> true | Slist0sep (_, _, _) -> true - | Sopt _ | Sflag _ -> true - | Sfacto s -> derive_eps s + | Sopt _ -> true | Stree t -> tree_derive_eps t - | Svala (_, s) -> derive_eps s - | Smeta (_, _, _) | Slist1 _ | Slist1sep (_, _, _) | Snterm _ | - Snterml (_, _) | Snext | Sself | Scut | Stoken _ -> + | Slist1 _ | Slist1sep (_, _, _) | Snterm _ | + Snterml (_, _) | Snext | Sself | Stoken _ -> false and tree_derive_eps = function @@ -90,38 +83,11 @@ let rec eq_symbol s1 s2 = | Slist1 s1, Slist1 s2 -> eq_symbol s1 s2 | Slist1sep (s1, sep1, b1), Slist1sep (s2, sep2, b2) -> eq_symbol s1 s2 && eq_symbol sep1 sep2 && b1 = b2 - | Sflag s1, Sflag s2 -> eq_symbol s1 s2 | Sopt s1, Sopt s2 -> eq_symbol s1 s2 - | Svala (ls1, s1), Svala (ls2, s2) -> ls1 = ls2 && eq_symbol s1 s2 | Stree _, Stree _ -> false - | Sfacto (Stree t1), Sfacto (Stree t2) -> - (* The only goal of the node 'Sfacto' is to allow tree comparison - (therefore factorization) without looking at the semantic - actions; allow factorization of rules like "SV foo" which are - actually expanded into a tree. *) - let rec eq_tree t1 t2 = - match t1, t2 with - Node n1, Node n2 -> - eq_symbol n1.node n2.node && eq_tree n1.son n2.son && - eq_tree n1.brother n2.brother - | LocAct (_, _), LocAct (_, _) -> true - | DeadEnd, DeadEnd -> true - | _ -> false - in - eq_tree t1 t2 | _ -> s1 = s2 let is_before s1 s2 = - let s1 = - match s1 with - Svala (_, s) -> s - | _ -> s1 - in - let s2 = - match s2 with - Svala (_, s) -> s - | _ -> s2 - in match s1, s2 with Stoken ("ANY", _), _ -> false | _, Stoken ("ANY", _) -> true @@ -158,9 +124,6 @@ let insert_tree entry_name gsymbols action tree = if eq_symbol s s1 then let t = Node {node = s1; son = insert sl son; brother = bro} in Some t - else if s = Scut then - try_insert s sl (Node {node = s; son = tree; brother = DeadEnd}) - else if s1 = Scut then try_insert s1 (s :: sl) tree else if is_before s1 s || derive_eps s && not (derive_eps s1) then let bro = match try_insert s sl bro with @@ -203,8 +166,6 @@ and token_exists_in_tree f = | LocAct (_, _) | DeadEnd -> false and token_exists_in_symbol f = function - Sfacto sy -> token_exists_in_symbol f sy - | Smeta (_, syl, _) -> List.exists (token_exists_in_symbol f) syl | Slist0 sy -> token_exists_in_symbol f sy | Slist0sep (sy, sep, _) -> token_exists_in_symbol f sy || token_exists_in_symbol f sep @@ -212,11 +173,9 @@ and token_exists_in_symbol f = | Slist1sep (sy, sep, _) -> token_exists_in_symbol f sy || token_exists_in_symbol f sep | Sopt sy -> token_exists_in_symbol f sy - | Sflag sy -> token_exists_in_symbol f sy | Stoken tok -> f tok | Stree t -> token_exists_in_tree f t - | Svala (_, sy) -> token_exists_in_symbol f sy - | Snterm _ | Snterml (_, _) | Snext | Sself | Scut -> false + | Snterm _ | Snterml (_, _) | Snext | Sself -> false let insert_level entry_name e1 symbols action slev = match e1 with @@ -341,17 +300,13 @@ Error: entries \"%s\" and \"%s\" do not belong to the same grammar.\n" flush stderr; failwith "Grammar.extend error" end - | Sfacto s -> check_gram entry s - | Smeta (_, sl, _) -> List.iter (check_gram entry) sl | Slist0sep (s, t, _) -> check_gram entry t; check_gram entry s | Slist1sep (s, t, _) -> check_gram entry t; check_gram entry s | Slist0 s -> check_gram entry s | Slist1 s -> check_gram entry s | Sopt s -> check_gram entry s - | Sflag s -> check_gram entry s | Stree t -> tree_check_gram entry t - | Svala (_, s) -> check_gram entry s - | Snext | Sself | Scut | Stoken _ -> () + | Snext | Sself | Stoken _ -> () and tree_check_gram entry = function Node {node = n; brother = bro; son = son} -> @@ -371,16 +326,12 @@ let get_initial entry = let insert_tokens gram symbols = let rec insert = function - Sfacto s -> insert s - | Smeta (_, sl, _) -> List.iter insert sl | Slist0 s -> insert s | Slist1 s -> insert s | Slist0sep (s, t, _) -> insert s; insert t | Slist1sep (s, t, _) -> insert s; insert t | Sopt s -> insert s - | Sflag s -> insert s | Stree t -> tinsert t - | Svala (_, s) -> insert s | Stoken ("ANY", _) -> () | Stoken tok -> gram.glexer.Plexing.tok_using tok; @@ -389,7 +340,7 @@ let insert_tokens gram symbols = Not_found -> let r = ref 0 in Hashtbl.add gram.gtokens tok r; r in incr r - | Snterm _ | Snterml (_, _) | Snext | Sself | Scut -> () + | Snterm _ | Snterml (_, _) | Snext | Sself -> () and tinsert = function Node {node = s; brother = bro; son = son} -> @@ -507,17 +458,13 @@ let rec decr_keyw_use gram = Hashtbl.remove gram.gtokens tok; gram.glexer.Plexing.tok_removing tok end - | Sfacto s -> decr_keyw_use gram s - | Smeta (_, sl, _) -> List.iter (decr_keyw_use gram) sl | Slist0 s -> decr_keyw_use gram s | Slist1 s -> decr_keyw_use gram s | Slist0sep (s1, s2, _) -> decr_keyw_use gram s1; decr_keyw_use gram s2 | Slist1sep (s1, s2, _) -> decr_keyw_use gram s1; decr_keyw_use gram s2 | Sopt s -> decr_keyw_use gram s - | Sflag s -> decr_keyw_use gram s | Stree t -> decr_keyw_use_in_tree gram t - | Svala (_, s) -> decr_keyw_use gram s - | Sself | Snext | Scut | Snterm _ | Snterml (_, _) -> () + | Sself | Snext | Snterm _ | Snterml (_, _) -> () and decr_keyw_use_in_tree gram = function DeadEnd | LocAct (_, _) -> () diff --git a/gramlib/gramext.mli b/gramlib/gramext.mli index a76b7da9a2..e888508277 100644 --- a/gramlib/gramext.mli +++ b/gramlib/gramext.mli @@ -25,8 +25,6 @@ and 'te g_level = lprefix : 'te g_tree } and g_assoc = NonA | RightA | LeftA and 'te g_symbol = - Sfacto of 'te g_symbol - | Smeta of string * 'te g_symbol list * Obj.t | Snterm of 'te g_entry | Snterml of 'te g_entry * string | Slist0 of 'te g_symbol @@ -34,13 +32,10 @@ and 'te g_symbol = | Slist1 of 'te g_symbol | Slist1sep of 'te g_symbol * 'te g_symbol * bool | Sopt of 'te g_symbol - | Sflag of 'te g_symbol | Sself | Snext - | Scut | Stoken of Plexing.pattern | Stree of 'te g_tree - | Svala of string list * 'te g_symbol and g_action = Obj.t and 'te g_tree = Node of 'te g_node diff --git a/gramlib/grammar.ml b/gramlib/grammar.ml index 04ec1049ed..760410894a 100644 --- a/gramlib/grammar.ml +++ b/gramlib/grammar.ml @@ -41,8 +41,6 @@ let print_str ppf s = fprintf ppf "\"%s\"" (string_escaped s) let rec print_symbol ppf = function - Sfacto s -> print_symbol ppf s - | Smeta (n, sl, _) -> print_meta ppf n sl | Slist0 s -> fprintf ppf "LIST0 %a" print_symbol1 s | Slist0sep (s, t, osep) -> fprintf ppf "LIST0 %a SEP %a%s" print_symbol1 s print_symbol1 t @@ -52,42 +50,23 @@ let rec print_symbol ppf = fprintf ppf "LIST1 %a SEP %a%s" print_symbol1 s print_symbol1 t (if osep then " OPT_SEP" else "") | Sopt s -> fprintf ppf "OPT %a" print_symbol1 s - | Sflag s -> fprintf ppf "FLAG %a" print_symbol1 s | Stoken (con, prm) when con <> "" && prm <> "" -> fprintf ppf "%s@ %a" con print_str prm - | Svala (_, s) -> fprintf ppf "V %a" print_symbol s | Snterml (e, l) -> fprintf ppf "%s%s@ LEVEL@ %a" e.ename (if e.elocal then "*" else "") print_str l - | Snterm _ | Snext | Sself | Scut | Stoken _ | Stree _ as s -> + | Snterm _ | Snext | Sself | Stoken _ | Stree _ as s -> print_symbol1 ppf s -and print_meta ppf n sl = - let rec loop i = - function - [] -> () - | s :: sl -> - let j = - try String.index_from n i ' ' with Not_found -> String.length n - in - fprintf ppf "%s %a" (String.sub n i (j - i)) print_symbol1 s; - if sl = [] then () - else - begin fprintf ppf " "; loop (min (j + 1) (String.length n)) sl end - in - loop 0 sl and print_symbol1 ppf = function - Sfacto s -> print_symbol1 ppf s | Snterm e -> fprintf ppf "%s%s" e.ename (if e.elocal then "*" else "") | Sself -> pp_print_string ppf "SELF" | Snext -> pp_print_string ppf "NEXT" - | Scut -> pp_print_string ppf "/" | Stoken ("", s) -> print_str ppf s | Stoken (con, "") -> pp_print_string ppf con | Stree t -> print_level ppf pp_print_space (flatten_tree t) - | Smeta (_, _, _) | Snterml (_, _) | Slist0 _ | Slist0sep (_, _, _) | - Slist1 _ | Slist1sep (_, _, _) | Sopt _ | Sflag _ | Stoken _ | - Svala (_, _) as s -> + | Snterml (_, _) | Slist0 _ | Slist0sep (_, _, _) | + Slist1 _ | Slist1sep (_, _, _) | Sopt _ | Stoken _ as s -> fprintf ppf "(%a)" print_symbol s and print_rule ppf symbols = fprintf ppf "@[<hov 0>"; @@ -162,31 +141,24 @@ let name_of_symbol entry = let rec get_token_list entry rev_tokl last_tok tree = match tree with Node {node = Stoken tok; son = son; brother = DeadEnd} -> - get_token_list entry (last_tok :: rev_tokl) (tok, None) son - | Node {node = Svala (ls, Stoken tok); son = son; brother = DeadEnd} -> - get_token_list entry (last_tok :: rev_tokl) (tok, Some ls) son + get_token_list entry (last_tok :: rev_tokl) tok son | _ -> if rev_tokl = [] then None else Some (rev_tokl, last_tok, tree) let rec name_of_symbol_failed entry = function - Sfacto s -> name_of_symbol_failed entry s | Slist0 s -> name_of_symbol_failed entry s | Slist0sep (s, _, _) -> name_of_symbol_failed entry s | Slist1 s -> name_of_symbol_failed entry s | Slist1sep (s, _, _) -> name_of_symbol_failed entry s | Sopt s -> name_of_symbol_failed entry s - | Sflag s -> name_of_symbol_failed entry s | Stree t -> name_of_tree_failed entry t - | Svala (_, s) -> name_of_symbol_failed entry s - | Smeta (_, s :: _, _) -> name_of_symbol_failed entry s | s -> name_of_symbol entry s and name_of_tree_failed entry = function Node {node = s; brother = bro; son = son} -> let tokl = match s with - Stoken tok -> get_token_list entry [] (tok, None) son - | Svala (ls, Stoken tok) -> get_token_list entry [] (tok, Some ls) son + Stoken tok -> get_token_list entry [] tok son | _ -> None in begin match tokl with @@ -205,7 +177,7 @@ and name_of_tree_failed entry = txt | Some (rev_tokl, last_tok, son) -> List.fold_left - (fun s (tok, _) -> + (fun s tok -> (if s = "" then "" else s ^ " ") ^ entry.egram.glexer.Plexing.tok_text tok) "" (List.rev (last_tok :: rev_tokl)) @@ -318,7 +290,7 @@ let tree_failed entry prev_symb_result prev_symb tree = let txt1 = name_of_symbol_failed entry sep in txt1 ^ " or " ^ txt ^ " expected" end - | Sopt _ | Sflag _ | Stree _ | Svala (_, _) -> txt ^ " expected" + | Sopt _ | Stree _ -> txt ^ " expected" | _ -> txt ^ " expected after " ^ name_of_symbol_failed entry prev_symb in if !error_verbose then @@ -426,29 +398,9 @@ let call_and_push ps al strm = let a = ps strm in let al = if !item_skipped then al else a :: al in item_skipped := false; al -let token_ematch gram (tok, vala) = +let token_ematch gram tok = let tematch = gram.glexer.Plexing.tok_match tok in - match vala with - Some al -> - let pa = - match al with - [] -> - let t = "V " ^ fst tok in gram.glexer.Plexing.tok_match (t, "") - | al -> - let rec loop = - function - a :: al -> - let pa = gram.glexer.Plexing.tok_match ("V", a) in - let pal = loop al in - (fun tok -> try pa tok with Stream.Failure -> pal tok) - | [] -> fun tok -> raise Stream.Failure - in - loop al - in - (fun tok -> - try Obj.repr (Ploc.VaAnt (Obj.magic (pa tok : string))) with - Stream.Failure -> Obj.repr (Ploc.VaVal (tematch tok))) - | None -> fun tok -> Obj.repr (tematch tok : string) + fun tok -> Obj.repr (tematch tok : string) let rec parser_of_tree entry nlevn alevn = function @@ -457,8 +409,6 @@ let rec parser_of_tree entry nlevn alevn = | Node {node = Sself; son = LocAct (act, _); brother = DeadEnd} -> (fun (strm__ : _ Stream.t) -> let a = entry.estart alevn strm__ in app act a) - | Node {node = Scut; son = son; brother = _} -> - parser_of_tree entry nlevn alevn son | Node {node = Sself; son = LocAct (act, _); brother = bro} -> let p2 = parser_of_tree entry nlevn alevn bro in (fun (strm__ : _ Stream.t) -> @@ -470,8 +420,7 @@ let rec parser_of_tree entry nlevn alevn = | Node {node = s; son = son; brother = DeadEnd} -> let tokl = match s with - Stoken tok -> get_token_list entry [] (tok, None) son - | Svala (ls, Stoken tok) -> get_token_list entry [] (tok, Some ls) son + Stoken tok -> get_token_list entry [] tok son | _ -> None in begin match tokl with @@ -488,24 +437,18 @@ let rec parser_of_tree entry nlevn alevn = raise (Stream.Error (tree_failed entry a s son)) in app act a) - | Some (rev_tokl, (last_tok, svala), son) -> - let lt = - let t = Stoken last_tok in - match svala with - Some l -> Svala (l, t) - | None -> t - in + | Some (rev_tokl, last_tok, son) -> + let lt = Stoken last_tok in let p1 = parser_of_tree entry nlevn alevn son in let p1 = parser_cont p1 entry nlevn alevn lt son in parser_of_token_list entry s son p1 (fun (strm__ : _ Stream.t) -> raise Stream.Failure) rev_tokl - (last_tok, svala) + last_tok end | Node {node = s; son = son; brother = bro} -> let tokl = match s with - Stoken tok -> get_token_list entry [] (tok, None) son - | Svala (ls, Stoken tok) -> get_token_list entry [] (tok, Some ls) son + Stoken tok -> get_token_list entry [] tok son | _ -> None in match tokl with @@ -525,18 +468,13 @@ let rec parser_of_tree entry nlevn alevn = | None -> raise (Stream.Error (tree_failed entry a s son)) end | None -> p2 strm) - | Some (rev_tokl, (last_tok, vala), son) -> - let lt = - let t = Stoken last_tok in - match vala with - Some ls -> Svala (ls, t) - | None -> t - in + | Some (rev_tokl, last_tok, son) -> + let lt = Stoken last_tok in let p2 = parser_of_tree entry nlevn alevn bro in let p1 = parser_of_tree entry nlevn alevn son in let p1 = parser_cont p1 entry nlevn alevn lt son in let p1 = - parser_of_token_list entry lt son p1 p2 rev_tokl (last_tok, vala) + parser_of_token_list entry lt son p1 p2 rev_tokl last_tok in fun (strm__ : _ Stream.t) -> try p1 strm__ with Stream.Failure -> p2 strm__ @@ -592,13 +530,6 @@ and parser_of_token_list entry s son p1 p2 rev_tokl last_tok = let a = ps strm__ in let act = p1 strm__ in app act a and parser_of_symbol entry nlevn = function - Sfacto s -> parser_of_symbol entry nlevn s - | Smeta (_, symbl, act) -> - let act = Obj.magic act entry symbl in - Obj.magic - (List.fold_left - (fun act symb -> Obj.magic act (parser_of_symbol entry nlevn symb)) - act symbl) | Slist0 s -> let ps = call_and_push (parser_of_symbol entry nlevn s) in let rec loop al (strm__ : _ Stream.t) = @@ -705,12 +636,6 @@ and parser_of_symbol entry nlevn = match try Some (ps strm__) with Stream.Failure -> None with Some a -> Obj.repr (Some a) | _ -> Obj.repr None) - | Sflag s -> - let ps = parser_of_symbol entry nlevn s in - (fun (strm__ : _ Stream.t) -> - match try Some (ps strm__) with Stream.Failure -> None with - Some _ -> Obj.repr true - | _ -> Obj.repr false) | Stree t -> let pt = parser_of_tree entry 1 0 t in (fun (strm__ : _ Stream.t) -> @@ -718,46 +643,11 @@ and parser_of_symbol entry nlevn = let a = pt strm__ in let ep = Stream.count strm__ in let loc = loc_of_token_interval bp ep in app a loc) - | Svala (al, s) -> - let pa = - match al with - [] -> - let t = - match s with - Sflag _ -> Some "V FLAG" - | Sopt _ -> Some "V OPT" - | Slist0 _ | Slist0sep (_, _, _) -> Some "V LIST" - | Slist1 _ | Slist1sep (_, _, _) -> Some "V LIST" - | Stoken (con, "") -> Some ("V " ^ con) - | _ -> None - in - begin match t with - Some t -> parser_of_token entry (t, "") - | None -> fun (strm__ : _ Stream.t) -> raise Stream.Failure - end - | al -> - let rec loop = - function - a :: al -> - let pa = parser_of_token entry ("V", a) in - let pal = loop al in - (fun (strm__ : _ Stream.t) -> - try pa strm__ with Stream.Failure -> pal strm__) - | [] -> fun (strm__ : _ Stream.t) -> raise Stream.Failure - in - loop al - in - let ps = parser_of_symbol entry nlevn s in - (fun (strm__ : _ Stream.t) -> - match try Some (pa strm__) with Stream.Failure -> None with - Some a -> Obj.repr (Ploc.VaAnt (Obj.magic a : string)) - | _ -> let a = ps strm__ in Obj.repr (Ploc.VaVal a)) | Snterm e -> (fun (strm__ : _ Stream.t) -> e.estart 0 strm__) | Snterml (e, l) -> (fun (strm__ : _ Stream.t) -> e.estart (level_number e l) strm__) | Sself -> (fun (strm__ : _ Stream.t) -> entry.estart 0 strm__) | Snext -> (fun (strm__ : _ Stream.t) -> entry.estart nlevn strm__) - | Scut -> (fun (strm__ : _ Stream.t) -> Obj.repr ()) | Stoken tok -> parser_of_token entry tok and parser_of_token entry tok = let f = entry.egram.glexer.Plexing.tok_match tok in @@ -891,13 +781,6 @@ let delete_rule entry sl = (* Normal interface *) -type token = string * string -type g = token Gramext.grammar - -type ('self, 'a) ty_symbol = token Gramext.g_symbol -type ('self, 'f, 'r) ty_rule = ('self, Obj.t) ty_symbol list -type 'a ty_production = ('a, Obj.t, Obj.t) ty_rule * Gramext.g_action - let create_toktab () = Hashtbl.create 301 let gcreate glexer = {gtokens = create_toktab (); glexer = glexer } @@ -916,12 +799,6 @@ type 'te gen_parsable = pa_tok_strm : 'te Stream.t; pa_loc_func : Plexing.location_function } -type parsable = token gen_parsable - -let parsable g cs = - let (ts, lf) = g.glexer.Plexing.tok_func cs in - {pa_chr_strm = cs; pa_tok_strm = ts; pa_loc_func = lf} - let parse_parsable entry p = let efun = entry.estart 0 in let ts = p.pa_tok_strm in @@ -953,105 +830,6 @@ let parse_parsable entry p = let loc = Stream.count cs, Stream.count cs + 1 in restore (); Ploc.raise (Ploc.make_unlined loc) exc -let find_entry e s = - let rec find_levels = - function - [] -> None - | lev :: levs -> - match find_tree lev.lsuffix with - None -> - begin match find_tree lev.lprefix with - None -> find_levels levs - | x -> x - end - | x -> x - and find_symbol = - function - Sfacto s -> find_symbol s - | Snterm e -> if e.ename = s then Some e else None - | Snterml (e, _) -> if e.ename = s then Some e else None - | Smeta (_, sl, _) -> find_symbol_list sl - | Slist0 s -> find_symbol s - | Slist0sep (s, _, _) -> find_symbol s - | Slist1 s -> find_symbol s - | Slist1sep (s, _, _) -> find_symbol s - | Sopt s -> find_symbol s - | Sflag s -> find_symbol s - | Stree t -> find_tree t - | Svala (_, s) -> find_symbol s - | Sself | Snext | Scut | Stoken _ -> None - and find_symbol_list = - function - s :: sl -> - begin match find_symbol s with - None -> find_symbol_list sl - | x -> x - end - | [] -> None - and find_tree = - function - Node {node = s; brother = bro; son = son} -> - begin match find_symbol s with - None -> - begin match find_tree bro with - None -> find_tree son - | x -> x - end - | x -> x - end - | LocAct (_, _) | DeadEnd -> None - in - match e.edesc with - Dlevels levs -> - begin match find_levels levs with - Some e -> e - | None -> raise Not_found - end - | Dparser _ -> raise Not_found -module Entry = - struct - type te = token - type 'a e = te g_entry - let create g n = - {egram = g; ename = n; elocal = false; estart = empty_entry n; - econtinue = (fun _ _ _ (strm__ : _ Stream.t) -> raise Stream.Failure); - edesc = Dlevels []} - let parse_parsable (entry : 'a e) p : 'a = - Obj.magic (parse_parsable entry p : Obj.t) - let parse (entry : 'a e) cs : 'a = - let parsable = parsable entry.egram cs in parse_parsable entry parsable - let parse_parsable_all (entry : 'a e) p : 'a = - begin try Obj.magic [(parse_parsable entry p : Obj.t)] with - Stream.Failure | Stream.Error _ -> [] - end - let parse_all (entry : 'a e) cs : 'a = - let parsable = parsable entry.egram cs in - parse_parsable_all entry parsable - let parse_token_stream (entry : 'a e) ts : 'a = - Obj.magic (entry.estart 0 ts : Obj.t) - let _warned_using_parse_token = ref false - let parse_token (entry : 'a e) ts : 'a = - (* commented: too often warned in Coq... - if not warned_using_parse_token.val then do { - eprintf "<W> use of Grammar.Entry.parse_token "; - eprintf "deprecated since 2017-06-16\n%!"; - eprintf "use Grammar.Entry.parse_token_stream instead\n%! "; - warned_using_parse_token.val := True - } - else (); - *) - parse_token_stream entry ts - let name e = e.ename - let of_parser g n (p : te Stream.t -> 'a) : 'a e = - {egram = g; ename = n; elocal = false; - estart = (fun _ -> (Obj.magic p : te Stream.t -> Obj.t)); - econtinue = (fun _ _ _ (strm__ : _ Stream.t) -> raise Stream.Failure); - edesc = Dparser (Obj.magic p : te Stream.t -> Obj.t)} - external obj : 'a e -> te Gramext.g_entry = "%identity" - let print ppf e = fprintf ppf "%a@." print_entry (obj e) - let find e s = find_entry (obj e) s - end - (* Unsafe *) let clear_entry e = @@ -1063,12 +841,6 @@ let clear_entry e = let gram_reinit g glexer = Hashtbl.clear g.gtokens; g.glexer <- glexer -module Unsafe = - struct - let gram_reinit = gram_reinit - let clear_entry = clear_entry - end - (* Functorial interface *) module type GLexerType = sig type te val lexer : te Plexing.lexer end @@ -1095,7 +867,6 @@ module type S = type ('self, 'a) ty_symbol type ('self, 'f, 'r) ty_rule type 'a ty_production - val s_facto : ('self, 'a) ty_symbol -> ('self, 'a) ty_symbol val s_nterm : 'a Entry.e -> ('self, 'a) ty_symbol val s_nterml : 'a Entry.e -> string -> ('self, 'a) ty_symbol val s_list0 : ('self, 'a) ty_symbol -> ('self, 'a list) ty_symbol @@ -1107,18 +878,14 @@ module type S = ('self, 'a) ty_symbol -> ('self, 'b) ty_symbol -> bool -> ('self, 'a list) ty_symbol val s_opt : ('self, 'a) ty_symbol -> ('self, 'a option) ty_symbol - val s_flag : ('self, 'a) ty_symbol -> ('self, bool) ty_symbol val s_self : ('self, 'self) ty_symbol val s_next : ('self, 'self) ty_symbol val s_token : Plexing.pattern -> ('self, string) ty_symbol val s_rules : 'a ty_production list -> ('self, 'a) ty_symbol - val s_vala : - string list -> ('self, 'a) ty_symbol -> ('self, 'a Ploc.vala) ty_symbol val r_stop : ('self, 'r, 'r) ty_rule val r_next : ('self, 'a, 'r) ty_rule -> ('self, 'b) ty_symbol -> ('self, 'b -> 'a, 'r) ty_rule - val r_cut : ('self, 'a, 'r) ty_rule -> ('self, 'a, 'r) ty_rule val production : ('a, 'f, Ploc.t -> 'a) ty_rule * 'f -> 'a ty_production module Unsafe : sig @@ -1187,7 +954,6 @@ module GMake (L : GLexerType) = type ('self, 'a) ty_symbol = te Gramext.g_symbol type ('self, 'f, 'r) ty_rule = ('self, Obj.t) ty_symbol list type 'a ty_production = ('a, Obj.t, Obj.t) ty_rule * Gramext.g_action - let s_facto s = Sfacto s let s_nterm e = Snterm e let s_nterml e l = Snterml (e, l) let s_list0 s = Slist0 s @@ -1195,15 +961,12 @@ module GMake (L : GLexerType) = let s_list1 s = Slist1 s let s_list1sep s sep b = Slist1sep (s, sep, b) let s_opt s = Sopt s - let s_flag s = Sflag s let s_self = Sself let s_next = Snext let s_token tok = Stoken tok let s_rules (t : Obj.t ty_production list) = Gramext.srules (Obj.magic t) - let s_vala sl s = Svala (sl, s) let r_stop = [] let r_next r s = r @ [s] - let r_cut r = r @ [Scut] let production (p : ('a, 'f, Ploc.t -> 'a) ty_rule * 'f) : 'a ty_production = Obj.magic p diff --git a/gramlib/grammar.mli b/gramlib/grammar.mli index 54b7eb5539..244ab710dc 100644 --- a/gramlib/grammar.mli +++ b/gramlib/grammar.mli @@ -8,77 +8,6 @@ Grammars entries can be extended using the [EXTEND] statement, added by loading the Camlp5 [pa_extend.cmo] file. *) -type g - (** The type for grammars, holding entries. *) -type token = string * string - -type parsable -val parsable : g -> char Stream.t -> parsable - (** Type and value allowing to keep the same token stream between - several calls of entries of the same grammar, to prevent possible - loss of tokens. To be used with [Entry.parse_parsable] below *) - -module Entry : - sig - type 'a e - val create : g -> string -> 'a e - val parse : 'a e -> char Stream.t -> 'a - val parse_all : 'a e -> char Stream.t -> 'a list - val parse_parsable : 'a e -> parsable -> 'a - val name : 'a e -> string - val of_parser : g -> string -> (token Stream.t -> 'a) -> 'a e - val parse_token_stream : 'a e -> token Stream.t -> 'a - val print : Format.formatter -> 'a e -> unit - val find : 'a e -> string -> Obj.t e - external obj : 'a e -> token Gramext.g_entry = "%identity" - val parse_token : 'a e -> token Stream.t -> 'a - end - (** Module to handle entries. -- [Entry.e] is the type for entries returning values of type ['a]. -- [Entry.create g n] creates a new entry named [n] in the grammar [g]. -- [Entry.parse e] returns the stream parser of the entry [e]. -- [Entry.parse_all e] returns the stream parser returning all possible - values while parsing with the entry [e]: may return more than one - value when the parsing algorithm is [Backtracking] -- [Entry.parse_all e] returns the parser returning all possible values. -- [Entry.parse_parsable e] returns the parsable parser of the entry [e]. -- [Entry.name e] returns the name of the entry [e]. -- [Entry.of_parser g n p] makes an entry from a token stream parser. -- [Entry.parse_token_stream e] returns the token stream parser of the - entry [e]. -- [Entry.print e] displays the entry [e] using [Format]. -- [Entry.find e s] finds the entry named [s] in the rules of [e]. -- [Entry.obj e] converts an entry into a [Gramext.g_entry] allowing - to see what it holds. -- [Entry.parse_token]: deprecated since 2017-06-16; old name for - [Entry.parse_token_stream] *) - -type ('self, 'a) ty_symbol -(** Type of grammar symbols. A type-safe wrapper around Gramext.symbol. The - first type argument is the type of the ambient entry, the second one is the - type of the produced value. *) - -type ('self, 'f, 'r) ty_rule - -type 'a ty_production - -(** {6 Clearing grammars and entries} *) - -module Unsafe : - sig - val gram_reinit : g -> token Plexing.lexer -> unit - val clear_entry : 'a Entry.e -> unit - end - (** Module for clearing grammars and entries. To be manipulated with - care, because: 1) reinitializing a grammar destroys all tokens - and there may have problems with the associated lexer if there - are keywords; 2) clearing an entry does not destroy the tokens - used only by itself. -- [Unsafe.reinit_gram g lex] removes the tokens of the grammar -- and sets [lex] as a new lexer for [g]. Warning: the lexer -- itself is not reinitialized. -- [Unsafe.clear_entry e] removes all rules of the entry [e]. *) - (** {6 Functorial interface} *) (** Alternative for grammars use. Grammars are no more Ocaml values: @@ -112,7 +41,6 @@ module type S = type ('self, 'a) ty_symbol type ('self, 'f, 'r) ty_rule type 'a ty_production - val s_facto : ('self, 'a) ty_symbol -> ('self, 'a) ty_symbol val s_nterm : 'a Entry.e -> ('self, 'a) ty_symbol val s_nterml : 'a Entry.e -> string -> ('self, 'a) ty_symbol val s_list0 : ('self, 'a) ty_symbol -> ('self, 'a list) ty_symbol @@ -124,18 +52,14 @@ module type S = ('self, 'a) ty_symbol -> ('self, 'b) ty_symbol -> bool -> ('self, 'a list) ty_symbol val s_opt : ('self, 'a) ty_symbol -> ('self, 'a option) ty_symbol - val s_flag : ('self, 'a) ty_symbol -> ('self, bool) ty_symbol val s_self : ('self, 'self) ty_symbol val s_next : ('self, 'self) ty_symbol val s_token : Plexing.pattern -> ('self, string) ty_symbol val s_rules : 'a ty_production list -> ('self, 'a) ty_symbol - val s_vala : - string list -> ('self, 'a) ty_symbol -> ('self, 'a Ploc.vala) ty_symbol val r_stop : ('self, 'r, 'r) ty_rule val r_next : ('self, 'a, 'r) ty_rule -> ('self, 'b) ty_symbol -> ('self, 'b -> 'a, 'r) ty_rule - val r_cut : ('self, 'a, 'r) ty_rule -> ('self, 'a, 'r) ty_rule val production : ('a, 'f, Ploc.t -> 'a) ty_rule * 'f -> 'a ty_production module Unsafe : diff --git a/gramlib/plexing.ml b/gramlib/plexing.ml index beebcd016e..986363ec1f 100644 --- a/gramlib/plexing.ml +++ b/gramlib/plexing.ml @@ -17,201 +17,3 @@ type 'te lexer = mutable tok_match : pattern -> 'te -> string; tok_text : pattern -> string; mutable tok_comm : location list option } - -let make_loc = Ploc.make_unlined -let dummy_loc = Ploc.dummy - -let lexer_text (con, prm) = - if con = "" then "'" ^ prm ^ "'" - else if prm = "" then con - else con ^ " '" ^ prm ^ "'" - -let locerr () = failwith "Lexer: location function" -let loct_create () = ref (Array.make 1024 None), ref false -let loct_func (loct, ov) i = - match - if i < 0 || i >= Array.length !loct then - if !ov then Some dummy_loc else None - else Array.unsafe_get !loct i - with - Some loc -> loc - | None -> locerr () -let loct_add (loct, ov) i loc = - if i >= Array.length !loct then - let new_tmax = Array.length !loct * 2 in - if new_tmax < Sys.max_array_length then - let new_loct = Array.make new_tmax None in - Array.blit !loct 0 new_loct 0 (Array.length !loct); - loct := new_loct; - !loct.(i) <- Some loc - else ov := true - else !loct.(i) <- Some loc - -let make_stream_and_location next_token_loc = - let loct = loct_create () in - let ts = - Stream.from - (fun i -> - let (tok, loc) = next_token_loc () in loct_add loct i loc; Some tok) - in - ts, loct_func loct - -let lexer_func_of_parser next_token_loc cs = - let line_nb = ref 1 in - let bolpos = ref 0 in - make_stream_and_location (fun () -> next_token_loc (cs, line_nb, bolpos)) - -let lexer_func_of_ocamllex lexfun cs = - let lb = - Lexing.from_function - (fun s n -> - try Bytes.set s 0 (Stream.next cs); 1 with Stream.Failure -> 0) - in - let next_token_loc _ = - let tok = lexfun lb in - let loc = make_loc (Lexing.lexeme_start lb, Lexing.lexeme_end lb) in - tok, loc - in - make_stream_and_location next_token_loc - -(* Char and string tokens to real chars and string *) - -let buff = ref (Bytes.create 80) -let store len x = - if len >= Bytes.length !buff then - buff := Bytes.(cat !buff (create (length !buff))); - Bytes.set !buff len x; - succ len -let get_buff len = Bytes.sub !buff 0 len - -let valch x = Char.code x - Char.code '0' -let valch_a x = Char.code x - Char.code 'a' + 10 -let valch_A x = Char.code x - Char.code 'A' + 10 - -let rec backslash s i = - if i = String.length s then raise Not_found - else - match s.[i] with - 'n' -> '\n', i + 1 - | 'r' -> '\r', i + 1 - | 't' -> '\t', i + 1 - | 'b' -> '\b', i + 1 - | '\\' -> '\\', i + 1 - | '"' -> '"', i + 1 - | '\'' -> '\'', i + 1 - | '0'..'9' as c -> backslash1 (valch c) s (i + 1) - | 'x' -> backslash1h s (i + 1) - | _ -> raise Not_found -and backslash1 cod s i = - if i = String.length s then '\\', i - 1 - else - match s.[i] with - '0'..'9' as c -> backslash2 (10 * cod + valch c) s (i + 1) - | _ -> '\\', i - 1 -and backslash2 cod s i = - if i = String.length s then '\\', i - 2 - else - match s.[i] with - '0'..'9' as c -> Char.chr (10 * cod + valch c), i + 1 - | _ -> '\\', i - 2 -and backslash1h s i = - if i = String.length s then '\\', i - 1 - else - match s.[i] with - '0'..'9' as c -> backslash2h (valch c) s (i + 1) - | 'a'..'f' as c -> backslash2h (valch_a c) s (i + 1) - | 'A'..'F' as c -> backslash2h (valch_A c) s (i + 1) - | _ -> '\\', i - 1 -and backslash2h cod s i = - if i = String.length s then '\\', i - 2 - else - match s.[i] with - '0'..'9' as c -> Char.chr (16 * cod + valch c), i + 1 - | 'a'..'f' as c -> Char.chr (16 * cod + valch_a c), i + 1 - | 'A'..'F' as c -> Char.chr (16 * cod + valch_A c), i + 1 - | _ -> '\\', i - 2 - -let rec skip_indent s i = - if i = String.length s then i - else - match s.[i] with - ' ' | '\t' -> skip_indent s (i + 1) - | _ -> i - -let skip_opt_linefeed s i = - if i = String.length s then i else if s.[i] = '\010' then i + 1 else i - -let eval_char s = - if String.length s = 1 then s.[0] - else if String.length s = 0 then failwith "invalid char token" - else if s.[0] = '\\' then - if String.length s = 2 && s.[1] = '\'' then '\'' - else - try - let (c, i) = backslash s 1 in - if i = String.length s then c else raise Not_found - with Not_found -> failwith "invalid char token" - else failwith "invalid char token" - -let eval_string loc s = - let rec loop len i = - if i = String.length s then get_buff len - else - let (len, i) = - if s.[i] = '\\' then - let i = i + 1 in - if i = String.length s then failwith "invalid string token" - else if s.[i] = '"' then store len '"', i + 1 - else - match s.[i] with - '\010' -> len, skip_indent s (i + 1) - | '\013' -> len, skip_indent s (skip_opt_linefeed s (i + 1)) - | c -> - try let (c, i) = backslash s i in store len c, i with - Not_found -> store (store len '\\') c, i + 1 - else store len s.[i], i + 1 - in - loop len i - in - Bytes.to_string (loop 0 0) - -let default_match = - function - "ANY", "" -> (fun (con, prm) -> prm) - | "ANY", v -> - (fun (con, prm) -> if v = prm then v else raise Stream.Failure) - | p_con, "" -> - (fun (con, prm) -> if con = p_con then prm else raise Stream.Failure) - | p_con, p_prm -> - fun (con, prm) -> - if con = p_con && prm = p_prm then prm else raise Stream.Failure - -let input_file = ref "" -let line_nb = ref (ref 0) -let bol_pos = ref (ref 0) -let restore_lexing_info = ref None - -(* The lexing buffer used by pa_lexer.cmo *) - -let rev_implode l = - let s = Bytes.create (List.length l) in - let rec loop i = - function - c :: l -> Bytes.unsafe_set s i c; loop (i - 1) l - | [] -> s - in - Bytes.to_string (loop (Bytes.length s - 1) l) - -module Lexbuf : - sig - type t - val empty : t - val add : char -> t -> t - val get : t -> string - end = - struct - type t = char list - let empty = [] - let add c l = c :: l - let get = rev_implode - end diff --git a/gramlib/plexing.mli b/gramlib/plexing.mli index 6b5f718bc3..96b432a8ad 100644 --- a/gramlib/plexing.mli +++ b/gramlib/plexing.mli @@ -35,74 +35,3 @@ and 'te lexer_func = char Stream.t -> 'te Stream.t * location_function and location_function = int -> Ploc.t (** The type of a function giving the location of a token in the source from the token number in the stream (starting from zero). *) - -val lexer_text : pattern -> string - (** A simple [tok_text] function. *) - -val default_match : pattern -> string * string -> string - (** A simple [tok_match] function, appling to the token type - [(string * string)] *) - -(** Lexers from parsers or ocamllex - - The functions below create lexer functions either from a [char stream] - parser or for an [ocamllex] function. With the returned function [f], - it is possible to get a simple lexer (of the type [Plexing.glexer] above): - {[ - { Plexing.tok_func = f; - Plexing.tok_using = (fun _ -> ()); - Plexing.tok_removing = (fun _ -> ()); - Plexing.tok_match = Plexing.default_match; - Plexing.tok_text = Plexing.lexer_text; - Plexing.tok_comm = None } - ]} - Note that a better [tok_using] function should check the used tokens - and raise [Plexing.Error] for incorrect ones. The other functions - [tok_removing], [tok_match] and [tok_text] may have other implementations - as well. *) - -val lexer_func_of_parser : - (char Stream.t * int ref * int ref -> 'te * Ploc.t) -> 'te lexer_func - (** A lexer function from a lexer written as a char stream parser - returning the next token and its location. The two references - with the char stream contain the current line number and the - position of the beginning of the current line. *) -val lexer_func_of_ocamllex : (Lexing.lexbuf -> 'te) -> 'te lexer_func - (** A lexer function from a lexer created by [ocamllex] *) - -(** Function to build a stream and a location function *) - -val make_stream_and_location : - (unit -> 'te * Ploc.t) -> 'te Stream.t * location_function - (** General function *) - -(** Useful functions and values *) - -val eval_char : string -> char -val eval_string : Ploc.t -> string -> string - (** Convert a char or a string token, where the backslashes had not - been interpreted into a real char or string; raise [Failure] if - bad backslash sequence found; [Plexing.eval_char (Char.escaped c)] - would return [c] and [Plexing.eval_string (String.escaped s)] would - return [s] *) - -val restore_lexing_info : (int * int) option ref -val input_file : string ref -val line_nb : int ref ref -val bol_pos : int ref ref - (** Special variables used to reinitialize line numbers and position - of beginning of line with their correct current values when a parser - is called several times with the same character stream. Necessary - for directives (e.g. #load or #use) which interrupt the parsing. - Without usage of these variables, locations after the directives - can be wrong. *) - -(** The lexing buffer used by streams lexers *) - -module Lexbuf : - sig - type t - val empty : t - val add : char -> t -> t - val get : t -> string - end diff --git a/gramlib/ploc.ml b/gramlib/ploc.ml index cb71f72678..082686db01 100644 --- a/gramlib/ploc.ml +++ b/gramlib/ploc.ml @@ -55,122 +55,9 @@ let sub loc sh len = {loc with bp = loc.bp + sh; ep = loc.bp + sh + len} let after loc sh len = {loc with bp = loc.ep + sh; ep = loc.ep + sh + len} let with_comment loc comm = {loc with comm = comm} -let name = ref "loc" - -let from_file fname loc = - let (bp, ep) = first_pos loc, last_pos loc in - try - let ic = open_in_bin fname in - let strm = Stream.of_channel ic in - let rec loop fname lin = - let rec not_a_line_dir col (strm__ : _ Stream.t) = - let cnt = Stream.count strm__ in - match Stream.peek strm__ with - Some c -> - Stream.junk strm__; - let s = strm__ in - if cnt < bp then - if c = '\n' then loop fname (lin + 1) - else not_a_line_dir (col + 1) s - else let col = col - (cnt - bp) in fname, lin, col, col + ep - bp - | _ -> fname, lin, col, col + 1 - in - let rec a_line_dir str n col (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some '\n' -> Stream.junk strm__; loop str n - | Some _ -> Stream.junk strm__; a_line_dir str n (col + 1) strm__ - | _ -> raise Stream.Failure - in - let rec spaces col (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some ' ' -> Stream.junk strm__; spaces (col + 1) strm__ - | _ -> col - in - let rec check_string str n col (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some '"' -> - Stream.junk strm__; - let col = - try spaces (col + 1) strm__ with - Stream.Failure -> raise (Stream.Error "") - in - a_line_dir str n col strm__ - | Some c when c <> '\n' -> - Stream.junk strm__; - check_string (str ^ String.make 1 c) n (col + 1) strm__ - | _ -> not_a_line_dir col strm__ - in - let check_quote n col (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some '"' -> Stream.junk strm__; check_string "" n (col + 1) strm__ - | _ -> not_a_line_dir col strm__ - in - let rec check_num n col (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some ('0'..'9' as c) -> - Stream.junk strm__; - check_num (10 * n + Char.code c - Char.code '0') (col + 1) strm__ - | _ -> let col = spaces col strm__ in check_quote n col strm__ - in - let begin_line (strm__ : _ Stream.t) = - match Stream.peek strm__ with - Some '#' -> - Stream.junk strm__; - let col = - try spaces 1 strm__ with - Stream.Failure -> raise (Stream.Error "") - in - check_num 0 col strm__ - | _ -> not_a_line_dir 0 strm__ - in - begin_line strm - in - let r = - try loop fname 1 with - Stream.Failure -> - let bol = bol_pos loc in fname, line_nb loc, bp - bol, ep - bol - in - close_in ic; r - with Sys_error _ -> fname, 1, bp, ep - -let second_line fname ep0 (line, bp) ep = - let ic = open_in fname in - seek_in ic bp; - let rec loop line bol p = - if p = ep then - begin close_in ic; if bol = bp then line, ep0 else line, ep - bol end - else - let (line, bol) = - match input_char ic with - '\n' -> line + 1, p + 1 - | _ -> line, bol - in - loop line bol (p + 1) - in - loop line bp bp - -let get loc = - if loc.fname = "" || loc.fname = "-" then - loc.line_nb, loc.bp - loc.bol_pos, loc.line_nb, loc.ep - loc.bol_pos, - loc.ep - loc.bp - else - let (bl, bc, ec) = - loc.line_nb, loc.bp - loc.bol_pos, loc.ep - loc.bol_pos - in - let (el, eep) = second_line loc.fname ec (bl, loc.bp) loc.ep in - bl, bc, el, eep, ec - bc - -let call_with r v f a = - let saved = !r in - try r := v; let b = f a in r := saved; b with e -> r := saved; raise e - exception Exc of t * exn let raise loc exc = match exc with Exc (_, _) -> raise exc | _ -> raise (Exc (loc, exc)) - -type 'a vala = - VaAnt of string - | VaVal of 'a diff --git a/gramlib/ploc.mli b/gramlib/ploc.mli index d2ab62db06..2ce6382183 100644 --- a/gramlib/ploc.mli +++ b/gramlib/ploc.mli @@ -84,39 +84,3 @@ val after : t -> int -> int -> t [len]. *) val with_comment : t -> string -> t (** Change the comment part of the given location *) - -(* miscellaneous *) - -val name : string ref - (** [Ploc.name.val] is the name of the location variable used in grammars - and in the predefined quotations for OCaml syntax trees. Default: - ["loc"] *) - -val get : t -> int * int * int * int * int - (** [Ploc.get loc] returns in order: 1/ the line number of the begin - of the location, 2/ its column, 3/ the line number of the first - character not in the location, 4/ its column and 5/ the length - of the location. The file where the location occurs (if any) may - be read during this operation. *) - -val from_file : string -> t -> string * int * int * int - (** [Ploc.from_file fname loc] reads the file [fname] up to the - location [loc] and returns the real input file, the line number - and the characters location in the line; the real input file - can be different from [fname] because of possibility of line - directives typically generated by /lib/cpp. *) - -(* pervasives *) - -type 'a vala = - VaAnt of string - | VaVal of 'a - (** Encloser of many abstract syntax tree nodes types, in "strict" mode. - This allow the system of antiquotations of abstract syntax tree - quotations to work when using the quotation kit [q_ast.cmo]. *) - -val call_with : 'a ref -> 'a -> ('b -> 'c) -> 'b -> 'c - (** [Ploc.call_with r v f a] sets the reference [r] to the value [v], - then call [f a], and resets [r] to its initial value. If [f a] raises - an exception, its initial value is also reset and the exception is - re-raised. The result is the result of [f a]. *) |
