Mova0.5 pre-release⌕
☰
home / docs / tools / macula

macula

MACULA Hebrew lowfat syntax trees of the Hebrew Bible into dependency trees, in CoNLL-U, as Ancient Hebrew (hbo) and Biblical Aramaic (arc); the Targums as text layers and a verse-aligned index in three languages.

Source. MACULA Hebrew Linguistic Datasets, available at github.com/Clear-Bible/macula-hebrew. © Biblica, Inc., CC BY 4.0. The syntax is the Westminster Hebrew Syntax of the J. Alan Groves Center (CC BY 4.0). The text and morphology come from the Open Scriptures Hebrew Bible (CC BY 4.0). The fields from the Semantic Dictionary of Biblical Hebrew (sdbh, lexdomain, coredomain, contextualdomain) are left out.

How it works

MACULA gives each sentence as word groups: clauses, with the roles of their parts (s, v, o, o2, io, pp, adv, p), and noun, preposition, number and adjective phrases, relative clauses and coordinations. The tool reads a dependency tree off them by head rules:

Words are MACULA's: prefixes (ו, ה, ב, ל …) and suffix pronouns are words of their own, and a written word of more than one is a multiword token (as in PTNK); the article swallowed by a preposition (בַּ = בְּ + הַ) is written ה. A name MACULA keeps as one word with a space (בְּאֵר שָׁבַע) is a word per part, flat:name. The paseq ׀, sof pasuq ׃ and the paragraph marks ס, פ are PUNCT tokens. FORM and LEMMA are in NFC. FEATS holds gender, number, person, PronType and the verb stem (HebBinyan, letters only). MISC holds the English gloss, the word reference, Strong's number and MACULA's argument frame (Frame=A0:…;A1:…, who does what), where it has one, and Lang=arc on the Aramaic words. The files pass the UD validator at level 2 (--lang hbo); level 3 finds 95 errors in the Torah (mostly advmod on a word that is no ADV).

Every tree is checked before it is written: one head per word, one root, no cycle (a negative control in the tests shows red).

Run

macula <lowfat-dir> <out-dir> [BOOK,…]

It writes <out-dir>/<BOOK>.conllu, with # sent_id = wlc:<BOOK>:<n> (one document per book) and # verse = GEN.1.1. It also writes <out-dir>/verses.tsv, which maps ids to verses. school-sents usfm gives English translations the same verse map, so the two line up verse by verse.

The Aramaic sentences go apart, to <out-dir>/arc/<BOOK>.conllu (# sent_id = wlc-arc:<BOOK>:<n>) and arc/verses.tsv. A sentence goes by the language of most of its words (MACULA's lang="A"); the whole Bible gives 268 Aramaic sentences (7 555 words, in Daniel, Ezra and Jeremiah 10:11) beside 22 945 Hebrew ones, and 2 sentences mix the two (Genesis 31:47 stays Hebrew).

Words are written in the order of the text. MACULA gives them in the order of its groups, which in 742 of 22 945 sentences (146 in the Torah) takes a word from further on (Ruth 1:1: «וַיֵּלֶךְ אִישׁ מִבֵּית לֶחֶם», אִישׁ in the subject group after the place). The heads are read in MACULA's order, then the words are sorted by their id and the heads renumbered. The scores against PTNK do not change, since they match words by id.

tools/hbo trains Mova's own parser for raw Hebrew on these trees.

Biblical Aramaic

MACULA marks every word with its language (lang="H" or "A"). The Aramaic words are Daniel 2:4b–7:28, Ezra 4:8–6:18 and 7:12–26, Jeremiah 10:11 and two words of Genesis 31:47. A sentence most of whose words are Aramaic goes to <out-dir>/arc/ (UD code arc), as above. Only two sentences mix the languages: Daniel 2:4 (the Hebrew frame «and the Chaldeans spoke to the king in Aramaic», then their words) goes to Aramaic, Genesis 31:47 (the name יְגַר שָׂהֲדוּתָא) stays Hebrew. Every Aramaic word has Lang=arc in MISC (in either folder), and a Hebrew word in an Aramaic sentence Lang=hbo.

The Aramaic trees use the same head rules, FEATS and MISC as the Hebrew ones; the stem is in HebBinyan too (PEAL, PAEL, HAPHEL, HITHPEEL …). Three lists have Aramaic members, used only for Aramaic words: the copula הֲוָה, the demonstratives דְּנָה, דָּא, אִלֵּין, דֵּךְ, אִלֵּךְ, דִּכֵּן (det), and the subordinator הֵן «if». The rest (verbs of saying אמר, ענה) share their consonants with Hebrew.

Limits: there is no Aramaic treebank to measure against, so the trees are unmeasured. MACULA's English glosses in the Aramaic chapters are shifted by one word around the emphatic article (the noun «the», the article «king»), and are carried as they are. The emphatic ending א is a word of its own (DET, det), as MACULA splits it.

The whole Tanakh (2026-10-18)

macula <WLC lowfat> <out>; the corpus keeps <out> as text/tanakh-wlc-macula and <out>/arc as text/tanakh-arc-macula:

sentenceswordsbooks
Hebrew (hbo)22 945468 35639
Aramaic (arc)2687 5553 (DAN, EZR, JER)

0 trees fail the check; 1 106 groups had no rule for their head (first child). Every book passes the UD validator at level 2, the Hebrew with --lang hbo, the Aramaic with --lang arc (and hbo).

The Targums and the three-language index

macula targums <sefaria Tanakh/Targum dir> <text-dir>
macula tanakh3 <text-dir> <en-pool.tsv> <out-dir>

targums copies the Targums from Sefaria's export as text layers, verse by verse (BOOK.C.V → text, markup off, NFC): Targum Onkelos (the Torah, the toratemetfreeware edition), Targum Jonathan (the Prophets, Mikraot Gedolot) and the later Targums of the Writings (Psalms, Proverbs, Job, the Song, Ruth, Lamentations, Ecclesiastes, Esther from Mikraot Gedolot; Chronicles from Wikisource). Only an edition whose licence is «Public Domain» is copied; any other is refused (a test shows red on CC BY-SA and NC). Each layer has a SOURCES.tsv.

tanakh3 writes one TSV per book, a row per verse in the Hebrew numbering: the verse, the Hebrew sentence ids, the Aramaic (Biblical Aramaic sentence ids, and the Targum verse as onkelos:, jonathan: or targum:BOOK.C.V) and the English sentence ids (the pool's .verses). A sentence that spans verses is listed at each.

Measured (2026-10-18), verses with each language:

versesHebrewAramaicEnglishall three
Torah5 8535 8535 8465 8525 845
Prophets9 2969 2959 2969 2949 293
Writings8 0657 7977 2898 0577 014

The Writings' Aramaic is missing where there is no Targum (Daniel's Hebrew chapters, Ezra, Nehemiah); the 268 verses of Daniel and Ezra in Aramaic have the Aramaic and no Hebrew. Eleven verses have no English sentence of their own: JPS joins them to the verse before inside one sentence (Psalm titles, Numbers 26:1).

The English follows the Hebrew numbering: eBible's JPS 1917 gives JPS's own (Hebrew) numbers in brackets where they differ from the English ones, and school-sents usfm … --hebrew-verses maps each sentence to the Hebrew verse it begins in (the marks are taken off before the cut, so the ids are the same with and without the flag, and the Torah keeps the ids of its pool of 2026-10-17). In the Ten Commandments (Exodus 20, Deuteronomy 5) JPS counts by the upper accents and the Westminster Leningrad Codex by the lower ones, as the English does, so there the English numbering stays.

No Aramaic parser exists yet: the Targums are text only, and their trees come later.

Measured (2026-10-17)

The Torah (GEN–DEU):

The whole Hebrew Bible (39 books, 2026-10-18): 23 213 sentences and 475 911 words, 7 549 of them Aramaic (Lang=arc: DAN 5 687, EZR 1 835, JER 25, GEN 2); 0 trees fail the check; 1 106 groups had no rule for their head. The head rules were made on the Torah and are not measured beyond it.

Against UD PTNK

UD Ancient Hebrew PTNK (UD 2.18) is CC BY-NC, so it serves only as a measure. Its words carry MACULA ids, so they line up word for word (macula compare). LAS is counted on the relation without its subtype. The rules are decided on train and dev; the test split is read once per change of the rules.

2026-10-17test UAStest LASdev UASdev LAStrain UAStrain LAS
first head rules86.2473.7984.5970.87
UD conventions for Hebrew88.3882.2386.6179.9887.1080.72
PTNK's readings, see below96.5193.5896.0493.0996.4393.63

The second row follows the UD conventions for Hebrew: the construct chain is compound:smixut; subordinating conjunctions (כִּי, אִם, לְמַעַן, פֶּן …) are mark; a demonstrative after a noun is det; an infinitive after a preposition advcl; the parts of a compound number flat; a clause right after a verb of saying, with no conjunction between, its ccomp; a ו at the head of a clause hangs on the clause's head, and a conjunction never on another conjunction.

The third row reads the groups as PTNK does (above, «How it works»). Each rule's gain, dev / train, UAS and LAS (LAS only where no head changes), measured when it was added or by leaving it out of its step:

ruledev UASdev LAStrain UAStrain LAS
a number, adverb or adjective before a noun: the noun heads+2.71+2.32+2.22+1.97
ClCl2, CLandCL2: the last clause heads+1.21+1.01+1.54+1.42
groups of function words spliced (מֵ + עִם, וְ + עַתָּה)+0.68+0.63+0.72+0.72
a preposition or את before a headless relative heads (PpRelp, OmpRelp)+0.48+0.46+0.37+0.38
in a group of clauses ו belongs to the clause after it; a clause after כִּי, אִם … is advcl+0.70+0.86+0.99+1.11
a clause after a clause with no conjunction is parataxis+0.15+0.66
QuanNP, AdjpofNp and a participle or adjective in construct are compound:smixut+1.46+1.13
זֶה, זֹאת, אֵלֶּה are det+0.35+0.28
a participle after a noun is acl:relcl+0.08+0.14
the article on a verbal participle is mark+0.21+0.19
לֵאמֹר: ל heads, אמר fixed, ל the quote's mark+0.37+0.37+0.51+0.52
הָיָה with an o predicate is a copula+1.44+1.41+0.91+0.88
הָיָה with a prepositional predicate (not וַיְהִי) is a copula+0.77+0.73+1.17+1.12
the quote's later clauses hang on its first, up to a wayyiqtol+0.33+0.30+0.34+0.29
o2 is xcomp+0.07+0.11
an infinitive after יכל, צוה, נתן, יסף, מאן … is xcomp+0.20+0.14
a noun phrase in adv is obl+0.64+0.35
the infinitive absolute in adv is obl:npmod+0.08+0.16
a later member of a list is conj+0.38+0.43
an object clause is ccomp+0.05+0.29+0.03+0.16
גַּם, אַף are advmod+0.19+0.13
the parts of a number after ו are conj+0.17+0.12
כִּי אִם: אִם is fixed+0.01+0.00+0.01+0.02
a headless relative after any preposition (כַּאֲשֶׁר)+0.05+0.00+0.09+0.05
תַּחַת, נֶגֶד, עִמָּד, נֹכַח head their phrase+0.35+0.32+0.29+0.27
a relative clause on the noun after כָּל hangs on כָּל+0.31+0.31+0.17+0.17
נָא and other interjections in adv are discourse+0.09+0.06

Measured and not kept: flattening a coordination inside a later conjunct (dev UAS −0.10, train +0.02); an adjective on the noun after כָּל hung on כָּל (dev −0.07); carrying the quote of לֵאמֹר over the clauses after it (train +0.01).

Lemmas compare by their consonants, since the order of points differs between sources.

Still apart from PTNK (train, right head, other relation): conj → parataxis 309, orphan → obl 179 (gapping is not read), xcomp → obl 143 (a second accusative of material, «overlay it with gold»), ccomp → obj 142, advmod → cc 121, advcl → parataxis 111. Most head errors left are where PTNK's sentences and MACULA's differ (a word is the root in one and a conj or parataxis in the other).

The dictionaries

The code is in src/dict.rs.

macula dict <trees-dir> <BDB.jsonl> <LexicalIndex.xml> <dict.tsv> [<en-pool.tsv>] [--lang arc] [--jastrow <Jastrow.jsonl>]
macula targum <onkelos-dir> <Jastrow.jsonl> <trees-dir> <en-pool.tsv> <out.tsv> [<n>]

dict builds an English dictionary of the words in the trees: the Hebrew words, or with --lang arc the Aramaic ones (Lang=arc).

Entries. Each row of dict.tsv has the key, lemma, count, MACULA's commonest glosses, the short definition of the OpenScriptures lexical index (CC BY 4.0; its Hebrew or its Aramaic part), the Brown–Driver–Briggs entry of 1906 (public domain, via Sefaria; for Aramaic its Aramaic part) and why, which says how each entry was chosen. The BDB entry is given twice: its bold senses as a short meaning, and its whole text with the markup taken off. With --jastrow, three more columns give the entry of Jastrow's dictionary of 1903 (public domain, via Sefaria): headword, italic senses, whole text.

Keys. A Hebrew word's key is its Strong's number. MACULA's extended numbers carry a letter (2050b is the conjunction ו, not Strong's 2050), so for them the key is the lemma (lemma:וְ). An Aramaic word's key is its lemma.

Which entry. One Strong's number often covers several entries (BDB lists 2617 under both חֶסֶד «goodness» and חֶסֶד² «shame»), and the first version took the first entry whose headword was the lemma, or the first entry of the number. Now every entry that lists the word's number or has its consonants is a candidate, and they are ranked, in order, by:

  1. a part of speech that does not differ from the word's. BDB's bold abbreviations (n.m., vb., prep. …) and Jastrow's gender and verb stems are read; only the open classes are compared (noun, adjective and number count as one, a name, a verb), since for the small words MACULA and the dictionaries part their classes differently;
  2. a full entry over a bare cross-reference («v. אבה»);
  3. a headword that is the lemma, pointed or without dagesh;
  4. how many of the verses where the word is used the entry cites;
  5. how many words of its bold (BDB) or italic (Jastrow) senses are among MACULA's glosses;
  6. a headword with the same consonants, ו and י aside (בְּכֹר, BDB בְּכוֹר);
  7. an entry of the word's language (Jastrow marks the Aramaic ones «ch.»);
  8. an entry that lists the word's Strong's number (only the word's commonest number, and not a lettered one);
  9. the dictionary's order.

A candidate with another headword must list the number. One with the same consonants only must list it, cite one of the word's verses, or, for an Aramaic word, be an Aramaic entry that shares a word with the glosses. The OSHB definition is chosen the same way, by headword, part of speech, the words it shares with the BDB entry chosen (חֶסֶד «goodness», not «shame»), the words it shares with the glosses, the number, and the index's order.

Examples. With an English pool from school-sents usfm … --hebrew-verses, dict.tsv.examples gives each word examples in layers: the verse in Hebrew (or Aramaic), word for word (MACULA's glosses), the verse in JPS 1917, and an empty column for the idea, a commentary to come. The examples are the word's two shortest one-verse sentences, ties going to the earlier book. The pool must be cut with --hebrew-verses: eBible's JPS numbers its verses the English way and gives the Hebrew number where it differs (982 marks in the Psalms alone), and our trees use the Hebrew numbers.

Targum Onkelos. targum counts the written forms of Onkelos (Sefaria's text, public domain, …/Targum/Onkelos/Torah/Onkelos <Book>/Hebrew/Onkelos <Book>.json) and matches each to a Jastrow entry: the headword itself, the same without dagesh, the same after a prefix ו ד ל ב, or the same consonants. A match by consonants only must cite one of the verses where the form is. Among the candidates the one wins whose italic senses are among MACULA's glosses of the Hebrew verses the form translates in the most verses (בַּר «son», not «field»), then the one that cites the most of these verses, then an Aramaic entry. The forms of one entry make one word. <out.tsv> lists the n commonest words (300 by default) with their forms; .examples gives each its two shortest verses with Onkelos, the Hebrew it translates, word for word and JPS 1917.

Pages. The site writes the dictionaries' pages from these tables (papers mova-site --tanakh-dict … --aramaic-dict … --targum … --torah-dict …, module hebrew_dicts): a page per word, the letters a hundred words to a page, a front with the 200 commonest words, Targum Onkelos fifty words to a page; each word with the glosses, OSHB, BDB and Jastrow meanings (whole entries folded), why they were chosen, and its verses, each linked to its page in the corpora.

Run (2026-10-18)

L=$RESEARCH_RAW/lexres/dictionaries; D=$MOVA_DATA/corpora/judaism/dict
macula <WLC/lowfat> $D/wlc-trees
school-sents usfm <ebible/engjps> $D/tanakh-jps1917.tsv jps - --hebrew-verses
macula dict $D/wlc-trees $L/sefaria/BDB_Dictionary.jsonl $L/oshb-hebrewlexicon/LexicalIndex.xml $D/tanakh-en.tsv $D/tanakh-jps1917.tsv
macula dict <torah trees> $L/sefaria/BDB_Dictionary.jsonl $L/oshb-hebrewlexicon/LexicalIndex.xml $D/torah-en.tsv $D/tanakh-jps1917.tsv
macula dict $D/wlc-trees $L/sefaria/BDB_Aramaic_Dictionary.jsonl $L/oshb-hebrewlexicon/LexicalIndex.xml $D/aramaic-en.tsv $D/tanakh-jps1917.tsv --lang arc --jastrow $L/sefaria/Jastrow_Dictionary.jsonl
macula targum <Onkelos/Torah> $L/sefaria/Jastrow_Dictionary.jsonl $D/wlc-trees $D/tanakh-jps1917.tsv $D/targum-onkelos.tsv 300

All of it takes about 25 s.

Measured (2026-10-18)

Limits.

Pragmatics

macula prag reads each Hebrew sentence into the columns of the parse database's prag.tsv: form, act, indirect, hedge, polarity, voice. It does this by rules on MACULA's words: the verb type in MISC Type= (wayyiqtol, imperative, jussive, cohortative, yiqtol, weqatal, …), person in FEATS, interrogatives, negatives and נָא. The code is in src/prag.rs.

macula prag <trees-dir> <out.tsv> [--with rule,…] [--without rule,…]
macula prag-compare <out.tsv> <trees-dir>/verses.tsv <en prag.tsv> <en pool.tsv.verses>
macula prag-quotes <en pool.tsv>

The rules are also a library call, macula::prag::read_sentence(rows, open_before, &Rules), which roundtrip mixed uses on the trees of the Hebrew parser.

prag adds four columns after teacher:

prag-quotes prints the JPS quote state of each English sentence, so the speech measure can be checked by eye.

How it works

  1. The sentence is cut into frame and quote.
    • לֵאמֹר opens a quote whatever verb comes before it, and everything after it is the quote. If only its own words follow («לֵאמֹר לוֹ»), the quote is in the next sentence.
    • Otherwise the ccomp our trees hang on a verb of saying (אמר, דבר, צוה, ענה, שאל, קרא) is the quote, together with the later clauses on that verb.
    • A narrator's wayyiqtol in the third person ends the quote: «וַיְהִי אוֹר», and there was light.
    • קָרָא with שֵׁם as its object names something. It does not speak.
    • In a multi-verb frame (וַיַּעַן … וַיֹּאמֶר) the later verb takes the quote.
  2. The quote is read as a character's speech, and the frame as narration. The row follows the English convention: a sentence that holds a quote takes the quote's form and act and voice «character». The frame's reading is kept in frame.
  3. Speech is carried from sentence to sentence within a book.
    • A frame that ends a verse («And the LORD spoke unto Moses, saying:») and a quote that reaches the end of its verse both leave a quote open.
    • The next sentence goes on in it (cont) until a narrator takes the story up again. That is a wayyiqtol in the third person with no first or second person in its clause, or a qatal with no mark of speech in the sentence.
  4. The speech is read.
    • An imperative, jussive or cohortative, or an infinitive absolute heading the clause, gives form imp and act request.
    • A yiqtol or weqatal in the second person («thou shalt (not) …») gives act request with indirect 1.
    • A question word (מִי, מָה, אֵיךְ, …) gives form wh, and interrogative הֲ gives q. A question takes act ask unless its first clause is a volitive.
    • A yiqtol or weqatal in the first person gives promise.
    • The form is the first clause's. The act is that of any clause.
    • נָא gives hedge 1.
    • Narration is decl, with act narrate for a wayyiqtol and assert otherwise.
  5. Polarity is left none. The English scheme's polarity is the speaker's evaluation (Smart annotator — layers, context, memory), not negation. Negation has its own column.

What is measured, and what each number means

prag-compare lines up the 5 782 verses that are one Hebrew sentence with the English reading of the same verses, which a teacher gave JPS 1917 sentence by sentence in the parse database. It gives:

Measured (2026-10-17)

The Torah, 5 782 verses that are one Hebrew sentence. Speech is given as agreement, and for Genesis also as precision / recall.

formactact classpolarityvoicevoice alonespeech GENspeech EXOspeech NUMnegation
the constant answer87.048.474.385.068.068.0————
root-based version (before)89.447.178.181.665.868.063.6 (97.2 / 27.7)64.372.7—
no rule (--without all)89.149.379.185.071.471.478.5 (97.8 / 58.2)72.977.897.8
now91.854.781.985.065.374.495.7 (96.5 / 94.9)83.983.197.8
the teacher's own voice86.4 (98.9 / 73.4)72.076.0

Reading the table:

Two runs give the same files byte for byte, and a run takes 0.13 s.

Each rule, left out of the rules now in use, or put in when it is off. The figures are the change in points. The decisions were made on the Genesis speech measure and on act class. Exodus and Numbers were watched as a check, so they are not strictly held out.

rulewhat it doeseffectkept
ccompthe ccomp of a verb of saying is the quotespeech GEN +12.2, EXO +4.9, NUM +3.3; act +4.5, class +2.4, form +2.3yes
carryquotes go on into the next sentencesspeech GEN +3.8, EXO +5.1, NUM +1.7; voice against the teacher −10.7 (it misses carried speech)yes
lemorלֵאמֹר opens a quote after any verbspeech GEN +1.3, NUM +4.2yes
close-qatala qatal with no mark of speech closes a quotespeech GEN +1.1, EXO +2.3, NUM +2.8yes
promisefirst-person yiqtol/weqatal in speech is a promise (commissive)act +0.6, class +0.5yes
first-formthe form is the first clause'sform +0.6yes
infabsan infinitive absolute heading a clause commandsform +0.2, act +0.3, class +0.3yes
ask-firsta question asks even with a second-person verbact +0.2, class +0.1yes
amarafter a finite אמר, what follows its arguments is the quote, or the next sentence isact −0.1, speech GEN ±0, NUM −0.3no
inner-framea frame inside open speech, or in the 1st/2nd person, is the character'sact −0.9, speech GEN −0.2, NUM −1.2no
proposea plural cohortative, or a jussive with נָא, suggestsact −0.2no
resolvea singular cohortative is the speaker's resolve (promise)act −0.1, class −0.1no
rhetoricalהֲלֹא assertsact −0.1no
close-offlineany unmarked clause that is not yiqtol/weqatal/volitive closes a quotespeech GEN −1.5, EXO −3.1 (voice against the teacher +6.8)no
law3a third-person yiqtol/weqatal in carried law prescribesact −4.1, class −8.7no
neg-polaritya negation makes polarity «neg» (the first versions)polarity −4.6no
evaluatewords that judge (טוב, ברך … / רע, ארר, חטא …) give polarity, negation flips itpolarity −5.4no

A distinction between לֹא + yiqtol (a lasting prohibition) and אַל + jussive (a specific one) was also tried. It changed nothing: the first is already a second-person command and the second a volitive. It was left out.

Sources

These were read, from the Scientist's library, and this is what each gave.

Limits

Limits

This page in Markdown → https://md.mova.elamur.ai/free/en/docs/tools/macula/