File: misc.ml

package info (click to toggle)
menhir 20071212.dfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 1,128 kB
  • ctags: 1,585
  • sloc: ml: 11,098; makefile: 111; sh: 24
file content (250 lines) | stat: -rw-r--r-- 5,653 bytes parent folder | download
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
(**************************************************************************)
(*                                                                        *)
(*  Menhir                                                                *)
(*                                                                        *)
(*  Franois Pottier and Yann Rgis-Gianas, INRIA Rocquencourt            *)
(*                                                                        *)
(*  Copyright 2005 Institut National de Recherche en Informatique et      *)
(*  en Automatique. All rights reserved. This file is distributed         *)
(*  under the terms of the Q Public License version 1.0, with the         *)
(*  change described in file LICENSE.                                     *)
(*                                                                        *)
(**************************************************************************)

let ( $$ ) x f = f x

let unSome = function
   None -> assert false
  | Some x -> x

let o2s o f =
  match o with
  | None ->
      ""
  | Some x ->
      f x

let single = function
  | [ x ] ->
      x
  | _ ->
      assert false

let rec mapd f = function
  | [] ->
      []
  | x :: xs ->
      let y1, y2 = f x in
      y1 :: y2 :: mapd f xs

let tabulateb n f =
  let a = Array.init n f in
  Array.get a,
  Array.fold_left (fun count element ->
    if element then count + 1 else count
  ) 0 a

let tabulateo number fold n f =
  let a = Array.create n None in
  let c = ref 0 in
  let () = fold (fun () element ->
    let image = f element in
    a.(number element) <- image;
    match image with
    | Some _ ->
	incr c
    | None ->
	()
  ) () in
  let get element =
    a.(number element)
  in
  get, !c

let rec truncate k xs =
  match k, xs with
  | 0, _ ->
      []
  | _, [] ->
      assert false
  | _, x :: xs ->
      x :: truncate (k-1) xs

let truncate k xs =
  if List.length xs <= k then xs else truncate k xs

module IntSet = Set.Make (struct 
			    type t = int
			    let compare = ( - )
			  end)

let separated_list_to_string printer separator list = 

  let rec loop x = function
    | [] ->
        printer x
    | y :: xs ->
        printer x 
	^ separator 
	^ loop y xs
  in

  match list with
  | [] ->
      ""
  | x :: xs ->
      loop x xs


let index_map string_map = 
  let n = StringMap.cardinal string_map in
  let a = Array.create n None in
  let conv, _ = StringMap.fold 
    (fun k v (conv, idx) ->
       a.(idx) <- Some (k, v);
       StringMap.add k idx conv, idx + 1)
    string_map (StringMap.empty, 0) 
  in
    ((fun n -> snd (unSome a.(n))),
     (fun k -> StringMap.find k conv),
     (fun n -> fst (unSome a.(n))))
  
let support_assoc l x =
  try
    List.assoc x l
  with Not_found -> x

let index (strings : string list) : int * string array * int StringMap.t =
  let name = Array.of_list strings
  and n, map = List.fold_left (fun (n, map) s ->
    n+1, StringMap.add s n map
  ) (0, StringMap.empty) strings in
  n, name, map

(* Turning an implicit list, stored using pointers through a hash
   table, into an explicit list. The head of the implicit list is
   not included in the explicit list. *)

let materialize (table : ('a, 'a option) Hashtbl.t) (x : 'a) : 'a list =
  let rec loop x =
    match Hashtbl.find table x with
    | None ->
	[]
    | Some x ->
	x :: loop x
  in
  loop x

(* [iteri] implements a [for] loop over integers, from 0 to
   [n-1]. *)

let iteri n f =
  for i = 0 to n - 1 do
    f i
  done

(* [foldi] implements a [for] loop over integers, from 0 to [n-1],
   with an accumulator. [foldij] implements a [for] loop over
   integers, from [start] to [n-1], with an accumulator. *)

let foldij start n f accu =
  let rec loop i accu =
    if i = n then
      accu
    else
      loop (i+1) (f i accu)
  in
  loop start accu

let foldi n f accu =
  foldij 0 n f accu

(* [qfold f accu q] repeatedly takes an element [x] off the queue [q]
   and applies [f] to the accumulator and to [x], until [q] becomes
   empty. Of course, [f] can add elements to [q] as a side-effect.

   We allocate an option to ensure that [qfold] is tail-recursive. *)

let rec qfold f accu q =
  match
    try
      Some (Queue.take q)
    with Queue.Empty ->
      None
  with
  | Some x ->
      qfold f (f accu x) q
  | None ->
      accu

(* [qiter f q] repeatedly takes an element [x] off the queue [q] and
   applies [f] to [x], until [q] becomes empty. Of course, [f] can add
   elements to [q] as a side-effect. *)

let qiter f q =
  try
    while true do
      f (Queue.take q)
    done
  with Queue.Empty ->
    ()

let rec smap f = function
  | [] ->
      []
  | (x :: xs) as l ->
      let x' = f x
      and xs' = smap f xs in
      if x == x' && xs == xs' then
	l
      else
	x' :: xs'

let normalize s =
  let s = String.copy s in
  let n = String.length s in
  for i = 0 to n - 1 do
    match s.[i] with
    | '('
    | ')'
    | ',' ->
	s.[i] <- '_'
    | _ ->
	()
  done;
  s

(* [postincrement r] increments [r] and returns its original value. *)

let postincrement r =
  let x = !r in
  r := x + 1;
  x

(* [gcp] returns the greatest common prefix of two strings. *)

let gcp s1 s2 =
  let n1 = String.length s1
  and n2 = String.length s2 in
  let rec loop i =
    if (i < n1) && (i < n2) && (s1.[i] = s2.[i]) then
      loop (i+1)
    else
      String.sub s1 0 i
  in
  loop 0

(* [gcps] returns the greatest common prefix of a nonempty list of strings. *)

let rec gcps = function
  | [] ->
      assert false
  | s :: ss ->
      let rec loop accu = function
	| [] ->
	    accu
	| s :: ss ->
	    loop (gcp s accu) ss
      in
      loop s ss