diff options
Diffstat (limited to 'lib/citation/book.ml')
| -rw-r--r-- | lib/citation/book.ml | 107 |
1 files changed, 97 insertions, 10 deletions
diff --git a/lib/citation/book.ml b/lib/citation/book.ml index 986a898..b43cdd8 100644 --- a/lib/citation/book.ml +++ b/lib/citation/book.ml @@ -19,26 +19,26 @@ let table = ("kings_3", [ "3 Kings"; "3 Kgs."; "3 Reg"; "Liber Regum III" ]); ("kings_4", [ "4 Kings"; "4 Reg"; "Liber Regum IV"; "4 Kgs." ]); ("esdras_2", [ "2 Esd."; "2 Esdr"; "Liber Esdrae"; "2 Esdras" ]); - ("tobit", [ "Tob"; "Liber Tobiae"; "Tobias" ]); + ("tobit", [ "Tob"; "Liber Tobiae"; "Tobias"; "Tobit" ]); ("judith", [ "Judith"; "Iudith"; "Liber Iudith"; "Jth" ]); ("esther", [ "Esther"; "Esth"; "Liber Esther" ]); ("proverbs", [ "Prov"; "Proverbs" ]); - ("song_of_songs", [ "Song"; "Cant."; "Canticle of Canticles" ]); + ("song_of_songs", [ "Song"; "Cant."; "Canticle of Canticles"; "Song of Solomon" ]); ("wisdom", [ "Wis"; "Wis."; "Sap"; "Liber Sapientiae"; "Wisdom" ]); ("ecclesiasticus", [ "Ecclus"; "Sir"; "Eccli"; "Ecclesiasticus" ]); - ("isaiah", [ "Isa"; "Isa."; "Isai"; "Isaias Propheta"; "Isaias" ]); - ("jeremiah", [ "Jer"; "Ier"; "Ieremias Propheta"; "Jeremias" ]); - ("ezekiel", [ "Ezech"; "Ezek"; "Ezechiel Propheta"; "Ezechiel" ]); + ("isaiah", [ "Isa"; "Isa."; "Isai"; "Isaias Propheta"; "Isaias"; "Isaiah" ]); + ("jeremiah", [ "Jer"; "Ier"; "Ieremias Propheta"; "Jeremias"; "Jeremiah" ]); + ("ezekiel", [ "Ezech"; "Ezek"; "Ezechiel Propheta"; "Ezechiel"; "Ezekiel" ]); ("daniel", [ "Dan"; "Daniel Propheta"; "Daniel" ]); ("osee", [ "Osee"; "Osee Propheta" ]); ("joel", [ "Joel"; "Ioel"; "Ioel Propheta" ]); ("jonas", [ "Jonas"; "Ionae"; "Ionas Propheta" ]); - ("malachi", [ "Mal"; "Malach"; "Malachias Propheta"; "Malachias" ]); - ("matthew", [ "Matt"; "Matt."; "Matth"; "Evangelium secundum Matthaeum"; "Matthew" ]); + ("malachi", [ "Mal"; "Malach"; "Malachias Propheta"; "Malachias"; "Malachi" ]); + ("matthew", [ "Matt"; "Matt."; "Matth"; "Mat"; "Evangelium secundum Matthaeum"; "Matthew" ]); ("mark", [ "Mark"; "Marc"; "Evangelium secundum Marcum" ]); ("luke", [ "Luke"; "Luc"; "Evangelium secundum Lucam" ]); ("john", [ "John"; "Ioann"; "Evangelium secundum Ioannem" ]); - ("acts", [ "Acts"; "Act"; "Actus Apostolorum"; "Acts of the Apostles" ]); + ("acts", [ "Acts"; "Act"; "Actus Apostolorum"; "Acts of the Apostles"; "The Acts" ]); ("romans", [ "Rom"; "Epistola ad Romanos"; "Romans" ]); ("corinthians_1", [ "1 Cor"; "1 Cor."; "Epistola I ad Corinthios"; "1 Corinthians" ]); ("corinthians_2", [ "2 Cor"; "2 Cor."; "Epistola II ad Corinthios"; "2 Corinthians" ]); @@ -64,6 +64,73 @@ let table = an [of_token] entry would let one book carry two different ids. *) ("apocalypse", [ "Apoc"; "Rev"; "Liber Apocalypsis"; "Apocalypse" ]) ] +(* Fix wave I2 (final-review.md, 2026-08-25-colitur-of-phases-3-5): books + data/of/lectionary.sexp cites that no EF file ever needed, so the survey + above never registered them -- 345 of 730 OF citation fields printed + unconverted (35%) because [Book.of_token] had never heard of them, not + because [Parse]'s grammar itself could not read the reference. English- + canonical spellings only, verified directly against that one file + (`grep`, not invented) -- the SAME "every spelling any of the files uses" + discipline [table] above states, extended to a fourth file. + + Deliberately a SEPARATE table, not folded into [table] above, for one + reason that matters: [table]'s ids are covered by [all] below, and + book.mli's own contract for [all] is "every SHIPPED language file is + asserted complete over" it (test_lang_coverage.ml's [test_every_book_ + named] and its siblings). lang/la.ini's own header is equally strict -- + "do not invent a Latin title", every `.full`/`.abbr` row cited to an + exact scan line -- and NONE of these 25 books is attested anywhere in + the EF's own scans (the EF lectionary/propers/commons never read from + Ruth, Job, Judges, Philemon, ... at all). Registering them in [table] + would force a choice between fabricating 50 uncited Latin titles (the + one thing this project refuses hardest) and quietly weakening book.mli's + own stated promise for the ids that DO have one. Neither is right, so + these ids are resolvable ([of_token]/[tokens]/[default_spelling] below + all include them) but excluded from [all] -- a citation using one still + PARSES and RENDERS (bin/main.ml's own [names_of] already falls back to + {!default_spelling} on a lang-table miss, book.mli's own documented + reason that function exists), it just renders in its own English + spelling rather than a Latin one no primary source has ever supplied, + the exact "degraded, not broken" contract {!default_spelling} documents. + + [samuel_1]/[samuel_2] in particular are NOT [kings_1]/[kings_2] below: + those tradition targets already denote (via traditions.ini's own + [modern] mapping, "kings_3 = kings_1") the SAME physical book as the + Vulgate's own [kings_3]/[kings_4] ("3/4 Kings" = modern "1/2 Kings") -- + a different pair of books from Samuel ("Liber Regum I/II" in the + Vulgate's own naming, never cited by any shipped EF data and so never + given an id before now). *) +let of_lectionary_table = + [ ("samuel_1", [ "1 Sam"; "1 Samuel" ]); + ("samuel_2", [ "2 Sam"; "2 Samuel" ]); + ("joshua", [ "Josh"; "Joshua" ]); + ("judges", [ "Judg"; "Judges" ]); + ("ruth", [ "Ruth" ]); + ("deuteronomy", [ "Deut"; "Deuteronomy" ]); + ("chronicles_1", [ "1 Chron"; "1 Chronicles" ]); + ("chronicles_2", [ "2 Chron"; "2 Chronicles" ]); + ("ezra", [ "Ezra" ]); + ("job", [ "Job" ]); + ("ecclesiastes", [ "Eccl"; "Ecclesiastes" ]); + ("baruch", [ "Bar"; "Baruch" ]); + ("lamentations", [ "Lam"; "Lamentations" ]); + ("amos", [ "Amos" ]); + ("micah", [ "Mic"; "Micah" ]); + ("nahum", [ "Nah"; "Nahum" ]); + ("habakkuk", [ "Hab"; "Habakkuk" ]); + ("zephaniah", [ "Zeph"; "Zephaniah" ]); + ("haggai", [ "Hag"; "Haggai" ]); + ("zechariah", [ "Zech"; "Zechariah" ]); + ("maccabees_1", [ "1 Macc"; "1 Maccabees" ]); + ("maccabees_2", [ "2 Macc"; "2 Maccabees" ]); + ("philemon", [ "Phlm"; "Philemon" ]); + ("jude", [ "Jude" ]); + (* [john_2]/[john_3], siblings of [john_1] above -- three separate + Johannine epistles, three separate ids, the same one-id-per-physical- + book rule every other entry in this file follows. *) + ("john_2", [ "2 John" ]); + ("john_3", [ "3 John" ]) ] + (* 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: @@ -89,15 +156,20 @@ let tradition_target_table = let tradition_targets = List.map fst tradition_target_table +(* Deliberately NOT [of_lectionary_table] -- see that table's own header for + why: those ids have no la.ini-verified name, so they stay out of the set + {!Colitur_naming.Lang}-completeness checks (test_lang_coverage.ml) run + against, without weakening what those checks still guarantee for every id + here. *) let all = List.map fst table @ tradition_targets let tokens = List.concat_map (fun (id, sp) -> List.map (fun s -> (s, id)) sp) - (table @ tradition_target_table) + (table @ tradition_target_table @ of_lectionary_table) let default_spelling id = - match List.assoc_opt id (table @ tradition_target_table) with + match List.assoc_opt id (table @ tradition_target_table @ of_lectionary_table) with | Some (first :: _) -> first | Some [] | None -> id @@ -120,3 +192,18 @@ let unknown_fields fields = fields let map tr id = match List.assoc_opt id tr with Some x -> x | None -> id + +(* Fix wave I2: books with exactly one chapter are conventionally cited by + VERSE ALONE, no chapter number at all ("Jude 17, 20b-25", "Phlm 7-22") -- + found while adding [of_lectionary_table] above: [jude]'s own citation + "Jude 17,20b-25" used to fail as "unknown book" (safe, if unconverted); + registering [jude] made it PARSE, but WRONGLY -- [Parse]'s existing + "a leading comma-piece that looks like a number introduces a chapter" + rule (parse.ml's own [parse_part], written for real multi-chapter data + like "15, 1-46") misread "17" as chapter 17, which does not exist in a + 25-verse, one-chapter book. A parse that SUCCEEDS with the wrong + structure is worse than one that fails: nothing downstream would ever + suspect it. [Parse.parse] consults this to skip that rule entirely for + these four ids and default to chapter 1. *) +let single_chapter_ids = [ "jude"; "philemon"; "john_2"; "john_3" ] +let is_single_chapter id = List.mem id single_chapter_ids |
