aboutsummaryrefslogtreecommitdiff
path: root/lib/citation/book.ml
blob: 2a2b9c0f08ce286bc672e34f840f54f8975bc388 (plain) (blame)
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
(* SPDX-License-Identifier: AGPL-3.0-or-later *)

type id = string

let to_string t = t

(* Every book cited across the shipped EF data (lectionary, sanctoral
   propers, and commons), with every spelling any of the three files uses.
   The dotted/undotted and modern/Vulgate pairs are inherited from lectio --
   see book.mli. Surveyed directly against the data, all three files, not
   the lectionary alone -- sanctoral.sexp alone carries more citations than
   the lectionary and was the source of every token missed in the first
   pass. *)
let table =
  [ ("genesis",          [ "Gen" ]);
    ("exodus",           [ "Ex"; "Exod" ]);
    ("leviticus",        [ "Lev" ]);
    ("numbers",          [ "Num" ]);
    ("kings_3",          [ "3 Kings"; "3 Kgs." ]);
    ("kings_4",          [ "4 Kings" ]);
    ("esdras_2",         [ "2 Esd." ]);
    ("tobit",            [ "Tob" ]);
    ("judith",           [ "Judith" ]);
    ("esther",           [ "Esther" ]);
    ("proverbs",         [ "Prov" ]);
    ("song_of_songs",    [ "Song" ]);
    ("wisdom",           [ "Wis"; "Wis." ]);
    ("ecclesiasticus",   [ "Ecclus"; "Sir"; "Eccli" ]);
    ("isaiah",           [ "Isa"; "Isa." ]);
    ("jeremiah",         [ "Jer" ]);
    ("ezekiel",          [ "Ezech"; "Ezek" ]);
    ("daniel",           [ "Dan" ]);
    ("osee",             [ "Osee" ]);
    ("joel",             [ "Joel" ]);
    ("jonas",            [ "Jonas" ]);
    ("malachi",          [ "Mal" ]);
    ("matthew",          [ "Matt"; "Matt." ]);
    ("mark",             [ "Mark" ]);
    ("luke",             [ "Luke" ]);
    ("john",             [ "John" ]);
    ("acts",             [ "Acts" ]);
    ("romans",           [ "Rom" ]);
    ("corinthians_1",    [ "1 Cor"; "1 Cor." ]);
    ("corinthians_2",    [ "2 Cor"; "2 Cor." ]);
    ("galatians",        [ "Gal" ]);
    ("ephesians",        [ "Eph"; "Eph." ]);
    ("philippians",      [ "Phil" ]);
    ("colossians",       [ "Col"; "Col." ]);
    ("thessalonians_1",  [ "1 Thess"; "1 Thess." ]);
    ("thessalonians_2",  [ "2 Thess" ]);
    ("timothy_1",        [ "1 Tim." ]);
    ("timothy_2",        [ "2 Tim"; "2 Tim." ]);
    ("titus",            [ "Titus" ]);
    ("hebrews",          [ "Heb" ]);
    ("james",            [ "Jas"; "James" ]);
    ("peter_1",          [ "1 Pet"; "1 Pet." ]);
    ("peter_2",          [ "2 Pet." ]);
    ("john_1",           [ "1 John" ]);
    (* "Apoc" is the Vulgate spelling and "Rev" its modern equivalent, but
       BOTH sit inside Vulgate-tradition data, so both resolve to the same
       Vulgate id here -- see book.mli's note by [apocalypse] never being an
       [of_token] result under that name. Do not add "revelation" as a
       spelling: it exists only as a tradition target (below), and giving it
       an [of_token] entry would let one book carry two different ids. *)
    ("apocalypse",       [ "Apoc"; "Rev" ]) ]

(* Targets a tradition can map ONTO that the Vulgate data never cites
   directly. Present so [tradition_of_fields] can validate both sides.
   [sirach] and [revelation] exist ONLY here, never as an [of_token] result:
   "Sir" and "Rev" already resolve to the Vulgate ids [ecclesiasticus] and
   [apocalypse] above, so a modern-numbering tradition maps ONTO these
   targets rather than data ever citing them directly. *)
let tradition_targets =
  [ "kings_1"; "kings_2"; "nehemiah"; "sirach"; "hosea"; "jonah"; "revelation" ]

let all = List.map fst table @ tradition_targets

let tokens =
  List.concat_map (fun (id, sp) -> List.map (fun s -> (s, id)) sp) table

let default_spelling id =
  match List.assoc_opt id table with
  | Some (first :: _) -> first
  | Some [] | None -> id

let of_token s =
  let s = String.trim s in
  List.assoc_opt s tokens

type tradition = (string * string) list

let vulgate = []

let known id = List.mem id all

let tradition_of_fields fields =
  List.filter (fun (a, b) -> known a && known b) fields

let unknown_fields fields =
  List.filter_map
    (fun (a, b) -> if known a && known b then None else Some a)
    fields

let map tr id = match List.assoc_opt id tr with Some x -> x | None -> id