package lrgrep
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Analyse the stack of a Menhir-generated LR parser using regular expressions
Install
dune-project
Dependency
Authors
Maintainers
Sources
lrgrep-0.3.tbz
sha256=84a1874d0c063da371e19c84243aac7c40bfcb9aaf204251e0eb0d1f077f2cde
sha512=5a16ff42a196fd741bc64a1bdd45b4dca0098633e73aa665829a44625ec15382891c3643fa210dbe3704336eab095d4024e093e37ae5313810f6754de6119d55
doc/src/lrijkstra_utils/tarjan.ml.html
Source file tarjan.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 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353(******************************************************************************) (* *) (* Menhir *) (* *) (* Copyright Inria. All rights reserved. This file is distributed under *) (* the terms of the GNU General Public License version 2, as described in *) (* the file LICENSE. *) (* *) (******************************************************************************) (* This module provides an implementation of Tarjan's algorithm for finding the strongly connected components of a graph. The algorithm runs when the functor is applied. Its complexity is $O(V+E)$, where $V$ is the number of vertices in the graph $G$, and $E$ is the number of edges. *) module Run (G : sig type node (* We assume each node has a unique index. Indices must range from $0$ to $n-1$, where $n$ is the number of nodes in the graph. *) val n: int val index: node -> int (* Iterating over a node's immediate successors. *) val successors: (node -> unit) -> node -> unit (* Iterating over all nodes. *) val iter: (node -> unit) -> unit end) = struct (* Define the internal data structure associated with each node. *) type data = { (* Each node carries a flag which tells whether it appears within the SCC stack (which is defined below). *) mutable stacked: bool; (* Each node carries a number. Numbers represent the order in which nodes were discovered. *) mutable number: int; (* Each node [x] records the lowest number associated to a node already detected within [x]'s SCC. *) mutable low: int; (* Each node carries a pointer to a representative element of its SCC. This field is used by the algorithm to store its results. *) mutable representative: G.node; (* Each representative node carries a list of the nodes in its SCC. This field is used by the algorithm to store its results. *) mutable scc: G.node list } (* Define a mapping from external nodes to internal ones. Here, we simply use each node's index as an entry into a global array. *) let table = (* Create the array. We initially fill it with [None], of type [data option], because we have no meaningful initial value of type [data] at hand. *) let table = Array.make G.n None in (* Initialize the array. *) G.iter (fun x -> table.(G.index x) <- Some { stacked = false; number = 0; low = 0; representative = x; scc = [] } ); (* Define a function which gives easy access to the array. It maps each node to its associated piece of internal data. *) function x -> match table.(G.index x) with | Some dx -> dx | None -> assert false (* Indices do not cover the range $0\ldots n$, as expected. *) (* Create an empty stack, used to record all nodes which belong to the current SCC. *) let scc_stack = Stack.create() (* Initialize a function which allocates numbers for (internal) nodes. A new number is assigned to each node the first time it is visited. Numbers returned by this function start at 1 and increase. Initially, all nodes have number 0, so they are considered unvisited. *) let mark = let counter = ref 0 in fun dx -> incr counter; dx.number <- !counter; dx.low <- !counter (* This reference will hold a list of all representative nodes. The components that have been identified last appear at the head of the list. *) let representatives = ref [] (* Look at all nodes of the graph, one after the other. Any unvisited nodes become roots of the search forest. *) let () = G.iter (fun root -> let droot = table root in if droot.number = 0 then begin (* This node hasn't been visited yet. Start a depth-first walk from it. *) mark droot; droot.stacked <- true; Stack.push droot scc_stack; let rec walk x = let dx = table x in G.successors (fun y -> let dy = table y in if dy.number = 0 then begin (* $y$ hasn't been visited yet, so $(x,y)$ is a regular edge, part of the search forest. *) mark dy; dy.stacked <- true; Stack.push dy scc_stack; (* Continue walking, depth-first. *) walk y; if dy.low < dx.low then dx.low <- dy.low end else if (dy.low < dx.low) && dy.stacked then begin (* The first condition above indicates that $y$ has been visited before $x$, so $(x, y)$ is a backwards or transverse edge. The second condition indicates that $y$ is inside the same SCC as $x$; indeed, if it belongs to another SCC, then the latter has already been identified and moved out of [scc_stack]. *) if dy.number < dx.low then dx.low <- dy.number end ) x; (* We are done visiting $x$'s neighbors. *) if dx.low = dx.number then begin (* $x$ is the entry point of a SCC. The whole SCC is now available; move it out of the stack. We pop elements out of the SCC stack until $x$ itself is found. *) let rec loop () = let element = Stack.pop scc_stack in element.stacked <- false; dx.scc <- element.representative :: dx.scc; element.representative <- x; if element != dx then loop() in loop(); representatives := x :: !representatives end in walk root end ) (* There only remains to make our results accessible to the outside. *) let representative x = (table x).representative let scc x = (table x).scc let representatives = Array.of_list !representatives (* The array [representatives] contains a representative for each component. The components that have been identified last appear first in this array. A component is identified only after its successors have been identified; therefore, this array is naturally in topological order. *) let yield action x = let data = table x in assert (data.representative == x); (* a sanity check *) assert (data.scc <> []); (* a sanity check *) action x data.scc let iter action = Array.iter (yield action) representatives let rev_topological_iter action = for i = Array.length representatives - 1 downto 0 do yield action representatives.(i) done let map action = Array.map (yield action) representatives |> Array.to_list let rev_map action = let accu = ref [] in rev_topological_iter (fun repr labels -> accu := action repr labels :: !accu ); !accu end open Fix.Indexing module type SCC = sig type node type n val n : n cardinal val representatives : (n, node index) vector val nodes : (n, node Utils.IndexSet.t) vector val component : (node, n index) vector end module IndexedSCC (G : sig include CARDINAL val successors : (n index -> unit) -> n index -> unit end) = struct module SCC = Run (struct type node = G.n index let n = cardinal G.n let index n = (n : _ index :> int) let successors = G.successors let iter f = Index.iter G.n f end) module Repr = Vector.Of_array(struct type a = G.n index let array = SCC.representatives end) type node = G.n type n = Repr.n let n = Vector.length Repr.vector let representatives = Repr.vector let nodes = Vector.map (fun node -> Utils.IndexSet.of_list (SCC.scc node)) representatives let component = Vector.make' G.n (fun () -> Index.of_int n 0) let () = Vector.iteri (fun scc nodes' -> Utils.IndexSet.iter (fun node -> Vector.set component node scc) nodes' ) nodes end open Utils open Misc type 'n scc = (module SCC with type node = 'n) let indexed_scc (type n) (n : n cardinal) ~succ : n scc = let module Scc = IndexedSCC(struct type nonrec n = n let n = n let successors = succ end) in (module Scc) let indexset_bind : 'a indexset -> ('a index -> 'b indexset) -> 'b indexset = fun s f -> IndexSet.fold_right (fun acc lr1 -> IndexSet.union (f lr1) acc) IndexSet.empty s let close_forward (type a n) ((module Scc) : n scc) ~(succ:(n index -> unit) -> n index -> unit) (rel: (n, a indexset) vector) = Vector.rev_iteri begin fun _scc nodes -> let sccs = ref IndexSet.empty in IndexSet.rev_iter begin fun i -> succ (fun j -> sccs := IndexSet.add Scc.component.:(j) !sccs) i end nodes; let sccs = !sccs in let set = indexset_bind sccs (fun scc -> rel.:(Scc.representatives.:(scc))) in let set = IndexSet.union (indexset_bind nodes (Vector.get rel)) set in IndexSet.iter (fun i -> rel.:(i) <- set) nodes end Scc.nodes let close_backward (type a n) ((module Scc) : n scc) ~(pred:(n index -> unit) -> n index -> unit) (rel: (n, a indexset) vector) = Vector.iteri begin fun _scc nodes -> let sccs = ref IndexSet.empty in IndexSet.rev_iter begin fun i -> pred (fun j -> sccs := IndexSet.add Scc.component.:(j) !sccs) i end nodes; let sccs = !sccs in let set = indexset_bind sccs (fun scc -> rel.:(Scc.representatives.:(scc))) in let set = IndexSet.union (indexset_bind nodes (Vector.get rel)) set in IndexSet.iter (fun i -> rel.:(i) <- set) nodes end Scc.nodes let close_relation (type n a) (succ : (n index -> unit) -> n index -> unit) (rel : (n, a indexset) vector) = close_forward (indexed_scc (Vector.length rel) ~succ) ~succ rel
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>