Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mora

A prosody engine, built on the mora.

Status (2026-08-18)

Published as mora 0.1.0. The engine is complete and tested; no pronunciation lexicon ships with it.

mora turns pronunciations into the units verse is measured in. It reads phones and knows nothing about spelling.

  • Syllabification by the sonority hierarchy with onset maximization. am.ber splits because sonority falls across the cluster; po.e.try keeps tr whole because it rises. What varies between languages is a rule struct, not the procedure.
  • Weight, counted in morae. A syllable is light, heavy, or superheavy depending on whether its nucleus is long and whether the language counts a coda consonant. That one flag is most of the difference between stress-timed, syllable-timed, and mora-timed languages, and it is why a haiku counted in English syllables comes out short.
  • Meter, accentual and quantitative from the same matcher. English iambic pentameter reads stress; Latin dactylic hexameter reads weight; Mode chooses, and nothing else changes. Scansion reports how much of a line fit, so a trochaic first foot registers as a substitution inside iambic pentameter rather than as a different meter.
  • Sonance: rhyme anchored at the last primary-stressed nucleus, plus slant rhyme, assonance, consonance, and alliteration. cat/hat rhyme, cat/cab are slant, cat/kit alliterate and share a consonant frame, and no word rhymes with itself.

The layering, and why it generalizes

The mora sits underneath the usual prosodic typology: syllable weight is counted in morae, weight-sensitive stress rules read that count, and quantitative meter is moraic outright. So only the bottom layer is language-specific.

layer per-language cost
phones a symbol table
syllables a SyllableRule
weight a WeightRule
meter nothing
sound kinship nothing

English ships as one module: a 39-entry ARPAbet table and two constants. A second language costs the same. The Latin stress rule is included as the proof that weight is the deeper layer, since it reads weight alone and no stress at all.

#![no_std], #![forbid(unsafe_code)], zero dependencies. Every collecting function has an _into form that writes into a caller buffer, so the whole engine runs without an allocator.

Use

First consumer is a writing surface that draws a poem as a wheel, with rhyme and meter as chords across it. Usable from any Rust project that needs to measure sound in text: verse tools, songwriting, TTS front ends, language teaching, or search over how words sound rather than what they mean.

cargo add mora
cargo add mora --no-default-features    # language-neutral core, no allocator
use mora::english::{SYLLABLE_RULE, WEIGHT_RULE, pronounce};
use mora::meter::{Foot, Mode, beats, scan_best};
use mora::sonance::is_perfect_rhyme;
use mora::syllable::syllabify;

let cat = pronounce("K AE1 T").unwrap();
let hat = pronounce("HH AE1 T").unwrap();
let (a, b) = (syllabify(&cat, SYLLABLE_RULE), syllabify(&hat, SYLLABLE_RULE));
assert!(is_perfect_rhyme((&cat, &a), (&hat, &b)));

// "the CAT is HERE" scans as two iambs.
let line = pronounce("DH AH0 K AE1 T IH0 Z HH IY1 R").unwrap();
let syllables = syllabify(&line, SYLLABLE_RULE);
let scansion = scan_best(
    &beats(&line, &syllables, Mode::Accentual, WEIGHT_RULE),
    &Foot::COMMON,
).unwrap();
assert_eq!(scansion.meter.foot, Foot::Iamb);

Pronunciations

None are bundled. Pronunciation lexicons are large and separately licensed, so this crate parses the format CMUdict publishes (english::cmudict_entry) and leaves storage to the consumer. Anything that can produce ARPAbet symbols will do, including a phonemizer of your own.

Boundaries

mora measures sound. It is not a phonemizer, not a semantic analyzer, and not a rhyming dictionary: it answers whether two given pronunciations rhyme, not which words in a language do. Meaning-side kinship belongs to an embedding model, and the two are meant to be read side by side rather than merged.

The canonical sound-kinship API is mora::sonance. The separately named sonance repository is an archive pointer, not another implementation or dependency surface.

License

MPL-2.0 (see LICENSE). Provenance is recorded in LICENSES.md: nothing here is third-party, and no lexicon ships. Published mora 0.1.0 keeps the MIT OR Apache-2.0 grant it shipped with; MPL-2.0 reaches crates.io at the next functional bump.


This README was generated by AI and will be edited by the author upon release.

About

A prosody engine built on the mora: syllabification, syllable weight, accentual and quantitative meter, and sound kinship.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages