package atd

  1. Overview
  2. Docs
Parser for the ATD data format description language

Install

Dune Dependency

Authors

  1. M
    Martin Jambon <martin@mjambon.com>
  2. R
    Rudi Grinberg <rudi.grinberg@gmail.com>
  3. M
    Martin Jambon <martin@r2c.dev>
  4. M
    Martin Jambon <github@mjambon.com>
  5. I
    Ivan Jager <aij+git@mrph.org>
  6. O
    oleksiy <oleksiy.golovko@ahrefs.com>
  7. D
    David Sheets <sheets@alum.mit.edu>
  8. R
    Rudi Grinberg <me@rgrinberg.com>
  9. M
    Martin Jambon <martin@esper.com>
  10. J
    Jeff Meister <nanaki@gmail.com>
  11. C
    Caio Wakamatsu <caio.wakamatsu@ahrefs.com>
  12. C
    Carmelo Piccione <carmelo.piccione@gmail.com>
  13. D
    Daniel Weil <danweil68@gmail.com>
  14. E
    Egor Chemokhonenko <egor.chemohonenko@ahrefs.com>
  15. Gabriel Scherer
  16. R
    Raman Varabets <roman.vorobets@gmail.com>
  17. T
    tzm <frank@boldsolutions.de>
  18. M
    Mathieu Baudet <mathieubaudet@fb.com>
  19. O
    Oleksiy Golovko <alexei.golovko@gmail.com>
  20. R
    Rauan Mayemir <rauan@mayemir.io>
  21. C
    Carmelo Piccione <cep1@solvuu.com>
  22. J
    John Billings <john@monkeynut.org>
  23. L
    Louis Roché <louis@louisroche.net>
  24. B
    Brendan Long <self@brendanlong.com>
  25. C
    Chris Yocum <cyocum@gmail.com>
  26. L
    Louis Roché (Ahrefs) <louis.roche@ahrefs.com>
  27. L
    Louis Roché <louis.roche@ahrefs.com>
  28. P
    Pavel Antoshkin <pavel.antoshkin@ahrefs.com>
  29. P
    Pierre Boutillier <pierre.boutillier@laposte.net>
  30. S
    Shon Feder <shon.feder@key.me>
  31. A
    Anurag Soni <anuragsoni.13@gmail.com>
  32. A
    Arjun Ravi Narayan <arjunravinarayan@gmail.com>
  33. A
    Asya-kawai <kawai-toshiki@aintek.xyz>
  34. C
    Christophe Troestler <christophe.Troestler@umons.ac.be>
  35. Damien Doligez
  36. D
    Daniel M <dan.mntg@gmail.com>
  37. D
    Ding Xiang Fei <dingxiangfei2009@protonmail.ch>
  38. F
    François Pottier <francois.pottier@inria.fr>
  39. J
    Javier Chavarri <javier.chavarri@gmail.com>
  40. K
    Kate <kit.ty.kate@disroot.org>
  41. L
    Louis <louis.roche@ahrefs.com>
  42. L
    Louis Roché <louis@cryptosense.com>
  43. R
    Raman Varabets <raman+git@ahrefs.com>
  44. S
    Stephane Legrand <slegrand45@gmail.com>
  45. V
    Vincent Bernardoff <vb@luminar.eu.org>
  46. H
    haoyang <haoyang@esper.co>
  47. P
    pmundkur <prashanth.mundkur@gmail.com>
  48. Y
    ygrek <ygrek@autistici.org>

Maintainers

Sources

atd-2.14.1.tbz
sha256=84d15eefa1b0c23823484eaadc984b58063de74d42004c5a44795da94597c4cb
sha512=ba03e00dc34666a06f0fe798d5c145a0ebe619c823f88c50a0e7963e12d13f7041baf3a03544be882f473daf3b0bf6238ef42fb5e83ba504dda2b7e41fb8bc36

doc/src/atd/unique_name.ml.html

Source file unique_name.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
(*
   Ensure unique identifiers that don't conflict with predefined Python
   identifiers or prefixes reserved by atdpy.
*)

open Printf

type t = {
  reserved_identifiers: (string, unit) Hashtbl.t;
  reserved_prefixes: string list;
  safe_prefix: string;

  (* Translations are used to look up the translation of an already-registered
     identifier. *)
  translations: (string, string) Hashtbl.t;

  (* Reverse translations are needed when creating a new translation.
     They're for checking that the new translation doesn't conflict with
     an existing translation. *)
  reverse_translations: (string, string) Hashtbl.t;
}

let has_prefix ~prefix src =
  let len = String.length prefix in
  if String.length src < len then
    false
  else
    try
      for i = 0 to len - 1 do
        if prefix.[i] <> src.[i] then
          raise Exit
      done;
      true
    with Exit -> false

let init ~reserved_identifiers ~reserved_prefixes ~safe_prefix =
  let reserved_identifiers =
    let tbl = Hashtbl.create 100 in
    List.iter (fun id -> Hashtbl.replace tbl id ()) reserved_identifiers;
    tbl
  in
  List.iter (fun prefix ->
    if has_prefix ~prefix safe_prefix then
      invalid_arg
        (sprintf "Unique_name.init: safe_prefix %S is not safe as it \
                  conflicts with reserved prefix %S"
           safe_prefix prefix)
  ) reserved_prefixes;
  {
    reserved_identifiers;
    reserved_prefixes;
    safe_prefix;
    translations = Hashtbl.create 100;
    reverse_translations = Hashtbl.create 100;
  }

let is_reserved env src_or_dst =
  Hashtbl.mem env.reserved_identifiers src_or_dst

let conflicts_with_existing_translation env dst =
  Hashtbl.mem env.reverse_translations dst

let has_reserved_prefix env src =
  List.exists (fun prefix -> has_prefix ~prefix src) env.reserved_prefixes

let enumerate_suffixes () =
  let counter = ref 0 in
  let get_suffix () =
    let suf =
      match !counter with
      | 0 -> ""
      | 1 -> "_"
      | n -> string_of_int n
    in
    incr counter;
    suf
  in
  get_suffix

let register ?preferred_translation env src =
  let pref_dst =
    match preferred_translation with
    | None -> src
    | Some x -> x
  in
  let get_suffix = enumerate_suffixes () in
  let rec find_available_suffix () =
    let suffix = get_suffix () in
    let dst = pref_dst ^ suffix in
    let dst =
      (* assume that safe_prefix is not a prefix of a reserved prefix *)
      if has_reserved_prefix env dst then
        env.safe_prefix ^ dst
      else
        dst
    in
    if is_reserved env dst || conflicts_with_existing_translation env dst then
      find_available_suffix ()
    else
      dst
  in
  let dst = find_available_suffix () in
  Hashtbl.add env.translations src dst;
  Hashtbl.add env.reverse_translations dst src;
  dst

let translate_only env src =
  Hashtbl.find_opt env.translations src

let translate ?preferred_translation env src =
  match translate_only env src with
  | Some dst -> dst
  | None -> register ?preferred_translation env src

let reverse_translate env dst =
  Hashtbl.find_opt env.reverse_translations dst

let create env src =
  let get_suffix = enumerate_suffixes () in
  let rec find_available_suffix () =
    let suffix = get_suffix () in
    let src = src ^ suffix in
    if Hashtbl.mem env.translations src then
      find_available_suffix ()
    else
      src
  in
  let src = find_available_suffix () in
  ignore (register env src);
  src

let all env =
  Hashtbl.fold (fun src dst acc -> (src, dst) :: acc) env.translations []
  |> List.sort (fun (a, _) (b, _) -> String.compare a b)
OCaml

Innovation. Community. Security.