package ocamlformat-lib
Auto-formatter for OCaml code
Install
Dune Dependency
github.com
Readme
Changelog
MIT; LGPL-2.1-only WITH OCaml-LGPL-linking-exception License
Edit opam file
Versions (5)
Authors
Maintainers
Sources
ocamlformat-0.25.1.tbz
sha256=dc8f2a330ca3930b36cacb2623bb360ed8bdf6e4a8acd293dbd9e2241a6fd33d
sha512=b28f545425fb5375447c90022d065dc7fd51ed2f66d8c1f65a71a6ad2465d039a8686e8f18249e5ad3a2362fee6149c855ef30eb45fb9d06d743a53d26b3e26f
doc/src/ocamlformat-lib.parser_recovery/merlin_recovery.ml.html
Source file merlin_recovery.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
let split_pos { Lexing.pos_lnum; pos_bol; pos_cnum; _ } = (pos_lnum, pos_cnum - pos_bol) let rev_filter ~f xs = let rec aux f acc = function | x :: xs when f x -> aux f (x :: acc) xs | _ :: xs -> aux f acc xs | [] -> acc in aux f [] xs let rec rev_scan_left acc ~f ~init = function | [] -> acc | x :: xs -> let init = f init x in rev_scan_left (init :: acc) ~f ~init xs module Make (Parser : MenhirLib.IncrementalEngine.EVERYTHING) (Recovery : sig val default_value : Location.t -> 'a Parser.symbol -> 'a type action = | Abort | R of int | S : 'a Parser.symbol -> action | Sub of action list type decision = | Nothing | One of action list | Select of (int -> action list) val depth : int array val recover : int -> decision val guide : 'a Parser.symbol -> bool val token_of_terminal : 'a Parser.terminal -> 'a -> Parser.token val nullable : 'a Parser.nonterminal -> bool end) = struct type 'a candidate = { line : int; min_col : int; max_col : int; env : 'a Parser.env; } type 'a candidates = { shifted : Parser.xsymbol option; final : 'a option; candidates : 'a candidate list; } module T = struct [@@@ocaml.warning "-37"] type 'a checkpoint = | InputNeeded of 'a Parser.env | Shifting of 'a Parser.env * 'a Parser.env * bool | AboutToReduce of 'a Parser.env * Parser.production | HandlingError of 'a Parser.env | Accepted of 'a | Rejected external inj : 'a checkpoint -> 'a Parser.checkpoint = "%identity" end let feed_token ~allow_reduction token env = let rec aux allow_reduction = function | Parser.HandlingError _ | Parser.Rejected -> `Fail | Parser.AboutToReduce _ when not allow_reduction -> `Fail | Parser.Accepted v -> `Accept v | (Parser.Shifting _ | Parser.AboutToReduce _) as checkpoint -> aux true (Parser.resume checkpoint) | Parser.InputNeeded env as checkpoint -> `Recovered (checkpoint, env) in aux allow_reduction (Parser.offer (T.inj (T.InputNeeded env)) token) let rec follow_guide col env = match Parser.top env with | None -> col | Some (Parser.Element (state, _, pos, _)) -> if Recovery.guide (Parser.incoming_symbol state) then match Parser.pop env with | None -> col | Some env -> follow_guide (snd (split_pos pos)) env else col let candidate env = let line, min_col, max_col = match Parser.top env with | None -> (1, 0, 0) | Some (Parser.Element (state, _, pos, _)) -> let depth = Recovery.depth.(Parser.number state) in let line, col = split_pos pos in if depth = 0 then (line, col, col) else let col' = match Parser.pop_many depth env with | None -> max_int | Some env -> ( match Parser.top env with | None -> max_int | Some (Parser.Element (_, _, pos, _)) -> follow_guide (snd (split_pos pos)) env ) in (line, min col col', max col col') in { line; min_col; max_col; env } let attempt r token = let _, startp, _ = token in let line, col = split_pos startp in let more_indented candidate = line <> candidate.line && candidate.min_col > col in let recoveries = let rec aux = function | x :: xs when more_indented x -> aux xs | xs -> xs in aux r.candidates in let same_indented candidate = line = candidate.line || (candidate.min_col <= col && col <= candidate.max_col) in let recoveries = let rec aux = function | x :: xs when same_indented x -> x :: aux xs | _ -> [] in aux recoveries in let rec aux = function | [] -> `Fail | x :: xs -> ( match feed_token ~allow_reduction:true token x.env with | `Fail -> aux xs | `Recovered (checkpoint, _) -> `Ok (checkpoint, x.env) | `Accept v -> ( match aux xs with `Fail -> `Accept v | x -> x ) ) in aux recoveries let decide env = let rec nth_state env n = if n = 0 then match Parser.top env with | None -> -1 (*allow giving up recovery on empty files*) | Some (Parser.Element (state, _, _, _)) -> Parser.number state else match Parser.pop env with | None -> assert (n = 1); -1 | Some env -> nth_state env (n - 1) in let st = nth_state env 0 in match Recovery.recover st with | Recovery.Nothing -> [] | Recovery.One actions -> actions | Recovery.Select f -> f (nth_state env Recovery.depth.(st)) let generate (type a) (env : a Parser.env) = let module E = struct exception Result of a end in let shifted = ref None in let rec aux acc env = match Parser.top env with | None -> (None, acc) | Some (Parser.Element (_state, _, _startp, endp)) -> ( let actions = decide env in let candidate0 = candidate env in let rec eval (env : a Parser.env) : Recovery.action -> a Parser.env = function | Recovery.Abort -> raise Not_found | Recovery.R prod -> let prod = Parser.find_production prod in Parser.force_reduction prod env | Recovery.S (Parser.N n as sym) -> let xsym = Parser.X sym in if !shifted = None && not (Recovery.nullable n) then shifted := Some xsym; let loc = { Location.loc_start = endp; loc_end = endp; loc_ghost = true; } in let v = Recovery.default_value loc sym in Parser.feed sym endp v endp env | Recovery.S (Parser.T t as sym) -> ( let xsym = Parser.X sym in if !shifted = None then shifted := Some xsym; let loc = { Location.loc_start = endp; loc_end = endp; loc_ghost = true; } in let v = Recovery.default_value loc sym in let token = (Recovery.token_of_terminal t v, endp, endp) in match feed_token ~allow_reduction:true token env with | `Fail -> assert false | `Accept v -> raise (E.Result v) | `Recovered (_, env) -> env ) | Recovery.Sub actions -> List.fold_left eval env actions in match rev_scan_left [] ~f:eval ~init:env actions |> List.map (fun env -> { candidate0 with env }) with | exception Not_found -> (None, acc) | exception E.Result v -> (Some v, acc) | [] -> (None, acc) | candidate :: _ as candidates -> aux (candidates @ acc) candidate.env ) in let final, candidates = aux [] env in (!shifted, final, candidates) let generate env = let shifted, final, candidates = generate env in let candidates = rev_filter candidates ~f:(fun t -> not (Parser.env_has_default_reduction t.env)) in { shifted; final; candidates = candidate env :: candidates } end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>