diff --git a/vidyut-prakriya/Makefile b/vidyut-prakriya/Makefile index e5bf45c..517bb74 100644 --- a/vidyut-prakriya/Makefile +++ b/vidyut-prakriya/Makefile @@ -56,13 +56,13 @@ test_tinantas: --hash "f8934f99631e811c333c41ddd4925229d2faab0dd875bc549bb38350319706db" ../target/release/test_tinantas \ --test-cases test-files/tinantas-nic-kartari.csv \ - --hash "5e173e6665872f205f8c6ca2addc166e221f0d435b800dee4360116d0a8af69b" + --hash "2e3d0f56c4e6d375b7064df034a7ee04a7cc91f10838ceee32cbeb37ad2870c5" ../target/release/test_tinantas \ --test-cases test-files/tinantas-san-kartari.csv \ - --hash "a4bce1c19d54ea2246429dbd345acaca24c380ac3b8c888ddb442e9d862af679" + --hash "0dfec6333abf094ed8199694e2e55436991f837cacf223de3fd1223b576712e3" ../target/release/test_tinantas \ --test-cases test-files/tinantas-yan-kartari.csv \ - --hash "b8c4b3cf7a7e5572af8a1290118f629fbf6812925fe6a41bf9ffadb47a658446" + --hash "08c5b0f9b6b2fa857018653583b63571eac3074804025d90c12e0c30a0db0616" ../target/release/test_tinantas \ --test-cases test-files/tinantas-basic-karmani.csv \ --hash "da0e4771bec284661bfd0f537734d44eb6e019e41a387e80dfaa80cf7dc27b03" @@ -71,10 +71,10 @@ test_krdantas: cargo build --release ../target/release/test_krdantas \ --test-cases test-files/krdantas-ktvA.csv \ - --hash "13cd3088b99eeea4d30d91e58f28ad07e9082e6f92f122ff64f4c367dd4ff36c" + --hash "f4e31b5df19f578133834be6abaaa802eee3d836bdb5487cfcef3a936eeb2204" ../target/release/test_krdantas \ --test-cases test-files/krdantas-kta.csv \ - --hash "650a4bc2e761f201389595785a5e6ab8a3023f657c58699aa269c01d28c75aae" + --hash "ddf06443f6ce62147fce21baed15afcb4720d1d9e69698157653cab3ace9e3c0" test_subantas: cargo run --bin test_subantas -- \ diff --git a/vidyut-prakriya/scripts/check_rule_coverage.py b/vidyut-prakriya/scripts/check_rule_coverage.py index 238a924..a1195c5 100755 --- a/vidyut-prakriya/scripts/check_rule_coverage.py +++ b/vidyut-prakriya/scripts/check_rule_coverage.py @@ -38,8 +38,8 @@ def print_legend(): for path in glob.glob("**/*.rs", root_dir=tests, recursive=True): with open(tests / path) as f: for line in f: - if m := re.search(r"(\d+_\d+_\d+)", line): - tested_rules.add(m.group(1).replace('_', '.')) + for match in re.findall(r"(\d+_\d+_\d+)", line): + tested_rules.add(match.replace('_', '.')) print_legend() num_ok = 0 diff --git a/vidyut-prakriya/src/ac_sandhi.rs b/vidyut-prakriya/src/ac_sandhi.rs index bc34a56..d1cc86b 100644 --- a/vidyut-prakriya/src/ac_sandhi.rs +++ b/vidyut-prakriya/src/ac_sandhi.rs @@ -2,14 +2,14 @@ //! ========= //! (6.1.66 - 6.1.101) -use crate::char_view::{get_at, xy, CharPrakriya}; +use crate::core::char_view::{get_at, xy, CharPrakriya}; +use crate::core::iterators::xy_rule; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; use crate::it_samjna; -use crate::iterators::xy_rule; -use crate::operators as op; -use crate::prakriya::Prakriya; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; use lazy_static::lazy_static; lazy_static! { @@ -22,7 +22,6 @@ lazy_static! { static ref EC: Set = s("ec"); static ref VAL: Set = s("val"); static ref HAL: Set = s("hal"); - static ref YAN: Set = s("yaR"); } pub fn try_lopo_vyor_vali(p: &mut Prakriya) { @@ -84,19 +83,6 @@ pub fn apply_general_ac_sandhi(p: &mut Prakriya) { }, ); - cp.for_chars(xy(|x, y| EC.contains(x) && AC.contains(y)), |p, text, i| { - let x = text.as_bytes()[i] as char; - let sub = match x { - 'e' => "ay", - 'E' => "Ay", - 'o' => "av", - 'O' => "Av", - _ => panic!("Unexpected sub"), - }; - p.run("6.1.78", |p| p.set_char_at(i, sub)); - true - }); - // HACK: ignore sandhi between upasarga and dhatu so that we can correctly derive prARinat, // etc. fn is_upasarga_sanadi_dhatu(p: &Prakriya, i: usize) -> bool { @@ -104,33 +90,50 @@ pub fn apply_general_ac_sandhi(p: &mut Prakriya) { && p.terms().last().expect("present").is_dhatu() } - cp.for_chars( - xy(|x, y| AK.contains(x) && AK.contains(y) && al::savarna(x).contains(y)), - |p, text, i| { + cp.for_chars(xy(|x, y| AC.contains(x) && AC.contains(y)), |p, text, i| { + p.dump(); + let x = text.as_bytes()[i] as char; + let y = text.as_bytes()[i + 1] as char; + + let t_x = get_at(p, i).expect("ok"); + + if t_x.has_tag(T::Pragrhya) { + // agnI iti, ... + p.step("6.1.125"); + false + } else if AK.contains(x) && AK.contains(y) && al::savarna(x).contains(y) { if is_upasarga_sanadi_dhatu(p, i) { return false; } - let x = text.as_bytes()[i] as char; p.run("6.1.101", |p| { p.set_char_at(i, &al::to_dirgha(x).expect("should be ac").to_string()); p.set_char_at(i + 1, ""); }); true - }, - ); - - cp.for_chars(xy(|x, y| IK.contains(x) && AC.contains(y)), |p, text, i| { - let x = text.as_bytes()[i] as char; - let res = match x { - 'i' | 'I' => "y", - 'u' | 'U' => "v", - 'f' | 'F' => "r", - 'x' | 'X' => "l", - _ => panic!("Unexpected res"), - }; - p.run("6.1.77", |p| p.set_char_at(i, res)); - true + } else if EC.contains(x) && AC.contains(y) { + let sub = match x { + 'e' => "ay", + 'E' => "Ay", + 'o' => "av", + 'O' => "Av", + _ => panic!("Unexpected sub"), + }; + p.run("6.1.78", |p| p.set_char_at(i, sub)); + true + } else if IK.contains(x) && AC.contains(y) { + let res = match x { + 'i' | 'I' => "y", + 'u' | 'U' => "v", + 'f' | 'F' => "r", + 'x' | 'X' => "l", + _ => panic!("Unexpected res"), + }; + p.run("6.1.77", |p| p.set_char_at(i, res)); + true + } else { + false + } }); // upa + fcCati -> upArcCati @@ -146,10 +149,9 @@ pub fn apply_general_ac_sandhi(p: &mut Prakriya) { // upa + eti -> upEti cp.for_terms( |x, y| { - x.is_upasarga() - && x.has_antya(&*A) - && y.has_u_in(&["i\\R", "eDa~\\"]) - && y.has_adi(&*EN) + let eti_edhati = y.has_adi(&*EN) && y.has_u_in(&["i\\R", "eDa~\\"]); + let is_uth = y.has_adi('U') && y.has_tag(T::FlagUth); + !x.is_agama() && x.has_antya(&*A) && (eti_edhati || is_uth) }, |p, _i, j| { let y = p.get(j).expect("ok"); @@ -159,11 +161,14 @@ pub fn apply_general_ac_sandhi(p: &mut Prakriya) { }, ); - // HACK for KOnAti + // HACK for KOnAti, DOta, and a few others cp.for_terms( - |x, _| x.has_text("KaU"), + |x, _| x.has_suffix_in(&["aU", "AU"]), |p, i, _| { - p.run_at("6.1.89", i, |t| t.set_text("KO")); + p.run_at("6.1.89", i, |t| { + t.set_antya(""); + t.set_antya("O") + }); }, ); @@ -223,7 +228,7 @@ pub fn try_sup_sandhi_before_angasya(p: &mut Prakriya) -> Option<()> { /// Helper function for `try_sup_sandhi_after_angasya` to avoid too much nesting. fn try_sup_sandhi_after_angasya_for_term(p: &mut Prakriya, i_sup: usize) -> Option<()> { - let i_anga = i_sup - 1; + let i_anga = p.find_prev_where(i_sup, |t| !t.is_empty())?; let anga = p.get(i_anga)?; let sup = p.get(i_sup)?; @@ -253,7 +258,7 @@ fn try_sup_sandhi_after_angasya_for_term(p: &mut Prakriya, i_sup: usize) -> Opti p.set(i_anga, op::antya("ur")); p.set(i_sup, op::adi("")); }); - } else if anga.has_text("saKi") || anga.has_text("pati") { + } else if anga.has_text_in(&["saKi", "pati"]) { // saKyuH, patyuH p.run_at("6.1.112", i_sup, op::text("us")); } @@ -329,6 +334,12 @@ fn apply_ac_sandhi_at_term_boundary(p: &mut Prakriya, i: usize) -> Option<()> { ); } + // TODO: not sure where else to put this. + let t = p.get(i)?; + if p.is_pada(i) && t.has_text("div") { + p.run_at("6.1.131", i, |t| t.set_antya("u")); + } + Some(()) } @@ -344,7 +355,7 @@ fn try_sut_kat_purva(p: &mut Prakriya) -> Option<()> { let prev = p.get(i_prev)?; let optional_add_sut_agama = |rule, p: &mut Prakriya, i_dhatu: usize| { - if p.run_optional(rule, |p| op::insert_agama_before(p, i_dhatu, "su~w")) { + if p.optional_run(rule, |p| op::insert_agama_before(p, i_dhatu, "su~w")) { it_samjna::run(p, i_dhatu).expect("ok"); } }; diff --git a/vidyut-prakriya/src/angasya.rs b/vidyut-prakriya/src/angasya.rs index 1b1da1c..a9d8249 100644 --- a/vidyut-prakriya/src/angasya.rs +++ b/vidyut-prakriya/src/angasya.rs @@ -1,6 +1,6 @@ //! One of the largest sections of the Ashtadhyayi starts with 6.4.1 and extends to the end of 7.4. //! Rule 6.4.1, *angasya*, declares that all rules within its scope apply to an *anga*, i.e. an -//! inflection base followed by a prefix. +//! inflectional base followed by a suffix. //! //! The *angasya* section of the Ashtadhyayi contains the grammar's core operations, such as: //! @@ -14,25 +14,23 @@ mod abhyasasya; mod asiddhavat; mod guna_vrddhi; -mod sup_adesha; +mod subanta; use crate::args::Lakara; +use crate::args::Unadi; pub use asiddhavat::try_cinvat_for_bhave_and_karmani_prayoga; use crate::ac_sandhi; use crate::args::Gana::*; -use crate::char_view::{get_at, xy, CharPrakriya}; +use crate::core::char_view::{get_at, xy, CharPrakriya}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Code, Prakriya, Rule}; use crate::dhatu_gana as gana; -use crate::filters as f; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya, Rule}; -use crate::samjna; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::stem_gana; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -61,6 +59,11 @@ fn maybe_rule(p: &mut Prakriya, rule: Code) -> Option { } } +fn add_num(t: &mut Term) { + op::mit("n")(t); + t.add_tag(T::FlagNum); +} + /// Runs rules that lengthen a vowel in the anga. fn try_do_dirgha(p: &mut Prakriya, i_anga: usize) -> Option<()> { let anga = p.get_if(i_anga, |t| !t.is_it_agama())?; @@ -76,7 +79,7 @@ fn try_do_dirgha(p: &mut Prakriya, i_anga: usize) -> Option<()> { p.run_at("6.4.2", i_anga, |t| t.set_antya(&sub.to_string())); } else if anga.has_u("kramu~") && n.has_u("ktvA") { // krantvA, krAntvA - p.run_optional_at("6.4.18", i_anga, |t| t.set_upadha("A")); + p.optional_run_at("6.4.18", i_anga, |t| t.set_upadha("A")); } else if (anga.has_antya(&*AC) || anga.has_u_in(&["ha\\na~", "ga\\mx~", "gami~"])) && n.has_u("san") { @@ -89,7 +92,7 @@ fn try_do_dirgha(p: &mut Prakriya, i_anga: usize) -> Option<()> { p.run_at(code, i_anga, |t| t.set_upadha("A")); } } else if anga.has_u("tanu~^") && n.has_u("san") { - p.run_optional_at("6.4.17", i_anga, |t| t.set_upadha("A")); + p.optional_run_at("6.4.17", i_anga, |t| t.set_upadha("A")); } else if anga.has_antya(&*ANUNASIKA) && (n.has_u("kvi~p") || jhal_knit()) { let blocked = anga.has_tag(T::FlagNoDirgha); if let Some(sub) = al::to_dirgha(anga.upadha()?) { @@ -142,7 +145,7 @@ fn try_cchvoh(p: &mut Prakriya) -> Option<()> { Some(()) } -pub fn try_run_dirgha_for_sarvanamasthane_asambuddhau( +fn try_run_dirgha_for_sarvanamasthane_asambuddhau( p: &mut Prakriya, i: usize, i_sup: usize, @@ -151,6 +154,10 @@ pub fn try_run_dirgha_for_sarvanamasthane_asambuddhau( let sup = p.get(i_sup)?; let sau = sup.has_u("su~"); + if !(sup.is_sarvanamasthana() && !sup.has_tag(T::Sambuddhi)) { + return None; + } + if anga.has_antya('n') { if anga.ends_with("in") || anga.has_text("pUzan") { let sub = al::to_dirgha(anga.upadha()?)?; @@ -161,7 +168,7 @@ pub fn try_run_dirgha_for_sarvanamasthane_asambuddhau( // yogI p.run_at("6.4.13", i, op::upadha(&sub.to_string())); } - } else { + } else if !sup.is_lupta() { // PalAni let sub = al::to_dirgha(anga.upadha()?)?; p.run_at("6.4.8", i, op::upadha(&sub.to_string())); @@ -173,36 +180,18 @@ pub fn try_run_dirgha_for_sarvanamasthane_asambuddhau( t.set_at(c, &sub.to_string()); }); } else if anga.has_text("ap") - || anga.has_tag(T::TrnTrc) + || anga.has_tag_in(&[T::TrnTrc, T::FlagTrjvat]) || anga.has_u_in(&[ "svasf", "naptf", "nezwf", "tvaswf", "kzawf", "hotf", "potf", "praSAstf", ]) { let sub = al::to_dirgha(anga.upadha()?)?; p.run_at("6.4.11", i, op::upadha(&sub.to_string())); - } - - Some(()) -} - -/// Runs various rules that cause dirgha-adesha in the anga. -/// This specific dirgha-adesha must occur before inserting num-agama. -/// -/// Example: gomat -> gomAt -> gomAnt -> gomAn -fn try_dirgha_adesha_before_num_agama(p: &mut Prakriya) -> Option<()> { - let i_sup = p.find_last(T::Sup)?; - let i_anga = p.find_prev_where(i_sup, |t| !t.is_agama())?; - - let anga = p.get(i_anga)?; - let sup = p.get(i_sup)?; - let sau = sup.has_u("su~"); - let is_atu = anga.has_tag(T::udit) && anga.ends_with("at"); - - if sup.has_tag(T::Sarvanamasthana) && !sup.has_tag(T::Sambuddhi) { - if (is_atu || anga.ends_with("as")) && sau && !anga.is_dhatu() { - let sub = al::to_dirgha(anga.upadha()?)?; - p.run_at("6.4.14", i_anga, op::upadha(&sub.to_string())); - } + } else if anga.has_text("svanp") { + // for svAmpi and svampi (svap + [jas -> Si]) + p.optional_run_at(Rule::Kaumudi("446"), i, |t| { + t.set_at(t.text.len() - 3, "A"); + }); } Some(()) @@ -230,7 +219,7 @@ fn try_dirgha_adesha_for_sup(p: &mut Prakriya) -> Option<()> { } else if anga.has_text("nf") { // nfRAm, nFRAm let sub = al::to_dirgha(anga.antya()?)?; - p.run_optional_at("6.4.6", i_anga, op::antya(&sub.to_string())); + p.optional_run_at("6.4.6", i_anga, op::antya(&sub.to_string())); } else if anga.has_antya('n') { let sub = al::to_dirgha(anga.upadha()?)?; p.run_at("6.4.7", i_anga, op::upadha(&sub.to_string())); @@ -238,7 +227,7 @@ fn try_dirgha_adesha_for_sup(p: &mut Prakriya) -> Option<()> { let sub = al::to_dirgha(anga.antya()?)?; p.run_at("6.4.3", i_anga, op::antya(&sub.to_string())); } - } else if sup.has_tag(T::Sarvanamasthana) && !sup.has_tag(T::Sambuddhi) { + } else { try_run_dirgha_for_sarvanamasthane_asambuddhau(p, i_anga, i_sup); } @@ -275,7 +264,7 @@ pub fn maybe_do_jha_adesha(p: &mut Prakriya) -> Option<()> { it_samjna::run(p, i).ok()?; } else if base.has_u("vida~") && base.has_gana(Adadi) { // vidate, vidrate - if p.run_optional("7.1.7", add_rut) { + if p.optional_run("7.1.7", add_rut) { it_samjna::run(p, i).ok()?; } } @@ -315,6 +304,10 @@ pub fn try_pratyaya_adesha(p: &mut Prakriya) -> Option<()> { let last = p.get_if(i, |t| t.is_pratyaya())?; let prev = p.get(i - 1)?; + if last.is_final() { + return None; + } + if last.has_text_in(&["yu~", "vu~"]) { if last.has_text("yu~") { p.run_at("7.1.1", i, op::text("ana")); @@ -346,7 +339,14 @@ pub fn try_pratyaya_adesha(p: &mut Prakriya) -> Option<()> { && p.has(i - 1, |t| t.has_u("SnA")) && t.has_text("hi") { - op::adesha("3.1.83", p, i - 1, "SAnac"); + let mut blocked = false; + if p.is_chandasi() { + // gfBAya, ... + blocked = op::optional_adesha("3.1.84", p, i - 1, "SAyac"); + } + if !blocked { + op::adesha("3.1.83", p, i - 1, "SAnac"); + } } } @@ -414,7 +414,7 @@ fn try_shiti(p: &mut Prakriya) -> Option<()> { if anga.has_u("sf\\") { // sartervegitāyāṃ gatau dhāvādeśam icchanti। anyatra sarati, anusarati // ityeva bhavati. (kAzikA) - can_run = !p.run_optional(Rule::Kashika("7.3.78"), |_| {}); + can_run = !p.optional_run(Rule::Kashika("7.3.78"), |_| {}); } if can_run { // pibati, jiGrati, Damati, ... @@ -447,60 +447,19 @@ fn try_pvadinam_hrasva(p: &mut Prakriya) -> Option<()> { Some(()) } -fn try_add_num_agama_for_sarvanamasthana(p: &mut Prakriya) -> Option<()> { - let i = p.find_last(T::Pratipadika)?; - let anga = p.get(i)?; - let sup = p.get(i + 1)?; - let napum = p.has_tag(T::Napumsaka); - - if sup.has_tag(T::Sarvanamasthana) { - if anga.has_tag_in(&[T::udit, T::fdit]) && !anga.is_dhatu() { - p.run_at("7.1.70", i, op::mit("n")); - } else if napum && (anga.has_antya(&*JHAL) || anga.has_antya(&*AC)) { - p.run_at("7.1.72", i, op::mit("n")); - } - } else if napum && anga.has_antya(&*IK) && sup.has_adi(&*AC) && sup.has_tag(T::Vibhakti) { - p.run_at("7.1.73", i, op::mit("n")); - } - - Some(()) -} - -/// Adds Agamas for words like trayA-R-Am, sarve-z-Am, etc. -fn try_add_agamas_to_sup(p: &mut Prakriya) -> Option<()> { - let last = p.terms().last()?; - // Check for `Bahuvacana` explicitly to exclude the `Am`-adesha for mAlAyAm, etc. - if last.has_text("Am") && last.has_tag(T::Bahuvacana) && last.has_tag(T::Sup) { - let i_last = p.terms().len() - 1; - let i_anga = i_last - 1; - let anga = p.get(i_last - 1)?; - if anga.has_tag(T::Sarvanama) { - op::insert_agama_at("7.1.52", p, i_last, "su~w"); - } else if anga.has_text("tri") { - // trayaH - p.run_at("7.1.53", i_anga, op::text("traya")); - } else if anga.is_hrasva() || anga.has_tag(T::Nadi) || anga.has_tag(T::StriNyap) { - op::insert_agama_at("7.1.54", p, i_last, "nu~w"); - } else if anga.has_tag(T::Sat) || anga.has_text("catur") { - op::insert_agama_at("7.1.55", p, i_last, "nu~w"); - } - } - - Some(()) -} - fn try_add_num_agama_for_dhatu_before_asiddhavat(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; let anga = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if anga.has_text_in(&["masj", "naS"]) && n.has_adi(&*JHAL) { p.run_at("7.1.60", i, |t| { if t.has_text("masj") { // "masjerantyāt pūrva numam icchanti anuṣaṅgādilopārtham।" (KV). t.set_text("masnj"); + t.add_tag(T::FlagNum); } else { - op::mit("n")(t); + add_num(t); } }); } @@ -518,17 +477,17 @@ fn try_add_num_agama_for_dhatu(p: &mut Prakriya) -> Option<()> { // 7.1.58 (idito nuM dhAtoH) is in `dhatu_karya`, so we skip it here. let anga = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if anga.has_u_in(gana::MUC_ADI) && n.has_u("Sa") { // muYcati - p.run_at("7.1.59", i, op::mit("n")); + p.run_at("7.1.59", i, add_num); } else if anga.has_u_in(gana::TRMPH_ADI) && n.has_u("Sa") { // tfmPati, ... - p.run_at("7.1.59.v1", i, op::mit("n")); + p.run_at("7.1.59.v1", i, add_num); } let anga = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let liti = n.has_lakshana("li~w"); if anga.has_u("qula\\Ba~\\z") && anga.has_text("laB") { let yi = n.has_adi('y'); @@ -540,27 +499,27 @@ fn try_add_num_agama_for_dhatu(p: &mut Prakriya) -> Option<()> { } else if n.has_u_in(&["Kal", "GaY"]) { if has_upasarga { // pralamBa, ... - p.run_at("7.1.67", i, op::mit("n")); + p.run_at("7.1.67", i, add_num); } // Otherwise, we get lABa, etc. } else if !has_upasarga && n.has_u_in(&["ciR", "Ramu~l"]) { - p.run_optional_at("7.1.69", i, op::mit("n")); + p.optional_run_at("7.1.69", i, add_num); } else if n.has_adi(&*AC) && !n.has_u("Sap") && !liti { - p.run_at("7.1.64", i, op::mit("n")); + p.run_at("7.1.64", i, add_num); } else if yi && i > 0 && p.has(i - 1, |t| t.has_u("AN")) { - p.run_at("7.1.65", i, op::mit("n")); + p.run_at("7.1.65", i, add_num); } else if yi && i > 0 && p.has(i - 1, |t| t.has_u("upa")) { - p.run_optional_at("7.1.66", i, op::mit("n")); + p.optional_run_at("7.1.66", i, add_num); } } else if n.has_adi(&*AC) { if anga.has_text("raD") || (anga.has_text("jaB") && anga.has_u("jaBI~\\")) { - if anga.has_u("ra\\Da~") && n.first()?.is_it_agama() && !liti { + if anga.has_u("ra\\Da~") && n.first().is_it_agama() && !liti { p.step("7.1.62"); } else { - p.run_at("7.1.61", i, op::mit("n")); + p.run_at("7.1.61", i, add_num); } } else if anga.has_u("ra\\Ba~\\") && anga.has_text("raB") && !n.has_u("Sap") && !liti { - p.run_at("7.1.63", i, op::mit("n")); + p.run_at("7.1.63", i, add_num); } } @@ -585,31 +544,30 @@ pub fn try_add_iit_agama(p: &mut Prakriya) -> Option<()> { let i_pratyaya_start = p.find_next_where(i_anga, |t| !t.is_empty())?; let anga = p.get(i_anga)?; - let n = p.view(i_pratyaya_start)?; + let n = p.pratyaya(i_pratyaya_start)?; let is_aprkta = n.slice().iter().map(|t| t.text.len()).sum::() == 1; if n.has_adi(&*HAL) && n.has_tag(T::Sarvadhatuka) { // HACK to avoid yAsut and prevent bruvIyAt, etc. let piti = n.has_tag(T::pit) && !n.has_tag(T::Nit); - let mut rule = None; if anga.has_text("brU") && piti { - rule = Some("7.3.93"); + op::insert_agama_at("7.3.93", p, i_pratyaya_start, "Iw"); } else if p.has(i_anga + 1, |t| t.has_u("yaN")) && piti { // HACK: use `i_anga + 1` to point to yaN, which is empty due to luk. - rule = maybe_rule(p, "7.3.94"); + p.optionally("7.3.94", |rule, p| { + op::insert_agama_at(rule, p, i_pratyaya_start, "Iw"); + }); } else if anga.has_u_in(&["tu\\", "ru", "zwu\\Y", "Samu~", "ama~"]) { - rule = maybe_rule(p, "7.3.95"); + p.optionally("7.3.95", |rule, p| { + op::insert_agama_at(rule, p, i_pratyaya_start, "Iw"); + }); } else if is_aprkta { // 7.3.98 overrides 7.2.76 in the it-Agama section, so it's placed there. if anga.has_u_in(&["asa~", "si~c"]) { - rule = Some("7.3.96"); + op::insert_agama_at("7.3.96", p, i_pratyaya_start, "Iw"); } } - - if let Some(rule) = rule { - op::insert_agama_at(rule, p, i_pratyaya_start, "Iw"); - } } Some(()) @@ -677,7 +635,7 @@ fn try_change_anga_before_y(p: &mut Prakriya) -> Option<()> { let i = p.find_first_where(|t| t.is_dhatu() || t.is_pratipadika())?; let i_n = p.find_next_where(i, |t| !t.is_empty())?; let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let akrt_sarva = !n.has_tag_in(&[T::Sarvadhatuka, T::Krt]); let has_upasarga = i > 0 && p.has(i - 1, |t| t.is_upasarga()); @@ -700,7 +658,7 @@ fn try_change_anga_before_y(p: &mut Prakriya) -> Option<()> { p.run_at("7.4.24", i, op::adi("i")); } else if anga.has_antya('f') { let dhatu = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let is_sha_or_yak = n.has_u_in(&["Sa", "yak"]); let is_ardhadhatuka_lin = n.has_lakshana("li~N") && n.has_tag(T::Ardhadhatuka); let is_sha_yak_lin = is_sha_or_yak || (n.has_adi('y') && is_ardhadhatuka_lin); @@ -726,8 +684,9 @@ fn try_change_anga_before_y(p: &mut Prakriya) -> Option<()> { p.run_at("7.4.27", i, op::antya("rI")); } } else if anga.has_u("ha\\na~") && n.has_u("yaN") { - p.run_optional_at("7.4.30.v1", i, op::text("GnI")); + p.optional_run_at("7.4.30.v1", i, op::text("GnI")); } else if anga.has_u_in(&["GrA\\", "DmA\\"]) && n.has_u("yaN") { + // jeGrIyate, deDmIyate p.run_at("7.4.31", i, op::antya("I")); } else if n.has_adi('y') { let sub = al::to_dirgha(anga.antya()?)?; @@ -757,8 +716,8 @@ fn try_anga_changes_to_t(p: &mut Prakriya, i_anga: usize) -> Option<()> { if anga.is_dhatu() { let anga = p.get(i_anga)?; - let n = p.view(i_anga + 1)?; - if anga.has_antya('s') && n.has_adi('s') && n.last()?.is_ardhadhatuka() { + let n = p.pratyaya(i_anga + 1)?; + if anga.has_antya('s') && n.has_adi('s') && n.last().is_ardhadhatuka() { p.run_at("7.4.49", i_anga, op::antya("t")); } @@ -772,7 +731,7 @@ fn try_anga_changes_to_t(p: &mut Prakriya, i_anga: usize) -> Option<()> { p.run_at(code, i_anga, op::antya("i")); } } else if anga.has_text_in(&["SA", "CA"]) { - p.run_optional_at("7.4.41", i_anga, op::antya("i")); + p.optional_run_at("7.4.41", i_anga, op::antya("i")); } else if anga.has_u("quDA\\Y") { p.run_at("7.4.42", i_anga, op::text("hi")); } else if anga.has_u("o~hA\\k") && next.has_u("ktvA") { @@ -787,8 +746,10 @@ fn try_anga_changes_to_t(p: &mut Prakriya, i_anga: usize) -> Option<()> { } } else { let next = p.get(i_anga + 1)?; - if anga.has_text("ap") && next.has_adi('B') { - p.run_at("7.4.48", i_anga, op::text("at")); + // Include terms ending with "ap" per Kaumudi. There aren't many, so to avoid generating, + // specify them manually. + if anga.has_text_in(&["ap", "svap"]) && next.has_adi('B') { + p.run_at("7.4.48", i_anga, |t| t.set_antya("t")); } } @@ -806,15 +767,13 @@ pub fn try_add_or_remove_nit(p: &mut Prakriya) -> Option<()> { let last = p.get(i)?; if anga.has_text("go") && last.is_sarvanamasthana() { - p.run_at("7.1.90", i, op::add_tag(T::Rit)); + p.add_tag_at("7.1.90", i, T::Rit); } else if anga.has_antya('o') && last.is_sarvanamasthana() { - p.run_at("7.1.90.v1", i, op::add_tag(T::Rit)); + p.add_tag_at("7.1.90.v1", i, T::Rit); } else if last.has_u("Ral") && last.has_tag(T::Uttama) { - p.run_optional_at("7.1.91", i, |t| { + p.optional_run_at("7.1.91", i, |t| { t.remove_tag(T::Rit); }); - } else if anga.has_text("saKi") && last.is_sarvanamasthana() && !last.has_tag(T::Sambuddhi) { - p.run_at("7.1.92", i, op::add_tag(T::Rit)); } Some(()) @@ -824,8 +783,10 @@ pub fn try_add_or_remove_nit(p: &mut Prakriya) -> Option<()> { /// /// (7.4.50 - 7.4.52) fn try_tas_asti_lopa(p: &mut Prakriya, i: usize) -> Option<()> { + let is_asti = |t: &Term| t.has_u("asa~") && t.has_gana(Adadi); + let term = p.get(i)?; - if term.has_text("tAs") || f::is_asti(term) { + if term.has_text("tAs") || is_asti(term) { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let n = p.get(i_n)?; if n.has_adi('s') { @@ -846,7 +807,7 @@ fn try_tas_asti_lopa(p: &mut Prakriya, i: usize) -> Option<()> { /// A miscellaneous function that needs to be refactored. fn unknown(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if anga.has_u("SIN") && anga.has_text("SI") { if n.is_knit() && n.has_adi('y') { @@ -922,7 +883,7 @@ fn try_change_cu_to_ku(p: &mut Prakriya, i: usize) -> Option<()> { } let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let has_c_j_antya = anga.has_antya('c') || anga.has_antya('j'); let sanlitoh = n.has_u("san") || n.has_lakshana("li~w"); let has_upasarga = |s| i > 0 && p.has(i - 1, |t| t.has_u(s)); @@ -934,7 +895,7 @@ fn try_change_cu_to_ku(p: &mut Prakriya, i: usize) -> Option<()> { p.step("7.3.60"); true } else if anga.has_u("vancu~") { - p.run_optional("7.3.63", |_| {}) + p.optional_run("7.3.63", |_| {}) } else if n.has_u("Ryat") { if anga.has_u_in(&["ya\\ja~^", "quyAcf~^", "ruca~\\", "fca~"]) || (anga.has_u("va\\ca~") && has_upasarga("pra")) @@ -942,13 +903,13 @@ fn try_change_cu_to_ku(p: &mut Prakriya, i: usize) -> Option<()> { p.step("7.3.66"); true } else if anga.has_u("va\\ca~") { - p.run_optional("7.3.67", |_| {}) + p.optional_run("7.3.67", |_| {}) } else if anga.has_u("yu\\ji~^r") && (has_upasarga("pra") || has_upasarga("ni")) { - p.run_optional("7.3.68", |_| {}) + p.optional_run("7.3.68", |_| {}) } else if anga.has_u("Bu\\ja~") { - p.run_optional("7.3.69", |_| {}) + p.optional_run("7.3.69", |_| {}) } else if has_c_j_antya { - p.run_optional("7.3.65", |_| {}) + p.optional_run("7.3.65", |_| {}) } else { false } @@ -957,24 +918,27 @@ fn try_change_cu_to_ku(p: &mut Prakriya, i: usize) -> Option<()> { }; let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if blocked { // Skip } else if has_c_j_antya && (n.has_tag(T::Git) || n.has_u("Ryat")) { let sub = convert(anga.antya()?)?; p.run_at("7.3.52", i, op::antya(sub)); + } else if anga.has_text("masj") && n.first().has_unadi(Unadi::u) { + let sub = convert(anga.antya()?)?; + p.run_at("7.3.53", i, op::antya(sub)); } else if anga.has_u("ha\\na~") && anga.has_adi('h') { - if anga.has_tag(T::Abhyasta) { + if anga.is_abhyasta() { p.run_at("7.3.55", i, op::adi("G")); } else if n.has_tag_in(&[T::Yit, T::Rit]) || anga.has_text("hn") { p.run_at("7.3.54", i, op::adi("G")); } - } else if anga.has_u("hi\\") && anga.has_tag(T::Abhyasta) && !n.has_u("caN") { + } else if anga.has_u("hi\\") && anga.is_abhyasta() && !n.has_u("caN") { p.run_at("7.3.56", i, op::adi("G")); } else if sanlitoh && anga.has_u("ji\\") && anga.has_gana(Bhvadi) { p.run_at("7.3.57", i, op::adi("g")); } else if sanlitoh && anga.has_u("ci\\Y") { - p.run_optional_at("7.3.58", i, op::adi("k")); + p.optional_run_at("7.3.58", i, op::adi("k")); } Some(()) @@ -1006,20 +970,24 @@ fn try_dhatu_rt_adesha(p: &mut Prakriya, i: usize) -> Option<()> { fn try_ato_dirgha(p: &mut Prakriya, i: usize) -> Option<()> { // HACK: work around lack of support for "ekah pUrvaparayoH" by skipping empty wAp-pratyaya. let i_next = p.find_next_where(i, |t| !t.is_empty())?; + let n = p.pratyaya(i_next)?; - let n = p.view(i_next)?; - - let ends_in_a = |t: &Term| t.has_antya('a'); + // For sanity / predictability, examine a nyAp-anta pratipadika only once. That is, if we have + // a pratipadika at index i and a nyap-pratyaya at index i + 1, accept i + 1 but reject i. + if p.has(i + 1, |t| t.is_nyap_pratyaya()) { + return None; + } if n.has_tag(T::Sarvadhatuka) { - if p.has(i, ends_in_a) && n.has_adi(&*YANY) { + if p.has(i, |t| t.has_antya('a')) && n.has_adi(&*YANY) { p.run_at("7.3.101", i, op::antya("A")); } - } else if n.has_tag(T::Sup) { - let anga = p.get(i)?; - let sup = p.view(i_next)?; - let is_aap = (anga.has_antya('A') && anga.has_tag(T::StriNyap)) - || p.has(i + 1, |t| t.has_u_in(&["wAp"])); + } else if n.last().is_sup() { + let anga = p.nyap_pratipadika(i)?; + let is_aap = anga.last().is_aap_pratyaya(); + let i_last_non_empty = anga.end_non_empty()?; + + let sup = p.pratyaya(i_next)?; let is_sambuddhi = sup.has_tag(T::Sambuddhi); // > bhyamādeśe kṛte śeṣelope ca bahuvacane jhalyet iti etvaṃ prāpnoti, tadaṅgavṛtte @@ -1032,27 +1000,27 @@ fn try_ato_dirgha(p: &mut Prakriya, i: usize) -> Option<()> { p.run_at("7.3.103", i, op::antya("e")); } else if sup.has_adi(&*YANY) { p.run_at("7.3.102", i, op::antya("A")); - } else if sup.last()?.has_text("os") { + } else if sup.last().has_text("os") { // devayoH p.run_at("7.3.104", i, op::antya("e")); } - } else if is_aap && (sup.last()?.has_text("os") || sup.has_u("wA")) { + } else if is_aap && (sup.last().has_text("os") || sup.has_u("wA")) { // senayoH - p.run_at("7.3.105", i, op::antya("e")); + p.run_at("7.3.105", i_last_non_empty, op::antya("e")); } else if is_sambuddhi - && (anga.has_text_in(&["ambA", "akkA", "allA"]) || anga.has_tag(T::Nadi)) + && (anga.first().has_text_in(&["ambA", "akkA", "allA"]) || anga.has_tag(T::Nadi)) { // amba, alla, akka, nadi let sub = al::to_hrasva(anga.antya()?)?; - p.run_at("7.3.107", i, op::antya(&sub.to_string())); + p.run_at("7.3.107", i_last_non_empty, op::antya(&sub.to_string())); } else if is_sambuddhi && is_aap { // sene - p.run_at("7.3.106", i, op::antya("e")); + p.run_at("7.3.106", i_last_non_empty, op::antya("e")); } else { let anga = p.get(i)?; if al::is_hrasva(anga.antya()?) && !anga.has_antya('a') { let sub = al::to_guna(anga.antya()?)?; - if sup.has_tag(T::Sambuddhi) { + if is_sambuddhi { // agne, vAyo p.run_at("7.3.108", i, op::antya(sub)); } else if sup.has_u("jas") { @@ -1075,7 +1043,7 @@ fn try_ato_dirgha(p: &mut Prakriya, i: usize) -> Option<()> { fn try_sic_vrddhi(p: &mut Prakriya) -> Option<()> { let i = p.find_last(T::Dhatu)?; - let vikarana = p.view(i + 1)?; + let vikarana = p.pratyaya(i + 1)?; let (i_it, i_sic) = match vikarana.slice().len() { 1 => (None, vikarana.start()), 2 => (Some(vikarana.start()), vikarana.end()), @@ -1185,7 +1153,7 @@ fn try_cani_before_guna(p: &mut Prakriya) -> Option<()> { // 7.4.7 blocks guna. if dhatu.has_upadha(&*FF) && is_nici && (is_cani || will_be_cani) { - p.run_optional_at("7.4.7", i, |t| { + p.optional_run_at("7.4.7", i, |t| { t.set_upadha("f"); t.add_tag(T::FlagGunaApavada); }); @@ -1219,7 +1187,7 @@ fn try_cani_after_guna(p: &mut Prakriya) -> Option<()> { "pIqa~", ]) { let sub = al::to_hrasva(dhatu.upadha()?)?; - p.run_optional_at("7.4.3", i, op::upadha(&sub.to_string())); + p.optional_run_at("7.4.3", i, op::upadha(&sub.to_string())); return Some(()); } @@ -1238,7 +1206,7 @@ fn try_cani_after_guna(p: &mut Prakriya) -> Option<()> { done = true; } else if i > 0 && dhatu.has_u("GrA\\") { // ajiGripat, ajiGrapat - done = p.run_optional_at("7.4.6", i, |t| t.set_antya("i")); + done = p.optional_run_at("7.4.6", i, |t| t.set_antya("i")); } if done { @@ -1320,7 +1288,7 @@ fn try_ksa_lopa(p: &mut Prakriya) -> Option<()> { && tin.has_adi(&*DANTYA) { // aduhvahi/aDukzAvahi, adugDA/aDukzata, ... - p.run_optional_at("7.3.73", i, op::luk); + p.optional_run_at("7.3.73", i, op::luk); } } @@ -1343,7 +1311,7 @@ fn try_add_agama_before_ni(p: &mut Prakriya) -> Option<()> { } let optional_append_agama = |rule, p: &mut Prakriya, i, sub| -> bool { - if p.run_optional(rule, |p| op::insert_agama_after(p, i, sub)) { + if p.optional_run(rule, |p| op::insert_agama_after(p, i, sub)) { it_samjna::run(p, i + 1).expect("ok"); true } else { @@ -1380,180 +1348,19 @@ fn try_add_agama_before_ni(p: &mut Prakriya) -> Option<()> { } else if dhatu.has_text("sPAy") { p.run_at("7.3.41", i, op::antya("v")); } else if dhatu.has_text("Sad") { - p.run_optional_at("7.3.42", i, op::antya("t")); + p.optional_run_at("7.3.42", i, op::antya("t")); } else if dhatu.has_text("ruh") { - p.run_optional_at("7.3.43", i, op::antya("p")); + p.optional_run_at("7.3.43", i, op::antya("p")); } Some(()) } -/// Runs rules that replace the first sounds of `asmad` and `yuzmad`, up to and including their `m` -/// sound. -fn try_maparyanta_for_asmad_and_yusmad(p: &mut Prakriya) -> Option<()> { - let i = p.find_first_where(|t| t.has_u_in(&["asmad", "yuzmad"]))?; - let sup = p.get_if(i + 1, |t| t.is_vibhakti())?; - - if sup.has_tag(T::Dvivacana) { - p.run_at("7.2.92", i, |t| { - t.find_and_replace_text("yuzm", "yuva"); - t.find_and_replace_text("asm", "Ava"); - }); - } else if sup.has_lakshana("jas") { - p.run_at("7.2.93", i, |t| { - t.find_and_replace_text("yuzm", "yUya"); - t.find_and_replace_text("asm", "vaya"); - }); - } else if sup.has_lakshana("su~") { - p.run_at("7.2.94", i, |t| { - t.find_and_replace_text("yuzm", "tva"); - t.find_and_replace_text("asm", "aha"); - }); - } else if sup.has_lakshana("Ne") { - p.run_at("7.2.95", i, |t| { - t.find_and_replace_text("yuzm", "tuBya"); - t.find_and_replace_text("asm", "mahya"); - }); - } else if sup.has_lakshana("Nas") { - p.run_at("7.2.96", i, |t| { - t.find_and_replace_text("yuzm", "tava"); - t.find_and_replace_text("asm", "mama"); - }); - } else if sup.has_tag(T::Ekavacana) { - p.run_at("7.2.97", i, |t| { - t.find_and_replace_text("yuzm", "tva"); - t.find_and_replace_text("asm", "ma"); - }); - } - - Some(()) -} - -/// Applies various rules that change the anga of a pratipadika. -/// -/// These changes occur *before* we change the vibhakti by making substitutions, adding Agamas, -/// etc. For changes *after* we change the vibhakti, see `try_anga_adesha_after_vibhakti_changes`. -fn try_anga_adesha_before_vibhakti_changes(p: &mut Prakriya) -> Option<()> { - let i = p.find_last(T::Pratipadika)?; - let anga = p.get(i)?; - let v = p.get(i + 1)?; - - if anga.has_text("azwan") && v.is_vibhakti() { - // Optional per Kashika. - p.run_optional_at("7.2.84", i, |t| { - t.set_antya(""); - t.set_antya("A"); - }); - } else if anga.has_text_in(&["tri", "catur"]) && p.has_tag(T::Stri) { - p.run_at("7.2.99", i, |t| { - t.find_and_replace_text("tri", "tisf"); - t.find_and_replace_text("catur", "catasf"); - }); - let v = p.get(i + 1)?; - if v.has_adi(&*AC) { - p.run_at("7.2.100", i, op::antya("r")); - } - } else if anga.has_text("jarA") && v.has_adi(&*AC) { - p.run_optional_at("7.2.101", i, op::text("jaras")); - } else if anga.has_u_in(stem_gana::TYAD_ADI) { - let i_v = i + 1; - let anga = p.get(i)?; - let v = p.get(i_v)?; - let sau = v.has_u("su~"); - - if sau && anga.has_u("adas") { - // asO - p.run("7.2.107", |p| { - p.set(i, |t| t.set_antya("O")); - p.set(i + 1, op::lopa); - }); - } else if sau && !v.is_empty() && anga.has_u("idam") { - // check for `!v.is_empty()` to allow `idam`. - p.step("7.2.108"); - if p.has_tag(T::Pum) { - p.run_at("7.2.111", i, |t| t.set_text("ayam")); - } else { - p.run_at("7.2.110", i, |t| t.set_text("iyam")); - } - } else if v.is_vibhakti() & &!v.is_empty() { - // tyaH, tyO, tye, ... - p.run_at("7.2.102", i, op::antya("a")); - } - - // 7.2.109 - 7.2.112 are in the other function. - - let anga = p.get(i)?; - if sau && !anga.has_antya('d') && !anga.has_antya('t') { - p.run_at("7.2.106", i, |t| { - t.find_and_replace_text("d", "s"); - t.find_and_replace_text("t", "s"); - }); - } - } else if anga.has_text("kim") { - if v.has_adi('t') || v.has_adi('h') { - p.run_at("7.2.104", i, op::text("ku")); - } else if v.has_u("at") { - p.run_at("7.2.105", i, op::text("kva")); - } else if v.is_vibhakti() && !v.is_empty() { - p.run_at("7.2.103", i, op::text("ka")); - } - } - - Some(()) -} - -fn try_anga_adesha_after_vibhakti_changes(p: &mut Prakriya) -> Option<()> { - let i = p.find_last(T::Pratipadika)?; - - let anga = p.get(i)?; - let sup = p.view(i + 1)?; - if !sup.has_tag(T::Sup) { - return None; - } - - if anga.has_text("rE") && sup.has_adi(&*HAL) { - p.run_at("7.2.85", i, op::antya("A")); - } else if anga.has_text_in(&["yuzmad", "asmad"]) { - let anadesha = !sup.last()?.has_any_lakshana(); - - if sup.has_adi(&*AC) && anadesha { - // mayA, tvayA - p.run_at("7.2.89", i, op::antya("y")); - } else if anadesha { - p.run_at("7.2.86", i, op::antya("A")); - } else if sup.has_tag(T::V2) { - p.run_at("7.2.87", i, op::antya("A")); - } else if sup.last()?.has_all_tags(&[T::V1, T::Dvivacana]) { - p.run_at("7.2.88", i, op::antya("A")); - } else { - p.run_at("7.2.90", i, op::antya("")); - } - } else if anga.has_text("idaa") { - if sup.has_tag_in(&[T::V1, T::V2]) { - // imam - p.run_at("7.2.109", i, |t| t.set_text("ima")); - } else { - // Other vibhaktis - if sup.has_adi(&*HAL) { - // asya - p.run_at("7.2.113", i, |t| t.find_and_replace_text("id", "")); - } else { - // anena - p.run_at("7.2.112", i, |t| t.set_text("ana")); - } - } - } - - try_maparyanta_for_asmad_and_yusmad(p); - - Some(()) -} - fn try_didhi_vevi_lopa(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if anga.has_u_in(&["dIDIN", "vevIN"]) && (n.has_adi(&*II) || n.has_adi('y')) { p.run_at("7.4.53", i, op::antya("")); } @@ -1576,6 +1383,11 @@ fn try_pratyaya_adesha_for_dhatu(p: &mut Prakriya) -> Option<()> { Some(()) } +pub fn run_before_stritva(p: &mut Prakriya) -> Option<()> { + subanta::run_before_stritva(p); + Some(()) +} + pub fn run_before_dvitva(p: &mut Prakriya) -> Option<()> { try_add_iit_agama(p); try_shiti(p); @@ -1632,16 +1444,7 @@ pub fn run_before_dvitva(p: &mut Prakriya) -> Option<()> { } pub fn run_after_dvitva(p: &mut Prakriya) -> Option<()> { - // Subanta rules - try_anga_adesha_before_vibhakti_changes(p); - sup_adesha::run_before_bhasya(p); - try_add_agamas_to_sup(p); - samjna::try_run_for_pada_or_bha(p); - asiddhavat::bhasya(p); - try_dirgha_adesha_before_num_agama(p); - try_add_num_agama_for_sarvanamasthana(p); - sup_adesha::run_after_bhasya(p); - try_anga_adesha_after_vibhakti_changes(p); + subanta::run(p); for i in 0..p.terms().len() { asiddhavat::run_after_dvitva(p, i); diff --git a/vidyut-prakriya/src/angasya/abhyasasya.rs b/vidyut-prakriya/src/angasya/abhyasasya.rs index 8b3408b..23d7a80 100644 --- a/vidyut-prakriya/src/angasya/abhyasasya.rs +++ b/vidyut-prakriya/src/angasya/abhyasasya.rs @@ -7,13 +7,13 @@ Runs rules that modify the abhyāsa. */ use crate::args::Gana; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::{Prakriya, Rule}; use crate::dhatu_gana as gana; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Prakriya, Rule}; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; -use crate::tag::Tag as T; use compact_str::CompactString; use lazy_static::lazy_static; @@ -85,7 +85,7 @@ fn try_abhyasa_lopa_and_dhatu_change_before_san(p: &mut Prakriya) -> Option<()> p.run_at(code, i, op::antya("is")); } } else if dhatu.has_text("rAD") { - do_abhyasa_lopa = p.run_optional_at("7.4.54.v1", i, op::upadha("is")); + do_abhyasa_lopa = p.optional_run_at("7.4.54.v1", i, op::upadha("is")); } else if dhatu.has_u_in(&["A\\px~", "jYapa~", "fDu~"]) { // Ipsati, jYIpsati, Irtsati let code = "7.4.55"; @@ -96,12 +96,12 @@ fn try_abhyasa_lopa_and_dhatu_change_before_san(p: &mut Prakriya) -> Option<()> } } else if dhatu.has_text("danB") { // Dipsati, DIpsati - if !p.run_optional_at("7.4.56.1", i, |t| t.set_at(1, "i")) { + if !p.optional_run_at("7.4.56.1", i, |t| t.set_at(1, "i")) { p.run_at("7.4.56.2", i, |t| t.set_at(1, "I")); } } else if dhatu.has_text("muc") && p.has_tag(T::Atmanepada) { // mokzate, mumukzate - do_abhyasa_lopa = p.run_optional("7.4.57", |p| { + do_abhyasa_lopa = p.optional_run("7.4.57", |p| { p.set(i, op::text("moc")); }); } else { @@ -164,7 +164,7 @@ fn run_for_sani_or_cani_at_index(p: &mut Prakriya, i: usize) -> Option<()> { } else if anga.has_u_in(SRU_ADI) && p.has(i + 2, |t| !t.has_u("san")) { // Example: sru -> sisrAvayizyati // Note that this rule must run after guna for the upadha check to be meaningful. - p.run_optional_at("7.4.81", i, op::antya("i")); + p.optional_run_at("7.4.81", i, op::antya("i")); } } @@ -172,9 +172,9 @@ fn run_for_sani_or_cani_at_index(p: &mut Prakriya, i: usize) -> Option<()> { let abhyasa = p.get(i)?; let dhatu = p.get(i + 1)?; if has_at_lopa && dhatu.has_u("gaRa") { - p.run_optional_at("7.4.97", i, op::antya("I")); + p.optional_run_at("7.4.97", i, op::antya("I")); } else if dhatu.has_text_in(&["vezw", "cezw"]) { - p.run_optional_at("7.4.96", i, op::antya("a")); + p.optional_run_at("7.4.96", i, op::antya("a")); } else if is_laghu_cani { if !dhatu.is_samyogadi() { if let Some(sub) = al::to_dirgha(abhyasa.antya()?) { @@ -215,7 +215,7 @@ fn try_general_rules(p: &mut Prakriya, i: usize) -> Option<()> { let dhatu = p.get(i_dhatu)?; if dhatu.has_u("zWivu~") { - p.run_optional(Rule::Kashika("6.1.64"), |p| { + p.optional_run(Rule::Kashika("6.1.64"), |p| { p.set(i, |t| t.find_and_replace_text("zW", "zT")) }); } @@ -319,12 +319,9 @@ fn try_rules_for_lit(p: &mut Prakriya, i: usize) -> Option<()> { if dhatu.has_antya(&*HAL) && dhatu.has_upadha(&*F_HAL) { // 'A' acepted only by some grammarians if dhatu.has_adi('A') { - let code = Rule::Kashika("7.4.71.k"); - if p.is_allowed(code) { - add_nut_agama(code, p, i_dhatu); - } else { - p.decline(code); - } + p.optionally(Rule::Kashika("7.4.71.k"), |rule, p| { + add_nut_agama(rule, p, i_dhatu); + }); } else { add_nut_agama("7.4.71", p, i_dhatu); } @@ -400,7 +397,7 @@ fn try_rules_for_yan(p: &mut Prakriya, i_abhyasa: usize) -> Option<()> { } let optional_add_agama = |rule, p: &mut Prakriya, i_dhatu, agama| -> bool { - let added = p.run_optional(rule, |p| op::insert_agama_before(p, i_dhatu, agama)); + let added = p.optional_run(rule, |p| op::insert_agama_before(p, i_dhatu, agama)); if added { it_samjna::run(p, i_dhatu).ok(); } diff --git a/vidyut-prakriya/src/angasya/asiddhavat.rs b/vidyut-prakriya/src/angasya/asiddhavat.rs index 6db97d9..aa92db2 100644 --- a/vidyut-prakriya/src/angasya/asiddhavat.rs +++ b/vidyut-prakriya/src/angasya/asiddhavat.rs @@ -12,16 +12,16 @@ see the `angasya` module. */ use crate::ac_sandhi; -use crate::args::Gana; +use crate::args::{Artha, Gana, TaddhitaArtha}; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::TermView; use crate::dhatu_gana as gana; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::Prakriya; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; -use crate::term::TermView; use lazy_static::lazy_static; lazy_static! { @@ -136,7 +136,7 @@ pub fn try_cinvat_for_bhave_and_karmani_prayoga(p: &mut Prakriya) -> Option<()> let ac_hana_graha_drza = upadesha_ac || hana_graha_drza; if sya_sic_siyut_tasi && bhavakarmanoh && ac_hana_graha_drza { - let ran = p.run_optional("6.4.62", |p| { + let ran = p.optional_run("6.4.62", |p| { p.set(i_n, |t| { t.add_tag(T::cit); t.add_tag(T::Rit); @@ -159,7 +159,7 @@ pub fn try_cinvat_for_bhave_and_karmani_prayoga(p: &mut Prakriya) -> Option<()> /// (6.4.63 - 6.4.69, excluding 6.4.64) fn run_for_kniti_ardhadhatuke_after_guna(p: &mut Prakriya, i: usize) -> Option<()> { let dhatu = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let aat = dhatu.has_antya('A'); let kniti_ardha = n.is_knit() && n.has_tag(T::Ardhadhatuka); @@ -182,7 +182,7 @@ fn run_for_kniti_ardhadhatuke_after_guna(p: &mut Prakriya, i: usize) -> Option<( } else if n.has_u("lyap") { if dhatu.has_u("me\\N") { // apamitya, apamAya - p.run_optional_at("6.4.70", i, op::antya("i")); + p.optional_run_at("6.4.70", i, op::antya("i")); } else { // pradAya p.step("6.4.69"); @@ -203,7 +203,7 @@ fn run_for_kniti_ardhadhatuke_after_guna(p: &mut Prakriya, i: usize) -> Option<( p.step("6.4.69"); } else if n.has_lakshana("li~N") { // gleyAt/glAyAt;, mleyAt/mlAyAt, ... - p.run_optional_at("6.4.68", i, op::antya("e")); + p.optional_run_at("6.4.68", i, op::antya("e")); } } } @@ -217,12 +217,12 @@ fn run_for_kniti_ardhadhatuke_after_guna(p: &mut Prakriya, i: usize) -> Option<( /// Constraints: must run after dvitva. fn run_for_kniti_ardhadhatuke_after_dvitva(p: &mut Prakriya, i: usize) -> Option<()> { let dhatu = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let aat = dhatu.has_antya('A'); let kniti_ardha = n.is_knit() && n.has_tag(T::Ardhadhatuka); - if aat && n.has_adi(&*AC) && (kniti_ardha || n.first()?.is_it_agama()) { + if aat && n.has_adi(&*AC) && (kniti_ardha || n.first().is_it_agama()) { // papiTa, tastTita, ... // By 1.1.59 (dvirvacane 'ci), this rule should be applied after dvitva. p.run_at("6.4.64", i, op::antya("")); @@ -238,13 +238,13 @@ fn run_for_kniti_ardhadhatuke_after_dvitva(p: &mut Prakriya, i: usize) -> Option fn try_run_kniti_for_dhatu(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get(i)?; let j = p.find_next_where(i, |t| !t.is_empty())?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; if !n.is_knit() { return None; } - let next_is_hi = n.first()?.has_text("hi"); + let next_is_hi = n.first().has_text("hi"); if anga.has_text_in(&["gam", "han", "jan", "Kan", "Gas"]) && n.has_adi(&*AC) && !n.has_u("aN") { p.run_at("6.4.98", i, op::upadha("")); } else if anga.has_u("Basa~") { @@ -266,19 +266,19 @@ fn try_run_kniti_for_dhatu(p: &mut Prakriya, i: usize) -> Option<()> { fn try_run_kniti(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get(i)?; let j = p.find_next_where(i, |t| !t.is_empty())?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; if !n.is_knit() { return None; } - let next_is_hi = n.first()?.has_text("hi"); - if has_antya_a_asiddhavat(anga) && n.first()?.has_text("hi") { + let next_is_hi = n.first().has_text("hi"); + if has_antya_a_asiddhavat(anga) && n.first().has_text("hi") { // Bavahi -> Bava p.run_at("6.4.105", n.start(), op::luk); } else if anga.has_antya('u') && anga.is_pratyaya() { let dhatu = p.get(i - 1)?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; let n_is_mv = n.has_adi('m') || n.has_adi('v'); if !is_samyogapurva(p, i) && next_is_hi { @@ -291,7 +291,7 @@ fn try_run_kniti(p: &mut Prakriya, i: usize) -> Option<()> { p.run_at("6.4.109", i, op::luk); } } else if n_is_mv && !is_samyogapurva(p, i) { - p.run_optional_at("6.4.107", i, op::antya("")); + p.optional_run_at("6.4.107", i, op::antya("")); } } @@ -303,7 +303,7 @@ fn try_run_kniti(p: &mut Prakriya, i: usize) -> Option<()> { fn try_run_kniti_sarvadhatuke_for_shna_and_abhyasta(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get(i)?; let i_n = p.find_next_where(i, |t| !t.is_empty())?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if !(anga.has_u("SnA") || anga.has_tag(T::Abhyasta)) { return None; @@ -313,19 +313,19 @@ fn try_run_kniti_sarvadhatuke_for_shna_and_abhyasta(p: &mut Prakriya, i: usize) if anga.has_text("daridrA") && n_is_haladi { p.run_at("6.4.114", i, op::antya("i")); } else if anga.has_u("YiBI\\") && n_is_haladi { - p.run_optional_at("6.4.115", i, op::antya("i")); + p.optional_run_at("6.4.115", i, op::antya("i")); } else if anga.has_antya('A') { let mut changed = false; if anga.has_u("o~hA\\k") && n_is_haladi { if n.has_adi('y') { p.run_at("6.4.118", i, op::antya("")); } else { - if n.last()?.has_text("hi") { - changed = p.run_optional_at("6.4.117", i, op::antya("A")); + if n.last().has_text("hi") { + changed = p.optional_run_at("6.4.117", i, op::antya("A")); } // Run 6.4.116 only if 6.4.117 was not run. if !changed { - changed = p.run_optional_at("6.4.116", i, op::antya("i")); + changed = p.optional_run_at("6.4.116", i, op::antya("i")); } } } @@ -349,7 +349,7 @@ fn try_run_kniti_sarvadhatuke_for_shna_and_abhyasta(p: &mut Prakriya, i: usize) fn try_run_kniti_sarvadhatuke(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if !n.has_tag(T::Sarvadhatuka) { return None; @@ -392,10 +392,10 @@ fn try_et_adesha_and_abhyasa_lopa_for_lit(p: &mut Prakriya, i: usize) -> Option< let dhatu = p.get_if(i, |t| t.has_all_tags(&[T::Dhatu, T::Abhyasta]))?; let abhyasa = p.get_if(i - 1, |t| t.is_abhyasa())?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let kniti = n.is_knit(); - let thali_seti = n.first()?.is_it_agama() && n.last()?.has_u("Tal"); + let thali_seti = n.first().is_it_agama() && n.last().has_u("Tal"); if !(kniti || thali_seti) { return None; } @@ -424,9 +424,9 @@ fn try_et_adesha_and_abhyasa_lopa_for_lit(p: &mut Prakriya, i: usize) -> Option< // TODO: why svAdi? For now, just follow what ashtadhyayi.com does. p.run("6.4.123", op_et_abhyasa_lopa); } else if dhatu.has_u("jFz") || dhatu.has_text_in(&["Bram", "tras"]) { - p.run_optional("6.4.124", op_et_abhyasa_lopa); + p.optional_run("6.4.124", op_et_abhyasa_lopa); } else if dhatu.has_u_in(gana::PHAN_ADI) { - p.run_optional("6.4.125", op_et_abhyasa_lopa); + p.optional_run("6.4.125", op_et_abhyasa_lopa); } else if dhatu.has_text_in(&["Sas", "dad"]) || dhatu.has_adi('v') || dhatu.has_tag(T::FlagGuna) { // No change. @@ -464,7 +464,7 @@ fn has_antya_a_asiddhavat(t: &Term) -> bool { /// (6.4.46 - 6.4.70) fn try_ardhadhatuke(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if !n.has_tag(T::Ardhadhatuka) { return None; } @@ -488,7 +488,7 @@ fn try_ardhadhatuke(p: &mut Prakriya, i: usize) -> Option<()> { }; if anga.has_text("Brasj") { - p.run_optional_at("6.4.47", i, op::text("Barj")); + p.optional_run_at("6.4.47", i, op::text("Barj")); } else if anga.text.ends_with("ya") && is_halah(p, i) { p.run("6.4.49", |p| { p.set(i, op::antya("")); @@ -515,7 +515,7 @@ fn try_upadha_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { } let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let anidit_hal = !anga.has_tag(T::idit) && anga.has_antya(&*HAL); let is_kniti = n.is_knit(); @@ -525,49 +525,49 @@ fn try_upadha_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { && (anga.has_antya('j') || anga.has_text("nanS")) && n.has_u("ktvA") { - p.run_optional_at("6.4.32", i, op::upadha("")); + p.optional_run_at("6.4.32", i, op::upadha("")); } else if anga.has_u("Ba\\njo~") && n.has_u("ciR") { - p.run_optional_at("6.4.33", i, op::upadha("")); + p.optional_run_at("6.4.33", i, op::upadha("")); } else if anidit_hal && is_kniti && anga.has_upadha('n') { - let mut can_run = true; + let mut blocked = false; // ancu gati-pUjanayoH if anga.has_u("ancu~") { - let code = "6.4.30"; - if p.is_allowed(code) { - p.step(code); - } else { - p.decline(code); - can_run = false; - } + blocked = p.optional_run("6.4.30", |_| {}); } - if can_run { + if !blocked { p.run_at("6.4.24", i, op::upadha("")); } } else if anga.has_text("ranj") { - if n.first()?.is_ni_pratyaya() { + if n.first().is_ni_pratyaya() { // "rañjerṇau mṛgaramaṇa upasaṅkhyānaṃ kartavyam" - p.run_optional_at("6.4.24.v2", i, op::upadha("")); - } else if n.first()?.has_u("Ginu~R") { + p.optional_run_at("6.4.24.v2", i, op::upadha("")); + } else if n.first().has_u("Ginu~R") { // "ghinuṇi ca rañjerupasaṅkhyānaṃ kartavyam" p.run_at("6.4.24.v3", i, op::upadha("")); } else if n.has_u("Sap") { p.run_at("6.4.26", i, op::upadha("")); } else if n.has_u("GaY") { - p.run_optional_at("6.4.27", i, op::upadha("")); + p.optional_run_at("6.4.27", i, op::upadha("")); } } else if anga.has_text_in(&["danS", "sanj", "svanj"]) && n.has_u("Sap") { // daSati p.run_at("6.4.25", i, op::upadha("")); } else if anga.has_text("syand") && n.has_u("GaY") { - p.run_optional("6.4.28", op::nipatana("syada")); + p.optional_run("6.4.28", op::nipatana("syada")); } else if anga.has_u("SAsu~") { - if n.last()?.has_text("hi") { + if n.last().has_text("hi") { // SAs + hi -> SAhi (-> SADi) p.run_at("6.4.35", i, op::text("SA")); } else if is_kniti && (n.has_u("aN") || n.has_adi(&*HAL)) { // "āṅaḥ śāsu icchāyām iti asya na bhavati" -- kashika p.run_at("6.4.34", i, op::upadha("i")); + } else if n.has_u("kvi~p") { + // "kvau ca śāsa ittvaṃ bhavatīti vaktavyam" + p.run_at("6.4.34.v1", i, op::upadha("i")); } + } else if anga.has_u("SAsu~\\") && n.has_u("kvi~p") { + // "kvippratyaye tu tasya api bhavatīti vaktavyam. āśīḥ, āśiṣau, āśiṣaḥ" + p.run_at("6.4.34.v2", i, op::upadha("i")); } Some(()) @@ -581,7 +581,7 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let anga = p.get_if(i, |t| t.has_antya(&*ANUNASIKA))?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; // Used to check if na-lopa was applied. let old_antya = anga.antya()?; @@ -592,7 +592,7 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { let kniti = is_knit(&n); let jhali_kniti = n.has_adi(&*JHAL) && kniti; - if anga.has_u("ha\\na~") && n.last()?.has_text("hi") { + if anga.has_u("ha\\na~") && n.last().has_text("hi") { // jahi p.run_at("6.4.36", i, op::text("ja")); } else if anga.has_text("gam") && n.has_u("kvip") { @@ -604,7 +604,7 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { // "janeḥ śyani 'jñājanorjā' (7.3.79) iti nityaṃ jādeśo bhavati." // - kashikavrtti if !(anga.has_text("jan") && n.has_u("Syan")) { - p.run_optional_at("6.4.43", i, |t| { + p.optional_run_at("6.4.43", i, |t| { t.set_antya("A"); }); } @@ -613,11 +613,11 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { } } else if anga.has_text("tan") && n.has_u("yak") { // tanyate, tAyate - p.run_optional_at("6.4.44", i, op::antya("A")); + p.optional_run_at("6.4.44", i, op::antya("A")); } else if anga.has_text("san") && n.has_u("ktic") { - let used = p.run_optional_at("6.4.45.b", i, op::antya("")); + let used = p.optional_run_at("6.4.45.b", i, op::antya("")); if !used { - p.run_optional_at("6.4.45.a", i, op::antya("A")); + p.optional_run_at("6.4.45.a", i, op::antya("A")); } } else if is_anudatta || is_tanadi || anga.has_text("van") { if jhali_kniti { @@ -633,7 +633,7 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { // TODO: why? let code = "6.4.38"; if anga.has_antya('m') { - p.run_optional_at(code, i, op::antya("")); + p.optional_run_at(code, i, op::antya("")); } else { p.run_at(code, i, op::antya("")); } @@ -706,7 +706,7 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { // Must run before guNa. let anga = p.get(i)?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; if anga.has_text("BU") && n.has_lakshana_in(&["lu~N", "li~w"]) { op::append_agama("6.4.88", p, i, "vu~k"); } else if anga.has_u("guhU~^") && n.has_adi(&*AC) && !n.is_knit() { @@ -715,19 +715,19 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { t.set_upadha("U"); t.add_tag(T::FlagGunaApavada); }); - } else if anga.has_u("du\\za~") && n.first()?.is_ni_pratyaya() { - if !p.run_optional("6.4.91", |_| {}) { + } else if anga.has_u("du\\za~") && n.first().is_ni_pratyaya() { + if !p.optional_run("6.4.91", |_| {}) { p.run_at("6.4.90", i, |t| { t.set_upadha("U"); t.add_tag(T::FlagGunaApavada); }); } - } else if anga.has_u("ciR") && n.last()?.has_text("ta") { + } else if anga.has_u("ciR") && n.last().has_text("ta") { p.run_at("6.4.104", n.end(), op::luk); } else if anga.has_u("daridrA") && n.has_tag(T::Ardhadhatuka) { if p.terms().last()?.has_lakshana("lu~N") { // Varttika. - if p.run_optional("6.4.114.v2", |_| {}) { + if p.optional_run("6.4.114.v2", |_| {}) { return None; } } @@ -739,7 +739,7 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { } let dhatu = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let aat = dhatu.has_antya('A'); if aat && n.has_u("yat") { p.run_at("6.4.65", i, op::antya("I")); @@ -754,7 +754,7 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { fn run_for_final_i_or_u(p: &mut Prakriya, i: usize) -> Option<()> { let anga = p.get_if(i, |t| !t.is_agama())?; let j = p.find_next_where(i, |t| !t.is_empty())?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; if !anga.has_antya(&*I_U) || !n.has_adi(&*AC) || anga.is_upasarga() { return None; @@ -770,10 +770,10 @@ fn run_for_final_i_or_u(p: &mut Prakriya, i: usize) -> Option<()> { let is_asamyogapurva = !is_samyogapurva(p, i); let anga = p.get(i)?; - let n = p.view(j)?; - if anga.has_text("strI") && n.last()?.is_pratyaya() { - if n.last()?.has_u_in(&["am", "Sas"]) { - p.run_optional_at("6.4.80", i, op::antya("iy")); + let n = p.pratyaya(j)?; + if anga.has_text("strI") && n.last().is_pratyaya() { + if n.last().has_u_in(&["am", "Sas"]) { + p.optional_run_at("6.4.80", i, op::antya("iy")); } else { p.run_at("6.4.79", i, op::antya("iy")); } @@ -787,7 +787,7 @@ fn run_for_final_i_or_u(p: &mut Prakriya, i: usize) -> Option<()> { // // [1]: https://archive.org/details/237131938MadhaviyaDhatuVrtti/page/n412/mode/1up if anga.has_u("i\\k") { - let used = p.run_optional_at("6.4.81", i, op::antya("y")); + let used = p.optional_run_at("6.4.81", i, op::antya("y")); if !used { // Copied from below for better control flow. p.run("6.4.77", |p| to_iy_uv(p, i)); @@ -842,13 +842,13 @@ pub fn run_for_ni(p: &mut Prakriya) -> Option<()> { } let i_dhatu = i_ni - 1; - let n = p.view(i_ni + 1)?; - let iti = n.first()?.is_it_agama(); + let n = p.pratyaya(i_ni + 1)?; + let iti = n.first().is_it_agama(); if n.has_tag(T::Ardhadhatuka) { let dhatu = p.get(i_dhatu)?; - if n.first()? + if n.first() .has_text_in(&["Am", "anta", "Alu", "Ayya", "itnu", "iznu"]) { // corayAm, spfhayAlu, etc. @@ -869,7 +869,7 @@ pub fn run_for_ni(p: &mut Prakriya) -> Option<()> { } let dhatu = p.get(i_dhatu)?; - let n = p.view(i_ni + 1)?; + let n = p.pratyaya(i_ni + 1)?; let ni = p.get(i_ni)?; if ni.has_u("Ric") { if n.has_u("Kac") { @@ -889,7 +889,7 @@ pub fn run_for_ni(p: &mut Prakriya) -> Option<()> { } else if dhatu.has_tag(T::mit) && dhatu.has_upadha(&*AC) { let mut run = true; if n.has_u_in(&["ciR", "Ramu~l"]) { - run = p.run_optional("6.4.93", |_| {}); + run = p.optional_run("6.4.93", |_| {}); } if run { p.run_at("6.4.92", i_dhatu, op::upadha_hrasva); @@ -904,7 +904,7 @@ fn try_kr_rule(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let anga = p.get(i)?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let last = p.terms().last()?; let sarva_kniti = last.is_sarvadhatuka() && last.is_knit(); @@ -915,10 +915,11 @@ fn try_kr_rule(p: &mut Prakriya, i: usize) -> Option<()> { Some(()) } -/// Runs rules in the "bhasya" section. +/// Tries "bhasya" rules for the pratpadika ending at `i`. /// -/// (6.4.129 - 6.4.175) -pub fn bhasya(p: &mut Prakriya) -> Option<()> { +/// A prakriya could have multiple "bha" terms if, for example, we have a pratipadika followed by a +/// taddhita-pratyaya followed by a strI-pratyaya. +pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { const PRIYA_ADI: &[&str] = &[ "priya", "sTira", @@ -934,9 +935,9 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { const PRA_ADI: &[&str] = &[ "pra", "sTa", "sPa", "var", "baMh", "gar", "varz", "trap", "drAG", "vfnd", ]; - let i = p.find_last(T::Bha)?; - let bha = p.get(i)?; + let bha = p.get_if(i, |t| t.has_tag(T::Bha))?; + let bha_prati = p.nyap_pratipadika(i)?; let next = p.get(i + 1)?; let taddhita = next.is_taddhita(); @@ -967,9 +968,12 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { // BUyizWa op::insert_agama_at("6.4.159", p, i + 1, "yi~w"); } - } else if bha.has_text("jya") { + } else if bha.has_text("jya") && next.has_u("Iyasu~n") { // jyAyas p.run_at("6.4.160", i + 1, |t| t.set_adi("A")); + } else if bha.num_vowels() == 1 { + // srajizWa, srajIyas, ... + p.step("6.4.163"); } else { // pawu -> pawizWa, pawiman, ... p.run_at("6.4.155", i, op::ti("")); @@ -984,8 +988,11 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { p.run_at("6.4.130", i, op::text("pad")); } else if bha.has_u("kvasu~") { p.run_at("6.4.131", i, op::text("us")); - } else if bha.has_text("vAh") { - op::adesha("6.4.132", p, i, "Uh"); + } else if i > 0 && p.has(i - 1, |t| t.has_text("vAh")) { + p.run_at("6.4.132", i - 1, |t| { + t.set_text("Uh"); + t.add_tag(T::FlagUth); + }); } else if bha.has_text_in(&["Svan", "yuvan", "maGavan"]) && !next.has_tag(T::Taddhita) { p.run_at("6.4.133", i, |t| t.find_and_replace_text("va", "u")); } else if bha.has_antya('n') { @@ -1019,6 +1026,9 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { } } else if ani && bha.ends_with("an") { p.step("6.4.167"); + } else if next.has_adi('y') && p.has_artha(Artha::Taddhita(TaddhitaArtha::TatraSadhu)) { + // TODO: expand conditions here. + p.step("6.4.168"); } else if bha.has_text_in(&["Atman", "aDvan"]) && next.has_u("Ka") { p.step("6.4.169"); } else if bha.has_text("ahan") { @@ -1039,14 +1049,14 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { p.step("6.4.137"); blocked = true; } else if next.has_u_in(&["Ni", "SI"]) { - blocked = p.run_optional("6.4.135", |_| {}); + blocked = p.optional_run("6.4.135", |_| {}); } if !blocked { p.run_at("6.4.134", i, op::upadha("")); } } - } else if bha.has_antya('A') && bha.is_dhatu() { - p.run_at("6.4.140", i, op::antya("")); + } else if bha_prati.has_antya('A') && bha_prati.last_non_empty()?.is_dhatu() { + p.run_at("6.4.140", bha_prati.end_non_empty()?, op::antya("")); } else if (bha.has_u("daRqin") && next.has_u("Pak")) || (bha.has_u("hastin") && next.has_u("Pak")) || (bha.has_u("aTarvan") && next.has_u("Wak")) @@ -1090,7 +1100,9 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { } else { p.run_at("6.4.146", i, |t| t.set_antya("o")); } - } else if (bha.has_antya(&*AA) || bha.has_antya(&*II)) && (taddhita || next.has_adi('I')) { + } else if (bha_prati.has_antya(&*AA) || bha_prati.has_antya(&*II)) + && (taddhita || next.has_adi('I')) + { if next.has_u("SI") { // Pale, ... p.step("6.4.148.v1"); @@ -1100,13 +1112,22 @@ pub fn bhasya(p: &mut Prakriya) -> Option<()> { t.set_antya(""); }); } else { - p.run_at("6.4.148", i, |t| t.set_antya("")); + p.run_at("6.4.148", bha_prati.end_non_empty()?, |t| t.set_antya("")); } } Some(()) } +/// Runs rules in the "bhasya" section. +/// +/// (6.4.129 - 6.4.175) +pub fn bhasya(p: &mut Prakriya) { + for i in 0..p.terms().len() { + try_bhasya_for_index(p, i); + } +} + pub fn run_after_guna(p: &mut Prakriya, i: usize) -> Option<()> { run_for_kniti_ardhadhatuke_after_guna(p, i); Some(()) @@ -1129,7 +1150,7 @@ pub fn run_final(p: &mut Prakriya, i: usize) -> Option<()> { try_et_adesha_and_abhyasa_lopa_for_lit(p, i); - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if n.has_tag(T::qit) { p.run_at("6.4.143", i, op::ti("")); } diff --git a/vidyut-prakriya/src/angasya/guna_vrddhi.rs b/vidyut-prakriya/src/angasya/guna_vrddhi.rs index 02bfb12..62f06fb 100644 --- a/vidyut-prakriya/src/angasya/guna_vrddhi.rs +++ b/vidyut-prakriya/src/angasya/guna_vrddhi.rs @@ -1,10 +1,10 @@ use crate::args::Gana; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::{Code, Prakriya}; +use crate::core::{Term, TermView}; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::{Term, TermView}; use lazy_static::lazy_static; lazy_static! { @@ -82,7 +82,7 @@ impl<'a> GunaVrddhiPrakriya<'a> { /// Returns the term that might condition guna/vrddhi. fn next(&self) -> TermView { - self.p.view(self.i_next).expect("ok") + self.p.pratyaya(self.i_next).expect("ok") } /// Checks a standard list of rules that block guna/vrddhi @@ -128,7 +128,7 @@ impl<'a> GunaVrddhiPrakriya<'a> { /// Tries `func` optionally and blocks further guna/vrddhi changes if it succeeds. fn run_optional(&mut self, rule: Code, func: impl Fn(&mut Term)) { if !self.done { - let ran = self.p.run_optional_at(rule, self.i_anga, func); + let ran = self.p.optional_run_at(rule, self.i_anga, func); self.done = ran; } } @@ -142,7 +142,8 @@ fn try_taddhita_vrddhi(p: &mut Prakriya, i: usize) -> Option<()> { ]; let anga = p.get(i)?; - let n = p.get_if(i + 1, |t| t.is_taddhita())?; + let i_n = p.find_next_where(i, |t| !t.is_empty())?; + let n = p.get_if(i_n, |t| t.is_taddhita())?; let rule = if n.has_tag_in(&[T::Yit, T::Rit]) { "7.2.117" @@ -207,7 +208,7 @@ fn try_nnit_vrddhi(p: &mut Prakriya, i: usize) -> Option<()> { } let anga = p.get(i)?; - let n = p.view(i_next)?; + let n = p.pratyaya(i_next)?; let is_cin = n.has_u("ciR") || n.has_tag(T::Cinvat); let is_cin_krt = is_cin || n.has_tag(T::Krt); let has_udatta = !anga.has_tag(T::Anudatta); @@ -222,7 +223,7 @@ fn try_nnit_vrddhi(p: &mut Prakriya, i: usize) -> Option<()> { if is_cin_krt && has_udatta && anga.has_antya('m') && !is_aacam_adi { p.step("7.3.34"); - } else if is_cin_krt && anga.has_text_in(&["jan", "vaD"]) { + } else if is_cin_krt && anga.has_text_in(&["jan", "vaD"]) && !n.has_u("YuR") { // ajani, avaDi, ... p.step("7.3.35"); } else if is_cin_krt && anga.has_antya('A') { @@ -260,13 +261,13 @@ fn try_nnit_vrddhi(p: &mut Prakriya, i: usize) -> Option<()> { fn try_vrddhi_adesha(p: &mut Prakriya, i: usize) -> Option<()> { let dhatu = p.get_if(i, |t| !t.has_tag(T::FlagGunaApavada))?; let i_n = p.find_next_where(i, |t| !t.is_empty())?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if dhatu.has_text("mfj") && !n.is_knit() { let mut gp = GunaVrddhiPrakriya::new(p, i, i_n); gp.check_guna_vrddhi_blocks(); gp.try_run("7.2.114", |t| t.try_upadha_vrddhi()); - } else if n.first()?.is_taddhita() { + } else if n.first().is_taddhita() { try_taddhita_vrddhi(p, i); } else { try_nnit_vrddhi(p, i); @@ -281,7 +282,7 @@ fn try_guna_adesha(p: &mut Prakriya, i: usize) -> Option<()> { let j = p.find_next_where(i, |t| !t.is_empty() && !t.has_u("pu~k"))?; let anga = p.get_if(i, |t| !t.is_agama() && !t.has_tag(T::FlagGunaApavada))?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; let is_sarva_ardha = n.has_tag_in(&[T::Sarvadhatuka, T::Ardhadhatuka]); let piti_sarvadhatuke = n.all(&[T::pit, T::Sarvadhatuka]); @@ -315,7 +316,7 @@ fn try_guna_adesha(p: &mut Prakriya, i: usize) -> Option<()> { let n = gp.next(); let sub = al::to_vrddhi(anga.antya()?)?; if anga.has_u("UrRuY") { - if n.last()?.is_aprkta() { + if n.last().is_aprkta() { // prOrRot gp.try_run("7.3.91", |t| t.try_antya_guna()); } else { @@ -414,7 +415,7 @@ fn try_r_guna_before_lit(p: &mut Prakriya, i: usize) -> Option<()> { } else { let mut skipped = false; if anga.has_text_in(&["SF", "dF", "pF"]) && !anga.has_gana(Gana::Curadi) { - skipped = p.run_optional_at("7.4.12", i, |t| { + skipped = p.optional_run_at("7.4.12", i, |t| { t.set_antya("f"); t.add_tag(T::FlagGunaApavada); }); @@ -434,7 +435,10 @@ fn run_for_index(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; let n = p.get(i_n)?; - if anga.has_u("jAgf") && !n.has_u_in(&["kvin", "ciR", "Ral"]) && !p.view(i_n)?.has_tag(T::Nit) { + if anga.has_u("jAgf") + && !n.has_u_in(&["kvin", "ciR", "Ral"]) + && !p.pratyaya(i_n)?.has_tag(T::Nit) + { // jAgf-guna takes priority over vrddhi. Skip if already applied (e.g. for jAgf + Ric). if anga.has_antya('f') { p.run_at("7.3.85", i, |t| { diff --git a/vidyut-prakriya/src/angasya/subanta.rs b/vidyut-prakriya/src/angasya/subanta.rs new file mode 100644 index 0000000..bcabff1 --- /dev/null +++ b/vidyut-prakriya/src/angasya/subanta.rs @@ -0,0 +1,748 @@ +/*! +subanta +======= + +Various rules that create subantas. These rules come primarily from adhyaya 7. + +If a subanta rule is deeply intertwined with other kinds of rules, we keep it out of this module in +favor of more generic modules like `angasya.rs`. +*/ +use crate::angasya::asiddhavat; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; +use crate::it_samjna; +use crate::samjna; +use crate::sounds as al; +use crate::sounds::{s, Set}; +use crate::stem_gana as gana; +use lazy_static::lazy_static; + +lazy_static! { + static ref AC: Set = s("ac"); + static ref HAL: Set = s("hal"); + static ref IK: Set = s("ik"); + static ref JHAL: Set = s("Jal"); +} + +// Inserts a num-Agama in the given term. We mark the tag with `FlagNum` so that we can check for +// num-Agama specifically in later rules. +fn add_num(t: &mut Term) { + op::mit("n")(t); + t.add_tag(T::FlagNum); +} + +fn yatha(needle: &str, old: &'static [&str], new: &'static [&str]) -> Option<&'static str> { + for (i, o) in old.iter().enumerate() { + if needle == *o { + return Some(new[i]); + } + } + None +} + +/// Runs various rules that cause dirgha-adesha in the anga. +/// This specific dirgha-adesha must occur before inserting num-agama. +/// +/// Example: gomat -> gomAt -> gomAnt -> gomAn +fn try_dirgha_adesha_before_num_agama(p: &mut Prakriya) -> Option<()> { + let i_sup = p.find_last(T::Sup)?; + let i_anga = p.find_prev_where(i_sup, |t| !t.is_agama())?; + + let anga = p.get(i_anga)?; + let sup = p.get(i_sup)?; + let sau = sup.has_u("su~"); + let is_atu = anga.has_tag(T::udit) && anga.ends_with("at"); + + if sup.is_sarvanamasthana() && !sup.has_tag(T::Sambuddhi) { + if (is_atu || anga.ends_with("as")) && sau && !anga.is_dhatu() { + let sub = al::to_dirgha(anga.upadha()?)?; + p.run_at("6.4.14", i_anga, op::upadha(&sub.to_string())); + } + } + + Some(()) +} + +/// Tries rules that replace the sup-pratyaya. +/// +/// (7.1.9 - 7.1.22) +/// +/// Rules for sup-lopa are in `try_napumsaka_su_am_adesha`. These must be run earlier -- see the +/// commentson that function for details. +fn try_sup_adesha(p: &mut Prakriya, i_anga: usize, i_sup: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i_sup)?; + + let is_napumsaka = p.has_tag(T::Napumsaka); + let is_jas_shas = sup.has_u_in(&["jas", "Sas"]); + + if anga.has_tag(T::zaw) && is_jas_shas { + // zaw, paYca, ... + p.run_at("7.1.22", i_sup, op::luk); + } else if anga.is_aap_pratyaya() && sup.has_text("O") { + // Kawve, ... + op::adesha("7.1.18", p, i_sup, "SI"); + } else if is_napumsaka && sup.has_text("O") { + // kuRqe, daDinI, maDunI, ... + op::adesha("7.1.19", p, i_sup, "SI"); + } else if is_napumsaka && is_jas_shas { + // kuRqAni, daDIni, maDUni, ... + op::adesha("7.1.20", p, i_sup, "Si"); + p.add_tag_at("1.1.42", i_sup, T::Sarvanamasthana); + } else if anga.has_text("azwA") && anga.has_u("azwan") && is_jas_shas { + // azwO + op::adesha("7.1.21", p, i_sup, "OS"); + } else if anga.has_text("adaa") && sup.has_u("wA") { + // TODO: ada instead of adaa? + // By 8.2.3, rule 8.2.80 is siddha with respect to wA --> nA. + p.run_at("8.2.80", i_anga, |t| { + t.set_text("amu"); + t.add_tag(T::Ghi); + }); + } else if anga.has_antya('a') { + let nasi_ni = &["Nasi~", "Ni"]; + let smat_smin = &["smAt", "smin"]; + let ta_nasi_nas = &["wA", "Nasi~", "Nas"]; + let ina_at_sya = &["ina", "At", "sya"]; + + let is_sarvanama = anga.is_sarvanama(); + let sup_u = match &sup.u { + Some(u) => u.to_string(), + None => "".to_string(), + }; + + if sup.has_text("Bis") { + // By this point in the code, "idam" and "adas" should both end with "a." + if anga.has_u_in(&["idam", "adas"]) { + // eBiH, amIBiH, ... + // TODO: a-koH + p.step("7.1.11"); + } else { + // narEH + p.run_at("7.1.9", i_sup, op::text("Es")); + } + } else if is_sarvanama && sup.has_u_in(nasi_ni) { + if let Some(sub) = yatha(&sup_u, nasi_ni, smat_smin) { + let mut blocked = false; + if anga.has_text_in(gana::PURVA_ADI) { + // pUrvasmAt, pUrvAt, pUrvasmin, pUrve, ... + blocked = p.optional_run("7.1.16", |_| {}); + } + + if !blocked { + // tasmAt, tasmin + p.run_at("7.1.15", i_sup, op::text(sub)); + } + } + } + + let sup = p.get(i_sup)?; + if sup.has_u_in(ta_nasi_nas) && sup.has_text_in(&["A", "as"]) { + if let Some(sub) = yatha(&sup_u, ta_nasi_nas, ina_at_sya) { + // devena, devAt, devasya + p.run_at("7.1.12", i_sup, op::text(sub)); + } + } else if sup.has_u("Ne") { + if is_sarvanama { + // tasmE + p.run_at("7.1.14", i_sup, op::text("smE")); + } else { + // devAya + p.run_at("7.1.13", i_sup, op::text("ya")); + } + } else if is_sarvanama && sup.has_u("jas") { + // te, sarve + op::adesha("7.1.17", p, i_sup, "SI"); + } + } else if anga.has_text_in(&["yuzmad", "asmad"]) { + // TODO: old function had a comment that this must follow 7.1.52 for "sAm". Is that still true? + + let i_sup = i_anga + 1; + let sup = p.pratyaya(i_sup)?; + + if sup.has_u("Nas") { + // mama, tava + op::adesha("7.1.27", p, i_sup, "aS"); + } else if sup.has_u("Ne") || sup.has_tag_in(&[T::V1, T::V2]) { + if sup.has_u("Sas") { + // asmAn, yuzmAn + op::adesha("7.1.29", p, i_sup, "n"); + } else { + // mahyam; aham, AvAm, vayam, mAm + // tuByam; tvam, yuvAm, yUyam, tvAm + op::adesha("7.1.28", p, i_sup, "am"); + } + } else if sup.has_u("Byas") { + if sup.has_tag(T::V5) { + // asmat, yuzmat + op::adesha("7.1.31", p, i_sup, "at"); + } else { + // asmaByam, yuzmaByam + op::adesha("7.1.30", p, i_sup, "Byam"); + } + } else if sup.all(&[T::V5, T::Ekavacana]) { + // mat, tvat + op::adesha("7.1.32", p, i_sup, "at"); + } else if sup.first().has_text("s") && sup.last().has_text("Am") { + // All three of these lines art part of 7.1.33. + let start = sup.start(); + p.terms_mut().remove(start); + op::adesha("7.1.33", p, i_sup, "Akam"); + } + } + + Some(()) +} + +/// Tries adesha rules for napumsaka stems ending in 'a'. +fn try_napumsaka_su_am_adesha(p: &mut Prakriya, i_anga: usize) -> Option<()> { + let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; + let sup = p.get(i_sup)?; + + let is_napumsaka = p.has_tag(T::Napumsaka); + if is_napumsaka && sup.has_u_in(&["su~", "am"]) { + let anga = p.get(i_anga)?; + if anga.has_antya('a') { + let mut done = false; + if anga.has_text_in(gana::USES_DATARA_DATAMA) + || anga.has_text_in(&["anya", "anyatara", "itara"]) + { + if anga.has_text("ekatara") { + // ekataram + p.step("7.1.26.v1"); + } else { + // anyat + op::adesha("7.1.25", p, i_sup, "adq"); + done = true; + } + } + if !done { + op::adesha("7.1.24", p, i_sup, "am"); + } + } else { + p.run_at("7.1.23", i_sup, op::luk); + } + } + + Some(()) +} + +/// Adds Agamas for words like trayA-R-Am, sarve-z-Am, etc. +fn try_add_sup_agamas(p: &mut Prakriya, i_anga: usize) -> Option<()> { + let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; + + let anga = p.nyap_pratipadika(i_anga)?; + let sup = p.get(i_sup)?; + + // Check for `Bahuvacana` explicitly to exclude the `Am`-adesha for mAlAyAm, etc. + if sup.has_text("Am") && sup.has_tag(T::Bahuvacana) { + if anga.first().is_sarvanama() { + // sarvezAm, ... + op::insert_agama_at("7.1.52", p, i_sup, "su~w"); + } else if anga.is_hrasva() || anga.has_tag(T::Nadi) || anga.last().is_aap_pratyaya() { + // vfkzARAm, ... + op::insert_agama_at("7.1.54", p, i_sup, "nu~w"); + } else if anga.has_tag(T::zaw) || anga.has_u_in(&["tri", "catur"]) { + // zaRRAm, ... + op::insert_agama_at("7.1.55", p, i_sup, "nu~w"); + } + } + + Some(()) +} + +fn try_add_num_agama_to_anga(p: &mut Prakriya, i_anga: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i_anga + 1)?; + let napum = p.has_tag(T::Napumsaka); + + if anga.has_tag_in(&[T::udit, T::fdit]) && !anga.is_dhatu() { + let shatr = anga.has_u("Satf~"); + // No `?` for i_prev here to avoid exiting early for e.g. "pums". + let i_prev = p.find_prev_where(i_anga, |t| !t.is_empty()); + + if shatr && (p.has(i_anga + 1, |t| t.has_u("SI") || t.has_tag(T::Nadi))) && i_anga > 0 { + let aat = p.has(i_prev?, |t| t.has_antya('a') || t.has_antya('A')); + if aat + || p.has(i_anga - 1, |t| { + t.has_u_in(&["Sap", "Syan", "Sa"]) && !t.is_lupta() + }) + { + if p.has(i_anga - 1, |t| { + t.has_u_in(&["Sap", "Syan"]) && !t.is_lupta() + }) { + // pacantI, pacanti, ... + p.run_at("7.1.81", i_anga, add_num); + } else { + // tudatI, tudantI, ... + p.optional_run_at("7.1.80", i_anga, add_num); + } + } + } else if sup.is_sarvanamasthana() { + if shatr && p.has(i_prev?, |t| t.is_abhyasta()) { + if napum { + // dadati, dadanti, ... + p.optional_run_at("7.1.79", i_anga, add_num); + } else { + // dadat, dadatO, dadataH, ... + p.step("7.1.78"); + } + } else { + p.run_at("7.1.70", i_anga, add_num); + } + } + } else if sup.is_sarvanamasthana() { + if i_anga > 0 + && anga.has_text("") + && p.has(i_anga - 1, |t| t.has_text("yuj")) + && !anga.is_samasa() + { + // yuN, yuYjO, yuYjaH + p.run_at("7.1.71", i_anga - 1, add_num); + } else if napum + && sup.is_sarvanamasthana() + && (anga.has_antya(&*JHAL) || anga.has_antya(&*AC)) + { + // udaSvinti, Sakfnti, yaSAMsi, ... + p.run_at("7.1.72", i_anga, add_num); + } + } else if napum && anga.has_antya(&*IK) && sup.has_adi(&*AC) && sup.is_vibhakti() { + p.run_at("7.1.73", i_anga, add_num); + } + + Some(()) +} + +fn try_misc_rules(p: &mut Prakriya, i_anga: usize, i_sup: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i_sup)?; + let sau = sup.has_u("su~"); + let sarvanamasthane = sup.has_tag(T::Sarvanamasthana); + + if sau && anga.has_u("anaquh") { + p.run_at("7.1.82", i_anga, |t| t.set_antya("nh")); + } else if sau && anga.has_text("div") { + // dyOH + p.run_at("7.1.84", i_anga, op::antya("O")); + } else if anga.has_text_in(&["paTin", "maTin", "fBukzin"]) { + if sau { + // panTAH, ... + p.run_at("7.1.85", i_anga, op::antya("A")); + } + + if sarvanamasthane { + // panTAnam, ... + p.run_at("7.1.86", i_anga, |t| t.find_and_replace_text("i", "a")); + if p.has(i_anga, |t| t.text.contains('T')) { + // panTAnam, ... + p.run_at("7.1.87", i_anga, |t| t.find_and_replace_text("T", "nT")); + } + } + + if p.has(i_anga, |t| t.has_tag(T::Bha)) { + // paTA, ... + p.run_at("7.1.88", i_anga, op::ti("")); + } + } else if anga.has_text("pums") && sarvanamasthane { + p.run_at("7.1.89", i_anga, |t| { + t.set_text("pumas"); + t.add_tag(T::udit); + }); + } + Some(()) +} + +fn try_sarvanamasthane_asambuddhau(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i)?; + + let sambuddhau = sup.has_tag(T::Sambuddhi); + let sarve = sup.is_sarvanamasthana(); + let sarve_asam = sarve && !sambuddhau; + let sau = sup.has_u("su~"); + + if sarve_asam && anga.has_text("saKi") { + if sau { + // saKA + p.run_at("7.1.93", i_anga, op::antya("an")); + } else { + // saKAyO, ... + p.add_tag_at("7.1.92", i_anga, T::Rit); + // HACK: do vrddhi here. + p.run_at("7.2.115", i_anga, |t| t.set_antya("E")); + } + } else if anga.has_text("krozwu") { + let mark_trjvat = |t: &mut Term| { + t.set_antya("f"); + t.add_tag(T::FlagTrjvat); + t.remove_tag(T::Ghi); + }; + if sarve_asam { + // krozwA, krozwArO, krozwAraH, ... + p.run_at("7.1.95", i_anga, mark_trjvat); + } else if sup.has_adi(&*AC) && sup.has_tag_in(&[T::V3, T::V4, T::V5, T::V6, T::V7]) { + p.optional_run_at("7.1.97", i_anga, mark_trjvat); + } + } + + let anga = p.get(i_anga)?; + if sarve_asam + && sau + && (anga.has_antya('f') || anga.has_text_in(&["uSanas", "purudaMsas", "anehas"])) + { + p.run_at("7.1.94", i_anga, op::antya("an")); + } else if sarve && (anga.has_text("catur") || anga.has_u("anaquh")) { + // TODO: am/Am? + if sambuddhau { + p.run_at("7.1.99", i_anga, op::mit("a")); + } else { + p.run_at("7.1.98", i_anga, op::mit("A")); + } + } + + Some(()) +} + +/// Applies various rules that change the anga of a pratipadika. +/// +/// These changes occur *before* we change the vibhakti by making substitutions. For changes +/// *after* we change the vibhakti, see `try_anga_adesha_after_vibhakti_changes`. +fn try_anga_adesha_before_vibhakti_changes(p: &mut Prakriya, i_anga: usize) -> Option<()> { + // The term *vibhakti* also applies to taddhita-pratyayas (5.3.1), which are in scope for the + // rules here. This is why we can't simply check `is_sup` instead. + let i_v = p.find_next_where(i_anga, |t| t.is_vibhakti())?; + + let anga = p.get(i_anga)?; + let v = p.get(i_v)?; + + // TODO: how to derive `enat`? + // if anga.has_text("etad") && (v.has_tag(T::V2) || v.has_u_in(&["wA", "os"])) { + // p.optional_run_at("2.4.34", i, |t| t.set_text("ena")); + // } + + if anga.has_text("azwan") && v.is_vibhakti() { + // Optional per Kashika. + p.optional_run_at("7.2.84", i_anga, |t| { + t.set_antya(""); + t.set_antya("A"); + }); + } else if anga.has_text_in(&["tri", "catur"]) && p.has_tag(T::Stri) { + p.run_at("7.2.99", i_anga, |t| { + t.find_and_replace_text("tri", "tisf"); + t.find_and_replace_text("catur", "catasf"); + }); + } else if anga.has_text("tri") && v.has_text("Am") && v.has_tag(T::Bahuvacana) { + // trayARAm + p.run_at("7.1.53", i_anga, op::text("traya")); + } + + let anga = p.nyap_pratipadika(i_anga)?; + let v = p.get(i_v)?; + if anga.first().has_text_in(&["tisf", "catasf"]) + && p.has_tag(T::Stri) + && p.has(i_anga + 1, |t| t.has_adi(&*AC)) + { + // trayARAm, tisfRAm, caturRAm, catasfRAm + // + // Rule 6.4.4 (na tisfcatasf) blocks dirgha on f. + p.run_at("7.2.100", i_anga, op::antya("r")); + } else if anga.first().has_text("jarA") && v.has_adi(&*AC) { + let i_start = anga.start(); + p.optionally("7.2.101", |rule, p| { + p.set(i_start, op::text("jaras")); + p.terms_mut().remove(i_start + 1); + p.step(rule); + }); + } else if anga.has_u_in(gana::TYAD_ADI) { + let sau = v.has_u("su~") && !v.is_lupta(); + + if sau && anga.has_u("adas") { + // asO + p.run("7.2.107", |p| { + p.set(i_anga, |t| t.set_antya("O")); + p.set(i_v, op::lopa); + }); + } else if sau && !v.is_empty() && anga.has_u("idam") { + // check for `!v.is_empty()` to allow `idam`. + p.step("7.2.108"); + if p.has_tag(T::Pum) { + p.run_at("7.2.111", i_anga, |t| t.set_text("ayam")); + } else { + p.run_at("7.2.110", i_anga, |t| t.set_text("iyam")); + } + } else if !v.is_empty() { + // tyaH, tyO, tye, ... + p.run_at("7.2.102", i_anga, op::antya("a")); + } + + // 7.2.109 - 7.2.112 are in `angasya::try_anga_adesha_after_vibhakti_changes`. + + let anga = p.get(i_anga)?; + if sau + && (anga.text.contains("d") || anga.text.contains("t")) + && (!anga.has_antya('d') && !anga.has_antya('t')) + { + p.run_at("7.2.106", i_anga, |t| { + t.find_and_replace_text("d", "s"); + t.find_and_replace_text("t", "s"); + // Add the FlagSaAdeshadi flag so that we get esa -> eza + t.add_tag(T::FlagSaAdeshadi); + }); + } + } else if anga.last().has_text("kim") { + if v.has_adi('t') || v.has_adi('h') { + p.run_at("7.2.104", i_anga, op::text("ku")); + } else if v.has_u("at") { + p.run_at("7.2.105", i_anga, op::text("kva")); + } else if !v.is_empty() { + p.run_at("7.2.103", i_anga, op::text("ka")); + } + } + + Some(()) +} + +fn try_anga_adesha_after_vibhakti_changes(p: &mut Prakriya) -> Option<()> { + let i = p.find_last(T::Pratipadika)?; + let i_sup = p.find_next_where(i, |t| !t.is_nyap_pratyaya())?; + + let anga = p.get(i)?; + let sup = p.pratyaya(i_sup)?; + if !sup.has_tag(T::Sup) { + return None; + } + + if anga.has_text("rE") && sup.has_adi(&*HAL) { + p.run_at("7.2.85", i, op::antya("A")); + } else if anga.has_text_in(&["yuzmad", "asmad"]) { + let anadesha = !sup.last().has_any_lakshana(); + + if sup.has_adi(&*AC) && anadesha { + // mayA, tvayA + p.run_at("7.2.89", i, op::antya("y")); + } else if anadesha { + p.run_at("7.2.86", i, op::antya("A")); + } else if sup.has_tag(T::V2) { + p.run_at("7.2.87", i, op::antya("A")); + } else if sup.last().has_all_tags(&[T::V1, T::Dvivacana]) { + p.run_at("7.2.88", i, op::antya("A")); + } else { + p.run_at("7.2.90", i, op::antya("")); + } + + let sup = p.pratyaya(i_sup)?; + if sup.has_tag(T::Dvivacana) { + p.run_at("7.2.92", i, |t| { + t.find_and_replace_text("yuzm", "yuva"); + t.find_and_replace_text("asm", "Ava"); + }); + } else if sup.has_lakshana("jas") { + p.run_at("7.2.93", i, |t| { + t.find_and_replace_text("yuzm", "yUya"); + t.find_and_replace_text("asm", "vaya"); + }); + } else if sup.has_lakshana("su~") { + p.run_at("7.2.94", i, |t| { + t.find_and_replace_text("yuzm", "tva"); + t.find_and_replace_text("asm", "aha"); + }); + } else if sup.has_lakshana("Ne") { + p.run_at("7.2.95", i, |t| { + t.find_and_replace_text("yuzm", "tuBya"); + t.find_and_replace_text("asm", "mahya"); + }); + } else if sup.has_lakshana("Nas") { + p.run_at("7.2.96", i, |t| { + t.find_and_replace_text("yuzm", "tava"); + t.find_and_replace_text("asm", "mama"); + }); + } else if sup.has_tag(T::Ekavacana) { + p.run_at("7.2.97", i, |t| { + t.find_and_replace_text("yuzm", "tva"); + t.find_and_replace_text("asm", "ma"); + }); + } + } else if anga.has_u("idam") && anga.has_antya('a') { + if sup.has_tag_in(&[T::V1, T::V2]) { + // imam + p.run_at("7.2.109", i, |t| t.set_text("ima")); + } else { + // Other vibhaktis + if sup.has_adi(&*HAL) { + // asya + p.run_at("7.2.113", i, |t| t.find_and_replace_text("id", "")); + } else { + // anena + p.run_at("7.2.112", i, |t| t.set_text("ana")); + } + } + } + + Some(()) +} + +fn try_pratipadika_guna(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let next = p.get(i_anga + 1)?; + + if anga.has_antya('f') && (next.has_u("Ni") || next.is_sarvanamasthana()) { + // kartari + let sub = al::to_guna(anga.antya()?)?; + p.run_at("7.3.110", i_anga, op::antya(sub)); + } else { + // `Ni` rules are an exception to 7.3.111. + let anga = p.get(i_anga)?; + let sup = p.get(i)?; + if anga.has_tag(T::Ghi) + && sup.has_tag(T::Nit) + && (anga.has_antya('i') || anga.has_antya('u')) + { + // agnaye, agneH + let sub = al::to_guna(anga.antya()?)?; + p.run_at("7.3.111", i_anga, op::antya(sub)); + } + } + Some(()) +} + +/// Runs rules that add various Agamas before the sup-pratyaya. +fn try_add_nit_agamas(p: &mut Prakriya, i_anga: usize) -> Option<()> { + let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; + let anga = p.get(i_anga)?; + let sup = p.get(i_sup)?; + + let niti = sup.has_tag(T::Nit); + let is_aap = anga.is_aap_pratyaya(); + + if anga.has_tag(T::Nadi) && niti { + op::insert_agama_at("7.3.112", p, i_sup, "Aw"); + } else if is_aap && niti { + if i_anga > 0 && p.has(i_anga - 1, |t| t.is_sarvanama()) { + // tasyE + p.run("7.3.114", |p| { + p.set(i_anga, op::antya("a")); + op::insert_agama_before(p, i_sup, "syAw") + }); + it_samjna::run(p, i_sup).ok()?; + } else { + // senAyE + op::insert_agama_at("7.3.113", p, i_sup, "yAw"); + } + } + + Some(()) +} + +/// Tries adesha rules for `Ni` (saptamI-ekavacana). +fn try_ni_adesha(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i)?; + if sup.has_u("Ni") { + let nadi_nyap = + anga.has_tag_in(&[T::Nadi, T::StriNyap]) || p.has(i_anga + 1, |t| t.has_u("wAp")); + let it_ut = anga.has_antya('i') || anga.has_antya('u'); + if it_ut { + if anga.has_tag(T::Nadi) { + op::adesha("7.3.117", p, i, "Am"); + } else if it_ut && anga.has_tag(T::Ghi) { + p.set(i_anga, |t| t.set_antya("a")); + op::adesha("7.3.119", p, i, "O"); + } else { + op::adesha("7.3.118", p, i, "O"); + } + } else if nadi_nyap { + op::adesha("7.3.116", p, i, "Am"); + } + } + + Some(()) +} + +/// Tries adesha of the trtiya-ekavacana pratyaya `wA`. +fn try_taa_adesha(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { + let anga = p.get(i_anga)?; + let sup = p.get(i)?; + if anga.has_tag(T::Ghi) && !p.has_tag(T::Stri) && sup.has_u("wA") { + op::adesha("7.3.120", p, i, "nA"); + } + + Some(()) +} + +/// Applies various rules before appending a strI-pratyaya. +/// - Drop su~ (for adas) +/// - Modify sarvanAma bases (to allow wAp-pratyaya). +pub fn run_before_stritva(p: &mut Prakriya) -> Option<()> { + let i_anga = p.find_last_where(|t| t.is_pratipadika_or_nyap())?; + + try_napumsaka_su_am_adesha(p, i_anga); + try_add_sup_agamas(p, i_anga); + try_anga_adesha_before_vibhakti_changes(p, i_anga); + + Some(()) +} + +/// Applies various rules before the "bhasya" section in 6.4. +fn run_before_bhasya(p: &mut Prakriya) -> Option<()> { + let i_anga = p.find_last_where(|t| t.is_pratipadika_or_nyap())?; + let i_next = i_anga + 1; + + try_sup_adesha(p, i_anga, i_next); + + // Must run before tA adesha for krozwrA, krozwunA + try_sarvanamasthane_asambuddhau(p, i_anga, i_next); + + let anga = p.get(i_anga)?; + let sup = p.get(i_next)?; + if anga.has_text_in(&["asTi", "daDi", "sakTi", "akzi"]) + && sup.has_tag_in(&[T::V3, T::V4, T::V5, T::V6, T::V7]) + { + // Must run before num-Agama. Order is: + // - an-Adeza + // - wA -> nA adesha (blocked by an-Adeza) + // - insertion of num-Agama + // - bhavya (causes nalopa of an) + p.run_at("7.1.75", i_anga, |t| { + t.set_antya("an"); + t.remove_tag(T::Ghi); + }); + } + + // This might cause "A --> nA" which blocks num-Agama. + try_taa_adesha(p, i_anga, i_next); + + Some(()) +} + +/// (7.1.19 - 7.1.32) +fn run_after_bhasya(p: &mut Prakriya) -> Option<()> { + let i_anga = p.find_last(T::Pratipadika)?; + let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; + + try_misc_rules(p, i_anga, i_sup); + try_add_num_agama_to_anga(p, i_anga); + try_ni_adesha(p, i_anga, i_sup); + try_pratipadika_guna(p, i_anga, i_sup); + + // TODO: replace uses of `i_anga` above if this works. + let i_anga = p.find_last_where(|t| t.is_pratipadika() || t.is_nyap_pratyaya())?; + try_add_nit_agamas(p, i_anga); + + Some(()) +} + +pub fn run(p: &mut Prakriya) { + run_before_bhasya(p); + + // Relevant changes made in the *bhasya* section: + // + // - change of of "-an" to "-n" (6.4.134) + samjna::try_run_for_pada_or_bha(p); + asiddhavat::bhasya(p); + + try_dirgha_adesha_before_num_agama(p); + run_after_bhasya(p); + try_anga_adesha_after_vibhakti_changes(p); +} diff --git a/vidyut-prakriya/src/angasya/sup_adesha.rs b/vidyut-prakriya/src/angasya/sup_adesha.rs deleted file mode 100644 index 4e83ec2..0000000 --- a/vidyut-prakriya/src/angasya/sup_adesha.rs +++ /dev/null @@ -1,368 +0,0 @@ -/*! -Runs rules that apply substitutions to the sup-pratyaya. -*/ -use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::Prakriya; -use crate::sounds as al; -use crate::stem_gana as gana; -use crate::tag::Tag as T; -use crate::term::Term; - -fn yatha(needle: &str, old: &'static [&str], new: &'static [&str]) -> Option<&'static str> { - for (i, o) in old.iter().enumerate() { - if needle == *o { - return Some(new[i]); - } - } - None -} - -fn is_aap(anga: &Term) -> bool { - anga.has_u_in(&["dAp", "wAp", "cAp"]) || (anga.has_antya('A') && anga.has_tag(T::StriNyap)) -} - -fn is_nyap_pratyaya(anga: &Term) -> bool { - anga.has_u_in(&["dAp", "wAp", "cAp", "NIp", "NIz"]) -} - -/// Tries adesha rules for napumsaka stems ending in 'a'. -fn try_napumsaka_su_am_adesha(p: &mut Prakriya, i_anga: usize, i_sup: usize) -> Option<()> { - let anga = p.get(i_anga)?; - p.get(i_sup)?; - - if anga.has_antya('a') { - if anga.has_text_in(gana::USES_DATARA_DATAMA) - || anga.has_text_in(&["anya", "anyatara", "itara"]) - { - p.run_at("7.1.25", i_sup, op::text("adq")); - } else { - op::adesha("7.1.24", p, i_sup, "am"); - } - } else { - p.run_at("7.1.23", i_sup, op::luk); - } - - Some(()) -} - -/// Tries adesha rules for stems ending in 'a'. -fn try_adanta_adesha(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { - let anga = p.get_if(i_anga, |t| t.has_antya('a'))?; - let sup = p.get(i)?; - - let nasi_ni = &["Nasi~", "Ni"]; - let smat_smin = &["smAt", "smin"]; - let ta_nasi_nas = &["wA", "Nasi~", "Nas"]; - let ina_at_sya = &["ina", "At", "sya"]; - - let is_sarvanama = anga.has_tag(T::Sarvanama); - let sup_u = match &sup.u { - Some(u) => u.to_string(), - None => "".to_string(), - }; - - if sup.has_text("Bis") { - if anga.has_u_in(&["idam", "adas"]) { - p.step("7.1.11"); - } else { - // narEH - p.run_at("7.1.9", i, op::text("Es")); - } - } else if is_sarvanama && sup.has_u_in(nasi_ni) { - let mut do_sub = true; - if anga.has_text_in(gana::PURVA_ADI) { - do_sub = !p.run_optional("7.1.16", |_| {}); - } - - if do_sub { - if let Some(sub) = yatha(&sup_u, nasi_ni, smat_smin) { - // tasmAt, tasmin - p.run_at("7.1.9", i, op::text(sub)); - } - } - } - - let sup = p.get(i)?; - if sup.has_u_in(ta_nasi_nas) && sup.has_text_in(&["A", "as"]) { - if let Some(sub) = yatha(&sup_u, ta_nasi_nas, ina_at_sya) { - // devena, devAt, devasya - p.run_at("7.1.12", i, op::text(sub)); - } - } else if sup.has_u("Ne") { - if is_sarvanama { - // tasmE - p.run_at("7.1.14", i, op::text("smE")); - } else { - // devAya - p.run_at("7.1.13", i, op::text("ya")); - } - } else if is_sarvanama && sup.has_u("jas") { - // te, sarve - op::adesha("7.1.17", p, i, "SI"); - } - - Some(()) -} - -/// Tries adesha rules for the bases `asmad` and `yuzmad`. -/// -/// Ordering: must come after 7.1.52 which creates "sAm" -fn try_yusmad_asmad_sup_adesha_before_bhasya(p: &mut Prakriya, i_anga: usize) -> Option<()> { - if !p.has(i_anga, |t| t.has_text_in(&["yuzmad", "asmad"])) { - return None; - } - - let i = i_anga + 1; - let sup = p.view(i_anga + 1)?; - - if sup.has_u("Nas") { - // mama, tava - op::adesha("7.1.27", p, i, "aS"); - } else if sup.has_u("Ne") || sup.has_tag_in(&[T::V1, T::V2]) { - if sup.has_u("Sas") { - // asmAn, yuzmAn - op::adesha("7.1.29", p, i, "n"); - } else { - // mahyam; aham, AvAm, vayam, mAm - // tuByam; tvam, yuvAm, yUyam, tvAm - op::adesha("7.1.28", p, i, "am"); - } - } else if sup.has_u("Byas") { - if sup.has_tag(T::V5) { - // asmat, yuzmat - op::adesha("7.1.31", p, i, "at"); - } else { - // asmaByam, yuzmaByam - op::adesha("7.1.30", p, i, "Byam"); - } - } else if sup.all(&[T::V5, T::Ekavacana]) { - // mat, tvat - op::adesha("7.1.32", p, i, "at"); - } - - Some(()) -} - -fn try_yusmad_asmad_sup_adesha_after_bhasya(p: &mut Prakriya, i_anga: usize) -> Option<()> { - if !p.has(i_anga, |t| t.has_text_in(&["yuzmad", "asmad"])) { - return None; - } - - let i = i_anga + 1; - let sup = p.view(i_anga + 1)?; - - if sup.first()?.has_text("s") && sup.last()?.has_text("Am") { - // All three of these lines ar part of 7.1.33. - let start = sup.start(); - p.terms_mut().remove(start); - op::adesha("7.1.33", p, i, "Akam"); - } - Some(()) -} - -fn try_sarvanamasthane_asambuddhau(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { - let anga = p.get(i_anga)?; - let sup = p.get(i)?; - - let sambuddhau = sup.has_tag(T::Sambuddhi); - let sarve_asambuddhau = sup.has_tag(T::Sarvanamasthana) && !sambuddhau; - let sau = sup.has_u("su~"); - - if sarve_asambuddhau { - if sau && anga.has_text("saKi") { - p.run_at("7.1.93", i_anga, op::antya("an")); - } else if sau - && (anga.has_antya('f') || anga.has_text_in(&["uSanas", "purudaMsas", "anehas"])) - { - p.run_at("7.1.94", i_anga, op::antya("an")); - } else if anga.has_text_in(&["catur", "anaquh"]) { - // TODO: am/Am? - if sambuddhau { - p.run_at("7.1.99", i_anga, op::mit("a")); - } else { - p.run_at("7.1.98", i_anga, op::mit("A")); - } - } - } - - Some(()) -} - -fn try_pratipadika_guna(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { - let anga = p.get(i_anga)?; - let sup = p.get_if(i, |t| t.is_sup())?; - - if anga.has_antya('f') && (sup.has_u("Ni") || sup.has_tag(T::Sarvanamasthana)) { - // kartari - let sub = al::to_guna(anga.antya()?)?; - p.run_at("7.3.110", i_anga, op::antya(sub)); - } else { - // `Ni` rules are an exception to 7.3.111. - let anga = p.get(i_anga)?; - let sup = p.get(i)?; - if anga.has_tag(T::Ghi) - && sup.has_tag(T::Nit) - && (anga.has_antya('i') || anga.has_antya('u')) - { - // agnaye, agneH - let sub = al::to_guna(anga.antya()?)?; - p.run_at("7.3.111", i_anga, op::antya(sub)); - } - } - Some(()) -} - -/// Runs rules that add various Agamas before the sup-pratyaya. -fn try_add_nit_agamas(p: &mut Prakriya, i_anga: usize) -> Option<()> { - let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; - let anga = p.get(i_anga)?; - let sup = p.get(i_sup)?; - - let niti = sup.has_tag(T::Nit); - let is_aap = (anga.has_antya('A') && is_aap(anga)) || p.has(i_anga + 1, is_nyap_pratyaya); - - if anga.has_tag(T::Nadi) && niti { - op::insert_agama_at("7.3.112", p, i_sup, "Aw"); - } else if is_aap && niti { - if anga.has_tag(T::Sarvanama) { - // tasyE - p.run("7.3.114", |p| { - p.set(i_anga, op::antya("a")); - op::insert_agama_before(p, i_sup, "syAw") - }); - it_samjna::run(p, i_sup).ok()?; - } else { - // senAyE - op::insert_agama_at("7.3.113", p, i_sup, "yAw"); - } - } - - Some(()) -} - -/// Tries adesha rules for `Ni` (saptamI-ekavacana). -fn try_ni_adesha(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { - let anga = p.get(i_anga)?; - let sup = p.get(i)?; - if sup.has_u("Ni") { - let nadi_nyap = - anga.has_tag_in(&[T::Nadi, T::StriNyap]) || p.has(i_anga + 1, |t| t.has_u("wAp")); - let it_ut = anga.has_antya('i') || anga.has_antya('u'); - if it_ut { - if anga.has_tag(T::Nadi) { - op::adesha("7.3.117", p, i, "Am"); - } else if it_ut && anga.has_tag(T::Ghi) { - p.set(i_anga, |t| t.set_antya("a")); - op::adesha("7.3.119", p, i, "O"); - } else { - op::adesha("7.3.118", p, i, "O"); - } - } else if nadi_nyap { - op::adesha("7.3.116", p, i, "Am"); - } - } - - Some(()) -} - -/// Tries adesha of the trtiya-ekavacana pratyaya `wA`. -fn try_taa_adesha(p: &mut Prakriya, i_anga: usize, i: usize) -> Option<()> { - let anga = p.get(i_anga)?; - let sup = p.get(i)?; - if anga.has_tag(T::Ghi) && !p.has_tag(T::Stri) && sup.has_u("wA") { - op::adesha("7.3.120", p, i, "nA"); - } - - Some(()) -} - -fn try_misc_rules(p: &mut Prakriya, i_anga: usize, i_sup: usize) -> Option<()> { - let anga = p.get(i_anga)?; - let sup = p.get(i_sup)?; - let sau = sup.has_u("su~"); - let sarvanamasthane = sup.has_tag(T::Sarvanamasthana); - - if sau && anga.has_text("div") { - // dyOH - p.run_at("7.1.84", i_anga, op::antya("O")); - } else if anga.has_text_in(&["paTin", "maTin", "fBukzin"]) { - if sau { - // panTAH, ... - p.run_at("7.1.85", i_anga, op::antya("A")); - } - - if sarvanamasthane { - // panTAnam, ... - p.run_at("7.1.86", i_anga, |t| t.find_and_replace_text("i", "a")); - if p.has(i_anga, |t| t.text.contains('T')) { - // panTAnam, ... - p.run_at("7.1.87", i_anga, |t| t.find_and_replace_text("T", "nT")); - } - } - - if p.has(i_anga, |t| t.has_tag(T::Bha)) { - // paTA, ... - p.run_at("7.1.88", i_anga, op::ti("")); - } - } else if anga.has_text("pums") && sarvanamasthane { - p.run_at("7.1.89", i_anga, |t| t.set_text("pumas")); - } - Some(()) -} - -pub fn run_before_bhasya(p: &mut Prakriya) -> Option<()> { - let i_anga = p.find_last(T::Pratipadika)?; - let i_sup = i_anga + 1; - - let anga = p.get(i_anga)?; - let sup = p.get(i_sup)?; - - let is_napumsaka = p.has_tag(T::Napumsaka); - let is_jas_shas = sup.has_u_in(&["jas", "Sas"]); - - if anga.has_tag(T::Sat) && is_jas_shas { - p.run_at("7.1.22", i_sup, op::luk); - } else if is_aap(anga) && sup.has_text("O") { - op::adesha("7.1.18", p, i_sup, "SI"); - } else if is_napumsaka && sup.has_text("O") { - op::adesha("7.1.19", p, i_sup, "SI"); - } else if is_napumsaka && is_jas_shas { - op::adesha("7.1.20", p, i_sup, "Si"); - } else if anga.has_text("azwA") && anga.has_u("azwan") && is_jas_shas { - op::adesha("7.1.21", p, i_sup, "OS"); - } else if is_napumsaka && sup.has_u_in(&["su~", "am"]) { - try_napumsaka_su_am_adesha(p, i_anga, i_sup); - } else { - try_adanta_adesha(p, i_anga, i_sup); - } - - // Add samjnas. - let sup = p.get(i_sup)?; - if sup.has_u("Si") { - p.run_at("1.1.42", i_sup, op::add_tag(T::Sarvanamasthana)); - } - - // This might cause "A --> nA" which blocks num-Agama. - try_taa_adesha(p, i_anga, i_sup); - - // Causes Bhyas -> at (asmat), which we need before bhatva - try_yusmad_asmad_sup_adesha_before_bhasya(p, i_anga); - - Some(()) -} - -/// (7.1.19 - 7.1.32) -pub fn run_after_bhasya(p: &mut Prakriya) -> Option<()> { - let i_anga = p.find_last(T::Pratipadika)?; - let i_sup = p.find_next_where(i_anga, |t| t.is_sup())?; - - try_yusmad_asmad_sup_adesha_after_bhasya(p, i_anga); - try_sarvanamasthane_asambuddhau(p, i_anga, i_sup); - try_misc_rules(p, i_anga, i_sup); - try_ni_adesha(p, i_anga, i_sup); - try_pratipadika_guna(p, i_anga, i_sup); - try_add_nit_agamas(p, i_anga); - - Some(()) -} diff --git a/vidyut-prakriya/src/ardhadhatuka.rs b/vidyut-prakriya/src/ardhadhatuka.rs index 9b8ff96..c51f007 100644 --- a/vidyut-prakriya/src/ardhadhatuka.rs +++ b/vidyut-prakriya/src/ardhadhatuka.rs @@ -1,13 +1,12 @@ //! ardhadhatuka -use crate::args::Gana; -use crate::args::Lakara; +use crate::args::{Gana, Lakara, Unadi}; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::TermView; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::Prakriya; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::TermView; use lazy_static::lazy_static; lazy_static! { @@ -22,7 +21,7 @@ lazy_static! { /// > 6.1.50 minātiminotidīṅāṃ lyapi ca /// > 6.1.51 vibhāṣā līyateḥ fn will_cause_guna(n: &TermView) -> bool { - let first = n.first().expect("ok"); + let first = n.first(); if first.is_knit() && !first.has_u("lyap") { return false; } @@ -58,15 +57,11 @@ pub fn dhatu_adesha_before_pada(p: &mut Prakriya, la: Lakara) { if p.has(i, |t| t.has_u("ca\\kzi~\\N")) { let mut use_khya = true; if la == Lakara::Lit { - if p.is_allowed("2.4.55") { - use_khya = false - } else { - p.decline("2.4.55") - } + use_khya = !p.optionally("2.4.55", |rule, p| p.step(rule)); } if use_khya { p.run("2.4.54", |p| { - op::upadesha(p, i, "KyAY"); + op::upadesha_no_it(p, i, "KyAY"); // Remove tags set by `ca\kzi~\N` p.set(i, |t| { t.remove_tags(&[T::anudattet, T::Nit]); @@ -74,6 +69,7 @@ pub fn dhatu_adesha_before_pada(p: &mut Prakriya, la: Lakara) { t.add_tag(T::Anudatta); }); }); + it_samjna::run(p, i).expect("ok"); } } } @@ -86,7 +82,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt let i = p.find_first(T::Dhatu)?; let j = p.find_next_where(i, |t| !t.is_empty())?; let dhatu = p.get(i)?; - let n = p.view(j)?; + let n = p.pratyaya(j)?; if dhatu.has_text("ad") { if n.has_lakshana("lu~N") || n.has_u("san") { @@ -123,7 +119,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt p.step("2.4.45.v1"); } - let n = p.view(j)?; + let n = p.pratyaya(j)?; if n.has_lakshana("lu~N") { // agAt op::adesha("2.4.45", p, i, "gA"); @@ -135,17 +131,22 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt op::optional_adesha("2.4.47", p, i, "gami~"); } } else if dhatu.has_u("i\\N") { - let to_gaa = |p: &mut Prakriya| op::upadesha(p, i, "gAN"); + let to_gaa = |p: &mut Prakriya| op::upadesha_no_it(p, i, "gAN"); + let mut run_it = false; if p.has(i + 1, |t| t.has_u("Ric")) && p.has(i + 2, |t| t.has_u_in(&["san", "caN"])) { - p.run_optional("2.4.51", to_gaa); + run_it = p.optional_run("2.4.51", to_gaa); } else if n.has_u("san") { // aDijigAMsate op::adesha("2.4.48", p, i, "gami~"); } else if n.has_lakshana("li~w") { p.run("2.4.49", to_gaa); + run_it = true; } else if n.has_lakshana_in(&["lu~N", "lf~N"]) { - p.run_optional("2.4.50", to_gaa); + run_it = p.optional_run("2.4.50", to_gaa); + } + if run_it { + it_samjna::run(p, i).expect("ok"); } } else if dhatu.has_u("asa~") { op::adesha("2.4.52", p, i, "BU"); @@ -155,11 +156,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt } else if dhatu.has_u("aja~") && !n.has_u_in(&["GaY", "ap"]) { let mut run = true; if n.has_u("lyu~w") { - if p.is_allowed("2.4.57") { - run = false; - } else { - p.decline("2.4.57") - } + run = !p.optional_run("2.4.57", |_| {}); } // vArttika: valAdAvArdhadhAtuke veSyate @@ -181,14 +178,9 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt let will_yasut = la == Some(Lakara::AshirLin) && p.has_tag(T::Parasmaipada); let is_lit_ajadi = la == Some(Lakara::Lit) && p.terms().last()?.has_adi(&*AC); let will_have_valadi = !(will_yasut || is_lit_ajadi); + // HACK: ignore Rvul, since it will be replaced with -aka. if n.has_adi(&*VAL) && will_have_valadi && !n.has_text("vu~") { - // HACK: ignore Rvul, since it will be replaced with -aka. - if p.is_allowed("2.4.56.v2") { - p.step("2.4.56.v2"); - run = false; - } else { - p.decline("2.4.56.v2"); - } + run = !p.optionally("2.4.56.v2", |rule, p| p.step(rule)); } if run { // aniT-tva comes from anudAtta in upadesha. @@ -202,7 +194,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt /// This code depends on the Ric-vikaraNa being present. fn dhatu_adesha_after_vikarana(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; if !n.has_tag(T::Ardhadhatuka) { return None; @@ -212,7 +204,7 @@ fn dhatu_adesha_after_vikarana(p: &mut Prakriya) -> Option<()> { if dhatu.has_u("i\\N") && p.terms().get(i + 2).is_some() { let n2 = p.terms().get(i + 2)?; if n.has_u("Ric") && n2.has_u_in(&["san", "caN"]) { - let done = p.run_optional("2.4.50", |p| op::upadesha(p, i, "gAN")); + let done = p.optional_run("2.4.50", |p| op::upadesha_no_it(p, i, "gAN")); if done { it_samjna::run(p, i).ok()?; } @@ -229,9 +221,12 @@ fn dhatu_adesha_after_vikarana(p: &mut Prakriya) -> Option<()> { fn try_aa_adesha(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let dhatu = p.get(i)?; + if dhatu.is_final() { + return None; + } // Substitution of A for root vowel if dhatu.has_antya(&*EC) && !n.has_tag(T::Sit) { @@ -248,7 +243,7 @@ fn try_aa_adesha(p: &mut Prakriya) -> Option<()> { p.run_at("6.1.48", i, op::antya("A")); } else if dhatu.has_u("zi\\Du~") && n.has_u("Ric") { // sADayati, seDayati - p.run_optional_at("6.1.49", i, op::upadha("A")); + p.optional_run_at("6.1.49", i, op::upadha("A")); } // 6.1.50 has a circular dependency: @@ -261,11 +256,15 @@ fn try_aa_adesha(p: &mut Prakriya) -> Option<()> { // So, "look ahead" and use this rule only if the suffix will potentially // cause guNa. See `will_cause_guna` for details. let dhatu = p.get(i)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let ashiti_lyapi = !n.has_tag(T::Sit) || n.has_u("lyap"); let nau = n.has_u("Ric"); - if dhatu.has_u_in(&["mI\\Y", "qumi\\Y", "dI\\N"]) && ashiti_lyapi && will_cause_guna(&n) { + if dhatu.has_u_in(&["mI\\Y", "qumi\\Y", "dI\\N"]) + && ashiti_lyapi + && !n.last().has_unadi(Unadi::u) + && will_cause_guna(&n) + { p.run_at("6.1.50", i, op::antya("A")); } else if dhatu.has_text("lI") && ashiti_lyapi @@ -275,19 +274,19 @@ fn try_aa_adesha(p: &mut Prakriya) -> Option<()> { // Accept both lI and lIN: // līyateriti yakā nirdeśo na tu śyanā. līlīṅorātvaṃ vā syādejviṣaye // lyapi ca. (SK) - p.run_optional_at("6.1.51", i, op::antya("A")); + p.optional_run_at("6.1.51", i, op::antya("A")); } else if dhatu.has_u("sPura~") && nau { - p.run_optional_at("6.1.54", i, op::upadha("A")); + p.optional_run_at("6.1.54", i, op::upadha("A")); } else if dhatu.has_u_in(&["ciY", "ci\\Y"]) && nau { - p.run_optional_at("6.1.54", i, op::antya("A")); + p.optional_run_at("6.1.54", i, op::antya("A")); } else if dhatu.has_u("vI\\") && dhatu.has_gana(Gana::Adadi) && nau { // Check gana to avoid aj -> vI - p.run_optional_at("6.1.55", i, op::antya("A")); + p.optional_run_at("6.1.55", i, op::antya("A")); } else if nau && p.has_tag(T::FlagHetuBhaya) { if dhatu.has_u("YiBI\\") { - p.run_optional_at("6.1.56", i, op::antya("A")); + p.optional_run_at("6.1.56", i, op::antya("A")); } else if dhatu.has_text("smi") { - p.run_optional_at("6.1.57", i, op::antya("A")); + p.optional_run_at("6.1.57", i, op::antya("A")); } } @@ -297,7 +296,7 @@ fn try_aa_adesha(p: &mut Prakriya) -> Option<()> { /// Runs rules that try adding am-Agama to a dhatu when certain pratyayas follow. pub fn try_add_am_agama(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let dhatu = p.get(i)?; @@ -307,7 +306,7 @@ pub fn try_add_am_agama(p: &mut Prakriya) -> Option<()> { p.run_at("6.1.58", i, op::mit("a")); } else if dhatu.has_tag(T::Anudatta) && dhatu.has_upadha('f') { // traptA, tarpitA, tarptA - p.run_optional_at("6.1.59", i, op::mit("a")); + p.optional_run_at("6.1.59", i, op::mit("a")); } } diff --git a/vidyut-prakriya/src/args.rs b/vidyut-prakriya/src/args.rs index 27cb204..daf8174 100644 --- a/vidyut-prakriya/src/args.rs +++ b/vidyut-prakriya/src/args.rs @@ -13,6 +13,9 @@ mod macros; mod dhatu; mod krt; +mod pada; +mod pratipadika; +mod samasa; mod sup; mod taddhita; mod tin; @@ -20,6 +23,9 @@ mod unadi; pub use dhatu::*; pub use krt::*; +pub use pada::*; +pub use pratipadika::*; +pub use samasa::*; pub use sup::*; pub use taddhita::*; pub use tin::*; diff --git a/vidyut-prakriya/src/args/dhatu.rs b/vidyut-prakriya/src/args/dhatu.rs index 7fdd2e6..8505a36 100644 --- a/vidyut-prakriya/src/args/dhatu.rs +++ b/vidyut-prakriya/src/args/dhatu.rs @@ -1,8 +1,8 @@ +use crate::core::errors::Error; use crate::enum_boilerplate; -use crate::errors::Error; use wasm_bindgen::prelude::wasm_bindgen; -/// Defines a gaṇa. +/// Defines a *gaṇa*. /// /// The dhatus in the Dhatupatha are organized in ten large *gaṇa*s or classes. These gaṇas /// add various properties to the dhatu, most notably the specific *vikaraṇa* (stem suffix) we use diff --git a/vidyut-prakriya/src/args/krt.rs b/vidyut-prakriya/src/args/krt.rs index d7245b3..e4273aa 100644 --- a/vidyut-prakriya/src/args/krt.rs +++ b/vidyut-prakriya/src/args/krt.rs @@ -1,6 +1,7 @@ use crate::args::unadi::Unadi; +use crate::args::Lakara; +use crate::core::errors::*; use crate::enum_boilerplate; -use crate::errors::*; use wasm_bindgen::prelude::wasm_bindgen; /// The complete list of ordinary krt-pratyayas. @@ -418,6 +419,7 @@ impl Upapada { pub struct KrdantaArgs { krt: Krt, artha: Option, + lakara: Option, upapada: Option, } @@ -427,6 +429,25 @@ impl KrdantaArgs { self.krt } + /// The lakara that this krt-pratyaya will replace. + pub fn lakara(&self) -> Option { + use BaseKrt::*; + use Lakara::*; + + if let Krt::Base(krt) = self.krt { + match krt { + Satf | SAnac => match self.lakara { + Some(Lat) | Some(Lrt) => self.lakara, + _ => Some(Lat), + }, + kAnac | kvasu => Some(Lit), + _ => None, + } + } else { + None + } + } + /// The upapada that conditions the krt pratyaya. pub fn upapada(&self) -> &Option { &self.upapada @@ -449,6 +470,7 @@ pub struct KrdantaArgsBuilder { krt: Option, upapada: Option, artha: Option, + lakara: Option, } impl KrdantaArgsBuilder { @@ -470,6 +492,15 @@ impl KrdantaArgsBuilder { self } + /// Sets the lakara to use in the derivation. + /// + /// This field is necessary for pratyayas like Satf and SAnac, which replace a specific lakara. + /// If `lakara` is not specified, prakriyas will default to lat-lakara. + pub fn lakara(&mut self, lakara: Lakara) -> &mut Self { + self.lakara = Some(lakara); + self + } + /// Converts the arguments in this builder into a `TinantaArgs` struct. /// /// `build()` will fail if any args are missing. @@ -480,6 +511,7 @@ impl KrdantaArgsBuilder { _ => return Err(Error::missing_required_field("krt")), }, upapada: self.upapada.as_ref().cloned(), + lakara: self.lakara, artha: self.artha, }) } diff --git a/vidyut-prakriya/src/args/macros.rs b/vidyut-prakriya/src/args/macros.rs index a4f7f7d..047846d 100644 --- a/vidyut-prakriya/src/args/macros.rs +++ b/vidyut-prakriya/src/args/macros.rs @@ -13,6 +13,7 @@ macro_rules! enum_boilerplate { } /// Iterates over all values of this enum in order. + #[allow(dead_code)] pub fn iter() -> impl Iterator { /// In Rust, `const` items are created at compile time. const ITEMS: &[$Enum] = &[ @@ -26,7 +27,7 @@ macro_rules! enum_boilerplate { impl std::str::FromStr for $Enum { type Err = Error; - fn from_str(value: &str) -> $crate::errors::Result { + fn from_str(value: &str) -> $crate::core::errors::Result { let ret = match value { $( $str => $Enum::$variant, diff --git a/vidyut-prakriya/src/args/pada.rs b/vidyut-prakriya/src/args/pada.rs new file mode 100644 index 0000000..51a6213 --- /dev/null +++ b/vidyut-prakriya/src/args/pada.rs @@ -0,0 +1,47 @@ +use crate::core::{Tag, Term}; + +/// Models a Sanskrit pada. +#[derive(Clone)] +pub struct Pada { + /// The terms that compose this pada. + terms: Vec, +} + +impl Pada { + /// Creates a new pada from the given text. + pub fn from_text(text: impl AsRef) -> Self { + let mut t = Term::make_upadesha(text.as_ref()); + t.add_tag(Tag::Pada); + Self { terms: vec![t] } + } + + /// Creates a new pada from the given text. + pub fn nipata(text: impl AsRef) -> Self { + let mut t = Term::make_upadesha(text.as_ref()); + + // ad-hoc it-samjna rules. + if t.has_suffix_in(&["Y", "N"]) { + t.set_antya(""); + } + + t.add_tags(&[Tag::Pada, Tag::Nipata, Tag::Sup]); + Self { terms: vec![t] } + } + + /// Creates a new pada from a list of terms. + /// + /// Returns `None` if these terms do not describe a valid pada. + pub(crate) fn from_terms(terms: Vec) -> Option { + let last = terms.last()?; + if last.is_pada() { + Some(Self { terms }) + } else { + None + } + } + + /// The terms in this pada. + pub(crate) fn terms(&self) -> &[Term] { + &self.terms + } +} diff --git a/vidyut-prakriya/src/args/pratipadika.rs b/vidyut-prakriya/src/args/pratipadika.rs new file mode 100644 index 0000000..efe5d6c --- /dev/null +++ b/vidyut-prakriya/src/args/pratipadika.rs @@ -0,0 +1,180 @@ +use crate::core::errors::Error; +use crate::core::Tag; +use crate::core::Term; +use enumset::EnumSet; + +/// A nominal stem. +/// +/// Rules 1.2.45 and 1.2.46 define a pratipadika as either: +/// +/// 1. A meaningful term that is neither a dhatu nor a pratyaya; +/// 2. A term whose last element is krt, taddhita, or a samasa. +/// +/// A pratipadika is the base to which we add sup-pratyayas. Through this process, we create +/// subantas (nominals), which are complete words. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct Pratipadika { + /// The terms that compose this pratipadika. + terms: Vec, +} + +impl Pratipadika { + /// Creates a new pratipadika. + pub fn from(text: impl AsRef) -> Self { + Self { + terms: vec![Term::make_upadesha(text.as_ref())], + } + } + + /// Creates a pratipadika from a list of terms. + /// + /// Returns `None` if these terms do not describe a valid pratipadika. + pub(crate) fn from_terms(terms: Vec) -> Option { + let last = terms.last()?; + if last.is_pratipadika() + || last.is_krt() + || last.is_taddhita() + || last.is_samasa() + || last.is_nyap_pratyaya() + { + // Also include nyAp-pratyayas. Though these are technically not pratipadikas, their + // association with them is so strong that we should include them here anyway. + Some(Self { terms }) + } else { + None + } + } + + /// The terms in this pratipadika. + pub(crate) fn terms(&self) -> &[Term] { + &self.terms + } + + /// The text of this pratipadika. + pub fn text(&self) -> String { + let mut ret = String::new(); + for t in self.terms() { + ret.push_str(&t.text); + } + ret + } + + /// Returns whether this pratipadika needs a `NI` or `Ap` pratyaya. + pub fn needs_nyap(&self) -> bool { + self.terms + .last() + .map_or(false, |t| t.has_tag(Tag::StriNyap)) + } + + /// Returns whether this pratipadika ends in a dhatu. + pub fn is_dhatu(&self) -> bool { + self.terms.last().map_or(false, |t| t.is_dhatu()) + } + + /// Returns a new builder for this struct. + pub fn builder() -> PratipadikaBuilder { + PratipadikaBuilder::default() + } +} + +/// Convenience struct for building a `Pratipadika` struct. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct PratipadikaBuilder { + text: Option, + is_nyap: bool, + is_dhatu: bool, + is_udit: bool, + is_pratyaya: bool, +} + +impl PratipadikaBuilder { + /// Sets the text of the pratipadika. + pub fn text(&mut self, value: impl AsRef) -> &mut Self { + self.text = Some(String::from(value.as_ref())); + self + } + + /// Sets whether this pratipadika should be treated as ending in `NI` or `Ap`. + pub fn is_nyap(&mut self, val: bool) -> &mut Self { + self.is_nyap = val; + self + } + + /// Sets whether this pratipadika should be treated as ending in a dhatu. + pub fn is_dhatu(&mut self, val: bool) -> &mut Self { + self.is_dhatu = val; + self + } + + /// Sets whether this pratipadika should be treated as ending in a dhatu. + pub fn is_udit(&mut self, val: bool) -> &mut Self { + self.is_udit = val; + self + } + + /// Sets whether this pratipadika should be treated as ending in a dhatu. + pub fn is_pratyaya(&mut self, val: bool) -> &mut Self { + self.is_pratyaya = val; + self + } + + /// Converts the arguments in this builder into a `Pratipadika` struct. + /// + /// `build()` will fail if `text` is missing. + pub fn build(&self) -> Result { + if let Some(text) = &self.text { + let mut term = Term::make_upadesha(&text); + let tags = self.create_tags(); + for tag in tags { + term.add_tag(tag); + } + let terms = vec![term]; + Ok(Pratipadika { terms }) + } else { + Err(Error::MissingRequiredField("text")) + } + } + + fn create_tags(&self) -> EnumSet { + let mut tags = EnumSet::default(); + if self.is_nyap { + tags.insert(Tag::StriNyap); + tags.insert(Tag::Stri); + } + if self.is_dhatu { + tags.insert(Tag::Dhatu); + } + if self.is_udit { + tags.insert(Tag::udit); + } + if self.is_dhatu { + tags.insert(Tag::Pratyaya); + } + + tags + } +} + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +mod tests { + use super::*; + + #[test] + fn create_pratipadika() { + let deva = Pratipadika::from("deva"); + assert_eq!(deva.text(), "deva"); + assert!(!deva.is_dhatu()); + } + + #[test] + fn create_pratipadika_with_dhatu() { + let senani = Pratipadika::builder() + .text("senAnI") + .is_dhatu(true) + .build() + .unwrap(); + assert_eq!(senani.text(), "senAnI"); + assert!(senani.is_dhatu()); + } +} diff --git a/vidyut-prakriya/src/args/samasa.rs b/vidyut-prakriya/src/args/samasa.rs new file mode 100644 index 0000000..7462948 --- /dev/null +++ b/vidyut-prakriya/src/args/samasa.rs @@ -0,0 +1,133 @@ +use crate::args::sup::Vibhakti; +use crate::args::Pratipadika; +use crate::core::errors::Error; + +/// A samasa type. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub enum SamasaType { + /// 2.1.5 + Avyayibhava, + /// 2.1.22 + Tatpurusha, + /// 1.2.42 + Karmadharaya, + /// 2.1.52 + Dvigu, + /// 2.2.1 + Ekadeshin, + /// 2.2.23 + Bahuvrihi, + /// 2.2.29 + Dvandva, + /// 2.2.29 (not defined explicitly) + SamaharaDvandva, +} + +/// Defines a subanta argument for a samasa. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct SamasaPada { + pratipadika: Pratipadika, + vibhakti: Vibhakti, + is_avyaya: bool, +} + +impl SamasaPada { + /// Creates a new pada to use when deriving the samasa. + pub fn new(pratipadika: Pratipadika, vibhakti: Vibhakti) -> Self { + Self { + pratipadika, + vibhakti, + is_avyaya: false, + } + } + + /// Creates a pada that will be bulit as an avyaya. + pub fn avyaya(pratipadika: Pratipadika) -> Self { + Self { + pratipadika, + vibhakti: Vibhakti::Prathama, + is_avyaya: true, + } + } + + /// Returns the pratipadika to use when deriving the samasa. + pub fn pratipadika(&self) -> &Pratipadika { + &self.pratipadika + } + + /// Returns the vibhakti to use when deriving the samasa. + /// + /// If deriving a tatpurusha, the choice of *vibhakti* here affects which tatpurusha rules are + /// available to the derivation. + pub fn vibhakti(&self) -> Vibhakti { + self.vibhakti + } + + pub(crate) fn is_avyaya(&self) -> bool { + self.is_avyaya + } +} + +/// The information required to derive a samasa in the grammar. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct SamasaArgs { + /// The items to combine in the samasa. + padas: Vec, + /// The samasa type to apply. + samasa_type: SamasaType, +} + +impl SamasaArgs { + /// Returns all padas to use in the derivation. + pub fn padas(&self) -> &Vec { + &self.padas + } + + /// Returns the samasa type to use in the derivation. + pub fn samasa_type(&self) -> SamasaType { + self.samasa_type + } + + /// Returns a new builder for this struct. + pub fn builder() -> SamasaArgsBuilder { + SamasaArgsBuilder::default() + } +} + +/// Convenience struct for building a `SamasaARgs` struct. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct SamasaArgsBuilder { + padas: Vec, + samasa_type: Option, +} + +impl SamasaArgsBuilder { + /// Sets the items to use in the derivation. + pub fn padas(&mut self, padas: Vec) -> &mut Self { + self.padas = padas; + self + } + + /// Sets the samasa type to use in the derivation. + pub fn samasa_type(&mut self, samasa_type: SamasaType) -> &mut Self { + self.samasa_type = Some(samasa_type); + self + } + + /// Converts the arguments in this builder into a `SamasaArgs` struct. + /// + /// `build()` will fail if any args are missing. + pub fn build(&self) -> Result { + Ok(SamasaArgs { + padas: if !self.padas.is_empty() { + self.padas.clone() + } else { + return Err(Error::missing_required_field("items")); + }, + samasa_type: match self.samasa_type { + Some(x) => x, + _ => return Err(Error::missing_required_field("samasa_type")), + }, + }) + } +} diff --git a/vidyut-prakriya/src/args/sup.rs b/vidyut-prakriya/src/args/sup.rs index c4e3576..52e72d8 100644 --- a/vidyut-prakriya/src/args/sup.rs +++ b/vidyut-prakriya/src/args/sup.rs @@ -1,8 +1,7 @@ use crate::args::tin::Vacana; +use crate::core::errors::Error; +use crate::core::Tag; use crate::enum_boilerplate; -use crate::errors::Error; -use crate::tag::Tag; -use enumset::EnumSet; use wasm_bindgen::prelude::wasm_bindgen; /// The gender of some subanta. @@ -86,126 +85,6 @@ impl Vibhakti { } } -/// The verb root to use for the derivation. -#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] -pub struct Pratipadika { - text: String, - tags: EnumSet, -} - -impl Pratipadika { - /// Creates a new pratipadika. - pub fn new(text: impl AsRef) -> Self { - Pratipadika::builder() - .text(text.as_ref()) - .build() - .expect("should have text") - } - - /// The text of this pratipadika. - pub fn text(&self) -> &String { - &self.text - } - - /// Returns whether this pratipadika ends in `NI` or `Ap.` - pub fn is_nyap(&self) -> bool { - self.tags.contains(Tag::StriNyap) - } - - /// Returns whether this pratipadika ends in a dhatu. - pub fn is_dhatu(&self) -> bool { - self.tags.contains(Tag::Dhatu) - } - - /// Returns whether this pratipadika is udit. - pub fn is_udit(&self) -> bool { - self.tags.contains(Tag::udit) - } - - /// Returns whether this pratipadika ends in a pratyaya. - pub fn is_pratyaya(&self) -> bool { - self.tags.contains(Tag::Pratyaya) - } - - /// Returns a new builder for this struct. - pub fn builder() -> PratipadikaBuilder { - PratipadikaBuilder::default() - } -} - -/// Convenience struct for building a `Pratipadika` struct. -#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] -pub struct PratipadikaBuilder { - text: Option, - is_nyap: bool, - is_dhatu: bool, - is_udit: bool, - is_pratyaya: bool, -} - -impl PratipadikaBuilder { - /// Sets the text of the pratipadika. - pub fn text(&mut self, value: impl AsRef) -> &mut Self { - self.text = Some(String::from(value.as_ref())); - self - } - - /// Sets whether this pratipadika should be treated as ending in `NI` or `Ap`. - pub fn is_nyap(&mut self, yes: bool) -> &mut Self { - self.is_nyap = yes; - self - } - - /// Sets whether this pratipadika should be treated as ending in a dhatu. - pub fn is_dhatu(&mut self, yes: bool) -> &mut Self { - self.is_dhatu = yes; - self - } - - /// Sets whether this pratipadika should be treated as ending in a dhatu. - pub fn is_udit(&mut self, yes: bool) -> &mut Self { - self.is_udit = yes; - self - } - - /// Sets whether this pratipadika should be treated as ending in a dhatu. - pub fn is_pratyaya(&mut self, yes: bool) -> &mut Self { - self.is_pratyaya = yes; - self - } - - /// Converts the arguments in this builder into a `Pratipadika` struct. - /// - /// `build()` will fail if `text` is missing. - pub fn build(&self) -> Result { - Ok(Pratipadika { - text: match &self.text { - Some(x) => x.clone(), - None => return Err(Error::MissingRequiredField("text")), - }, - tags: self.create_tags()?, - }) - } - - fn create_tags(&self) -> Result, Error> { - let mut tags = EnumSet::default(); - if self.is_nyap { - tags.insert(Tag::StriNyap); - } - if self.is_dhatu { - tags.insert(Tag::Dhatu); - } - if self.is_udit { - tags.insert(Tag::udit); - } - if self.is_dhatu { - tags.insert(Tag::Pratyaya); - } - - Ok(tags) - } -} - /// The information required to derive a subanta in the grammar. pub struct SubantaArgs { linga: Linga, @@ -218,10 +97,12 @@ impl SubantaArgs { pub fn linga(&self) -> Linga { self.linga } + /// The vacana to use in the derivation. pub fn vacana(&self) -> Vacana { self.vacana } + /// The vibhakti to use in the derivation. pub fn vibhakti(&self) -> Vibhakti { self.vibhakti @@ -247,11 +128,13 @@ impl SubantaArgsBuilder { self.linga = Some(val); self } + /// Sets the vacana to use in the derivation. pub fn vacana(&mut self, val: Vacana) -> &mut Self { self.vacana = Some(val); self } + /// Sets the vibhakti to use in the derivation. pub fn vibhakti(&mut self, val: Vibhakti) -> &mut Self { self.vibhakti = Some(val); @@ -278,41 +161,3 @@ impl SubantaArgsBuilder { }) } } - -#[cfg(test)] -#[allow(clippy::unwrap_used)] -mod tests { - use super::*; - - #[test] - fn create_pratipadika() { - let deva = Pratipadika::new("deva"); - assert_eq!(deva.text(), &"deva"); - assert!(!deva.is_nyap()); - assert!(!deva.is_dhatu()); - } - - #[test] - fn create_pratipadika_with_nyap() { - let mala = Pratipadika::builder() - .text("mAlA") - .is_nyap(true) - .build() - .unwrap(); - assert_eq!(mala.text(), &"mAlA"); - assert!(mala.is_nyap()); - assert!(!mala.is_dhatu()); - } - - #[test] - fn create_pratipadika_with_dhatu() { - let senani = Pratipadika::builder() - .text("senAnI") - .is_dhatu(true) - .build() - .unwrap(); - assert_eq!(senani.text(), &"senAnI"); - assert!(senani.is_dhatu()); - assert!(!senani.is_nyap()); - } -} diff --git a/vidyut-prakriya/src/args/taddhita.rs b/vidyut-prakriya/src/args/taddhita.rs index 7b7c545..3320450 100644 --- a/vidyut-prakriya/src/args/taddhita.rs +++ b/vidyut-prakriya/src/args/taddhita.rs @@ -1,5 +1,5 @@ +use crate::core::errors::*; use crate::enum_boilerplate; -use crate::errors::*; use wasm_bindgen::prelude::wasm_bindgen; /// The complete list of taddhita-pratyayas. @@ -17,6 +17,8 @@ pub enum Taddhita { akac, /// -a ac, + /// -aWa + aWac, /// -a aR, /// -a @@ -27,10 +29,16 @@ pub enum Taddhita { atasuc, /// -astAt astAti, + /// -Akin, + Akinic, /// -Ara Arak, /// -i iY, + /// -ita + itac, + /// -ina + inac, /// -in ini, /// -iman @@ -50,15 +58,23 @@ pub enum Taddhita { /// -Era Erak, /// -ka + ka, + /// -ka kak, + /// -kawa + kawac, /// -ka kan, + /// -ka + kap, /// -kalpa kalpap, /// -kftvas kftvasuc, - /// -ka - ka, + /// -kuwAra + kuwArac, + /// -kura, + kuRap, /// -Ina Ka, /// -Ina @@ -71,6 +87,12 @@ pub enum Taddhita { Gan, /// -iya Gas, + /// -caRa + caRap, + /// -cara + caraw, + /// -cuYcu + cuYcup, /// -Ayana cPaY, /// -- @@ -81,6 +103,10 @@ pub enum Taddhita { CaR, /// -Iya, Cas, + /// -jAtIya + jAtIyar, + /// -jAha + jAhac, /// -a, Ya, /// -ika @@ -90,9 +116,13 @@ pub enum Taddhita { /// -ya Yya, /// -a + wac, + /// -a waq, /// -iWa wiWan, + /// -wIwa + wIwac, /// -ya wyaR, /// -ana @@ -115,6 +145,8 @@ pub enum Taddhita { qupac, /// -mat qmatup, + /// -ya + qyaR, /// -vala qvalac, /// -aka @@ -153,8 +185,14 @@ pub enum Taddhita { tikan, /// -tya tyak, + /// -tyaka + tyakan, /// -tya tyap, + /// -tana + tyu, + /// -tana + tyul, /// -tra tral, /// -trA @@ -167,6 +205,8 @@ pub enum Taddhita { Tyan, /// -TA TAl, + /// -daGna + daGnac, /// -dA dA, /// -dAnIm @@ -175,20 +215,32 @@ pub enum Taddhita { deSya, /// -deSIya deSIyar, + /// -dvayasa + dvayasac, /// -dhA DA, /// -na na, /// -na naY, + /// -nAwa + nAwac, /// -Ayana Pak, /// -Ayana PaY, /// -Ayani PiY, + /// -bahu + bahuc, + /// -biqa + biqac, + /// -birIsa + birIsac, /// -Bakta Baktal, + /// -Brawa + Brawac, /// -ma ma, /// -mat @@ -197,6 +249,12 @@ pub enum Taddhita { map, /// -maya mayaw, + /// -mAtra + mAtrac, + /// -pASa + pASap, + /// -piwa + piwac, /// -ya ya, /// -ya @@ -215,8 +273,12 @@ pub enum Taddhita { rUpap, /// -rhi rhil, + /// -rUpya + rUpya, /// -la lac, + /// -vat + vatup, /// -vaya vaya, /// -vin @@ -235,8 +297,14 @@ pub enum Taddhita { vyan, /// -Sa Sa, + /// -SaNkawa + SaNkawac, /// -Sas Sas, + /// -SAla + SAlac, + /// -ka + zkan, /// -tra zwarac, /// -ika @@ -261,13 +329,17 @@ enum_boilerplate!(Taddhita, { a => "a", akac => "akac", ac => "ac", + aWac => "aWac", aY => "aY", aR => "aR", at => "at", atasuc => "atasu~c", astAti => "astAti~", + Akinic => "Akini~c", Arak => "Arak", iY => "iY", + itac => "itac", + inac => "inac", ini => "ini~", imanic => "imani~c", ila => "ila", @@ -277,28 +349,39 @@ enum_boilerplate!(Taddhita, { Iyasun => "Iyasu~n", eRya => "eRya", Erak => "Erak", - kan => "kan", + ka => "ka", kak => "kak", + kawac => "kawac", + kap => "kap", + kan => "kan", kalpap => "kalpap", kftvasuc => "kftvasu~c", - ka => "ka", + kuwArac => "kuwArac", + kuRap => "kuRap", Ka => "Ka", KaY => "KaY", Ga => "Ga", Gac => "Gac", Gan => "Gan", Gas => "Gas", + caRap => "caRap", + caraw => "caraw", + cuYcup => "cuYcup", cPaY => "cPaY", cvi => "cvi~", Ca => "Ca", CaR => "CaR", Cas => "Cas", + jAtIyar => "jAtIyar", + jAhac => "jAhac", Ya => "Ya", YiW => "YiW", Yya => "Yya", YyaN => "Yyan", + wac => "wac", waq => "waq", wiWan => "wi~Wan", + wIwac => "wIwac", wyaR => "wyaR", wyu => "wyu~", wyul => "wyu~l", @@ -310,6 +393,7 @@ enum_boilerplate!(Taddhita, { Wap => "Wap", qupac => "qupac", qmatup => "qmatu~p", + qyaR => "qyaR", qvalac => "qvalac", qvun => "qvu~n", Qak => "Qak", @@ -329,28 +413,41 @@ enum_boilerplate!(Taddhita, { ti => "ti", tikan => "tikan", tyak => "tyak", + tyakan => "tyakan", tyap => "tyap", + tyu => "tyu~", + tyul => "tyu~l", tral => "tral", trA => "trA", tva => "tva", Tamu => "Tamu~", Tyan => "Tyan", TAl => "TAl", + daGnac => "daGnac", + dvayasac => "dvayasac", dA => "dA", dAnIm => "dAnIm", deSya => "deSya", deSIyar => "deSIyar", DA => "DA", na => "na", + nAwac => "nAwac", naY => "naY", ma => "ma", matup => "matu~p", map => "map", mayaw => "mayaw", + pASap => "pASap", + piwac => "piwac", Pak => "Pak", PaY => "PaY", PiY => "PiY", + bahuc => "bahuc", + biqac => "biqac", + birIsac => "birIsac", Baktal => "Baktal", + Brawac => "Brawac", + mAtrac => "mAtrac", ya => "ya", yak => "yak", yaY => "yaY", @@ -359,10 +456,12 @@ enum_boilerplate!(Taddhita, { yus => "yus", ra => "ra", rhil => "rhil", + rUpya => "rUpya", lac => "lac", rUpap => "rUpap", - viDal => "viDal", + vatup => "vatu~p", vaya => "vaya", + viDal => "viDal", vini => "vini~", vuk => "vu~k", vuY => "vu~Y", @@ -370,7 +469,10 @@ enum_boilerplate!(Taddhita, { vyat => "vyat", vyan => "vyan", Sa => "Sa", + SaNkawac => "SaNkawac", + SAlac => "SAlac", Sas => "Sas", + zkan => "zkan", zwarac => "zwarac", zWac => "zWac", zWan => "zWan", @@ -505,6 +607,26 @@ pub enum TaddhitaArtha { TadVahati, /// What one pierces. (4.4.83) TadVidhyati, + /// What one has obtained. (4.4.85) + Labdha, + /// Where one has gone. (4.4.86) + Gata, + /// In which this is seen. (4.4.87) + AsminDrshyam, + /// Whose root is removed. (4.4.88) + AsyaAbarhi, + /// Joined with this. (4.4.90) + Samyukta, + /// Not deviating from this. (4.4.92) + Anapeta, + /// Made of this. (4.4.93) + Nirmita, + /// Dear to this. (4.4.95) + Priya, + /// Skilled in this. (4.4.98) + TatraSadhu, + /// Living there. (4.4.107) + TatraVasi, /// One for whom this is good. (5.1.7) TasmaiHitam, /// What could be created from this raw material. (5.1.12) @@ -513,6 +635,14 @@ pub enum TaddhitaArtha { TadAsyaTadAsminSyat, /// What is bought with this. (5.1.37) TenaKritam, + /// One deserves this. (5.1.63) + TadArhati, + /// One performs this. (5.1.72) + TadVartayati, + /// Fallen into this. (5.1.73) + Apanna, + /// Who goes. (5.1.75) + Gacchati, /// The existence of which. (5.1.119) TasyaBhava, /// A place of growing, when that place is a field. (5.2.1) @@ -525,6 +655,26 @@ pub enum TaddhitaArtha { Vyapnoti, /// Obtains. (5.2.8) Prapnoti, + /// Who witnesses this. (5.2.10) + TadAnubhavati, + /// Who intends to go. (5.2.11) + Gami, + /// Fit to go. (5.2.15) + AlamGami, + /// Formerly this. (5.2.18) + BhutaPurva, + /// What can be traveled in one day. (5.2.19) + EkahaGama, + /// The ripening season of this. (5.2.24) + TasyaPakamula, + /// The root of this. (5.2.25) + TasyaMula, + /// Celebrated through this. (5.2.26) + TenaVitta, + /// Measure. (5.2.37) + Pramana, + /// Volume. (5.2.39) + Parimana, /// What one has or is in. (5.2.94) TadAsyaAstiAsmin, /// Words meaning direction, location, or time. (5.3.27) diff --git a/vidyut-prakriya/src/args/tin.rs b/vidyut-prakriya/src/args/tin.rs index 236a8f6..d35839d 100644 --- a/vidyut-prakriya/src/args/tin.rs +++ b/vidyut-prakriya/src/args/tin.rs @@ -1,6 +1,6 @@ +use crate::core::errors::Error; +use crate::core::Tag; use crate::enum_boilerplate; -use crate::errors::Error; -use crate::tag::Tag; use wasm_bindgen::prelude::wasm_bindgen; /// The prayoga of some tinanta. @@ -153,22 +153,22 @@ impl Lakara { } } -/// The pada of some tinanta. +/// The pada of some tinanta or krdanta. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[wasm_bindgen] -pub enum Pada { +pub enum DhatuPada { /// Parasmaipada. Parasmai, /// Atmanepada. Atmane, } -enum_boilerplate!(Pada, { +enum_boilerplate!(DhatuPada, { Parasmai => "parasmai", Atmane => "atmane", }); -impl Pada { +impl DhatuPada { pub(crate) fn as_tag(&self) -> Tag { match self { Self::Parasmai => Tag::Parasmaipada, @@ -193,7 +193,7 @@ pub struct TinantaArgs { purusha: Purusha, lakara: Lakara, vacana: Vacana, - pada: Option, + pada: Option, } impl TinantaArgs { @@ -221,7 +221,7 @@ impl TinantaArgs { /// /// If unset, the program will use whatever padas are allowed by the Atmanepada section of the /// Ashtadhyayi. See the `atmanepada` module for details. - pub fn pada(&self) -> Option { + pub fn pada(&self) -> Option { self.pada } @@ -238,7 +238,7 @@ pub struct TinantaArgsBuilder { purusha: Option, lakara: Option, vacana: Option, - pada: Option, + pada: Option, } impl TinantaArgsBuilder { @@ -270,7 +270,7 @@ impl TinantaArgsBuilder { /// /// If unset, the program will use whatever padas are allowed by the Atmanepada section of the /// Ashtadhyayi. See the `atmanepada` module for details. - pub fn pada(mut self, val: Pada) -> Self { + pub fn pada(mut self, val: DhatuPada) -> Self { self.pada = Some(val); self } diff --git a/vidyut-prakriya/src/args/unadi.rs b/vidyut-prakriya/src/args/unadi.rs index 3955ae0..0c600d1 100644 --- a/vidyut-prakriya/src/args/unadi.rs +++ b/vidyut-prakriya/src/args/unadi.rs @@ -1,5 +1,5 @@ +use crate::core::errors::*; use crate::enum_boilerplate; -use crate::errors::*; use wasm_bindgen::prelude::wasm_bindgen; @@ -19,6 +19,8 @@ pub enum Unadi { aknuc, /// -aNga aNgac, + /// -adAnu + radAnuk, /// -a ac, /// -aji @@ -634,6 +636,7 @@ pub enum Unadi { enum_boilerplate!(Unadi, { aknuc => "aknuc", aNgac => "aNgac", + radAnuk => "radAnuk", ac => "ac", aji => "aji", awan => "awan", @@ -845,7 +848,7 @@ enum_boilerplate!(Unadi, { qau => "qau", qaw => "qaw", qati => "qati", - qavatu => "qavatu", + qavatu => "qavatu~", qimi => "qimi", qutac => "qutac", qun => "qun", diff --git a/vidyut-prakriya/src/ashtadhyayi.rs b/vidyut-prakriya/src/ashtadhyayi.rs index 85585ff..669fb2f 100644 --- a/vidyut-prakriya/src/ashtadhyayi.rs +++ b/vidyut-prakriya/src/ashtadhyayi.rs @@ -1,342 +1,16 @@ /*! -The Ashtadhyayi and its rules. +A high-level interface to `vidyut-prakriya`. The main struct here is `Ashtadhyayi`. This struct accepts various config options that control how words are derived in the system. For details, see `AshtadhyayiBuilder`. */ -use crate::ac_sandhi; -use crate::angasya; -use crate::ardhadhatuka; -use crate::args::Upapada; use crate::args::{ - Artha, BaseKrt, Dhatu, KrdantaArgs, Krt, Lakara, Linga, Pratipadika, Prayoga, SubantaArgs, - TaddhitantaArgs, TinantaArgs, + Dhatu, KrdantaArgs, Pada, Pratipadika, SamasaArgs, SubantaArgs, TaddhitantaArgs, TinantaArgs, }; -use crate::atidesha; -use crate::atmanepada; -use crate::dhatu_karya; -use crate::dvitva; -use crate::errors::*; -use crate::it_agama; -use crate::krt; -use crate::la_karya; -use crate::linganushasanam; -use crate::misc; -use crate::prakriya::Prakriya; -use crate::prakriya_stack::PrakriyaStack; -use crate::pratipadika_karya; -use crate::samjna; -use crate::samprasarana; -use crate::sanadi; -use crate::stritva; -use crate::sup_karya; -use crate::taddhita; -use crate::tag::Tag; -use crate::term::Term; -use crate::tin_pratyaya; -use crate::tripadi; -use crate::uttarapade; -use crate::vikarana; - -/// Adds a dhatu to the prakriya and runs basic follow-up tasks, such as: -/// -/// - replacing initial `R` and `z` with `n` and `s`, respectively. -/// - recording and removing any it-samjnas -/// - adding any necessary sanAdi-pratyayas. -fn add_dhatu(p: &mut Prakriya, dhatu: &Dhatu, is_ardhadhatuka: bool) -> Result<()> { - dhatu_karya::run(p, dhatu)?; - - sanadi::try_add_specific_sanadi_pratyayas(p, is_ardhadhatuka); - if p.terms().last().expect("ok").is_pratyaya() { - samjna::run(p); - run_rules(p, None, false)?; - } - - for s in dhatu.sanadi() { - sanadi::try_add_general_sanadi_pratyaya(p, *s); - samjna::run(p); - // Needed for BIzayate, etc. - atmanepada::run(p); - run_rules(p, None, false)?; - } - - if !dhatu.sanadi().is_empty() { - p.debug("~~~~~~~~~~~~~~ completed dhatu ~~~~~~~~~~~~~~~~~~") - } - - Ok(()) -} - -// Adds a lakara and decides which pada it is allowed to use. -fn add_lakara_and_decide_pada(p: &mut Prakriya, lakara: Lakara) { - la_karya::run(p, lakara); - ardhadhatuka::dhatu_adesha_before_pada(p, lakara); - atmanepada::run(p); -} - -/// Runs rules that potentially add a lakara. -/// -/// Certain krt-pratyayas are allowed only if they replace a specific lakara. To accommodate those -/// rules, first run this check. -fn maybe_add_lakara_for_krt(p: &mut Prakriya, krt: Krt) { - if let Krt::Base(b) = krt { - use BaseKrt::*; - use Lakara::*; - if matches!(b, Satf | SAnac) { - // TODO: also support Lrt (gamizyat) and karmani. - p.add_tag(Tag::Kartari); - add_lakara_and_decide_pada(p, Lat); - } else if matches!(b, kAnac | kvasu) { - // TODO: also support karmani. - p.add_tag(Tag::Kartari); - add_lakara_and_decide_pada(p, Lit); - } - } -} - -fn run_various_dhatu_tasks(p: &mut Prakriya) { - // Needed transitively for dhatu-samprasarana. - angasya::try_pratyaya_adesha(p); - // Must run before it-Agama. - angasya::try_cinvat_for_bhave_and_karmani_prayoga(p); - - // Depends on jha_adesha since it conditions on the first sound. - it_agama::run_before_attva(p); - // Depends on it_agama for certain rules. - atidesha::run_before_attva(p); - - // Samprasarana of the dhatu is conditioned on several other operations, which we must execute - // first: - // - // 1. jha_adesha (affects it-Agama). - // 2. it_agama (affects kit-Nit) - // 3. atidesha (for kit-Nit) - samprasarana::run_for_dhatu(p); - // Ad-Adeza and other special tasks for Ardhadhatuka - ardhadhatuka::run_before_dvitva(p); - - // Now finish it_agama and atidesha - it_agama::run_after_attva(p); - atidesha::run_after_attva(p); -} - -fn run_rules(p: &mut Prakriya, lakara: Option, is_ardhadhatuka: bool) -> Result<()> { - misc::run_pad_adi(p); - - p.debug("==== Tin-siddhi ===="); - // Do lit-siddhi and AzIrlin-siddhi first to support the valAdi vArttika for aj -> vi. - let is_lit_or_ashirlin = matches!(lakara, Some(Lakara::Lit) | Some(Lakara::AshirLin)); - if let Some(lakara) = lakara { - if is_lit_or_ashirlin { - tin_pratyaya::try_general_siddhi(p, lakara); - tin_pratyaya::try_siddhi_for_jhi(p, lakara); - } - } - - p.debug("==== Vikaranas ===="); - ardhadhatuka::run_before_vikarana(p, lakara, is_ardhadhatuka); - vikarana::run(p)?; - samjna::run(p); - - if let Some(lakara) = lakara { - if !is_lit_or_ashirlin { - tin_pratyaya::try_general_siddhi(p, lakara); - } - } - - // Constraints: - // - should run before atidesha rules because of Rittva. - // - should also run for subantas. - angasya::try_add_or_remove_nit(p); - - p.debug("==== Dhatu tasks ===="); - run_various_dhatu_tasks(p); - - // Must follow tin-siddhi and it-Agama, which could change the first sound of the pratyaya. - ardhadhatuka::try_add_am_agama(p); - - p.debug("==== Dvitva (dvirvacane 'ci) ===="); - dvitva::try_dvirvacane_aci(p); - let used_dvirvacane_aci = p.find_last_where(Term::is_abhyasta).is_some(); - if used_dvirvacane_aci { - samprasarana::run_for_abhyasa(p); - } - - // If Ji causes dvitva, that dvitva will be performed in `try_dvirvacane_aci` above. - // So by this point, it's safe to replace Ji. (See 3.4.109, which replaces Ji if it follows a - // term called `abhyasta`.) - if let Some(lakara) = lakara { - if !is_lit_or_ashirlin { - tin_pratyaya::try_siddhi_for_jhi(p, lakara); - } - } - uttarapade::run(p); - angasya::maybe_do_jha_adesha(p); - - ac_sandhi::try_sup_sandhi_before_angasya(p); - angasya::run_before_dvitva(p); - - p.debug("==== Dvitva (default) ===="); - dvitva::run(p); - if !used_dvirvacane_aci { - samprasarana::run_for_abhyasa(p); - } - - p.debug("==== After dvitva ===="); - angasya::run_after_dvitva(p); - uttarapade::run_after_guna(p); - ac_sandhi::try_sup_sandhi_after_angasya(p); - ac_sandhi::run_common(p); - - p.debug("==== Tripadi ===="); - tripadi::run(p); - - Ok(()) -} - -fn derive_tinanta(mut prakriya: Prakriya, dhatu: &Dhatu, args: &TinantaArgs) -> Result { - let p = &mut prakriya; - let prayoga = args.prayoga(); - let lakara = args.lakara(); - let purusha = args.purusha(); - let vacana = args.vacana(); - p.add_tags(&[prayoga.as_tag(), purusha.as_tag(), vacana.as_tag()]); - p.set_lakara(lakara); - - // Prayogas other than kartari will never be sarvadhatuka, since yak-vikarana is not - // sarvadhatuka. - let is_ardhadhatuka = match prayoga { - Prayoga::Kartari => lakara.is_ardhadhatuka(), - _ => true, - }; - - add_dhatu(p, dhatu, is_ardhadhatuka)?; - add_lakara_and_decide_pada(p, lakara); - - // Try adding am-pratyaya and the corresponding dhatu before tin-adesha, since doing so affects - // the pada. - vikarana::try_add_am_pratyaya_for_lit(p); - tin_pratyaya::adesha(p, purusha, vacana); - samjna::run(p); - - run_rules(p, Some(lakara), is_ardhadhatuka)?; - - Ok(prakriya) -} - -fn derive_subanta( - mut prakriya: Prakriya, - pratipadika: &Pratipadika, - args: &SubantaArgs, -) -> Result { - let p = &mut prakriya; - - // First, create the pratipadika. - pratipadika_karya::run(p, pratipadika, args.linga()); - stritva::run(p); - if p.terms().len() > 1 { - run_rules(p, None, false)?; - } - - // Then, add the sup-pratyaya. - sup_karya::run(p, args); - samjna::run(p); - run_rules(p, None, false)?; - - Ok(prakriya) -} - -/// Derives a single krdanta from the given conditions. -fn derive_krdanta(mut prakriya: Prakriya, dhatu: &Dhatu, args: &KrdantaArgs) -> Result { - let p = &mut prakriya; - - // If defined, set the meaning condition that this prakriya must follow. - if let Some(artha) = args.artha() { - p.set_artha(Artha::Krt(artha)); - } - - if let Some(upa) = args.upapada() { - let mut upapada = Term::make_upadesha(upa.text()); - upapada.add_tag(Tag::Pratipadika); - match upa { - Upapada::Avyaya(_) => upapada.add_tag(Tag::Avyaya), - _ => (), - } - p.push(upapada); - - let mut su = Term::make_text(""); - su.add_tags(&[Tag::Pratyaya, Tag::Vibhakti, Tag::Sup, Tag::Pada]); - p.push(su); - samjna::run(p); - } - - let krt = args.krt(); - add_dhatu(p, dhatu, krt.is_ardhadhatuka())?; - maybe_add_lakara_for_krt(p, krt); - vikarana::try_add_am_pratyaya_for_lit(p); - - let added = krt::run(p, args); - if !added { - return Err(Error::Abort(prakriya)); - } - - linganushasanam::run(p); - stritva::run(p); - samjna::run(p); - - run_rules(p, None, true)?; - - Ok(prakriya) -} - -fn derive_taddhitanta( - mut prakriya: Prakriya, - pratipadika: &Pratipadika, - args: &TaddhitantaArgs, -) -> Result { - let taddhita = args.taddhita(); - let p = &mut prakriya; - - // If defined, set the meaning condition that this prakriya must follow. - if let Some(artha) = args.artha() { - p.set_artha(Artha::Taddhita(artha)); - } - - // Begin the derivation. - pratipadika_karya::run(p, pratipadika, Linga::Pum); - samjna::run(p); - - let added = taddhita::run(p, taddhita); - if !added { - return Err(Error::Abort(prakriya)); - } - - linganushasanam::run(p); - stritva::run(p); - samjna::run(p); - - run_rules(p, None, false)?; - - Ok(prakriya) -} - -fn derive_vakya( - mut prakriya: Prakriya, - first: impl AsRef, - second: impl AsRef, -) -> Result { - let p = &mut prakriya; - let mut pada1 = Term::make_text(&first.as_ref()); - let mut pada2 = Term::make_text(&second.as_ref()); - pada1.add_tag(Tag::Pada); - pada2.add_tag(Tag::Pada); - p.push(pada1); - p.push(pada2); - - run_rules(p, None, false)?; - - Ok(prakriya) -} +use crate::core::prakriya_stack::PrakriyaStack; +use crate::core::Prakriya; +use crate::core::Tag; +use crate::sutrapatha; /// An interface to the rules of the Ashtadhyayi. /// @@ -416,7 +90,7 @@ impl Ashtadhyayi { pub fn derive_tinantas(&self, dhatu: &Dhatu, args: &TinantaArgs) -> Vec { let mut stack = self.create_prakriya_stack(); // TODO: handle error properly. - stack.find_all(|p| derive_tinanta(p, dhatu, args)); + stack.find_all(|p| sutrapatha::derive_tinanta(p, dhatu, args)); let mut prakriyas = stack.prakriyas(); // If the caller specified an explicit pada, keep only the results that match that pada. @@ -424,10 +98,10 @@ impl Ashtadhyayi { // TODO: to avoid wasting time on deriving words that we'll just throw out, push this // further into `derive_tinanta`. if let Some(pada) = args.pada() { - use crate::args::Pada; + use crate::args::DhatuPada; prakriyas.retain(|p| match pada { - Pada::Parasmai => p.has_tag(pada.as_tag()) && !p.has_tag(Tag::AmAtmanepada), - Pada::Atmane => p.has_tag_in(&[pada.as_tag(), Tag::AmAtmanepada]), + DhatuPada::Parasmai => p.has_tag(pada.as_tag()) && !p.has_tag(Tag::AmAtmanepada), + DhatuPada::Atmane => p.has_tag_in(&[pada.as_tag(), Tag::AmAtmanepada]), }); } @@ -456,7 +130,7 @@ impl Ashtadhyayi { /// ``` pub fn derive_subantas(&self, pratipadika: &Pratipadika, args: &SubantaArgs) -> Vec { let mut stack = self.create_prakriya_stack(); - stack.find_all(|p| derive_subanta(p, pratipadika, args)); + stack.find_all(|p| sutrapatha::derive_subanta(p, pratipadika, args)); stack.prakriyas() } @@ -473,14 +147,14 @@ impl Ashtadhyayi { /// let a = Ashtadhyayi::new(); /// let dhatu = Dhatu::new("BU", Gana::Bhvadi); /// let args = KrdantaArgs::builder() - /// .krt(Krt::ktvA) + /// .krt(BaseKrt::ktvA) /// .build()?; /// let prakriyas = a.derive_krdantas(&dhatu, &args); /// # Ok::<(), Error>(()) /// ``` pub fn derive_krdantas(&self, dhatu: &Dhatu, args: &KrdantaArgs) -> Vec { let mut stack = self.create_prakriya_stack(); - stack.find_all(|p| derive_krdanta(p, dhatu, args)); + stack.find_all(|p| sutrapatha::derive_krdanta(p, dhatu, args)); stack.prakriyas() } @@ -508,17 +182,66 @@ impl Ashtadhyayi { args: &TaddhitantaArgs, ) -> Vec { let mut stack = self.create_prakriya_stack(); - stack.find_all(|p| derive_taddhitanta(p, pratipadika, args)); + stack.find_all(|p| sutrapatha::derive_taddhitanta(p, pratipadika, args)); + stack.prakriyas() + } + + /// Returns all possible stryanta prakriyas that can be derived with the given initial + /// conditions. + /// + /// + /// ### Example + /// + /// ``` + /// # use vidyut_prakriya::Ashtadhyayi; + /// # use vidyut_prakriya::Error; + /// # use vidyut_prakriya::args::*; + /// let a = Ashtadhyayi::new(); + /// let pratipadika = Pratipadika::new("nara"); + /// let prakriyas = a.derive_stryantas(&pratipadika); + /// # Ok::<(), Error>(()) + /// ``` + pub fn derive_stryantas(&self, pratipadika: &Pratipadika) -> Vec { + let mut stack = self.create_prakriya_stack(); + stack.find_all(|p| sutrapatha::derive_stryanta(p, pratipadika)); + stack.prakriyas() + } + + /// Returns all possible sandhi results that follow from the given initial conditions. + /// + /// + /// ### Example + /// + /// ``` + /// # use vidyut_prakriya::Ashtadhyayi; + /// # use vidyut_prakriya::Error; + /// # use vidyut_prakriya::args::*; + /// let a = Ashtadhyayi::new(); + /// # Ok::<(), Error>(()) + pub fn derive_samasas(&self, args: &SamasaArgs) -> Vec { + let mut stack = self.create_prakriya_stack(); + stack.find_all(|p| sutrapatha::derive_samasa(p, &args)); stack.prakriyas() } /// Returns all possible sandhi results that follow from the given initial conditions. - pub fn derive_vakyas(&self, first: impl AsRef, second: impl AsRef) -> Vec { + /// + /// + /// ### Example + /// + /// ``` + /// # use vidyut_prakriya::Ashtadhyayi; + /// # use vidyut_prakriya::Error; + /// # use vidyut_prakriya::args::*; + /// let a = Ashtadhyayi::new(); + /// # Ok::<(), Error>(()) + pub fn derive_vakyas(&self, padas: &[Pada]) -> Vec { let mut stack = self.create_prakriya_stack(); - stack.find_all(|p| derive_vakya(p, &first, &second)); + stack.find_all(|p| sutrapatha::derive_vakya(p, &padas)); stack.prakriyas() } + /// Creates a prakriya stack that generates prakriyas according to our derivation options. fn create_prakriya_stack(&self) -> PrakriyaStack { PrakriyaStack::new(self.log_steps, self.is_chandasi) } @@ -526,14 +249,14 @@ impl Ashtadhyayi { /// A builder for creating an `Ashtadhyayi` struct. pub struct AshtadhyayiBuilder { - a: Ashtadhyayi, + ashtadhyayi: Ashtadhyayi, } impl AshtadhyayiBuilder { /// Creates a new builder. fn new() -> Self { Self { - a: Ashtadhyayi::new(), + ashtadhyayi: Ashtadhyayi::new(), } } @@ -546,7 +269,7 @@ impl AshtadhyayiBuilder { /// be available. This is best used when you want to generate a word list and don't need the /// underlying derivation. pub fn log_steps(mut self, value: bool) -> Self { - self.a.log_steps = value; + self.ashtadhyayi.log_steps = value; self } @@ -556,12 +279,12 @@ impl AshtadhyayiBuilder { /// /// - If `false`, each `Prakriya` will use a standard ruleset. pub fn is_chandasa(mut self, value: bool) -> Self { - self.a.is_chandasi = value; + self.ashtadhyayi.is_chandasi = value; self } /// Creates an `Ashtadhyayi` struct. pub fn build(self) -> Ashtadhyayi { - self.a + self.ashtadhyayi } } diff --git a/vidyut-prakriya/src/atidesha.rs b/vidyut-prakriya/src/atidesha.rs index 5fd7fec..c3ede5a 100644 --- a/vidyut-prakriya/src/atidesha.rs +++ b/vidyut-prakriya/src/atidesha.rs @@ -4,10 +4,10 @@ atidesha (1.2.1 - 1.2.17) */ use crate::args::Antargana; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::{Code, Prakriya}; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; use lazy_static::lazy_static; lazy_static! { @@ -31,29 +31,31 @@ impl<'a> AtideshaPrakriya<'a> { } fn optional(&mut self, rule: Code, func: impl Fn(&mut Prakriya)) { - self.added = self.p.run_optional(rule, func); + self.added = self.p.optional_run(rule, func); } fn optional_block(&mut self, rule: Code) { - self.added = self.p.run_optional(rule, |_| {}); + self.added = self.p.optional_run(rule, |_| {}); } fn add_nit(&mut self, rule: Code, i: usize) { - self.p.run_at(rule, i, op::add_tag(T::Nit)); + self.p.add_tag_at(rule, i, T::Nit); self.added = true; } fn optional_add_nit(&mut self, rule: Code, i: usize) { - self.added = self.p.run_optional_at(rule, i, |t| t.add_tag(T::Nit)); + self.added = self.p.optional_run_at(rule, i, |t| t.add_tag(T::Nit)); } fn add_kit(&mut self, rule: Code, i: usize) { - self.p.run_at(rule, i, op::add_tag(T::kit)); + self.p.add_tag_at(rule, i, T::kit); self.added = true; } fn optional_add_kit(&mut self, rule: Code, i: usize) { - self.added = self.p.run_optional_at(rule, i, |t| t.add_tag(T::kit)); + self.added = self.p.optionally(rule, |rule, p| { + p.add_tag_at(rule, i, T::kit); + }); } fn remove_kit(&mut self, rule: Code, i: usize) { @@ -62,7 +64,7 @@ impl<'a> AtideshaPrakriya<'a> { } fn optional_remove_kit(&mut self, rule: Code, i: usize) { - self.added = self.p.run_optional_at(rule, i, |t| t.remove_tag(T::kit)); + self.added = self.p.optional_run_at(rule, i, |t| t.remove_tag(T::kit)); } } @@ -71,17 +73,17 @@ fn try_add_nit(p: &mut Prakriya, i: usize) -> Option<()> { let mut ap = AtideshaPrakriya::new(p); let cur = ap.p.get(i)?; - let n = ap.p.view(i + 1)?; + let n = ap.p.pratyaya(i + 1)?; let apit = !n.has_tag(T::pit); - let iti = n.first()?.is_it_agama(); + let iti = n.first().is_it_agama(); let gan_kutadi = cur.has_u("gAN") || cur.has_antargana(Antargana::Kutadi); let i_n = n.end(); if gan_kutadi && !n.has_tag_in(&[T::Rit, T::Yit]) { ap.add_nit("1.2.1", i_n); } else if cur.has_u("vyaca~") - && n.last()?.is_krt() + && n.last().is_krt() && !n.has_tag_in(&[T::Rit, T::Yit]) && !n.has_u("asi~") { @@ -105,7 +107,7 @@ fn try_add_kit_for_various_pratyayas(p: &mut Prakriya, i: usize) -> Option let mut wrap = AtideshaPrakriya::new(p); let cur = wrap.p.get(i)?; - let n = wrap.p.view(i + 1)?; + let n = wrap.p.pratyaya(i + 1)?; if cur.is_agama() { return None; } @@ -124,12 +126,12 @@ fn try_add_kit_for_various_pratyayas(p: &mut Prakriya, i: usize) -> Option // Optional per Siddhanta-kaumudi. wrap.optional_add_kit("1.2.6.v1", i_n); } else if cur.has_text_in(&["mfq", "mfd", "guD", "kuz", "kliS", "vad", "vas"]) - && n.last()?.has_u("ktvA") + && n.last().has_u("ktvA") { // mfqitvA, mfditvA, ... wrap.add_kit("1.2.7", i_n); } else if cur.has_text_in(&["rud", "vid", "muz", "grah", "svap", "praC"]) - && n.last()?.has_u_in(&["ktvA", "san"]) + && n.last().has_u_in(&["ktvA", "san"]) { // ruditvA, viditvA, ..., rurutizati, vividizati, ... wrap.add_kit("1.2.8", i_n); @@ -148,7 +150,7 @@ fn try_add_kit_for_sic(p: &mut Prakriya, i: usize) -> Option { let mut wrap = AtideshaPrakriya::new(p); let cur = wrap.p.get(i)?; - let n = wrap.p.view(i + 1)?; + let n = wrap.p.pratyaya(i + 1)?; let last = wrap.p.terms().last()?; let i_n = n.end(); @@ -201,16 +203,16 @@ fn try_remove_kit_for_set_pratyaya(p: &mut Prakriya, i: usize) -> Option<()> { let mut wrap = AtideshaPrakriya::new(p); let cur = wrap.p.get(i)?; - let n = wrap.p.view(i + 1)?; + let n = wrap.p.pratyaya(i + 1)?; let i_n = n.end(); - if !n.first()?.is_it_agama() { + if !n.first().is_it_agama() { return None; } - let nistha = n.last()?.has_tag(T::Nistha); - let ktva = n.last()?.has_u("ktvA"); - let san = n.last()?.has_u("san"); + let nistha = n.last().has_tag(T::Nistha); + let ktva = n.last().has_u("ktvA"); + let san = n.last().has_u("san"); // TODO: 1.2.21 if (nistha || ktva) && cur.has_u("pUN") { @@ -285,7 +287,7 @@ pub fn run_before_attva(p: &mut Prakriya) { /// 4. iT-Agama (A) --> atidesha and samprasarana (A) pub fn run_after_attva(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; - let n = p.view(i + 1)?; + let n = p.pratyaya(i + 1)?; let i_tin = p.terms().len() - 1; let dhatu = p.get(i)?; diff --git a/vidyut-prakriya/src/atmanepada.rs b/vidyut-prakriya/src/atmanepada.rs index 3a96149..57a5561 100644 --- a/vidyut-prakriya/src/atmanepada.rs +++ b/vidyut-prakriya/src/atmanepada.rs @@ -12,10 +12,10 @@ //! *Atmanepada* to that pratyaya as appropriate. use crate::args::Gana; +use crate::core::Rule::Kaumudi; +use crate::core::Tag as T; +use crate::core::{Code, Prakriya, Rule}; use crate::dhatu_gana::{DYUT_ADI, VRT_ADI}; -use crate::prakriya::Rule::Kaumudi; -use crate::prakriya::{Code, Prakriya, Rule}; -use crate::tag::Tag as T; const GAMY_RCCHI: &[(&str, Gana)] = &[ ("ga\\mx~", Gana::Bhvadi), @@ -100,7 +100,7 @@ impl<'a> PadaPrakriya<'a> { /// Optionally marks this prakriya as AtmanepadI. fn optional_atma(&mut self, rule: impl Into) { - self.p.run_optional(rule, op_atmanepada); + self.p.optional_run(rule, op_atmanepada); } /// Marks this prakriya as parasmaipadI. @@ -110,13 +110,13 @@ impl<'a> PadaPrakriya<'a> { /// Marks this prakriya as parasmaipadI. fn optional_para(&mut self, rule: Code) { - self.p.run_optional(rule, op_parasmaipada); + self.p.optional_run(rule, op_parasmaipada); } } pub fn run(p: &mut Prakriya) -> Option<()> { if p.has_tag(T::Atmanepada) { - // E.g. if set by gana sutra (see `dhatu_karya`) + // E.g. if set by some gana sutra. See `dhatu_karya` for examples of this. return None; } @@ -255,7 +255,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { { // If this option is declined, we'll use the general rule below (1.3.74). Thus we get // BAyayati/BAyayate per the normal rules and BApayate/BIzayate if 1.3.68 is accepted. - pp.p.run_optional("1.3.68", |p| { + pp.p.optional_run("1.3.68", |p| { op_atmanepada(p); p.add_tag(T::FlagHetuBhaya); }); diff --git a/vidyut-prakriya/src/bin/create_krdantas.rs b/vidyut-prakriya/src/bin/create_krdantas.rs index fd5d3ab..d694f43 100644 --- a/vidyut-prakriya/src/bin/create_krdantas.rs +++ b/vidyut-prakriya/src/bin/create_krdantas.rs @@ -6,7 +6,7 @@ use clap::Parser; use serde::Serialize; use std::error::Error; use std::io; -use vidyut_prakriya::args::{KrdantaArgs, BaseKrt}; +use vidyut_prakriya::args::{BaseKrt, KrdantaArgs}; use vidyut_prakriya::{Ashtadhyayi, Dhatupatha}; #[derive(Parser)] diff --git a/vidyut-prakriya/src/bin/create_subantas.rs b/vidyut-prakriya/src/bin/create_subantas.rs index 22a47b4..495b0a3 100644 --- a/vidyut-prakriya/src/bin/create_subantas.rs +++ b/vidyut-prakriya/src/bin/create_subantas.rs @@ -23,7 +23,7 @@ fn dhatu_pratipadika(s: &str) -> Pratipadika { fn pum(s: &str) -> TestCase { TestCase { - pratipadika: Pratipadika::new(s), + pratipadika: Pratipadika::from(s), linga: Linga::Pum, } } @@ -60,14 +60,14 @@ fn stri_dhatu(s: &str) -> TestCase { fn stri_no_nyap(s: &str) -> TestCase { TestCase { - pratipadika: Pratipadika::new(s), + pratipadika: Pratipadika::from(s), linga: Linga::Stri, } } fn na(s: &str) -> TestCase { TestCase { - pratipadika: Pratipadika::new(s), + pratipadika: Pratipadika::from(s), linga: Linga::Napumsaka, } } @@ -267,8 +267,8 @@ fn run() -> Result<(), Box> { linga: linga.as_str(), vibhakti: vibhakti.as_str(), vacana: vacana.as_str(), - pratipadika: pratipadika.text(), - is_nyap: pratipadika.is_nyap(), + pratipadika: &pratipadika.text(), + is_nyap: pratipadika.needs_nyap(), is_dhatu: pratipadika.is_dhatu(), }; diff --git a/vidyut-prakriya/src/core.rs b/vidyut-prakriya/src/core.rs new file mode 100644 index 0000000..be341a2 --- /dev/null +++ b/vidyut-prakriya/src/core.rs @@ -0,0 +1,22 @@ +//! Core data structures and utility functions that support the rest of the system. +//! +//! The core modules here are: +//! +//! - `term`, which defines the `Term` struct +//! - `prakriya`, which defines the `Prakriya` struct + +pub mod char_view; +pub mod errors; +pub mod iterators; +pub mod operators; +pub mod prakriya_stack; + +mod prakriya; +mod tag; +mod term; +mod term_view; + +pub use prakriya::*; +pub use tag::*; +pub use term::*; +pub use term_view::*; diff --git a/vidyut-prakriya/src/char_view.rs b/vidyut-prakriya/src/core/char_view.rs similarity index 92% rename from vidyut-prakriya/src/char_view.rs rename to vidyut-prakriya/src/core/char_view.rs index 8d3de94..029892c 100644 --- a/vidyut-prakriya/src/char_view.rs +++ b/vidyut-prakriya/src/core/char_view.rs @@ -1,5 +1,5 @@ -use crate::prakriya::Prakriya; -use crate::term::Term; +use crate::core::Prakriya; +use crate::core::Term; use compact_str::CompactString; /// A wrapper for `Prakriya` that has stronger support for sound rules that apply within and across @@ -29,6 +29,11 @@ impl<'a> CharPrakriya<'a> { } } + /// Exits the `CharPrakriya` context and returns a reference to the original prakriya. + pub fn p(self) -> &'a mut Prakriya { + self.p + } + /// Iterates over all characters in the prakriya. If `filter` applies at some index `i`, this /// method applies `operator` to the same index `i`. /// @@ -179,6 +184,19 @@ pub fn get_at(p: &Prakriya, index: usize) -> Option<&Term> { None } +/// Gets the term corresponding to character `i` of the current prakriya. +pub fn get_term_index_at(p: &Prakriya, index: usize) -> Option { + let mut cur = 0; + for (i, t) in p.terms().iter().enumerate() { + let delta = t.text.len(); + if (cur..cur + delta).contains(&index) { + return Some(i); + } + cur += delta; + } + None +} + /// Helper function for iterating over a sliding window that is two characters long. pub fn xy(inner: impl Fn(char, char) -> bool) -> impl Fn(&mut Prakriya, &str, usize) -> bool { move |_, text, i| { diff --git a/vidyut-prakriya/src/errors.rs b/vidyut-prakriya/src/core/errors.rs similarity index 98% rename from vidyut-prakriya/src/errors.rs rename to vidyut-prakriya/src/core/errors.rs index c3f088c..f3d8d72 100644 --- a/vidyut-prakriya/src/errors.rs +++ b/vidyut-prakriya/src/core/errors.rs @@ -1,4 +1,4 @@ -use crate::prakriya::Prakriya; +use crate::core::Prakriya; use std::fmt; use std::io; use std::num; diff --git a/vidyut-prakriya/src/iterators.rs b/vidyut-prakriya/src/core/iterators.rs similarity index 92% rename from vidyut-prakriya/src/iterators.rs rename to vidyut-prakriya/src/core/iterators.rs index 028b51c..e6a333a 100644 --- a/vidyut-prakriya/src/iterators.rs +++ b/vidyut-prakriya/src/core/iterators.rs @@ -1,5 +1,5 @@ -use crate::prakriya::Prakriya; -use crate::term::Term; +use crate::core::Prakriya; +use crate::core::Term; /// Processes a sliding window of terms, where each term is non-empty. /// diff --git a/vidyut-prakriya/src/operators.rs b/vidyut-prakriya/src/core/operators.rs similarity index 90% rename from vidyut-prakriya/src/operators.rs rename to vidyut-prakriya/src/core/operators.rs index 3e3f0e9..0b27f39 100644 --- a/vidyut-prakriya/src/operators.rs +++ b/vidyut-prakriya/src/core/operators.rs @@ -21,21 +21,12 @@ closures. This approach gives us a terse and simple scheme for describing variou Rust's zero-cost abstractions ensure that there is no runtime penalty for juggling so many closures. */ +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::it_samjna; -use crate::prakriya::{Prakriya, Rule}; use crate::sounds as al; use crate::sounds::is_ac; -use crate::tag::Tag as T; -use crate::term::Term; - -/// Wraps a `Term` operator and converts it to a `Prakriya` operator. -pub fn t(i: usize, f: impl Fn(&mut Term)) -> impl Fn(&mut Prakriya) { - move |p| { - if let Some(t) = p.get_mut(i) { - f(t); - } - } -} // Substitution // ============ @@ -71,6 +62,10 @@ pub fn mit(sub: &'static str) -> impl Fn(&mut Term) { let text = &t.text; if let Some(i) = text.rfind(is_ac) { t.text.replace_range(i + 1..i + 1, sub); + } else { + // If no vowels, place at beginning of text. This is a HACK for when sounds are removed + // by "ekaH pUrvaparayoH". + t.text.replace_range(0..0, sub); } } } @@ -94,14 +89,6 @@ pub fn text(sub: &'static str) -> impl Fn(&mut Term) { move |t| t.text.replace_range(.., sub) } -pub fn upadesha_no_it(p: &mut Prakriya, i: usize, sub: &str) { - if let Some(t) = p.get_mut(i) { - t.save_lakshana(); - t.set_u(sub); - t.set_text(sub); - } -} - // Insertion of new terms // ====================== @@ -122,13 +109,11 @@ pub fn insert_agama_at(rule: impl Into, p: &mut Prakriya, index: usize, ag it_samjna::run(p, index).expect("ok"); } -// legacy func that marks the rule after it-samjna-prakarana. -pub fn upadesha(p: &mut Prakriya, i: usize, sub: &str) { +pub fn upadesha_no_it(p: &mut Prakriya, i: usize, sub: &str) { if let Some(t) = p.get_mut(i) { t.save_lakshana(); t.set_u(sub); t.set_text(sub); - it_samjna::run(p, i).expect("ok"); } } @@ -166,12 +151,15 @@ pub fn adesha(rule: impl Into, p: &mut Prakriya, i: usize, sub: &str) { } } -pub fn optional_adesha(rule: impl Into + Copy, p: &mut Prakriya, i: usize, sub: &str) { - if p.is_allowed(rule) { +pub fn optional_adesha( + rule: impl Into + Copy, + p: &mut Prakriya, + i: usize, + sub: &str, +) -> bool { + p.optionally(rule, |rule, p| { adesha(rule, p, i, sub); - } else { - p.decline(rule); - } + }) } pub fn yatha<'a>(needle: &str, old: &[&'a str], new: &[&'a str]) -> Option<&'a str> { @@ -238,7 +226,7 @@ pub fn add_tag(tag: T) -> impl Fn(&mut Term) { #[cfg(test)] mod tests { use super::*; - use crate::term::Term; + use crate::core::Term; #[test] fn test_adi() { diff --git a/vidyut-prakriya/src/prakriya.rs b/vidyut-prakriya/src/core/prakriya.rs similarity index 53% rename from vidyut-prakriya/src/prakriya.rs rename to vidyut-prakriya/src/core/prakriya.rs index dcf8e8f..4a66dae 100644 --- a/vidyut-prakriya/src/prakriya.rs +++ b/vidyut-prakriya/src/core/prakriya.rs @@ -1,6 +1,12 @@ -use crate::args::{Artha, Lakara}; -use crate::tag::Tag; -use crate::term::{Term, TermView}; +/*! +Manages the derivation state. + +Users interested in understanding this module should start by reading the comments on the +`Prakriya` struct, which manages a derivation from start to finish. +*/ +use crate::args::{Artha, Lakara, Pada, Pratipadika}; +use crate::core::Tag; +use crate::core::{Term, TermView}; use compact_str::CompactString; use enumset::EnumSet; @@ -10,31 +16,35 @@ pub type Code = &'static str; /// A rule applied in the prakriya. /// /// Most of a derivation's rules come directly from the Ashtadhyayi. But, some derivations use -/// rules from other sources. We use this model to clearly define which are which. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +/// rules from other sources. We use this model to clearly define where different rules come from. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum Rule { - /// A sutra from the Ashtadhyayi. + /// A sutra from the Ashtadhyayi. The string data here is an adhyaya-pada-sutra string, e.g. + /// "3.1.68". Ashtadhyayi(&'static str), - /// A comment in the Kashika-vrtti on a specific sutra. + /// A comment in the Kashika-vrtti on a specific sutra. The string data here is an + /// adhyaya-pada-sutra string that describes the sutra being commented on. Kashika(&'static str), - /// A sutra from the Dhatupatha. + /// A sutra from the Dhatupatha. The string data here is a gana-sutra string, e.g. "10.0493". Dhatupatha(&'static str), - /// A sutra from the Unadipatha. - UP(&'static str), - /// A sutra from the Paniniya-Linganushasanam. + /// A sutra from the Unadipatha. The string here is a gana-sutra string, e.g. "1.1". + Unadipatha(&'static str), + /// A sutra from the Paniniya-Linganushasanam. The string here is the sutra's position in the + /// text, e.g. "40". Linganushasana(&'static str), - /// A quotation from the Vaiyakarana-siddhanta-kaumudi. + /// A quotation from the Vaiyakarana-siddhanta-kaumudi. The string here is the position of the + /// sutra being commented on in Kaumudi order, e.g. "446". Kaumudi(&'static str), } impl Rule { - /// The string reprentation of this rule. + /// The string representation of this rule. pub fn code(&self) -> &'static str { match self { Self::Ashtadhyayi(x) => x, Self::Kashika(x) => x, Self::Dhatupatha(x) => x, - Self::UP(x) => x, + Self::Unadipatha(x) => x, Self::Linganushasana(x) => x, Self::Kaumudi(x) => x, } @@ -50,7 +60,13 @@ impl From<&'static str> for Rule { } /// Represents a step of the derivation. -#[derive(Debug)] +/// +/// A `Step` records both which rule was applied and the result of applying that rule. As of now, +/// we record a result as a simple `String`. In the future, we hope to convert `Step` into a richer +/// structure with more information about the specific change. For example, we might explicitly +/// indicate which term in the result was changed, which kind of rule was replied, and whether this +/// rule was optional. +#[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct Step { rule: Rule, result: String, @@ -63,19 +79,15 @@ impl Step { } /// The result of applying `rule`. - /// - /// For now, `result` is a simple string. In the future, we might convert this into a richer - /// structure with more information about the specific change. For example, we might explicitly - /// indicate which term in the result was changed. pub fn result(&self) -> &String { &self.result } } /// Records whether an optional rule was accepted or declined. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RuleChoice { - /// Indicates that a rule was applied during the derivation. + /// Indicates that a rule was accepted during the derivation. Accept(Rule), /// Indicates that a rule was declined during the derivation. Decline(Rule), @@ -83,7 +95,7 @@ pub enum RuleChoice { /// Configuration options that affect how a `Prakriya` behaves during the derivation. #[derive(Default, Debug)] -pub struct Config { +pub(crate) struct Config { pub rule_choices: Vec, pub log_steps: bool, pub is_chandasi: bool, @@ -96,6 +108,34 @@ impl Config { } /// Models a Paninian derivation. +/// +/// A derivation has two main parts: a *state* that describes what terms are present in the +/// derivation and a *history* that records which rules the derivation has used so far. +/// +/// +/// # State +/// +/// `Prakriya` manages the derivation state with a `Vec` that explicitly models all parts of +/// the derivation. Each `Term` is essentially a string that has been annotated with rich metadata. +/// `Prakriya` also contains important metadata that applies across the entire derivation (as +/// opposed to a specific term), such as whether the derivation as a whole expresses a certain +/// meaning condition. +/// +/// `Term` has an unstable API and is not ready to be exposed publicly. For details on what `Term` +/// contains, see the crate-internal `term` module. +/// +/// +/// # History +/// +/// `Prakriya` manages the history state with a `Vec` that record which rules have been +/// applied and with which results. In addition, it manages a `Vec` that records which +/// optional rules the derivation has encountered and which choices the derivation has made for +/// those rules. +/// +/// `Prakriya` also records various config options from the `Ashtadhyayi` object that created it. +/// For example, we might want the derivation to use *chandasi* rules, or we might wish to block +/// such rules. Or, we might want to skip history logging so that we can generate words more +/// quickly. #[derive(Default, Debug)] pub struct Prakriya { terms: Vec, @@ -103,14 +143,15 @@ pub struct Prakriya { history: Vec, artha: Option, config: Config, - rule_decisions: Vec, + rule_choices: Vec, lakara: Option, } /// Public API +/// ========== impl Prakriya { - /// Returns the current state of the derivation. If the derivation is complete, `text()` will - /// thus represent the derivation's final output, which is a complete Sanskrit *pada*. + /// Returns a string representation of the current derivation state. If the derivation is + /// complete, `text()` will thus represent the derivation's final output. pub fn text(&self) -> String { let mut ret = String::from(""); for t in &self.terms { @@ -122,7 +163,7 @@ impl Prakriya { /// Returns all of the optional rules that were encountered during the derivation and whether /// they were accepted or rejected. pub fn rule_choices(&self) -> &Vec { - &self.rule_decisions + &self.rule_choices } /// Returns all of the rules that were applied during the derivation and the output of each @@ -132,14 +173,39 @@ impl Prakriya { &self.history } - /// (experimental) Returns the semantic condition (artha) under which this prakriya was + /// (experimental) Returns the semantic condition (artha) under which this derivation was /// created. pub fn artha(&self) -> Option { self.artha } } -/// Crate-only API +/// Private API +/// =========== +/// +/// `Prakriya` has a rich API that we have designed under two main constraints: +/// +/// 1. We want a concise way to model the thousands of rules in the Ashtadhyayi and its related +/// texts. This API helps not only with our ability to implement rules quickly but also with readability. +/// +/// 2. We want a compositional API that lets us model various combinations of optionality, scope +/// (i.e. over a term or over a prakriya), and complexity (i.e. a single rule or a block of +/// rules). +/// +/// The main method for mutating the derivation is `run`, which applies an arbitrary change to the +/// prakriya then record the change in the derivation history. We also provide `run_at` as a +/// conveninece method to change just one term. We manage optional rules with an `optionally` +/// method that works as follows: +/// +/// ```rust,ignore +/// # use vidyut_prakriya::{Prakriya, Tag}; +/// // Mark that `prakriya` contains a dhatu that should accept an atmanepada-pratyaya. +/// prakriya.optionally("1.2.3", |rule, p| { +/// p.run(rule, |p| p.add_tag(Tag::Atmanepada)); +/// }) +/// ``` +/// +/// But for convenience, we have also defined `run_optional` and `run_optional_at`. impl Prakriya { /// Creates an empty prakriya. pub(crate) fn new() -> Self { @@ -149,12 +215,14 @@ impl Prakriya { history: Vec::new(), artha: None, config: Config::new(), - rule_decisions: Vec::new(), + rule_choices: Vec::new(), lakara: None, } } - /// Like `text` but creates a CompactString. + /// Like `text` but creates a `CompactString`. + /// + /// `CompactString` is an implementation detail that we don't wish to expose in the public API. pub(crate) fn compact_text(&self) -> CompactString { let mut ret = CompactString::from(""); for t in &self.terms { @@ -212,9 +280,10 @@ impl Prakriya { /// Returns whether the term at the given index can be called "pada". /// - /// A term can be called `pada` iff: - /// - it has the pada-samjna; - /// - it is followed by one or more consecutive empty terms, the last of which is a pada. + /// A term X can be called `pada` iff: + /// - X has the pada-samjna; + /// - there is a term Y with the pada-samjna such that X comes before Y and all terms between X + /// and Y are empty. pub(crate) fn is_pada(&self, i: usize) -> bool { if let Some(t) = self.get(i) { if t.is_pada() { @@ -236,8 +305,8 @@ impl Prakriya { } } - pub(crate) fn view(&self, i: usize) -> Option { - TermView::new(self.terms(), i) + pub(crate) fn custom_view(&self, start: usize, end: usize) -> Option { + TermView::new(self.terms(), start, end) } /// Returns the index of the first `Term` that matches the predicate function `f` or `None` if @@ -292,6 +361,10 @@ impl Prakriya { } } + pub(crate) fn find_next_not_empty(&self, index: usize) -> Option { + self.find_next_where(index, |t| !t.is_empty()) + } + pub(crate) fn find_last_where(&self, f: impl Fn(&Term) -> bool) -> Option { for (i, t) in self.terms.iter().enumerate().rev() { if f(t) { @@ -313,7 +386,7 @@ impl Prakriya { } /// Finds the term that contains the char at index `i_char` in `self.text()`. - pub fn find_for_char_at(&self, i_char: usize) -> Option { + pub(crate) fn find_for_char_at(&self, i_char: usize) -> Option { let mut cur = 0; for (i, t) in self.terms().iter().enumerate() { let delta = t.text.len(); @@ -326,7 +399,7 @@ impl Prakriya { } /// Replaces character `i` of the current prakriya with the given substitute. - pub fn set_char_at(&mut self, i_char: usize, substitute: &str) { + pub(crate) fn set_char_at(&mut self, i_char: usize, substitute: &str) { let mut cur = 0; for t in self.terms_mut() { let delta = t.text.len(); @@ -339,6 +412,23 @@ impl Prakriya { } } + /// Sets the penultimate sound within the range `[start, end]` to the given value. + pub(crate) fn set_upadha_within_range(&mut self, start: usize, end: usize, substitute: &str) { + debug_assert!(start <= end); + + let mut cur = 0; + let nth_rev = 1; + for t in self.terms[start..=end].iter_mut().rev() { + for (i_char, _) in t.text.bytes().enumerate().rev() { + if cur == nth_rev { + t.text.replace_range(i_char..=i_char, substitute); + return; + } + cur += 1; + } + } + } + // Filters /// Returns whether a term exists at `index` and matches the condition in `filter`. @@ -364,6 +454,64 @@ impl Prakriya { tags.iter().any(|t| self.tags.contains(*t)) } + /// Creates a pada view whose last index is `i_end`. + pub(crate) fn pada(&self, i_end: usize) -> Option { + let t = self.get(i_end)?; + if t.is_sup() || t.is_tin() { + TermView::new(&self.terms(), 0, i_end) + } else { + None + } + } + + /// Creates a nyAp/pratipadika view whose last index is `i_end`. + /// + /// The pratipadika-samjna technically does not include the nyAp-pratyayas. But, most rules + /// that deal with pratipadikas also want access to terms ending in nyAp-pratyayas per rule + /// 4.1.2 (NyAp-prAtipadikAt). So, this method returns both pratipadikas and nyAp-antas. + pub(crate) fn nyap_pratipadika(&self, i_end: usize) -> Option { + let t = self.get(i_end)?; + if t.is_pratipadika_or_nyap() { + TermView::new(&self.terms(), 0, i_end) + } else { + None + } + } + + /// Creates a pratyaya view whose first index is `i_start`. + /// + /// (This is a legacy API.) + pub(crate) fn pratyaya(&self, i_start: usize) -> Option { + TermView::with_start(self.terms(), i_start) + } + + /// Returns whether the prakriya contains a pratipadika with value `text` that ends at index `i`. + /// + /// A simple pratipadika exists in exactly one term, but a more complex pratipadika (krdanta, + /// a taddhitanta, or a samasa) can extend over multiple terms. This method is a unified API + /// that checks for either type of pratipadika. + pub(crate) fn has_pratipadika(&self, index: usize, text: &str) -> bool { + // Strategy: iterate backward term by term until we have matched all chars in `text`. If + // there is any mismatch, return false. + let mut offset = text.len(); + for i in (0..=index).rev() { + let t = self.get(i).expect("present"); + let slice = &text[0..offset]; + if slice.ends_with(t.text.as_str()) { + // No risk of overflow here because `t.text` is at least as long as `slice`. + offset -= t.text.len(); + if offset == 0 { + return true; + } + } else { + // No match. + break; + } + } + + false + } + // Basic mutators /// Adds a tag to the prakriya. @@ -372,7 +520,7 @@ impl Prakriya { } /// Returns whether the prakriya has the given artha. - pub(crate) fn has_artha(&mut self, artha: Artha) -> bool { + pub(crate) fn has_artha(&self, artha: Artha) -> bool { self.artha == Some(artha) } @@ -419,6 +567,13 @@ impl Prakriya { self.terms.push(t); } + /// Adds the given term to the end of the term list. + pub(crate) fn extend(&mut self, terms: &[Term]) { + for t in terms { + self.terms.push(t.clone()); + } + } + pub(crate) fn maybe_save_sthanivat(&mut self) { for i in 0..self.terms().len() { let t = self.get_mut(i).expect("ok"); @@ -430,22 +585,27 @@ impl Prakriya { // Rule application - /// Runs the given operator. - pub(crate) fn run(&mut self, code: impl Into, operator: impl Fn(&mut Prakriya)) -> bool { - operator(self); - self.step(code); + /// Runs `func` on the `Prakriya` then records `rule` in the derivation history. + /// + /// `rule` will be recorded regardless of whether or not `operator` caused any changes. + /// + /// Returns: `true`. We return a boolean value for consistency with functions like + /// `run_optional`. + pub(crate) fn run(&mut self, rule: impl Into, func: impl Fn(&mut Prakriya)) -> bool { + func(self); + self.step(rule); true } - /// Applies the given operator to the given term. + /// Runs `func` on the term at `index` then records `rule` in the derivation history. pub(crate) fn run_at( &mut self, rule: impl Into, index: usize, - operator: impl Fn(&mut Term), + func: impl Fn(&mut Term), ) -> bool { if let Some(term) = self.get_mut(index) { - operator(term); + func(term); self.step(rule.into()); true } else { @@ -453,41 +613,62 @@ impl Prakriya { } } - /// Applies the given operator optionally. + /// Adds `tag` to the term at `index` then records `rule` in the derivation history. + /// + /// In the future, we might use this method to annotate which rules are samjna rules. + pub(crate) fn add_tag_at(&mut self, rule: impl Into, index: usize, tag: Tag) { + self.run_at(rule.into(), index, |t| t.add_tag(tag)); + } + + /// Runs `func` optionally and records whether the option was accepted or rejected. /// - /// Returns: whether the operation was applied. This return value is required for certain - /// complex conditions (e.g. 6.4.116 & 117; "if this rule was not applied, ..."). - pub(crate) fn run_optional( + /// Returns: whether the option was accepted. + pub(crate) fn optionally( &mut self, rule: impl Into, - operator: impl Fn(&mut Prakriya), + func: impl FnOnce(Rule, &mut Prakriya), ) -> bool { let rule = rule.into(); if self.is_allowed(rule) { - self.run(rule, operator) + func(rule, self); + true } else { self.decline(rule); false } } - /// Applies the given operator to the given term. - pub(crate) fn run_optional_at( + /// Optionally runs `func` on the `Prakriya`. If `func` was applied, records `rule` in the + /// derivation history. + /// + /// Returns: whether `func` was applied. This return value is required for certain complex + /// conditions (e.g. 6.4.116 & 117; "if this rule was not applied, ..."). + pub(crate) fn optional_run( + &mut self, + rule: impl Into, + func: impl Fn(&mut Prakriya), + ) -> bool { + self.optionally(rule, |rule, p| { + p.run(rule, func); + }) + } + + /// Optionally runs `func` on the term at `index`. If `func` was applied, records `rule` in the + /// derivation history. + /// + /// Returns: whether `func` was applied. + pub(crate) fn optional_run_at( &mut self, rule: impl Into, index: usize, operator: impl Fn(&mut Term), ) -> bool { - let rule = rule.into(); - if self.is_allowed(rule) { - self.run_at(rule, index, operator) - } else { - self.decline(rule); - false - } + self.optionally(rule, |rule, p| { + p.run_at(rule, index, operator); + }) } - /// Adds a rule and its result to the history. + /// Adds `rule` and the current derivation state to the derivation history. pub(crate) fn step(&mut self, rule: impl Into) { if self.config.log_steps { let state = self.terms.iter().fold(String::new(), |a, b| { @@ -523,10 +704,8 @@ impl Prakriya { #[cfg(debug_assertions)] pub(crate) fn dump(&mut self) { let n = self.terms().len(); - self.debug(format!("p: {:?}", self.tags)); - for i in 0..n { - self.debug(format!("{i}: {:?}", self.terms()[i])); - } + self.debug(format!("tags: {:?}", self.tags)); + self.debug(format!("{:#?}", self.terms())); } #[allow(unused)] @@ -564,10 +743,38 @@ impl Prakriya { } pub(crate) fn accept(&mut self, rule: impl Into) { - self.rule_decisions.push(RuleChoice::Accept(rule.into())); + self.rule_choices.push(RuleChoice::Accept(rule.into())); } pub(crate) fn decline(&mut self, rule: impl Into) { - self.rule_decisions.push(RuleChoice::Decline(rule.into())); + self.rule_choices.push(RuleChoice::Decline(rule.into())); + } +} + +impl From for Option { + /// (experimental) Converts this prakriya to a `Pratipadika`. + fn from(p: Prakriya) -> Self { + Pratipadika::from_terms(p.terms) + } +} + +impl From<&Prakriya> for Option { + /// (experimental) Converts this prakriya to a `Pratipadika`. + fn from(p: &Prakriya) -> Self { + Pratipadika::from_terms(p.terms.clone()) + } +} + +impl From for Option { + /// (experimental) Converts this prakriya to a `Pratipadika`. + fn from(p: Prakriya) -> Self { + Pada::from_terms(p.terms) + } +} + +impl From<&Prakriya> for Option { + /// (experimental) Converts this prakriya to a `Pratipadika`. + fn from(p: &Prakriya) -> Self { + Pada::from_terms(p.terms.clone()) } } diff --git a/vidyut-prakriya/src/prakriya_stack.rs b/vidyut-prakriya/src/core/prakriya_stack.rs similarity index 97% rename from vidyut-prakriya/src/prakriya_stack.rs rename to vidyut-prakriya/src/core/prakriya_stack.rs index 0f28315..6427b96 100644 --- a/vidyut-prakriya/src/prakriya_stack.rs +++ b/vidyut-prakriya/src/core/prakriya_stack.rs @@ -1,5 +1,5 @@ -use crate::errors::*; -use crate::prakriya::{Config, Prakriya, RuleChoice}; +use crate::core::errors::*; +use crate::core::{Config, Prakriya, RuleChoice}; /// Explores all optional derivations for some input. /// diff --git a/vidyut-prakriya/src/tag.rs b/vidyut-prakriya/src/core/tag.rs similarity index 89% rename from vidyut-prakriya/src/tag.rs rename to vidyut-prakriya/src/core/tag.rs index 444f3d2..abe70ee 100644 --- a/vidyut-prakriya/src/tag.rs +++ b/vidyut-prakriya/src/core/tag.rs @@ -1,4 +1,4 @@ -use crate::errors::*; +use crate::core::errors::*; use enumset::EnumSetType; /// An annotation on some `Term`. @@ -7,9 +7,14 @@ use enumset::EnumSetType; /// and other long-term dependencies that we need to track during the derivation, such as whether /// guna was performed in an earlier rule. /// -/// We use Rust's `enumset` crate to efficiently store tags in an unsigned 128-bit integer. The -/// constraint of `enumset` is that we are allowed at most 128 tags. For now we are well under that -/// limit, but if needed, we can explore other options. +/// We use Rust's `enumset` crate to efficiently store tags in an array of unsigned integers. +/// +/// +/// # Naming conventions +/// +/// We allow non-camel-case names so that we can name specific `Tag`s according to SLP1 +/// conventions. Doing so lets us more easily distinguish among `Tag`s like `Nit`, `Yit`, Rit`, and +/// `nit`. #[allow(non_camel_case_types)] #[derive(Debug, EnumSetType)] pub enum Tag { @@ -21,6 +26,10 @@ pub enum Tag { Avyaya, Agama, Pratyaya, + + Samasa, + Upasarjana, + Unadi, Pratipadika, Vibhakti, @@ -28,13 +37,17 @@ pub enum Tag { Sarvanamasthana, Tin, La, + Nipata, Nistha, Krt, Krtya, Sup, + Nyap, Taddhita, Vikarana, + // it-samjnas + // ========== /// Placeholder *it* with no specific meaning. adit, /// (pratyaya) prevents it-agama for nisthA pratyayas per 7.2.16 but allows it optionally in @@ -57,8 +70,10 @@ pub enum Tag { /// (dhatu) indicates replacement of the "t" of a nistha-pratyaya with "n" per 8.2.45 (lagta -> /// lagna). odit, - /// (pratyaya) prevents guna and vrddhi. Causes samprasarana for vac-Adi roots (vac -> ukta) - /// per 6.1.15 and grah-Adi roots (grah -> gfhIta) per 6.1.16. + /// (krt) prevents guna and vrddhi. Causes samprasarana for vac-Adi roots (vac -> ukta) per + /// 6.1.15 and grah-Adi roots (grah -> gfhIta) per 6.1.16. + /// + /// (taddhita) causes vrddhi per 7.2.118. Indicates antodAtta per 6.1.165. /// /// (agama) indicates that the Agama should be added after the term, per 1.1.46. kit, @@ -117,11 +132,10 @@ pub enum Tag { /// /// (pratyaya) marks the pratyaya as sArvadhAtuka per 3.4.113. Sit, - /// (pratyaya) + /// (pratyaya) uses NIz-pratyaya in strI-linga per 4.1.41. zit, /// (pratyaya) indicates that the previous term should be called `pada` per 1.4.16. sit, - /// (dhatu) indicates the optional use of aN-pratyaya in luN-lakAra per 3.1.57. irit, /// (dhatu) indicates that kta-pratyaya denotes the present tense as opposed to the past tense. @@ -186,6 +200,11 @@ pub enum Tag { V6, V7, + // Vibhakti conditions + Sambodhana, + Amantrita, + Sambuddhi, + // Linga (subanta) Pum, Stri, @@ -195,12 +214,8 @@ pub enum Tag { Nadi, Ghi, - // Vibhakti conditions - Sambodhana, - Amantrita, - Sambuddhi, - // Dvitva + /// The doubled Abhyasa, Abhyasta, @@ -218,8 +233,12 @@ pub enum Tag { FlagGunaApavada, FlagGuna, + FlagTrjvat, + // Flags on the `Prakriya`. - FlagAdeshadi, + FlagNaAdeshadi, + FlagSaAdeshadi, + FlagNum, FlagNoArdhadhatuka, FlagHasAnitKsa, FlagHagSetSic, @@ -241,9 +260,13 @@ pub enum Tag { FlagNoDirgha, // Indicates replacement of f/F with f (acIkftat, ...). FlagUrRt, + /// Indicates use of UW-adesha. + FlagUth, Sankhya, Sat, + // zRAntA zat + zaw, /// Indicates the insertion of `na` through the Snam-vikarana. Snam, @@ -253,6 +276,14 @@ pub enum Tag { /// A sound whose first vowel is vrddhi. Vrddha, + // Compound types (prakriya-only) + Avyayibhava, + Tatpurusha, + Karmadharaya, + Bahuvrihi, + Dvandva, + Samahara, + StriNyap, TrnTrc, Pada, @@ -261,9 +292,12 @@ pub enum Tag { Dvitva, Gha, + Pragrhya, + Complete, + // Indicates that a derivation phase is complete, e.g. to avoid running abhyAsa rules // twice. - Complete, + Final, /// Indicates use of ru-Adesha. Ru, diff --git a/vidyut-prakriya/src/term.rs b/vidyut-prakriya/src/core/term.rs similarity index 73% rename from vidyut-prakriya/src/term.rs rename to vidyut-prakriya/src/core/term.rs index 882bd6a..e2e6bcf 100644 --- a/vidyut-prakriya/src/term.rs +++ b/vidyut-prakriya/src/core/term.rs @@ -1,8 +1,8 @@ -use crate::args::{Antargana, Gana}; +use crate::args::{Antargana, Gana, Unadi}; +use crate::core::Tag; use crate::sounds; use crate::sounds::Pattern; use crate::sounds::{s, Set}; -use crate::tag::Tag; use compact_str::CompactString; use enumset::EnumSet; @@ -12,18 +12,36 @@ lazy_static! { static ref AC: Set = s("ac"); } -/// `Term` is a text string with additional metadata. It is a generalized version of an *upadesha* -/// that also stores abhyAsas and other strings that don't have an upadesha associated with them. -#[derive(Clone, Debug, Eq, PartialEq)] +/// A string with additional metadata. +/// +/// A typical prakriya uses various kinds of terms. For example, the prakriya for *cakAra* contains +/// an abhyasa, a dhatu, and a pratyaya. All of these terms likewise have their own metadata. For +/// example, the *a* at the end of *cakAra* conveys uttama-purusha and eka-vacana, and it is also a +/// tin-pratyaya that has replaced an earlier *tip*-pratyaya. +/// +/// `Term` is a general-purpose struct that manages these strings and their associated metadata. +/// Its main field is `text`, a `CompactString` that is more memory-efficient than a standard +/// `String`. +/// +/// Most of a `Term`'s metadata is stored in `tags`, a memory-efficient set of `Tag` values. `Tag` +/// generalizes the *samjna* concept and also stores other metadata that we have found useful for +/// deriving words. For details, see the documentation in the `tag` module. +/// +/// `Term` provides a rich API that is concise yet readable. Almost all mutations to a `Prakriya` +/// occur through the use of the `Term` API. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Term { - /// The *upadesha* of this term, if one exists. + /// The *aupadeshika* form of this term, if one exists. + /// + /// The *aupadeshka* text contains anubandhas, accent, and other "meta" terms that define + /// various properties in the grammar. We store all of this metadata on the `Term`'s `tags` + /// field. /// - /// The *upadesha* contains anubandhas, accent, and other "meta" terms that define various - /// properties in the grammar. This field is changed only when there is a full substitution, - /// e.g. substitution of `ktvA` with `lyap`. - pub u: Option, + /// This field is changed only when there is a full substitution, e.g. substitution of `ktvA` + /// with `lyap`. + pub(crate) u: Option, /// The text of this term. This string contains sound changes such as guna, vrddhi, lopa, etc. - pub text: CompactString, + pub(crate) text: CompactString, /// The form of the term to use for sthAnivad-bhAva substitutions, e.g. for dvitva on the /// dhatu. For example, when applying dvitva for BAvi, the abhyasa should be BO, not BAv. /// @@ -243,12 +261,12 @@ impl Term { // Samjna properties // ----------------- - /// Returns whether the term is an abhyAsa. + /// Returns whether the term has the `abhyAsa` samjna. pub fn is_abhyasa(&self) -> bool { self.has_tag(Tag::Abhyasa) } - /// Returns whether the term is an abhyasta. + /// Returns whether the term has the `abhyasta` samjna. pub fn is_abhyasta(&self) -> bool { self.has_tag(Tag::Abhyasta) } @@ -273,11 +291,33 @@ impl Term { self.has_tag(Tag::Avyaya) } - /// Returns whether the term has the `Dhatu` samjna. + /// Returns whether the term is "final," i.e. whether it has been through at least one full + /// pass of the grammar. + /// + /// We track "finality" so that we can avoid re-running rules on terms where doing so makes no + /// sense. + /// + /// Examples: + /// - We should not change the Qa of rUQA to eya (7.1.2). + /// - We should not change the DO of DOta to DA (6.1.45). + pub fn is_final(&self) -> bool { + self.has_tag(Tag::Final) + } + + pub fn is_ekavacana(&self) -> bool { + self.has_tag(Tag::Ekavacana) + } + + /// Returns whether the term has the `dhatu` samjna. pub fn is_dhatu(&self) -> bool { self.has_tag(Tag::Dhatu) } + /// Returns whether the term has the `Gati` samjna. + pub fn is_gati(&self) -> bool { + self.has_tag(Tag::Gati) + } + /// Returns whether the term is kit or Nit. pub fn is_knit(&self) -> bool { self.has_tag_in(&[Tag::kit, Tag::Nit]) @@ -288,11 +328,26 @@ impl Term { self.has_tag(Tag::Krt) } + /// Returns whether the term has the `Krtya` samjna. + pub fn is_krtya(&self) -> bool { + self.has_tag(Tag::Krtya) + } + + /// Returns whether the term has undergone lopa (1.1.60) + pub fn is_lupta(&self) -> bool { + self.has_tag_in(&[Tag::Luk, Tag::Slu, Tag::Lup]) + } + /// Returns whether the term is `Ric` or `RiN`. pub fn is_ni_pratyaya(&self) -> bool { self.has_u_in(&["Ric", "RiN"]) } + /// Returns whether the term has the `Krt` samjna. + pub fn is_nipata(&self) -> bool { + self.has_tag(Tag::Nipata) + } + /// Returns whether the term is a nistha. pub fn is_nistha(&self) -> bool { self.has_tag(Tag::Nistha) @@ -315,20 +370,44 @@ impl Term { self.has_tag(Tag::Pratipadika) } + /// Returns whether the term has the `Pratipadika` samjna or is a nyAp-pratyaya. + pub fn is_pratipadika_or_nyap(&self) -> bool { + self.has_tag(Tag::Pratipadika) || self.is_nyap_pratyaya() + } + /// Returns whether the term has the `Pratyaya` samjna. pub fn is_pratyaya(&self) -> bool { self.has_tag(Tag::Pratyaya) } + /// Returns whether the term has the `Sankhya` samjna. + pub fn is_sankhya(&self) -> bool { + self.has_tag(Tag::Sankhya) + } + /// Returns whether the term is an unAdi-pratyaya. pub fn is_unadi(&self) -> bool { self.has_tag(Tag::Unadi) } + /// Returns whether the term is an unAdi-pratyaya. + pub fn has_unadi(&self, unadi: Unadi) -> bool { + self.has_tag(Tag::Unadi) && self.has_u(unadi.as_str()) + } + + pub fn is_aap_pratyaya(&self) -> bool { + self.has_tag(Tag::Pratyaya) && self.has_u_in(&["dAp", "wAp", "cAp"]) + } + pub fn is_nyap_pratyaya(&self) -> bool { self.has_tag(Tag::Pratyaya) && self.has_u_in(&["wAp", "cAp", "dAp", "NIp", "NIz"]) } + /// Returns whether the term has the `Taddhita` samjna. + pub fn is_samasa(&self) -> bool { + self.has_tag(Tag::Samasa) + } + /// Returns whether the term has the `Sarvanama` samjna. pub fn is_sarvadhatuka(&self) -> bool { self.has_tag(Tag::Sarvadhatuka) @@ -354,6 +433,11 @@ impl Term { self.has_tag(Tag::Taddhita) } + /// Returns whether the term has the `Sup` samjna. + pub fn is_tin(&self) -> bool { + self.has_tag(Tag::Tin) + } + /// Returns whether the term is an upasarga. pub fn is_upasarga(&self) -> bool { self.has_tag(Tag::Upasarga) @@ -412,6 +496,7 @@ impl Term { } /// Returns whether the first syllable of the term is or could be laghu. + #[allow(dead_code)] pub fn is_laghu_adi(&self) -> bool { let mut had_ac = false; let mut num_consonants = 0; @@ -577,237 +662,3 @@ impl Term { } } } - -/// A `Term` with its Agamas. -/// -/// `TermView` bundles a `Term` with its agamas. -/// -/// # Construction rules -/// TODO. -/// -/// # Examples -/// - isIDvam [i + sIyu~w + Dvam] -/// - isya [i + sya] -#[derive(Debug)] -pub struct TermView<'a> { - terms: &'a Vec, - start: usize, - end: usize, -} - -impl<'a> TermView<'a> { - pub fn new(terms: &'a Vec, start: usize) -> Option { - if start >= terms.len() { - return None; - } - - let mut end = start; - for (i, t) in terms.iter().enumerate().filter(|(i, _)| *i >= start) { - // A `kit` Agama is part of the term it follows, i.e. there is no view available here. - // Exception: iw-Agama marked as kit. - if i == start && t.has_all_tags(&[Tag::Agama, Tag::kit]) && !t.has_u("iw") { - return None; - } - - if !t.has_tag(Tag::Agama) { - end = i; - break; - } - } - Some(TermView { terms, start, end }) - } - - // Accessors - - pub fn slice(&self) -> &[Term] { - &self.terms[self.start..=self.end] - } - - pub fn first(&self) -> Option<&Term> { - self.terms.get(self.start) - } - - pub fn last(&self) -> Option<&Term> { - self.terms.get(self.end) - } - - pub fn start(&self) -> usize { - self.start - } - - #[allow(unused)] - pub fn get(&self, i: usize) -> Option<&Term> { - self.slice().get(i) - } - - pub fn end(&self) -> usize { - self.end - } - - #[allow(unused)] - pub fn is_padanta(&self) -> bool { - self.is_empty() && self.ends_word() - } - - /// Returns whether this view has any text. - #[allow(unused)] - pub fn is_empty(&self) -> bool { - self.slice().iter().all(|t| t.text.is_empty()) - } - - /// Returns whether this view is at the very end of the given word. - #[allow(unused)] - pub fn ends_word(&self) -> bool { - self.end == self.terms.len() - 1 - } - - fn matches_sound_pattern(&self, c: Option, pattern: impl Pattern) -> bool { - match c { - Some(c) => pattern.matches(c), - None => false, - } - } - - pub fn adi(&self) -> Option { - for t in self.slice() { - match t.adi() { - Some(c) => return Some(c), - None => continue, - } - } - None - } - - #[allow(unused)] - pub fn antya(&self) -> Option { - for t in self.slice().iter().rev() { - match t.antya() { - Some(c) => return Some(c), - None => continue, - } - } - None - } - - pub fn has_adi(&self, pattern: impl Pattern) -> bool { - self.matches_sound_pattern(self.adi(), pattern) - } - - #[allow(unused)] - pub fn has_antya(&self, pattern: impl Pattern) -> bool { - self.matches_sound_pattern(self.antya(), pattern) - } - - pub fn has_u(&self, u: &str) -> bool { - match self.slice().first() { - Some(t) => t.has_u(u), - None => false, - } - } - - pub fn has_u_in(&self, us: &[&str]) -> bool { - match self.slice().first() { - Some(t) => t.has_u_in(us), - None => false, - } - } - - pub fn has_tag(&self, tag: Tag) -> bool { - self.slice().iter().any(|t| t.has_tag(tag)) - } - - pub fn has_lakshana(&self, s: &str) -> bool { - self.slice().iter().any(|t| t.has_lakshana(s)) - } - - pub fn has_lakshana_in(&self, items: &[&str]) -> bool { - self.slice().iter().any(|t| t.has_lakshana_in(items)) - } - - pub fn all(&self, tags: &[Tag]) -> bool { - for tag in tags { - if self.slice().iter().any(|t| t.has_tag(*tag)) { - continue; - } - return false; - } - true - } - - pub fn has_tag_in(&self, tags: &[Tag]) -> bool { - tags.iter() - .any(|tag| self.slice().iter().any(|t| t.has_tag(*tag))) - } - - pub fn is_knit(&self) -> bool { - self.has_tag_in(&[Tag::kit, Tag::Nit]) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn gam() -> Term { - let mut t = Term::make_upadesha("gamx~"); - t.set_text("gam"); - t - } - - #[test] - fn test_make_upadesha() { - let t = gam(); - assert!(t.has_u("gamx~")); - assert!(t.has_text("gam")); - } - - #[test] - fn test_sound_selectors() { - let t = gam(); - - assert_eq!(t.adi(), Some('g')); - assert_eq!(t.upadha(), Some('a')); - assert_eq!(t.antya(), Some('m')); - - assert_eq!(t.get_at(0), Some('g')); - assert_eq!(t.get_at(1), Some('a')); - assert_eq!(t.get_at(2), Some('m')); - assert_eq!(t.get_at(3), None); - } - - #[test] - fn is_laghu() { - let term = Term::make_text; - - assert!(term("i").is_laghu()); - assert!(term("vid").is_laghu()); - assert!(!term("BU").is_laghu()); - assert!(!term("uC").is_laghu()); - assert!(!term("IS").is_laghu()); - assert!(!term("Ikz").is_laghu()); - } - - #[test] - fn test_properties() { - let t = gam(); - - assert!(t.has_adi('g')); - assert!(t.has_upadha('a')); - assert!(t.has_antya('m')); - assert!(!t.is_empty()); - } - - #[test] - fn test_mutators() { - let mut t = gam(); - - assert!(t.has_text("gam")); - t.set_adi("x"); - t.set_upadha("y"); - t.set_antya("z"); - assert!(t.has_adi('x')); - assert!(t.has_upadha('y')); - assert!(t.has_antya('z')); - assert!(t.has_text("xyz")); - } -} diff --git a/vidyut-prakriya/src/core/term_view.rs b/vidyut-prakriya/src/core/term_view.rs new file mode 100644 index 0000000..2360de8 --- /dev/null +++ b/vidyut-prakriya/src/core/term_view.rs @@ -0,0 +1,348 @@ +use crate::core::Tag; +use crate::core::Term; +use crate::sounds::Pattern; + +/// A view over multiple terms. +/// +/// `Prakriya` models a derivation as a sequence of `Term`s, where each `Term` stores a string with +/// its associated metadata. At times, however, we might wish to work with a *sequence* of +/// associated terms instead. Some examples: +/// +/// - a pratipadika with its strI-pratyaya (kumAr + I) +/// - a dhatu with its krt-pratyaya (kf + ta) +/// - a pratyaya with its Agamas (I + sIy + Dvam) +/// - a pada with all of its components (ci + kIr + z + a + ti) +/// +/// `TermView` provides an API for working with these sequences. It provides a simple API that +/// mirrors the `Term` API, and it provides raw access to its underlying `Term`s as escape hatches. +/// +/// Instead of creating TermView directly, we recommend using the [`pada`], [`nyap_pratipadika`], +/// or [`pratyaya`] methods on `Prakriya. +/// +/// [`pada`]: Prakriya::get +/// [`nyap_pratipadika`]: Prakriya::nyap_pratipadika +/// [`pratyaya`]: Prakriya::view +#[derive(Debug)] +pub struct TermView<'a> { + /// All of the terms in the prakriya. We store the entire `Term` list so that our internal + /// indices line up with the indices we would use on `Prakriya`. + terms: &'a Vec, + /// Index of the first term in the view (inclusive). + start: usize, + /// Index of the last term in the view (inclusive). + end: usize, +} + +impl<'a> TermView<'a> { + /// Creates a new term view over the interval `[start, end]`` + pub fn new(terms: &'a Vec, start: usize, end: usize) -> Option { + if end + 1 <= terms.len() { + Some(TermView { terms, start, end }) + } else { + None + } + } + + pub fn with_start(terms: &'a Vec, start: usize) -> Option { + if start >= terms.len() { + return None; + } + + let mut end = start; + for (i, t) in terms.iter().enumerate().filter(|(i, _)| *i >= start) { + // A `kit` Agama is part of the term it follows, i.e. there is no view available here. + // Exception: iw-Agama marked as kit. + if i == start && t.has_all_tags(&[Tag::Agama, Tag::kit]) && !t.has_u("iw") { + return None; + } + + if !t.has_tag(Tag::Agama) { + end = i; + break; + } + } + Some(TermView { terms, start, end }) + } + + /// Returns this view's text. + #[allow(unused)] + pub fn text(&self) -> String { + let mut ret = String::from(""); + for t in self.slice() { + ret.push_str(&t.text); + } + ret + } + + /// Returns whether this view has the provided text. + pub fn has_text(&self, value: &str) -> bool { + // Strategy: iterate backward term by term until we have matched all chars in `text`. If + // there is any mismatch, return false. + let mut offset = value.len(); + for t in self.slice().iter().rev() { + let slice = &value[0..offset]; + if slice.ends_with(t.text.as_str()) { + // No risk of overflow here because `t.text` is at least as long as `slice`. + offset -= t.text.len(); + if offset == 0 { + return true; + } + } else { + // No match. + break; + } + } + + false + } + + /// Returns whether this view's text is equal to any of the strings in `items`. + pub fn has_text_in(&self, values: &[&str]) -> bool { + values.iter().any(|v| self.has_text(v)) + } + + // Accessors + + pub fn terms(&self) -> &[Term] { + &self.terms + } + + pub fn slice(&self) -> &[Term] { + &self.terms[self.start..=self.end] + } + + pub fn first(&self) -> &Term { + self.terms.get(self.start).expect("present") + } + + pub fn last(&self) -> &Term { + self.terms.get(self.end).expect("present") + } + + pub fn last_non_empty(&self) -> Option<&Term> { + self.terms.get(self.end_non_empty()?) + } + + /// Returns the first index in the view. + pub fn start(&self) -> usize { + self.start + } + + /// Returns the last index in the view. + pub fn end(&self) -> usize { + self.end + } + + /// Returns the last index in the view that is non-empty. + /// + /// `end_non_empty` is useful if the view ends in an empty pratyaya, such as a kvip-pratyaya. + pub fn end_non_empty(&self) -> Option { + for i in (self.start..=self.end).rev() { + if !self.terms.get(i).expect("present").is_empty() { + return Some(i); + } + } + None + } + + #[allow(unused)] + pub fn is_padanta(&self) -> bool { + self.is_empty() && self.ends_word() + } + + /// Returns whether the view's text is empty. + #[allow(unused)] + pub fn is_empty(&self) -> bool { + self.slice().iter().all(|t| t.text.is_empty()) + } + + /// Returns whether this view is at the very end of the given word. + #[allow(unused)] + pub fn ends_word(&self) -> bool { + self.end == self.terms.len() - 1 + } + + /// Returns the number of vowels contained in this term's text. + #[allow(unused)] + pub fn num_vowels(&self) -> usize { + self.slice().iter().map(|t| t.num_vowels()).sum() + } + + fn matches_sound_pattern(&self, c: Option, pattern: impl Pattern) -> bool { + match c { + Some(c) => pattern.matches(c), + None => false, + } + } + + pub fn adi(&self) -> Option { + for t in self.slice() { + match t.adi() { + Some(c) => return Some(c), + None => continue, + } + } + None + } + + /// Returns the view's penultimate sound. + pub fn upadha(&self) -> Option { + let nth_rev = 1; + let mut i = 0; + // O(n) is the best I can think of: + for t in self.slice().iter().rev() { + for c in t.text.chars().rev() { + if i == nth_rev { + return Some(c); + } + i += 1; + } + } + None + } + + /// Returns the last sound in the view if it exists. + pub fn antya(&self) -> Option { + for t in self.slice().iter().rev() { + match t.antya() { + Some(c) => return Some(c), + None => continue, + } + } + None + } + + pub fn has_adi(&self, pattern: impl Pattern) -> bool { + self.matches_sound_pattern(self.adi(), pattern) + } + + #[allow(unused)] + pub fn has_antya(&self, pattern: impl Pattern) -> bool { + self.matches_sound_pattern(self.antya(), pattern) + } + + pub fn has_u(&self, u: &str) -> bool { + match self.slice().first() { + Some(t) => t.has_u(u), + None => false, + } + } + + pub fn has_u_in(&self, us: &[&str]) -> bool { + match self.slice().first() { + Some(t) => t.has_u_in(us), + None => false, + } + } + + pub fn has_tag(&self, tag: Tag) -> bool { + self.slice().iter().any(|t| t.has_tag(tag)) + } + + pub fn has_lakshana(&self, s: &str) -> bool { + self.slice().iter().any(|t| t.has_lakshana(s)) + } + + pub fn has_lakshana_in(&self, items: &[&str]) -> bool { + self.slice().iter().any(|t| t.has_lakshana_in(items)) + } + + pub fn all(&self, tags: &[Tag]) -> bool { + for tag in tags { + if self.slice().iter().any(|t| t.has_tag(*tag)) { + continue; + } + return false; + } + true + } + + pub fn has_tag_in(&self, tags: &[Tag]) -> bool { + tags.iter() + .any(|tag| self.slice().iter().any(|t| t.has_tag(*tag))) + } + + pub fn is_hrasva(&self) -> bool { + match self.last_non_empty() { + Some(t) => t.is_hrasva(), + None => false, + } + } + + /// Returns whether the term has the `Krtya` samjna. + pub fn is_krtya(&self) -> bool { + self.last().has_tag(Tag::Krtya) + } + + pub fn is_knit(&self) -> bool { + self.has_tag_in(&[Tag::kit, Tag::Nit]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn gam() -> Term { + let mut t = Term::make_upadesha("gamx~"); + t.set_text("gam"); + t + } + + #[test] + fn test_make_upadesha() { + let t = gam(); + assert!(t.has_u("gamx~")); + assert!(t.has_text("gam")); + } + + #[test] + fn test_sound_selectors() { + let t = gam(); + + assert_eq!(t.adi(), Some('g')); + assert_eq!(t.upadha(), Some('a')); + assert_eq!(t.antya(), Some('m')); + + assert_eq!(t.get_at(0), Some('g')); + assert_eq!(t.get_at(1), Some('a')); + assert_eq!(t.get_at(2), Some('m')); + assert_eq!(t.get_at(3), None); + } + + #[test] + fn is_laghu() { + let term = Term::make_text; + + assert!(term("i").is_laghu()); + assert!(term("vid").is_laghu()); + assert!(!term("BU").is_laghu()); + assert!(!term("uC").is_laghu()); + assert!(!term("IS").is_laghu()); + assert!(!term("Ikz").is_laghu()); + } + + #[test] + fn test_properties() { + let t = gam(); + + assert!(t.has_adi('g')); + assert!(t.has_upadha('a')); + assert!(t.has_antya('m')); + assert!(!t.is_empty()); + } + + #[test] + fn test_mutators() { + let mut t = gam(); + + assert!(t.has_text("gam")); + t.set_adi("x"); + t.set_upadha("y"); + t.set_antya("z"); + assert!(t.has_adi('x')); + assert!(t.has_upadha('y')); + assert!(t.has_antya('z')); + assert!(t.has_text("xyz")); + } +} diff --git a/vidyut-prakriya/src/dhatu_karya.rs b/vidyut-prakriya/src/dhatu_karya.rs index 40af663..70817cf 100644 --- a/vidyut-prakriya/src/dhatu_karya.rs +++ b/vidyut-prakriya/src/dhatu_karya.rs @@ -11,14 +11,14 @@ Operations here include: use crate::args::Antargana; use crate::args::Dhatu; use crate::args::Gana; +use crate::core::errors::*; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::dhatu_gana as gana; -use crate::errors::*; +use crate::ganapatha::PRA_ADI; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Prakriya, Rule}; -use crate::stem_gana::PRA_ADI; -use crate::tag::Tag as T; -use crate::term::Term; /// Adds the mula-dhatu to the prakriya. fn add_mula_dhatu(p: &mut Prakriya, dhatu: &Dhatu) { @@ -33,7 +33,7 @@ fn add_samjnas(p: &mut Prakriya, i: usize) { if p.has(i, |t| { t.has_text_in(&["dA", "de", "do", "DA", "De"]) && !t.has_u("dA\\p") }) { - p.run_at("1.1.20", i, op::add_tag(T::Ghu)); + p.add_tag_at("1.1.20", i, T::Ghu); }; } @@ -54,9 +54,9 @@ fn try_run_bhvadi_gana_sutras(p: &mut Prakriya) -> Option<()> { p.step(DP("01.0937")); is_mit_blocked = true; } else if dhatu.has_u("Samo~") { - is_mit_blocked = p.run_optional(DP("01.0938"), |_| {}) + is_mit_blocked = p.optional_run(DP("01.0938"), |_| {}) } else if dhatu.has_text("yam") && is_bhvadi { - is_mit_blocked = p.run_optional(DP("01.0939"), |_| {}) + is_mit_blocked = p.optional_run(DP("01.0939"), |_| {}) } else if dhatu.has_u("sKadi~\\r") && i > 0 && p.has(i - 1, |t| t.has_u_in(&["ava", "pari"])) @@ -71,16 +71,16 @@ fn try_run_bhvadi_gana_sutras(p: &mut Prakriya) -> Option<()> { if is_mit_blocked { // Do nothing. } else if is_bhvadi && dhatu.has_text_in(&["jval", "hval", "hmal", "nam"]) && !has_upasarga { - p.run_optional_at(DP("01.0935"), i, op::add_tag(T::mit)); + p.optional_run_at(DP("01.0935"), i, op::add_tag(T::mit)); } else if dhatu.has_text_in(&["glE", "snA", "van", "vam"]) && !has_upasarga { - p.run_optional_at(DP("01.0936"), i, op::add_tag(T::mit)); + p.optional_run_at(DP("01.0936"), i, op::add_tag(T::mit)); } else if (dhatu.has_u_in(&["janI~\\", "jFz", "knasu~", "ra\\nja~^"]) && dhatu.has_gana(Gana::Divadi)) || (is_bhvadi && dhatu.ends_with("am")) { - p.run_at(DP("01.0934"), i, op::add_tag(T::mit)); + p.add_tag_at(DP("01.0934"), i, T::mit); } else if is_bhvadi && dhatu.has_u_in(gana::GHAT_ADI) { - p.run_at(DP("01.0933"), i, op::add_tag(T::mit)); + p.add_tag_at(DP("01.0933"), i, T::mit); } Some(()) @@ -96,7 +96,7 @@ fn try_run_divadi_gana_sutras(p: &mut Prakriya) -> Option<()> { "zUN", "dUN", "dI\\N", "qIN", "DI\\N", "mI\\N", "rI\\N", "lI\\N", "vrI\\N", ]) { // sUna, dUna, dIna, ... - p.run_at(DP("04.0162"), i, op::add_tag(T::odit)); + p.add_tag_at(DP("04.0162"), i, T::odit); } Some(()) @@ -108,7 +108,7 @@ fn try_run_curadi_gana_sutras(p: &mut Prakriya, i: usize) -> Option<()> { let dhatu = p.get_if(i, |t| t.has_gana(Gana::Curadi))?; if dhatu.has_u_in(gana::JNAP_ADI) { - p.run_at(DP("10.0493"), i, op::add_tag(T::mit)); + p.add_tag_at(DP("10.0493"), i, T::mit); } let dhatu = p.get(i)?; @@ -141,19 +141,19 @@ fn try_satva_and_natva(p: &mut Prakriya, i: usize) -> Option<()> { if t.text == "zaR" { t.text.replace_range(.., "san"); } - t.add_tag(T::FlagAdeshadi); + t.add_tag(T::FlagSaAdeshadi); }); } else { // zah -> sah p.run_at("6.1.64", i, |t| { - t.add_tag(T::FlagAdeshadi); + t.add_tag(T::FlagSaAdeshadi); t.set_adi("s"); }); } } else if dhatu.has_adi('R') { // RI -> nI p.run_at("6.1.65", i, |t| { - t.add_tag(T::FlagAdeshadi); + t.add_tag(T::FlagNaAdeshadi); t.set_adi("n"); }); } else if dhatu.has_u("DraRa~") { @@ -278,29 +278,29 @@ mod tests { fn test_satva() { let t = check("zaha~\\", "01.0988"); assert_eq!(t.text, "sah"); - assert!(t.has_all_tags(&[T::Dhatu, T::FlagAdeshadi])); + assert!(t.has_all_tags(&[T::Dhatu, T::FlagSaAdeshadi])); let t = check("zWA\\", "01.1077"); assert_eq!(t.text, "sTA"); - assert!(t.has_all_tags(&[T::Dhatu, T::FlagAdeshadi])); + assert!(t.has_all_tags(&[T::Dhatu, T::FlagSaAdeshadi])); } #[test] fn test_satva_blocked() { let t = check("zWivu~", "04.0004"); assert_eq!(t.text, "zWiv"); - assert!(!t.has_tag(T::FlagAdeshadi)); + assert!(!t.has_tag(T::FlagSaAdeshadi)); let t = check("zvazka~\\", "01.0105"); assert_eq!(t.text, "zvazk"); - assert!(!t.has_tag(T::FlagAdeshadi)); + assert!(!t.has_tag(T::FlagSaAdeshadi)); } #[test] fn test_natva() { let t = check("RI\\Y", "01.1049"); assert_eq!(t.text, "nI"); - assert!(t.has_all_tags(&[T::Dhatu, T::FlagAdeshadi])); + assert!(t.has_all_tags(&[T::Dhatu, T::FlagNaAdeshadi])); } #[test] diff --git a/vidyut-prakriya/src/dhatupatha.rs b/vidyut-prakriya/src/dhatupatha.rs index 0dedff0..f34d94a 100644 --- a/vidyut-prakriya/src/dhatupatha.rs +++ b/vidyut-prakriya/src/dhatupatha.rs @@ -4,7 +4,7 @@ comments on the `Dhatupatha` struct. */ use crate::args::{Antargana, Dhatu, Gana}; -use crate::errors::*; +use crate::core::errors::*; use std::path::Path; /// An entry in the Dhatupatha. diff --git a/vidyut-prakriya/src/dvitva.rs b/vidyut-prakriya/src/dvitva.rs index 1cb531c..17f7191 100644 --- a/vidyut-prakriya/src/dvitva.rs +++ b/vidyut-prakriya/src/dvitva.rs @@ -2,13 +2,12 @@ /// /// TODO: the code here is repetitive and can be consolidated with a bit more thought. use crate::ac_sandhi; -use crate::filters as f; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Code, Prakriya}; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use compact_str::CompactString; use lazy_static::lazy_static; @@ -54,7 +53,7 @@ fn try_dvitva_for_ajadi_dhatu(rule: Code, p: &mut Prakriya, i: usize) -> Option< p.insert_after(i, abhyasa); p.insert_after(i + 1, third); p.step(rule); - p.run_at("6.1.4", i + 1, op::add_tag(T::Abhyasa)); + p.add_tag_at("6.1.4", i + 1, T::Abhyasa); p.set(i, |t| t.add_tag(T::Abhyasta)); p.set(i + 1, |t| t.add_tag(T::Abhyasta)); @@ -135,7 +134,7 @@ fn try_dvitva_for_sanadi_ajadi(rule: Code, p: &mut Prakriya, i_dhatu: usize) -> } p.step(rule); - p.run_at("6.1.4", i_ac + 1, |t| t.add_tag(T::Abhyasa)); + p.add_tag_at("6.1.4", i_ac + 1, T::Abhyasa); p.run("6.1.5", |p| { p.set(i_ac, op::add_tag(T::Abhyasta)); p.set(i_ac + 1, op::add_tag(T::Abhyasta)); @@ -157,14 +156,14 @@ fn try_dvitva(rule: Code, p: &mut Prakriya, i: usize) -> Option<()> { !(t.is_agama() && t.has_tag(T::kit) && !t.is_it_agama()) })?; let dhatu = p.get(i)?; - let next = p.view(i_n)?; + let next = p.pratyaya(i_n)?; if dhatu.has_adi(&*AC) - && next.last()?.is_pratyaya() - && next.last()?.has_u_in(&["san", "Ric", "yaN", "RiN"]) + && next.last().is_pratyaya() + && next.last().has_u_in(&["san", "Ric", "yaN", "RiN"]) { try_dvitva_for_sanadi_ajadi(rule, p, i); - } else if f::is_eka_ac(dhatu) || al::is_hal(dhatu.adi()?) { + } else if dhatu.is_ekac() || al::is_hal(dhatu.adi()?) { let mut abhyasa = Term::make_text(""); abhyasa.set_text(&dhatu.sthanivat()); @@ -177,7 +176,7 @@ fn try_dvitva(rule: Code, p: &mut Prakriya, i: usize) -> Option<()> { let i_abhyasa = i; let i_dhatu = i + 1; - p.run_at("6.1.4", i_abhyasa, op::add_tag(T::Abhyasa)); + p.add_tag_at("6.1.4", i_abhyasa, T::Abhyasa); p.set(i_abhyasa, |t| t.add_tag(T::Abhyasta)); p.set(i_dhatu, |t| t.add_tags(&[T::Abhyasta, T::Dvitva])); @@ -206,14 +205,14 @@ fn run_at_index(p: &mut Prakriya, i: usize) -> Option<()> { // These are termed abhyasta, but they can still undergo dvitva because // the rules below are conditioned specifically on "anabhyAsasya" ("not having an abhyasa") // from 6.1.8. - p.run_at("6.1.6", i, op::add_tag(T::Abhyasta)); + p.add_tag_at("6.1.6", i, T::Abhyasta); } // Use a view to include `iw`-Agama. Skip vu~k and other dhatu-agamas. let i_n = p.find_next_where(i, |t| { !(t.is_agama() && t.has_tag(T::kit) && !t.is_it_agama()) })?; - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; if n.has_lakshana("li~w") { let dhatu = p.get(i)?; // kAshikA: diff --git a/vidyut-prakriya/src/filters.rs b/vidyut-prakriya/src/filters.rs deleted file mode 100644 index c9ec222..0000000 --- a/vidyut-prakriya/src/filters.rs +++ /dev/null @@ -1,28 +0,0 @@ -/*! -Components for creating filters. - -A *filter* is a function that accepts a `Term` and returns a boolean value. We use filters to check -whether a given rule can apply. - -For most use cases, we recommend using the helper methods on `Term`, which have a more readable -calling convention. -*/ -use crate::args::Gana; -use crate::sounds::{s, Set}; -use crate::term::Term; -use lazy_static::lazy_static; - -lazy_static! { - static ref AC: Set = s("ac"); -} - -/// Returns whether the given term has exactly one vowel sound. -pub fn is_eka_ac(t: &Term) -> bool { - let num_ac = t.text.chars().filter(|c| AC.contains(*c)).count(); - num_ac == 1 -} - -/// Returns whether this term is the dhAtu `as` in the sense of `asti`. -pub fn is_asti(t: &Term) -> bool { - t.has_u("asa~") && t.has_gana(Gana::Adadi) -} diff --git a/vidyut-prakriya/src/ganapatha.rs b/vidyut-prakriya/src/ganapatha.rs new file mode 100644 index 0000000..37ecdf4 --- /dev/null +++ b/vidyut-prakriya/src/ganapatha.rs @@ -0,0 +1,1535 @@ +/*! +Implements rules from the Gaṇapāṭha. + +Most of these lists come directly from the Kashika Vrtti. If a list is unclear to us, we adjust it +using data from . +*/ + +/// 1.1.27 sarvAdIni sarvanAmAni (1) +pub const SARVA_ADI: &[&str] = &[ + "sarva", "viSva", "uBa", "uBaya", "qatara", "qatama", "anya", "anyatara", "itara", "tvat", + "tva", "nema", "sama", "sima", "pUrva", "para", "avara", "dakziRa", "uttara", "apara", "aDara", + "sva", "antara", "tyad", "tad", "yad", "etad", "idam", "adas", "eka", "dvi", "yuzmad", "asmad", + "Bavatu~", "kim", +]; + +/// 1.4.57 cAdayo sattve (3) +/// TODO: no cet, na cet +#[allow(dead_code)] +pub const CA_ADI: &[&str] = &[ + "ca", "vA", "ha", "aha", "eva", "evam", "nUnam", "SaSvat", "yugapat", "sUpat", "kUpat", + "kuvit", "net", "cet", "caR", "kaccit", "yatra", "naha", "hanta", "mAkim", "nakim", "mAN", + "naY", "yAvat", "tAvat", "tvA", "tvE", "dvE", "rE", "SrOzaw", "vOzaw", "svAhA", "vazaw", + "svaDA", "om", "kila", "taTA", "aTa", "su", "sma", "asmi", "a", "i", "u", "f", "x", "e", "E", + "o", "O", "am", "tak", "uY", "ukaY", "velAyAm", "mAtrAyAm", "yaTA", "yat", "yam", "tat", "kim", + "purA", "adDA", "Dik", "hAhA", "he", "hE", "pyAw", "pAw", "TAw", "aho", "utAho", "ho", "tum", + "taTAhi", "Kalu", "Am", "Aho", "aTo", "nanu", "manye", "miTyA", "asi", "brUhi", "tu", "nu", + "iti", "iva", "vat", "cana", "bata", "iha", "Sam", "kam", "anukam", "nahikam", "hikam", + "sukam", "satyam", "ftam", "SfadDA", "idDA", "muDA", "jAtu", "kaTam", "kutaH", "kutra", "ava", + "anu", "hAhO", "hEhA", "IhA", "Ahosvit", "Cambaw", "Kam", "dizwyA", "paSu", "vaw", "saha", + "Anuzak", "aNga", "Paw", "tAjak", "aye", "are", "cawu", "bAw", "kum", "Kum", "Gum", "hum", + "AIm", "SIm", "sIm", "vE", +]; + +/// 1.4.58 prAdayaH (4) +pub const PRA_ADI: &[&str] = &[ + "pra", "parA", "apa", "sam", "anu", "ava", "nis", "nir", "dus", "dur", "vi", "AN", "ni", "aDi", + "api", "ati", "su", "ud", "aBi", "prati", "pari", "upa", +]; + +/// 2.1.40 saptamI SORqEH (8) +pub const SHAUNDA_ADI: &[&str] = &[ + "SORqa", "DUrta", "kitava", "vyAqa", "pravIRa", "saMvIta", "antar", "aDi", "pawu", "paRqita", + "capala", "nipuRa", +]; + +/// 2.1.70 kumAraH SramaRAdiBiH () +pub const SHRAMANA_ADI: &[&str] = &[ + "SramaRA", + "pravrajitA", + "kulawA", + "garBiRI", + "tApasI", + "dAsI", + "banDakI", + "aDyApaka", + "aBirUpaka", + "paRqita", + "pawu", + "mfdu", + "kuSala", + "capala", + "nipuRA", +]; + +/// 2.2.9 yAjakAdiBiS ca () +pub const YAJAKA_ADI: &[&str] = &[ + "yAjaka", + "pUjaka", + "paricAraka", + "parivezaka", + "parizecaka", + "snAtaka", + "aDyApaka", + "utsAha", + "udvartaka", + "hotf", + "Batf", + "raTagaRaka", + "pattigaRaka", +]; + +/// 4.1.4 ajAdyataz wAp (54) +pub const AJA_ADI: &[&str] = &[ + // jAti + "aja", + "eqaka", + "kokila", + "cawaka", + "aSva", + "mUzika", + // age + "bAla", + "hoqa", + "pAka", + "vatsa", + "manda", + "vilAta", + // lyuw + "pUrvApaharaRa", + "aparApaharaRa", + // Pala + "samPala", + "BastraPala", + "ajinaPala", + "SaRaPala", + "piRqaPala", + "triPala", + // puzpa + "satpuzpa", + "prAkpuzpa", + "kARqapuzpa", + "prAntapuzpa", + "Satapuzpa", + "ekapuzpa", + // TODO: optional for SUdra in different senses. + "SUdra", + // halanta + "kruYc", + "uzRih", + "devaviS", + // matrimony + "jyezWa", + "kanizWa", + "maDyama", + // naY + "amUla", +]; + +/// 4.1.10 na zaw-svasrAdiByaH (46) +pub const SVASR_ADI: &[&str] = &[ + "svasf", "duhitf", "nanAndf", "yAtf", "mAtf", "tisf", "catasf", +]; + +/// 4.1.41 zid-gOrAdiByaS ca (48) +pub const GAURA_ADI: &[&str] = &[ + "gOra", + "matsya", + "manuzya", + "SfNga", + "piNgala", + "haya", + "gavaya", + "mukaya", + "fzya", + "puwa", + "dURa", + "druRa", + "droRa", + "hariRa", + "kokaRa", + "kAkaRa", + "pawara", + "uRaka", + "Amala", + "Amalaka", + "kubala", + "bimba", + "badara", + "Parkaraka", + "karkaraka", + "tarkAra", + "SarkAra", + "puzkara", + "SiKaRqa", + "sala", + "SazkaRqa", + "sananda", + "suzama", + "suzava", + "alinda", + "gaqu", + "zARqaSa", + "AQaka", + "Ananda", + "ASvatTa", + "sfpAwa", + "AKaka", + "Apaccika", + "Sazkula", + "sUrya", + "sUrma", + "SUrpa", + "sUpa", + "vfsa", + "atasa", + "Ba", + "BfNga", + "maha", + "maWa", + "Ceda", + "peSa", + "meda", + "Svan", + "takzan", + "anaquhI", + "anaqvAhI", + // "ezaRaH karaRe", + "deha", + "dehala", + "kAkAdana", + "gavAdana", + "tejana", + "rajana", + "lavaRa", + "OdgAhamAni", + "AdgAhamAni", + "gOtama", + "gotama", + "pAraka", + "AyasTURa", + "ayaHsTURa", + "BOrika", + "BOliki", + "BOliNgi", + "yAna", + "meGa", + "Alambi", + "Alaji", + "AlabDi", + "Alakzi", + "kevAla", + "Apaka", + "Arawa", + "nawa", + "wowa", + "nowa", + "mUlAwa", + "SAtana", + "potana", + "pAtana", + "pAWana", + "pAnaWa", + "AstaraRa", + "aDikaraRa", + "aDikAra", + "AgrahAyaRI", + "AgrahAyaRI", + "pratyavarohiRI", + "secana", + // "sumaNgalAtsaMjYAyAm", + "aRqara", + "sundara", + "maRqala", + "manTara", + "maNgala", + "pawa", + "piRwa", + "zaRqa", + "urda", + "garda", + "Sama", + "sUd", + "Oqa", + "Ardra", + "hfda", + "hrada", + "pARqa", + "BARqala", + "BARqa", + "lohARqa", + "kadara", + "kandara", + "kadala", + "taruRa", + "taluna", + "kalmAza", + "bfhat", + "mahat", + "soma", + "sODarma", + // "rohiRI nakzatre", + // "revatI nakzatre", + "vikala", + "nizPala", + "puzkala", + // "kawAcCroRivacane", + // "pippalyAdayaSca", + "pippalI", + "haritakI", + "harItakI", + "koSAtakI", + "SamI", + "varI", + "SarI", + "pfTivI", + "krozwu", + "mAtAmaha", + "pitAmaha", +]; + +/// 4.1.45 bahvAdiByaS ca (49) +pub const BAHU_ADI: &[&str] = &[ + "bahu", + "padDati", + "aNkati", + "aYcati", + "aMhati", + "vaMhati", + "Sakawi", + "Sakti", + "SAri", + "vAri ", + "rAti", + "rADi", + "SADi", + "ahi", + "kapi", + "yazwi", + "muni", + "caRqa", + "arAla", + "kamala", + "kfpARa", + "vikawa", + "viSAla", + "viSaNkawa", + "Baruja", + "Dvaja", + "kalyARa", + "udAra", + "purARa", + "ahan", +]; + +/// 4.1.84 aSvapatyAdiByaSca (53) +pub const ASHVAPATI_ADI: &[&str] = &[ + "aSvapati", + "Satapati", + "Danapati", + "gaRapati", + "rAzwrapati", + "kulapati", + "gfhapati", + "DAnyapati", + "paSupati", + "Darmapati", + "saBApati", + "prARapati", + "kzetrapati", +]; + +/// 4.1.86 utsAdiByo 'Y (54) +pub const UTSA_ADI: &[&str] = &[ + "utsa", + "udapAna", + "vikara", + "vinoda", + "mahAnada", + "mahAnasa", + "mahAprARa", + "taruRa", + "taluna", + "bazkayAse", + "Denu", + "pfTivI", + "paNkti", + "jagatI", + "trizwuB", + "anuzwuB", + "janapada", + "Barata", + "uSInara", + "grIzma", + "pIlu", + "kula", + "udasTAna", + "pfzadaMSe", + "BallakIya", + "raTantara", + "maDyandina", + "bfhat", + "mahat", + "sattvat", + "kuru", + "paYcAla", + "indrAvasAna", + "uzRih", + "kakuB", + "suvarRa", + "deva", +]; + +/// 4.1.96 bAhvAdiByazca (55) +pub const BAAHU_ADI: &[&str] = &[ + "bAhu", + "upabAhu", + "upavAku", + "nivAku", + "SivAku", + "vawAku", + "upanindu", + "upabindu", + "vfzalI", + "vfkalA", + "cUqA", + "balAkA", + "mUzikA", + "kuSalA", + "BagalA", + "CagalA", + "DruvakA", + "DuvakA", + "sumitrA", + "durmitrA", + "puzkarasad", + "anuharat", + "devaSarman", + "agniSarman", + "BadraSarman", + "suSarman", + "kunAman", + "sunAman", + "paYcan", + "saptan", + "azwan", + // amitOjasa has sa-lopa + "amitOjasa", + "suDAvat", + "udaYcu", + "Siras", + "mAza", + "SarAvin", + "marIcI", + "kSemavfdDin", + "SfNKalatodin", + "KaranAdin", + "nagaramardin", + "prAkAramardin", + "loman", + "ajIgarta", + "kfzra", + "yuDizWira", + "arjuna", + "sAmba", + "gada", + "pradyumna", + "rAma", + "udaNku", +]; + +/// 4.1.98 gotre kuYjAdiByaS cPaY (56) +pub const KUNJA_ADI: &[&str] = &[ + "kuYja", "braDna", "SaNKa", "Basman", "gaRa", "loman", "SaWa", "SAka", "SAkawa", "SuRqA", + "SuBa", "vipASa", "skanda", "stamBa", +]; + +/// 4.1.99 naqAdiByaH Pak (57) +pub const NADA_ADI: &[&str] = &[ + "naqa", + "cara", + "baka", + "muYja", + "itika", + "itiSa", + "upaka", + "lamaka", + "SalaNku", + "SalaNkam", + "saptala", + "vAjapya", + "tika", + "agniSarman", + "prARa", + "nara", + "sAyaka", + "dAsa", + "mitra", + "dvIpa", + "piNgara", + "piNgala", + "kiNkara", + "kiNkala", + "kAtara", + "kAtala", + "kASya", + "kASyapa", + "kAvya", + "aja", + "amuzya", + "kfzRa", + "raRa", + "amitra", + "ligu", + "citra", + "kumAra", + "krozwu", + "krozwam", + "loha", + "durga", + "stamBa", + "SiMSipA", + "agra", + "tfRa", + "Sakawa", + "sumanas", + "sumata", + "mimata", + "fk", + "jat", + "yuganDara", + "haMsaka", + "daRqin", + "hastin", + "paYcAla", + "camasin", + "sukftya", + "sTiraka", + "brAhmaRa", + "cawaka", + "badara", + "aSvala", + "Karapa", + "kAmuka", + "vrahmadatta", + "udumbara", + "SoRa", + "aloha", + "daRqa", +]; + +/// For 4.1.104. +pub const BIDA_ADI: &[&str] = &[ + "bida", + "urva", + "kaSyapa", + "kuSika", + "BaradvAja", + "upamanyu", + "kilAlapa", + "kidarBa", + "viSvAnara", + "fzwizeRa", + "ftaBAga", + "haryaSva", + "priyaka", + "Apastamba", + "kUcavAra", + "Saradvat", + "Sunaka", + "Denu", + "gopavana", + "Sigru", + "bindu", + "BAjana", + "aSvAvatAna", + "SyAmAka", + "SyamAka", + "SyAparRa", + "harita", + "kindAsa", + "vahraska", + "arkalUza", + "vaDyoza", + "vizRuvfdDa", + "pratiboDa", + "raTAntara", + "raTItara", + "gavizWira", + "nizAda", + "maWara", + "mfda", + "punarBU", + "putra", + "duhitf", + "nanAndf", + "parastrI", +]; + +/// For 4.1.105. +pub const GARGA_ADI: &[&str] = &[ + "garga", + "vatsa", + "vAjAse", + "saMskfti", + "aja", + "vyAGrapAt", + "vidaBft", + "prAcInayoga", + "agasti", + "pulasti", + "reBa", + "agniveSa", + "SaNKa", + "SaWa", + "GUma", + "avawa", + "camasa", + "DanaYjaya", + "manasa", + "vfkza", + "viSvAvasu", + "janamAna", + "lohita", + "SaMsita", + "baBru", + "maRqu", + "makzu", + "aligu", + "SaNku", + "ligu", + "gulu", + "mantu", + "jigIzu", + "manu", + "tantu", + "manAyI", + "BUta", + "kaTaka", + "kaza", + "taRqa", + "vataRqa", + "kapi", + "kata", + "kurukata", + "anaquH", + "kaRva", + "Sakala", + "gokakza", + "agastya", + "kuRqina", + "yajYavalka", + "uBaya", + "jAta", + "virohita", + "vfzagaRa", + "rahUgaRa", + "SaRqila", + "vaRa", + "kaculuka", + "mudgala", + "musala", + "parASara", + "jatUkarRa", + "mAntrita", + "saMhita", + "aSmaraTa", + "SarkarAkza", + "pUtimAza", + "sTURa", + "araraka", + "piNgala", + "kfzRa", + "golunda", + "ulUka", + "titikza", + "Bizaj", + "Baqita", + "BaRqita", + "dalBa", + "cikita", + "devahU", + "indrahU", + "ekalU", + "pippalU", + "vfdagni", + "jamadagni", + "suloBin", + "ukatTa", + "kuwIgu", +]; + +/// 4.1.110 aSvAdiByaH PaY (60) +pub const ASHVA_ADI: &[&str] = &[ + "aSva", + "aSman", + "SaNKa", + "pawu", + "rohiRa", + "KarjUra", + "KarjUla", + "piYjUra", + "Baqila", + "BaRqila", + "Baqita", + "BaRqita", + "BaRqika", + "prahfta", + "romAda", + "kzatra", + "grIvA", + "kASa", + "golANkya", + "arka", + "svana", + "Dvana", + "pAda", + "cakra", + "kula", + "pavitra", + "gomin", + "SyAma", + "DUma", + "DUmra", + "vAgmin", + "viSvAnara", + "kuwa", + "veSa", + "Sapa", + "natta", + "taqa", + "naqa", + "grIzma", + "arha", + "viSamya", + "viSAlA", + "giri", + "capala", + "cunama", + "dAsaka", + "vElya", + "Darma", + "Anaquhra", + "puMsijAta", + "arjuna", + "SUdraka", + "sumanas", + "durmanas", + "kzAnta", + "prAcya", + "kita", + "kARa", + "cumba", + "SravizWA", + "vIkzya", + "pavindA", + "Atreya", + "kutsa", + "Atava", + "kitava", + "Siva", + "Kadira", + "BAradvAja", +]; + +/// 4.1.112 SivAdiByo 'R (61) +pub const SHIVA_ADI: &[&str] = &[ + "Siva", + "prOzWa", + "prOzWika", + "caRqa", + "jamBa", + "muni", + "sanDi", + "BUri", + "kuWAra", + "anaBimlAna", + "kakutsTa", + "kahoqa", + "leKa", + "roDa", + "KaYjana", + "kohaqa", + "pizwa", + "hehaya", + "KaYjAra", + "KaYjAla", + "surohikA", + "parRa", + "kahUza", + "parila", + "vataRqa", + "tfRa", + "karRa", + "kzIrahfda", + "jalahfda", + "parizika", + "jawilika", + "goPilika", + "baDirikA", + "maYjIraka", + "vfzRika", + "reKa", + "AleKana", + "viSravaRa", + "ravaRa", + "vartanAkza", + "piwaka", + "piwAka", + "tfkzAka", + "naBAka", + "UrRanABa", + "jaratkAru", + "utkzipA", + "rohitika", + "AryaSveta", + "supizwa", + "KarjUrakarRa", + "masUrakarRa", + "tURakarRa", + "mayUrakarRa", + "Kaqaraka", + "takzan", + "fzwizeRa", + "gaNgA", + "vipASa", + "yaska", + "lahra", + "druhyu", + "ayaHsTURa", + "Balandana", + "virUpAkza", + "BUmi", + "ilA", + "sapatnI", + "dvyaca", +]; + +/// 4.1.146 revatyAdiByaz Wak (65) +pub const REVATI_ADI: &[&str] = &[ + "revatI", + "aSvapAlI", + "maRipAlI", + "dvArapAlI", + "vfkavaYcin", + "vfkabanDu", + "vfkagrAha", + "karRagrAha", + "daRqagrAha", + "kukkUwAkza", + "kakudAkza", + "cAmaragrAha", +]; + +/// For 4.1.123. +pub const SHUBHRA_ADI: &[&str] = &[ + "SuBra", + "vizwapura", + // TODO: many others +]; + +/// For 4.1.126. +pub const KALYANI_ADI: &[&str] = &[ + "kalyARI", + "suBagA", + "durBagA", + "banDakI", + "anudfzwi", + "anusfzwi", + "jaratI", + "balIvardI", + "jyezWA", + "kanizWA", + "maDyamA", + "parastrI", +]; + +/// For 4.2.38. +pub const BHIKSHA_ADI: &[&str] = &[ + "BikzA", "garBiRI", "kzetra", "karIza", "aNgAra", "carmin", "Darmin", "sahasra", "yuvati", + "padAti", "padDati", "aTarvan", "dakziRA", "BUta", +]; + +/// For 4.2.45. +pub const KHANDIKA_ADI: &[&str] = &[ + "KaRqikA", + "vaqavA", + "kzudrakamAla", + "Bikzuka", + "Suka", + "ulUka", + "Svan", + "yuga", + "ahan", + "varatrA", + "halabanDa", +]; + +/// For 4.2.49. +pub const PASHA_ADI: &[&str] = &[ + "pASa", "tfRa", "DUma", "vAta", "aNgAra", "pota", "bAlaka", "piwaka", "piwAka", "Sakawa", + "hala", "naqa", "vana", +]; + +/// For 4.2.75. +pub const SANKALA_ADI: &[&str] = &[ + "saNkala", + "puzkala", + "udvapa", + "uqupa", + "utpuwa", + "kumBa", + "viDAna", + "sudakza", + "sudatta", + "suBUta", + "sunetra", + "supiNgala", + "sikatA", + "pUtIkI", + "pUlasa", + "kUlAsa", + "palASa", + "niveSa", + "gaveza", + "gamBIra", + "itara", + "Sarman", + "ahan", + "loman", + "veman", + "varuRa", + "bahula", + "sadyoja", + "aBizikta", + "goBft", + "rAjaBft", + "gfha", + "Bfta", + "Balla", + "mAla", + "vft", +]; + +/// For 4.2.77. +pub const SUVASTA_ADI: &[&str] = &[ + "suvAstu", + "varRu", + "BaRqu", + "KaRqu", + "secAlin", + "karpUrin", + "SiKaRdin", + "garta", + "karkaSa", + "SawIkarRa", + "kfzRa", + "karka", + "karNkaDU matI", + "gohra", + "ahisakTa", + "vft", +]; + +/// For 4.2.86. +pub const MADHU_ADI: &[&str] = &[ + "maDu", + "bisa", + "sTARu", + "muzwi", + "ikzu", + "veRu", + "ramya", + "fkza", + "karkanDu", + "SamI", + "kirIra", + "hima", + "kiSarA", + "SarpaRA", + "marut", + "maruva", + "dArvAGAwa", + "Sara", + "izwakA", + "takzaSilA", + "Sakti", + "AsandI", + "Asuti", + "SalAkA", + "AmiDI", + "KaqA", + "vewA", + "maDvAdiH", +]; + +/// For 4.2.95. +pub const KATRI_ADI: &[&str] = &[ + "katri", + "umBi", + "puzkara", + "modana", + "kumBI", + "kuRqina", + "nagara", + "vaYjI", + "Bakti", + "mAhizmatI", + "carmaRvatI", + "grAma", + "uKyA", + // kuqyA takes ya-lopa + "kuqyA", + "katryAdiH", +]; + +/// 4.2.97 nadyAdiByo Qak (106) +pub const NADI_ADI: &[&str] = &[ + "nadI", + "mahI", + "vArARasI", + "SrAvastI", + "kOSAmbI", + "navakOSAmbI", + "kASaParI", + "KAdirI", + "pUrvanagarI", + "pAvA", + "mAvA", + "sAlvA", + "dArvA", + "dAlvA", + "vAsenakI", + "vaqavA", +]; + +/// 4.2.86 maDvAdiByaS ca (102) +pub const KASHI_ADI: &[&str] = &[ + "kASi", + "cedi", + "bedi", + "saMjYA", + "saMvAha", + "acyuta", + "mohamAna", + "SakulAda", + "hastikarzU", + "kudAman", + "hiraRya", + "karaRa", + "goDASana", + "BOriki", + "BOliNgi", + "arindama", + "sarvamitra", + "devadatta", + "sADumitra", + "dAsamitra", + "dAsagrAma", + "sODAvatAna", + "yuvarAja", + "uparAja", + "sinDumitra", + "devarAja", + // ApadAdipUrvapadAt kAlAt + "ApatkAla", + "UrDvakAla", + "tatkAla", +]; + +/// 4.2.133 kacCAdiByaS ca (110) +pub const KACCHA_ADI: &[&str] = &[ + "kacCa", + "sinDu", + "varRu", + "ganDAra", + "maDumat", + "kamboja", + "kaSmIra", + "sAlva", + "kuru", + "raNku", + "aRu", + "KaRqa", + "dvIpa", + "anUpa", + "ajavAha", + "vijApakaH", + "kulUna", +]; + +/// 4.2.138 gahAdiByaS ca (111) +pub const GAHA_ADI: &[&str] = &[ + "gaha", + "antaHsTa", + "sama", + "vizama", + "maDya", + "maDyama", + "uttama", + "aNga", + "vaNga", + "magaDa", + "pUrvapkza", + "aparapakza", + "aDamaSAKa", + "uttamaSAKa", + "samAnaSAKa", + "ekagrAma", + "ekavfkza", + "ekapalASa", + "ezvagra", + "izvanI", + "avasyandI", + "kAmaprasTa", + "KAqAyani", + "kAveraRi", + "SONgi", + "Asuri", + "AhiMsi", + "Amitri", + "vyAqi", + "vEdaji", + "BOji", + "AQyaSvi", + "AnfSaMsi", + "sOvi", + "pAraki", + "agniSarman", + "devaSarman", + "SrOti", + "Arawaki", + "vAlmIki", + "kzemavfdDin", + "uttara", + "antara", + // TODO: remainder + "jana", + "para", + "deva", + "veRukA", +]; + +/// For 4.3.16. +pub const SANDHIVELA_ADI: &[&str] = &[]; + +/// For 4.3.54. +pub const DIG_ADI: &[&str] = &[ + "diS", "varga", "pUga", "gaRa", "pakza", "DAyyA", "mitra", "meDA", "antara", "paTin", "rahas", + "alIka", "uKA", "sAkzin", "Adi", "anta", "muKa", "jaGna", "meGa", "yUTa", "udaka", "nyAya", + "vaMSa", "anuvaMSa", "viSa", "kAla", "ap", "AkASa", "digAdiH", +]; + +/// For 4.3.76. +pub const SHUNDIKA_ADI: &[&str] = &[ + "SuRqika", "kfkaRa", "sTaRqila", "udapAna", "upala", "tIrTa", "BUmi", "tfRa", "parRa", +]; + +/// For 4.3.92. +pub const SHANDIKA_ADI: &[&str] = &[ + "SaRqika", + "sarvasena", + "sarvakeSa", + "Saka", + "sawa", + "raka", + "SaNKa", + "boDa", +]; + +/// For 4.3.93. +pub const SINDHU_ADI: &[&str] = &[ + "sinDu", "varRu", "ganDAra", "maDumat", "kamboja", "kaSmIra", "sAlva", "kizkinDA", "gadikA", + "urasa", "darat", +]; + +/// For 4.3.93. +pub const TAKSHASHILA_ADI: &[&str] = &[ + "takzaSilA", + "vatsodDaraRa", + "kOmedura", + "kaRqavAraRa", + "grAmaRI", + "sarAlaka", + "kaMsa", + "kinnara", + "saMkucita", + "siMhakozWa", + "karRakozWa", + "barbara", + "avasAna", +]; + +/// For 4.3.131. +pub const RAIVATIKA_ADI: &[&str] = &[ + "rEvatika", + "svApiSi", + "kzEmavfdDi", + "gOragrIvi", + "Odameyi", + "OdavAhi", + "bEjavApi", +]; + +/// For 4.4.10. +pub const PARPA_ADI: &[&str] = &[ + "parpa", "aSva", "aSvatTa", "raTa", "jAla", "nyAsa", "vyAla", "pAda", "paYca", "padika", +]; + +/// For 4.3.118. +pub const KULALA_ADI: &[&str] = &[ + "kulAla", + "varuqa", + "caRqAla", + "nizAda", + "karmAra", + "senA", + "siraGra", + "sendriya", + "devarAja", + "parizat", + "vaDU", + "ruru", + "Druva", + "rudra", + "anaquH", + "brahman", + "kumBakAra", + "SvapAka", +]; + +/// For 4.3.164. +pub const PLAKSHA_ADI: &[&str] = &[ + "plakza", "nyagroDa", "aSvatTa", "iNgudI", "Sigru", "kakarnDu", "vuhatI", +]; + +/// For 4.4.12. +pub const VETANA_ADI: &[&str] = &[ + "vetana", + "vAha", + "arDavAha", + "DanurdaRqa", + "jAla", + "vesa", + "upavesa", + "prezana", + "upasti", + "suKa", + "SayyA", + "Sakti", + "upanizad", + "upaveza", + "sraj", + "pAda", + "upasTAna", +]; + +/// For 4.4.19. +pub const AKSHADYUTA_ADI: &[&str] = &[ + "akzadyUta", + "jAnuprahfta", + "jaNGAprahfta", + "pAdasvedana", + "kaRwakamardana", + "gatAgata", + "yAtopayAta", + "anugata", +]; + +/// 4.4.62 CatrAdiByo RaH (142) +pub const CHATRA_ADI: &[&str] = &[ + "Catra", "buBukzA", "SikzA", "puroha", "sTA", "curA", "upasTAna", "fzi", "karman", "viSvaDA", + "tapas", "satya", "anfta", "SibikA", +]; + +/// 4.4.98 pratijanAdiByaH KaY (143) +pub const PRATIJANA_ADI: &[&str] = &[ + "pratijana", + "idaMyuga", + "saMyuga", + "samayuga", + "parayuga", + "parakula", + "parasyakula", + "amuzyakula", + "sarvajana", + "viSvajana", + "mahAjana", + "paYcajana", +]; + +/// 4.4.102 kaTAdiByaz Wak (144) +pub const KATHA_ADI: &[&str] = &[ + "kaTA", + "vikaTA", + "viSvakaTA", + "saMkaTA", + "vitaRqA", + "kuzwavid", + "kuzWavid", + "janavAda", + "janevAda", + "janovAda", + "vftti", + "saMgfha", + "guRagaRa", + "Ayurveda", +]; + +/// 4.4.103 guqAdiByaz WaY (145) +pub const GUDA_ADI: &[&str] = &[ + "guqa", + "kulmAza", + "saktu", + "apUpa", + "mAMsOdana", + "ikzu", + "veRu", + "saNgrAma", + "saMGAta", + "saMkAma", + "saMvAha", + "pravAsa", + "nivAsa", + "upavAsa", +]; + +/// 5.1.66 daRqAdiByaH (152) +pub const DANDA_ADI: &[&str] = &[ + "daRqa", + "musala", + "maDuparka", + "kaSA", + "arGa", + "meGa", + "meDA", + "suvarRa", + "udaka", + "vaDa", + "yuga", + "guhA", + "BAga", + "iBa", + "BaNga", +]; + +/// 5.1.122 pRTvAdiBya imanijvA (162) +pub const PRTHU_ADI: &[&str] = &[ + "pfTu", "mfdu", "mahat", "pawu", "tanu", "laGu", "bahu", "sADu", "veRu", "ASu", "bahula", + "guru", "daRqa", "uru", "KaRqa", "caRqa", "bAla", "akiYcana", "hoqa", "pAka", "vatsa", "manda", + "svAdu", "hrasva", "dIrGa", "priya", "vfza", "fju", "kzipra", "kzupra", "kzudra", +]; + +/// 5.2.36 tadasya saMjAtaM tArakAdiBya itac (172) +pub const TARAKA_ADI: &[&str] = &[ + "tArakA", + "puzpa", + "karRaka", + "maYjarI", + "fjIza", + "kzaRa", + "sUtra", + "mUtra", + "nizkramaRa", + "purIza", + "uccAra", + "pracAra", + "vicAra", + "kuqmala", + "kaRwaka", + "musala", + "mukula", + "kusuma", + "kutUhala", + "stabaka", + "stavaka", + "kisalaya", + "pallava", + "KaRqa", + "vega", + "nidrA", + "mudrA", + "buBukzA", + "DenuzyA", + "pipAsA", + "SradDA", + "aBra", + "pulaka", + "aNgAraka", + "varRaka", + "droha", + "doha", + "suKa", + "duHKa", + "utkaRWA", + "Bara", + "vyADi", + "varman", + "vraRa", + "gOrava", + "SAstra", + "taraNga", + "tilaka", + "candraka", + "anDakAra", + "garva", + "kumura", + "mukura", + "harza", + "utkarza", + "raRa", + "kuvalaya", + "garGa", + "kzuD", + "sImanta", + "jvara", + "gara", + "roga", + "romAYca", + "paRqA", + "kujjala", + "tfz", + "koraka", + "kallola", + "sTapuwa", + "Pala", + "kaYcuka", + "SfNgAra", + "aNkura", + "SEvala", + "bakula", + "Svamra", + "ArAla", + "kalaNka", + "kardama", + "kandala", + "mUrcCA", + "aNgAra", + "hastaka", + "pribimba", + "viGnatantra", + "pratyaya", + "dIkzA", + "garja", +]; + +/// 5.3.101 SAKAdiByo yat (191) +pub const SHAKHA_ADI: &[&str] = &[ + "SAKA", "muKa", "jaGana", "SfNga", "meGa", "caraRa", "skanDa", "Siras", "uras", "agra", + "Sarana", +]; + +/// 5.3.107 SarkarAdiByo 'R (192) +pub const SHARKARA_ADI: &[&str] = &[ + "SarkarA", + "kapAlikA", + "pizwika", + "puRqarIka", + "Satapatra", + "goloman", + "gopucCa", + "narAcI ", + "nakulA", + "sikatA", +]; + +/// 5.3.108 aNgulyAdiByaz Wak (193) +pub const ANGULI_ADI: &[&str] = &[ + "aNguli", "Baruja", "baBru", "valgu", "maRqara", "maRqala", "Sazkula", "kapi", "udaSvit", + "goRI", "uras", "SiKara", "kuliSa", +]; + +/// 5.3.116 dAmanyAditrigartazazWAc CaH (194) +pub const DAMANI_ADI: &[&str] = &[ + "dAmanI", + "Olapi", + "AkidantI", + "kAkaranti", + "kAkadanti", + "Satruntapi", + "sArvaseni", + "bindu", + "mOYjAyana", + "ulaBa", + "sAvitrIputra", +]; + +/// 5.3.117 parSvAdi-yODeyAdiByAmaRaYO (195) +pub const PARSHU_ADI: &[&str] = &[ + "parSu", + "asura", + "rakzas", + "bAhlIka", + "vayas", + "marut", + "daSArha", + "piSAca", + "viSAla", + "aSani", + "kArzApaRa", + "satvat", + "vasu", + "parSvAdiH", +]; + +/// 5.3.117 parSvAdi-yODeyAdiByAmaRaYO (196) +pub const YAUDHEYA_ADI: &[&str] = &[ + "yODeya", "kOSeya", "krOSeya", "SOkreya", "SOBreya", "DArteya", "vArteya", "jAbAleya", + "trigarta", "Barata", "uSInara", +]; + +/// 5.4.3 sTUlAdiByaH prakAravacane kan (197) +pub const STHULA_ADI: &[&str] = &[ + "sTUla", + "aRu", + "mAza", + "izu", + "kfzRa", + "yava", + "ikzu", + "tila", + "pAdya", + "kAla", + "avadAta", + "gomUtra", + "surA", + "jIrRa", + "patra", + "mUla", + "kumArIputra", + "kumAra", + "SvaSura", + "maRi", +]; + +/// 5.4.3 uraH-praBftiByaH kap +pub const URAH_PRABHRTI: &[&str] = &[ + "uras", "sarpis", "upAdah", "pums", "anaquh", "payas", "nO", "lakzmI", "daDi", "maDu", "SAlI", + "SAli", +]; + +// 5.4.29 yAvAviByaH kan (252) +// TODO: others +pub const YAVA_ADI: &[&str] = &[ + "yAva", "maRi", "asTi", "caRqa", "pIta", "stamBa", "ftu", "paSu", "aRu", "putra", "snAta", + "SUnya", "dAna", "tanu", "jYAta", +]; + +// 5.4.34 vinayAdiByaz Wak (253) +pub const VINAYA_ADI: &[&str] = &[ + "vinaya", + "samaya", + "upAya", + "saNgati", + "kaTaYcit", + "akasmAt", + "samayAcAra", + "upacAra", + "samAcAra", + "vyavahAra", + "sampradAna", + "samutkarza", + "samUha", + "viSeza", + "atyaya", +]; diff --git a/vidyut-prakriya/src/it_agama.rs b/vidyut-prakriya/src/it_agama.rs index 1450b27..05cc11a 100644 --- a/vidyut-prakriya/src/it_agama.rs +++ b/vidyut-prakriya/src/it_agama.rs @@ -27,14 +27,13 @@ Order of operations: */ use crate::args::Gana::*; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::{Code, Prakriya}; +use crate::core::{Term, TermView}; use crate::dhatu_gana as gana; -use crate::filters as f; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya}; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::{Term, TermView}; use lazy_static::lazy_static; lazy_static! { @@ -47,7 +46,7 @@ lazy_static! { fn is_hacky_eka_ac(t: &Term) -> bool { // HACK to have ekac apply for am-Agama - f::is_eka_ac(t) || t.text.contains("fa") + t.is_ekac() || t.text.contains("fa") } /// Returns whether the given term is vet by 7.2.44. @@ -98,7 +97,7 @@ impl<'a> ItPrakriya<'a> { /// Returns the view before which we might add iw-Agama. fn next(&self) -> TermView { - self.p.view(self.i_next).expect("present") + self.p.pratyaya(self.i_next).expect("present") } /// Returns whether the term before the anga has an upasarga with one of the given values. @@ -174,7 +173,7 @@ fn try_lengthen_it_agama(p: &mut Prakriya, i: usize) -> Option<()> { } let dhatu = p.get(i - 1)?; - let n = p.view(i)?; + let n = p.pratyaya(i)?; let last = p.terms().last()?; if last.has_lakshana("li~w") { @@ -191,7 +190,7 @@ fn try_lengthen_it_agama(p: &mut Prakriya, i: usize) -> Option<()> { } else if n.slice().iter().any(|t| t.has_u("si~c")) && last.is_parasmaipada() { p.step("7.2.40"); } else { - p.run_optional_at("7.2.38", i, op::text("I")); + p.optional_run_at("7.2.38", i, op::text("I")); } } @@ -205,7 +204,7 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option return None; } - let ktvi = n.last()?.has_u("ktvA"); + let ktvi = n.last().has_u("ktvA"); if n.has_u("kvasu~") { let anga = ip.anga(); @@ -353,7 +352,7 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option // cikarizati, jigarizati, didarizate, diDarizate, papracCizati ip.try_add("7.2.75"); } - } else if ktvi || n.last()?.is_nistha() { + } else if ktvi || n.last().is_nistha() { if anga.has_text("kliS") { // kliSitvA, klizwvA ip.optional_try_add("7.2.50"); @@ -433,7 +432,7 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option let mut can_run = true; // TODO: Adikarmani. if ip.p.any(&[T::Bhave]) { - can_run = ip.p.run_optional("7.2.17", |_| {}); + can_run = ip.p.optional_run("7.2.17", |_| {}); } if can_run { ip.try_block("7.2.16"); @@ -550,7 +549,7 @@ fn run_sarvadhatuke_for_term(ip: &mut ItPrakriya) -> Option<()> { let anga = ip.anga(); let i_n = ip.i_next; - let tin = n.last()?; + let tin = n.last(); let rudh_adi = &["rudi~r", "Yizva\\pa~", "Svasa~", "ana~", "jakza~"]; let is_aprkta = n.slice().iter().map(|t| t.text.len()).sum::() == 1; @@ -569,7 +568,7 @@ fn run_sarvadhatuke_for_term(ip: &mut ItPrakriya) -> Option<()> { let is_pit = n.has_tag(T::pit) && !n.has_tag(T::Nit); if n.has_adi(&*HAL) && n.has_tag(T::Sarvadhatuka) && is_pit && is_aprkta { let use_at = - ip.p.run_optional("7.3.99", |p| op::insert_agama_before(p, i_n, "aw")); + ip.p.optional_run("7.3.99", |p| op::insert_agama_before(p, i_n, "aw")); if !use_at { ip.p.run("7.3.98", |p| op::insert_agama_before(p, i_n, "Iw")); } @@ -618,7 +617,7 @@ pub fn run_before_attva(p: &mut Prakriya) -> Option<()> { // Add the `Ittva` tag so that we can skip this term next time. p.set(i, |t| t.add_tag(T::FlagIttva)); - if p.view(i_n).is_some() { + if p.pratyaya(i_n).is_some() { let mut ip = ItPrakriya::new(p, i, i_n); run_valadau_ardhadhatuke_before_attva_for_term(&mut ip); run_sarvadhatuke_for_term(&mut ip); diff --git a/vidyut-prakriya/src/it_samjna.rs b/vidyut-prakriya/src/it_samjna.rs index 972851a..b2febe8 100644 --- a/vidyut-prakriya/src/it_samjna.rs +++ b/vidyut-prakriya/src/it_samjna.rs @@ -4,10 +4,10 @@ //! //! The most "core" prakaraṇa is the it-saṁjñā-prakaraṇa, which identifies remove different `it` //! sounds from an upadeśa. Most derivations use this prakaraṇa at least once. -use crate::errors::*; -use crate::prakriya::Prakriya; +use crate::core::errors::*; +use crate::core::Prakriya; +use crate::core::{Tag as T, Term}; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; use compact_str::CompactString; use lazy_static::lazy_static; @@ -25,6 +25,10 @@ fn get_adi(s: &CompactString) -> Option { s.as_bytes().first().map(|u| *u as char) } +fn is_cutu_exempt_taddhita(t: &Term) -> bool { + t.is_taddhita() && t.has_u_in(&["jAtIyar", "caraw", "cuYcup", "caRap"]) +} + /// Runs rule 1.3.2 ("upadeśe janunāsika iṭ"). fn run_1_3_2(p: &mut Prakriya, i_term: usize, before: &mut CompactString) -> Option<()> { let term = p.get_mut(i_term)?; @@ -145,12 +149,23 @@ pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { if let Some(t) = p.get_mut(i) { if HAL.contains(antya) && !irit { let vibhaktau_tusmah = t.is_vibhakti() && TUSMA.contains(antya); - if !vibhaktau_tusmah { + + // Not sure how this is supposed to work: + // + // - 5.3.12 introduces at-pratyaya (kim + at --> kva). + // - 5.3.1 (prAg diSo viBaktiH) includes 5.3.12 as part of its adhikara. + // - So, these pratyayas are in scope for 1.3.4. Example: dAnIm-pratyaya (5.3.18) for + // idAnIm. + // - But, at-pratyaya *should* have its final t deleted. + // + // For now, hard-code an exception. + let is_vibhakti_exception = t.has_u("at") && t.is_taddhita(); + if vibhaktau_tusmah && !is_vibhakti_exception { + p.step("1.3.4"); + } else { t.add_tag(T::parse_it(antya)?); temp.truncate(temp.len() - 1); p.step("1.3.3"); - } else { - p.step("1.3.4"); } } } @@ -186,7 +201,7 @@ pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { t.add_tag(T::parse_it(adi)?); temp_slice = &temp_slice[1..]; p.step("1.3.6") - } else if CUTU.contains(adi) { + } else if CUTU.contains(adi) && !is_cutu_exempt_taddhita(t) { // The sounds C, J, W, and Q are replaced later in the grammar. // If we substitute them now, those rules will become vyartha. if !CUTU_EXCEPTION.contains(adi) { @@ -225,7 +240,7 @@ pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { #[cfg(test)] mod tests { use super::*; - use crate::term::Term; + use crate::core::Term; fn check(t: Term) -> Term { let mut p = Prakriya::new(); diff --git a/vidyut-prakriya/src/krt.rs b/vidyut-prakriya/src/krt.rs index d159c3d..88a87a2 100644 --- a/vidyut-prakriya/src/krt.rs +++ b/vidyut-prakriya/src/krt.rs @@ -1,5 +1,5 @@ use crate::args::KrdantaArgs; -use crate::prakriya::Prakriya; +use crate::core::Prakriya; mod basic; mod unadi_sutras; diff --git a/vidyut-prakriya/src/krt/basic.rs b/vidyut-prakriya/src/krt/basic.rs index b78e0a7..d291b36 100644 --- a/vidyut-prakriya/src/krt/basic.rs +++ b/vidyut-prakriya/src/krt/basic.rs @@ -61,15 +61,15 @@ use crate::args::Gana; use crate::args::KrtArtha::*; use crate::args::Taddhita; use crate::args::{BaseKrt, Krt}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::dhatu_gana as gana; use crate::it_samjna; use crate::krt::utils::KrtPrakriya; -use crate::operators as op; -use crate::prakriya::{Prakriya, Rule}; use crate::sounds::{s, Set}; use crate::stem_gana::TYAD_ADI; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -780,6 +780,8 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { } else if krt == kvin { if !upapada.has_text("udaka") && dhatu.has_text("spfS") { kp.try_add("3.2.58", kvin); + } else if dhatu.has_u("df\\Si~r") { + kp.try_add("3.2.60", kvin); } else { let code = "3.2.59"; if upapada.has_text("ftu") && dhatu.has_u("ya\\ja~^") { @@ -867,6 +869,15 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { _ => {} } + if kp.has_krt && krt == kvip { + let dhatu = kp.dhatu(); + if dhatu.has_text("Sri") { + // SrI + // TODO: others + kp.p.run_at("3.2.178.v1", i_dhatu, |t| t.set_antya("I")); + } + } + Some(kp.has_krt) } @@ -922,7 +933,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { let added = kp.try_add("3.1.96", krt); if added && krt == K::tavyat && kp.dhatu().has_u("va\\sa~") { // vAstavya - kp.p.run_optional_at("3.1.96.v1", i + 1, |t| t.add_tag(T::Rit)); + kp.p.optional_run_at("3.1.96.v1", i + 1, |t| t.add_tag(T::Rit)); } } @@ -954,11 +965,11 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { kp.optional_try_add("3.1.120", K::kyap); } else { // This rule makes rule 3.1.110 optional for vfz. - skip_3_1_110 = kp.p.run_optional("3.1.120", |_| {}); + skip_3_1_110 = kp.p.optional_run("3.1.120", |_| {}); } } else if dhatu.has_text("mfj") { // This rule makes rule 3.1.110 optional for mfj. - skip_3_1_110 = kp.p.run_optional("3.1.113", |_| {}); + skip_3_1_110 = kp.p.optional_run("3.1.113", |_| {}); } // Specific rules (required) @@ -1117,6 +1128,8 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { K::Rvi => { if dhatu.has_u("Ba\\ja~^") { kp.try_add("3.2.62", krt); + } else if i > 0 && dhatu.has_u("va\\ha~^") { + kp.try_add("3.2.64", krt); } } @@ -1126,6 +1139,9 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { kp.try_add(code, krt); } else if krt == K::vic && dhatu.has_text("riz") { kp.try_add(code, krt); + } else { + // suSarmA, prAtaritvan, vijAvA, rez, ... + kp.try_add("3.2.76", krt); } } @@ -1137,7 +1153,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if kp.has_krt { let i_last = kp.p.terms().len() - 1; - kp.p.run_at("1.1.26", i_last, op::add_tag(T::Nistha)); + kp.p.add_tag_at("1.1.26", i_last, T::Nistha); } } @@ -1208,7 +1224,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if has_pada_match && !kp.has_krt { let i_la = kp.p.terms().len() - 1; kp.try_replace_lakara("3.2.128", i_la, krt); - kp.p.run_at("3.2.127", i_la, op::add_tag(T::Sat)); + kp.p.add_tag_at("3.2.127", i_la, T::Sat); } } diff --git a/vidyut-prakriya/src/krt/unadi_sutras.rs b/vidyut-prakriya/src/krt/unadi_sutras.rs index c6a8ba1..cf1a718 100644 --- a/vidyut-prakriya/src/krt/unadi_sutras.rs +++ b/vidyut-prakriya/src/krt/unadi_sutras.rs @@ -13,9 +13,7 @@ The pratyayas in the Unadipatha enter the Ashtadhyayi through rule 3.3.1: ### Design notes -Our module below is a work-in-progress sketch and uses the version of the text available [on - -For now, we have stored Unadi pratyayas on our `Krt` enum. Points in favor of this decision: +Should ordinary krt-pratyayas and unadi-pratyayas be stored on the same enum? Points in favor: - Unadi pratyayas are "just" krt pratyayas, so it makes sense to store them in the same way. - Storing all krt pratyayas in the same way is simpler for downstream code. For example, storing @@ -29,29 +27,28 @@ Points against: - Our system cannot distinguish between these two kinds of pratyayas, which affects how downstream code interacts with this project. -As this module develops, we will probably split the Unadi pratyayas into their own enum. - -[unadi]: https://ashtadhyayi.com/unaadi +We found the points against more convincing and have stored these pratyayas in two separate enums. */ use crate::args::{Krt, Unadi}; +use crate::core::Tag as T; +use crate::core::{Prakriya, Rule}; use crate::krt::utils::KrtPrakriya; -use crate::prakriya::{Prakriya, Rule}; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; use lazy_static::lazy_static; lazy_static! { static ref NAM: Set = s("Yam"); } -/// A helper function that updates the pratyaya by marking it with the given `tag`. +/// A helper function that marks the pratyaya with the given `tag`. fn mark_as(tag: T) -> impl Fn(&mut Prakriya) { move |p| { - let i_last = p.terms().len() - 1; - p.set(i_last, |t| t.add_tag(tag)); + let i_pratyaya = p.terms().len() - 1; + p.set(i_pratyaya, |t| t.add_tag(tag)); } } +/// A helper function that replaces the dhatu's text. fn set_text(text: &'static str) -> impl Fn(&mut Prakriya) { move |p| { let i_dhatu = p.terms().len() - 2; @@ -59,6 +56,7 @@ fn set_text(text: &'static str) -> impl Fn(&mut Prakriya) { } } +/// A helper function that replaces the last sound of the dhatu. fn set_antya(text: &'static str) -> impl Fn(&mut Prakriya) { move |p| { let i_dhatu = p.terms().len() - 2; @@ -66,9 +64,12 @@ fn set_antya(text: &'static str) -> impl Fn(&mut Prakriya) { } } +/// Tries to add the given unAdi-pratyaya to the prakriya. +/// +/// Returns: whether the function added a pratyaya. pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { use crate::args::Unadi as U; - use Rule::UP; + use Rule::Unadipatha as UP; let i = p.find_first(T::Dhatu)?; @@ -83,9 +84,9 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { // For convenience below, wrap `Prakriya` in a new `KrtPrakriya` type that contains `krt` and // records whether or not any of these rules were applied. let mut kp = KrtPrakriya::new(p, krt); + let i_dhatu = kp.i_dhatu; let dhatu = kp.dhatu(); - let has_upasarga = |text| i > 0 && kp.p.has(i, |t| t.is_upasarga() && t.has_text(text)); // NOTE: some of the older code checks against the aupadeshika form of the dhatu. But since the @@ -122,8 +123,10 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { ]) { kp.try_add(UP("1.10"), krt); } else if dhatu.has_text("syand") { + // sinDu kp.try_add_with(UP("1.11"), krt, set_text("sinD")); } else if dhatu.has_text("und") { + // indu kp.try_add_with(UP("1.12"), krt, set_text("ind")); } else if dhatu.has_text("Iz") { kp.try_add_with(UP("1.13"), krt, |p| { @@ -131,12 +134,25 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { p.set(i + 1, |t| t.add_tag(T::kit)); }); } else if dhatu.has_text("skand") { + // kandu kp.try_add_with(UP("1.14"), krt, set_text("kand")); } else if dhatu.has_text("sfj") { + // rajju kp.try_add_with(UP("1.15"), krt, set_text("rajj")); } else if dhatu.has_text("kft") { + // tarku kp.try_add_with(UP("1.16"), krt, set_text("tfk")); + } else if dhatu.has_text("val") { + // valgu + kp.try_add_with(UP("1.19"), krt, set_text("valg")); + } else if dhatu.has_u("So\\") { + // SiSu + kp.try_add_with(UP("1.20"), krt, |p| { + p.set(i, |t| t.set_text("SiS")); + p.set(i + 1, |t| t.add_tag(T::kit)); + }); } else if dhatu.has_text("yA") { + // yayu kp.try_add_with(UP("1.21"), krt, set_text("yay")); } } @@ -145,6 +161,12 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { kp.try_add(UP("1.45"), krt); } } + U::qavatu => { + if dhatu.has_u("BA\\") { + // Bavat + kp.try_add(UP("1.63"), krt); + } + } U::tun => { if dhatu.has_u_in(&[ "zi\\Y", "tanu~^", "ga\\mx~", "masI~", "zaca~\\", "ava~", "quDA\\Y", "kru\\Sa~", @@ -194,6 +216,12 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { kp.try_add_with(UP("1.147"), krt, set_text("grIz")); } } + // TODO: not in ashtadhyayi.com's Unadipatha, but mentioned in KV 1.1.60. + U::radAnuk => { + if dhatu.has_u("jIva~") { + kp.try_add(UP("1.163"), krt); + } + } U::eRu => { if dhatu.has_text_in(&["kf", "hf"]) { kp.try_add(UP("2.1"), krt); @@ -310,8 +338,10 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { } U::ksi => { if dhatu.has_u_in(&["pluza~", "kuza~", "Su\\za~"]) { + // plukzi, kukzi, Sukzi kp.try_add(UP("3.155"), krt); } else if dhatu.has_u("aSU~") { + // akzi kp.try_add_with(UP("3.156"), krt, mark_as(T::nit)); } } @@ -455,8 +485,10 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { } U::amac => { if dhatu.has_u("praTa~\\") { + // praTama kp.try_add(UP("5.68"), krt); } else if dhatu.has_u("cara~") { + // carama kp.try_add(UP("5.69"), krt); } } diff --git a/vidyut-prakriya/src/krt/utils.rs b/vidyut-prakriya/src/krt/utils.rs index f33fb66..eb0d2a3 100644 --- a/vidyut-prakriya/src/krt/utils.rs +++ b/vidyut-prakriya/src/krt/utils.rs @@ -1,9 +1,9 @@ use crate::args::{Artha, BaseKrt, Krt, KrtArtha}; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Prakriya, Rule}; -use crate::tag::Tag as T; -use crate::term::Term; impl Krt { /// Converts this krt-pratyaya to an appropriate `Term`. @@ -38,7 +38,7 @@ impl Krt { /// - remembers which `krt` pratyaya the caller wishes to add, which simplifies the calling API. /// - records whether a `krt` pratyaya has been added or not, which simplifies the control flow for /// optional rules. -pub struct KrtPrakriya<'a> { +pub(crate) struct KrtPrakriya<'a> { /// The underlying prakriya. pub p: &'a mut Prakriya, /// The first index of the dhatu. @@ -163,6 +163,11 @@ impl<'a> KrtPrakriya<'a> { let krt = krt.into(); self.had_match = true; if self.krt == krt && !self.has_krt { + self.p.set(i_lakara, |t| { + t.add_tag(T::Krt); + // Remove `fdit` from `lf~w` so that we don't trigger 7.1.70 (ugidacAm ...). + t.remove_tag(T::fdit); + }); op::adesha(rule, self.p, i_lakara, krt.as_str()); self.has_krt = true; true @@ -172,14 +177,22 @@ impl<'a> KrtPrakriya<'a> { } pub fn do_nipatana(&mut self, rule: impl Into, sub: &str) { - self.p.run(rule, op::nipatana(sub)); + self.p.run(rule, |p| { + op::nipatana(sub)(p); + + // For later rules, also push an empty version of the pratyaya. + // (Example: 8.2.62 kvin-pratyayasya kuH) + let mut t = self.krt.to_term(); + t.set_text(""); + p.push(t); + }); self.had_match = true; self.has_krt = true } pub fn optional_do_nipatana(&mut self, rule: impl Into, sub: &str) -> bool { self.had_match = true; - if self.p.run_optional(rule, op::nipatana(sub)) { + if self.p.optional_run(rule, op::nipatana(sub)) { self.has_krt = true; true } else { @@ -190,6 +203,8 @@ impl<'a> KrtPrakriya<'a> { /// If there's a match, adds the given `krt` pratyaya then runs `func`. /// /// This method does nothing if a krt pratyaya has already been added. + /// + /// Returns: whether `krt` was added. pub fn try_add_with( &mut self, rule: impl Into, diff --git a/vidyut-prakriya/src/la_karya.rs b/vidyut-prakriya/src/la_karya.rs index d65db96..7eb28a2 100644 --- a/vidyut-prakriya/src/la_karya.rs +++ b/vidyut-prakriya/src/la_karya.rs @@ -1,16 +1,15 @@ use crate::args::Lakara; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Code, Prakriya}; use crate::it_samjna; -use crate::prakriya::{Code, Prakriya}; -use crate::tag::Tag as T; -use crate::term::Term; fn add_la(rule: Code, p: &mut Prakriya, i: usize, la: &str) { - let mut la = Term::make_upadesha(la); - la.add_tag(T::Pratyaya); - la.add_tag(T::La); - - p.insert_after(i, la); - p.step(rule); + p.run(rule, |p| { + let mut la = Term::make_upadesha(la); + la.add_tags(&[T::Pratyaya, T::La]); + p.insert_after(i, la) + }); it_samjna::run(p, i + 1).expect("should always succeed"); } diff --git a/vidyut-prakriya/src/lib.rs b/vidyut-prakriya/src/lib.rs index 0775426..784603b 100644 --- a/vidyut-prakriya/src/lib.rs +++ b/vidyut-prakriya/src/lib.rs @@ -3,9 +3,9 @@ #![deny(clippy::unwrap_used)] pub use crate::ashtadhyayi::{Ashtadhyayi, AshtadhyayiBuilder}; +pub use crate::core::errors::Error; +pub use crate::core::{Prakriya, Rule, RuleChoice, Step}; pub use crate::dhatupatha::Dhatupatha; -pub use crate::errors::Error; -pub use crate::prakriya::{Prakriya, Rule, RuleChoice, Step}; // Public modules. // - `args` defines the API contract. @@ -15,8 +15,6 @@ pub use crate::prakriya::{Prakriya, Rule, RuleChoice, Step}; pub mod args; pub mod dhatupatha; -mod errors; - mod binary_only; #[doc(hidden)] pub mod private { @@ -24,18 +22,9 @@ pub mod private { pub use crate::binary_only::*; } -// Data structures -mod char_view; -mod prakriya; -mod prakriya_stack; +// Data structures and utilities +mod core; mod sounds; -mod tag; -mod term; - -// Utility functions -mod filters; -mod iterators; -mod operators; // Rules mod ac_sandhi; @@ -47,6 +36,7 @@ mod atmanepada; mod dhatu_gana; mod dhatu_karya; mod dvitva; +mod ganapatha; mod it_agama; mod it_samjna; mod krt; @@ -54,12 +44,14 @@ mod la_karya; mod linganushasanam; mod misc; mod pratipadika_karya; +mod samasa; mod samjna; mod samprasarana; mod sanadi; mod stem_gana; mod stritva; mod sup_karya; +mod sutrapatha; mod taddhita; mod tin_pratyaya; mod tripadi; diff --git a/vidyut-prakriya/src/linganushasanam.rs b/vidyut-prakriya/src/linganushasanam.rs index c6839b5..7e0f054 100644 --- a/vidyut-prakriya/src/linganushasanam.rs +++ b/vidyut-prakriya/src/linganushasanam.rs @@ -2,33 +2,542 @@ Implements rules from the pāṇiṇīyaliṅgānuśāśanam, which assigns lingas to various terms. */ -use crate::prakriya::{Prakriya, Rule}; -use crate::tag::Tag as T; +use crate::core::Tag as T; +use crate::core::{Prakriya, Rule}; + +const DVARA_ADI: &[&str] = &[ + "dvAra", + "agra", + "sPara", + "takra", + "vakra", + "vapra", + "kzipra", + "kzudra", + "nAra", + "tIra", + "dUra", + "kfcCra", + "randRa", + "aSra", + "SvaBra", + "BIra", + "gaBIra", + "krUra", + "vicitra", + "keyUra", + "kedAra", + "udAra", + "ajasra", + "SarIra", + "kandara", + "mandAra", + "paYjara", + "ajara", + "jaWara", + "jira", + "vEra", + "cAmara", + "puzkara", + "gahvara", + "kuhara", + "kuwIra", + "kulIra", + "catvara", + "kASmIra", + "nIra", + "ambara", + "SiSira", + "tantra", + "yantra", + "nakzatra", + "kzetra", + "mitra", + "kalatra", + "citra", + "mUtra", + "sUtra", + "vaktra", + "netra", + "gotra", + "aNgulitra", + "Balatra", + "Sastra", + "SAstra", + "vastra", + "patra", + "pAtra", + "Catra", +]; + +#[derive(Debug)] +struct LingaPrakriya<'a> { + p: &'a mut Prakriya, + done: bool, +} + +impl<'a> LingaPrakriya<'a> { + fn new(p: &'a mut Prakriya) -> Self { + LingaPrakriya { p, done: false } + } + fn mark_pum(&mut self, rule: Rule) { + if !self.done { + self.p.add_tag(T::Pum); + self.p.step(rule); + } + self.done = true; + } + + fn mark_stri(&mut self, rule: Rule) { + if !self.done { + self.p.add_tag(T::Stri); + self.p.step(rule); + } + self.done = true; + } + + fn mark_napumsaka(&mut self, rule: Rule) { + if !self.done { + self.p.add_tag(T::Napumsaka); + self.p.step(rule); + } + self.done = true; + } + + fn mark_pum_napumsaka(&mut self, _rule: Rule) {} + + fn mark_stri_napumsaka(&mut self, _rule: Rule) {} + + fn mark_stri_pum(&mut self, _rule: Rule) {} +} /// Runs the linganushasana rules over the given prakriya. pub fn run(p: &mut Prakriya) -> Option<()> { use Rule::Linganushasana as L; - let last = p.terms().last()?; - if last.is_taddhita() && last.has_u("tal") { - p.add_tag(T::Stri); - p.step(L("17")); - } else if last.is_krt() { - if last.has_u_in(&["GaY", "ap"]) { - p.add_tag(T::Pum); - p.step(L("36")); + let mut lp = LingaPrakriya::new(p); + let i_last = lp.p.terms().len() - 1; + + // strI (2 - 34) + // ============= + + let last = lp.p.get(i_last)?; + if last.has_antya('f') && last.has_u_in(&["mAtf", "duhitf", "svasf", "yAtf", "nanAndf"]) { + // mAtf, ... + lp.mark_stri(L("3")); + } else if last.is_unadi() && last.has_u_in(&["ani", "U"]) { + // avani, camU, ... + lp.mark_stri(L("4")); + } else if last.has_text_in(&["aSani", "BaraRi", "araRi"]) { + lp.mark_stri_pum(L("5")); + } else if last.is_unadi() && last.has_u_in(&["mi", "ni"]) { + // BUmi, glAni, ... + lp.mark_stri(L("6")); + } else if last.is_pratyaya() && last.has_u("ktin") { + // kfti, ... + lp.mark_stri(L("9")); + } else if last.is_pratyaya() && last.has_antya('I') { + // lakzmIH ... + lp.mark_stri(L("10")); + } else if last.is_pratyaya() && (last.has_antya('U') || last.has_u("NAp")) { + // kurUH, vidyA, ... + lp.mark_stri(L("11")); + } else if last.is_taddhita() && last.has_u("tal") { + // SuklatA, ... + lp.mark_stri(L("17")); + } else if last.has_text_in(&["BUmi", "vidyut", "sarit", "latA", "vanitA"]) { + // TODO: others + lp.mark_stri(L("18")); + } else if last.has_text("yAdas") { + // yAdaH + lp.mark_stri(L("19")); + } else if last.has_text_in(&["BAs", "sruj", "sraj", "diS", "uzRih", "upAnah"]) { + // BAH, ... + lp.mark_stri(L("20")); + } else if last.has_text_in(&["gfhasTURa", "SaSorRa"]) { + // gfhasTURam, SaSorRam + lp.mark_napumsaka(L("22")); + } else if last.has_text_in(&["sTURa", "UrRa"]) { + // sTURA, sTURam, ... + lp.mark_stri_napumsaka(L("21")); + } + + // pumAn (35 - 117) + // ================ + + let last = lp.p.get(i_last)?; + if last.is_krt() { + let i_dhatu = lp.p.find_last_where(|t| t.is_dhatu())?; + let dhatu = lp.p.get(i_dhatu)?; + + if last.has_text_in(&["Baya", "liNga", "Baga", "pada"]) { + // Bayam, ... + lp.mark_napumsaka(L("38")); + } else if last.has_u_in(&["GaY", "ap"]) { + lp.mark_pum(L("36")); + } else if last.has_u_in(&["Ga", "ac"]) { + lp.mark_pum(L("37")); } else if last.has_u("naN") { - let i_dhatu = p.find_last_where(|t| t.is_dhatu())?; - let dhatu = p.get(i_dhatu)?; if dhatu.has_text("yAc") { - p.add_tag(T::Stri); - p.step(L("40")); + lp.mark_stri(L("40")); } else { - p.add_tag(T::Pum); - p.step(L("39")); + lp.mark_pum(L("39")); } + } else if dhatu.has_tag(T::Ghu) && last.has_u("ki") { + lp.mark_pum(L("41")); + } + } else if last.has_text_in(&[ + "deva", "asura", "Atman", "svarga", "giri", "samudra", "naKa", "keSa", "danta", "stana", + "Buja", "kaRWa", "Kaqga", "Sara", "PaNka", + ]) { + // TODO: the rule accepts pratipadikas with these *meanings*, not (just) the pratipadikas + // themselves. + lp.mark_napumsaka(L("43")); + } else if last.has_text_in(&["trivizwapa", "triBuvana"]) { + // trivizwapam, ... + // (exception to 43) + lp.mark_napumsaka(L("44")); + } else if last.has_text_in(&["dyo", "div"]) { + // dyOH + // (exception to 43) + lp.mark_stri(L("45")); + } else if last.has_text_in(&["izu", "bAhu"]) { + // izuH, ... + // (exception to 43) + lp.mark_stri_pum(L("46")); + } else if last.has_text_in(&["bARa", "kARqa"]) { + // bARaH, ... + // (exception to 43) + lp.mark_pum_napumsaka(L("47")); + } else if last.has_antya('n') { + // rAjA, ... + lp.mark_pum(L("48")); + } else if last.has_text_in(&["kratu", "puruza", "kapola", "gulPa", "meDa"]) { + // TODO: the rule accepts pratipadikas with these *meanings*, not (just) the pratipadikas + // themselves. + // kratuH, ... + } else if last.has_text("aBra") { + // aBram + // (exception to 49) + lp.mark_napumsaka(L("50")); + } else if last.has_antya('u') { + if last.has_text_in(&[ + "Denu", "rajju", "kuhu", "sarayu", "tanu", "reRu", "priyaNgu", + ]) { + // DenuH, ... + // TODO: rule has kuhU in most editions but this section is for udanta -- typo for + // kuhu? + lp.mark_stri(L("52")); + } else if last.has_text_in(&[ + "SmaSru", "jAnu", "vasu", "svAdu", "aSru", "jatu", "trapu", "tAlu", + ]) { + // SmaSru, ... + lp.mark_napumsaka(L("54")); + } else if last.has_text_in(&["madgu", "maDu", "sIDu", "SIDu", "sAnu", "kamaRqalu"]) { + // madguH, madgu + lp.mark_pum_napumsaka(L("56")); + } else { + // praBuH, ... + lp.mark_pum(L("51")); + } + } else if last.ends_with("ru") { + if last.has_text_in(&["dAru", "kaSeru", "jatu", "vastu", "mastu"]) { + lp.mark_napumsaka(L("58")); + } else { + lp.mark_pum(L("57")); + } + } + + // prAgaraSmer akArANtaH (60 - 100) + // ================================ + // (nested within pumAn adhikAra) + + let last = lp.p.get(i_last)?; + let at = last.has_antya('a'); + // adhikAra starts at rule 60 and ends at rule 100. + if at && last.has_upadha('k') { + if last.has_text_in(&["cibuka", "SAlUka", "prAtipadika", "aMSuka", "ulmuka"]) { + lp.mark_napumsaka(L("62")); + } else if last.has_text_in(&[ + "kaRwaka", "anIka", "saraka", "modaka", "cazaka", "mastaka", "pustaka", "taqAka", + "nizka", "Suzka", "varcaska", "pinAka", "BARqaka", "piRqaka", "kawaka", "SaRqaka", + "piwaka", "tAlaka", "Palaka", "pulAka", + ]) { + lp.mark_pum_napumsaka(L("62")); + } else { + lp.mark_pum(L("61")); + } + } else if at && last.has_upadha('w') { + if last.has_text_in(&[ + "kirIwa", "mukuwa", "lalAwa", "vawa", "vIwa", "SfRgAwa", "karAwa", "lozwa", + ]) { + lp.mark_pum_napumsaka(L("65")); + } else if last.has_text_in(&[ + "kuwa", "kUwa", "kawa", "pawa", "kavAwa", "karpawa", "nawa", "nikawa", "kIwa", "kawa", + ]) { + lp.mark_pum_napumsaka(L("66")); + } else { + lp.mark_pum(L("64")); + } + } else if at && last.has_upadha('R') { + // guRaH, ... + lp.mark_pum(L("67")); + } else if at && last.has_upadha('T') { + // raTaH, ... + lp.mark_pum(L("70")); + } else if at && last.has_upadha('n') { + if last.has_text_in(&[ + "jaGana", "akina", "tuhina", "kAnana", "vana", "vfjina", "vipina", "vetana", "SAsana", + "sopAna", "miTuna", "SmaSAna", "ratna", "nimna", "cihna", + ]) { + lp.mark_napumsaka(L("75")); + } else if last.has_text_in(&[ + "mAna", + "yAna", + "aBiDAna", + "malina", + "pulina", + "udyAna", + "Sayana", + "Asana", + "sTAna", + "candana", + "asamAna", + "Bavana", + "vasana", + "saMBAvana", + "viBAvana", + "vimAna", + ]) { + lp.mark_pum_napumsaka(L("76")); + } else { + // PenaH, ... + lp.mark_pum(L("74")); + } + } else if at && last.has_upadha('p') { + if last.has_text_in(&[ + "pApa", "rUpa", "uqupa", "talpa", "Silpa", "puzpa", "samIpa", "antarIpa", + ]) { + // pApam, ... + lp.mark_napumsaka(L("78")); + } else if last.has_text_in(&["SUrpa", "kutapa", "kuRapa", "dvIpa", "viwapa"]) { + // SUrpaH, SUrpam, ... + lp.mark_pum_napumsaka(L("79")); + } else { + // yUpaH, ... + lp.mark_pum(L("77")); + } + } else if at && last.has_upadha('B') { + if last.has_text("talaBa") { + // talaBam + lp.mark_napumsaka(L("81")); + } else if last.has_text("jfmBa") { + // jfmBam, jfmBaH + lp.mark_pum_napumsaka(L("82")); + } else { + // stamBaH, ... + lp.mark_pum(L("80")); + } + } else if at && last.has_upadha('m') { + if last.has_text_in(&[ + "rukma", "siDma", "yugma", "eDma", "gulma", "aDyAtma", "kuNkuma", + ]) { + lp.mark_napumsaka(L("84")); + } else if last.has_text_in(&[ + "saMgrAma", "dAqima", "kusuma", "ASrama", "kzema", "kzOma", "homa", "uddAma", + ]) { + // saMgrAmaH, saMgrAmam, ... + lp.mark_pum_napumsaka(L("85")); + } else { + // somaH, ... + lp.mark_pum(L("83")); + } + } else if at && last.has_upadha('y') { + if last.has_text_in(&["kisalaya", "hfdaya", "indriya", "uttarIya"]) { + // kisalayam, ... + lp.mark_napumsaka(L("87")); + } else if last.has_text_in(&["gomaya", "kazAya", "malaya", "anvaya", "avyaya"]) { + lp.mark_pum_napumsaka(L("88")); + } else { + // samayaH, ... + lp.mark_pum(L("86")); + } + } else if at && last.has_upadha('r') { + if last.has_text_in(DVARA_ADI) { + lp.mark_napumsaka(L("90")); + } else if last.has_text_in(&[ + "cakra", + "vajra", + "anDakAra", + "sAra", + "avAra", + "pAra", + "kzIra", + "tomara", + "SfNgAra", + "bazaNgAra", + "mandAra", + "uSIra", + "timira", + "SiSira", + ]) { + lp.mark_pum_napumsaka(L("92")); + } else { + // kzuraH + lp.mark_pum(L("89")); + } + } else if at && last.has_upadha('z') { + if last.has_text_in(&[ + "SirIza", "fjIza", "ambarIza", "pIyUza", "purIza", "kilbiza", "kalmAza", + ]) { + lp.mark_napumsaka(L("94")); + } else if last.has_text_in(&["yUza", "karIza", "miza", "viza", "varza"]) { + lp.mark_pum_napumsaka(L("95")); + } else { + // vfzaH + lp.mark_pum(L("93")); + } + } else if at && last.has_upadha('s') { + if last.has_text_in(&["panasa", "bisa", "busa", "sAhasa"]) { + // panasam, ... + lp.mark_napumsaka(L("97")); + } else if last.has_text_in(&[ + "camasa", "aMsa", "rasa", "niryAsa", "upavAsa", "kArpAsa", "vAsa", "mAsa", "kAsa", + "kAMsa", "mAMsa", + ]) { + // camasam, camasaH, ... + lp.mark_pum_napumsaka(L("98")); + } else { + // vatsaH, ... + lp.mark_pum(L("96")); + } + } + + let last = lp.p.get(i_last)?; + if last.has_text_in(&["marut", "garut", "tarat", "ftvij"]) { + // marut, ... + lp.mark_pum(L("108")); + } else if last.has_text_in(&[ + "fzi", "rASi", "dfti", "granTi", "krimi", "Dvani", "bali", "kOli", "mOli", "ravi", "kavi", + "kapi", "muni", + ]) { + lp.mark_pum(L("109")); + } else if last.has_text_in(&["Dvaja", "gaja", "muYja", "puYja"]) { + // DvajaH, ... + lp.mark_pum(L("110")); + } else if last.has_text_in(&[ + "hasta", "kunta", "anta", "vrAta", "vAta", "dUta", "Duta", "sUta", "cUta", "muhUrta", + ]) { + // hasta, ... + lp.mark_pum(L("111")); + } else if last.has_text_in(&[ + "zaRqa", "maRqa", "karaRqa", "BaraRqa", "varaRqa", "tuRqa", "gaRqa", "muRqa", "pAzaRqa", + "SiKaRqa", + ]) { + // zaRqaH, ... + lp.mark_pum(L("112")); + } else if last.has_text_in(&["vaMSa", "aMSa", "puroqASa"]) { + // vaMSaH, ... + lp.mark_pum(L("113")); + } else if last.has_text_in(&["hrada", "kanda", "kunda", "budbuda", "Sabda"]) { + // hradaH, ... + lp.mark_pum(L("114")); + } + + // napuMsakam (118 - 170) + // ====================== + + let last = lp.p.get(i_last)?; + if last.has_u_in(&["tva", "zyaY"]) { + // Suklatvam, SOklyam, ... + lp.mark_napumsaka(L("121")); + } else if last.has_suffix_in(&["is", "us"]) { + if last.has_text("arcis") { + // arciH + lp.mark_stri_napumsaka(L("135")); + } else if last.has_text("Cadis") { + // CadiH + lp.mark_stri(L("135")); + } else { + // haviH, DanuH + lp.mark_napumsaka(L("134")); + } + } else if last.has_text_in(&["vaktra", "netra", "araRya", "gARqIva"]) { + // vaktraH, vaktram + lp.mark_pum_napumsaka(L("134")); + } else if last.has_upadha('l') { + if last.has_text_in(&[ + "tUla", "upala", "tAla", "kusUla", "tarala", "kambala", "devala", "vfzala", + ]) { + lp.mark_pum(L("142")); + } else if last.has_text_in(&[ + "SIla", "mUla", "maNgala", "sAla", "kamala", "tala", "musala", "kuRqala", "patala", + "mfRAla", "vAla", "nigala", "palAla", "biqAla", "Kila", "SUla", + ]) { + lp.mark_pum_napumsaka(L("142")); + } else { + // kulam + lp.mark_napumsaka(L("141")); } + } else if last.ends_with("tra") { + lp.mark_napumsaka(L("154")); + } else if last.has_text_in(&[ + "viyat", "jagat", "sakft", "Sakan", "pfzat", "Sakft", "yakft", "udaSvit", + ]) { + lp.mark_napumsaka(L("164")); + } else if last.has_text("dEva") { + lp.mark_pum_napumsaka(L("167")); } + // strIpuMsayoH (171 - 175) + // ======================== + + let last = lp.p.get(i_last)?; + if last.has_text_in(&[ + "go", "maRi", "yazwi", "muzwi", "pAwali", "vasti", "SAlmali", "truwi", "masi", "marIci", + ]) { + lp.mark_stri_pum(L("172")); + } else if last.has_text_in(&["mftyu", "sIDu", "karkanDu", "kizku", "kuRqu", "reRu"]) { + // TODO: reRu in rule 52? + lp.mark_stri_pum(L("172")); + } + + // puMnapuMsakayoH (176 - 182) + // =========================== + + let last = lp.p.get(i_last)?; + if last.has_text_in(&[ + "Gfta", "BUta", "musta", "kzvelita", "ErAvata", "pustaka", "busta", "lohita", + ]) { + // GftaH, Gftam + lp.mark_pum_napumsaka(L("177")); + } else if last.has_text_in(&["SfNga", "arGa", "nidAGa", "udyama", "Salya", "dfQa"]) { + // SfNgaH, SfNgam + lp.mark_pum_napumsaka(L("178")); + } else if last.has_text_in(&[ + "vajra", "kuJya", "kuTa", "kUrca", "prasTa", "darpa", "arBa", "arDa", "arca", "darBa", + "pucCa", + ]) { + // vajraH, vajram + // TODO: vajra also in sutra 92? + lp.mark_pum_napumsaka(L("179")); + } else if last.has_text_in(&["kabanDa", "OzaDa", "AyuDa", "ant"]) { + // kabanDaH, kabanDam + lp.mark_pum_napumsaka(L("180")); + } else if last.has_text_in(&[ + "daRqa", "maRqa", "Kama", "Sama", "sEnDava", "pArSva", "AkASa", "kuSa", "kASa", "aNkuSa", + "kuliSa", + ]) { + // daRqaH, daRqam + lp.mark_pum_napumsaka(L("181")); + } else if last.has_text_in(&[ + "gfha", "meha", "deha", "pawwa", "pawaha", "azwApada", "ambuda", "kakuda", + ]) { + lp.mark_pum_napumsaka(L("182")); + } + + // aviSizwaliNgam (183 - 189) + // ========================== + Some(()) } diff --git a/vidyut-prakriya/src/misc.rs b/vidyut-prakriya/src/misc.rs index 27ee06a..06cfe8c 100644 --- a/vidyut-prakriya/src/misc.rs +++ b/vidyut-prakriya/src/misc.rs @@ -1,5 +1,5 @@ -use crate::operators as op; -use crate::prakriya::Prakriya; +use crate::core::operators as op; +use crate::core::Prakriya; /// Miscellaneous rules that we should put somewhere else. const PADA_ADI: &[&str] = &[ @@ -18,12 +18,15 @@ pub fn run_pad_adi(p: &mut Prakriya) -> Option<()> { let prati = p.get(i_prati)?; let is_shas_prabhrti = p.has(i_next, |t| { // HACK: exclude None, which is a placeholder form for upapada-krdantas. - t.is_vibhakti() && !t.has_u_in(&["su~", "O", "jas", "am", "Ow"]) && t.u != None + t.is_vibhakti() + && !t.is_lupta() + && !t.has_u_in(&["su~", "O", "jas", "am", "Ow"]) + && t.u != None }); if is_shas_prabhrti { if let Some(sub) = op::yatha(&prati.text, PADA_ADI, PAD_ADI) { - p.run_optional_at("6.1.63", i_prati, |t| t.set_text(sub)); + p.optional_run_at("6.1.63", i_prati, |t| t.set_text(sub)); } } diff --git a/vidyut-prakriya/src/pratipadika_karya.rs b/vidyut-prakriya/src/pratipadika_karya.rs index 7b546f3..ac4c5d2 100644 --- a/vidyut-prakriya/src/pratipadika_karya.rs +++ b/vidyut-prakriya/src/pratipadika_karya.rs @@ -1,42 +1,106 @@ -use crate::args::{Linga, Pratipadika}; -use crate::operators as op; -use crate::prakriya::Prakriya; +use crate::args::Pratipadika; +use crate::args::SamasaArgs; +use crate::args::Vibhakti; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::sounds as al; -use crate::tag::Tag as T; -use crate::term::Term; - -pub fn run(p: &mut Prakriya, pratipadika: &Pratipadika, linga: Linga) -> Option<()> { - // The prAtipadika enters the prakriyA - let mut term = Term::make_upadesha(pratipadika.text()); - if pratipadika.is_nyap() { - term.add_tag(T::Stri); - term.add_tag(T::StriNyap); - } - if pratipadika.is_dhatu() { - term.add_tag(T::Dhatu); - } - if pratipadika.is_udit() { - term.add_tag(T::udit); + +/// Appends a pratipadika to the prakriya. +/// +/// Scope: subantas, taddhitas +pub fn add_one(p: &mut Prakriya, pratipadika: &Pratipadika) { + p.extend(pratipadika.terms()); + + // HACK: Add a dummy pratyaya so rules pass. + // TODO: see if we can delete `is_nyap`. + if pratipadika.needs_nyap() { + let sub = if pratipadika + .terms() + .last() + .map_or(false, |t| t.has_antya('I')) + { + "NIp" + } else { + "wAp" + }; + let mut nyap = Term::make_upadesha(sub); + nyap.add_tags(&[T::Pratyaya, T::StriNyap]); + nyap.set_text(""); + p.push(nyap); } - if pratipadika.is_pratyaya() { - term.add_tag(T::Pratyaya); + + add_samjnas(p); +} + +/// Appends multiple pratipadikas to the prakriya. +/// +/// Scope: samasas +pub fn add_all(p: &mut Prakriya, args: &SamasaArgs) { + // Initialize the prakriya by adding all items with dummy sup-pratyayas in between. + for pada in args.padas() { + for t in pada.pratipadika().terms() { + p.push(t.clone()); + } + if pada.is_avyaya() { + p.terms_mut().last_mut().expect("ok").add_tag(T::Avyaya); + } + p.push(make_sup_pratyaya(pada.vibhakti())); } + // Remove the trailing sup-pratyaya. + p.terms_mut().pop(); - p.push(term); + add_samjnas(p); +} - // Add samjnas - p.run_at("1.2.45", 0, |t| { - t.add_tag(T::Pratipadika); - }); - p.add_tag(linga.as_tag()); +/// Assigns the pratipadika-samjna to all matching terms in the prakriya. +fn add_samjnas(p: &mut Prakriya) -> Option<()> { + for i in 0..p.terms().len() { + let t = p.get(i)?; - if linga == Linga::Napumsaka { - let prati = p.get(0)?; - let sub = al::to_hrasva(prati.antya()?)?; - if !prati.has_antya(sub) { - p.run_at("1.2.47", 0, op::antya(&sub.to_string())); + if t.is_krt() || t.is_taddhita() || t.is_samasa() { + p.add_tag_at("1.2.46", i, T::Pratipadika); + } else if !t.is_dhatu() && !t.is_pratyaya() && !t.is_agama() && !t.is_abhyasa() { + // 1.2.45 specifies "arthavat", so exclude meaningless terms (agamas and abhyasas). + // TODO: is there anything else that's not arthavat? + p.add_tag_at("1.2.45", i, T::Pratipadika); } } Some(()) } + +/// Runs rurles specific to napumsaka-pratipadikas. +pub fn run_napumsaka_rules(p: &mut Prakriya) -> Option<()> { + if p.has_tag(T::Napumsaka) { + let i_last_not_empty = p.find_last_where(|t| !t.is_empty() && !t.is_sup())?; + let t = p.get(i_last_not_empty)?; + let sub = al::to_hrasva(t.antya()?)?; + if !t.has_antya(sub) { + p.run_at("1.2.47", i_last_not_empty, op::antya(&sub.to_string())); + } + } + None +} + +/// Creates a dummy sup-pratyaya. +/// +/// Scope: samasas +fn make_sup_pratyaya(vibhakti: Vibhakti) -> Term { + use Vibhakti::*; + let (u, vibhakti) = match vibhakti { + Prathama | Sambodhana => ("su~", T::V1), + Dvitiya => ("am", T::V2), + Trtiya => ("wA", T::V3), + Caturthi => ("Ne", T::V4), + Panchami => ("Nasi", T::V5), + Sasthi => ("Nas", T::V6), + Saptami => ("Ni", T::V7), + }; + + let mut su = Term::make_upadesha(u); + su.set_text(""); + su.add_tags(&[T::Pratyaya, T::Sup, T::Vibhakti, T::Pada, vibhakti]); + su +} diff --git a/vidyut-prakriya/src/samasa.rs b/vidyut-prakriya/src/samasa.rs new file mode 100644 index 0000000..4f1ed64 --- /dev/null +++ b/vidyut-prakriya/src/samasa.rs @@ -0,0 +1,371 @@ +use crate::args::SamasaArgs; +use crate::args::SamasaType; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::{Prakriya, Rule}; +use crate::core::{Term, TermView}; +use crate::ganapatha as gana; + +// 2.1.3 samAsaH +// 2.1.4 saha supA + +#[derive(Debug)] +struct SamasaPrakriya<'a> { + p: &'a mut Prakriya, + done: bool, +} + +impl<'a> SamasaPrakriya<'a> { + fn new(p: &'a mut Prakriya) -> Self { + SamasaPrakriya { p, done: false } + } +} + +impl<'a> SamasaPrakriya<'a> { + fn mark_as_type(&mut self, rule: Rule, samasa_tag: T) { + self.p.run(rule, |p| { + p.add_tag(samasa_tag); + p.terms_mut().last_mut().expect("ok").add_tag(T::Samasa); + }); + self.done = true; + } + fn mark_avyayibhava(&mut self, rule: impl Into) { + self.mark_as_type(rule.into(), T::Avyayibhava); + } + + fn mark_tatpurusha(&mut self, rule: impl Into) { + self.mark_as_type(rule.into(), T::Tatpurusha); + } + + fn mark_bahuvrihi(&mut self, rule: impl Into) { + self.mark_as_type(rule.into(), T::Bahuvrihi); + } + + fn mark_dvandva(&mut self, rule: impl Into, args: &SamasaArgs) { + let is_samahara = args.is_samahara_dvandva(); + self.p.run(rule, |p| { + p.add_tag(T::Dvandva); + if is_samahara { + p.add_tag(T::Samahara); + } + p.terms_mut().last_mut().expect("ok").add_tag(T::Samasa); + }); + self.done = true; + } +} + +impl SamasaArgs { + fn is_avyayibhava(&self) -> bool { + self.samasa_type() == SamasaType::Avyayibhava + } + + fn is_tatpurusha(&self) -> bool { + matches!( + self.samasa_type(), + SamasaType::Tatpurusha | SamasaType::Karmadharaya + ) + } + + fn is_karmadharaya(&self) -> bool { + matches!(self.samasa_type(), SamasaType::Karmadharaya) + } + + fn is_bahuvrihi(&self) -> bool { + self.samasa_type() == SamasaType::Bahuvrihi + } + + fn is_dvandva(&self) -> bool { + matches!( + self.samasa_type(), + SamasaType::Dvandva | SamasaType::SamaharaDvandva + ) + } + + fn is_samahara_dvandva(&self) -> bool { + matches!(self.samasa_type(), SamasaType::SamaharaDvandva) + } +} + +impl<'a> TermView<'a> { + /// Creates a view over a subanta starting at `i_start`. + fn pratipadika_view(p: &'a Prakriya, i_start: usize) -> Option { + let maybe_i_end = p.find_next_where(i_start, |t| t.is_sup() && !t.has_tag(T::Luk)); + + match maybe_i_end { + Some(i_end) => { + if i_end == i_start { + None + } else { + TermView::new(p.terms(), i_start, i_end - 1) + } + } + None => { + // Include everything up to the end of `terms`. + TermView::new(p.terms(), i_start, p.terms().len() - 1) + } + } + } + + fn sup(&self) -> Option<&Term> { + self.terms().get(self.end() + 1) + } + + fn is_avyaya(&self) -> bool { + self.first().has_tag(T::Avyaya) + } + + fn is_dvitiya(&self) -> bool { + self.sup().expect("ok").has_tag(T::V2) + } + + fn is_trtiya(&self) -> bool { + self.sup().expect("ok").has_tag(T::V3) + } + + fn is_caturthi(&self) -> bool { + self.sup().expect("ok").has_tag(T::V4) + } + + fn is_panchami(&self) -> bool { + self.sup().expect("ok").has_tag(T::V5) + } + + fn is_sasthi(&self) -> bool { + self.sup().expect("ok").has_tag(T::V6) + } + + fn is_saptami(&self) -> bool { + self.sup().expect("ok").has_tag(T::V7) + } + + fn is_krt(&self) -> bool { + self.last().is_krt() + } + + fn is_kta(&self) -> bool { + self.last().has_u("kta") + } +} + +fn make_su_pratyaya() -> Term { + let mut su = Term::make_upadesha("su~"); + su.set_text(""); + su.add_tags(&[T::Pratyaya, T::Sup, T::Vibhakti, T::Pada, T::V1]); + su +} + +/// Decides on the samasa type that best applies to `p`. +/// +/// Returns: whether or not `p` contains a samasa. +fn decide_samasa_type(p: &mut Prakriya, args: &SamasaArgs) -> Option { + let mut sp = SamasaPrakriya::new(p); + + let purva = TermView::pratipadika_view(sp.p, 0)?; + let i_uttara_start = sp.p.find_next_where(purva.end(), |t| !t.is_sup())?; + let uttara = TermView::pratipadika_view(sp.p, i_uttara_start)?; + + if args.is_avyayibhava() { + if purva.has_text("yaTA") { + // TODO: avyaya + sp.mark_avyayibhava("2.1.7"); + } else if purva.has_text("yAvat") { + // TODO: avyaya + sp.mark_avyayibhava("2.1.8"); + } else if uttara.has_text("prati") { + sp.mark_avyayibhava("2.1.9"); + } else if (purva.has_text_in(&["akza", "SalAkA"]) || purva.has_tag(T::Sankhya)) + && uttara.has_text("pari") + { + sp.mark_avyayibhava("2.1.10"); + } else if purva.has_text_in(&["apa", "pari", "bahis"]) && uttara.is_panchami() { + sp.mark_avyayibhava("2.1.12"); + } else if purva.has_text("A") { + sp.mark_avyayibhava("2.1.13"); + } else if purva.has_text_in(&["aBi", "prati"]) { + sp.mark_avyayibhava("2.1.14"); + } else if purva.has_text("anu") { + // TODO: 2.1.16 + sp.mark_avyayibhava("2.1.15"); + } else if purva.first().is_sankhya() { + // dvimuni, ... + sp.mark_avyayibhava("2.1.19"); + } else if purva.is_avyaya() { + sp.mark_avyayibhava("2.1.6"); + } + } else if args.is_tatpurusha() { + if purva.is_dvitiya() { + if uttara.has_text_in(&[ + "Srita", "atIta", "patita", "gata", "atyasta", "prApta", "Apanna", + ]) { + sp.mark_tatpurusha("2.1.24"); + } else if purva.has_text("KawvA") && uttara.is_kta() { + sp.mark_tatpurusha("2.1.26"); + } + } else if purva.has_text("svayam") && uttara.is_kta() { + sp.mark_tatpurusha("2.1.25"); + } else if purva.has_text("sAmi") && uttara.is_kta() { + sp.mark_tatpurusha("2.1.27"); + } else if purva.is_trtiya() { + if uttara.has_text_in(&[ + "pUrva", "sadfSa", "sama", "Una", "kalaha", "nipuRa", "miSra", "SlakzRa", + ]) { + // TODO: artha + sp.mark_tatpurusha("2.1.31"); + } else if (purva.has_text("ahi") && uttara.has_text("hata")) + || (purva.has_text("naKa") && uttara.has_text("nirBinna")) + || (purva.has_text("paraSu") && uttara.has_text("Cinna")) + { + sp.mark_tatpurusha("2.1.32"); + } else if uttara.is_krtya() { + sp.mark_tatpurusha("2.1.33"); + } else if uttara.has_text_in(&["anna", "odana"]) { + // daDyodana, ... + sp.mark_tatpurusha("2.1.34"); + } else { + // TODO: gunavacana + sp.mark_tatpurusha("2.1.30"); + } + } else if purva.is_caturthi() { + // We don't need a check like: + // + // uttara.has_text_in(&["arTa", "bali", "hita", "suKa", "rakzita"]) + // + // Because `tadartha` includes most cases. + sp.mark_tatpurusha("2.1.36"); + } else if purva.is_panchami() { + if uttara.has_text("Baya") { + // vfkaBaya, ... + sp.mark_tatpurusha("2.1.37"); + } else if uttara.has_text_in(&["BIta", "BIti", "BI"]) { + // vfkaBIta, ... + sp.mark_tatpurusha("2.1.37.v1"); + } else if uttara.has_text_in(&["apeta", "apoQa", "mukta", "patita", "apatrasta"]) { + // suKApeta, ... + sp.mark_tatpurusha("2.1.38"); + } else if purva.has_text_in(&["stoka", "antika", "dUra", "kfcCra"]) && uttara.is_kta() { + // stokAnmukta, ... + sp.mark_tatpurusha("2.1.39"); + } + } else if purva.is_saptami() { + if uttara.has_text_in(gana::SHAUNDA_ADI) { + sp.mark_tatpurusha("2.1.40"); + } else if uttara.has_text_in(&["sidDa", "Suzka", "pakva", "banDa"]) { + sp.mark_tatpurusha("2.1.41"); + } else if uttara.has_text("DvANkza") { + sp.mark_tatpurusha("2.1.42"); + } else if uttara.is_krtya() { + sp.mark_tatpurusha("2.1.43"); + } else if uttara.is_kta() { + if purva.has_text("tatra") { + sp.mark_tatpurusha("2.1.46"); + } else { + sp.mark_tatpurusha("2.1.45"); + } + } + } else if args.is_karmadharaya() { + if purva.has_text_in(&["eka", "sarva", "jarat", "purARa", "nava", "kevala"]) { + sp.mark_tatpurusha("2.1.49"); + } else if purva.has_text_in(&[ + "pUrva", "apara", "praTama", "carama", "jaGanya", "samAna", "maDya", "maDyama", + "vIra", + ]) { + sp.mark_tatpurusha("2.1.54"); + } else if purva.has_text_in(&["sat", "mahat", "parama", "uttama", "utkfzwa"]) { + // satpuruza, ... + sp.mark_tatpurusha("2.1.61"); + } else if purva.has_text_in(&["vfndAraka", "nAga", "kuYjara"]) { + // govfndAraka, ... + sp.mark_tatpurusha("2.1.62"); + } else if purva.has_text_in(&["katara", "katama"]) { + // govfndAraka, ... + sp.mark_tatpurusha("2.1.63"); + } else if purva.has_text("kim") { + sp.mark_tatpurusha("2.1.64"); + } else if uttara.has_text_in(&[ + "powA", + "yuvati", + "stoka", + "katipaya", + "gfzwi", + "Denu", + "vaSA", + "vehat", + "bazkayaRI", + "pravaktf", + "Srotriya", + "aDyApaka", + "DUrta", + ]) { + // iBapowA, ... + sp.mark_tatpurusha("2.1.65"); + } else if purva.has_text("yuvan") + && uttara.has_text_in(&["Kalati", "palita", "valina", "jarati"]) + { + // yuvaKalati + sp.mark_tatpurusha("2.1.67"); + } else if purva.is_krtya() || purva.has_text("tulya") { + // BojyozRa + sp.mark_tatpurusha("2.1.68"); + } else if purva.has_text("kumAra") && uttara.has_text_in(gana::SHRAMANA_ADI) { + // kumAraSramaRa, ... + sp.mark_tatpurusha("2.1.70"); + } else { + sp.mark_tatpurusha("2.1.57"); + } + } else if purva.has_text("naY") { + // abrAhmaRa, ... + sp.mark_tatpurusha("2.2.6"); + } else if purva.has_text("Izat") && !uttara.is_krt() { + sp.mark_tatpurusha("2.2.7"); + } else if purva.is_sasthi() { + if uttara.has_text_in(gana::YAJAKA_ADI) { + sp.mark_tatpurusha("2.2.9"); + } else { + sp.mark_tatpurusha("2.2.8"); + } + } else if purva.has_text("ku") || purva.last().is_gati() || purva.has_text_in(gana::PRA_ADI) + { + sp.mark_tatpurusha("2.2.18"); + } + } else if args.is_bahuvrihi() { + sp.mark_bahuvrihi("2.2.24"); + } else if args.is_dvandva() { + // "samAhAra" is not provided explictly, so reuse the same rule. + sp.mark_dvandva("2.2.29", args); + } + + Some(sp.done) +} + +pub fn run(p: &mut Prakriya, args: &SamasaArgs) -> bool { + let res = decide_samasa_type(p, args); + match res { + Some(true) => (), + _ => return false, + } + + if p.has_tag(T::Tatpurusha) && args.is_karmadharaya() { + p.run("1.2.42", |p| p.add_tag(T::Karmadharaya)); + } + + let i_last = p.terms().len() - 1; + for i in 0..=i_last { + if p.has(i, |t| t.is_sup()) { + p.run_at("2.4.71", i, op::luk); + } + } + + if p.has_tag(T::Avyayibhava) { + p.run("2.4.17", |p| p.add_tag(T::Napumsaka)); + + let i_last = p.terms().len() - 1; + p.run("4.1.2", |p| p.push(make_su_pratyaya())); + if p.has(i_last, |t| t.has_antya('a')) { + p.run_at("2.4.83", i_last + 1, |t| t.set_text("am")); + } else { + p.run_at("2.4.82", i_last + 1, op::luk); + } + } + + true +} diff --git a/vidyut-prakriya/src/samjna.rs b/vidyut-prakriya/src/samjna.rs index 3bce7fa..ae3c5cc 100644 --- a/vidyut-prakriya/src/samjna.rs +++ b/vidyut-prakriya/src/samjna.rs @@ -1,29 +1,60 @@ -use crate::operators as op; -use crate::prakriya::Prakriya; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; +use crate::ganapatha::SARVA_ADI; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::stem_gana::{LAUKIKA_SANKHYA, PRATHAMA_ADI, PURVA_ADI, SARVA_ADI, USES_DATARA_DATAMA}; -use crate::tag::Tag as T; -use crate::term::Term; +use crate::stem_gana::{LAUKIKA_SANKHYA, PRATHAMA_ADI, PURVA_ADI, USES_DATARA_DATAMA}; use lazy_static::lazy_static; lazy_static! { static ref AC: Set = s("ac"); } -fn try_run_for_pratipadika(p: &mut Prakriya) -> Option<()> { +/// Returns whether this term ends in tIya-pratyaya. +fn is_tiya(t: &Term) -> bool { + // HACK: hard-coded. + t.has_u_in(&["dvitIya", "tftIya"]) +} + +fn is_vatu(_: &Term) -> bool { + // HACK: placeholder + false +} + +fn is_dati(t: &Term) -> bool { + // HACK: hard-coded. + t.has_u_in(&["kati"]) +} + +fn try_run_for_pratipadika(p: &mut Prakriya) { + for i in 0..p.terms().len() { + if p.has(i, |t| t.is_pratipadika()) { + try_run_for_pratipadika_at_index(p, i); + } + } +} + +fn try_run_for_pratipadika_at_index(p: &mut Prakriya, i: usize) -> Option<()> { + use op::add_tag; + const TYAD_ADI: &[&str] = &[ "tyad", "tad", "yad", "etad", "idam", "adas", "eka", "dvi", "yuzmad", "asmad", "Bavatu~", "kim", ]; - let i = p.find_first(T::Pratipadika)?; + + let mut i = i; + if p.has(i, |t| t.is_empty()) && i > 0 { + i = p.find_prev_where(i, |t| !t.is_empty())?; + } let prati = p.get(i)?; let adi_ac = prati.text.find(al::is_ac)?; if al::is_vrddhi(prati.get_at(adi_ac)?) { - p.run_at("1.1.73", i, op::add_tag(T::Vrddha)); + p.add_tag_at("1.1.73", i, T::Vrddha); } else if prati.has_u_in(TYAD_ADI) { - p.run_at("1.1.74", i, op::add_tag(T::Vrddha)); + p.add_tag_at("1.1.74", i, T::Vrddha); } let prati = p.get(i)?; @@ -31,25 +62,35 @@ fn try_run_for_pratipadika(p: &mut Prakriya) -> Option<()> { let ii_uu = prati.has_antya('I') || prati.has_antya('U'); let i_u = prati.has_antya('i') || prati.has_antya('u'); - if prati.has_text_in(&["bahu", "gaRa"]) || prati.has_text_in(LAUKIKA_SANKHYA) { + + if prati.has_u_in(&["bahu", "gaRa"]) + || is_vatu(prati) + || is_dati(prati) + || prati.has_u_in(LAUKIKA_SANKHYA) + { // TODO: vatu, qati - p.run_at("1.1.23", i, op::add_tag(T::Sankhya)); + p.add_tag_at("1.1.23", i, T::Sankhya); let prati = p.get(i)?; - if prati.has_antya('z') || prati.has_antya('n') { - p.run_at("1.1.24", i, op::add_tag(T::Sat)); + if prati.has_antya('z') || prati.has_antya('n') || is_dati(prati) { + p.add_tag_at("1.1.24", i, T::zaw); } - } else if prati.has_text_in(PRATHAMA_ADI) && jasi { - p.run_optional_at("1.1.33", i, op::add_tag(T::Sarvanama)); - } else if prati.has_text_in(SARVA_ADI) || prati.has_text_in(USES_DATARA_DATAMA) { + } else if prati.has_u_in(PRATHAMA_ADI) && jasi { + // praTamAH, praTame, ... + p.optional_run_at("1.1.33", i, add_tag(T::Sarvanama)); + } else if is_tiya(prati) && p.has(i + 1, |t| t.has_tag(T::Nit)) { + // dvitIyAya, dvitIyasmE, ... + p.optional_run_at("1.1.33.v1", i, add_tag(T::Sarvanama)); + } else if prati.has_u_in(SARVA_ADI) || prati.has_u_in(USES_DATARA_DATAMA) { let mut sarvanama = true; - if prati.has_text_in(PURVA_ADI) && jasi { - sarvanama = !p.run_optional("1.1.34", |_| {}); + if prati.has_u_in(PURVA_ADI) && jasi { + sarvanama = !p.optional_run("1.1.34", |_| {}); } if sarvanama { - p.run_at("1.1.27", i, op::add_tag(T::Sarvanama)); + p.add_tag_at("1.1.27", i, T::Sarvanama); } } else if i_u || ii_uu { - let sup = p.get(i + 1)?; + let i_sup = p.find_next_where(i, |t| t.is_sup())?; + let sup = p.get_if(i_sup, |t| !t.is_lupta())?; // iyan-uvan are defined in 6.4.77 (Snu-dhAtu-bhruvAm) -- only dhAtu and bhrU apply here. let iyan_uvan_astri = @@ -64,27 +105,34 @@ fn try_run_for_pratipadika(p: &mut Prakriya) -> Option<()> { let mut decided = false; if stri_linga && (iyan_uvan_astri || i_u) && sup.has_tag(T::Nit) { - decided = p.run_optional_at("1.4.6", i, op::add_tag(T::Nadi)); + decided = p.optionally("1.4.6", |code, p| { + p.add_tag_at(code, i_sup - 1, T::Nadi); + }); } let prati = p.get(i)?; - let sup = p.get(i + 1)?; + let sup = p.get(i_sup)?; if i_u && !decided && !prati.has_text("saKi") { - // TODO: patiH samAsa eva - if !prati.has_text("pati") { - p.run_at("1.4.7", i, op::add_tag(T::Ghi)); + if prati.has_text("pati") { + if prati.is_samasa() { + p.add_tag_at("1.4.8", i_sup - 1, T::Ghi); + } + } else { + p.add_tag_at("1.4.7", i_sup - 1, T::Ghi); } - } else if ii_uu { + } else if ii_uu && !decided { if iyan_uvan_astri { if sup.has_u("Am") { - p.run_optional_at("1.4.5", i, op::add_tag(T::Nadi)); + p.optionally("1.4.5", |code, p| { + p.add_tag_at(code, i_sup - 1, T::Nadi); + }); } else { // "he SrIH", "he BrUH", but "he stri" p.step("1.4.4"); } } else { // Base case - p.run_at("1.4.3", i, op::add_tag(T::Nadi)); + p.add_tag_at("1.4.3", i_sup - 1, T::Nadi); } } } @@ -112,21 +160,65 @@ pub fn try_run_for_pada_or_bha(p: &mut Prakriya) -> Option<()> { // do nothing // TODO: why? } else { - let next = p.view(i + 1)?; - // Includes both sup-pratayas and taddhitas, per SK on 1.4.17. - let is_svadi = next.has_tag_in(&[T::Sup, T::Taddhita]); + let next = p.pratyaya(i + 1)?; + // "svAdi" refers to any pratyaya introduced in adhyayas 4 and 5. These include: + // - sup pratyayas (4.1.2) + // - NI and Ap pratyayas (4.1.3 - 4.1.75) + // - taddhita pratyayas (4.1.76 - end of adhyaya 5) + let is_svadi = next.has_tag_in(&[T::Sup, T::Nyap, T::Taddhita]); if next.has_tag(T::sit) { - p.run_at("1.4.16", i, op::add_tag(T::Pada)); + p.add_tag_at("1.4.16", i, T::Pada); } else if is_svadi && !next.has_tag(T::Sarvanamasthana) { if next.has_adi('y') || next.has_adi(&*AC) { - p.run_at("1.4.18", i, op::add_tag(T::Bha)); - } else if (term.has_antya('t') || term.has_antya('s')) - && is_matvartha(next.first()?) + p.add_tag_at("1.4.18", i, T::Bha); + } else if (term.has_antya('t') || term.has_antya('s')) && is_matvartha(next.first()) { - p.run_at("1.4.19", i, op::add_tag(T::Bha)); + p.add_tag_at("1.4.19", i, T::Bha); } else { - p.run_at("1.4.17", i, op::add_tag(T::Pada)); + p.add_tag_at("1.4.17", i, T::Pada); + } + } + } + } + + Some(()) +} + +pub fn run_for_pragrhya(p: &mut Prakriya) -> Option<()> { + for i in 0..p.terms().len() { + let pada = p.pada(i); + if let Some(pada) = pada { + // Add the tag to the specific vowel sound (non-empty) so that it's more accessible + // during ac-sandhi. + let i_last = pada.end_non_empty()?; + if pada.has_antya('I') + || pada.has_antya('U') + || pada.has_antya('e') && pada.last().has_tag(T::Dvivacana) + { + // harI etO, ... + p.add_tag_at("1.1.11", i_last, T::Pragrhya); + } else if pada.has_text_in(&["amI", "amU"]) { + // amI atra, ... + p.add_tag_at("1.1.12", i_last, T::Pragrhya); + } else if pada.last().has_u("Se") { + p.add_tag_at("1.1.13", i_last, T::Pragrhya); + } else if pada.first().is_nipata() { + if pada.has_u("uY") { + // U~ iti + let done = p.optional_run_at("1.1.18", i_last, |t| t.set_text("U~")); + if !done { + // u iti, viti + p.optionally("1.1.17", |rule, p| p.add_tag_at(rule, i_last, T::Pragrhya)); + } + } else if pada.text().len() == 1 + && pada.num_vowels() == 1 + && !pada.first().has_u("AN") + { + p.add_tag_at("1.1.14", i_last, T::Pragrhya); + } else if pada.has_antya('o') { + // Aho iti + p.add_tag_at("1.1.15", i_last, T::Pragrhya); } } } @@ -139,16 +231,16 @@ fn try_run_for_sup(p: &mut Prakriya) -> Option<()> { let i = p.find_last(T::Sup)?; if p.has_tag(T::Sambodhana) { - p.run_at("2.3.48", i, op::add_tag(T::Amantrita)); + p.add_tag_at("2.3.48", i, T::Amantrita); if p.has_tag(T::Ekavacana) { - p.run_at("2.3.49", i, op::add_tag(T::Sambuddhi)); + p.add_tag_at("2.3.49", i, T::Sambuddhi); } } let sup = p.get(i)?; // For 1.1.42, see the `sup_adesha` module. if sup.has_u_in(&["su~", "O", "jas", "am", "Ow"]) && !p.has_tag(T::Napumsaka) { - p.run_at("1.1.43", i, op::add_tag(T::Sarvanamasthana)); + p.add_tag_at("1.1.43", i, T::Sarvanamasthana); } Some(()) @@ -158,7 +250,7 @@ fn try_run_for_taddhita(p: &mut Prakriya) -> Option<()> { let i = p.find_last(T::Taddhita)?; if p.has(i, |t| t.has_u_in(&["tarap", "tamap"])) { - p.run_at("1.1.22", i, |t| t.add_tag(T::Gha)); + p.add_tag_at("1.1.22", i, T::Gha); } Some(()) @@ -168,26 +260,23 @@ fn try_run_for_dhatu_pratyaya(p: &mut Prakriya, i: usize) -> Option<()> { // TODO: add other exclusions here. let pratyaya = p.get_if(i, |t| !t.has_tag_in(&[T::Sup, T::Taddhita]))?; - let add_sarva = op::t(i, op::add_tag(T::Sarvadhatuka)); - let add_ardha = op::t(i, op::add_tag(T::Ardhadhatuka)); - if pratyaya.is_pratyaya() { if pratyaya.has_lakshana("li~w") { - p.run("3.4.115", add_ardha); + p.add_tag_at("3.4.115", i, T::Ardhadhatuka); } else if pratyaya.has_lakshana("li~N") && p.has_tag(T::Ashih) { - p.run("3.4.116", add_ardha); + p.add_tag_at("3.4.116", i, T::Ardhadhatuka); } else if pratyaya.has_tag_in(&[T::Tin, T::Sit]) { - if !pratyaya.has_tag(T::Sarvadhatuka) { - p.run("3.4.113", add_sarva); + if !pratyaya.is_sarvadhatuka() { + p.add_tag_at("3.4.113", i, T::Sarvadhatuka); } } else { // Suffixes introduced before "dhAtoH" are not called ArdhadhAtuka. // So they will not cause guNa and will not condition iT-Agama. if pratyaya.has_tag(T::FlagNoArdhadhatuka) { // do nothing - } else if !pratyaya.is_empty() && !pratyaya.has_tag(T::Ardhadhatuka) { + } else if !pratyaya.is_empty() && !pratyaya.is_ardhadhatuka() { // Check `is_empty` to avoid including luk, etc. - p.run("3.4.114", add_ardha); + p.add_tag_at("3.4.114", i, T::Ardhadhatuka); } } } diff --git a/vidyut-prakriya/src/samprasarana.rs b/vidyut-prakriya/src/samprasarana.rs index 2f11803..b53c37a 100644 --- a/vidyut-prakriya/src/samprasarana.rs +++ b/vidyut-prakriya/src/samprasarana.rs @@ -1,12 +1,12 @@ +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Code, Prakriya}; /// Applies samprasarana changes as needed. /// /// Order of operations: /// - Must follow atidesha so that suffixes have the kit/Nit annotations necessary to cause /// samprasanara. use crate::dhatu_gana as gana; -use crate::prakriya::{Code, Prakriya}; -use crate::tag::Tag as T; -use crate::term::Term; fn is_vaci_svapi(t: &Term) -> bool { t.is_dhatu() @@ -113,7 +113,7 @@ pub fn run_for_dhatu(p: &mut Prakriya) -> Option<()> { return None; } - let n = p.view(i_n)?; + let n = p.pratyaya(i_n)?; let n_is_yan = n.has_u("yaN"); let n_is_lit = n.has_lakshana("li~w"); let n_will_be_abhyasta = n_is_lit || n.has_u_in(&["san", "yaN", "Slu", "caN"]); @@ -126,7 +126,7 @@ pub fn run_for_dhatu(p: &mut Prakriya) -> Option<()> { }; let optional_set_text = |rule, p: &mut Prakriya, text| { - p.run_optional_at(rule, i, |t| { + p.optional_run_at(rule, i, |t| { t.set_text(text); t.add_tag(T::FlagSamprasarana); }); diff --git a/vidyut-prakriya/src/sanadi.rs b/vidyut-prakriya/src/sanadi.rs index 7e702bd..f87f203 100644 --- a/vidyut-prakriya/src/sanadi.rs +++ b/vidyut-prakriya/src/sanadi.rs @@ -1,14 +1,12 @@ use crate::args::Gana; use crate::args::Sanadi; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::dhatu_gana as gana; -use crate::filters as f; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::Rule; -use crate::prakriya::{Code, Prakriya}; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -21,7 +19,7 @@ const AYADAYA: &[&str] = &[ ]; /// Adds `upadesha` as a pratyaya after the dhatu at index `i_dhatu`. -fn add_sanadi(rule: Code, p: &mut Prakriya, i_dhatu: usize, upadesha: &str) { +fn add_sanadi(rule: impl Into, p: &mut Prakriya, i_dhatu: usize, upadesha: &str) { p.run(rule, |p| { let mut pratyaya = Term::make_upadesha(upadesha); pratyaya.add_tags(&[T::Pratyaya]); @@ -29,25 +27,10 @@ fn add_sanadi(rule: Code, p: &mut Prakriya, i_dhatu: usize, upadesha: &str) { }); let i_pratyaya = i_dhatu + 1; - p.run_at("3.1.32", i_pratyaya, op::add_tag(T::Dhatu)); + p.add_tag_at("3.1.32", i_pratyaya, T::Dhatu); it_samjna::run(p, i_pratyaya).expect("ok") } -/// Optionally adds `upadesha` as a pratyaya after the dhatu at index `i_dhatu`. -fn optional_add_sanadi(rule: Code, p: &mut Prakriya, i_dhatu: usize, upadesha: &str) { - let added = p.run_optional(rule, |p| { - let mut pratyaya = Term::make_upadesha(upadesha); - pratyaya.add_tags(&[T::Pratyaya]); - p.insert_after(i_dhatu, pratyaya); - }); - - if added { - let i_pratyaya = i_dhatu + 1; - p.run_at("3.1.32", i_pratyaya, op::add_tag(T::Dhatu)); - it_samjna::run(p, i_pratyaya).expect("ok") - } -} - /// Runs rules that apply only if using yaN-pratyay with luk. fn run_rules_for_yan_luk(p: &mut Prakriya) -> Option<()> { use Rule::Dhatupatha as DP; @@ -93,31 +76,30 @@ pub fn try_add_specific_sanadi_pratyayas(p: &mut Prakriya, is_ardhadhatuka: bool } else if dhatu.has_u_in(AYADAYA) { let mut can_add_pratyaya = true; - let code = "3.1.31"; if is_ardhadhatuka { - if p.is_allowed(code) { - can_add_pratyaya = false; - // TODO: not sure where to do this. - if p.has(i, |t| t.has_u("fti")) { - p.set(i, |t| t.set_text("ft")); - } - p.step(code); - } else { - p.decline(code); - } + can_add_pratyaya = !p.optionally("3.1.31", |rule, p| { + p.run_at(rule, i, |t| { + // TODO: not sure where to do this. + if t.has_u("fti") { + t.set_text("ft") + } + }); + }); } if can_add_pratyaya { let dhatu = p.get(i)?; if dhatu.has_u_in(&["gupU~", "DUpa~", "viCa~", "paRa~\\", "pana~\\"]) { - let code = "3.1.28"; + let rule = "3.1.28"; if dhatu.has_u("paRa~\\") { // > stutyarthena paninā sāhacaryāt tadarthaḥ paṇiḥ pratyayamutpādayati na // > vyavahārārthaḥ. śatasya paṇate. sahasrasaya paṇate // -- KV on 3.1.28 - optional_add_sanadi(code, p, i, "Aya"); + p.optionally(rule, |rule, p| { + add_sanadi(rule, p, i, "Aya"); + }); } else { - add_sanadi(code, p, i, "Aya"); + add_sanadi(rule, p, i, "Aya"); } } else if dhatu.has_u("fti") { // ftIyate @@ -156,7 +138,7 @@ pub fn try_add_general_sanadi_pratyaya(p: &mut Prakriya, sanadi: Sanadi) -> Opti || dhatu.has_u_in(&["awa~", "f\\", "aSa~", "aSU~\\", "UrRuY"]) { add_sanadi("3.1.22.v1", p, i, "yaN"); - } else if f::is_eka_ac(dhatu) && dhatu.has_adi(&*HAL) { + } else if dhatu.is_ekac() && dhatu.has_adi(&*HAL) { add_sanadi("3.1.22", p, i, "yaN"); } diff --git a/vidyut-prakriya/src/sounds.rs b/vidyut-prakriya/src/sounds.rs index 7398fae..c3a8457 100644 --- a/vidyut-prakriya/src/sounds.rs +++ b/vidyut-prakriya/src/sounds.rs @@ -41,7 +41,6 @@ use std::fmt; type Sound = char; lazy_static! { - static ref SUTRAS: Vec = create_shiva_sutras(); static ref SOUND_PROPS: HashMap = create_sound_props(); static ref AC: Set = s("ac"); static ref HAL: Set = s("hal"); @@ -75,7 +74,7 @@ impl Set { } impl fmt::Display for Set { - /// Returns all chars in the given set in the traditional Sanskrit order. + /// Returns all chars in this set in their traditional Sanskrit order. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut ret = String::new(); for c in "aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzsh".chars() { @@ -160,39 +159,20 @@ impl Pattern for &Set { } } +/// A shiva sutra. struct Sutra { - sounds: String, + /// The sounds in the sutra. + sounds: &'static str, + /// The final it letter of the sutra. it: Sound, } impl Sutra { - fn new(sounds: &str, it: Sound) -> Self { - Sutra { - sounds: sounds.to_string(), - it, - } + const fn new(sounds: &'static str, it: Sound) -> Self { + Sutra { sounds, it } } } -fn create_shiva_sutras() -> Vec { - vec![ - Sutra::new("aiu", 'R'), - Sutra::new("fx", 'k'), - Sutra::new("eo", 'N'), - Sutra::new("EO", 'c'), - Sutra::new("hyvr", 'w'), - Sutra::new("l", 'R'), - Sutra::new("YmNRn", 'm'), - Sutra::new("JB", 'Y'), - Sutra::new("GQD", 'z'), - Sutra::new("jbgqd", 'S'), - Sutra::new("KPCWTcwt", 'v'), - Sutra::new("kp", 'y'), - Sutra::new("Szs", 'r'), - Sutra::new("h", 'l'), - ] -} - fn create_sound_props() -> HashMap { fn flatten_multi(data: Vec<(Set, T)>) -> HashMap> { let mut mapping = HashMap::default(); @@ -312,12 +292,15 @@ pub fn is_samyoganta(text: &str) -> bool { let mut chars = text.chars().rev(); if let Some(x) = chars.next() { if let Some(y) = chars.next() { + // HACK: always treat a string ending with `C` as samyogAnta since it either follows a + // consonant or will become cC by 6.1.73. return (HAL.contains(x) && HAL.contains(y)) || x == 'C'; } } false } +/// Converts the sound to its guna replacement, including any "rapara" sounds (1.1.51). pub fn to_guna(s: Sound) -> Option<&'static str> { let res = match s { // TODO: remove 'a' | 'A' line @@ -331,6 +314,7 @@ pub fn to_guna(s: Sound) -> Option<&'static str> { Some(res) } +/// Converts the sound to its vrddhi replacement, including any "rapara" sounds (1.1.51). pub fn to_vrddhi(s: Sound) -> Option<&'static str> { let res = match s { 'a' | 'A' => "A", @@ -345,7 +329,9 @@ pub fn to_vrddhi(s: Sound) -> Option<&'static str> { Some(res) } -// 1.1.48 UkAlojjhrasvadIrghaplutaH +/// Converts the sound to its hrasva (short) replacement. +/// +/// 1.1.48 UkAlojjhrasvadIrghaplutaH pub fn to_hrasva(s: Sound) -> Option { let res = match s { 'a' | 'A' => 'a', @@ -353,6 +339,7 @@ pub fn to_hrasva(s: Sound) -> Option { 'u' | 'U' => 'u', 'f' | 'F' => 'f', 'x' | 'X' => 'x', + // 1.1.48 "eca igGrasvAdeSe" 'e' | 'E' => 'i', 'o' | 'O' => 'u', _ => return None, @@ -360,7 +347,9 @@ pub fn to_hrasva(s: Sound) -> Option { Some(res) } -// 1.1.48 UkAlojjhrasvadIrghaplutaH +/// Converts the sound to its dIrgha (long) replacement. +/// +/// 1.1.48 UkAlojjhrasvadIrghaplutaH pub fn to_dirgha(s: Sound) -> Option { let res = match s { 'a' | 'A' => 'A', @@ -383,6 +372,23 @@ pub fn to_dirgha(s: Sound) -> Option { /// - `R` refers to the first `R` (a i u R). /// - `R2` refers to the second `R` (la R). fn pratyahara(s: &str) -> Set { + const SUTRAS: &[Sutra] = &[ + Sutra::new("aiu", 'R'), + Sutra::new("fx", 'k'), + Sutra::new("eo", 'N'), + Sutra::new("EO", 'c'), + Sutra::new("hyvr", 'w'), + Sutra::new("l", 'R'), + Sutra::new("YmNRn", 'm'), + Sutra::new("JB", 'Y'), + Sutra::new("GQD", 'z'), + Sutra::new("jbgqd", 'S'), + Sutra::new("KPCWTcwt", 'v'), + Sutra::new("kp", 'y'), + Sutra::new("Szs", 'r'), + Sutra::new("h", 'l'), + ]; + let first = s.as_bytes()[0] as char; let use_second_n = s.ends_with("R2"); @@ -421,17 +427,18 @@ fn pratyahara(s: &str) -> Set { } } + // This function is not part of the public API, so the `assert` is reasonable. assert!(!res.is_empty(), "Could not parse pratyahara `{s}`"); Set::from(&res) } -/// Parses a list of upadeshas and returns the sound set it corresponds to. +/// Parses a list of terms and returns the sound set it specifies. /// -/// Upadeshas this function accepts: +/// This function accepts the following terms: /// - pratyaharas ("ac", "hal") /// - udit sounds ("ku~", "pu~") /// - vowels ("a", "e") -/// - simple consonants ("h", "k") +/// - simple consonants ("h", "k"). Note that these consonants don't have the trailing `a`. /// /// `s` is an abbrevation for "sound_set." Since this function is so frequent in the codebase, we /// have shortened its name for brevity. @@ -456,36 +463,52 @@ pub fn s(terms: &str) -> Set { /// Models the point of articulation of a Sanskrit sound. #[derive(Clone, Copy, Eq, PartialEq)] enum Sthana { + /// The base of the throat. Kantha, + /// The hard palate. Talu, + /// The roof of the mouth. Murdha, + /// The teeth. Danta, + /// The lips. Oshtha, + /// The nose. Nasika, + /// The base of the throat and the hard palate. KanthaTalu, + /// The base of the throat and the lips. KanthaOshtha, + /// The teeth and the lips. DantaOshtha, } /// Models the voicing of a Sanskrit sound. #[derive(Clone, Copy, Eq, PartialEq)] enum Ghosha { + /// Voices. Ghoshavat, + /// Unvoiced. Aghosha, } /// Models the aspiration of a Sanskrit sound. #[derive(Clone, Copy, Eq, PartialEq)] enum Prana { + /// Aspirated. Mahaprana, + /// Unaspirated. Alpaprana, } /// Models the articulatory effort of a Sanskrit sound. #[derive(Clone, Copy, Eq, PartialEq)] enum Prayatna { + /// Open. Vivrta, + /// Slightly closed. Ishat, + /// Closed. Sprshta, } diff --git a/vidyut-prakriya/src/stem_gana.rs b/vidyut-prakriya/src/stem_gana.rs index 26eed22..2c00529 100644 --- a/vidyut-prakriya/src/stem_gana.rs +++ b/vidyut-prakriya/src/stem_gana.rs @@ -1,13 +1,3 @@ -/// 1.1.27 sarvAdIni sarvanAmAni -/// -/// TODO: add others -pub const SARVA_ADI: &[&str] = &[ - "sarva", "viSva", "uBa", "uBaya", "qatara", "qatama", "anya", "anyatara", "itara", "tvat", - "tva", "nema", "sama", "sima", "pUrva", "para", "avara", "dakziRa", "uttara", "apara", "aDara", - "sva", "antara", "tyad", "tad", "yad", "etad", "idam", "adas", "eka", "dvi", "yuzmad", "asmad", - "Bavatu~", "kim", -]; - pub const LAUKIKA_SANKHYA: &[&str] = &[ "eka", "dvi", "tri", "catur", "paYcan", "zaz", "saptan", "azwan", "navan", "daSan", "zoqaSan", ]; @@ -19,18 +9,19 @@ pub const USES_DATARA_DATAMA: &[&str] = &[ "katara", "yatara", "tatara", "ekatara", "katama", "yatama", "tatama", "ekatama", ]; +#[rustfmt::skip] #[allow(unused)] pub const PRATHAMA_ADI: &[&str] = &[ - "praTama", "carama", // "taya", - "alpa", "arDa", "katipaya", "nema", + "praTama", + "carama", + // TODO: expand "taya" + "dvitaya", + "alpa", + "arDa", + "katipaya", + "nema", ]; pub const PURVA_ADI: &[&str] = &[ "pUrva", "para", "avara", "dakziRa", "uttara", "apara", "aDara", "sva", "antara", ]; - -/// pra-Adi gana. These terms are called *upasarga* by rule 1.4.59. -pub const PRA_ADI: &[&str] = &[ - "pra", "parA", "apa", "sam", "anu", "ava", "nis", "nir", "dus", "dur", "vi", "AN", "ni", "aDi", - "api", "ati", "su", "ud", "aBi", "prati", "pari", "upa", -]; diff --git a/vidyut-prakriya/src/stritva.rs b/vidyut-prakriya/src/stritva.rs index 96dc697..8d6f2a3 100644 --- a/vidyut-prakriya/src/stritva.rs +++ b/vidyut-prakriya/src/stritva.rs @@ -14,158 +14,224 @@ Generally, these pratyayas are of two types: 2. NI (NIp, NIz, ...), which creates stems that end in I. */ +use crate::core::errors::Error; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; +use crate::enum_boilerplate; +use crate::ganapatha as gana; use crate::it_samjna; -use crate::prakriya::{Code, Prakriya}; -use crate::tag::Tag as T; -use crate::term::Term; - -const AJA_ADI: &[&str] = &[ - // jAti - "aja", - "eqaka", - "kokila", - "cawaka", - "aSva", - "mUzika", - // age - "bAla", - "hoqa", - "pAka", - "vatsa", - "manda", - "vilAta", - // lyuw - "pUrvApaharaRa", - "aparApaharaRa", - // Pala - "samPala", - "BastraPala", - "ajinaPala", - "SaRaPala", - "piRqaPala", - "triPala", - // puzpa - "satpuzpa", - "prAkpuzpa", - "kARqapuzpa", - "prAntapuzpa", - "Satapuzpa", - "ekapuzpa", - // TODO: optional for SUdra in different senses. - "SUdra", - // halanta - "kruYc", - "uzRih", - "devaviS", - // matrimony - "jyezWa", - "kanizWa", - "maDyama", - // naY - "amUla", -]; -const SVASR_ADI: &[&str] = &[ - "svasf", "duhitf", "nanAndf", "yAtf", "mAtf", "tisf", "catasf", -]; +/// Models a strI-pratyaya. +/// +/// We use this enum for consistency with `BaseKrt`, `Unadi`, and `Taddhita`. +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +enum Stri { + cAp, + wAp, + qAp, + NIn, + NIp, + NIz, +} -const BAHU_ADI: &[&str] = &[ - "bahu", - "padDati", - "aNkati", - "aYcati", - "aMhati", - "vaMhati", - "Sakawi", - "Sakti", - "SAri", - "vAri ", - "rAti", - "rADi", - "SADi", - "ahi", - "kapi", - "yazwi", - "muni", - "caRqa", - "arAla", - "kamala", - "kfpARa", - "vikawa", - "viSAla", - "viSaNkawa", - "Baruja", - "Dvaja", - "kalyARa", - "udAra", - "purARa", - "ahan", -]; +impl Stri { + fn to_term(self) -> Term { + let mut stri = Term::make_upadesha(self.as_str()); + stri.add_tags(&[T::Pratyaya, T::Nyap]); + stri + } +} + +enum_boilerplate!(Stri, { + cAp => "cAp", + wAp => "wAp", + qAp => "qAp", + NIn => "NIn", + NIp => "NIp", + NIz => "NIz", +}); const INDRA_ADI: &[&str] = &[ "indra", "varuRa", "Bava", "Sarva", "rudra", "mfqa", "hima", "araRya", "yava", "yavana", "mAtula", "AcArya", ]; -fn add(rule: Code, p: &mut Prakriya, s: &str) { - let i = p.terms().len(); - let mut t = Term::make_upadesha(s); - t.add_tag(T::Pratyaya); - - p.terms_mut().push(t); - p.step(rule); - it_samjna::run(p, i).expect("should never fail"); +/// A wrapper for `Prakriya` that adds at most one strI-pratyaya to the prakriya. +struct StriPrakriya<'a> { + p: &'a mut Prakriya, + i_prati: usize, + pub done: bool, } -fn add_with_agama(rule: Code, p: &mut Prakriya, s: &str, agama: &str) { - let i = p.terms().len() - 1; +impl<'a> StriPrakriya<'a> { + fn new(p: &'a mut Prakriya) -> Option { + let i_prati = p.find_last_where(|t| t.is_pratipadika() || t.is_taddhita() || t.is_krt())?; + Some(Self { + p, + done: false, + i_prati, + }) + } - let a = Term::make_agama(agama); - p.terms_mut().push(a); + fn last(&self) -> &Term { + self.p.get(self.i_prati).expect("ok") + } - let mut t = Term::make_upadesha(s); - t.add_tag(T::Pratyaya); - p.terms_mut().push(t); + /// Prevents any stri-pratyaya from being added to the prakriya. + fn block(&mut self, rule: impl Into) { + self.p.step(rule.into()); + self.done = true; + } - p.step(rule); + /// Tries to add `stri` to the prakriya. + /// + /// Returns whether the pratyaya was added. + fn try_add(&mut self, rule: impl Into, stri: Stri) -> bool { + self.try_add_with(rule, stri, |_| {}) + } - it_samjna::run(p, i + 1).expect("should never fail"); - it_samjna::run(p, i + 2).expect("should never fail"); -} + /// Tries to add `stri` to the prakriya, then runs `func` if `stri` was added successfully. + /// + /// Returns whether the pratyaya was added. + fn try_add_with( + &mut self, + rule: impl Into, + stri: Stri, + func: impl Fn(&mut Prakriya), + ) -> bool { + if !self.done { + self.p.terms_mut().insert(self.i_prati + 1, stri.to_term()); + func(self.p); + self.p.step(rule.into()); + it_samjna::run(self.p, self.i_prati + 1).expect("should never fail"); + + // HACK: nadi for NIz, etc. + if stri.as_str().contains("I") { + self.p.add_tag_at("1.4.3", self.i_prati + 1, T::Nadi); + } + + self.done = true; + true + } else { + false + } + } + + fn try_add_with_agama(&mut self, rule: impl Into, stri: Stri, agama: &str) -> bool { + if !self.done { + let i_prati = self.i_prati; + let terms = self.p.terms_mut(); + terms.insert(i_prati + 1, Term::make_agama(agama)); + terms.insert(i_prati + 2, stri.to_term()); + self.p.step(rule); + + it_samjna::run(self.p, i_prati + 1).expect("should never fail"); + it_samjna::run(self.p, i_prati + 2).expect("should never fail"); + + self.done = true; + true + } else { + false + } + } -fn optional_add(rule: Code, p: &mut Prakriya, s: &str) { - if p.is_allowed(rule) { - let i = p.terms().len(); - let mut t = Term::make_upadesha(s); - t.add_tag(T::Pratyaya); - - p.terms_mut().push(t); - p.step(rule); - it_samjna::run(p, i).expect("should never fail"); - } else { - p.decline(rule); + /// Tries to add `stri` to the prakriya according to the optional rule `rule`. + /// + /// Returns whether the pratyaya was added. + fn optional_try_add(&mut self, rule: impl Into, stri: Stri) -> bool { + let rule = rule.into(); + if !self.done { + if self.p.is_allowed(rule) { + self.try_add(rule, stri) + } else { + self.p.decline(rule); + false + } + } else { + false + } } } /// Runs strītva rules. pub fn run(p: &mut Prakriya) -> Option<()> { + use Stri::*; + if !p.has_tag(T::Stri) { return None; } - let last = p.terms().last()?; - - if last.has_text_in(BAHU_ADI) { - optional_add("4.1.45", p, "NIz"); - } else if last.has_text_in(INDRA_ADI) { - add_with_agama("4.1.49", p, "NIz", "Anu~k"); - } else if last.has_text_in(AJA_ADI) || last.has_antya('a') { - add("4.1.4", p, "wAp"); - } else if last.has_text_in(SVASR_ADI) { - // TODO: Sat - p.step("4.1.10"); + let mut sp = StriPrakriya::new(p)?; + let last = sp.last(); + + // HACK: block uzRihA for now. + if last.has_text("uzRih") { + return None; + } + + if !last.has_tag(T::Upasarjana) { + if (last.has_tag(T::wit) && last.has_antya('a') && !last.has_tag(T::La)) + // The rule has "Qa" which indicates the class of Qa-pratyayas. For simplicity, + // we enumerate them manually. But, we ignore the literal "Qa"-pratyaya because it's + // always napumsaka. + || last.has_u_in(&["Qak", "QaY"]) + // Other pratyayas are as given. + || last.has_u_in(&[ + "aR", "aY", "dvayasac", "daGnac", "mAtrac", "tayap", "Wak", "WaY", "kaY", "kvarap", + ]) + { + sp.try_add("4.1.15", NIp); + } else if last.has_u("yaY") { + sp.try_add("4.1.16", NIp); + } else if last.has_tag(T::zit) || last.has_text_in(gana::GAURA_ADI) { + // nartanI, gOrI + sp.try_add("4.1.41", NIz); + } else if last.has_text_in(gana::BAHU_ADI) { + // bahvI, bahu + sp.optional_try_add("4.1.45", NIz); + } else if last.has_text_in(INDRA_ADI) { + sp.try_add_with_agama("4.1.49", NIz, "Anu~k"); + } + } + + let last = sp.last(); + if last.has_text_in(gana::AJA_ADI) || last.has_antya('a') { + // ajA, ... + sp.try_add("4.1.4", wAp); + } else if last.has_tag_in(&[T::udit, T::fdit, T::xdit]) { + if last.is_dhatu() { + sp.block("4.1.6.v1") + } else { + // BavatI, pacantI, ... + sp.try_add("4.1.6", NIp); + } + } else if last.ends_with("van") { + let i_prati = sp.i_prati; + // SarvarI + sp.try_add_with("4.1.7", NIp, |p| { + p.set(i_prati, |t| t.set_antya("r")); + }); + } else if last.has_text("pAd") { + // dvipadA, ... + let done = sp.optional_try_add("4.1.9", wAp); + if !done { + // dvipAt, dvipadI, ... + sp.optional_try_add("4.1.8", NIp); + } + } else if last.has_tag(T::zaw) || last.has_text_in(gana::SVASR_ADI) { + // + sp.block("4.1.10"); + } else if last.ends_with("man") { + let done = sp.optional_try_add("4.1.13", wAp); + if !done { + // pAme, pAmAnO, ... + sp.block("4.1.11"); + } } else if last.has_antya('f') || last.has_antya('n') { - add("4.1.5", p, "NIp"); + // kartrI, daRqinI, ... + sp.try_add("4.1.5", NIp); } Some(()) diff --git a/vidyut-prakriya/src/sup_karya.rs b/vidyut-prakriya/src/sup_karya.rs index 8073099..52375ae 100644 --- a/vidyut-prakriya/src/sup_karya.rs +++ b/vidyut-prakriya/src/sup_karya.rs @@ -1,53 +1,54 @@ use crate::args::{SubantaArgs, Vacana, Vibhakti}; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::it_samjna; -use crate::prakriya::Prakriya; -use crate::tag::Tag as T; -use crate::term::Term; -#[allow(unused)] fn find_sup(vibhakti: Vibhakti, vacana: Vacana) -> &'static str { + use Vacana::*; + use Vibhakti::*; match (vibhakti, vacana) { - (Vibhakti::Prathama, Vacana::Eka) => "su~", - (Vibhakti::Prathama, Vacana::Dvi) => "O", - (Vibhakti::Prathama, Vacana::Bahu) => "jas", - (Vibhakti::Dvitiya, Vacana::Eka) => "am", - (Vibhakti::Dvitiya, Vacana::Dvi) => "Ow", - (Vibhakti::Dvitiya, Vacana::Bahu) => "Sas", - (Vibhakti::Trtiya, Vacana::Eka) => "wA", - (Vibhakti::Trtiya, Vacana::Dvi) => "ByAm", - (Vibhakti::Trtiya, Vacana::Bahu) => "Bis", - (Vibhakti::Caturthi, Vacana::Eka) => "Ne", - (Vibhakti::Caturthi, Vacana::Dvi) => "ByAm", - (Vibhakti::Caturthi, Vacana::Bahu) => "Byas", - (Vibhakti::Panchami, Vacana::Eka) => "Nasi~", - (Vibhakti::Panchami, Vacana::Dvi) => "ByAm", - (Vibhakti::Panchami, Vacana::Bahu) => "Byas", - (Vibhakti::Sasthi, Vacana::Eka) => "Nas", - (Vibhakti::Sasthi, Vacana::Dvi) => "os", - (Vibhakti::Sasthi, Vacana::Bahu) => "Am", - (Vibhakti::Saptami, Vacana::Eka) => "Ni", - (Vibhakti::Saptami, Vacana::Dvi) => "os", - (Vibhakti::Saptami, Vacana::Bahu) => "sup", - - (Vibhakti::Sambodhana, Vacana::Eka) => "su~", - (Vibhakti::Sambodhana, Vacana::Dvi) => "O", - (Vibhakti::Sambodhana, Vacana::Bahu) => "jas", + (Prathama, Eka) => "su~", + (Prathama, Dvi) => "O", + (Prathama, Bahu) => "jas", + (Dvitiya, Eka) => "am", + (Dvitiya, Dvi) => "Ow", + (Dvitiya, Bahu) => "Sas", + (Trtiya, Eka) => "wA", + (Trtiya, Dvi) => "ByAm", + (Trtiya, Bahu) => "Bis", + (Caturthi, Eka) => "Ne", + (Caturthi, Dvi) => "ByAm", + (Caturthi, Bahu) => "Byas", + (Panchami, Eka) => "Nasi~", + (Panchami, Dvi) => "ByAm", + (Panchami, Bahu) => "Byas", + (Sasthi, Eka) => "Nas", + (Sasthi, Dvi) => "os", + (Sasthi, Bahu) => "Am", + (Saptami, Eka) => "Ni", + (Saptami, Dvi) => "os", + (Saptami, Bahu) => "sup", + + (Sambodhana, Eka) => "su~", + (Sambodhana, Dvi) => "O", + (Sambodhana, Bahu) => "jas", } } -#[allow(unused)] pub fn run(p: &mut Prakriya, args: &SubantaArgs) -> Option<()> { let sup = find_sup(args.vibhakti(), args.vacana()); let mut sup = Term::make_upadesha(sup); - sup.add_tag(T::Pratyaya); - sup.add_tag(T::Vibhakti); - sup.add_tag(T::Sup); - sup.add_tag(args.vibhakti().as_tag()); - sup.add_tag(args.vacana().as_tag()); + sup.add_tags(&[ + T::Pratyaya, + T::Vibhakti, + T::Sup, + args.vibhakti().as_tag(), + args.vacana().as_tag(), + ]); - p.add_tag(args.linga().as_tag()); - p.add_tag(args.vacana().as_tag()); + p.add_tags(&[args.linga().as_tag(), args.vacana().as_tag()]); if args.vibhakti() == Vibhakti::Sambodhana { p.add_tag(T::Sambodhana); } diff --git a/vidyut-prakriya/src/sutrapatha.rs b/vidyut-prakriya/src/sutrapatha.rs new file mode 100644 index 0000000..3dc5630 --- /dev/null +++ b/vidyut-prakriya/src/sutrapatha.rs @@ -0,0 +1,395 @@ +/*! +The rules of the Ashtadhyayi. + + +# About the sutrapatha + +The sutrapatha is the core of Paniniya-vyakarana and defines the grammar itself. It consists of +around 4000 formal rules that generate valid Sanskrit expressions if applied with the various +secondary texts of the Paninian school (i.e. the Unadipatha, the Ganapatha, the Dhatupatha, and the +Linganushasanam). + +The rules of the sutrapatha enable and disable each other in various complex patterns. Most +commonly, two rules have an utsarga-apavAda relation, where an exception (apavAda) takes priority +over a general principle (utsarga). The sutrapatha uses various other conflict resolution +mechanisms as well. Most notably, the bulk of the tripAdi (8.2 - 8.4) uses an imperative control +flow, meaning that an earlier rule takes priority over a later one. + + +# About this code + +To manage some of the complexity of the sutrapatha, we have tried to group rules according to their +logical function: defining lakaras, adding pratyayas, etc. This is not always possible due to the +inherent complexities of the text. For that reason, we strongly recommend navigating the rules of +the sutrapatha by grepping over our code. +*/ +use crate::ac_sandhi; +use crate::angasya; +use crate::ardhadhatuka; +use crate::args::Upapada; +use crate::args::{ + Artha, Dhatu, KrdantaArgs, Lakara, Pada, Pratipadika, Prayoga, SamasaArgs, SubantaArgs, + TaddhitantaArgs, TinantaArgs, +}; +use crate::atidesha; +use crate::atmanepada; +use crate::core::errors::*; +use crate::core::Prakriya; +use crate::core::Tag; +use crate::core::Term; +use crate::dhatu_karya; +use crate::dvitva; +use crate::it_agama; +use crate::krt; +use crate::la_karya; +use crate::linganushasanam; +use crate::misc; +use crate::pratipadika_karya; +use crate::samasa; +use crate::samjna; +use crate::samprasarana; +use crate::sanadi; +use crate::stritva; +use crate::sup_karya; +use crate::taddhita; +use crate::tin_pratyaya; +use crate::tripadi; +use crate::uttarapade; +use crate::vikarana; + +/// Adds a dhatu to the prakriya and runs basic follow-up tasks, such as: +/// +/// - adding upasargas +/// - replacing initial `R` and `z` with `n` and `s`, respectively. +/// - recording and removing any it-samjnas +/// - adding any necessary sanAdi-pratyayas. +/// +/// Scope: tinantas and krdantas +fn add_dhatu(p: &mut Prakriya, dhatu: &Dhatu, is_ardhadhatuka: bool) -> Result<()> { + dhatu_karya::run(p, dhatu)?; + + sanadi::try_add_specific_sanadi_pratyayas(p, is_ardhadhatuka); + if p.terms().last().expect("ok").is_pratyaya() { + samjna::run(p); + run_main_rules(p, None, false)?; + } + + for s in dhatu.sanadi() { + sanadi::try_add_general_sanadi_pratyaya(p, *s); + samjna::run(p); + // Needed for BIzayate, etc. + // TODO: revisit this. Is this really necessary here? + atmanepada::run(p); + run_main_rules(p, None, false)?; + } + + if !dhatu.sanadi().is_empty() { + p.debug("~~~~~~~~~~~~~~ completed dhatu ~~~~~~~~~~~~~~~~~~") + } + + Ok(()) +} + +/// Adds a lakara to the prakriya and decides which pada it is allowed to use. +/// +/// Scope: tinantas and certain krdantas (gacCat, jagmivas, gamyamAna, ...) +fn add_lakara_and_decide_pada(p: &mut Prakriya, lakara: Lakara) { + la_karya::run(p, lakara); + // Constraints: + // - must come after `la_karya`, which affects the choice of cakz -> KyAY. + ardhadhatuka::dhatu_adesha_before_pada(p, lakara); + // Constraints: + // - must come after `dhatu_adesha_before_pada` to allow parasmaipada for cakz -> KyAY. + atmanepada::run(p); + // Try adding am-pratyaya and the corresponding dhatu before tin-adesha, since doing so affects + // which tin-pratyaya we use with bhU and kR. + vikarana::try_add_am_pratyaya_for_lit(p); +} + +/// Scope: tinantas and krdantas +fn run_dhatu_tasks_before_pratyaya(p: &mut Prakriya) { + // Needed transitively for dhatu-samprasarana. + angasya::try_pratyaya_adesha(p); + // Must run before it-Agama. + angasya::try_cinvat_for_bhave_and_karmani_prayoga(p); + + // Depends on jha_adesha since it conditions on the first sound. + it_agama::run_before_attva(p); + // Depends on it_agama for certain rules. + atidesha::run_before_attva(p); + + // Samprasarana of the dhatu is conditioned on several other operations, which we must execute + // first: + // + // 1. jha_adesha (affects it-Agama). + // 2. it_agama (affects kit-Nit) + // 3. atidesha (for kit-Nit) + samprasarana::run_for_dhatu(p); + // Ad-Adeza and other special tasks for Ardhadhatuka + ardhadhatuka::run_before_dvitva(p); + + // Now finish it_agama and atidesha + it_agama::run_after_attva(p); + atidesha::run_after_attva(p); +} + +/// Scope: all prakriyas +fn run_main_rules(p: &mut Prakriya, lakara: Option, is_ardhadhatuka: bool) -> Result<()> { + misc::run_pad_adi(p); + + p.debug("==== Tin-siddhi ===="); + // Do lit-siddhi and AzIrlin-siddhi first to support the valAdi vArttika for aj -> vi. + let is_lit_or_ashirlin = matches!(lakara, Some(Lakara::Lit) | Some(Lakara::AshirLin)); + if let Some(lakara) = lakara { + if is_lit_or_ashirlin { + tin_pratyaya::try_general_siddhi(p, lakara); + tin_pratyaya::try_siddhi_for_jhi(p, lakara); + } + } + + p.debug("==== Vikaranas ===="); + ardhadhatuka::run_before_vikarana(p, lakara, is_ardhadhatuka); + vikarana::run(p)?; + samjna::run(p); + + if let Some(lakara) = lakara { + if !is_lit_or_ashirlin { + tin_pratyaya::try_general_siddhi(p, lakara); + } + } + + // Constraints: + // - should run before atidesha rules because of Rittva. + // - should also run for subantas. + angasya::try_add_or_remove_nit(p); + + p.debug("==== Dhatu tasks ===="); + run_dhatu_tasks_before_pratyaya(p); + + // Must follow tin-siddhi and it-Agama, which could change the first sound of the pratyaya. + ardhadhatuka::try_add_am_agama(p); + + p.debug("==== Dvitva (dvirvacane 'ci) ===="); + dvitva::try_dvirvacane_aci(p); + let used_dvirvacane_aci = p.find_last_where(Term::is_abhyasta).is_some(); + if used_dvirvacane_aci { + samprasarana::run_for_abhyasa(p); + } + + // If Ji causes dvitva, that dvitva will be performed in `try_dvirvacane_aci` above. + // So by this point, it's safe to replace Ji. (See 3.4.109, which replaces Ji if it follows a + // term called `abhyasta`.) + if let Some(lakara) = lakara { + if !is_lit_or_ashirlin { + tin_pratyaya::try_siddhi_for_jhi(p, lakara); + } + } + uttarapade::run(p); + angasya::maybe_do_jha_adesha(p); + + ac_sandhi::try_sup_sandhi_before_angasya(p); + angasya::run_before_dvitva(p); + + p.debug("==== Dvitva (default) ===="); + dvitva::run(p); + if !used_dvirvacane_aci { + samprasarana::run_for_abhyasa(p); + } + + p.debug("==== After dvitva ===="); + angasya::run_after_dvitva(p); + uttarapade::run_after_guna(p); + ac_sandhi::try_sup_sandhi_after_angasya(p); + ac_sandhi::run_common(p); + + p.debug("==== Tripadi ===="); + tripadi::run(p); + + Ok(()) +} + +/// Derives a single tinanta from the given conditions. +pub fn derive_tinanta( + mut prakriya: Prakriya, + dhatu: &Dhatu, + args: &TinantaArgs, +) -> Result { + let p = &mut prakriya; + let prayoga = args.prayoga(); + let lakara = args.lakara(); + let purusha = args.purusha(); + let vacana = args.vacana(); + p.add_tags(&[prayoga.as_tag(), purusha.as_tag(), vacana.as_tag()]); + p.set_lakara(lakara); + + // Prayogas other than kartari will never be sarvadhatuka, since yak-vikarana is not + // sarvadhatuka. + let is_ardhadhatuka = match prayoga { + Prayoga::Kartari => lakara.is_ardhadhatuka(), + _ => true, + }; + + add_dhatu(p, dhatu, is_ardhadhatuka)?; + add_lakara_and_decide_pada(p, lakara); + tin_pratyaya::adesha(p, purusha, vacana); + samjna::run(p); + run_main_rules(p, Some(lakara), is_ardhadhatuka)?; + + Ok(prakriya) +} + +/// Derives a single subanta from the given conditions. +pub fn derive_subanta( + mut prakriya: Prakriya, + pratipadika: &Pratipadika, + args: &SubantaArgs, +) -> Result { + let p = &mut prakriya; + + // First, create the pratipadika. + pratipadika_karya::add_one(p, pratipadika); + + p.add_tag(args.linga().as_tag()); + pratipadika_karya::run_napumsaka_rules(p); + + // Then, add the sup-pratyaya. + sup_karya::run(p, args); + samjna::run(p); + + // Add strI-pratyayas. This should be done after adding the sup-pratyaya so that we satisfy the + // following constraints: + // + // - su~ must be added before sup-luk (7.1.23) + // - sup-luk must be checked before changing adas to ada (7.2.102) + // - ada must be in place before running stritva (4.1.4) + angasya::run_before_stritva(p); + stritva::run(p); + + run_main_rules(p, None, false)?; + + Ok(prakriya) +} + +/// Derives a single krdanta from the given conditions. +pub fn derive_krdanta( + mut prakriya: Prakriya, + dhatu: &Dhatu, + args: &KrdantaArgs, +) -> Result { + let p = &mut prakriya; + + // If defined, set the meaning condition that this prakriya must follow. + if let Some(artha) = args.artha() { + p.set_artha(Artha::Krt(artha)); + } + + if let Some(upa) = args.upapada() { + let mut upapada = Term::make_upadesha(upa.text()); + upapada.add_tag(Tag::Pratipadika); + match upa { + Upapada::Avyaya(_) => upapada.add_tag(Tag::Avyaya), + _ => (), + } + p.push(upapada); + + let mut su = Term::make_text(""); + su.add_tags(&[Tag::Pratyaya, Tag::Vibhakti, Tag::Sup, Tag::Pada]); + p.push(su); + samjna::run(p); + } + + let krt = args.krt(); + add_dhatu(p, dhatu, krt.is_ardhadhatuka())?; + if let Some(la) = args.lakara() { + p.add_tag(Tag::Kartari); + add_lakara_and_decide_pada(p, la); + } + let added = krt::run(p, args); + if !added { + return Err(Error::Abort(prakriya)); + } + + linganushasanam::run(p); + stritva::run(p); + samjna::run(p); + run_main_rules(p, None, true)?; + + Ok(prakriya) +} + +pub fn derive_taddhitanta( + mut prakriya: Prakriya, + pratipadika: &Pratipadika, + args: &TaddhitantaArgs, +) -> Result { + let taddhita = args.taddhita(); + let p = &mut prakriya; + + // If defined, set the meaning condition that this prakriya must follow. + if let Some(artha) = args.artha() { + p.set_artha(Artha::Taddhita(artha)); + } + + // Begin the derivation. + pratipadika_karya::add_one(p, pratipadika); + samjna::run(p); + + let added = taddhita::run(p, taddhita); + if !added { + if cfg!(debug_assertions) { + println!("{:?}: {:#?}", args.taddhita(), p); + } + return Err(Error::Abort(prakriya)); + } + + angasya::run_before_stritva(p); + linganushasanam::run(p); + stritva::run(p); + samjna::run(p); + run_main_rules(p, None, false)?; + + Ok(prakriya) +} + +pub fn derive_stryanta(mut prakriya: Prakriya, pratipadika: &Pratipadika) -> Result { + let p = &mut prakriya; + + pratipadika_karya::add_one(p, pratipadika); + p.add_tag(Tag::Stri); + + stritva::run(p); + samjna::run(p); + run_main_rules(p, None, false)?; + + Ok(prakriya) +} + +pub fn derive_samasa(mut prakriya: Prakriya, args: &SamasaArgs) -> Result { + let p = &mut prakriya; + + pratipadika_karya::add_all(p, &args); + let added = samasa::run(p, &args); + if !added { + return Err(Error::Abort(prakriya)); + } + + pratipadika_karya::run_napumsaka_rules(p); + taddhita::run_for_samasas(p); + run_main_rules(p, None, false)?; + + Ok(prakriya) +} + +pub fn derive_vakya(mut prakriya: Prakriya, padas: &[Pada]) -> Result { + let p = &mut prakriya; + for pada in padas { + for term in pada.terms() { + p.push(term.clone()); + } + } + + samjna::run_for_pragrhya(p); + run_main_rules(p, None, false)?; + + Ok(prakriya) +} diff --git a/vidyut-prakriya/src/taddhita.rs b/vidyut-prakriya/src/taddhita.rs index 1a2c53d..c34858f 100644 --- a/vidyut-prakriya/src/taddhita.rs +++ b/vidyut-prakriya/src/taddhita.rs @@ -10,9 +10,8 @@ rules in the Ashtadhyayi. The core types here are: derivations with taddhitas. */ use crate::args::Taddhita; -use crate::prakriya::Prakriya; +use crate::core::Prakriya; -mod gana; mod matvartha_prakarana; mod nan_snan_adhikara_prakarana; mod panchami_prakarana; @@ -73,8 +72,11 @@ pub fn run(prakriya: &mut Prakriya, taddhita: Taddhita) -> bool { pragiviya::run(tp); // 5.3.96 - 5.4.67 svarthika_prakarana::run(tp); - // 5.4.68 - 5.4.160 (end of 5.4) - samasanta_prakarana::run(tp); tp.has_taddhita } + +pub fn run_for_samasas(prakriya: &mut Prakriya) { + // 5.4.68 - 5.4.160 (end of 5.4) + samasanta_prakarana::run(prakriya); +} diff --git a/vidyut-prakriya/src/taddhita/gana.rs b/vidyut-prakriya/src/taddhita/gana.rs index 966b171..139597f 100644 --- a/vidyut-prakriya/src/taddhita/gana.rs +++ b/vidyut-prakriya/src/taddhita/gana.rs @@ -1,1018 +1,2 @@ -/// Various lists (ganas) for the taddhita-prakarana. -/// -/// Unless otherwise mentioned, all lists come from the Kashika Vrtti. -/// For 4.1.84. -pub const ASHVAPATI_ADI: &[&str] = &[ - "aSvapati", - "Satapati", - "Danapati", - "gaRapati", - "rAzwrapati", - "kulapati", - "gfhapati", - "DAnyapati", - "paSupati", - "Darmapati", - "saBApati", - "prARapati", - "kzetrapati", -]; -/// For 4.1.86. -pub const UTSA_ADI: &[&str] = &[ - "utsa", - "udapAna", - "vikara", - "vinoda", - "mahAnada", - "mahAnasa", - "mahAprARa", - "taruRa", - "taluna", - "bazkayAse", - "Denu", - "pfTivI", - "paNkti", - "jagatI", - "trizwuB", - "anuzwuB", - "janapada", - "Barata", - "uSInara", - "grIzma", - "pIlu", - "kula", - "udasTAna", - "pfzadaMSe", - "BallakIya", - "raTantara", - "maDyandina", - "bfhat", - "mahat", - "sattvat", - "kuru", - "paYcAla", - "indrAvasAna", - "uzRih", - "kakuB", - "suvarRa", - "deva", -]; - -/// For 4.1.96. -pub const BAHU_ADI: &[&str] = &[ - "bAhu", - "upabAhu", - "upavAku", - "nivAku", - "SivAku", - "vawAku", - "upanindu", - "upabindu", - "vfzalI", - "vfkalA", - "cUqA", - "balAkA", - "mUzikA", - "kuSalA", - "BagalA", - "CagalA", - "DruvakA", - "DuvakA", - "sumitrA", - "durmitrA", - "puzkarasad", - "anuharat", - "devaSarman", - "agniSarman", - "BadraSarman", - "suSarman", - "kunAman", - "sunAman", - "paYcan", - "saptan", - "azwan", - // amitOjasa has sa-lopa - "amitOjasa", - "suDAvat", - "udaYcu", - "Siras", - "mAza", - "SarAvin", - "marIcI", - "kSemavfdDin", - "SfNKalatodin", - "KaranAdin", - "nagaramardin", - "prAkAramardin", - "loman", - "ajIgarta", - "kfzra", - "yuDizWira", - "arjuna", - "sAmba", - "gada", - "pradyumna", - "rAma", - "udaNku", -]; - -/// For 4.1.98. -pub const KUNJA_ADI: &[&str] = &[ - "kuYja", "braDna", "SaNKa", "Basman", "gaRa", "loman", "SaWa", "SAka", "SAkawa", "SuRqA", - "SuBa", "vipASa", "skanda", "stamBa", -]; - -/// For 4.1.99. -pub const NADA_ADI: &[&str] = &[ - "naqa", - "cara", - "baka", - "muYja", - "itika", - "itiSa", - "upaka", - "lamaka", - "SalaNku", - "SalaNkam", - "saptala", - "vAjapya", - "tika", - "agniSarman", - "prARa", - "nara", - "sAyaka", - "dAsa", - "mitra", - "dvIpa", - "piNgara", - "piNgala", - "kiNkara", - "kiNkala", - "kAtara", - "kAtala", - "kASya", - "kASyapa", - "kAvya", - "aja", - "amuzya", - "kfzRa", - "raRa", - "amitra", - "ligu", - "citra", - "kumAra", - "krozwu", - "krozwam", - "loha", - "durga", - "stamBa", - "SiMSipA", - "agra", - "tfRa", - "Sakawa", - "sumanas", - "sumata", - "mimata", - "fk", - "jat", - "yuganDara", - "haMsaka", - "daRqin", - "hastin", - "paYcAla", - "camasin", - "sukftya", - "sTiraka", - "brAhmaRa", - "cawaka", - "badara", - "aSvala", - "Karapa", - "kAmuka", - "vrahmadatta", - "udumbara", - "SoRa", - "aloha", - "daRqa", -]; - -/// For 4.1.104. -pub const BIDA_ADI: &[&str] = &[ - "bida", - "urva", - "kaSyapa", - "kuSika", - "BaradvAja", - "upamanyu", - "kilAlapa", - "kidarBa", - "viSvAnara", - "fzwizeRa", - "ftaBAga", - "haryaSva", - "priyaka", - "Apastamba", - "kUcavAra", - "Saradvat", - "Sunaka", - "Denu", - "gopavana", - "Sigru", - "bindu", - "BAjana", - "aSvAvatAna", - "SyAmAka", - "SyamAka", - "SyAparRa", - "harita", - "kindAsa", - "vahraska", - "arkalUza", - "vaDyoza", - "vizRuvfdDa", - "pratiboDa", - "raTAntara", - "raTItara", - "gavizWira", - "nizAda", - "maWara", - "mfda", - "punarBU", - "putra", - "duhitf", - "nanAndf", - "parastrI", -]; - -/// For 4.1.105. -pub const GARGA_ADI: &[&str] = &[ - "garga", - "vatsa", - "vAjAse", - "saMskfti", - "aja", - "vyAGrapAt", - "vidaBft", - "prAcInayoga", - "agasti", - "pulasti", - "reBa", - "agniveSa", - "SaNKa", - "SaWa", - "GUma", - "avawa", - "camasa", - "DanaYjaya", - "manasa", - "vfkza", - "viSvAvasu", - "janamAna", - "lohita", - "SaMsita", - "baBru", - "maRqu", - "makzu", - "aligu", - "SaNku", - "ligu", - "gulu", - "mantu", - "jigIzu", - "manu", - "tantu", - "manAyI", - "BUta", - "kaTaka", - "kaza", - "taRqa", - "vataRqa", - "kapi", - "kata", - "kurukata", - "anaquH", - "kaRva", - "Sakala", - "gokakza", - "agastya", - "kuRqina", - "yajYavalka", - "uBaya", - "jAta", - "virohita", - "vfzagaRa", - "rahUgaRa", - "SaRqila", - "vaRa", - "kaculuka", - "mudgala", - "musala", - "parASara", - "jatUkarRa", - "mAntrita", - "saMhita", - "aSmaraTa", - "SarkarAkza", - "pUtimAza", - "sTURa", - "araraka", - "piNgala", - "kfzRa", - "golunda", - "ulUka", - "titikza", - "Bizaj", - "Baqita", - "BaRqita", - "dalBa", - "cikita", - "devahU", - "indrahU", - "ekalU", - "pippalU", - "vfdagni", - "jamadagni", - "suloBin", - "ukatTa", - "kuwIgu", -]; - -/// For 4.1.110. -pub const ASHVA_ADI: &[&str] = &[ - "aSva", - "aSman", - "SaNKa", - "pawu", - "rohiRa", - "KarjUra", - "KarjUla", - "piYjUra", - "Baqila", - "BaRqila", - "Baqita", - "BaRqita", - "BaRqika", - "prahfta", - "romAda", - "kzatra", - "grIvA", - "kASa", - "golANkya", - "arka", - "svana", - "Dvana", - "pAda", - "cakra", - "kula", - "pavitra", - "gomin", - "SyAma", - "DUma", - "DUmra", - "vAgmin", - "viSvAnara", - "kuwa", - "veSa", - "Sapa", - "natta", - "taqa", - "naqa", - "grIzma", - "arha", - "viSamya", - "viSAlA", - "giri", - "capala", - "cunama", - "dAsaka", - "vElya", - "Darma", - "Anaquhra", - "puMsijAta", - "arjuna", - "SUdraka", - "sumanas", - "durmanas", - "kzAnta", - "prAcya", - "kita", - "kARa", - "cumba", - "SravizWA", - "vIkzya", - "pavindA", - "Atreya", - "kutsa", - "Atava", - "kitava", - "Siva", - "Kadira", - "BAradvAja", -]; - -/// For 4.1.112. -pub const SHIVA_ADI: &[&str] = &[ - "Siva", - "prOzWa", - "prOzWika", - "caRqa", - "jamBa", - "muni", - "sanDi", - "BUri", - "kuWAra", - "anaBimlAna", - "kakutsTa", - "kahoqa", - "leKa", - "roDa", - "KaYjana", - "kohaqa", - "pizwa", - "hehaya", - "KaYjAra", - "KaYjAla", - "surohikA", - "parRa", - "kahUza", - "parila", - "vataRqa", - "tfRa", - "karRa", - "kzIrahfda", - "jalahfda", - "parizika", - "jawilika", - "goPilika", - "baDirikA", - "maYjIraka", - "vfzRika", - "reKa", - "AleKana", - "viSravaRa", - "ravaRa", - "vartanAkza", - "piwaka", - "piwAka", - "tfkzAka", - "naBAka", - "UrRanABa", - "jaratkAru", - "utkzipA", - "rohitika", - "AryaSveta", - "supizwa", - "KarjUrakarRa", - "masUrakarRa", - "tURakarRa", - "mayUrakarRa", - "Kaqaraka", - "takzan", - "fzwizeRa", - "gaNgA", - "vipASa", - "yaska", - "lahra", - "druhyu", - "ayaHsTURa", - "Balandana", - "virUpAkza", - "BUmi", - "ilA", - "sapatnI", - "dvyaca", -]; - -/// For 4.1.123. -pub const SHUBHRA_ADI: &[&str] = &[ - "SuBra", - "vizwapura", - // TODO: many others -]; - -/// For 4.1.126. -pub const KALYANI_ADI: &[&str] = &[ - "kalyARI", - "suBagA", - "durBagA", - "banDakI", - "anudfzwi", - "anusfzwi", - "jaratI", - "balIvardI", - "jyezWA", - "kanizWA", - "maDyamA", - "parastrI", -]; - -/// For 4.1.146. -pub const REVATI_ADI: &[&str] = &[ - "revatI", - "aSvapAlI", - "maRipAlI", - "dvArapAlI", - "vfkavaYcin", - "vfkabanDu", - "vfkagrAha", - "karRagrAha", - "daRqagrAha", - "kukkUwAkza", - "kakudAkza", - "cAmaragrAha", -]; - -/// For 4.2.38. -pub const BHIKSHA_ADI: &[&str] = &[ - "BikzA", "garBiRI", "kzetra", "karIza", "aNgAra", "carmin", "Darmin", "sahasra", "yuvati", - "padAti", "padDati", "aTarvan", "dakziRA", "BUta", -]; - -/// For 4.2.45. -pub const KHANDIKA_ADI: &[&str] = &[ - "KaRqikA", - "vaqavA", - "kzudrakamAla", - "Bikzuka", - "Suka", - "ulUka", - "Svan", - "yuga", - "ahan", - "varatrA", - "halabanDa", -]; - -/// For 4.2.49. -pub const PASHA_ADI: &[&str] = &[ - "pASa", "tfRa", "DUma", "vAta", "aNgAra", "pota", "bAlaka", "piwaka", "piwAka", "Sakawa", - "hala", "naqa", "vana", -]; - -/// For 4.2.75. -pub const SANKALA_ADI: &[&str] = &[ - "saNkala", - "puzkala", - "udvapa", - "uqupa", - "utpuwa", - "kumBa", - "viDAna", - "sudakza", - "sudatta", - "suBUta", - "sunetra", - "supiNgala", - "sikatA", - "pUtIkI", - "pUlasa", - "kUlAsa", - "palASa", - "niveSa", - "gaveza", - "gamBIra", - "itara", - "Sarman", - "ahan", - "loman", - "veman", - "varuRa", - "bahula", - "sadyoja", - "aBizikta", - "goBft", - "rAjaBft", - "gfha", - "Bfta", - "Balla", - "mAla", - "vft", -]; - -/// For 4.2.77. -pub const SUVASTA_ADI: &[&str] = &[ - "suvAstu", - "varRu", - "BaRqu", - "KaRqu", - "secAlin", - "karpUrin", - "SiKaRdin", - "garta", - "karkaSa", - "SawIkarRa", - "kfzRa", - "karka", - "karNkaDU matI", - "gohra", - "ahisakTa", - "vft", -]; - -/// For 4.2.86. -pub const MADHU_ADI: &[&str] = &[ - "maDu", - "bisa", - "sTARu", - "muzwi", - "ikzu", - "veRu", - "ramya", - "fkza", - "karkanDu", - "SamI", - "kirIra", - "hima", - "kiSarA", - "SarpaRA", - "marut", - "maruva", - "dArvAGAwa", - "Sara", - "izwakA", - "takzaSilA", - "Sakti", - "AsandI", - "Asuti", - "SalAkA", - "AmiDI", - "KaqA", - "vewA", - "maDvAdiH", -]; - -/// For 4.2.95. -pub const KATRI_ADI: &[&str] = &[ - "katri", - "umBi", - "puzkara", - "modana", - "kumBI", - "kuRqina", - "nagara", - "vaYjI", - "Bakti", - "mAhizmatI", - "carmaRvatI", - "grAma", - "uKyA", - // kuqyA takes ya-lopa - "kuqyA", - "katryAdiH", -]; - -/// For 4.2.97. -pub const NADI_ADI: &[&str] = &[ - "nadI", - "mahI", - "vArARasI", - "SrAvastI", - "kOSAmbI", - "navakOSAmbI", - "kASaParI", - "KAdirI", - "pUrvanagarI", - "pAvA", - "mAvA", - "sAlvA", - "dArvA", - "dAlvA", - "vAsenakI", - "vaqavA", -]; - -/// For 4.2.86. -pub const KASHI_ADI: &[&str] = &[ - "kASi", - "cedi", - "bedi", - "saMjYA", - "saMvAha", - "acyuta", - "mohamAna", - "SakulAda", - "hastikarzU", - "kudAman", - "hiraRya", - "karaRa", - "goDASana", - "BOriki", - "BOliNgi", - "arindama", - "sarvamitra", - "devadatta", - "sADumitra", - "dAsamitra", - "dAsagrAma", - "sODAvatAna", - "yuvarAja", - "uparAja", - "sinDumitra", - "devarAja", - // ApadAdipUrvapadAt kAlAt - "ApatkAla", - "UrDvakAla", - "tatkAla", -]; - -/// For 4.2.133. -pub const KACCHA_ADI: &[&str] = &[ - "kacCa", - "sinDu", - "varRu", - "ganDAra", - "maDumat", - "kamboja", - "kaSmIra", - "sAlva", - "kuru", - "raNku", - "aRu", - "KaRqa", - "dvIpa", - "anUpa", - "ajavAha", - "vijApakaH", - "kulUna", -]; - -/// For 4.2.138. -pub const GAHA_ADI: &[&str] = &[ - "gaha", - "antaHsTa", - "sama", - "vizama", - "maDya", - "maDyama", - "uttama", - "aNga", - "vaNga", - "magaDa", - "pUrvapkza", - "aparapakza", - "aDamaSAKa", - "uttamaSAKa", - "samAnaSAKa", - "ekagrAma", - "ekavfkza", - "ekapalASa", - "ezvagra", - "izvanI", - "avasyandI", - "kAmaprasTa", - "KAqAyani", - "kAveraRi", - "SONgi", - "Asuri", - "AhiMsi", - "Amitri", - "vyAqi", - "vEdaji", - "BOji", - "AQyaSvi", - "AnfSaMsi", - "sOvi", - "pAraki", - "agniSarman", - "devaSarman", - "SrOti", - "Arawaki", - "vAlmIki", - "kzemavfdDin", - "uttara", - "antara", - // TODO: remainder - "jana", - "para", - "deva", - "veRukA", -]; - -/// For 4.3.16. -pub const SANDHIVELA_ADI: &[&str] = &[]; - -/// For 4.3.54. -pub const DIG_ADI: &[&str] = &[ - "diS", "varga", "pUga", "gaRa", "pakza", "DAyyA", "mitra", "meDA", "antara", "paTin", "rahas", - "alIka", "uKA", "sAkzin", "Adi", "anta", "muKa", "jaGna", "meGa", "yUTa", "udaka", "nyAya", - "vaMSa", "anuvaMSa", "viSa", "kAla", "ap", "AkASa", "digAdiH", -]; - -/// For 4.3.76. -pub const SHUNDIKA_ADI: &[&str] = &[ - "SuRqika", "kfkaRa", "sTaRqila", "udapAna", "upala", "tIrTa", "BUmi", "tfRa", "parRa", -]; - -/// For 4.3.92. -pub const SHANDIKA_ADI: &[&str] = &[ - "SaRqika", - "sarvasena", - "sarvakeSa", - "Saka", - "sawa", - "raka", - "SaNKa", - "boDa", -]; - -/// For 4.3.93. -pub const SINDHU_ADI: &[&str] = &[ - "sinDu", "varRu", "ganDAra", "maDumat", "kamboja", "kaSmIra", "sAlva", "kizkinDA", "gadikA", - "urasa", "darat", -]; - -/// For 4.3.93. -pub const TAKSHASHILA_ADI: &[&str] = &[ - "takzaSilA", - "vatsodDaraRa", - "kOmedura", - "kaRqavAraRa", - "grAmaRI", - "sarAlaka", - "kaMsa", - "kinnara", - "saMkucita", - "siMhakozWa", - "karRakozWa", - "barbara", - "avasAna", -]; - -/// For 4.3.131. -pub const RAIVATIKA_ADI: &[&str] = &[ - "rEvatika", - "svApiSi", - "kzEmavfdDi", - "gOragrIvi", - "Odameyi", - "OdavAhi", - "bEjavApi", -]; - -/// For 4.4.10. -pub const PARPA_ADI: &[&str] = &[ - "parpa", "aSva", "aSvatTa", "raTa", "jAla", "nyAsa", "vyAla", "pAda", "paYca", "padika", -]; - -/// For 4.3.118. -pub const KULALA_ADI: &[&str] = &[ - "kulAla", - "varuqa", - "caRqAla", - "nizAda", - "karmAra", - "senA", - "siraGra", - "sendriya", - "devarAja", - "parizat", - "vaDU", - "ruru", - "Druva", - "rudra", - "anaquH", - "brahman", - "kumBakAra", - "SvapAka", -]; - -/// For 4.3.164. -pub const PLAKSHA_ADI: &[&str] = &[ - "plakza", "nyagroDa", "aSvatTa", "iNgudI", "Sigru", "kakarnDu", "vuhatI", -]; - -/// For 4.4.12. -pub const VETANA_ADI: &[&str] = &[ - "vetana", - "vAha", - "arDavAha", - "DanurdaRqa", - "jAla", - "vesa", - "upavesa", - "prezana", - "upasti", - "suKa", - "SayyA", - "Sakti", - "upanizad", - "upaveza", - "sraj", - "pAda", - "upasTAna", -]; - -/// For 4.4.19. -pub const AKSHADYUTA_ADI: &[&str] = &[ - "akzadyUta", - "jAnuprahfta", - "jaNGAprahfta", - "pAdasvedana", - "kaRwakamardana", - "gatAgata", - "yAtopayAta", - "anugata", -]; - -pub const CHATRA_ADI: &[&str] = &[ - "Catra", "buBukzA", "SikzA", "puroha", "sTA", "curA", "upasTAna", "fzi", "karman", "viSvaDA", - "tapas", "satya", "anfta", "SibikA", -]; - -/// For 5.1.122. -pub const PRTHU_ADI: &[&str] = &[ - "pfTu", "mfdu", "mahat", "pawu", "tanu", "laGu", "bahu", "sADu", "veRu", "ASu", "bahula", - "guru", "daRqa", "uru", "KaRqa", "caRqa", "bAla", "akiYcana", "hoqa", "pAka", "vatsa", "manda", - "svAdu", "hrasva", "dIrGa", "priya", "vfza", "fju", "kzipra", "kzupra", "kzudra", -]; - -/// For 5.3.101. -pub const SHAKHA_ADI: &[&str] = &[ - "SAKA", "muKa", "jaGana", "SfNga", "meGa", "caraRa", "skanDa", "Siras", "uras", "agra", - "Sarana", -]; - -/// For 5.3.107. -pub const SHARKARA_ADI: &[&str] = &[ - "SarkarA", - "kapAlikA", - "pizwika", - "puRqarIka", - "Satapatra", - "goloman", - "gopucCa", - "narAcI ", - "nakulA", - "sikatA", -]; - -/// For 5.3.108. -pub const ANGULI_ADI: &[&str] = &[ - "aNguli", "Baruja", "baBru", "valgu", "maRqara", "maRqala", "Sazkula", "kapi", "udaSvit", - "goRI", "uras", "SiKara", "kuliSa", -]; - -/// For 5.3.117. (part 1) -pub const PARSHU_ADI: &[&str] = &[ - "parSu", - "asura", - "rakzas", - "bAhlIka", - "vayas", - "marut", - "daSArha", - "piSAca", - "viSAla", - "aSani", - "kArzApaRa", - "satvat", - "vasu", - "parSvAdiH", -]; - -/// For 5.3.116. -pub const DAMANI_ADI: &[&str] = &[ - "dAmanI", - "Olapi", - "AkidantI", - "kAkaranti", - "kAkadanti", - "Satruntapi", - "sArvaseni", - "bindu", - "mOYjAyana", - "ulaBa", - "sAvitrIputra", -]; - -/// For 5.3.117. (part 2) -pub const YAUDHEYA_ADI: &[&str] = &[ - "yODeya", "kOSeya", "krOSeya", "SOkreya", "SOBreya", "DArteya", "vArteya", "jAbAleya", - "trigarta", "Barata", "uSInara", -]; - -/// For 5.4.3. -pub const STHULA_ADI: &[&str] = &[ - "sTUla", - "aRu", - "mAza", - "izu", - "kfzRa", - "yava", - "ikzu", - "tila", - "pAdya", - "kAla", - "avadAta", - "gomUtra", - "surA", - "jIrRa", - "patra", - "mUla", - "kumArIputra", - "kumAra", - "SvaSura", - "maRi", -]; diff --git a/vidyut-prakriya/src/taddhita/nan_snan_adhikara_prakarana.rs b/vidyut-prakriya/src/taddhita/nan_snan_adhikara_prakarana.rs index 56db87d..826f95a 100644 --- a/vidyut-prakriya/src/taddhita/nan_snan_adhikara_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/nan_snan_adhikara_prakarana.rs @@ -1,6 +1,6 @@ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; -use crate::taddhita::gana; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; pub fn run(tp: &mut TaddhitaPrakriya) { diff --git a/vidyut-prakriya/src/taddhita/panchami_prakarana.rs b/vidyut-prakriya/src/taddhita/panchami_prakarana.rs index c074ce7..ca60836 100644 --- a/vidyut-prakriya/src/taddhita/panchami_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/panchami_prakarana.rs @@ -1,23 +1,29 @@ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(DhanyanamBhavaneKshetre, |tp| { let prati = tp.prati(); if prati.has_text_in(&["vrIhi", "SAli"]) { + // vrEheya, ... tp.try_add("5.2.2", Qak); } else if prati.has_text_in(&["yava", "yavaka", "zazwika"]) { + // vavya, ... tp.try_add("5.2.3", yat); } else if prati.has_text_in(&["tila", "mAza", "umA", "BaNgA", "aRu"]) { + // tilya, tElIna, ... tp.optional_try_add("5.2.4", yat); } + // mOdrIna, ... tp.try_add("5.2.1", KaY); }); tp.with_context(Krta, |tp| { let prati = tp.prati(); if prati.has_text("sarvacarman") { + // sarvacarmIRa, sArvacarmIRa let code = "5.2.5"; tp.try_add(code, Ka); tp.try_add(code, KaY); @@ -27,6 +33,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(Darshana, |tp| { let prati = tp.prati(); if prati.has_text_in(&["yaTAmuKa", "sammuKa"]) { + // yaTAmuKIna, sammuKIna tp.try_add("5.2.6", Ka); } }); @@ -40,6 +47,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { "sarvapatra", "sarvapAtra", ]) { + // sarvapaTIna tp.try_add("5.2.7", Ka); } }); @@ -47,7 +55,149 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(Prapnoti, |tp| { let prati = tp.prati(); if prati.has_text("Aprapada") { + // AprapadIna tp.try_add("5.2.8", Ka); } }); + + let prati = tp.prati(); + if prati.has_text_in(&["anupada", "sarvAnna", "AyAnaya"]) { + // anupadIna + tp.try_add("5.2.9", Ka); + } + + tp.with_context(TadAnubhavati, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["parovara", "parampara", "putrapOtra"]) { + // parovarIRa, ... + tp.try_add("5.2.10", Ka); + } + }); + + tp.with_context(Gami, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["avArapAra", "atyanta", "anukAma"]) { + // avArapArIRa, ... + tp.try_add("5.2.11", Ka); + } + }); + + tp.with_context(AlamGami, |tp| { + let prati = tp.prati(); + if prati.has_text("anugu") { + // anugavIna, ... + tp.try_add("5.2.15", Ka); + } else if prati.has_text("aDvan") { + let code = "5.2.16"; + tp.try_add(code, yat); + tp.try_add(code, Ka); + } else if prati.has_text("aByamitra") { + let code = "5.2.17"; + tp.try_add(code, yat); + tp.try_add(code, Ka); + tp.try_add(code, Ca); + } + }); + + tp.with_context(BhutaPurva, |tp| { + let prati = tp.prati(); + if prati.has_text("gozWa") { + tp.try_add("5.2.18", KaY); + } + }); + + tp.with_context(EkahaGama, |tp| { + let prati = tp.prati(); + if prati.has_text("aSva") { + tp.try_add("5.2.19", KaY); + } + }); + + tp.with_context(TenaJivati, |tp| { + let prati = tp.prati(); + if prati.has_text("vrAta") { + tp.try_add("5.2.21", KaY); + } + }); + + tp.with_context(TasyaPakamula, |tp| { + let code = "5.2.24"; + tp.try_add(code, kuRap); + tp.try_add(code, jAhac); + }); + + tp.with_context(TasyaMula, |tp| { + let code = "5.2.25"; + let prati = tp.prati(); + if prati.has_text("pakza") { + tp.try_add(code, ti); + } + }); + + tp.with_context(TenaVitta, |tp| { + let code = "5.2.26"; + tp.try_add(code, cuYcup); + tp.try_add(code, caRap); + }); + + let prati = tp.prati(); + if prati.has_text_in(&["sam", "pra", "ud", "vi"]) { + if prati.has_text("vi") { + let code = "5.2.28"; + tp.try_add(code, SAlac); + tp.try_add(code, SaNkawac); + } + tp.try_add("5.2.29", kawac); + } else if prati.has_text("ava") { + let code = "5.2.30"; + tp.try_add(code, kawac); + tp.try_add(code, kuwArac); + } else if prati.has_text("ava") { + let code = "5.2.31"; + tp.try_add(code, wIwac); + tp.try_add(code, nAwac); + tp.try_add(code, Brawac); + } else if prati.has_text("ni") { + let code = "5.2.32"; + tp.try_add(code, biqac); + tp.try_add(code, birIsac); + + let code = "5.2.33"; + let i_prati = tp.i_prati; + tp.try_add_with(code, inac, |p| p.set(i_prati, |t| t.set_text("cik"))); + tp.try_add_with(code, piwac, |p| p.set(i_prati, |t| t.set_text("ci"))); + } else if prati.has_text_in(&["upa", "aDi"]) { + tp.try_add("5.2.34", tyakan); + } else if prati.has_text("karman") { + tp.try_add("5.2.35", aWac); + } else if prati.has_text_in(gana::TARAKA_ADI) { + tp.try_add("5.2.36", itac); + } + + tp.with_context(Pramana, |tp| { + let prati = tp.prati(); + + if prati.has_text_in(&["puruza", "hastin"]) { + let code = "5.2.38"; + tp.try_add(code, dvayasac); + tp.try_add(code, daGnac); + tp.try_add(code, mAtrac); + tp.try_add(code, aR); + } else { + let code = "5.2.37"; + tp.try_add(code, dvayasac); + tp.try_add(code, daGnac); + tp.try_add(code, mAtrac); + } + }); + + tp.with_context(Parimana, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["yad", "tad", "etad"]) { + tp.try_add("5.2.39", vatup); + } else if prati.has_text_in(&["kim", "idam"]) { + let i_prati = tp.i_prati; + tp.try_add_with("5.2.40", vatup, |p| p.set(i_prati + 1, |t| t.set_adi("G"))); + } + }); } diff --git a/vidyut-prakriya/src/taddhita/pragdishiya.rs b/vidyut-prakriya/src/taddhita/pragdishiya.rs index 70c8971..40e9e9b 100644 --- a/vidyut-prakriya/src/taddhita/pragdishiya.rs +++ b/vidyut-prakriya/src/taddhita/pragdishiya.rs @@ -4,8 +4,8 @@ Implements the taddhita rules in the "prAg diSo viBaktiH" section of pada 5.3. (5.3.1 - 5.3.26) */ use crate::args::Taddhita; +use crate::core::Tag as T; use crate::taddhita::utils::TaddhitaPrakriya; -use crate::tag::Tag as T; pub fn run(tp: &mut TaddhitaPrakriya) { let i_prati = tp.i_prati; @@ -14,9 +14,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let add = |rule, tp: &mut TaddhitaPrakriya, taddhita| { tp.try_add_with(rule, taddhita, |p| { p.set(i_prati + 1, |t| { - if taddhita != Taddhita::at { - t.add_tag(T::Vibhakti); - } + t.add_tag(T::Vibhakti); }) }); }; @@ -92,7 +90,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } else if prati.has_u("etad") { tp.p.run_at("5.3.5", i_prati, |t| t.set_text("a")); } else if prati.has_u("sarva") && t.has_adi('d') { - tp.p.run_optional_at("5.3.6", i_prati, |t| t.set_text("sa")); + tp.p.optional_run_at("5.3.6", i_prati, |t| t.set_text("sa")); } } } diff --git a/vidyut-prakriya/src/taddhita/pragdivyatiya.rs b/vidyut-prakriya/src/taddhita/pragdivyatiya.rs index 7e7e80e..e5386cd 100644 --- a/vidyut-prakriya/src/taddhita/pragdivyatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragdivyatiya.rs @@ -6,12 +6,12 @@ Implements the taddhita rules in the "prAg dIvyato 'R" section of pada 4.1. use crate::args::Taddhita; use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; +use crate::core::operators as op; +use crate::core::Tag as T; +use crate::ganapatha as gana; use crate::it_samjna; -use crate::operators as op; use crate::sounds::{s, Set}; -use crate::taddhita::gana; use crate::taddhita::utils::TaddhitaPrakriya; -use crate::tag::Tag as T; use lazy_static::lazy_static; lazy_static! { @@ -310,7 +310,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let putra_anta = prati.ends_with("putra"); let added = tp.optional_try_add("4.1.157", PiY); if added && putra_anta { - tp.p.run_optional_at("4.1.159", i_prati, |t| t.text += "k"); + tp.p.optional_run_at("4.1.159", i_prati, |t| t.text += "k"); } } } @@ -355,7 +355,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { // Atreya, ... // TODO: an-iY tp.try_add("4.1.122", Qak); - } else if prati.has_tag(T::Stri) { + } else if prati.has_tag(T::StriNyap) { // General case. if is_dvi_ac { // dAtteya, ... @@ -370,7 +370,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let prati = tp.prati(); if tp.had_match { // Do nothing if any other pratyaya above matches. - } else if prati.has_suffix_in(gana::BAHU_ADI) { + } else if prati.has_suffix_in(gana::BAAHU_ADI) { // HACK: check suffix instead of uttarapada tp.try_add("4.1.96", iY); } else if prati.has_text("suDAtf") { diff --git a/vidyut-prakriya/src/taddhita/pragghitiya.rs b/vidyut-prakriya/src/taddhita/pragghitiya.rs index 45e42c5..88a7a9c 100644 --- a/vidyut-prakriya/src/taddhita/pragghitiya.rs +++ b/vidyut-prakriya/src/taddhita/pragghitiya.rs @@ -5,7 +5,9 @@ Implements the taddhita rules in the "prAg GitAd yat" section of pada 4.4. */ use crate::args::Taddhita; use crate::args::TaddhitaArtha::*; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; +use crate::Rule; pub fn run(tp: &mut TaddhitaPrakriya) { use Taddhita as P; @@ -33,19 +35,151 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.try_add("4.4.83", P::yat); }); - // [good first issue] - // - // Try implementing rule 4.4.84 and rule 4.4.85! - // - // - rule: add `P::yat` after the pratipadikas "Dana" or "gaRa." - // - meaning context: `Labdha`. You will need to add `Labdha` as a new entry to `Artha`. - // - test examples: `Danya` and `gaRya`. - // - You will need to add these to `pada_4_4.rs`. - // - Look at other tests in that file for help on the test syntax. - // - Remember to change the second argument for `assert_has_artha_taddhita` to `Labdha`. + tp.with_context(Labdha, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["Dana", "gaRa"]) { + // Danya, gaRya + tp.try_add("4.4.84", P::yat); + } else if prati.has_text("anna") { + // Anna + tp.try_add("4.4.85", P::Ra); + } + }); + + tp.with_context(Gata, |tp| { + let prati = tp.prati(); + if prati.has_text("vaSa") { + // vaSya + tp.try_add("4.4.86", P::yat); + } + }); + + tp.with_context(AsminDrshyam, |tp| { + let prati = tp.prati(); + if prati.has_text("pada") { + // padya + tp.try_add("4.4.87", P::yat); + } + }); + + tp.with_context(AsyaAbarhi, |tp| { + let prati = tp.prati(); + if prati.has_text("mUla") { + // mUlya + tp.try_add("4.4.88", P::yat); + } + }); + + tp.with_context(Samyukta, |tp| { + let prati = tp.prati(); + if prati.has_text("gfhapati") { + // gArhapatya + tp.try_add("4.4.90", P::Yya); + } + }); let prati = tp.prati(); if prati.has_text_in(&["nO", "vayas", "Darma", "viza", "mUla", "sItA", "tulA"]) { tp.try_add("4.4.91", P::yat); } + + tp.with_context(Anapeta, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["Darma", "paTin", "arTa", "nyAya"]) { + // gArhapatya + tp.try_add("4.4.92", P::yat); + } + }); + + tp.with_context(Nirmita, |tp| { + let prati = tp.prati(); + if prati.has_text("Candas") { + // Candasya + tp.try_add("4.4.93", P::yat); + } else if prati.has_text("uras") { + // urasya, Orasa + tp.optional_try_add("4.4.94.a", P::yat); + tp.try_add("4.4.94.b", P::aR); + } + }); + + tp.with_context(Priya, |tp| { + let prati = tp.prati(); + if prati.has_text("hfdaya") { + // hfdya + tp.try_add("4.4.95", P::yat); + } + }); + + let prati = tp.prati(); + if prati.has_text_in(&["mata", "jana", "hala"]) { + tp.try_add("4.4.97", P::yat); + } + + tp.with_context(TatraSadhu, |tp| { + let prati = tp.prati(); + if prati.has_text_in(gana::PRATIJANA_ADI) { + // prAtijanIna, ... + tp.try_add("4.4.99", P::KaY); + } else if prati.has_text("Bakta") { + // BAkta + tp.try_add("4.4.100", P::Ra); + } else if prati.has_text("parizad") { + // pArizada + tp.try_add(Rule::Kashika("4.4.101"), P::Ra); + // pArizadya + tp.try_add("4.4.101", P::Rya); + } else if prati.has_text_in(gana::KATHA_ADI) { + // kATika, ... + tp.try_add("4.4.102", P::Wak); + } else if prati.has_text_in(gana::GUDA_ADI) { + // gOqika, ... + tp.try_add("4.4.103", P::WaY); + } else if prati.has_text_in(&["paTi", "atiTi", "vasati", "svapati"]) { + // pATeya, ... + tp.try_add("4.4.104", P::QaY); + } else if prati.has_text("saBA") { + if tp.p.is_chandasi() { + // saBeya + tp.try_add("4.4.106", P::Qa); + } else { + // saBya + tp.try_add("4.4.105", P::ya); + } + } else { + // sAmanya, ... + tp.try_add("4.4.98", P::yat); + } + }); + + tp.with_context(TatraVasi, |tp| { + let prati = tp.prati(); + if prati.has_text("samAnatIrTa") { + // satIrTya + tp.try_add("4.4.107", P::yat); + } + }); + + tp.with_context(TatraBhava, |tp| { + let prati = tp.prati(); + if tp.p.is_chandasi() { + if prati.has_text_in(&["pATas", "nadI"]) { + // pATya, ... + tp.try_add("4.4.111", P::qyaR); + } else if prati.has_text_in(&["veSanta", "himavat"]) { + // vESanta, ... + tp.try_add("4.4.112", P::aR); + } else if prati.has_text("tugra") { + // tugriya + tp.try_add("4.4.115", P::Gan); + } else if prati.has_text("agra") { + tp.try_add("4.4.116", P::yat); + let code = "4.4.117"; + tp.try_add(code, P::Ga); + tp.try_add(code, P::Ca); + } else if prati.has_text_in(&["samudra", "aBra"]) { + tp.try_add("4.4.118", P::Ga); + } + } + }); } diff --git a/vidyut-prakriya/src/taddhita/pragiviya.rs b/vidyut-prakriya/src/taddhita/pragiviya.rs index 8ed80d9..2f020e0 100644 --- a/vidyut-prakriya/src/taddhita/pragiviya.rs +++ b/vidyut-prakriya/src/taddhita/pragiviya.rs @@ -6,8 +6,9 @@ immediately before it. */ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; +use crate::core::operators as op; +use crate::core::Tag; use crate::taddhita::utils::TaddhitaPrakriya; -use crate::tag::Tag; fn try_base_cases(tp: &mut TaddhitaPrakriya, _rule: &'static str) { let prati = tp.prati(); @@ -19,7 +20,7 @@ fn try_base_cases(tp: &mut TaddhitaPrakriya, _rule: &'static str) { } } -pub fn run(tp: &mut TaddhitaPrakriya) { +pub fn run(tp: &mut TaddhitaPrakriya) -> Option<()> { tp.with_context(DigDeshaKala, |tp| { let prati = tp.prati(); if prati.has_text_in(&["dakziRa", "uttara"]) { @@ -37,6 +38,32 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.try_add("5.3.42", DA); } + let last = tp.p.terms().last().expect("present"); + if last.is_taddhita() && last.has_u("DA") { + let i_last = tp.p.terms().len() - 1; + let prati = tp.prati(); + if prati.has_text("eka") { + op::optional_adesha("5.3.44", tp.p, i_last, "Dyamu~Y"); + } else if prati.has_text_in(&["dvi", "tri"]) { + let done = op::optional_adesha("5.3.45", tp.p, i_last, "Damu~Y"); + if !done { + op::optional_adesha("5.3.46", tp.p, i_last, "eDAc"); + } + } + } + + tp.try_add("5.3.47", pASap); + let prati = tp.prati(); + if prati.has_text("eka") { + tp.try_add("5.3.52", Akinic); + } + + tp.try_add("5.3.53", caraw); + + let code = "5.3.54"; + tp.try_add(code, caraw); + tp.try_add(code, rUpya); + let code = "5.3.55"; tp.try_add(code, tamap); tp.try_add(code, izWan); @@ -45,6 +72,33 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.try_add(code, tarap); tp.try_add(code, Iyasun); + if tp.p.terms().last()?.has_u_in(&["Iyasu~n", "izWan"]) { + let prati = tp.prati(); + if prati.has_text("praSasya") && tp.p.terms().last()?.has_u_in(&["Iyasu~n", "izWan"]) { + // Sreyas, SrezWa + let done = + tp.p.optional_run_at("5.3.60", tp.i_prati, |t| t.set_text("Sra")); + if !done { + // jyAyas, jyezWa + tp.p.run_at("5.3.61", tp.i_prati, |t| t.set_text("jya")); + } + } else if prati.has_text("vfdDa") { + // jyAyas, jyezWa + // This is optional so that 6.4.157 can produce varzIyas and varzizWa. + tp.p.optional_run_at("5.3.62", tp.i_prati, |t| t.set_text("jya")); + } else if prati.has_text_in(&["antika", "bAQa"]) { + let sub = if prati.has_text("antika") { + "neda" + } else { + "sADa" + }; + tp.p.run_at("5.3.63", tp.i_prati, |t| t.set_text(sub)); + } else if prati.has_text_in(&["yuvan", "alpa"]) { + // kanIyas, kanizWa + tp.p.optional_run_at("5.3.64", tp.i_prati, |t| t.set_text("kan")); + } + } + // vaiyAkaraRarUpa tp.try_add("5.3.66", rUpap); @@ -54,6 +108,14 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.try_add(code, deSya); tp.try_add(code, deSIyar); + tp.try_prepend("5.3.68", bahuc); + + tp.try_add("5.3.69", jAtIyar); + + // -------------------- + // 5.3.70 prAg ivAt kaH + // -------------------- + tp.with_context(Ajnate, |tp| { try_base_cases(tp, "5.3.73"); }); @@ -97,4 +159,6 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(Avakshepane, |tp| { tp.try_add("5.3.95", kan); }); + + None } diff --git a/vidyut-prakriya/src/taddhita/pragvahatiya.rs b/vidyut-prakriya/src/taddhita/pragvahatiya.rs index 9458331..5405432 100644 --- a/vidyut-prakriya/src/taddhita/pragvahatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragvahatiya.rs @@ -5,9 +5,9 @@ Implements the taddhita rules in the "prAg vahatez Wak" section of pada 4.4. */ use crate::args::Taddhita; use crate::args::TaddhitaArtha::*; -use crate::operators as op; -use crate::prakriya::Rule; -use crate::taddhita::gana; +use crate::core::operators as op; +use crate::core::Rule; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; pub fn run(tp: &mut TaddhitaPrakriya) { diff --git a/vidyut-prakriya/src/taddhita/pragvatiya.rs b/vidyut-prakriya/src/taddhita/pragvatiya.rs index 850843b..bfbe15d 100644 --- a/vidyut-prakriya/src/taddhita/pragvatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragvatiya.rs @@ -5,8 +5,15 @@ Implements the taddhita rules in the "prAg vatez Wan" section of pada 5.1. */ use crate::args::Taddhita; use crate::args::TaddhitaArtha::*; +use crate::core::Tag as T; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; -use crate::tag::Tag as T; + +fn try_base_cases(tp: &mut TaddhitaPrakriya, _code: &'static str) { + use Taddhita as P; + + tp.try_add("5.1.18", P::WaY); +} pub fn run(tp: &mut TaddhitaPrakriya) { use Taddhita as P; @@ -27,6 +34,61 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let code = "5.1.36"; tp.try_add(code, P::yat); tp.try_add(code, P::aR); + } else { + try_base_cases(tp, "5.1.37"); + } + }); + + tp.with_context(TadArhati, |tp| { + let prati = tp.prati(); + if prati.has_text_in(gana::DANDA_ADI) { + tp.try_add("5.1.66", P::yat); + } else if prati.has_text("pAtra") { + let code = "5.1.68"; + tp.try_add(code, P::yat); + tp.try_add(code, P::Gan); + } else if prati.has_text_in(&["kaqaNgara", "dakzirA"]) { + let code = "5.1.69"; + tp.try_add(code, P::yat); + tp.try_add(code, P::Ca); + } else if prati.has_text("sTAlIbila") { + let code = "5.1.70"; + tp.try_add(code, P::yat); + tp.try_add(code, P::Ca); + } else if prati.has_text_in(&["yajYa", "ftvij"]) { + let t = if prati.has_text("yajYa") { + P::Ga + } else { + P::KaY + }; + tp.try_add("5.1.71", t); + } else { + try_base_cases(tp, "5.1.63"); + } + }); + + tp.with_context(TadVartayati, |tp| { + let prati = tp.prati(); + if prati.has_text_in(&["pArAyaRa", "turAyaRa", "cAndrAyaRa"]) { + try_base_cases(tp, "5.1.72"); + } + }); + + tp.with_context(Apanna, |tp| { + let prati = tp.prati(); + if prati.has_text("saMSaya") { + try_base_cases(tp, "5.1.73"); + } + }); + + tp.with_context(Gacchati, |tp| { + let i_prati = tp.i_prati; + let prati = tp.prati(); + if prati.has_text("yojana") { + try_base_cases(tp, "5.1.74"); + } else if prati.has_text("paTin") { + tp.try_add("5.1.75", P::zkan); + tp.try_add_with("5.1.76", P::Ra, |p| p.set(i_prati, |t| t.set_text("panTa"))); } }); diff --git a/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs b/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs index 68e6f4e..cd9425d 100644 --- a/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs @@ -3,12 +3,126 @@ Implements the taddhita rules in the "samAsAntAH" section of pada 5.4. (5.4.68 - 5.4.160) */ +use crate::args::Taddhita; use crate::args::Taddhita::*; -use crate::taddhita::utils::TaddhitaPrakriya; +use crate::core::Tag as T; +use crate::core::{Prakriya, Rule}; +use crate::ganapatha as gana; +use crate::it_samjna; +use crate::sounds::{s, Set}; +use lazy_static::lazy_static; -pub fn run(tp: &mut TaddhitaPrakriya) { - let prati = tp.prati(); - if prati.has_text_in(&["brahmavarcas", "hastivarcas"]) { - tp.try_add("5.4.78", ac); +lazy_static! { + static ref CU: Set = s("cu~"); +} + +impl Prakriya { + fn is_bahuvrihi(&self) -> bool { + self.has_tag(T::Bahuvrihi) + } + + fn is_tatpurusha(&self) -> bool { + self.has_tag(T::Tatpurusha) + } + + fn is_avyayibhava(&self) -> bool { + self.has_tag(T::Avyayibhava) + } + + fn is_samahara_dvandva(&self) -> bool { + self.has_tag(T::Dvandva) && self.has_tag(T::Samahara) + } +} + +fn add(rule: impl Into, p: &mut Prakriya, taddhita: Taddhita) -> bool { + let rule = rule.into(); + + p.run(rule, |p| { + p.push(taddhita.to_term()); + }); + let i_last = p.terms().len() - 1; + it_samjna::run(p, i_last).expect("should never fail"); + + true +} + +pub fn run(p: &mut Prakriya) -> Option<()> { + let i_uttara = p.find_last_where(|t| t.is_pratipadika_or_nyap())?; + let i_purva = p.find_prev_where(i_uttara, |t| t.is_pratipadika_or_nyap())?; + + let purva = p.get(i_purva)?; + let uttara = p.get(i_uttara)?; + + if uttara.has_text("varcas") { + if purva.has_text_in(&["brahman", "hastin"]) { + // brahmavarcasa, ... + add("5.4.78", p, ac); + } else if purva.has_text_in(&["pallya", "rAjan"]) { + // pallyavarcasa, ... + add("5.4.78.v1", p, ac); + } + } else if purva.has_text_in(&["ava", "sam", "anDa"]) && uttara.has_text("tamas") { + // avatamasam, ... + add("5.4.79", p, ac); + } else if purva.has_text("Svas") && uttara.has_text_in(&["vasIya", "Sreyas"]) { + // SvovasIyam, ... + add("5.4.80", p, ac); + } else if purva.has_text_in(&["anu", "ava", "tapta"]) && uttara.has_text("rahas") { + // anurahasam, ... + add("5.4.81", p, ac); + } else if p.is_tatpurusha() { + if uttara.has_text_in(&["rAjan", "ahan", "saKi"]) { + // mahArAja, ... + add("5.4.91", p, wac); + } else if purva.has_text_in(&["grAma", "kOwa"]) && uttara.has_text("takzan") { + // grAmatakza, ... + add("5.4.95", p, wac); + } else if purva.has_text("ati") && uttara.has_text("Svan") { + // atiSva + add("5.4.96", p, wac); + } else if uttara.has_text("sakTi") { + // Ignore "uttama-mfga-pUrva" because by "ca" we can accept most words here. + add("5.4.98", p, wac); + } else if purva.has_text("arDa") && uttara.has_text("nO") { + // arDanAvam + add("5.4.100", p, wac); + } + } else if p.is_samahara_dvandva() { + let antya = uttara.antya()?; + if CU.contains(antya) || matches!(antya, 'd' | 'z' | 'h') { + add("5.4.106", p, wac); + } + } else if p.is_avyayibhava() { + if uttara.ends_with("an") { + // uparAjam, ... + add("5.4.108", p, wac); + } + } else if p.is_bahuvrihi() { + if uttara.has_text("Danus") { + // SArNgaDanvA, ... + p.run_at("5.4.132", i_uttara, |t| t.set_antya("an")); + } else if uttara.has_text("jAyA") { + // yuvajAni, ... + p.run_at("5.4.134", i_uttara, |t| t.set_antya("ni")); + } else if purva.has_text_in(&["ud", "pUti", "su", "suraBi"]) && uttara.has_text("ganDa") { + // udganDi, ... + p.run_at("5.4.135", i_uttara, |t| t.set_antya("i")); + } else if uttara.has_text("kAkuda") { + if purva.has_text_in(&["ud", "vi"]) { + // utkAkut, ... + p.run_at("5.4.148", i_uttara, |t| t.set_antya("")); + } else if purva.has_text("pUrRa") { + // pUrRakAkut, pUrRakAkuda + p.optional_run_at("5.4.149", i_uttara, |t| t.set_antya("")); + } + } else if purva.has_text_in(&["su", "dur", "dus"]) && uttara.has_text("hfdaya") { + // suhfd, durhfd + p.optional_run_at("5.4.150", i_uttara, |t| t.set_text("hfd")); + } else if uttara.has_text_in(gana::URAH_PRABHRTI) && uttara.is_ekavacana() { + // vyUQoraska, ... + add("5.4.151", p, kap); + } } + + Some(()) } diff --git a/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs b/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs index df0f710..3a13c0f 100644 --- a/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs @@ -1,33 +1,10 @@ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; -use crate::taddhita::gana; +use crate::core::Tag as T; +use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; -use crate::tag::Tag as T; pub fn run(tp: &mut TaddhitaPrakriya) { - // TODO: others - const YAVA_ADI: &[&str] = &[ - "yAva", "maRi", "asTi", "caRqa", "pIta", "stamBa", "ftu", "paSu", "aRu", "putra", "snAta", - "SUnya", "dAna", "tanu", "jYAta", - ]; - const VINAYA_ADI: &[&str] = &[ - "vinaya", - "samaya", - "upAya", - "saNgati", - "kaTaYcit", - "akasmAt", - "samayAcAra", - "upacAra", - "samAcAra", - "vyavahAra", - "sampradAna", - "samutkarza", - "samUha", - "viSeza", - "atyaya", - ]; - let i_prati = tp.i_prati; tp.with_context(IvePratikrtau, |tp| { @@ -137,18 +114,23 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let prati = tp.prati(); if prati.has_text("deva") { + // devatA tp.try_add("5.4.27", tal); } else if prati.has_text("avi") { + // avika tp.try_add("5.4.28", ka); - } else if prati.has_text_in(YAVA_ADI) { + } else if prati.has_text_in(gana::YAVA_ADI) { + // yAvaka tp.try_add("5.4.29", kan); } else if prati.has_text("lohita") { + // lohitaka tp.try_add("5.4.30", kan); tp.try_add("5.4.31", kan); tp.try_add("5.4.32", kan); } else if prati.has_text("kAla") { + // kAlaka tp.try_add("5.4.33", kan); - } else if prati.has_text_in(VINAYA_ADI) { + } else if prati.has_text_in(gana::VINAYA_ADI) { tp.try_add_with("5.4.34", Wak, |p| { p.set(i_prati, |t| { if t.has_text("upAya") { @@ -157,6 +139,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { }); }); } else if prati.has_text("vAc") { + // vAcika tp.try_add("5.4.35", Wak); } else if prati.has_text("mfd") { tp.try_add("5.4.39", tikan); diff --git a/vidyut-prakriya/src/taddhita/utils.rs b/vidyut-prakriya/src/taddhita/utils.rs index 7991eb0..4c6cbeb 100644 --- a/vidyut-prakriya/src/taddhita/utils.rs +++ b/vidyut-prakriya/src/taddhita/utils.rs @@ -1,8 +1,8 @@ use crate::args::{Artha, Taddhita, TaddhitaArtha}; +use crate::core::Tag as T; +use crate::core::Term; +use crate::core::{Prakriya, Rule}; use crate::it_samjna; -use crate::prakriya::{Prakriya, Rule}; -use crate::tag::Tag as T; -use crate::term::Term; impl Taddhita { /// Converts this taddhita to a term that can be added to the prakriya. @@ -20,6 +20,7 @@ impl Taddhita { /// - remembers which `taddhita` pratyaya the caller wishes to add. /// - records whether a `taddhita` pratyaya has been added or not, which simplifies the control /// flow for optional rules. +#[derive(Debug)] pub struct TaddhitaPrakriya<'a> { /// The underlying prakriya. pub p: &'a mut Prakriya, @@ -103,9 +104,13 @@ impl<'a> TaddhitaPrakriya<'a> { } let rule = rule.into(); - let prati = &self.prati().text; if cfg!(debug_assertions) { - println!("Try: {rule:?} {prati} + {taddhita:?}"); + self.p.debug(format!( + "Try {}: {} + {:?}", + rule.code(), + &self.prati().text, + taddhita, + )); } self.had_match = true; @@ -127,10 +132,27 @@ impl<'a> TaddhitaPrakriya<'a> { } } + /// Prepends the given `taddhita` pratyaya. + /// + /// This method is used only for bahuc-pratyaya. We keep this method here for readability. + pub fn try_prepend(&mut self, rule: impl Into, taddhita: Taddhita) -> bool { + if taddhita == self.taddhita && !self.has_taddhita { + self.p.run(rule, |p| { + p.terms_mut().insert(0, taddhita.to_term()); + }); + + it_samjna::run(self.p, 0).expect("should never fail"); + self.has_taddhita = true; + true + } else { + false + } + } + /// If there's a match, optionally adds the given `taddhita` pratyaya. /// /// This method does nothing if a pratyaya has already been added. - pub fn optional_try_add(&mut self, rule: &'static str, taddhita: Taddhita) -> bool { + pub fn optional_try_add(&mut self, rule: impl Into + Copy, taddhita: Taddhita) -> bool { self.optional_try_add_with(rule, taddhita, |_| {}) } diff --git a/vidyut-prakriya/src/tin_pratyaya.rs b/vidyut-prakriya/src/tin_pratyaya.rs index 744b165..4a89895 100644 --- a/vidyut-prakriya/src/tin_pratyaya.rs +++ b/vidyut-prakriya/src/tin_pratyaya.rs @@ -14,12 +14,10 @@ //! All of these rules are found at the end of section 3.4 of the Ashtadhyayi. use crate::args::{Gana, Lakara, Purusha, Vacana}; -use crate::errors::*; +use crate::core::errors::Result; +use crate::core::operators as op; +use crate::core::{Code, Prakriya, Tag as T, Term}; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::{Code, Prakriya}; -use crate::tag::Tag as T; -use crate::term::Term; const TIN_PARA: &[&str] = &["tip", "tas", "Ji", "sip", "Tas", "Ta", "mip", "vas", "mas"]; const NAL_PARA: &[&str] = &["Ral", "atus", "us", "Tal", "aTus", "a", "Ral", "va", "ma"]; @@ -151,7 +149,7 @@ fn maybe_do_lot_only_siddhi(p: &mut Prakriya, i: usize) -> Option<()> { }); if p.has_tag(T::Chandasi) { - p.run_optional_at("3.4.88", i, op::add_tag(T::Pit)); + p.optional_run_at("3.4.88", i, op::add_tag(T::Pit)); } } else if tin.ends_with("mi") { // BavAni @@ -203,10 +201,10 @@ fn maybe_do_lin_siddhi(p: &mut Prakriya, i_tin: usize, la: Lakara) -> Result<()> if la == Lakara::AshirLin { // Add kit to the pratyaya, not the Agama. - p.run_at("3.4.104", i, op::add_tag(T::kit)); + p.add_tag_at("3.4.104", i, T::kit); } else { // Add Nit to the pratyaya, not the Agama. - p.run_at("3.4.103", i, op::add_tag(T::Nit)); + p.add_tag_at("3.4.103", i, T::Nit); } it_samjna::run(p, i - 1)?; } else { @@ -240,7 +238,7 @@ fn yatha(rule: Code, p: &mut Prakriya, i: usize, old: &[&str], new: &[&str]) { } fn yatha_optional(rule: Code, p: &mut Prakriya, i: usize, old: &[&str], new: &[&str]) { - if p.run_optional(rule, |p| op::upadesha_yatha(p, i, old, new)) { + if p.optional_run(rule, |p| op::upadesha_yatha(p, i, old, new)) { it_samjna::run(p, i).ok(); } } @@ -302,7 +300,7 @@ fn siddhi(p: &mut Prakriya, la: Lakara) -> Option<()> { if dhatu.has_u("vida~") && tin.has_u_in(TIN_PARA) { yatha_optional("3.4.83", p, i, TIN_PARA, NAL_PARA); } else if dhatu.has_text("brU") && tin.has_u_in(&TIN_PARA[..5]) { - p.run_optional("3.4.84", |p| { + p.optional_run("3.4.84", |p| { p.set(i_dhatu, |t| t.set_text("Ah")); op::upadesha_yatha(p, i, TIN_PARA, NAL_PARA); it_samjna::run(p, i).ok(); diff --git a/vidyut-prakriya/src/tripadi.rs b/vidyut-prakriya/src/tripadi.rs index e3315c8..392cffb 100644 --- a/vidyut-prakriya/src/tripadi.rs +++ b/vidyut-prakriya/src/tripadi.rs @@ -14,7 +14,7 @@ the tripādi applies rules in order and will (generally) never "go back" to app mod pada_8_2; mod pada_8_3; mod pada_8_4; -use crate::prakriya::Prakriya; +use crate::core::Prakriya; /// Runs all rules of the tripadi. pub fn run(p: &mut Prakriya) { diff --git a/vidyut-prakriya/src/tripadi/pada_8_2.rs b/vidyut-prakriya/src/tripadi/pada_8_2.rs index 9f9dd2d..2c14634 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_2.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_2.rs @@ -1,13 +1,13 @@ use crate::args::Gana; -use crate::char_view::{get_at, get_term_and_offset_indices, xyz, CharPrakriya}; +use crate::core::char_view::{get_at, get_term_and_offset_indices, xyz, CharPrakriya}; +use crate::core::iterators::xy_rule; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::dhatu_gana; -use crate::iterators::xy_rule; -use crate::operators as op; -use crate::prakriya::Prakriya; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use compact_str::CompactString; use lazy_static::lazy_static; @@ -29,48 +29,59 @@ lazy_static! { static ref HAL: Set = s("hal"); } +fn do_ru_adesha(rule: &'static str, p: &mut Prakriya, i: usize) { + p.run_at(rule, i, |t| { + t.set_antya("ru~"); + t.add_tag(T::Ru); + }); + // Delete nasal vowel of "ru~". + p.run_at("1.3.2", i, |t| { + t.set_antya(""); + t.set_antya(""); + }); +} + /// Runs rules for lopa of the final `n` of a prAtipadika. /// Example: rAjan + Bis -> rAjaBis. /// /// (8.2.7 - 8.2.8) fn try_na_lopa(p: &mut Prakriya) -> Option<()> { - let i_prati = p.find_last(T::Pratipadika)?; - let sup = p.view(i_prati + 1)?; - - let prati = p.get(i_prati)?; - - let is_pada = prati.is_pada() - || sup.is_empty() - || p.has(i_prati + 1, |t| t.has_tag_in(&[T::Upasarga, T::Dhatu])); - if prati.has_antya('n') && is_pada { - if prati.has_u("ahan") { - // Special exception for ahan - if p.has(i_prati + 1, |t| t.is_empty()) { - p.run_at("8.2.69", i_prati, |t| t.set_antya("r")); - } else { - p.run_at("8.2.68", i_prati, |t| t.set_antya("ru~")); + for i_prati in 0..p.terms().len() { + let prati = p.get(i_prati)?; + let is_pada = || p.is_pada(i_prati); + + if prati.is_pratipadika() && prati.has_antya('n') && is_pada() { + let prati = p.get(i_prati)?; + if prati.has_u("ahan") { + // Special exception for ahan + if p.has(i_prati + 1, |t| t.is_empty()) { + p.run_at("8.2.69", i_prati, |t| t.set_antya("r")); + } else { + do_ru_adesha("8.2.68", p, i_prati); + } + return None; } - return None; - } - let mut blocked = false; - if sup.has_tag(T::Sambuddhi) || sup.has_u("Ni") { - if p.has_tag(T::Napumsaka) { - // "vA napuMsakAnAm" - // (nAman, nAma) - blocked = p.run_optional("8.2.8.v1", |_| {}); - } else { - // sambuddhi: yogin, Atman - // ni: vyoman, Sarman, etc. (vedic) - p.step("8.2.8"); - blocked = true; + let mut blocked = false; + let sup = p.pratyaya(i_prati + 1)?; + if sup.has_tag(T::Sambuddhi) || sup.has_u("Ni") { + if p.has_tag(T::Napumsaka) { + // "vA napuMsakAnAm" + // (nAman, nAma) + blocked = p.optional_run("8.2.8.v1", |_| {}); + } else { + // sambuddhi: yogin, Atman + // ni: vyoman, Sarman, etc. (vedic) + p.step("8.2.8"); + blocked = true; + } } - } - if !blocked { - // rAjA, rAjaByAm, ... - // (these can be called `pada` by 1.4.17. - p.run_at("8.2.7", i_prati, op::antya("")); + if !blocked { + // rAjA, rAjaByAm, ... + // (these can be called `pada` by 1.4.17. + p.run_at("8.2.7", i_prati, op::antya("")); + } } } @@ -139,7 +150,7 @@ fn try_change_r_to_l(p: &mut Prakriya) -> Option<()> { p.run_at("8.2.20", i, do_ra_la); } else if x.has_gana(Gana::Tudadi) && y.has_adi(&*AC) { // TODO: why only gana 6? - p.run_optional_at("8.2.21", i, do_ra_la); + p.optional_run_at("8.2.21", i, do_ra_la); } } } @@ -264,7 +275,7 @@ fn try_lopa_of_samyoganta_and_s(p: &mut Prakriya) -> Option<()> { { return true; } - if num_hals >= 2 && j == cur.text.len() - 1 && cur.is_pada() { + if num_hals >= 2 && j == cur.text.len() - 1 && p.is_pada(i) { return true; } } @@ -298,7 +309,7 @@ fn try_lopa_of_samyoganta_and_s(p: &mut Prakriya) -> Option<()> { } // For now, use separate logic for other padas, e.g. upapadas. - // Check "JHAL" to ignore bahiranga changes like "dadhy atra". + // Check "JHAL" to ignore lopa on bahiranga changes like "dadhy atra". for i in 0..p.terms().len() { while p.has(i, |t| { t.is_pada() && t.is_samyoganta() && t.has_antya(&*JHAL) @@ -307,7 +318,8 @@ fn try_lopa_of_samyoganta_and_s(p: &mut Prakriya) -> Option<()> { } } - if !p.terms().last().expect("ok").is_dhatu() { + // A second form of 8.2.23 for when the last term has just one letter. + if p.is_pada(p.terms().len() - 1) { let mut cp = CharPrakriya::new(p); cp.for_chars_rev( |_, text, i| al::is_samyoganta(text) && i == text.len() - 1, @@ -348,7 +360,7 @@ fn try_ha_adesha(p: &mut Prakriya) -> Option<()> { if is_dhatu { let dhatu = p.get(i)?; if dhatu.has_u_in(DRUHA_ADI) { - p.run_optional("8.2.33", |p| p.set(i, op::antya("G"))); + p.optional_run("8.2.33", |p| p.set(i, op::antya("G"))); } else if dhatu.has_u("Ra\\ha~^") { p.run_at("8.2.34", i, op::antya("D")); } else if dhatu.has_text("Ah") { @@ -423,17 +435,24 @@ fn try_ch_to_s(p: &mut Prakriya) { fn per_term_1a(p: &mut Prakriya) -> Option<()> { for i in 0..p.terms().len() { - let x = p.get(i)?; + let x = p.get_if(i, |t| { + if t.is_final() { + !t.has_antya('Y') + } else { + true + } + })?; - let jhali_or_ante = match p.find_next_where(i, |t| !t.is_empty()) { + let is_ante = p.is_pada(i); + let is_jhali = match p.find_next_where(i, |t| !t.is_empty()) { Some(j) => { let t = p.get(j)?; (t.is_pratyaya() || t.is_agama()) && t.has_adi(&*JHAL) } - None => p.terms().last()?.is_pada(), + None => false, }; - if x.has_antya(&*CU) && (x.is_pada() || jhali_or_ante) { + if x.has_antya(&*CU) && (is_jhali || is_ante) { if let Some(c) = x.antya() { let sub = CU_TO_KU.get(c)?; p.run_at("8.2.30", i, |t| { @@ -456,7 +475,8 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { let if_y = match p.find_next_where(i, |t| !t.is_empty()) { Some(i_y) => { let y = p.get(i_y)?; - y.has_adi('s') || (y.is_pratyaya() && y.text.starts_with("Dv")) + let is_sdhvoh = y.has_adi('s') || (y.is_pratyaya() && y.text.starts_with("Dv")); + is_sdhvoh || p.is_pada(i) } None => true, }; @@ -469,6 +489,9 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { } } + // Blocks 8.2.39 so must appear first. + try_rutva(p); + // Exclude the following from 8.2.39 so that the corresponding rules aren't // vyartha: // - s for 8.2.66 (sasajuSo ruH) @@ -476,7 +499,9 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { let c = p.get(i)?; // HACK to exclude erroneous sandhi on (upa -> up -> ub) let is_pada = p.is_pada(i) && !(c.is_upasarga() && !c.has_u("ud")); - let has_exception = c.has_antya(&*JHAL_TO_JASH_EXCEPTIONS); + let has_exception = c.has_antya(&*JHAL_TO_JASH_EXCEPTIONS) + // HACK to exclude "z" of pipaWiz, etc. + || (c.has_u("san") && c.has_text("z")); if c.has_antya(&*JHAL) && !has_exception && is_pada { let key = c.antya()?; @@ -485,10 +510,6 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { } } - Some(()) -} - -fn run_misc_rules_1(p: &mut Prakriya) -> Option<()> { xy_rule( p, |x, y| { @@ -519,7 +540,7 @@ fn run_rules_for_nistha_t(p: &mut Prakriya) -> Option<()> { let i_d = p.find_last(T::Dhatu)?; let i_k = i_d + 1; - let k = p.view(i_k)?; + let k = p.pratyaya(i_k)?; if !k.has_tag(T::Nistha) { return None; } @@ -568,10 +589,10 @@ fn run_rules_for_nistha_t(p: &mut Prakriya) -> Option<()> { let code = "8.2.56"; if dhatu.has_u("hrI\\") { // By default, hrI takes -ta. So, this rule allows -na. - p.run_optional_at(code, i_k, op::adi("n")); + p.optional_run_at(code, i_k, op::adi("n")); } else { // By default, these dhatus take -na. So, this rule allows -ta. - blocked = p.run_optional(code, |_| {}); + blocked = p.optional_run(code, |_| {}); } } else if dhatu.has_u("vi\\dx~^") { // TODO: think through the rules below. They all work correctly, but most users won't @@ -599,7 +620,7 @@ fn run_rules_for_nistha_t(p: &mut Prakriya) -> Option<()> { let set_adi = |rule, p: &mut Prakriya, s| p.run_at(rule, i_k, op::adi(s)); let to_n = |rule, p: &mut Prakriya| set_adi(rule, p, "n"); - let optional_to_n = |rule, p: &mut Prakriya| p.run_optional_at(rule, i_k, op::adi("n")); + let optional_to_n = |rule, p: &mut Prakriya| p.optional_run_at(rule, i_k, op::adi("n")); let dhatu = p.get(i_d)?; if dhatu.is_samyogadi() && dhatu.has_at(1, &*YAN) && dhatu.has_antya('A') { @@ -621,8 +642,9 @@ fn run_rules_for_nistha_t(p: &mut Prakriya) -> Option<()> { optional_to_n("8.2.48", p); } else if dhatu.has_text("dyU") { optional_to_n("8.2.49", p); - } else if dhatu.has_text("vA") && i_d > 0 && p.has(i_d - 1, |t| t.has_text("nis")) { - // Check for "nis" because this is before the rutva section. + } else if dhatu.has_text("vA") && i_d > 0 && p.has(i_d - 1, |t| t.has_text_in(&["nis", "nir"])) + { + // TODO: include both "nis" and "nir" ? optional_to_n("8.2.50", p); } else if dhatu.has_text("Suz") { // Suzka @@ -635,52 +657,32 @@ fn run_rules_for_nistha_t(p: &mut Prakriya) -> Option<()> { // kzAma set_adi("8.2.53", p, "m"); } else if dhatu.has_text("stI") && i_d > 0 && p.has(i_d - 1, |t| t.has_u("pra")) { - p.run_optional_at("8.2.54", i_k, |t| t.set_adi("m")); + p.optional_run_at("8.2.54", i_k, |t| t.set_adi("m")); } Some(()) } fn run_misc_rules_2(p: &mut Prakriya) -> Option<()> { - xy_rule( - p, - |x, y| x.is_dhatu() && x.has_antya('m') && (y.has_adi('m') || y.has_adi('v')), - |p, i, _| { - p.run_at("8.2.65", i, op::antya("n")); - }, - ); - - Some(()) -} - -fn try_add_final_r(p: &mut Prakriya) -> Option<()> { - try_add_final_r_with_final_tin(p); - - // TODO: sajuS for i in 0..p.terms().len() { - if p.is_pada(i) && p.has(i, |t| t.has_antya('s')) { - p.run_at("8.2.66", i, op::antya("ru~")); + if p.is_pada(i) { + let t = p.get(i)?; + if t.is_dhatu() && p.has(i + 1, |t| t.has_u("kvi~n")) { + // Gftaspfk, ... + let sub = if t.has_antya('n') { "N" } else { "k" }; + p.run_at("8.2.62", i, |t| t.set_antya(sub)); + } else if t.is_dhatu() && t.has_u("Ra\\Sa~") && p.has(i + 1, |t| t.has_u("kvi~p")) { + // nak, naw + p.optional_run_at("8.2.63", i, |t| t.set_antya("k")); + } } } - // 6.1.113 and 6.1.114 are not part of the tripAdi, but they have no scope to apply otherwise. - xy_rule( - p, - |x, y| x.ends_with("aru~") && y.has_adi('a'), - |p, i, j| { - p.run("6.1.113", |p| { - p.set(i, |t| t.find_and_replace_text("aru~", "o")); - p.set(j, |t| t.set_adi("")); - }); - }, - ); xy_rule( p, - |x, y| x.ends_with("aru~") && y.has_adi(&*HASH), + |x, y| x.is_dhatu() && x.has_antya('m') && (y.has_adi('m') || y.has_adi('v')), |p, i, _| { - p.run_at("6.1.114", i, |t| { - t.find_and_replace_text("aru~", "o"); - }); + p.run_at("8.2.65", i, op::antya("n")); }, ); @@ -713,21 +715,77 @@ fn try_add_final_r_with_final_tin(p: &mut Prakriya) -> Option<()> { } else if (dhatu.has_antya('s') || dhatu.has_antya('d')) && tin.has_u("sip") { if dhatu.has_antya('s') { // acakAs + s -> acakAH, acakAt, acakAd - p.run_optional_at("8.2.74", i_dhatu, op::antya("d")); + p.optional_run_at("8.2.74", i_dhatu, op::antya("d")); } else { // aruRad + s -> aruRaH, aruRat, aruRad - p.run_optional_at("8.2.75", i_dhatu, op::antya("ru~")); + if p.optional_run_at("8.2.75", i_dhatu, op::antya("ru~")) { + // Delete nasal vowel of "ru~". + p.run_at("1.3.2", i_dhatu, |t| { + t.set_antya(""); + t.set_antya(""); + }); + } } } Some(()) } +fn try_rutva(p: &mut Prakriya) -> Option<()> { + try_add_final_r_with_final_tin(p); + + for i in 0..p.terms().len() { + let term = p.get(i)?; + + // for pipaWiz -> pipaWIH. This "z" is asiddha, but our code isn't smart enough to + // detect that. + let hacky_is_s_san = term.has_text("z") && term.has_u("san"); + let is_sa = term.has_antya('s') || hacky_is_s_san; + let is_sajush = p.has_pratipadika(i, "sajuz"); + if p.is_pada(i) && (is_sa || is_sajush) { + do_ru_adesha("8.2.66", p, i); + } + } + + Some(()) +} + +fn try_add_final_r(p: &mut Prakriya) -> Option<()> { + try_add_final_r_with_final_tin(p); + + // 6.1.113 and 6.1.114 are not part of the tripAdi, but they have no scope to apply otherwise. + xy_rule( + p, + |x, y| x.ends_with("ar") && x.has_tag(T::Ru) && y.has_adi('a'), + |p, i, j| { + p.run("6.1.113", |p| { + p.set(i, |t| { + t.set_antya(""); + t.set_antya("o"); + }); + p.set(j, |t| t.set_adi("")); + }); + }, + ); + xy_rule( + p, + |x, y| x.ends_with("ar") && x.has_tag(T::Ru) && y.has_adi(&*HASH), + |p, i, _| { + p.run_at("6.1.114", i, |t| { + t.set_antya(""); + t.set_antya("o"); + }); + }, + ); + + Some(()) +} + /// (8.2.76 - 8.2.79) fn try_lengthen_dhatu_vowel(p: &mut Prakriya) -> Option<()> { let i = p.find_first_where(|t| t.is_dhatu())?; - let i_n = p.find_next_where(i, |t| !t.is_empty())?; - let dhatu = p.get(i)?; + let i_last = p.find_last_where(|t| t.is_dhatu())?; + let i_n = p.find_next_where(i, |t| !t.is_empty()); let is_rv = |opt| match opt { Some(c) => c == 'r' || c == 'v', @@ -742,18 +800,24 @@ fn try_lengthen_dhatu_vowel(p: &mut Prakriya) -> Option<()> { None => false, }; let before_upadha = |t: &Term| t.text.chars().rev().nth(2); + let dhatu = p.get(i)?; + // Use a view for pipaWiH -> pipaWIH (pi + paW + i + z) + let dhatu_view = p.custom_view(i, i_last)?; // karotereva tatra grahaRAd ityAhuH (SK 2536) // TODO: bha if dhatu.has_text("Cur") || (dhatu.has_text("kur") && dhatu.has_u("qukf\\Y")) { p.step("8.2.79"); + } else if is_ik(dhatu_view.upadha()) && is_rv(dhatu_view.antya()) && p.is_pada(i_last) { + // pipaWIH, ... + let sub = al::to_dirgha(dhatu_view.upadha()?)?; + p.run("8.2.76", |p| { + p.set_upadha_within_range(i, i_last, &sub.to_string()); + }); } else if is_ik(dhatu.upadha()) && is_rv(dhatu.antya()) { let sub = al::to_dirgha(dhatu.upadha()?)?; - if p.has(i_n, |t| t.has_adi(&*HAL)) { + if p.has(i_n?, |t| t.has_adi(&*HAL)) { p.run_at("8.2.77", i, op::upadha(&sub.to_string())); - } else { - // TODO: only applies to padas. - // p.op_term("8.2.76", i, op::upadha(&sub.to_string())); } } else if is_ik(before_upadha(dhatu)) && is_rv(dhatu.upadha()) && is_hal(dhatu.antya()) { let pre_upadha = before_upadha(dhatu)?; @@ -776,8 +840,8 @@ fn try_rules_for_adas(p: &mut Prakriya) -> Option<()> { let adas = p.get_if(i, |t| t.has_u("adas"))?; let sup = p.terms().last()?; - // "s" might become "ru~" above, so check for "ru~" as well as final "s". - if !adas.has_antya('~') && !adas.has_antya('s') { + // "s" might become "ru~" above, so check for "r" as well as final "s". + if !adas.has_antya('r') && !adas.has_antya('s') { if (adas.has_antya('e') || sup.has_adi('e')) && sup.has_tag(T::Bahuvacana) { p.run("8.2.81", |p| { let t = p.get_mut(i).expect("ok"); @@ -791,19 +855,35 @@ fn try_rules_for_adas(p: &mut Prakriya) -> Option<()> { } else if adas.text.contains('d') { p.run("8.2.80", |p| { let t = p.get_mut(i).expect("ok"); - if t.has_antya('d') { - t.set_antya("m"); - } else { - t.set_upadha("m"); + + let mut changed = false; + for (i, c) in t.text.bytes().enumerate().rev() { + let c = c as char; + if AC.contains(c) { + let sub = if al::is_dirgha(c) { "U" } else { "u" }; + t.set_at(i, sub); + changed = true; + break; + } else if c == 'd' { + // Should change the vowel *after* d, not before. + break; + } } - if t.has_antya('a') { - t.set_antya("u") - } else if t.has_antya(&*AC) { - t.set_antya("U") - } else { - // amU - p.set(i + 1, |t| t.set_adi("U")); + + if !changed { + // Change first sound of next real term. + if let Some(i_next) = p.find_next_not_empty(i) { + // for amU, etc. + p.set(i_next, |t| { + let c = t.adi().expect("present"); + let sub = if al::is_dirgha(c) { "U" } else { "u" }; + t.set_adi(sub) + }); + } } + + // d --> m + p.set(i, |t| t.find_and_replace_text("d", "m")); }); } } @@ -825,10 +905,9 @@ pub fn run(p: &mut Prakriya) { try_ch_to_s(p); // 8.2.30 -- general rule for ha and ch_s per_term_1a(p); - // 8.2.37 - 8.2.39 + // 8.2.37 - 8.2.41 per_term_1b(p); - run_misc_rules_1(p); run_rules_for_nistha_t(p); run_misc_rules_2(p); diff --git a/vidyut-prakriya/src/tripadi/pada_8_3.rs b/vidyut-prakriya/src/tripadi/pada_8_3.rs index 890e802..1ff4be8 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_3.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_3.rs @@ -1,14 +1,14 @@ use crate::args::Gana; -use crate::char_view::{get_term_and_offset_indices, xy, CharPrakriya}; +use crate::core::char_view::{get_term_and_offset_indices, xy, CharPrakriya}; +use crate::core::iterators::xy_rule; +use crate::core::operators as op; +use crate::core::Code; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::it_samjna; -use crate::iterators::xy_rule; -use crate::operators as op; -use crate::prakriya::Code; -use crate::prakriya::Prakriya; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -20,13 +20,13 @@ lazy_static! { static ref SHAR: Set = s("Sar"); static ref HAL: Set = s("hal"); static ref AC: Set = s("ac"); + static ref IK: Set = s("ik"); static ref AA: Set = s("a"); static ref ASH: Set = s("aS"); } fn try_ra_lopa(p: &mut Prakriya) -> Option<()> { for i in 0..p.terms().len() { - let c = p.get(i)?; let is_avasane = p.find_next_where(i, |t| !t.is_empty()).is_none(); let is_khari = if let Some(j) = p.find_next_where(i, |t| !t.is_empty()) { p.has(j, |t| t.has_adi(&*KHAR)) @@ -34,36 +34,34 @@ fn try_ra_lopa(p: &mut Prakriya) -> Option<()> { false }; - // Quick HACK to remove `u~` - if c.ends_with("ru~") { - p.set(i, |t| { - t.set_antya(""); - t.set_antya(""); - t.add_tag(T::Ru); - }); - p.step("1.3.2"); - } - // 8.3.15 // TODO: next pada // HACK: use has_upadha to block "pra Rcchati -> pr Arcchati -> pHArcCati" let c = p.get(i)?; let has_ru = c.has_antya('r') && !c.has_upadha(&*HAL); - if has_ru { - if p.has(i + 1, |t| t.has_adi('r')) { - p.run_at("8.3.14", i, op::antya("")); - let c = p.get(i)?; - if c.is_hrasva() { - let sub = al::to_dirgha(p.get(i)?.antya()?)?; - // Placed here, otherwise this is vyartha. See `8.3.13` for the Qa case of - // this rule. - p.run_at("6.3.111", i, op::antya(&sub.to_string())); + if !has_ru { + continue; + } + + if p.has(i + 1, |t| t.has_adi('r')) { + p.run_at("8.3.14", i, op::antya("")); + let c = p.get(i)?; + if c.is_hrasva() { + let sub = al::to_dirgha(p.get(i)?.antya()?)?; + // Placed here, otherwise this is vyartha. See `8.3.13` for the Qa case of + // this rule. + p.run_at("6.3.111", i, op::antya(&sub.to_string())); + } + } else if p.is_pada(i) && (is_avasane || is_khari) { + if p.has(i + 1, |t| !t.is_empty() && t.is_sup()) { + if p.has(i, |t| t.has_tag(T::Ru)) { + // payaHsu, ... + p.run_at("8.3.16", i, |t| t.set_antya("H")); } - } else if p.is_pada(i) && (is_avasane || is_khari) { - p.run_at("8.3.15", i, |t| { - t.set_antya(""); - t.text += "H"; - }); + // Otherwise, we have gIrzu, etc. + } else { + // vfkzaH, ... + p.run_at("8.3.15", i, |t| t.set_antya("H")); } } } @@ -121,6 +119,10 @@ fn try_mn_to_anusvara(p: &mut Prakriya) -> Option<()> { let t = p.get(i_term).expect("ok"); if t.is_pada() && i_offset + 1 == t.text.len() { false + } else if t.has_text("pums") && !p.has(i_term + 1, |t| t.is_pada()) { + // Don't make this change for "m" in a pratipadika, so that we can derive + // "supums". + false } else { p.run("8.3.24", |p| p.set_char_at(i, "M")); true @@ -134,16 +136,21 @@ fn try_mn_to_anusvara(p: &mut Prakriya) -> Option<()> { Some(()) } -fn try_add_dhut_agama(p: &mut Prakriya) { - xy_rule( - p, - |x, y| x.has_tag(T::Pada) && x.has_antya('q') && y.has_adi('s'), - |p, _, j| { - if p.run_optional("8.3.29", |p| op::insert_agama_before(p, j, "Du~w")) { +fn try_add_dhut_agama(p: &mut Prakriya) -> Option<()> { + for i in 0..p.terms().len() { + let j = p.find_next_not_empty(i)?; + let x = p.get(i)?; + let y = p.get(j)?; + if p.is_pada(i) && x.has_antya('q') && y.has_adi('s') { + p.optionally("8.3.29", |rule, p| { + op::insert_agama_before(p, j, "Du~w"); + p.step(rule); it_samjna::run(p, j).ok(); - } - }, - ); + }); + } + } + + Some(()) } /// Runs rules that modify the visarjanIya (visarga). @@ -153,12 +160,16 @@ fn try_visarjaniyasya(p: &mut Prakriya) -> Option<()> { let is_samasa = |p: &Prakriya, i_x| p.has(i_x + 1, |t| t.is_empty() && t.is_pada()); for i_x in 0..p.terms().len() { - let x = p.get_if(i_x, |t| t.has_antya('H'))?; + let x = match p.get_if(i_x, |t| t.has_antya('H')) { + Some(t) => t, + None => continue, + }; + let i_y = p.find_next_where(i_x, |t| !t.is_empty())?; let y = p.get(i_y)?; if y.has_adi(&*SHAR) { - p.run_optional_at("8.3.36", i_x, |t| t.set_antya("s")); + p.optional_run_at("8.3.36", i_x, |t| t.set_antya("s")); } else if y.has_at(1, &*SHAR) { p.run_at("8.3.35", i_x, |_| {}); } else if y.has_adi(&*KU_PU) { @@ -167,7 +178,7 @@ fn try_visarjaniyasya(p: &mut Prakriya) -> Option<()> { } else if is_it_ut_upadha(x) && !x.is_pratyaya() { p.run_at("8.3.41", i_x, |t| t.set_antya("z")); } else if x.has_text("tiras") && x.has_tag(T::Gati) { - p.run_optional_at("8.3.42", i_x, |t| t.set_antya("s")); + p.optional_run_at("8.3.42", i_x, |t| t.set_antya("s")); } else if x.text.ends_with("aH") && is_samasa(p, i_x) && !x.is_avyaya() @@ -193,14 +204,17 @@ fn try_visarjaniyasya(p: &mut Prakriya) -> Option<()> { struct ShaPrakriya<'a> { p: &'a mut Prakriya, i_term: usize, + i_char: usize, done: bool, } impl<'a> ShaPrakriya<'a> { - fn new(p: &'a mut Prakriya, i_dhatu: usize) -> Self { + fn new(p: &'a mut Prakriya, i_char: usize) -> Self { + let i_term = p.find_for_char_at(i_char).expect("ok"); Self { p, - i_term: i_dhatu, + i_term, + i_char, done: false, } } @@ -228,7 +242,7 @@ impl<'a> ShaPrakriya<'a> { fn try_shatva(&mut self, rule: Code) { if !self.done { - self.p.run_at(rule, self.i_term, |t| t.set_adi("z")); + self.p.run(rule, |p| p.set_char_at(self.i_char, "z")); } self.done = true; } @@ -244,7 +258,7 @@ impl<'a> ShaPrakriya<'a> { if !self.done { let done = self .p - .run_optional_at(rule, self.i_term, |t| t.set_adi("z")); + .optional_run(rule, |p| p.set_char_at(self.i_char, "z")); self.done = done; done } else { @@ -253,15 +267,19 @@ impl<'a> ShaPrakriya<'a> { } } -fn run_shatva_rules_at_index(sp: &mut ShaPrakriya) -> Option<()> { +fn run_shatva_rules_at_char_index(sp: &mut ShaPrakriya, text: &str) -> Option<()> { use Gana::*; let i = sp.i_term; let t = sp.term(); - // Skip if not s-Adi. - // Also skip abhyasas since we handle these as part of the dhatu rules. - if !t.has_adi('s') || t.is_abhyasa() { + // Skip abhyasas since we handle these as part of the dhatu rules. + if t.is_abhyasa() { + return None; + } + + // Skip unAdi-pratyayas that don't allow satva. + if t.is_krt() && t.has_u("isan") { return None; } @@ -279,13 +297,13 @@ fn run_shatva_rules_at_index(sp: &mut ShaPrakriya) -> Option<()> { // visfpa // TODO: savanAdi sp.try_block("8.3.110"); - } else if (t.has_u("sAt") && t.is_pratyaya()) || i == 0 { + } else if (t.has_u("sAt") && t.is_pratyaya()) || sp.i_char == 0 { // daDisAt, daDi siYcati sp.try_block("8.3.111"); } else if t.has_u("zi\\ca~^") && sp.p.has(i + 1, |t| t.has_u("yaN")) { // aBisesicyate sp.try_block("8.3.112"); - } else if t.has_u_in(&["ziDa~", "ziDU~"]) && sp.has_upasarga_in(&["pari", "aBi", "vi"]) { + } else if t.has_u_in(&["ziDa~"]) && sp.has_upasarga_in(&["pari", "aBi", "vi"]) { // Based on commentary, this seems to apply only for abhi-sidh and // pari-sidh. SK has vi-sidh. sp.try_block("8.3.113"); @@ -472,21 +490,77 @@ fn run_shatva_rules_at_index(sp: &mut ShaPrakriya) -> Option<()> { } } let term = sp.term(); - if term.has_tag(T::FlagAdeshadi) && !abhyasa_vyavaya { + if term.has_tag(T::FlagSaAdeshadi) && !abhyasa_vyavaya { sp.try_block("8.3.111"); } } + let term = sp.term(); + if sp.i_term > 0 && term.is_samasa() { + // TODO: these rules assume one term per pratipadika. + let i_purva = sp.p.find_prev_where(sp.i_term, |t| !t.is_empty())?; + let purva = sp.p.get(i_purva)?; + let uttara = term; + + if purva.has_text("aNguli") && uttara.has_u("saNga") { + // aNgulizaNga + sp.try_shatva("8.3.80"); + } else if purva.has_text("BIru") && uttara.has_u("sTAna") { + // BIruzWAna + sp.try_shatva("8.3.81"); + } else if purva.has_text("agni") && uttara.has_u_in(&["stut", "stoma", "soma"]) { + // BIruzWAna + sp.try_shatva("8.3.82"); + } else if purva.has_text_in(&["mAtf", "pitf"]) && uttara.has_u("svasf") { + // mAtfzvasA, ... + sp.try_shatva("8.3.84"); + } else if purva.has_text_in(&["vi", "ku", "Sami", "pari"]) && uttara.has_u("sTala") { + // vizWala, ... + sp.try_shatva("8.3.96"); + } else if purva.has_text_in(&[ + "amba", "Amba", "go", "BUmi", "savya", "apa", "dvi", "tri", "ku", "Seku", "SaNku", + "aNgu", "maYji", "puYji", "parame", "barhis", "divi", "agni", + ]) && uttara.has_u("sTa") + { + // ambazWa, ... + sp.try_shatva("8.3.97"); + } + } else if term.has_upadha(&*IK) + && term.has_antya('s') + && sp + .p + .has(sp.i_term + 1, |t| t.is_taddhita() && t.has_adi('t')) + { + // sarpizwama, ... + sp.try_shatva("8.3.101"); + } + // General rules // ------------- - let term_view = sp.p.view(sp.i_term)?; - let prev = sp.prev()?; - - let is_apadanta = !term_view.is_empty(); - // HACK: added Agama here. We should exclude it. - let adesha_pratyaya = term_view.has_tag_in(&[T::Pratyaya, T::FlagAdeshadi]); - if prev.has_antya(&*IN_KU) && is_apadanta && adesha_pratyaya && term_view.has_adi('s') { + let term_view = sp.p.pratyaya(sp.i_term); + let is_apadanta = match &term_view { + Some(v) => !v.is_empty(), + None => false, + }; + let adesha_pratyaya = match &term_view { + Some(v) => v.has_tag_in(&[T::Pratyaya, T::FlagSaAdeshadi]), + None => false, + }; + let in_koh = match sp.prev() { + Some(t) => t.has_antya(&*IN_KU), + None => false, + }; + if in_koh && is_apadanta && adesha_pratyaya { + const SVIDI_SVADI: &[&str] = &[ + "YizvidA~\\", + "YizvidA~", + "zvi\\dA~", + "zvada~\\", + "zvada~", + "zaha~", + "zaha~\\", + ]; let term = sp.term(); // Use `find_next_where` to find `san` because position of `san` is uncertain due to iw-Agama // and ni-pratyaya. `z` is part of the rule. @@ -495,60 +569,119 @@ fn run_shatva_rules_at_index(sp: &mut ShaPrakriya) -> Option<()> { if shan.is_some() { let nau = sp.p.has(sp.i_term + 1, |t| t.is_ni_pratyaya()); - if term.has_u("zwu\\Y") || nau { - // Prefer `has_u_in` over `has_text_in` because `has_u_in` is more reliable and doesn't - // include sound changes. - // TODO: does this overgenerate? - if nau - && term.has_u_in(&[ - "YizvidA~\\", - "YizvidA~", - "zvi\\dA~", - "zvada~\\", - "zvada~", - "zaha~", - "zaha~\\", - ]) - { - sp.p.step("8.3.62"); - } else { + + // Prefer `has_u_in` over `has_text_in` because `has_u_in` is more reliable and doesn't + // include sound changes. + // TODO: does this overgenerate? + if nau && term.has_u_in(SVIDI_SVADI) { + sp.try_block("8.3.62"); + } else { + let code = "8.3.61"; + if term.has_u("zwu\\Y") || nau { // stu -> tuzwUsati // siv -> sizevayizati - sp.try_shatva("8.3.61"); + sp.try_shatva(code); + } else { + // sisikzati + sp.try_block(code); } } + } + } + + let mut prev_chars = text[..sp.i_char].chars().rev(); + let inku = if let Some(y) = prev_chars.next() { + if IN_KU.contains(y) { + true } else { - if term.has_u("sAti~") { - // agnisAt ... - sp.try_block("8.3.111") + let i_term = sp.p.find_for_char_at(sp.i_char - 1).expect("ok"); + let is_num = y == 'M' && sp.p.has(i_term, |t| t.has_tag(T::FlagNum)); + let is_num_visarjaniya_shar = is_num || y == 'H' || SHAR.contains(y); + + if is_num_visarjaniya_shar { + // Per commentaries, allow at most one num-visarjaniya-shar sound in-between. + prev_chars.next().map_or(false, |c| IN_KU.contains(c)) } else { - // General case. - sp.try_shatva("8.3.59"); + false } } + } else { + false + }; + + let is_antya = sp.i_char + 1 == text.len(); + + let term = sp.p.pratyaya(sp.i_term)?; + if inku && term.has_tag_in(&[T::Pratyaya, T::FlagSaAdeshadi]) && !is_antya { + // For zRus, etc. -- we want to change the first s here, not the second. + let is_first_s_of_term = if sp.i_term == 0 { + sp.i_char == 0 + } else { + let num_chars_before: usize = + sp.p.terms()[..sp.i_term].iter().map(|t| t.text.len()).sum(); + num_chars_before == sp.i_char + }; + let t = sp.p.get(sp.i_term)?; + if t.is_dhatu() && !is_first_s_of_term { + return None; + } + + if term.has_u("sAti~") { + // agnisAt ... + sp.try_block("8.3.111"); + } else { + // General case. + sp.try_shatva("8.3.59"); + } } Some(()) } +/* +fn find_shatva_spans(text: &str) -> Vec<(usize, usize)> { + let mut ret = Vec::new(); + let mut i_inku = None; + for (i, c) in text.chars().enumerate() { + if IN_KU.contains(c) { + // Start of span. + i_inku = Some(i); + } else if c == 's' { + if let Some(inku) = i_inku { + // End of span. + ret.push((inku, i)); + } + i_inku = None; + } else if c == '~' { + // Ignore nasal vowel markings. + } else if !"MH".contains(c) { + // By 8.3.58, reset if we see a sound that is not in num-visarjanIya. + i_inku = None; + } + } + ret +} +*/ + fn run_shatva_rules(p: &mut Prakriya) -> Option<()> { // Iterate in reverse order so that we can produce `san` -> `zan`, which can then trigger // 8.3.61. - for i in (0..p.terms().len()).rev() { - let mut sp = ShaPrakriya::new(p, i); - run_shatva_rules_at_index(&mut sp); - } - - // HACK for ezaH - if p.get(0)?.has_text("esa") && p.get(0)?.has_tag(T::Sarvanama) { - p.run_at("8.3.59", 0, |t| t.set_text("eza")); + // + // Use a `bytes()` iterator because `chars()` doesn't support `.enumerate().rev()` + let text = p.text(); + for (i, c) in text.bytes().enumerate().rev() { + if (c as char) == 's' { + let mut sp = ShaPrakriya::new(p, i); + run_shatva_rules_at_char_index(&mut sp, &text); + } } // Other s -> z rules xy_rule( p, |x, _| { - x.has_u_in(&["va\\sa~", "SAsu~", "Gasx~"]) + // Also include SAsu~\\ for ASizO, etc. + x.has_u_in(&["va\\sa~", "SAsu~", "SAsu~\\", "Gasx~"]) && ((x.has_upadha(&*IN_KU) && x.has_antya('s')) // HACK for UsatuH (U + s + atuH) || x.has_text("s")) @@ -594,7 +727,7 @@ fn try_murdhanya_for_dha_in_tinanta(p: &mut Prakriya) -> Option<()> { if inah && shidhvam_lun_lit && dha { if p.has(i_anga + 1, |t| t.is_it_agama()) { - p.run_optional_at("8.3.79", i, op::adi("Q")); + p.optional_run_at("8.3.79", i, op::adi("Q")); } else { p.run_at("8.3.78", i, op::adi("Q")); } diff --git a/vidyut-prakriya/src/tripadi/pada_8_4.rs b/vidyut-prakriya/src/tripadi/pada_8_4.rs index d45ec38..f00fcc5 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_4.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_4.rs @@ -1,11 +1,13 @@ use crate::args::Gana; -use crate::char_view::{get_at, get_term_and_offset_indices, xy, xyz, CharPrakriya}; -use crate::operators as op; -use crate::prakriya::Prakriya; +use crate::core::char_view::{ + get_term_and_offset_indices, get_term_index_at, xy, xyz, CharPrakriya, +}; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -85,6 +87,16 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> let x = p.get(i_x)?; let y = p.get(i_y)?; + /* + if y.is_samasa() { + if x.has_text_in(&["puragA", "miSrakA", "siDrakA", "SArikA", "kowarA", "agre"]) + && y.has_u("vana") + { + + } + } + */ + if i_x != i_y && x.is_pada() && x.has_antya('z') { // nizpAna, ... p.step("8.4.35"); @@ -128,7 +140,7 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> let is_hinu = || (dhatu.has_text("hi") && y.has_u("Snu")); let is_mina = || (dhatu.has_text("mI") && y.has_u("SnA")); - if y.has_adi('n') && y.has_tag(T::FlagAdeshadi) { + if y.has_adi('n') && y.has_tag(T::FlagNaAdeshadi) { p.run("8.4.14", |p| p.set_char_at(i_n, "R")); } else if is_hinu() || is_mina() { // prahiRoti @@ -148,7 +160,7 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> if dhatu_in(dhatu, GAD_ADI) || dhatu.has_tag(T::Ghu) { p.run("8.4.17", |p| p.set_char_at(i_n, "R")); } else if !(dhatu.has_adi('k') || dhatu.has_adi('K') || dhatu.has_tag(T::FlagShanta)) { - p.run_optional("8.4.18", |p| p.set(i_y, |t| t.set_adi("R"))); + p.optional_run("8.4.18", |p| p.set(i_y, |t| t.set_adi("R"))); } else { // pranikaroti, pranikhAdati } @@ -162,7 +174,7 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> } else if dhatu.has_u("ha\\na~") && dhatu.has_upadha('a') { let i_z = p.find_next_where(i_y, |t| !t.is_empty())?; if p.has(i_z, |t| t.has_adi('v') || t.has_adi('m')) { - p.run_optional("8.4.23", |p| p.set(i_y, |t| t.set_antya("R"))); + p.optional_run("8.4.23", |p| p.set(i_y, |t| t.set_antya("R"))); } else { p.run_at("8.4.22", i_dhatu, |t| t.set_antya("R")); } @@ -181,7 +193,8 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> } else { // 8.4.1 states *samAna-pade*, which means that the span must not cross a pada. let is_samana_pada = !p.terms()[i_x..i_y].iter().any(|t| { - t.has_tag_in(&[T::Sup, T::Tin]) || (t.has_tag(T::Pada) && !t.is_pratipadika()) + t.has_tag_in(&[T::Sup, T::Tin]) + || (t.has_tag(T::Pada) && !t.is_pratipadika() && !t.is_nyap_pratyaya()) }); // Allow "carman -> carmaRA" but disallow "sruGna -> *sruGRa" let is_exempt_pratipadika = p.has(i_x, |t| t.text.starts_with("srOGn")); @@ -270,8 +283,9 @@ fn try_change_stu_to_parasavarna(cp: &mut CharPrakriya) { |p, text, i| { let x = text.as_bytes()[i] as char; let y = text.as_bytes()[i + 1] as char; - let prev = get_at(p, i).expect("should be defined"); - if prev.has_tag(T::Pada) && prev.has_antya(&*SWU) { + let i_term = get_term_index_at(p, i).expect("defined"); + let prev = p.get(i_term).expect("defined"); + if p.is_pada(i_term) && prev.has_antya(&*SWU) { p.step("8.4.42"); false } else if TU.contains(x) && y == 'z' { @@ -404,18 +418,12 @@ fn try_jhal_adesha(cp: &mut CharPrakriya) -> Option<()> { JHAL.contains(x) && i == text.len() - 1 && p.terms().last().expect("present").is_pada() }, |p, text, i| { - let code = "8.4.56"; let x = text.as_bytes()[i] as char; let sub = JHAL_TO_CAR.get(x).expect("present"); if x != sub { - if p.is_allowed(code) { + p.optional_run("8.4.56", |p| { p.set_char_at(i, &sub.to_string()); - p.step(code); - true - } else { - p.decline(code); - false - } + }) } else { false } @@ -456,9 +464,16 @@ fn try_to_savarna(cp: &mut CharPrakriya) { }); cp.for_terms( - |x, y| x.is_upasarga() && x.has_u("ud") && y.has_u_in(&["zWA\\", "zwaBi~\\"]), + // TODO: which stanbh-dhAtus should we include? + |x, y| { + x.is_upasarga() + && x.has_u("ud") + && y.has_adi('s') + && y.has_u_in(&["zWA\\", "zwaBi~\\", "stanBu~"]) + }, |p, _, j| { - p.run_at("8.4.61", j, |t| t.set_adi("t")); + // "atrāghoṣasya sasya tādṛśa eva thakāraḥ" (SK) + p.run_at("8.4.61", j, |t| t.set_adi("T")); }, ); @@ -477,7 +492,7 @@ fn try_to_savarna(cp: &mut CharPrakriya) { _ => None, }; if let Some(sub) = sub { - p.run_optional("8.4.62", |p| p.set_char_at(i + 1, sub)) + p.optional_run("8.4.62", |p| p.set_char_at(i + 1, sub)) } else { false } @@ -485,19 +500,19 @@ fn try_to_savarna(cp: &mut CharPrakriya) { cp.for_chars( xyz(|x, y, z| JHAY.contains(x) && y == 'S' && AT.contains(z)), - |p, _, i| p.run_optional("8.4.63", |p| p.set_char_at(i + 1, "C")), + |p, _, i| p.optional_run("8.4.63", |p| p.set_char_at(i + 1, "C")), ); cp.for_chars( xyz(|x, y, z| HAL.contains(x) && YAM.contains(y) && YAM.contains(z) && y == z), - |p, _, i| p.run_optional("8.4.64", |p| p.set_char_at(i + 1, "")), + |p, _, i| p.optional_run("8.4.64", |p| p.set_char_at(i + 1, "")), ); cp.for_chars( xyz(|x, y, z| { HAL.contains(x) && JHAR.contains(y) && JHAR.contains(z) && al::is_savarna(y, z) }), - |p, _, i| p.run_optional("8.4.65", |p| p.set_char_at(i + 1, "")), + |p, _, i| p.optional_run("8.4.65", |p| p.set_char_at(i + 1, "")), ); } @@ -510,6 +525,18 @@ pub fn run(p: &mut Prakriya) { try_to_anunasika(&mut cp); try_jhal_adesha(&mut cp); try_to_savarna(&mut cp); + + let p = cp.p(); + + // a a iti + if p.terms().iter().any(|t| t.text.contains('a')) { + p.step("8.4.68"); + } + + // Mark terms as Final so they won't be altered further in future derivations. + for t in p.terms_mut() { + t.add_tag(T::Final); + } } #[cfg(test)] diff --git a/vidyut-prakriya/src/utils.rs b/vidyut-prakriya/src/utils.rs deleted file mode 100644 index 3926879..0000000 --- a/vidyut-prakriya/src/utils.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::prakriya::Prakriya; -use crate::term::Term; - -/// Processes a sliding window of terms where each term is non-empty. -pub fn xy_rule( - p: &mut Prakriya, - filter: impl Fn(&Term, &Term) -> bool, - op: impl Fn(&mut Prakriya, usize, usize), -) -> Option<()> { - let n = p.terms().len(); - for i in 0..n - 1 { - let j = p.find_next_where(i, |t| !t.is_empty())?; - - let x = p.get(i)?; - let y = p.get(j)?; - if filter(x, y) { - op(p, i, j); - } - } - Some(()) -} diff --git a/vidyut-prakriya/src/uttarapade.rs b/vidyut-prakriya/src/uttarapade.rs index 635ef16..d4287df 100644 --- a/vidyut-prakriya/src/uttarapade.rs +++ b/vidyut-prakriya/src/uttarapade.rs @@ -3,12 +3,12 @@ use crate::args::Artha; use crate::args::TaddhitaArtha; -use crate::operators as op; -use crate::prakriya::Prakriya; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::sounds as al; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -39,7 +39,16 @@ pub fn run(p: &mut Prakriya) -> Option<()> { let purva = p.get(i_purva)?; let uttara = p.get(i_uttara)?; - if purva.has_text("pAda") + if purva.has_text("mahat") + && (p.has_tag_in(&[T::Karmadharaya, T::Bahuvrihi]) || uttara.has_text("jAtIya")) + { + p.run_at("6.3.46", i_purva, |t| t.set_antya("A")); + } else if purva.has_text("hfdaya") + && (uttara.has_u_in(&["yat", "aR"]) || uttara.has_text_in(&["leKa", "lAsa"])) + { + // hflleKa, ... + p.run_at("6.3.50", i_purva, |t| t.set_text("hfd")); + } else if purva.has_text("pAda") && uttara.has_u("yat") && !p.has_artha(Artha::Taddhita(TaddhitaArtha::Tadarthye)) { diff --git a/vidyut-prakriya/src/vikarana.rs b/vidyut-prakriya/src/vikarana.rs index 35c7c79..04e80d9 100644 --- a/vidyut-prakriya/src/vikarana.rs +++ b/vidyut-prakriya/src/vikarana.rs @@ -17,14 +17,14 @@ // substitutions by lopa that block the prakarana. use crate::args::Gana::*; +use crate::core::errors::*; +use crate::core::operators as op; +use crate::core::Prakriya; +use crate::core::Tag as T; +use crate::core::Term; use crate::dhatu_gana::{DYUT_ADI, PUSH_ADI, TAN_ADI}; -use crate::errors::*; use crate::it_samjna; -use crate::operators as op; -use crate::prakriya::Prakriya; use crate::sounds::{s, Set}; -use crate::tag::Tag as T; -use crate::term::Term; use lazy_static::lazy_static; lazy_static! { @@ -80,7 +80,7 @@ fn maybe_replace_cli_with_ksa(p: &mut Prakriya, i: usize) -> Option<()> { let sprs = &["spfS", "mfS", "kfz", "tfp", "dfp"]; if xyz(p, i, |x, _, _| x.has_text_in(sprs)) { - if p.run_optional("3.1.44.v1", |p| op::upadesha_no_it(p, i + 1, "si~c")) { + if p.optional_run("3.1.44.v1", |p| op::upadesha_no_it(p, i + 1, "si~c")) { return None; } } @@ -103,7 +103,7 @@ fn maybe_replace_cli_with_ksa(p: &mut Prakriya, i: usize) -> Option<()> { let to_ksa = replace_with(i + 1, "ksa"); if dhatu.has_text("Sliz") && dhatu.has_gana(Divadi) { // aSlizat, aSlikzat - added = p.run_optional("3.1.46", to_ksa); + added = p.optional_run("3.1.46", to_ksa); } let to_ksa = replace_with(i + 1, "ksa"); @@ -119,7 +119,7 @@ fn maybe_replace_cli_with_ksa(p: &mut Prakriya, i: usize) -> Option<()> { if dhatu.has_text("dfS") { p.step("3.1.47") } else if dhatu.has_tag(T::Udit) { - p.run_optional("3.1.45", |p| { + p.optional_run("3.1.45", |p| { to_ksa(p); // Needed if we use "ksa" with a veT root. p.add_tag(T::FlagHasAnitKsa); @@ -152,7 +152,10 @@ fn maybe_replace_cli_with_can(p: &mut Prakriya, i: usize) -> Option<()> { p.run("3.1.48.v1", to_can); } else if dhatu.has_text_in(&["De", "Svi"]) { // adaDAt, aSiSviyat - p.run_optional("3.1.49", to_can); + p.optional_run("3.1.49", to_can); + } else if dhatu.has_u("gupU~") && p.is_chandasi() { + // ajuguputam + p.optional_run("3.1.50", to_can); } // TODO: 3.1.50 - 3.1.51 @@ -172,12 +175,7 @@ fn maybe_replace_cli_with_an(p: &mut Prakriya, i: usize) -> Option<()> { } else if dhatu.has_text_in(&["lip", "sic", "hve"]) { let mut skip = false; if tin.is_atmanepada() { - if p.is_allowed("3.1.54") { - p.step("3.1.54"); - skip = true; - } else { - p.decline("3.1.54") - } + skip = p.optional_run("3.1.54", |_| {}); } if !skip { p.run("3.1.53", to_an); @@ -204,13 +202,11 @@ fn maybe_replace_cli_with_an(p: &mut Prakriya, i: usize) -> Option<()> { // SAsu~\\ (ASAste) is not part of the rule. (KV) p.run("3.1.56", to_an); } else if is_parasmai && dhatu.has_tag(T::irit) { - p.run_optional("3.1.57", to_an); + p.optional_run("3.1.57", to_an); } else if is_parasmai && dhatu.has_text_in(&jr_stambhu) { - p.run_optional("3.1.58", to_an); - } else if is_parasmai - && dhatu.has_text_in(&["kf", "mf", "df", "ruh"]) - && p.has_tag(T::Chandasi) - { + p.optional_run("3.1.58", to_an); + } else if dhatu.has_u_in(&["qukf\\Y", "mf\\N", "dF", "ru\\ha~"]) && p.is_chandasi() { + // akarat, amarat, ... p.run("3.1.59", to_an); } } @@ -241,7 +237,7 @@ fn maybe_replace_cli_with_cin(p: &mut Prakriya, i: usize) -> Option<()> { "o~pyAyI~\\", ]) { // adIpi, ajani, aboDi, ... - p.run_optional("3.1.61", to_cin); + p.optional_run("3.1.61", to_cin); } else if p.has_tag(T::Karmani) { p.run("3.1.66", to_cin); } @@ -287,7 +283,7 @@ fn add_kr_bhu_or_as_after_am_pratyaya(p: &mut Prakriya) { let mut ran = false; if !ran { // corayAmbaBUva, ... - ran = p.run_optional("3.1.40:BU", |p| { + ran = p.optional_run("3.1.40:BU", |p| { let mut dhatu = Term::make_dhatu("BU", Bhvadi, None); dhatu.set_text("BU"); dhatu.add_tag(T::Dhatu); @@ -305,7 +301,7 @@ fn add_kr_bhu_or_as_after_am_pratyaya(p: &mut Prakriya) { } if !ran { // corayAmAsa, ... - ran = p.run_optional("3.1.40:as", |p| { + ran = p.optional_run("3.1.40:as", |p| { let mut dhatu = Term::make_dhatu("asa~", Adadi, None); dhatu.set_text("as"); dhatu.add_tag(T::Dhatu); @@ -357,7 +353,7 @@ pub fn try_add_am_pratyaya_for_lit(p: &mut Prakriya) -> Option<()> { p.run("3.1.37", add_aam); } else if dhatu.has_text_in(&["uz", "jAgf"]) || (dhatu.has_text("vid") && dhatu.has_gana(Adadi)) { - let used = p.run_optional("3.1.38", add_aam); + let used = p.optional_run("3.1.38", add_aam); if used { let dhatu = p.get(i)?; if dhatu.has_text("vid") { @@ -373,7 +369,7 @@ pub fn try_add_am_pratyaya_for_lit(p: &mut Prakriya) -> Option<()> { aam.add_tags(&[T::Pratyaya, T::Slu]); p.insert_after(i, aam); }; - if !p.run_optional("3.1.39", add_sluvat_am) { + if !p.optional_run("3.1.39", add_sluvat_am) { return None; } } else { @@ -397,7 +393,7 @@ fn maybe_add_am_pratyaya_for_lot(p: &mut Prakriya) { }; if p.has(i, |t| t.has_text("vid") && t.has_gana(Adadi) && is_lot) { - let added_am = p.run_optional("3.1.41", add_aam); + let added_am = p.optional_run("3.1.41", add_aam); if added_am { // Derive by nipAtana @@ -431,7 +427,7 @@ fn add_sarvadhatuka_vikarana(p: &mut Prakriya) -> Option<()> { if dhatu.has_text_in(&[ "BrAS", "BlAS", "Bram", "kram", "klam", "tras", "truw", "laz", ]) { - let applied = p.run_optional("3.1.70", add_vikarana("Syan")); + let applied = p.optional_run("3.1.70", add_vikarana("Syan")); // Needed to make 3.1.69 available to roots like Bram if !applied && p.has(i, |t| t.has_gana(Divadi)) { @@ -440,19 +436,19 @@ fn add_sarvadhatuka_vikarana(p: &mut Prakriya) -> Option<()> { } else if dhatu.has_u("yasu~") { if !has_upasarga { // yasyati, yasati - divadi_declined = !p.run_optional("3.1.71", add_vikarana("Syan")); + divadi_declined = !p.optional_run("3.1.71", add_vikarana("Syan")); } else if i > 0 && p.has(i - 1, |t| t.has_u("sam")) { // saMyasyati, saMyasati - divadi_declined = !p.run_optional("3.1.72", add_vikarana("Syan")); + divadi_declined = !p.optional_run("3.1.72", add_vikarana("Syan")); } } else if dhatu.has_u("akzU~") { // akzRoti, akzati - p.run_optional("3.1.75", add_vikarana("Snu")); + p.optional_run("3.1.75", add_vikarana("Snu")); } else if dhatu.has_u("takzU~") { // takzRoti, takzati - p.run_optional("3.1.76", add_vikarana("Snu")); + p.optional_run("3.1.76", add_vikarana("Snu")); } else if dhatu.has_u_in(&stanbhu_stunbhu) { - p.run_optional("3.1.82", add_vikarana("Snu")); + p.optional_run("3.1.82", add_vikarana("Snu")); } if p.find_first(T::Vikarana).is_some() { @@ -511,35 +507,25 @@ fn maybe_sic_lopa_before_parasmaipada( let dhatu = p.get(i)?; if dhatu.has_text_in(&["GrA", "De", "So", "Co", "so"]) { let code = "2.4.78"; - // De takes luk by 2.4.77, so 2.4.78 allows aluk. if dhatu.has_text("De") { - if p.is_allowed(code) { - p.step(code); + // De takes luk by 2.4.77, so 2.4.78 allows aluk. + if p.optional_run(code, |_| {}) { return None; - } else { - p.decline(code); } - } else { + } else if p.optional_run_at(code, i_vikarana, op::luk) { // The other roots avoid luk by default, so 2.4.78 allows luk. - if p.is_allowed(code) { - p.run_at(code, i_vikarana, op::luk); - return None; - } else { - p.decline(code); - } + return None; } } - let gati_stha = |t: &Term| { + // Run only if aluk was not used above. + if p.has(i, |t| { (t.has_text("gA") && t.has_gana(Adadi)) || t.has_text("sTA") || t.has_tag(T::Ghu) || (t.has_text("pA") && t.has_gana(Bhvadi)) || t.has_text("BU") - }; - - // Run only if aluk was not used above. - if p.has(i, gati_stha) { + }) { p.run_at("2.4.77", i_vikarana, op::luk); } @@ -556,7 +542,7 @@ fn maybe_sic_lopa_for_tanadi_atmanepada( let tin = p.get(i_tin)?; if dhatu.has_u_in(TAN_ADI) && tin.has_text_in(&["ta", "TAs"]) { // atata, ataTAH - p.run_optional_at("2.4.79", i_vikarana, op::luk); + p.optional_run_at("2.4.79", i_vikarana, op::luk); } Some(()) @@ -589,6 +575,12 @@ fn try_pratyaya_lopa(p: &mut Prakriya) -> Option<()> { } pub fn run(p: &mut Prakriya) -> Result<()> { + // Skip if a vikarana is already present, e.g. when adding a subanta to a krdanta that has + // already been created. + if p.find_first(T::Vikarana).is_some() { + return Ok(()); + } + let tin = match p.terms().last() { Some(t) => t, None => return Ok(()), diff --git a/vidyut-prakriya/src/wasm.rs b/vidyut-prakriya/src/wasm.rs index 9a769cf..d06a750 100644 --- a/vidyut-prakriya/src/wasm.rs +++ b/vidyut-prakriya/src/wasm.rs @@ -11,9 +11,9 @@ Although these bindings are usable and reliable, we want to improve their ergono JavaScript callers can use them more idiomatically. */ use crate::args::*; +use crate::core::Rule; +use crate::core::{Prakriya, Step}; use crate::dhatupatha::Dhatupatha; -use crate::prakriya::Rule; -use crate::prakriya::{Prakriya, Step}; use serde::Serialize; extern crate console_error_panic_hook; @@ -56,7 +56,7 @@ impl Rule { Self::Kashika(s) => format!("kAzikA {s}"), Self::Linganushasana(s) => format!("liNgA {s}"), Self::Kaumudi(s) => format!("kOmudI {s}"), - Self::UP(s) => format!("uRAdi {s}"), + Self::Unadipatha(s) => format!("uRAdi {s}"), } } } @@ -133,7 +133,7 @@ impl Vidyut { prayoga: Prayoga, purusha: Purusha, vacana: Vacana, - pada: Option, + pada: Option, sanadi: Option, upasarga: Option, ) -> JsValue { @@ -177,7 +177,7 @@ impl Vidyut { .expect("should be well-formed"); let a = Ashtadhyayi::new(); - let pratipadika = Pratipadika::new(pratipadika); + let pratipadika = Pratipadika::from(pratipadika); let prakriyas = a.derive_subantas(&pratipadika, &args); let web_prakriyas = to_web_prakriyas(&prakriyas); diff --git a/vidyut-prakriya/temp.txt b/vidyut-prakriya/temp.txt new file mode 100644 index 0000000..104942f --- /dev/null +++ b/vidyut-prakriya/temp.txt @@ -0,0 +1,13 @@ +1.4.18 --> SrI + e +7.3.112 --> SrI + Aw + e +1.3.3 --> SrI + Aw + e +1.3.9 --> SrI + A + e +6.4.77 --> Sriy + A + e +6.1.90 --> Sriy + + E +debug --> ==== Tripadi ==== +[Accept(Ashtadhyayi("1.4.6")), Accept(Ashtadhyayi("1.4.6"))] + +1.4.18 --> SrI + e +6.4.77 --> Sriy + e +debug --> ==== Tripadi ==== +[Decline(Ashtadhyayi("1.4.6")), Decline(Ashtadhyayi("1.4.6"))] diff --git a/vidyut-prakriya/test_utils/src/lib.rs b/vidyut-prakriya/test_utils/src/lib.rs index fc21113..7117ec9 100644 --- a/vidyut-prakriya/test_utils/src/lib.rs +++ b/vidyut-prakriya/test_utils/src/lib.rs @@ -8,6 +8,8 @@ extern crate vidyut_prakriya; use vidyut_prakriya::args::Antargana; use vidyut_prakriya::args::Purusha as P; +use vidyut_prakriya::args::SamasaPada; +use vidyut_prakriya::args::SamasaType::*; use vidyut_prakriya::args::Vacana::*; use vidyut_prakriya::args::Vibhakti::*; use vidyut_prakriya::args::*; @@ -41,6 +43,75 @@ impl Tester { } } + /// Core derivation methods + /// ----------------------- + + /// Derives tinantas from the given initial conditions. + fn derive_tinantas(&self, dhatu: &Dhatu, args: &TinantaArgs) -> Vec { + self.ashtadhyayi.derive_tinantas(dhatu, args) + } + + /// Derives tinantas from the given initial conditions. + fn derive_subantas(&self, p: &Pratipadika, args: &SubantaArgs) -> Vec { + self.ashtadhyayi.derive_subantas(p, args) + } + + fn derive_krdantas(&self, dhatu: &Dhatu, args: &KrdantaArgs) -> Vec { + self.ashtadhyayi.derive_krdantas(dhatu, args) + } + + /// Derives taddhitantas from the given initial conditions. + fn derive_taddhitantas(&self, p: &Pratipadika, args: &TaddhitantaArgs) -> Vec { + self.ashtadhyayi.derive_taddhitantas(p, args) + } + + /// Derives samasas from the given initial conditions. + fn derive_stryantas(&self, p: &Pratipadika) -> Vec { + self.ashtadhyayi.derive_stryantas(p) + } + + /// Derives samasas from the given initial conditions. + fn derive_samasas(&self, args: &SamasaArgs) -> Vec { + self.ashtadhyayi.derive_samasas(args) + } + + /// Derives vakyas from the given initial conditions. + fn derive_vakyas(&self, padas: &[Pada]) -> Vec { + self.ashtadhyayi.derive_vakyas(padas) + } + + /// Creation methods + /// ---------------- + + pub fn create_sup( + &self, + expected: &str, + prati: &Pratipadika, + linga: Linga, + vibhakti: Vibhakti, + vacana: Vacana, + ) -> Pada { + let args = SubantaArgs::builder() + .linga(linga) + .vibhakti(vibhakti) + .vacana(vacana) + .build() + .unwrap(); + let prakriyas = self.derive_subantas(prati, &args); + for p in prakriyas.iter() { + if p.text() == expected { + let pada: Option = p.into(); + return pada.unwrap(); + } + } + print_all_prakriyas(&prakriyas); + let alts: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + panic!("Could not create \"{}\". Alternatives: {alts:?}", expected); + } + + /// Core assertion methods + /// ---------------------- + /// Asserts that the given input conditions produce the tinantas `expected`. fn assert_has_tin( &self, @@ -58,11 +129,8 @@ impl Tester { .lakara(lakara) .build() .unwrap(); - let actual = derive_tinantas( - &self.ashtadhyayi, - &dhatu.clone().with_prefixes(prefixes), - &args, - ); + let actual = self.derive_tinantas(&dhatu.clone().with_prefixes(prefixes), &args); + let actual = sanitize_results(actual); assert_padas(actual, expected); } @@ -81,14 +149,11 @@ impl Tester { .purusha(purusha) .vacana(vacana) .lakara(lakara) - .pada(Pada::Parasmai) + .pada(DhatuPada::Parasmai) .build() .unwrap(); - let actual = derive_tinantas( - &self.ashtadhyayi, - &dhatu.clone().with_prefixes(prefixes), - &args, - ); + let actual = self.derive_tinantas(&dhatu.clone().with_prefixes(prefixes), &args); + let actual = sanitize_results(actual); assert_padas(actual, expected); } @@ -107,14 +172,11 @@ impl Tester { .purusha(purusha) .vacana(vacana) .lakara(lakara) - .pada(Pada::Atmane) + .pada(DhatuPada::Atmane) .build() .unwrap(); - let actual = derive_tinantas( - &self.ashtadhyayi, - &dhatu.clone().with_prefixes(prefixes), - &args, - ); + let actual = self.derive_tinantas(&dhatu.clone().with_prefixes(prefixes), &args); + let actual = sanitize_results(actual); assert_padas(actual, expected); } @@ -135,233 +197,382 @@ impl Tester { .lakara(lakara) .build() .unwrap(); - let actual = derive_tinantas( - &self.ashtadhyayi, - &dhatu.clone().with_prefixes(prefixes), - &args, - ); + let actual = self.derive_tinantas(&dhatu.clone().with_prefixes(prefixes), &args); + let actual = sanitize_results(actual); assert_padas(actual, expected); } + fn assert_has_sup( + &self, + prati: &Pratipadika, + linga: Linga, + vibhakti: Vibhakti, + vacana: Vacana, + expected: &[&str], + ) { + let args = SubantaArgs::builder() + .linga(linga) + .vacana(vacana) + .vibhakti(vibhakti) + .build() + .unwrap(); + let prakriyas = self.derive_subantas(prati, &args); + let actual = sanitize_results(prakriyas); + assert_padas(actual, expected); + } + + fn assert_has_vakya(&self, padas: &[Pada], expected: &[&str]) { + let prakriyas = self.ashtadhyayi.derive_vakyas(padas); + let prakriyas = sanitize_results(prakriyas); + + let expected: Vec<_> = expected.iter().map(|text| text.replace(" ", "")).collect(); + let actuals: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + assert_results(&expected, &actuals, prakriyas); + } + + /// Fine-grained assertion methods + /// ------------------------------ + /// Asserts that the given input conditions produce the prathamA-eka tinantas in `expected` - fn assert_has_lakara(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_tin(prefixes, dhatu, la, P::Prathama, Eka, expected); + fn assert_has_lakara(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_tin(prefixes, d, la, P::Prathama, Eka, expected); } - pub fn assert_has_tip(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Prathama, Eka, expected); + pub fn assert_has_tip(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Prathama, Eka, expected); } - pub fn assert_has_tas(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Prathama, Dvi, expected); + pub fn assert_has_tas(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Prathama, Dvi, expected); } - pub fn assert_has_jhi(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Prathama, Bahu, expected); + pub fn assert_has_jhi(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Prathama, Bahu, expected); } - pub fn assert_has_sip(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Madhyama, Eka, expected); + pub fn assert_has_sip(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Madhyama, Eka, expected); } - pub fn assert_has_thas(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Madhyama, Dvi, expected); + pub fn assert_has_thas(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Madhyama, Dvi, expected); } - pub fn assert_has_tha(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Madhyama, Bahu, expected); + pub fn assert_has_tha(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Madhyama, Bahu, expected); } - pub fn assert_has_mip(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Uttama, Eka, expected); + pub fn assert_has_mip(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Uttama, Eka, expected); } - pub fn assert_has_vas(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Uttama, Dvi, expected); + pub fn assert_has_vas(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Uttama, Dvi, expected); } - pub fn assert_has_mas(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_parasmai_tin(prefixes, dhatu, la, P::Uttama, Bahu, expected); + pub fn assert_has_mas(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_parasmai_tin(prefixes, d, la, P::Uttama, Bahu, expected); } - pub fn assert_has_ta(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Prathama, Eka, expected); + pub fn assert_has_ta(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Prathama, Eka, expected); } - pub fn assert_has_aataam( - &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, - expected: &[&str], - ) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Prathama, Dvi, expected); + pub fn assert_has_aataam(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Prathama, Dvi, expected); } - pub fn assert_has_jha(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Prathama, Bahu, expected); + pub fn assert_has_jha(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Prathama, Bahu, expected); } - pub fn assert_has_thaas( - &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, - expected: &[&str], - ) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Madhyama, Eka, expected); + pub fn assert_has_thaas(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Madhyama, Eka, expected); } - pub fn assert_has_aathaam( - &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, - expected: &[&str], - ) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Madhyama, Dvi, expected); + pub fn assert_has_aathaam(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Madhyama, Dvi, expected); + } + + pub fn assert_has_dhvam(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Madhyama, Bahu, expected); + } + + pub fn assert_has_iw(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Uttama, Eka, expected); + } + + pub fn assert_has_vahi(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Uttama, Dvi, expected); } - pub fn assert_has_dhvam( + pub fn assert_has_mahin(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_atmane_tin(prefixes, d, la, P::Uttama, Bahu, expected); + } + + pub fn assert_has_ta_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Prathama, Eka, expected); + } + + pub fn assert_has_aataam_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Prathama, Dvi, expected); + } + + pub fn assert_has_jha_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Prathama, Bahu, expected); + } + + pub fn assert_has_thaas_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Madhyama, Eka, expected); + } + + pub fn assert_has_aathaam_k( &self, prefixes: &[&str], - dhatu: &Dhatu, + d: &Dhatu, la: Lakara, expected: &[&str], ) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Madhyama, Bahu, expected); + self.assert_has_karmani_tin(prefixes, d, la, P::Madhyama, Dvi, expected); + } + + pub fn assert_has_dhvam_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Madhyama, Bahu, expected); + } + + pub fn assert_has_iw_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Uttama, Eka, expected); } - pub fn assert_has_iw(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Uttama, Eka, expected); + pub fn assert_has_vahi_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Uttama, Dvi, expected); } - pub fn assert_has_vahi(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Uttama, Dvi, expected); + pub fn assert_has_mahin_k(&self, prefixes: &[&str], d: &Dhatu, la: Lakara, expected: &[&str]) { + self.assert_has_karmani_tin(prefixes, d, la, P::Uttama, Bahu, expected); } - pub fn assert_has_mahin( + pub fn assert_has_krt( &self, prefixes: &[&str], dhatu: &Dhatu, - la: Lakara, + krt: impl Into, expected: &[&str], ) { - self.assert_has_atmane_tin(prefixes, dhatu, la, P::Uttama, Bahu, expected); + let args = KrdantaArgs::builder().krt(krt.into()).build().unwrap(); + let mut prakriyas = self.derive_krdantas(&dhatu.clone().with_prefixes(prefixes), &args); + prakriyas.sort_by_key(|p| p.text()); + prakriyas.dedup_by_key(|p| p.text()); + // Allowed in pada sandhi, but noisy here. + prakriyas.retain(|p| !p.text().contains("cS")); + + assert_padas(prakriyas, expected); } - pub fn assert_has_ta_k(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Prathama, Eka, expected); + pub fn assert_has_samasas(&self, args: &SamasaArgs, expected: &[&str]) { + let mut prakriyas = self.derive_samasas(&args); + prakriyas.sort_by_key(|p| p.text()); + prakriyas.dedup_by_key(|p| p.text()); + assert_padas(prakriyas, expected); } - pub fn assert_has_aataam_k( + /// A simpler interface to `assert_has_samasas` that accepts exactly two items. + fn assert_samasa_of_type( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + padas: &[SamasaPada], + samasa_type: SamasaType, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Prathama, Dvi, expected); + let args = SamasaArgs::builder() + .padas(Vec::from(padas)) + .samasa_type(samasa_type) + .build() + .unwrap(); + let t = Tester::default(); + t.assert_has_samasas(&args, expected); } - pub fn assert_has_jha_k( + fn assert_has_bahuvrihi( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Prathama, Bahu, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Prathama), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Bahuvrihi, + expected, + ); } - pub fn assert_has_thaas_k( + fn assert_has_avyayibhava( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Madhyama, Eka, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::avyaya(a.to_p()), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Avyayibhava, + expected, + ); } - pub fn assert_has_aathaam_k( + fn assert_has_karmadharaya( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Madhyama, Dvi, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Prathama), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Karmadharaya, + expected, + ); } - pub fn assert_has_dhvam_k( + fn assert_has_dvitiya_tatpurusha( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Madhyama, Bahu, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Dvitiya), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); } - pub fn assert_has_iw_k(&self, prefixes: &[&str], dhatu: &Dhatu, la: Lakara, expected: &[&str]) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Uttama, Eka, expected); + fn assert_has_trtiya_tatpurusha( + &self, + a: impl IntoPratipadika, + b: impl IntoPratipadika, + expected: &[&str], + ) { + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Trtiya), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); } - pub fn assert_has_vahi_k( + fn assert_has_caturthi_tatpurusha( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Uttama, Dvi, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Caturthi), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); } - pub fn assert_has_mahin_k( + fn assert_has_panchami_tatpurusha( &self, - prefixes: &[&str], - dhatu: &Dhatu, - la: Lakara, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - self.assert_has_karmani_tin(prefixes, dhatu, la, P::Uttama, Bahu, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Panchami), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); } - fn assert_has_sup( + fn assert_has_sasthi_tatpurusha( &self, - pratipadika: &Pratipadika, - linga: Linga, - vibhakti: Vibhakti, - vacana: Vacana, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - let args = SubantaArgs::builder() - .linga(linga) - .vacana(vacana) - .vibhakti(vibhakti) - .build() - .unwrap(); - - let results = self.ashtadhyayi.derive_subantas(pratipadika, &args); - let actual = sanitize_results(results); - assert_padas(actual, expected); + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Sasthi), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); } - pub fn assert_has_krt( + fn assert_has_saptami_tatpurusha( &self, - prefixes: &[&str], - dhatu: &Dhatu, - krt: impl Into, + a: impl IntoPratipadika, + b: impl IntoPratipadika, expected: &[&str], ) { - let args = KrdantaArgs::builder().krt(krt.into()).build().unwrap(); - let actual = derive_krdantas( - &self.ashtadhyayi, - &dhatu.clone().with_prefixes(prefixes), - args, + self.assert_samasa_of_type( + &[ + SamasaPada::new(a.to_p(), Vibhakti::Saptami), + SamasaPada::new(b.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, ); - assert_padas(actual, expected); + } + + /// Derives taddhitantas from the given initial conditions. + fn derive_artha_taddhitantas( + &self, + p: &Pratipadika, + t: Taddhita, + a: Option, + ) -> Vec { + let args = if let Some(a) = a { + TaddhitantaArgs::builder() + .taddhita(t) + .artha(a) + .build() + .unwrap() + } else { + TaddhitantaArgs::builder().taddhita(t).build().unwrap() + }; + let results = self.derive_taddhitantas(p, &args); + sanitize_results(results) + } + + pub fn assert_has_artha_taddhita( + &self, + prati: &str, + requested_artha: TaddhitaArtha, + t: Taddhita, + expected: &[&str], + ) { + let pratipadika = Pratipadika::from(prati); + let mut prakriyas = self.derive_artha_taddhitantas(&pratipadika, t, Some(requested_artha)); + prakriyas.retain(|p| { + if let Some(Artha::Taddhita(prakriya_artha)) = p.artha() { + requested_artha.is_type_of(prakriya_artha) + } else { + false + } + }); + assert_padas(prakriyas, expected); } } @@ -391,10 +602,182 @@ fn sanitize_results(mut results: Vec) -> Vec { .collect() } -/// Derives tinantas from the given initial conditions. -fn derive_tinantas(a: &Ashtadhyayi, dhatu: &Dhatu, args: &TinantaArgs) -> Vec { - let results = a.derive_tinantas(dhatu, args); - sanitize_results(results) +pub fn create_pratipadika(text: &str, prakriyas: &[Prakriya]) -> Pratipadika { + for p in prakriyas.iter() { + if p.text() == text { + let prati: Option = p.into(); + return prati.unwrap(); + } + } + print_all_prakriyas(&prakriyas); + let alts: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + panic!("Could not create \"{}\". Alternatives: {alts:?}", text); +} + +pub fn create_pada(text: &str, prakriyas: &[Prakriya]) -> Pada { + for p in prakriyas.iter() { + if p.text() == text { + let pada: Option = p.into(); + return pada.unwrap(); + } + } + print_all_prakriyas(&prakriyas); + let alts: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + panic!("Could not create \"{}\". Alternatives: {alts:?}", text); +} + +/// Creates a krdanta as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_krdanta( + text: &str, + prefixes: &[&str], + d: &Dhatu, + krt: impl Into, +) -> Pratipadika { + let args = KrdantaArgs::builder().krt(krt).build().unwrap(); + let d = d.clone().with_prefixes(prefixes); + + let tester = Tester::default(); + let prakriyas = tester.derive_krdantas(&d, &args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a krdanta as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_upapada_krdanta( + text: &str, + upapada: &str, + prefixes: &[&str], + d: &Dhatu, + krt: impl Into, +) -> Pratipadika { + let args = KrdantaArgs::builder() + .krt(krt) + .upapada(Upapada::make_subanta(upapada)) + .build() + .unwrap(); + let d = d.clone().with_prefixes(prefixes); + + let tester = Tester::default(); + let prakriyas = tester.derive_krdantas(&d, &args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a krdanta as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_taddhitanta( + text: &str, + base: impl IntoPratipadika, + taddhita: Taddhita, +) -> Pratipadika { + let args = TaddhitantaArgs::builder() + .taddhita(taddhita) + .build() + .unwrap(); + + let tester = Tester::default(); + let prakriyas = tester.derive_taddhitantas(&base.to_p(), &args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a krdanta as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_stryanta(text: &str, base: &str) -> Pratipadika { + let tester = Tester::default(); + let prakriyas = tester.derive_stryantas(&Pratipadika::from(base)); + create_pratipadika(text, &prakriyas) +} + +/// Creates a samasa as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_samasa(text: &str, items: &[&str], samasa_type: SamasaType) -> Pratipadika { + let padas: Vec<_> = items + .iter() + .map(|s| { + let prati = s.to_p(); + SamasaPada::new(prati, Vibhakti::Prathama) + }) + .collect(); + let args = SamasaArgs::builder() + .padas(padas) + .samasa_type(samasa_type) + .build() + .unwrap(); + + let tester = Tester::default(); + let prakriyas = tester.derive_samasas(&args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a samasa as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_avyaya_tatpurusha( + text: &str, + first: impl IntoPratipadika, + second: impl IntoPratipadika, +) -> Pratipadika { + let padas = vec![ + SamasaPada::avyaya(first.to_p()), + SamasaPada::new(second.to_p(), Vibhakti::Prathama), + ]; + let args = SamasaArgs::builder() + .padas(padas) + .samasa_type(Tatpurusha) + .build() + .unwrap(); + + let tester = Tester::default(); + let prakriyas = tester.derive_samasas(&args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a samasa as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_tatpurusha(text: &str, items: &[&str], vibhakti: Vibhakti) -> Pratipadika { + debug_assert!(items.len() == 2); + + let padas = vec![ + SamasaPada::new(Pratipadika::from(items[0]), vibhakti), + SamasaPada::new(Pratipadika::from(items[1]), Vibhakti::Prathama), + ]; + let args = SamasaArgs::builder() + .padas(padas) + .samasa_type(Tatpurusha) + .build() + .unwrap(); + + let tester = Tester::default(); + let prakriyas = tester.derive_samasas(&args); + create_pratipadika(text, &prakriyas) +} + +/// Creates a samasa as a pratipadika. +/// +/// This function is a shorthand that lets us test certain subanta forms more easily. +pub fn create_samasa_p(text: &str, pratis: &[Pratipadika], samasa_type: SamasaType) -> Pratipadika { + let padas: Vec<_> = pratis + .iter() + .map(|s| { + let prati = s.to_p(); + SamasaPada::new(prati, Vibhakti::Prathama) + }) + .collect(); + let args = SamasaArgs::builder() + .padas(padas) + .samasa_type(samasa_type) + .build() + .unwrap(); + + let tester = Tester::default(); + let prakriyas = tester.derive_samasas(&args); + create_pratipadika(text, &prakriyas) } /// Derives krdantas from the given initial conditions. @@ -409,24 +792,17 @@ fn derive_krdantas(a: &Ashtadhyayi, dhatu: &Dhatu, args: KrdantaArgs) -> Vec) -> Vec { - let args = if let Some(a) = a { - TaddhitantaArgs::builder() - .taddhita(t) - .artha(a) - .build() - .unwrap() - } else { - TaddhitantaArgs::builder().taddhita(t).build().unwrap() - }; - let a = Ashtadhyayi::new(); - let results = a.derive_taddhitantas(p, &args); + let tester = Tester::default(); + let results = tester.derive_artha_taddhitantas(p, t, a); sanitize_results(results) } /// Derives vakyas from the given initial conditions. fn derive_vakyas(first: &str, second: &str) -> Vec { - let a = Ashtadhyayi::new(); - let mut results = a.derive_vakyas(&first, &second); + let padas = vec![Pada::from_text(first), Pada::from_text(second)]; + + let tester = Tester::default(); + let mut results = tester.derive_vakyas(&padas); results.sort_by_key(|p| p.text()); results.dedup_by_key(|p| p.text()); results @@ -439,7 +815,7 @@ fn debug_text(rule: Rule) -> String { Rule::Kashika(x) => format!("kA {x}"), Rule::Kaumudi(x) => format!("kO {x}"), Rule::Linganushasana(x) => format!("Li {x}"), - Rule::UP(x) => format!("uRA {x}"), + Rule::Unadipatha(x) => format!("uRA {x}"), } } @@ -458,39 +834,49 @@ fn print_all_prakriyas(prakriyas: &[Prakriya]) { // -------------------- // These functions are too heavy for regular use. Instead, use the smaller assert functions below. -/// Asserts that the given `prakriyas` produce the `expected` results. -/// -/// If there is any difference, this function will nicely print out each prakriya in `prakriyas`. -fn assert_padas(prakriyas: Vec, expected: &[&str]) { - let actuals: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); +fn assert_results(expected: &[String], actuals: &[String], prakriyas: Vec) { + let mut expected = Vec::from(expected); + expected.sort(); + expected.dedup(); + + let mut actuals = Vec::from(actuals); + actuals.sort(); + actuals.dedup(); if actuals.len() != expected.len() { print_all_prakriyas(&prakriyas); } + // Before comparing, confirm lengths are the same. assert_eq!( actuals.len(), expected.len(), "expected: {expected:?}, actual: {actuals:?}" ); - let mut expected = Vec::from(expected); - expected.sort(); - expected.dedup(); - for (i, p) in prakriyas.iter().enumerate() { let actual = p.text(); if actual != expected[i] { print_all_prakriyas(&prakriyas); } + assert_eq!( actual, expected[i], - "expected: {expected:?}, actual: {actuals:?}" + "expected: {expected:?}, actual: {actual:?}" ); } } +/// Asserts that the given `prakriyas` produce the `expected` results. +/// +/// If there is any difference, this function will nicely print out each prakriya in `prakriyas`. +fn assert_padas(prakriyas: Vec, expected: &[&str]) { + let expected: Vec<_> = expected.iter().map(|t| t.to_string()).collect(); + let actuals: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + assert_results(&expected, &actuals, prakriyas); +} + /// Checks the given combination of `dhatu` and `prefixes` produces the `expected` results given /// this `lakara`/`purusha`/`vacana` combination. pub fn assert_has_tinanta( @@ -505,35 +891,17 @@ pub fn assert_has_tinanta( t.assert_has_tin(prefixes, dhatu, lakara, purusha, vacana, expected); } +pub fn assert_has_vakya(first: &Pada, second: &Pada, expected: &[&str]) { + let t = Tester::default(); + t.assert_has_vakya(&vec![first.to_owned(), second.to_owned()], expected); +} + pub fn assert_has_sandhi(first: &str, second: &str, expected: &[&str]) { let prakriyas = derive_vakyas(&first, &second); + let expected: Vec<_> = expected.iter().map(|text| text.replace(" ", "")).collect(); let actuals: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); - if actuals.len() != expected.len() { - print_all_prakriyas(&prakriyas); - } - - assert_eq!( - actuals.len(), - expected.len(), - "expected: {expected:?}, actual: {actuals:?}" - ); - - let mut expected: Vec<_> = expected.iter().map(|text| text.replace(" ", "")).collect(); - expected.sort(); - expected.dedup(); - - for (i, p) in prakriyas.iter().enumerate() { - let actual = p.text(); - - if actual != expected[i] { - print_all_prakriyas(&prakriyas); - } - assert_eq!( - actual, expected[i], - "expected: {expected:?}, actual: {actuals:?}" - ); - } + assert_results(&expected, &actuals, prakriyas); } // Dhatu helpers @@ -586,7 +954,7 @@ pub fn yan_luk(dhatu: &Dhatu) -> Dhatu { /// Shorthand for building a pratipadika. pub fn prati(text: &str) -> Pratipadika { - Pratipadika::new(text) + Pratipadika::from(text) } /// Shorthand for building a pratipadika that ends with NI/Ap. @@ -747,26 +1115,18 @@ pub fn assert_has_upapada_krdanta_raw( // Taddhitanta helpers // ------------------- -pub fn assert_has_taddhitanta(prati: &Pratipadika, t: Taddhita, expected: &[&str]) { - assert_padas(derive_taddhitantas(prati, t, None), expected); +pub fn assert_has_taddhitanta(prati: impl IntoPratipadika, t: Taddhita, expected: &[&str]) { + assert_padas(derive_taddhitantas(&prati.to_p(), t, None), expected); } pub fn assert_has_artha_taddhita( prati: &str, requested_artha: TaddhitaArtha, - t: Taddhita, + taddhita: Taddhita, expected: &[&str], ) { - let pratipadika = Pratipadika::new(prati); - let mut prakriyas = derive_taddhitantas(&pratipadika, t, Some(requested_artha)); - prakriyas.retain(|p| { - if let Some(Artha::Taddhita(prakriya_artha)) = p.artha() { - requested_artha.is_type_of(prakriya_artha) - } else { - false - } - }); - assert_padas(prakriyas, expected); + let t = Tester::default(); + t.assert_has_artha_taddhita(prati, requested_artha, taddhita, expected); } // Subanta helpers @@ -781,7 +1141,7 @@ pub fn assert_has_subantas_raw( vacana: Vacana, expected: &[&str], ) { - let pratipadika = Pratipadika::new(pratipadika_text); + let pratipadika = Pratipadika::from(pratipadika_text); let a = Ashtadhyayi::new(); let args = SubantaArgs::builder() .linga(linga) @@ -797,53 +1157,171 @@ pub fn assert_has_subantas_raw( assert_padas(actual, expected); } -pub trait Prati { +pub trait IntoPratipadika { fn to_p(self) -> Pratipadika; } -impl Prati for &Pratipadika { +impl IntoPratipadika for &Pratipadika { fn to_p(self) -> Pratipadika { self.clone() } } -impl Prati for &str { +impl IntoPratipadika for &str { fn to_p(self) -> Pratipadika { - Pratipadika::new(self) + Pratipadika::from(self) } } -macro_rules! test_sup { +macro_rules! assert_sup { ($fn_name:ident, $vibhakti:expr, $vacana:expr) => { - pub fn $fn_name(prati: impl Prati, linga: Linga, expected: &[&str]) { + pub fn $fn_name(prati: impl IntoPratipadika, linga: Linga, expected: &[&str]) { let t = Tester::default(); t.assert_has_sup(&prati.to_p(), linga, $vibhakti, $vacana, &expected); } }; } -// TODO: move these to Tester. -test_sup!(assert_has_sup_1s, Prathama, Eka); -test_sup!(assert_has_sup_1d, Prathama, Dvi); -test_sup!(assert_has_sup_1p, Prathama, Bahu); -test_sup!(assert_has_sup_2s, Dvitiya, Eka); -test_sup!(assert_has_sup_2d, Dvitiya, Dvi); -test_sup!(assert_has_sup_2p, Dvitiya, Bahu); -test_sup!(assert_has_sup_3s, Trtiya, Eka); -test_sup!(assert_has_sup_3d, Trtiya, Dvi); -test_sup!(assert_has_sup_3p, Trtiya, Bahu); -test_sup!(assert_has_sup_4s, Caturthi, Eka); -test_sup!(assert_has_sup_4d, Caturthi, Dvi); -test_sup!(assert_has_sup_4p, Caturthi, Bahu); -test_sup!(assert_has_sup_5s, Panchami, Eka); -test_sup!(assert_has_sup_5d, Panchami, Dvi); -test_sup!(assert_has_sup_5p, Panchami, Bahu); -test_sup!(assert_has_sup_6s, Sasthi, Eka); -test_sup!(assert_has_sup_6d, Sasthi, Dvi); -test_sup!(assert_has_sup_6p, Sasthi, Bahu); -test_sup!(assert_has_sup_7s, Saptami, Eka); -test_sup!(assert_has_sup_7d, Saptami, Dvi); -test_sup!(assert_has_sup_7p, Saptami, Bahu); -test_sup!(assert_has_sup_ss, Sambodhana, Eka); -test_sup!(assert_has_sup_sd, Sambodhana, Dvi); -test_sup!(assert_has_sup_sp, Sambodhana, Bahu); +assert_sup!(assert_has_sup_1s, Prathama, Eka); +assert_sup!(assert_has_sup_1d, Prathama, Dvi); +assert_sup!(assert_has_sup_1p, Prathama, Bahu); +assert_sup!(assert_has_sup_2s, Dvitiya, Eka); +assert_sup!(assert_has_sup_2d, Dvitiya, Dvi); +assert_sup!(assert_has_sup_2p, Dvitiya, Bahu); +assert_sup!(assert_has_sup_3s, Trtiya, Eka); +assert_sup!(assert_has_sup_3d, Trtiya, Dvi); +assert_sup!(assert_has_sup_3p, Trtiya, Bahu); +assert_sup!(assert_has_sup_4s, Caturthi, Eka); +assert_sup!(assert_has_sup_4d, Caturthi, Dvi); +assert_sup!(assert_has_sup_4p, Caturthi, Bahu); +assert_sup!(assert_has_sup_5s, Panchami, Eka); +assert_sup!(assert_has_sup_5d, Panchami, Dvi); +assert_sup!(assert_has_sup_5p, Panchami, Bahu); +assert_sup!(assert_has_sup_6s, Sasthi, Eka); +assert_sup!(assert_has_sup_6d, Sasthi, Dvi); +assert_sup!(assert_has_sup_6p, Sasthi, Bahu); +assert_sup!(assert_has_sup_7s, Saptami, Eka); +assert_sup!(assert_has_sup_7d, Saptami, Dvi); +assert_sup!(assert_has_sup_7p, Saptami, Bahu); +assert_sup!(assert_has_sup_ss, Sambodhana, Eka); +assert_sup!(assert_has_sup_sd, Sambodhana, Dvi); +assert_sup!(assert_has_sup_sp, Sambodhana, Bahu); + +macro_rules! create_sup { + ($fn_name:ident, $vibhakti:expr, $vacana:expr) => { + pub fn $fn_name(expected: &str, prati: impl IntoPratipadika, linga: Linga) -> Pada { + let t = Tester::default(); + t.create_sup(&expected, &prati.to_p(), linga, $vibhakti, $vacana) + } + }; +} + +create_sup!(create_sup_1s, Prathama, Eka); +create_sup!(create_sup_1d, Prathama, Dvi); +create_sup!(create_sup_1p, Prathama, Bahu); +create_sup!(create_sup_2s, Dvitiya, Eka); +create_sup!(create_sup_2d, Dvitiya, Dvi); +create_sup!(create_sup_2p, Dvitiya, Bahu); +create_sup!(create_sup_3s, Trtiya, Eka); +create_sup!(create_sup_3d, Trtiya, Dvi); +create_sup!(create_sup_3p, Trtiya, Bahu); +create_sup!(create_sup_4s, Caturthi, Eka); +create_sup!(create_sup_4d, Caturthi, Dvi); +create_sup!(create_sup_4p, Caturthi, Bahu); +create_sup!(create_sup_5s, Panchami, Eka); +create_sup!(create_sup_5d, Panchami, Dvi); +create_sup!(create_sup_5p, Panchami, Bahu); +create_sup!(create_sup_6s, Sasthi, Eka); +create_sup!(create_sup_6d, Sasthi, Dvi); +create_sup!(create_sup_6p, Sasthi, Bahu); +create_sup!(create_sup_7s, Saptami, Eka); +create_sup!(create_sup_7d, Saptami, Dvi); +create_sup!(create_sup_7p, Saptami, Bahu); +create_sup!(create_sup_ss, Sambodhana, Eka); +create_sup!(create_sup_sd, Sambodhana, Dvi); +create_sup!(create_sup_sp, Sambodhana, Bahu); + +macro_rules! assert_samasa { + ($fn_name:ident) => { + pub fn $fn_name( + purva: impl IntoPratipadika, + uttara: impl IntoPratipadika, + expected: &[&str], + ) { + let t = Tester::default(); + t.$fn_name(purva, uttara, expected); + } + }; +} + +assert_samasa!(assert_has_bahuvrihi); +assert_samasa!(assert_has_avyayibhava); +assert_samasa!(assert_has_karmadharaya); +assert_samasa!(assert_has_dvitiya_tatpurusha); +assert_samasa!(assert_has_trtiya_tatpurusha); +assert_samasa!(assert_has_caturthi_tatpurusha); +assert_samasa!(assert_has_panchami_tatpurusha); +assert_samasa!(assert_has_sasthi_tatpurusha); +assert_samasa!(assert_has_saptami_tatpurusha); + +pub fn assert_has_avyaya_tatpurusha( + first: impl IntoPratipadika, + second: impl IntoPratipadika, + expected: &[&str], +) { + let t = Tester::default(); + t.assert_samasa_of_type( + &[ + SamasaPada::avyaya(first.to_p()), + SamasaPada::new(second.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); +} + +pub fn assert_has_misc_tatpurusha( + first: impl IntoPratipadika, + second: impl IntoPratipadika, + expected: &[&str], +) { + let t = Tester::default(); + t.assert_samasa_of_type( + &[ + SamasaPada::new(first.to_p(), Vibhakti::Sasthi), + SamasaPada::new(second.to_p(), Vibhakti::Prathama), + ], + Tatpurusha, + expected, + ); +} + +pub fn assert_has_dvandva(items: &[&str], expected: &[&str]) { + let args = SamasaArgs::builder() + .padas( + items + .iter() + .map(|s| SamasaPada::new(Pratipadika::from(s), Vibhakti::Prathama)) + .collect(), + ) + .samasa_type(Dvandva) + .build() + .unwrap(); + let t = Tester::default(); + t.assert_has_samasas(&args, expected); +} + +pub fn assert_has_samahara_dvandva(items: &[&str], expected: &[&str]) { + let args = SamasaArgs::builder() + .padas( + items + .iter() + .map(|s| SamasaPada::new(Pratipadika::from(s), Vibhakti::Prathama)) + .collect(), + ) + .samasa_type(SamaharaDvandva) + .build() + .unwrap(); + let t = Tester::default(); + t.assert_has_samasas(&args, expected); +} diff --git a/vidyut-prakriya/tests/api.rs b/vidyut-prakriya/tests/api.rs index a6d02c3..b753d3a 100644 --- a/vidyut-prakriya/tests/api.rs +++ b/vidyut-prakriya/tests/api.rs @@ -36,7 +36,7 @@ fn derive_tinantas() { .purusha(Purusha::Prathama) .vacana(Vacana::Eka) .lakara(Lakara::Lat) - .pada(Pada::Parasmai) + .pada(DhatuPada::Parasmai) .build() .unwrap(); let prakriyas = a.derive_tinantas(&kr, &args_parasmai); @@ -49,7 +49,7 @@ fn derive_tinantas() { .purusha(Purusha::Prathama) .vacana(Vacana::Eka) .lakara(Lakara::Lat) - .pada(Pada::Atmane) + .pada(DhatuPada::Atmane) .build() .unwrap(); let prakriyas = a.derive_tinantas(&kr, &args_atmane); diff --git a/vidyut-prakriya/tests/kashika_1_1.rs b/vidyut-prakriya/tests/kashika_1_1.rs index 4ee5ed6..5bbe673 100644 --- a/vidyut-prakriya/tests/kashika_1_1.rs +++ b/vidyut-prakriya/tests/kashika_1_1.rs @@ -4,8 +4,11 @@ use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Pada; use vidyut_prakriya::args::Purusha as P; use vidyut_prakriya::args::Taddhita as T; +use vidyut_prakriya::args::TaddhitaArtha::*; +use vidyut_prakriya::args::Unadi; use vidyut_prakriya::args::Vacana::*; #[test] @@ -152,6 +155,51 @@ fn sutra_1_1_10() { // TODO: anaquham } +#[test] +fn sutra_1_1_11() { + let hari = create_sup_1d("harI", "hari", Pum); + let etau = create_sup_1d("etO", "etad", Pum); + assert_has_vakya(&hari, &etau, &["harI etO"]); +} + +#[test] +fn sutra_1_1_12() { + let ami = create_sup_1p("amI", "adas", Pum); + let amu = create_sup_1d("amU", "adas", Pum); + let atra = Pada::from_text("atra"); + let asate = Pada::from_text("Asate"); + + assert_has_vakya(&ami, &atra, &["amI atra"]); + assert_has_vakya(&ami, &asate, &["amI Asate"]); + assert_has_vakya(&amu, &atra, &["amU atra"]); + assert_has_vakya(&amu, &asate, &["amU Asate"]); + + // adasaH? + let shami = Pada::from_text("SamI"); + let dadimi = Pada::from_text("dAqimI"); + assert_has_vakya(&shami, &atra, &["Samyatra"]); + assert_has_vakya(&dadimi, &atra, &["dAqimyatra"]); + + // TODO: amuke +} + +#[test] +fn sutra_1_1_15() { + let aho = Pada::nipata("Aho"); + let utaho = Pada::nipata("utAho"); + let iti = Pada::from_text("iti"); + + assert_has_vakya(&aho, &iti, &["Aho iti"]); + assert_has_vakya(&utaho, &iti, &["utAho iti"]); +} + +#[test] +fn sutra_1_1_17_to_sutra_1_1_18() { + let un = Pada::nipata("uY"); + let iti = Pada::from_text("iti"); + assert_has_vakya(&un, &iti, &["u iti", "U~ iti", "viti"]); +} + #[test] fn sutra_1_1_20() { assert_has_tip( @@ -305,11 +353,21 @@ fn sutra_1_1_40() { assert_has_krdanta(&[], &d("qukf\\Y", Tanadi), Krt::ktvA, &["kftvA"]); assert_has_krdanta(&[], &d("hf\\Y", Bhvadi), Krt::ktvA, &["hftvA"]); // TODO: tosun + // kasun assert_has_krdanta(&["vi"], &d("sf\\px~", Tudadi), Krt::kasun, &["visfpas"]); assert_has_krdanta(&["AN"], &d("u~tfdi~^r", Rudhadi), Krt::kasun, &["Atfdas"]); } +#[test] +fn sutra_1_1_41() { + assert_has_avyayibhava("upa", "agni", &["upAgni"]); + assert_has_avyayibhava("prati", "agni", &["pratyagni"]); + assert_has_avyayibhava("upa", "payas", &["upapayaH"]); + + // TODO: others +} + #[test] fn sutra_1_1_42() { assert_has_sup_1p("kuRqa", Napumsaka, &["kuRqAni"]); @@ -334,6 +392,13 @@ fn sutra_1_1_43() { assert_has_sup_1d("veman", Napumsaka, &["vemanI", "vemnI"]); } +#[test] +fn sutra_1_1_44() { + let svi = d("wuo~Svi", Bhvadi); + assert_has_tip(&[], &svi, Lit, &["SuSAva", "SiSvAya"]); + assert_has_tas(&[], &svi, Lit, &["SuSuvatuH", "SiSviyatuH"]); +} + #[test] fn sutra_1_1_45() { let yaj = d("ya\\ja~^", Bhvadi); @@ -382,6 +447,37 @@ fn sutra_1_1_48() { // TODO: assert_has_sup_1s("atimAlA", Pum, &["atimAlaH"]); } +#[test] +fn sutra_1_1_49() { + let as_ = d("asa~", Adadi); + assert_has_krdanta(&[], &as_, Krt::tfc, &["Bavitf"]); + assert_has_krdanta(&[], &as_, Krt::tumun, &["Bavitum"]); + assert_has_krdanta(&[], &as_, Krt::tavya, &["Bavitavya"]); + + let bru = d("brUY", Adadi); + assert_has_krdanta(&[], &bru, Krt::tfc, &["vaktf"]); + assert_has_krdanta(&[], &bru, Krt::tumun, &["vaktum"]); + assert_has_krdanta(&[], &bru, Krt::tavya, &["vaktavya"]); +} + +#[test] +fn sutra_1_1_50() { + assert_has_sandhi("daRqa", "agram", &["daRqAgram"]); + assert_has_sandhi("yUpa", "agram", &["yUpAgram"]); + + // TODO: arthataH + + assert_has_krdanta(&[], &d("qupa\\ca~^z", Bhvadi), Krt::GaY, &["pAka"]); + assert_has_krdanta(&[], &d("tya\\ja~", Bhvadi), Krt::GaY, &["tyAga"]); + assert_has_krdanta(&[], &d("ra\\nja~^", Bhvadi), Krt::GaY, &["rAga", "raNga"]); + + assert_has_sup_4s("adas", Pum, &["amuzmE"]); + assert_has_sup_4d("adas", Pum, &["amUByAm"]); + + assert_has_sandhi("vAk", "hasati", &["vAg Gasati", "vAg hasati"]); + assert_has_sandhi("trizWup", "hasati", &["trizWub Basati", "trizWub hasati"]); +} + #[test] fn sutra_1_1_51() { assert_has_krdanta(&[], &d("qukf\\Y", Tanadi), Krt::tfc, &["kartf"]); @@ -406,6 +502,9 @@ fn sutra_1_1_55() { // Sit assert_has_sup_1p("kuRqa", Napumsaka, &["kuRqAni"]); assert_has_sup_2p("kuRqa", Napumsaka, &["kuRqAni"]); + + assert_has_krdanta(&[], &d("ci\\Y", Svadi), Krt::tfc, &["cetf"]); + assert_has_krdanta(&[], &d("zwu\\Y", Adadi), Krt::tfc, &["stotf"]); } #[test] @@ -477,6 +576,13 @@ fn sutra_1_1_59() { assert_has_lat(&[], &yan(&d("DmA\\", Bhvadi)), &["deDmIyate"]); } +#[test] +fn sutra_1_1_60() { + assert_has_artha_taddhita("goDA", TasyaApatyam, T::Qrak, &["gODera"]); + assert_has_jha(&[], &d("qupa\\ca~^z", Bhvadi), VidhiLin, &["paceran"]); + assert_has_krdanta(&[], &d("jIva~", Bhvadi), Unadi::radAnuk, &["jIradAnu"]); +} + #[test] fn sutra_1_1_61() { assert_has_tip(&[], &d("a\\da~", Adadi), Lat, &["atti"]); @@ -484,27 +590,47 @@ fn sutra_1_1_61() { // TODO: lup } +#[test] +fn sutra_1_1_64() { + assert_has_upapada_krdanta("agni", &[], &d("ci\\Y", Svadi), Krt::kvip, &["agnicit"]); + assert_has_upapada_krdanta("soma", &[], &d("zu\\Y", Svadi), Krt::kvip, &["somasut"]); + + let pac = d("qupa\\ca~^z", Bhvadi); + assert_has_aataam(&[], &pac, Lat, &["pacete"]); + assert_has_aathaam(&[], &pac, Lat, &["paceTe"]); +} + +#[test] +fn sutra_1_1_66() { + assert_has_sandhi("daDi", "udakam", &["daDyudakam"]); + assert_has_sandhi("maDu", "idam", &["maDvidam"]); + assert_has_sandhi("pacati", "odanam", &["pacatyodanam"]); + assert_has_sandhi("agnicit", "atra", &["agnicid atra"]); +} + +#[test] +fn skip_sutra_1_1_71() {} + #[test] fn sutra_1_1_73() { assert_has_taddhitanta(&nyap("SAlA"), T::Ca, &["SAlIya"]); assert_has_taddhitanta(&nyap("mAlA"), T::Ca, &["mAlIya"]); - assert_has_taddhitanta(&prati("Opagava"), T::Ca, &["OpagavIya"]); - assert_has_taddhitanta(&prati("kApawava"), T::Ca, &["kApawavIya"]); - // TODO: do others + assert_has_taddhitanta("Opagava", T::Ca, &["OpagavIya"]); + assert_has_taddhitanta("kApawava", T::Ca, &["kApawavIya"]); } #[test] fn sutra_1_1_74() { - assert_has_taddhitanta(&prati("tyad"), T::Ca, &["tyadIya"]); - assert_has_taddhitanta(&prati("tad"), T::Ca, &["tadIya"]); - assert_has_taddhitanta(&prati("etad"), T::Ca, &["etadIya"]); - assert_has_taddhitanta(&prati("idam"), T::Ca, &["idamIya"]); - assert_has_taddhitanta(&prati("adas"), T::Ca, &["adasIya"]); + assert_has_taddhitanta("tyad", T::Ca, &["tyadIya"]); + assert_has_taddhitanta("tad", T::Ca, &["tadIya"]); + assert_has_taddhitanta("etad", T::Ca, &["etadIya"]); + assert_has_taddhitanta("idam", T::Ca, &["idamIya"]); + assert_has_taddhitanta("adas", T::Ca, &["adasIya"]); // TODO: enable these. - // assert_has_taddhitanta(&prati("yuzmad"), T::Ca, &["tvadIya"]); - // assert_has_taddhitanta(&prati("yuzmad"), T::PiY, &["tvAdAyani"]); - // assert_has_taddhitanta(&prati("asmad"), T::Ca, &["madIya"]); - // assert_has_taddhitanta(&prati("asmad"), T::PiY, &["mAdAyani"]); - // assert_has_taddhitanta(&prati("Bavatu~"), T::Ca, &["BavadIya"]); - assert_has_taddhitanta(&prati("kim"), T::Ca, &["kimIya"]); + // assert_has_taddhitanta("yuzmad", T::Ca, &["tvadIya"]); + // assert_has_taddhitanta("yuzmad", T::PiY, &["tvAdAyani"]); + // assert_has_taddhitanta("asmad", T::Ca, &["madIya"]); + // assert_has_taddhitanta("asmad", T::PiY, &["mAdAyani"]); + // assert_has_taddhitanta("Bavatu~", T::Ca, &["BavadIya"]); + assert_has_taddhitanta("kim", T::Ca, &["kimIya"]); } diff --git a/vidyut-prakriya/tests/kashika_1_2.rs b/vidyut-prakriya/tests/kashika_1_2.rs index 2f64106..7fe9200 100644 --- a/vidyut-prakriya/tests/kashika_1_2.rs +++ b/vidyut-prakriya/tests/kashika_1_2.rs @@ -4,6 +4,7 @@ use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::*; #[test] @@ -463,6 +464,13 @@ fn sutra_1_2_41() { assert_has_upapada_krdanta("pAda", &[], &bhaj, Krt::Rvi, &["pAdaBAj"]); } +#[test] +fn sutra_1_2_42() { + assert_has_karmadharaya("parama", "rAjya", &["paramarAjya"]); + assert_has_karmadharaya("uttama", "rAjya", &["uttamarAjya"]); + // TODO: others +} + #[test] fn sutra_1_2_45() { assert_has_sup_1s("qitTa", Pum, &["qitTaH"]); @@ -474,6 +482,38 @@ fn sutra_1_2_45() { // TODO: others } +#[test] +fn sutra_1_2_46() { + let kr = d("qukf\\Y", Tanadi); + let hr = d("hf\\Y", Bhvadi); + + // krt + let karaka = create_krdanta("kAraka", &[], &kr, Krt::Rvul); + assert_has_sup_1s(&karaka, Pum, &["kArakaH"]); + let haraka = create_krdanta("hAraka", &[], &hr, Krt::Rvul); + assert_has_sup_1s(&haraka, Pum, &["hArakaH"]); + let kartr = create_krdanta("kartf", &[], &kr, Krt::tfc); + assert_has_sup_1s(&kartr, Pum, &["kartA"]); + let hartr = create_krdanta("hartf", &[], &hr, Krt::tfc); + assert_has_sup_1s(&hartr, Pum, &["hartA"]); + + // taddhita + let aupagava = create_taddhitanta("Opagava", "upagu", T::aR); + assert_has_sup_1s(&aupagava, Pum, &["OpagavaH"]); + let kapatava = create_taddhitanta("kApawava", "kapawu", T::aR); + assert_has_sup_1s(&kapatava, Pum, &["kApawavaH"]); + + // samasa + let rajapurusha = create_tatpurusha("rAjapuruza", &["rAjan", "puruza"], Vibhakti::Sasthi); + assert_has_sup_1s(&rajapurusha, Pum, &["rAjapuruzaH"]); + let brahmanakambala = create_tatpurusha( + "brAhmaRakambala", + &["brAhmaRa", "kambala"], + Vibhakti::Sasthi, + ); + assert_has_sup_1s(&brahmanakambala, Pum, &["brAhmaRakambalaH"]); +} + #[test] fn sutra_1_2_47() { assert_has_sup_1s("atirE", Napumsaka, &["atiri"]); diff --git a/vidyut-prakriya/tests/kashika_1_3.rs b/vidyut-prakriya/tests/kashika_1_3.rs index 8b05e3a..bbf4a60 100644 --- a/vidyut-prakriya/tests/kashika_1_3.rs +++ b/vidyut-prakriya/tests/kashika_1_3.rs @@ -119,6 +119,9 @@ fn sutra_1_3_8() { // assert_has_taddhitanta(&prati("vfkza"), T::kan, &["vfkzaka"]); } +#[test] +fn skip_sutra_1_3_9() {} + #[test] fn sutra_1_3_10() { use vidyut_prakriya::args::TaddhitaArtha::*; @@ -132,6 +135,9 @@ fn sutra_1_3_10() { // TODO: others } +#[test] +fn skip_sutra_1_3_11() {} + #[test] fn sutra_1_3_12() { // anudAttet diff --git a/vidyut-prakriya/tests/kashika_1_4.rs b/vidyut-prakriya/tests/kashika_1_4.rs index f228894..2f9abd1 100644 --- a/vidyut-prakriya/tests/kashika_1_4.rs +++ b/vidyut-prakriya/tests/kashika_1_4.rs @@ -7,14 +7,6 @@ use vidyut_prakriya::args::Linga::*; use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::*; -fn dhatu_prati(text: &str) -> Pratipadika { - Pratipadika::builder() - .text(text) - .is_dhatu(true) - .build() - .unwrap() -} - #[test] fn sutra_1_4_3() { // IkArAnta @@ -49,7 +41,7 @@ fn sutra_1_4_4() { #[test] fn sutra_1_4_5() { - let shri = dhatu_prati("SrI"); + let shri = create_krdanta("SrI", &[], &d("SriY", Bhvadi), Krt::kvip); assert_has_sup_6p(&shri, Stri, &["SriyAm", "SrIRAm"]); assert_has_sup_6p("BrU", Stri, &["BruvAm", "BrURAm"]); // astrI @@ -58,9 +50,11 @@ fn sutra_1_4_5() { #[test] fn sutra_1_4_6() { + let shri = create_krdanta("SrI", &[], &d("SriY", Bhvadi), Krt::kvip); + assert_has_sup_4s("kfti", Stri, &["kftyE", "kftaye"]); assert_has_sup_4s("Denu", Stri, &["DenvE", "Denave"]); - assert_has_sup_4s(&dhatu_prati("SrI"), Stri, &["SriyE", "Sriye"]); + assert_has_sup_4s(&shri, Stri, &["SriyE", "Sriye"]); assert_has_sup_4s("BrU", Stri, &["BruvE", "Bruve"]); // astrI assert_has_sup_4s("strI", Stri, &["striyE"]); @@ -143,6 +137,12 @@ fn sutra_1_4_16() { assert_has_taddhitanta(&prati("ftu"), T::Gas, &["ftviya"]); } +#[test] +fn skip_sutra_1_4_17() {} + +#[test] +fn skip_sutra_1_4_18() {} + #[test] fn sutra_1_4_19() { assert_has_taddhitanta(&prati("udaSvit"), T::matup, &["udaSvitvat"]); @@ -184,6 +184,9 @@ fn sutra_1_4_80() { assert_has_tip(&["tiras"], &d("qukf\\Y", Tanadi), Lat, &["tiraskaroti"]); } +#[test] +fn skip_sutra_1_4_99_to_sutra_1_4_104() {} + #[test] fn sutra_1_4_105() { let pac = d("qupa\\ca~^z", Bhvadi); @@ -213,3 +216,12 @@ fn sutra_1_4_109() { assert_has_sandhi("daDi", "atra", &["daDyatra"]); assert_has_sandhi("maDu", "atra", &["maDvatra"]); } + +#[test] +fn sutra_1_4_110() { + // TODO: ashtadhyayi.com has daDiM, maDuM -- why? + assert_has_sup_1s("daDi", Napumsaka, &["daDi"]); + assert_has_sup_1s("maDu", Napumsaka, &["maDu"]); + assert_has_sup_1s("vfkza", Pum, &["vfkzaH"]); + assert_has_sup_1s("plakza", Pum, &["plakzaH"]); +} diff --git a/vidyut-prakriya/tests/kashika_2_1.rs b/vidyut-prakriya/tests/kashika_2_1.rs new file mode 100644 index 0000000..f79d2d8 --- /dev/null +++ b/vidyut-prakriya/tests/kashika_2_1.rs @@ -0,0 +1,301 @@ +extern crate test_utils; +use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; +use vidyut_prakriya::args::Dhatu; +use vidyut_prakriya::args::Gana::*; +use vidyut_prakriya::args::Lakara::*; +use vidyut_prakriya::args::Pratipadika; + +pub fn create_kta(text: &str, prefixes: &[&str], d: &Dhatu) -> Pratipadika { + create_krdanta(text, prefixes, d, Krt::kta) +} + +#[test] +fn sutra_2_1_1() { + assert_has_dvitiya_tatpurusha("kazwa", "Srita", &["kazwaSrita"]); + assert_has_trtiya_tatpurusha("SaNkulA", "KaRqa", &["SaNkulAKaRqa"]); + assert_has_caturthi_tatpurusha("yUpa", "dAru", &["yUpadAru"]); + assert_has_panchami_tatpurusha("vfka", "Baya", &["vfkaBaya"]); + assert_has_sasthi_tatpurusha("rAjan", "puruza", &["rAjapuruza"]); + assert_has_saptami_tatpurusha("akza", "SORqa", &["akzaSORqa"]); +} + +#[test] +fn skip_sutra_2_1_3() {} + +#[test] +fn sutra_2_1_4() { + assert_has_tip(&["anu", "vi"], &d("cala~", Bhvadi), Lan, &["anuvyacalat"]); + assert_has_tip(&["anu", "pra"], &d("vfzu~", Bhvadi), Lan, &["anuprAvarzat"]); +} + +#[test] +fn sutra_2_1_5() { + assert_has_avyayibhava("yaTA", "vfdDa", &["yaTAvfdDam"]); +} + +#[ignore] +#[test] +fn sutra_2_1_6() { + // TODO: Kashika seems to have typos on ashtadhyayi.com -- double check these. + assert_has_avyayibhava("aDi", "strI", &["aDistri"]); + assert_has_avyayibhava("aDi", "kumArI", &["aDikumAri"]); + assert_has_avyayibhava("upa", "kumBa", &["upakumBam"]); + assert_has_avyayibhava("upa", "maRika", &["upamaRikam"]); + assert_has_avyayibhava("su", "madra", &["sumadram"]); + assert_has_avyayibhava("su", "magaDa", &["sumagaDam"]); + assert_has_avyayibhava("dur", "gavadika", &["durgavadikam"]); + assert_has_avyayibhava("dur", "yavana", &["duryavanam"]); + assert_has_avyayibhava("nir", "makzika", &["nirmakzikam"]); + assert_has_avyayibhava("nir", "maSaka", &["nirmaSakam"]); + assert_has_avyayibhava("ati", "hima", &["atihimam"]); + assert_has_avyayibhava("nir", "hima", &["nirhimam"]); + assert_has_avyayibhava("nir", "SIta", &["niHSItam", "niSSItam"]); + assert_has_avyayibhava("ati", "tEsfka", &["atitEsfkam"]); + assert_has_avyayibhava("tad", "pARini", &["tatpARini"]); + assert_has_avyayibhava("anu", "raTa", &["anuraTam"]); + assert_has_avyayibhava("prati", "arTa", &["pratyarTam"]); + assert_has_avyayibhava("yaTA", "Sakti", &["yaTASakti"]); + assert_has_avyayibhava("anu", "jyezWa", &["anujyezWam"]); + assert_has_avyayibhava("sa", "cakra", &["sacakram"]); + assert_has_avyayibhava("sa", "brahman", &["sabrahma"]); + assert_has_avyayibhava("sa", "kzatra", &["sakzatram"]); + assert_has_avyayibhava("sa", "busa", &["sabusam"]); + assert_has_avyayibhava("sa", "agni", &["sAgni"]); + assert_has_avyayibhava("sa", "izwi", &["sezwi"]); +} + +#[test] +fn sutra_2_1_7() { + assert_has_avyayibhava("yaTA", "vfdDa", &["yaTAvfdDam"]); + assert_has_avyayibhava("yaTA", "aDyApaka", &["yaTADyApakam"]); +} + +#[test] +fn sutra_2_1_8() { + assert_has_avyayibhava("yAvat", "amatra", &["yAvadamatram"]); +} + +#[test] +fn sutra_2_1_9() { + assert_has_avyayibhava("SAka", "prati", &["SAkaprati"]); +} + +#[test] +fn sutra_2_1_10() { + assert_has_avyayibhava("akza", "pari", &["akzapari"]); + assert_has_avyayibhava("SalAkA", "pari", &["SalAkApari"]); + assert_has_avyayibhava("eka", "pari", &["ekapari"]); + assert_has_avyayibhava("dvi", "pari", &["dvipari"]); + assert_has_avyayibhava("tri", "pari", &["tripari"]); + assert_has_avyayibhava("catus", "pari", &["catuzpari"]); +} + +#[test] +fn sutra_2_1_13() { + assert_has_avyayibhava("A", "pAwaliputra", &["ApAwaliputram"]); + assert_has_avyayibhava("A", "kumAra", &["AkumAram"]); +} + +#[test] +fn sutra_2_1_14() { + assert_has_avyayibhava("aBi", "agni", &["aByagni"]); + assert_has_avyayibhava("prati", "agni", &["pratyagni"]); +} + +#[test] +fn sutra_2_1_15() { + assert_has_avyayibhava("anu", "vana", &["anuvanam"]); +} + +#[test] +fn sutra_2_1_24() { + assert_has_dvitiya_tatpurusha("kazwa", "Srita", &["kazwaSrita"]); + assert_has_dvitiya_tatpurusha("naraka", "Srita", &["narakaSrita"]); + assert_has_dvitiya_tatpurusha("kAntAra", "atIta", &["kAntArAtIta"]); + assert_has_dvitiya_tatpurusha("naraka", "patita", &["narakapatita"]); + assert_has_dvitiya_tatpurusha("grAma", "gata", &["grAmagata"]); + assert_has_dvitiya_tatpurusha("taraNga", "atyasta", &["taraNgAtyasta"]); + assert_has_dvitiya_tatpurusha("tuhina", "atyasta", &["tuhinAtyasta"]); + assert_has_dvitiya_tatpurusha("suKa", "prApta", &["suKaprApta"]); + assert_has_dvitiya_tatpurusha("suKa", "Apanna", &["suKApanna"]); + assert_has_dvitiya_tatpurusha("duHKa", "Apanna", &["duHKApanna"]); +} + +#[test] +fn sutra_2_1_25() { + let dhauta = create_kta("DOta", &[], &d("DAvu~^", Bhvadi)); + let vilina = create_kta("vilIna", &["vi"], &d("lI\\N", Divadi)); + assert_has_avyaya_tatpurusha("svayam", &dhauta, &["svayanDOta"]); + assert_has_avyaya_tatpurusha("svayam", &vilina, &["svayaMvilIna"]); +} + +#[test] +fn sutra_2_1_26() { + let arudha = create_kta("ArUQa", &["AN"], &d("ru\\ha~", Bhvadi)); + let pluta = create_kta("pluta", &[], &d("plu\\N", Bhvadi)); + assert_has_dvitiya_tatpurusha("KawvA", &arudha, &["KawvArUQa"]); + assert_has_dvitiya_tatpurusha("KawvA", &pluta, &["KawvApluta"]); +} + +#[test] +fn sutra_2_1_27() { + let krta = create_kta("kfta", &[], &d("qukf\\Y", Tanadi)); + let pita = create_kta("pIta", &[], &d("pA\\", Bhvadi)); + let bhukta = create_kta("Bukta", &[], &d("Bu\\ja~", Rudhadi)); + assert_has_avyaya_tatpurusha("sAmi", &krta, &["sAmikfta"]); + assert_has_avyaya_tatpurusha("sAmi", &pita, &["sAmipIta"]); + assert_has_avyaya_tatpurusha("sAmi", &bhukta, &["sAmiBukta"]); +} + +#[test] +fn sutra_2_1_31() { + assert_has_trtiya_tatpurusha("mAsa", "pUrva", &["mAsapUrva"]); + assert_has_trtiya_tatpurusha("saMvatsara", "pUrva", &["saMvatsarapUrva"]); + assert_has_trtiya_tatpurusha("mAtf", "sadfSa", &["mAtfsadfSa"]); + assert_has_trtiya_tatpurusha("pitf", "sadfSa", &["pitfsadfSa"]); + assert_has_trtiya_tatpurusha("mAtf", "sama", &["mAtfsama"]); + assert_has_trtiya_tatpurusha("mASa", "Una", &["mASona"]); + assert_has_trtiya_tatpurusha("kArzApaRa", "Una", &["kArzApaRona"]); + // TODO: mAzavikala, kArzApanavikala + assert_has_trtiya_tatpurusha("asi", "kalaha", &["asikalaha"]); + assert_has_trtiya_tatpurusha("vAc", "kalaha", &["vAkkalaha"]); + assert_has_trtiya_tatpurusha("vAc", "nipuRa", &["vANnipuRa"]); + assert_has_trtiya_tatpurusha("AcAra", "nipuRa", &["AcAranipuRa"]); + assert_has_trtiya_tatpurusha("guqa", "miSra", &["guqamiSra"]); + assert_has_trtiya_tatpurusha("tila", "miSra", &["tilamiSra"]); + assert_has_trtiya_tatpurusha("AcAra", "SlakzRa", &["AcAraSlakzRa"]); +} + +#[test] +fn sutra_2_1_33() { + let peya = create_krdanta("peya", &[], &d("pA\\", Bhvadi), Krt::yat); + assert_has_trtiya_tatpurusha("kAka", &peya, &["kAkapeya"]); + + let lehya = create_krdanta("lehya", &[], &d("li\\ha~^", Adadi), Krt::Ryat); + assert_has_trtiya_tatpurusha("Svan", &lehya, &["Svalehya"]); + + let chedya = create_krdanta("Cedya", &[], &d("Ci\\di~^r", Rudhadi), Krt::Ryat); + assert_has_trtiya_tatpurusha("bAzpa", &chedya, &["bAzpacCedya"]); + + let sanceya = create_krdanta("saYceya", &["sam"], &d("ci\\Y", Svadi), Krt::yat); + assert_has_trtiya_tatpurusha("kaRwaka", &sanceya, &["kaRwakasaYceya"]); +} + +#[test] +fn sutra_2_1_34() { + assert_has_trtiya_tatpurusha("daDi", "odana", &["daDyodana"]); + assert_has_trtiya_tatpurusha("kzIra", "odana", &["kzIrOdana"]); +} + +#[test] +fn sutra_2_1_36() { + assert_has_caturthi_tatpurusha("yUpa", "dAru", &["yUpadAru"]); + assert_has_caturthi_tatpurusha("kuRqala", "hiraRya", &["kuRqalahiraRya"]); + assert_has_caturthi_tatpurusha("brAhmaRa", "arTa", &["brAhmaRArTa"]); + assert_has_caturthi_tatpurusha("kubera", "bali", &["kuberabali"]); + assert_has_caturthi_tatpurusha("mahArAja", "bali", &["mahArAjabali"]); + assert_has_caturthi_tatpurusha("go", "hita", &["gohita"]); + assert_has_caturthi_tatpurusha("aSva", "hita", &["aSvahita"]); + assert_has_caturthi_tatpurusha("go", "suKa", &["gosuKa"]); + assert_has_caturthi_tatpurusha("aSva", "suKa", &["aSvasuKa"]); + assert_has_caturthi_tatpurusha("go", "rakzita", &["gorakzita"]); + assert_has_caturthi_tatpurusha("aSva", "rakzita", &["aSvarakzita"]); +} + +#[test] +fn sutra_2_1_37() { + assert_has_panchami_tatpurusha("vfka", "Baya", &["vfkaBaya"]); + assert_has_panchami_tatpurusha("cOra", "Baya", &["cOraBaya"]); + assert_has_panchami_tatpurusha("dasyu", "Baya", &["dasyuBaya"]); +} + +#[test] +fn sutra_2_1_37_v1() { + assert_has_panchami_tatpurusha("vfka", "BIta", &["vfkaBIta"]); + assert_has_panchami_tatpurusha("vfka", "BIti", &["vfkaBIti"]); + assert_has_panchami_tatpurusha("vfka", "BI", &["vfkaBI"]); +} + +#[test] +fn sutra_2_1_38() { + assert_has_panchami_tatpurusha("suKa", "apeta", &["suKApeta"]); + assert_has_panchami_tatpurusha("kalpanA", "apoQa", &["kalpanApoQa"]); + assert_has_panchami_tatpurusha("cakra", "mukta", &["cakramukta"]); + assert_has_panchami_tatpurusha("svarga", "patita", &["svargapatita"]); + assert_has_panchami_tatpurusha("taraNga", "apatrasta", &["taraNgApatrasta"]); +} + +#[test] +fn sutra_2_1_40() { + assert_has_saptami_tatpurusha("akza", "SORqa", &["akzaSORqa"]); + assert_has_saptami_tatpurusha("akza", "DUrta", &["akzaDUrta"]); + assert_has_saptami_tatpurusha("akza", "kitava", &["akzakitava"]); +} + +#[test] +fn sutra_2_1_41() { + assert_has_saptami_tatpurusha("sANkASya", "sidDa", &["sANkASyasidDa"]); + assert_has_saptami_tatpurusha("kAmpilya", "sidDa", &["kAmpilyasidDa"]); + assert_has_saptami_tatpurusha("Atapa", "Suzka", &["AtapaSuzka"]); + assert_has_saptami_tatpurusha("CAyA", "Suzka", &["CAyASuzka"]); + assert_has_saptami_tatpurusha("sTAlI", "pakva", &["sTAlIpakva"]); + assert_has_saptami_tatpurusha("kumBI", "pakva", &["kumBIpakva"]); + assert_has_saptami_tatpurusha("cakra", "banDa", &["cakrabanDa"]); +} + +#[test] +fn sutra_2_1_42() { + assert_has_saptami_tatpurusha("tIrTa", "DvANkza", &["tIrTaDvANkza"]); + // TODO: others +} + +#[test] +fn sutra_2_1_58() { + assert_has_karmadharaya("pUrva", "puruza", &["pUrvapuruza"]); + assert_has_karmadharaya("apara", "puruza", &["aparapuruza"]); + assert_has_karmadharaya("praTama", "puruza", &["praTamapuruza"]); + assert_has_karmadharaya("carama", "puruza", &["caramapuruza"]); + assert_has_karmadharaya("jaGanya", "puruza", &["jaGanyapuruza"]); + assert_has_karmadharaya("samAna", "puruza", &["samAnapuruza"]); + assert_has_karmadharaya("maDya", "puruza", &["maDyapuruza"]); + assert_has_karmadharaya("maDyama", "puruza", &["maDyamapuruza"]); + assert_has_karmadharaya("vIra", "puruza", &["vIrapuruza"]); +} + +#[test] +fn sutra_2_1_61() { + assert_has_karmadharaya("sat", "puruza", &["satpuruza"]); + assert_has_karmadharaya("mahat", "puruza", &["mahApuruza"]); + assert_has_karmadharaya("parama", "puruza", &["paramapuruza"]); + assert_has_karmadharaya("uttama", "puruza", &["uttamapuruza"]); + assert_has_karmadharaya("utkfzwa", "puruza", &["utkfzwapuruza"]); +} + +#[test] +fn sutra_2_1_62() { + assert_has_karmadharaya("go", "vfndAraka", &["govfndAraka"]); + assert_has_karmadharaya("aSva", "vfndAraka", &["aSvavfndAraka"]); + assert_has_karmadharaya("go", "nAga", &["gonAga"]); + assert_has_karmadharaya("aSva", "nAga", &["aSvanAga"]); + assert_has_karmadharaya("go", "kuYjara", &["gokuYjara"]); + assert_has_karmadharaya("aSva", "kuYjara", &["aSvakuYjara"]); + // TODO: pujyamAna? +} + +#[ignore] +#[test] +fn sutra_2_1_64() { + assert_has_karmadharaya("kim", "rAjan", &["kiMrAjan"]); + assert_has_karmadharaya("kim", "saKi", &["kiMsaKi"]); + assert_has_karmadharaya("kim", "go", &["kiNgo"]); +} + +#[test] +fn sutra_2_1_67() { + assert_has_karmadharaya("yuvan", "Kalati", &["yuvaKalati"]); + assert_has_karmadharaya("yuvan", "palita", &["yuvapalita"]); + assert_has_karmadharaya("yuvan", "valina", &["yuvavalina"]); + assert_has_karmadharaya("yuvan", "jarati", &["yuvajarati"]); + // TODO: stri +} diff --git a/vidyut-prakriya/tests/kashika_2_2.rs b/vidyut-prakriya/tests/kashika_2_2.rs new file mode 100644 index 0000000..07d61b7 --- /dev/null +++ b/vidyut-prakriya/tests/kashika_2_2.rs @@ -0,0 +1,25 @@ +extern crate test_utils; +use test_utils::*; + +#[test] +fn sutra_2_2_8() { + assert_has_sasthi_tatpurusha("rAjan", "puruza", &["rAjapuruza"]); + assert_has_sasthi_tatpurusha("brAhmaRa", "kambala", &["brAhmaRakambala"]); +} + +#[ignore] +#[test] +fn sutra_2_2_24() { + assert_has_bahuvrihi("UQa", "raTa", &["UQaraTa"]); + assert_has_bahuvrihi("upagfta", "paSu", &["upagftapaSu"]); + assert_has_bahuvrihi("udDfta", "odana", &["udDftOdana"]); + assert_has_bahuvrihi("citra", "go", &["citragu"]); +} + +#[test] +fn sutra_2_2_29() { + assert_has_dvandva(&["plakza", "nyagroDa"], &["plakzanyagroDa"]); + assert_has_dvandva(&["Dava", "Kadira", "palASa"], &["DavaKadirapalASa"]); + assert_has_samahara_dvandva(&["vAc", "tvac"], &["vAktvaca"]); + assert_has_samahara_dvandva(&["vAc", "dfzad"], &["vAgdfzada"]); +} diff --git a/vidyut-prakriya/tests/kashika_2_3.rs b/vidyut-prakriya/tests/kashika_2_3.rs index 8bd9f2c..b8515d9 100644 --- a/vidyut-prakriya/tests/kashika_2_3.rs +++ b/vidyut-prakriya/tests/kashika_2_3.rs @@ -28,6 +28,9 @@ fn sutra_2_3_47() { assert_has_sup_sp("devadatta", Pum, &["devadattAH"]); } +#[test] +fn skip_sutra_2_3_48() {} + #[test] fn sutra_2_3_49() { assert_has_sup_ss("pawu", Pum, &["pawo"]); diff --git a/vidyut-prakriya/tests/kashika_3_1.rs b/vidyut-prakriya/tests/kashika_3_1.rs index c82b3e1..1996462 100644 --- a/vidyut-prakriya/tests/kashika_3_1.rs +++ b/vidyut-prakriya/tests/kashika_3_1.rs @@ -286,6 +286,9 @@ fn sutra_3_1_41() { assert_has_thas(&[], &vid, Lot, &["vidANkurutam", "vittam"]); } +#[test] +fn skip_sutra_3_1_43() {} + #[test] fn sutra_3_1_44() { assert_has_tip(&[], &d("qukf\\Y", Tanadi), Lun, &["akArzIt"]); @@ -375,6 +378,18 @@ fn sutra_3_1_49() { ); } +#[test] +fn sutra_3_1_50() { + let gup = d("gupU~", Bhvadi); + let t = Tester::with_chaandasa(); + t.assert_has_thas( + &[], + &gup, + Lun, + &["ajugupatam", "agOptam", "agopizwam", "agopAyizwam"], + ); +} + #[test] fn sutra_3_1_52() { let asu = d("asu~", Divadi); @@ -453,6 +468,16 @@ fn sutra_3_1_58() { ); } +#[ignore] +#[test] +fn sutra_3_1_59() { + let t = Tester::with_chaandasa(); + t.assert_has_tip(&[], &d("qukf\\Y", Tanadi), Lun, &["akarat"]); + t.assert_has_tip(&[], &d("mf\\N", Tudadi), Lun, &["amarat"]); + t.assert_has_tip(&[], &d("dF", Kryadi), Lun, &["adarat"]); + t.assert_has_tip(&["AN"], &d("ru\\ha~", Bhvadi), Lun, &["Aruhat"]); +} + #[test] fn sutra_3_1_60() { let pad = d("pa\\da~\\", Divadi); diff --git a/vidyut-prakriya/tests/kashika_3_2.rs b/vidyut-prakriya/tests/kashika_3_2.rs index 53e2965..60178ae 100644 --- a/vidyut-prakriya/tests/kashika_3_2.rs +++ b/vidyut-prakriya/tests/kashika_3_2.rs @@ -3,6 +3,7 @@ use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; +use vidyut_prakriya::args::Linga::*; use vidyut_prakriya::args::*; #[test] @@ -1049,6 +1050,14 @@ fn sutra_3_2_128() { assert_has_krdanta(&[], &d("ya\\ja~^", Bhvadi), Krt::SAnan, &["yajamAna"]); } +#[test] +fn sutra_3_2_131() { + let dvishat = create_krdanta("dvizat", &[], &d("dvi\\za~^", Adadi), Krt::Satf); + assert_has_sup_1s(&dvishat, Pum, &["dvizan"]); + assert_has_sup_1d(&dvishat, Pum, &["dvizantO"]); + assert_has_sup_1p(&dvishat, Pum, &["dvizantaH"]); +} + #[test] fn sutra_3_2_135() { assert_has_krdanta(&[], &d("qukf\\Y", Tanadi), Krt::tfn, &["kartf"]); diff --git a/vidyut-prakriya/tests/kashika_3_3.rs b/vidyut-prakriya/tests/kashika_3_3.rs index 5da72cb..8d710dc 100644 --- a/vidyut-prakriya/tests/kashika_3_3.rs +++ b/vidyut-prakriya/tests/kashika_3_3.rs @@ -4,7 +4,9 @@ use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::KrtArtha::*; use vidyut_prakriya::args::Lakara::*; +use vidyut_prakriya::args::Linga::*; use vidyut_prakriya::args::*; +use vidyut_prakriya::Ashtadhyayi; fn assert_has_bhave_krdanta(upapadas: &[&str], dhatu: &Dhatu, krt: BaseKrt, expected: &[&str]) { assert_has_artha_krdanta(upapadas, dhatu, KrtArtha::Bhava, krt, expected); @@ -55,6 +57,7 @@ fn sutra_3_3_3() { #[test] fn sutra_3_3_10() { assert_has_krdanta(&[], &d("Bu\\ja~", Rudhadi), Krt::tumun, &["Boktum"]); + assert_has_krdanta(&[], &d("Bu\\ja~", Rudhadi), Krt::Rvul, &["Bojaka"]); } #[test] @@ -63,6 +66,30 @@ fn sutra_3_3_13() { assert_has_tip(&[], &d("hf\\Y", Bhvadi), Lrt, &["harizyati"]); } +#[test] +fn sutra_3_3_14() { + let kr = d("qukf\\Y", Tanadi); + + let create_lrt_sat = |text, dhatu: &Dhatu, krt: BaseKrt| { + let a = Ashtadhyayi::new(); + let args = KrdantaArgs::builder().lakara(Lrt).krt(krt).build().unwrap(); + let prakriyas = a.derive_krdantas(&dhatu, &args); + create_pratipadika(text, &prakriyas) + }; + + let karishyat = create_lrt_sat("karizyat", &kr, Krt::Satf); + let karishyamana = create_lrt_sat("karizyamARa", &kr, Krt::SAnac); + assert_has_sup_2s(&karishyat, Pum, &["karizyantam"]); + assert_has_sup_2s(&karishyamana, Pum, &["karizyamARam"]); + assert_has_sup_ss(&karishyat, Pum, &["karizyan"]); + assert_has_sup_ss(&karishyamana, Pum, &["karizyamARa"]); + assert_has_sup_1s(&karishyat, Pum, &["karizyan"]); + assert_has_sup_1s(&karishyamana, Pum, &["karizyamARaH"]); + + assert_has_tip(&[], &kr, Lrt, &["karizyati"]); + assert_has_ta(&[], &kr, Lrt, &["karizyate"]); +} + #[test] fn sutra_3_3_15() { assert_has_tip(&[], &d("qukf\\Y", Tanadi), Lut, &["kartA"]); @@ -632,3 +659,11 @@ fn sutra_3_3_120() { assert_has_krdanta(&["ava"], &d("tF", Bhvadi), Krt::GaY, &["avatAra"]); assert_has_krdanta(&["ava"], &d("stFY", Kryadi), Krt::GaY, &["avastAra"]); } + +#[test] +fn sutra_3_3_137() { + let jiv = d("jIva~", Bhvadi); + assert_has_tip(&[], &jiv, AshirLin, &["jIvyAt"]); + assert_has_tip(&[], &jiv, Lot, &["jIvatu", "jIvatAt"]); + assert_has_tip(&[], &jiv, Lat, &["jIvati"]); +} diff --git a/vidyut-prakriya/tests/kashika_3_4.rs b/vidyut-prakriya/tests/kashika_3_4.rs index 0b6ffdf..d227624 100644 --- a/vidyut-prakriya/tests/kashika_3_4.rs +++ b/vidyut-prakriya/tests/kashika_3_4.rs @@ -27,6 +27,28 @@ fn sutra_3_4_21() { assert_has_krdanta(&[], &d("zRA\\", Adadi), Krt::ktvA, &["snAtvA"]); } +#[test] +fn sutra_3_4_67() { + let kf = d("qukf\\Y", Tanadi); + assert_has_krdanta(&[], &kf, Krt::Rvul, &["kAraka"]); + assert_has_krdanta(&[], &kf, Krt::tfc, &["kartf"]); + + assert_has_krdanta(&[], &d("wunadi~", Bhvadi), Krt::lyu, &["nandana"]); + assert_has_krdanta(&[], &d("graha~^", Kryadi), Krt::Rini, &["grAhin"]); + assert_has_krdanta(&[], &d("qupa\\ca~^z", Bhvadi), Krt::ac, &["paca"]); +} + +#[test] +fn sutra_3_4_69() { + let gam = d("ga\\mx~", Bhvadi); + assert_has_ta_k(&[], &gam, Lat, &["gamyate"]); + assert_has_tip(&[], &gam, Lat, &["gacCati"]); + + let aas = d("Asa~\\", Adadi); + assert_has_ta_k(&[], &aas, Lat, &["Asyate"]); + assert_has_ta(&[], &aas, Lat, &["Aste"]); +} + #[test] fn sutra_3_4_70() { let kf = &d("qukf\\Y", Tanadi); @@ -220,7 +242,7 @@ fn sutra_3_4_91() { } #[test] -fn sutra_3_4_92_and_sutra_3_4_93() { +fn sutra_3_4_92() { let kf = d("qukf\\Y", Tanadi); assert_has_mip(&[], &kf, Lot, &["karavARi"]); assert_has_vas(&[], &kf, Lot, &["karavAva"]); @@ -230,6 +252,14 @@ fn sutra_3_4_92_and_sutra_3_4_93() { assert_has_mahin(&[], &kf, Lot, &["karavAmahE"]); } +#[test] +fn sutra_3_4_93() { + let kf = d("qukf\\Y", Tanadi); + assert_has_iw(&[], &kf, Lot, &["karavE"]); + assert_has_vahi(&[], &kf, Lot, &["karavAvahE"]); + assert_has_mahin(&[], &kf, Lot, &["karavAmahE"]); +} + // 3.4.94 - 3.4.98 are for lew. #[test] diff --git a/vidyut-prakriya/tests/kashika_4_1.rs b/vidyut-prakriya/tests/kashika_4_1.rs index 075b0fc..12fdfdf 100644 --- a/vidyut-prakriya/tests/kashika_4_1.rs +++ b/vidyut-prakriya/tests/kashika_4_1.rs @@ -1,15 +1,18 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; +use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Linga::*; use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; +use vidyut_prakriya::args::Unadi; use vidyut_prakriya::args::*; fn assert_has_pum(prati: &str, expected: &[&str]) { assert_has_sup_1s(prati, Pum, expected); } -fn assert_has_stri(prati: &str, expected: &[&str]) { +fn assert_has_stri(prati: impl IntoPratipadika, expected: &[&str]) { assert_has_sup_1s(prati, Stri, expected); } @@ -163,7 +166,7 @@ fn sutra_4_1_2() { assert_has_sup_7d(&karishagandhya, Stri, &["kArIzaganDyayoH"]); assert_has_sup_7p(&karishagandhya, Stri, &["kArIzaganDyAsu"]); - let drshad = Pratipadika::new("dfzad"); + let drshad = Pratipadika::from("dfzad"); assert_has_sup_1s(&drshad, Pum, &["dfzat"]); assert_has_sup_1d(&drshad, Pum, &["dfzadO"]); assert_has_sup_1p(&drshad, Pum, &["dfzadaH"]); @@ -235,6 +238,40 @@ fn sutra_4_1_5() { assert_has_stri("Catrin", &["CatriRI"]); } +#[test] +fn sutra_4_1_6() { + let bhavat = create_krdanta("Bavat", &[], &d("BA\\", Adadi), Unadi::qavatu); + assert_has_stri(&bhavat, &["BavatI"]); + + let abhibhavat = create_avyaya_tatpurusha("atiBavat", &Pratipadika::from("ati"), &bhavat); + assert_has_stri(&abhibhavat, &["atiBavatI"]); + + let pacat = create_krdanta("pacat", &[], &d("qupa\\ca~^z", Bhvadi), Krt::Satf); + assert_has_stri(&pacat, &["pacantI"]); + + let yajat = create_krdanta("yajat", &[], &d("ya\\ja~", Bhvadi), Krt::Satf); + assert_has_stri(&yajat, &["yajantI"]); +} + +#[test] +fn sutra_4_1_7() { + assert_has_stri("DIvan", &["DIvarI"]); + assert_has_stri("pIvan", &["pIvarI"]); + assert_has_stri("Sarvan", &["SarvarI"]); +} + +#[ignore] +#[test] +fn sutra_4_1_9() { + assert_has_sup_1s("dAman", Stri, &["dAmA"]); + assert_has_sup_1s("dAman", Stri, &["dAmAnO"]); + assert_has_sup_1s("dAman", Stri, &["dAmAnaH"]); + + assert_has_sup_1s("pAman", Stri, &["pAmA"]); + assert_has_sup_1s("pAman", Stri, &["pAmAnO"]); + assert_has_sup_1s("pAman", Stri, &["pAmAnaH"]); +} + #[test] fn sutra_4_1_10() { assert_has_stri("svasf", &["svasA"]); @@ -245,6 +282,51 @@ fn sutra_4_1_10() { // TODO: others } +#[ignore] +#[test] +fn sutra_4_1_15() { + let kurucara = create_upapada_krdanta("kurucara", "kuru", &[], &d("cara~", Bhvadi), Krt::wa); + let madracara = create_upapada_krdanta("madracara", "madra", &[], &d("cara~", Bhvadi), Krt::wa); + assert_has_stri(&kurucara, &["kurucarI"]); + assert_has_stri(&madracara, &["madracarI"]); + + let pacamana = create_krdanta("pacamAna", &[], &d("qupa\\ca~^z", Bhvadi), Krt::SAnac); + let yajamana = create_krdanta("yajamAna", &[], &d("ya\\ja~^", Bhvadi), Krt::SAnac); + assert_has_stri(&pacamana, &["pacamAnA"]); + assert_has_stri(&yajamana, &["yajamAnA"]); + + let sauparneya = create_taddhitanta("sOparReya", &nyap("suparRA"), T::Qak); + let vainateya = create_taddhitanta("vEnateya", &nyap("vinatA"), T::Qak); + assert_has_stri(&sauparneya, &["sOparReyI"]); + assert_has_stri(&vainateya, &["vEnateyI"]); + + let kr = d("qukf\\Y", Tanadi); + let kumbhakara = create_upapada_krdanta("kumBakAra", "kumBa", &[], &kr, Krt::aR); + let nagarakara = create_upapada_krdanta("nagarakAra", "nagara", &[], &kr, Krt::aR); + assert_has_stri(&kumbhakara, &["kumBakArI"]); + assert_has_stri(&nagarakara, &["nagarakArI"]); + + let aupagava = create_taddhitanta("Opagava", "upagu", T::aR); + assert_has_stri(&aupagava, &["OpagavI"]); + + // TODO: many, many others +} + +#[test] +fn sutra_4_1_41() { + // zit + let nartaka = create_krdanta("nartaka", &[], &d("nftI~", Divadi), Krt::zvun); + assert_has_stri(&nartaka, &["nartakI"]); + let khanaka = create_krdanta("Kanaka", &[], &d("Kanu~^", Bhvadi), Krt::zvun); + assert_has_stri(&khanaka, &["KanakI"]); + let rajaka = create_krdanta("rajaka", &[], &d("ra\\nja~^", Bhvadi), Krt::zvun); + assert_has_stri(&rajaka, &["rajakI"]); + + // gaurAdi + assert_has_stri("gOra", &["gOrI"]); + assert_has_stri("matsya", &["matsI"]); +} + #[test] fn sutra_4_1_45() { assert_has_stri("bahu", &["bahvI", "bahuH"]); @@ -263,8 +345,6 @@ fn sutra_4_1_49() { assert_has_stri("yava", &["yavAnI"]); assert_has_stri("yavana", &["yavanAnI"]); assert_has_stri("mAtula", &["mAtulAnI"]); - - // TODO: others; } #[test] @@ -454,8 +534,8 @@ fn sutra_4_1_117() { #[test] fn sutra_4_1_118() { - assert_has_taddhitanta(&nyap("pilA"), T::aR, &["pEla"]); - assert_has_taddhitanta(&nyap("pilA"), T::Qak, &["pEleya"]); + assert_has_taddhitanta(&nyap("pIlA"), T::aR, &["pEla"]); + assert_has_taddhitanta(&nyap("pIlA"), T::Qak, &["pEleya"]); } #[test] diff --git a/vidyut-prakriya/tests/kashika_4_2.rs b/vidyut-prakriya/tests/kashika_4_2.rs index b8206d1..093d636 100644 --- a/vidyut-prakriya/tests/kashika_4_2.rs +++ b/vidyut-prakriya/tests/kashika_4_2.rs @@ -219,91 +219,91 @@ fn sutra_4_2_50() { #[test] fn sutra_4_2_67() { - assert_has_taddhitanta(&prati("udumbara"), T::aR, &["Odumbara"]); - assert_has_taddhitanta(&prati("balbaja"), T::aR, &["bAlbaja"]); - assert_has_taddhitanta(&prati("parvata"), T::aR, &["pArvata"]); + assert_has_taddhitanta("udumbara", T::aR, &["Odumbara"]); + assert_has_taddhitanta("balbaja", T::aR, &["bAlbaja"]); + assert_has_taddhitanta("parvata", T::aR, &["pArvata"]); } #[test] fn sutra_4_2_68() { - assert_has_taddhitanta(&prati("kuSAmba"), T::aR, &["kOSAmba"]); - assert_has_taddhitanta(&prati("sahasra"), T::aR, &["sAhasra"]); + assert_has_taddhitanta("kuSAmba", T::aR, &["kOSAmba"]); + assert_has_taddhitanta("sahasra", T::aR, &["sAhasra"]); } #[test] fn sutra_4_2_69() { - assert_has_taddhitanta(&prati("fjunO"), T::aR, &["ArjunAva"]); - assert_has_taddhitanta(&prati("Siba"), T::aR, &["SEba"]); + assert_has_taddhitanta("fjunO", T::aR, &["ArjunAva"]); + assert_has_taddhitanta("Siba", T::aR, &["SEba"]); } #[test] fn sutra_4_2_70() { - assert_has_taddhitanta(&prati("vidiSA"), T::aR, &["vEdiSa"]); - assert_has_taddhitanta(&prati("himavat"), T::aR, &["hEmavata"]); + assert_has_taddhitanta("vidiSA", T::aR, &["vEdiSa"]); + assert_has_taddhitanta("himavat", T::aR, &["hEmavata"]); } #[test] fn sutra_4_2_71() { - assert_has_taddhitanta(&prati("araqu"), T::aY, &["Araqava"]); - assert_has_taddhitanta(&prati("kakzatu"), T::aY, &["kAkzatava"]); - assert_has_taddhitanta(&prati("karkawelu"), T::aY, &["kArkawelava"]); + assert_has_taddhitanta("araqu", T::aY, &["Araqava"]); + assert_has_taddhitanta("kakzatu", T::aY, &["kAkzatava"]); + assert_has_taddhitanta("karkawelu", T::aY, &["kArkawelava"]); } #[test] fn sutra_4_2_72() { - assert_has_taddhitanta(&prati("izukAvat"), T::aY, &["EzukAvata"]); - assert_has_taddhitanta(&prati("siDrAkAvat"), T::aY, &["sEDrAkAvata"]); + assert_has_taddhitanta("izukAvat", T::aY, &["EzukAvata"]); + assert_has_taddhitanta("siDrAkAvat", T::aY, &["sEDrAkAvata"]); // bahu-ac? - assert_has_taddhitanta(&prati("ahimat"), T::aR, &["Ahimata"]); - assert_has_taddhitanta(&prati("yavamat"), T::aR, &["yAvamata"]); - assert_has_taddhitanta(&prati("mAlAvat"), T::aR, &["mAlAvata"]); + assert_has_taddhitanta("ahimat", T::aR, &["Ahimata"]); + assert_has_taddhitanta("yavamat", T::aR, &["yAvamata"]); + assert_has_taddhitanta("mAlAvat", T::aR, &["mAlAvata"]); } #[test] fn sutra_4_2_75() { - assert_has_taddhitanta(&prati("saNkala"), T::aY, &["sANkala"]); - assert_has_taddhitanta(&prati("puzkala"), T::aY, &["pOzkala"]); + assert_has_taddhitanta("saNkala", T::aY, &["sANkala"]); + assert_has_taddhitanta("puzkala", T::aY, &["pOzkala"]); } #[test] fn sutra_4_2_77() { - assert_has_taddhitanta(&prati("suvAstu"), T::aR, &["sOvAstava"]); - assert_has_taddhitanta(&prati("varRu"), T::aR, &["vArRava"]); + assert_has_taddhitanta("suvAstu", T::aR, &["sOvAstava"]); + assert_has_taddhitanta("varRu", T::aR, &["vArRava"]); } #[test] fn sutra_4_2_78() { - assert_has_taddhitanta(&prati("roRI"), T::aR, &["rORa"]); - assert_has_taddhitanta(&prati("ajakaroRI"), T::aR, &["AjakaroRa"]); - assert_has_taddhitanta(&prati("sihikaroRI"), T::aR, &["sEhikaroRa"]); + assert_has_taddhitanta("roRI", T::aR, &["rORa"]); + assert_has_taddhitanta("ajakaroRI", T::aR, &["AjakaroRa"]); + assert_has_taddhitanta("sihikaroRI", T::aR, &["sEhikaroRa"]); } #[test] fn sutra_4_2_79() { - assert_has_taddhitanta(&prati("karRacCidrika"), T::aR, &["kArRacCidrika"]); - assert_has_taddhitanta(&prati("karRavezwaka"), T::aR, &["kArRavezwaka"]); - assert_has_taddhitanta(&prati("triSaNku"), T::aR, &["trESaNkava"]); + assert_has_taddhitanta("karRacCidrika", T::aR, &["kArRacCidrika"]); + assert_has_taddhitanta("karRavezwaka", T::aR, &["kArRavezwaka"]); + assert_has_taddhitanta("triSaNku", T::aR, &["trESaNkava"]); } #[test] fn sutra_4_2_84() { - assert_has_taddhitanta(&prati("SarkarA"), T::Wak, &["SArkarika"]); - assert_has_taddhitanta(&prati("SarkarA"), T::Ca, &["SarkarIya"]); + assert_has_taddhitanta("SarkarA", T::Wak, &["SArkarika"]); + assert_has_taddhitanta("SarkarA", T::Ca, &["SarkarIya"]); } #[test] fn sutra_4_2_86() { - assert_has_taddhitanta(&prati("maDu"), T::matup, &["maDumat"]); - assert_has_taddhitanta(&prati("bisa"), T::matup, &["bisavat"]); + assert_has_taddhitanta("maDu", T::matup, &["maDumat"]); + assert_has_taddhitanta("bisa", T::matup, &["bisavat"]); } #[ignore] #[test] fn sutra_4_2_87() { - assert_has_taddhitanta(&prati("kumuda"), T::qmatup, &["kumudvat"]); - assert_has_taddhitanta(&prati("naqa"), T::qmatup, &["maqvat"]); - assert_has_taddhitanta(&prati("vetasa"), T::qmatup, &["vetasvat"]); + assert_has_taddhitanta("kumuda", T::qmatup, &["kumudvat"]); + assert_has_taddhitanta("naqa", T::qmatup, &["maqvat"]); + assert_has_taddhitanta("vetasa", T::qmatup, &["vetasvat"]); } // Seze @@ -313,87 +313,87 @@ fn sutra_4_2_87() { #[ignore] #[test] fn sutra_4_2_92() { - assert_has_taddhitanta(&prati("rAzwra"), T::Ga, &["rAzwriya"]); - assert_has_taddhitanta(&prati("avArapAra"), T::Ka, &["avArapArIRa"]); + assert_has_taddhitanta("rAzwra", T::Ga, &["rAzwriya"]); + assert_has_taddhitanta("avArapAra", T::Ka, &["avArapArIRa"]); - assert_has_taddhitanta(&prati("cakzus"), T::aR, &["cAkzuza"]); - assert_has_taddhitanta(&prati("SravaRa"), T::aR, &["SrAvaRa"]); - assert_has_taddhitanta(&prati("dfzad"), T::aR, &["dArzada"]); - assert_has_taddhitanta(&prati("ulUkala"), T::aR, &["OlUKala"]); - assert_has_taddhitanta(&prati("aSva"), T::aR, &["ASva"]); - assert_has_taddhitanta(&prati("catur"), T::aR, &["cAtura"]); - assert_has_taddhitanta(&prati("caturdaSI"), T::aR, &["cAturdaSa"]); + assert_has_taddhitanta("cakzus", T::aR, &["cAkzuza"]); + assert_has_taddhitanta("SravaRa", T::aR, &["SrAvaRa"]); + assert_has_taddhitanta("dfzad", T::aR, &["dArzada"]); + assert_has_taddhitanta("ulUkala", T::aR, &["OlUKala"]); + assert_has_taddhitanta("aSva", T::aR, &["ASva"]); + assert_has_taddhitanta("catur", T::aR, &["cAtura"]); + assert_has_taddhitanta("caturdaSI", T::aR, &["cAturdaSa"]); } #[test] fn sutra_4_2_93() { - assert_has_taddhitanta(&prati("rAzwra"), T::Ga, &["rAzwriya"]); - assert_has_taddhitanta(&prati("avArapAra"), T::Ka, &["avArapArIRa"]); + assert_has_taddhitanta("rAzwra", T::Ga, &["rAzwriya"]); + assert_has_taddhitanta("avArapAra", T::Ka, &["avArapArIRa"]); } #[test] fn sutra_4_2_93_v1() { - assert_has_taddhitanta(&prati("avAra"), T::Ka, &["avArIRa"]); - assert_has_taddhitanta(&prati("pAra"), T::Ka, &["pArIRa"]); - assert_has_taddhitanta(&prati("pArAvara"), T::Ka, &["pArAvarIRa"]); + assert_has_taddhitanta("avAra", T::Ka, &["avArIRa"]); + assert_has_taddhitanta("pAra", T::Ka, &["pArIRa"]); + assert_has_taddhitanta("pArAvara", T::Ka, &["pArAvarIRa"]); } #[test] fn sutra_4_2_94() { - assert_has_taddhitanta(&prati("grAma"), T::ya, &["grAmya"]); - assert_has_taddhitanta(&prati("grAma"), T::KaY, &["grAmIRa"]); + assert_has_taddhitanta("grAma", T::ya, &["grAmya"]); + assert_has_taddhitanta("grAma", T::KaY, &["grAmIRa"]); } #[test] fn sutra_4_2_95() { - assert_has_taddhitanta(&prati("katri"), T::QakaY, &["kAtreyaka"]); - assert_has_taddhitanta(&prati("umBi"), T::QakaY, &["OmBeyaka"]); + assert_has_taddhitanta("katri", T::QakaY, &["kAtreyaka"]); + assert_has_taddhitanta("umBi", T::QakaY, &["OmBeyaka"]); } #[test] fn sutra_4_2_97() { - assert_has_taddhitanta(&prati("nadI"), T::Qak, &["nAdeya"]); - assert_has_taddhitanta(&prati("mahI"), T::Qak, &["mAheya"]); + assert_has_taddhitanta("nadI", T::Qak, &["nAdeya"]); + assert_has_taddhitanta("mahI", T::Qak, &["mAheya"]); } #[test] fn sutra_4_2_98() { - assert_has_taddhitanta(&prati("dakziRA"), T::tyak, &["dAkziRAtya"]); - assert_has_taddhitanta(&prati("paScAt"), T::tyak, &["pAScAttya"]); - assert_has_taddhitanta(&prati("puras"), T::tyak, &["pOrastya"]); + assert_has_taddhitanta("dakziRA", T::tyak, &["dAkziRAtya"]); + assert_has_taddhitanta("paScAt", T::tyak, &["pAScAttya"]); + assert_has_taddhitanta("puras", T::tyak, &["pOrastya"]); } #[test] fn sutra_4_2_99() { - assert_has_taddhitanta(&prati("kApiSI"), T::zPak, &["kApiSAyana"]); + assert_has_taddhitanta("kApiSI", T::zPak, &["kApiSAyana"]); // TODO: stri } #[ignore] #[test] fn sutra_4_2_101() { - assert_has_taddhitanta(&prati("dyu"), T::yat, &["divya"]); - assert_has_taddhitanta(&prati("prAc"), T::yat, &["prAcya"]); - assert_has_taddhitanta(&prati("apAc"), T::yat, &["apAcya"]); - assert_has_taddhitanta(&prati("udac"), T::yat, &["udIcya"]); - assert_has_taddhitanta(&prati("pratyac"), T::yat, &["pratIcya"]); + assert_has_taddhitanta("dyu", T::yat, &["divya"]); + assert_has_taddhitanta("prAc", T::yat, &["prAcya"]); + assert_has_taddhitanta("apAc", T::yat, &["apAcya"]); + assert_has_taddhitanta("udac", T::yat, &["udIcya"]); + assert_has_taddhitanta("pratyac", T::yat, &["pratIcya"]); } #[test] fn sutra_4_2_102() { - assert_has_taddhitanta(&prati("kanTA"), T::Wak, &["kAnTika"]); + assert_has_taddhitanta("kanTA", T::Wak, &["kAnTika"]); } #[test] fn sutra_4_2_103() { - assert_has_taddhitanta(&prati("kanTA"), T::vuk, &["kAnTaka"]); + assert_has_taddhitanta("kanTA", T::vuk, &["kAnTaka"]); } #[test] fn sutra_4_2_105() { - assert_has_taddhitanta(&prati("Ezamas"), T::tyap, &["Ezamastya"]); - assert_has_taddhitanta(&prati("hyas"), T::tyap, &["hyastya"]); - assert_has_taddhitanta(&prati("Svas"), T::tyap, &["Svastya"]); + assert_has_taddhitanta("Ezamas", T::tyap, &["Ezamastya"]); + assert_has_taddhitanta("hyas", T::tyap, &["hyastya"]); + assert_has_taddhitanta("Svas", T::tyap, &["Svastya"]); // TODO: others } @@ -408,16 +408,46 @@ fn sutra_4_2_106() { #[ignore] #[test] fn sutra_4_2_114() { - assert_has_taddhitanta(&prati("gArgya"), T::Ca, &["gArgIya"]); - assert_has_taddhitanta(&prati("vAtsa"), T::Ca, &["vAtsIya"]); - assert_has_taddhitanta(&prati("SAla"), T::Ca, &["SAlIya"]); - assert_has_taddhitanta(&prati("mAla"), T::Ca, &["mAlIya"]); + assert_has_taddhitanta("gArgya", T::Ca, &["gArgIya"]); + assert_has_taddhitanta("vAtsa", T::Ca, &["vAtsIya"]); + assert_has_taddhitanta("SAla", T::Ca, &["SAlIya"]); + assert_has_taddhitanta("mAla", T::Ca, &["mAlIya"]); } #[ignore] #[test] fn sutra_4_2_115() { - assert_has_taddhitanta(&prati("Bavat"), T::Wak, &["BAvatka"]); - assert_has_taddhitanta(&prati("Bavat"), T::Cas, &["BavadIya"]); - assert_has_taddhitanta(&prati("Bavat"), T::Ca, &[]); + assert_has_taddhitanta("Bavat", T::Wak, &["BAvatka"]); + assert_has_taddhitanta("Bavat", T::Cas, &["BavadIya"]); + assert_has_taddhitanta("Bavat", T::Ca, &[]); +} + +#[test] +fn sutra_4_2_131() { + assert_has_artha_taddhita("madra", TatraJata, T::kan, &["madraka"]); + assert_has_artha_taddhita("vfji", TatraJata, T::kan, &["vfjika"]); +} + +#[test] +fn sutra_4_2_132() { + assert_has_artha_taddhita("fzika", TatraJata, T::aR, &["Arzika"]); + assert_has_artha_taddhita("mahizika", TatraJata, T::aR, &["mAhizika"]); +} + +#[test] +fn sutra_4_2_133() { + assert_has_artha_taddhita("kacCa", TatraJata, T::aR, &["kAcCa"]); + assert_has_artha_taddhita("sinDu", TatraJata, T::aR, &["sEnDava"]); + assert_has_artha_taddhita("varRu", TatraJata, T::aR, &["vArRava"]); +} + +#[test] +fn sutra_4_2_138() { + assert_has_artha_taddhita("gaha", TatraJata, T::Ca, &["gahIya"]); + assert_has_artha_taddhita("antaHsTa", TatraJata, T::Ca, &["antaHsTIya"]); +} + +#[test] +fn sutra_4_2_143() { + assert_has_artha_taddhita("parvata", TatraJata, T::Ca, &["parvatIya"]); } diff --git a/vidyut-prakriya/tests/kashika_4_3.rs b/vidyut-prakriya/tests/kashika_4_3.rs index 299ea0f..15bdd40 100644 --- a/vidyut-prakriya/tests/kashika_4_3.rs +++ b/vidyut-prakriya/tests/kashika_4_3.rs @@ -43,6 +43,23 @@ fn sutra_4_3_8() { assert_has_artha_taddhita("maDya", TatraJata, T::aR, &["maDyama"]); } +#[test] +fn sutra_4_3_14() { + assert_has_artha_taddhita("niSA", TatraBhava, T::aR, &["nESa"]); + assert_has_artha_taddhita("niSA", TatraBhava, T::WaY, &["nESika"]); + assert_has_artha_taddhita("pradoza", TatraBhava, T::aR, &["prAdoza"]); + assert_has_artha_taddhita("pradoza", TatraBhava, T::WaY, &["prAdozika"]); +} + +#[ignore] +#[test] +fn sutra_4_3_15() { + assert_has_artha_taddhita("Svas", TatraBhava, T::WaY, &["SOvastika"]); + assert_has_artha_taddhita("Svas", TatraBhava, T::tyap, &["Svastya"]); + assert_has_artha_taddhita("Svas", TatraBhava, T::tyu, &["Svastana"]); + assert_has_artha_taddhita("Svas", TatraBhava, T::tyul, &["Svastana"]); +} + #[test] fn sutra_4_3_17() { assert_has_artha_taddhita("prAvfz", TatraSambhute, T::eRya, &["prAvfzeRya"]); @@ -483,8 +500,37 @@ fn sutra_4_3_147() { assert_has_artha_taddhita("pizwa", TasyaVikara, T::kan, &["pizwaka"]); } +#[test] +fn sutra_4_3_157() { + assert_has_artha_taddhita("uzwra", TasyaVikara, T::vuY, &["Ozwraka"]); +} + +#[test] +fn sutra_4_3_158() { + assert_has_artha_taddhita("umA", TasyaVikara, T::vuY, &["Omaka"]); + assert_has_artha_taddhita("umA", TasyaVikara, T::aR, &["Oma"]); + assert_has_artha_taddhita("UrRA", TasyaVikara, T::vuY, &["OrRaka"]); + assert_has_artha_taddhita("UrRA", TasyaVikara, T::aY, &["OrRa"]); +} + #[test] fn sutra_4_3_160() { assert_has_artha_taddhita("go", TasyaVikara, T::yat, &["gavya"]); assert_has_artha_taddhita("payas", TasyaVikara, T::yat, &["payasya"]); } + +#[test] +fn sutra_4_3_161() { + assert_has_artha_taddhita("dru", TasyaVikara, T::yat, &["dravya"]); +} + +#[test] +fn sutra_4_3_162() { + assert_has_artha_taddhita("dru", TasyaVikara, T::vaya, &["druvaya"]); +} + +#[test] +fn sutra_4_3_164() { + assert_has_artha_taddhita("plakza", TasyaVikara, T::aR, &["plAkza"]); + assert_has_artha_taddhita("nyagroDa", TasyaVikara, T::aR, &["nEyagroDa"]); +} diff --git a/vidyut-prakriya/tests/kashika_4_4.rs b/vidyut-prakriya/tests/kashika_4_4.rs index 340397f..034cf75 100644 --- a/vidyut-prakriya/tests/kashika_4_4.rs +++ b/vidyut-prakriya/tests/kashika_4_4.rs @@ -552,6 +552,37 @@ fn sutra_4_4_83() { // TODO: a-DanuzA } +#[test] +fn sutra_4_4_84() { + assert_has_artha_taddhita("Dana", Labdha, T::yat, &["Danya"]); + assert_has_artha_taddhita("gaRa", Labdha, T::yat, &["gaRya"]); +} + +#[test] +fn sutra_4_4_85() { + assert_has_artha_taddhita("anna", Labdha, T::Ra, &["Anna"]); +} + +#[test] +fn sutra_4_4_86() { + assert_has_artha_taddhita("vaSa", Gata, T::yat, &["vaSya"]); +} + +#[test] +fn sutra_4_4_87() { + assert_has_artha_taddhita("pada", AsminDrshyam, T::yat, &["padya"]); +} + +#[test] +fn sutra_4_4_88() { + assert_has_artha_taddhita("mUla", AsyaAbarhi, T::yat, &["mUlya"]); +} + +#[test] +fn sutra_4_4_90() { + assert_has_artha_taddhita("gfhapati", Samyukta, T::Yya, &["gArhapatya"]); +} + #[test] fn sutra_4_4_91() { assert_has_taddhitanta(&prati("nO"), T::yat, &["nAvya"]); @@ -563,3 +594,133 @@ fn sutra_4_4_91() { assert_has_taddhitanta(&prati("tulA"), T::yat, &["tulya"]); // TODO: others } + +#[test] +fn sutra_4_4_92() { + assert_has_artha_taddhita("Darma", Anapeta, T::yat, &["Darmya"]); + assert_has_artha_taddhita("paTin", Anapeta, T::yat, &["paTya"]); + assert_has_artha_taddhita("arTa", Anapeta, T::yat, &["arTya"]); + assert_has_artha_taddhita("nyAya", Anapeta, T::yat, &["nyAyya"]); +} + +#[test] +fn sutra_4_4_93() { + assert_has_artha_taddhita("Candas", Nirmita, T::yat, &["Candasya"]); +} + +#[test] +fn sutra_4_4_94() { + assert_has_artha_taddhita("uras", Nirmita, T::aR, &["Orasa"]); + assert_has_artha_taddhita("uras", Nirmita, T::yat, &["urasya"]); +} + +#[test] +fn sutra_4_4_95() { + assert_has_artha_taddhita("hfdaya", Priya, T::yat, &["hfdya"]); +} + +#[test] +fn sutra_4_4_97() { + assert_has_taddhitanta("mata", T::yat, &["matya"]); + assert_has_taddhitanta("jana", T::yat, &["janya"]); + assert_has_taddhitanta("hala", T::yat, &["halya"]); +} + +#[test] +fn sutra_4_4_98() { + assert_has_artha_taddhita("sAman", TatraSadhu, T::yat, &["sAmanya"]); + assert_has_artha_taddhita("veman", TatraSadhu, T::yat, &["vemanya"]); + assert_has_artha_taddhita("karman", TatraSadhu, T::yat, &["karmaRya"]); + assert_has_artha_taddhita("SaraRa", TatraSadhu, T::yat, &["SaraRya"]); +} + +#[test] +fn sutra_4_4_99() { + assert_has_artha_taddhita("pratijana", TatraSadhu, T::KaY, &["prAtijanIna"]); + assert_has_artha_taddhita("idaMyuga", TatraSadhu, T::KaY, &["EdaMyugIna"]); + assert_has_artha_taddhita("saMyuga", TatraSadhu, T::KaY, &["sAMyugIna"]); +} + +#[test] +fn sutra_4_4_100() { + assert_has_artha_taddhita("Bakta", TatraSadhu, T::Ra, &["BAkta"]); +} + +#[test] +fn sutra_4_4_101() { + assert_has_artha_taddhita("parizad", TatraSadhu, T::Rya, &["pArizadya"]); + assert_has_artha_taddhita("parizad", TatraSadhu, T::Ra, &["pArizada"]); +} + +#[test] +fn sutra_4_4_102() { + assert_has_artha_taddhita("kaTA", TatraSadhu, T::Wak, &["kATika"]); + assert_has_artha_taddhita("vikaTA", TatraSadhu, T::Wak, &["vEkaTika"]); +} + +#[test] +fn sutra_4_4_103() { + assert_has_artha_taddhita("guqa", TatraSadhu, T::WaY, &["gOqika"]); + assert_has_artha_taddhita("kulmAza", TatraSadhu, T::WaY, &["kOlmAzika"]); + assert_has_artha_taddhita("saktu", TatraSadhu, T::WaY, &["sAktuka"]); +} + +#[test] +fn sutra_4_4_104() { + assert_has_artha_taddhita("paTi", TatraSadhu, T::QaY, &["pATeya"]); + assert_has_artha_taddhita("atiTi", TatraSadhu, T::QaY, &["AtiTeya"]); + assert_has_artha_taddhita("vasati", TatraSadhu, T::QaY, &["vAsateya"]); + assert_has_artha_taddhita("svapati", TatraSadhu, T::QaY, &["svApateya"]); +} + +#[test] +fn sutra_4_4_105() { + assert_has_artha_taddhita("saBA", TatraSadhu, T::ya, &["saBya"]); +} + +#[test] +fn sutra_4_4_106() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("saBA", TatraSadhu, T::Qa, &["saBeya"]); +} + +#[ignore] +#[test] +fn sutra_4_4_111() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("pATas", TatraBhava, T::qyaR, &["pATya"]); + t.assert_has_artha_taddhita("nadI", TatraBhava, T::qyaR, &["nAdya"]); +} + +#[test] +fn sutra_4_4_112() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("veSanta", TatraBhava, T::aR, &["vESanta"]); + t.assert_has_artha_taddhita("himavat", TatraBhava, T::aR, &["hEmavata"]); +} + +#[test] +fn sutra_4_4_115() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("tugra", TatraBhava, T::Gan, &["tugriya"]); +} + +#[test] +fn sutra_4_4_116() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("agra", TatraBhava, T::yat, &["agrya"]); +} + +#[test] +fn sutra_4_4_117() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("agra", TatraBhava, T::Ga, &["agriya"]); + t.assert_has_artha_taddhita("agra", TatraBhava, T::Ca, &["agrIya"]); +} + +#[test] +fn sutra_4_4_118() { + let t = Tester::with_chaandasa(); + t.assert_has_artha_taddhita("samudra", TatraBhava, T::Ga, &["samudriya"]); + t.assert_has_artha_taddhita("aBra", TatraBhava, T::Ga, &["aBriya"]); +} diff --git a/vidyut-prakriya/tests/kashika_5_2.rs b/vidyut-prakriya/tests/kashika_5_2.rs index 9f3ac58..b03c42e 100644 --- a/vidyut-prakriya/tests/kashika_5_2.rs +++ b/vidyut-prakriya/tests/kashika_5_2.rs @@ -67,40 +67,48 @@ fn sutra_5_2_8() { assert_has_artha_taddhita("Aprapada", Prapnoti, T::Ka, &["AprapadIna"]); } +#[ignore] +#[test] +fn sutra_5_2_9() { + assert_has_taddhitanta("anupada", T::Ka, &["anupadIna"]); + assert_has_taddhitanta("sarvAnna", T::Ka, &["sarvAnnIna"]); + assert_has_taddhitanta("AyAnaya", T::Ka, &["AyAnayIna"]); +} + #[test] fn sutra_5_2_94() { - assert_has_taddhitanta(&prati("go"), T::matup, &["gomat"]); - assert_has_taddhitanta(&prati("vfkza"), T::matup, &["vfkzavat"]); - assert_has_taddhitanta(&prati("yava"), T::matup, &["yavamat"]); - assert_has_taddhitanta(&prati("plakza"), T::matup, &["plakzavat"]); + assert_has_taddhitanta("go", T::matup, &["gomat"]); + assert_has_taddhitanta("vfkza", T::matup, &["vfkzavat"]); + assert_has_taddhitanta("yava", T::matup, &["yavamat"]); + assert_has_taddhitanta("plakza", T::matup, &["plakzavat"]); } #[test] fn sutra_5_2_96() { - assert_has_taddhitanta(&prati("cUqA"), T::lac, &["cUqAla"]); - assert_has_taddhitanta(&prati("cUqA"), T::matup, &["cUqAvat"]); + assert_has_taddhitanta("cUqA", T::lac, &["cUqAla"]); + assert_has_taddhitanta("cUqA", T::matup, &["cUqAvat"]); // AtaH - assert_has_taddhitanta(&prati("hasta"), T::matup, &["hastavat"]); - assert_has_taddhitanta(&prati("pAda"), T::matup, &["pAdavat"]); + assert_has_taddhitanta("hasta", T::matup, &["hastavat"]); + assert_has_taddhitanta("pAda", T::matup, &["pAdavat"]); } #[test] fn sutra_5_2_100() { - assert_has_taddhitanta(&prati("loman"), T::Sa, &["lomaSa"]); - assert_has_taddhitanta(&prati("loman"), T::matup, &["lomavat"]); - assert_has_taddhitanta(&prati("pAman"), T::na, &["pAmana"]); - assert_has_taddhitanta(&prati("pAman"), T::matup, &["pAmavat"]); - assert_has_taddhitanta(&prati("picCa"), T::ilac, &["picCila"]); - assert_has_taddhitanta(&prati("picCa"), T::matup, &["picCavat"]); - assert_has_taddhitanta(&prati("uras"), T::ilac, &["urasila"]); - assert_has_taddhitanta(&prati("uras"), T::matup, &["urasvat"]); + assert_has_taddhitanta("loman", T::Sa, &["lomaSa"]); + assert_has_taddhitanta("loman", T::matup, &["lomavat"]); + assert_has_taddhitanta("pAman", T::na, &["pAmana"]); + assert_has_taddhitanta("pAman", T::matup, &["pAmavat"]); + assert_has_taddhitanta("picCa", T::ilac, &["picCila"]); + assert_has_taddhitanta("picCa", T::matup, &["picCavat"]); + assert_has_taddhitanta("uras", T::ilac, &["urasila"]); + assert_has_taddhitanta("uras", T::matup, &["urasvat"]); } #[test] fn sutra_5_2_121() { - assert_has_taddhitanta(&prati("yaSas"), T::vini, &["yaSasvin"]); - assert_has_taddhitanta(&prati("payas"), T::vini, &["payasvin"]); - assert_has_taddhitanta(&prati("mAyA"), T::vini, &["mAyAvin"]); - assert_has_taddhitanta(&prati("meDA"), T::vini, &["meDAvin"]); - assert_has_taddhitanta(&prati("sraj"), T::vini, &["sragvin"]); + assert_has_taddhitanta("yaSas", T::vini, &["yaSasvin"]); + assert_has_taddhitanta("payas", T::vini, &["payasvin"]); + assert_has_taddhitanta("mAyA", T::vini, &["mAyAvin"]); + assert_has_taddhitanta("meDA", T::vini, &["meDAvin"]); + assert_has_taddhitanta("sraj", T::vini, &["sragvin"]); } diff --git a/vidyut-prakriya/tests/kashika_5_3.rs b/vidyut-prakriya/tests/kashika_5_3.rs index e9f74aa..b1322ab 100644 --- a/vidyut-prakriya/tests/kashika_5_3.rs +++ b/vidyut-prakriya/tests/kashika_5_3.rs @@ -1,113 +1,114 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::Linga::*; use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; #[ignore] #[test] fn sutra_5_3_3() { - assert_has_taddhitanta(&prati("idam"), T::ha, &["iha"]); + assert_has_taddhitanta("idam", T::ha, &["iha"]); } #[ignore] #[test] fn sutra_5_3_4() { - assert_has_taddhitanta(&prati("idam"), T::rhil, &["etarhi"]); - assert_has_taddhitanta(&prati("idam"), T::Tamu, &["itTam"]); + assert_has_taddhitanta("idam", T::rhil, &["etarhi"]); + assert_has_taddhitanta("idam", T::Tamu, &["itTam"]); } #[test] fn sutra_5_3_5() { - assert_has_taddhitanta(&prati("etad"), T::tasil, &["atas"]); - assert_has_taddhitanta(&prati("etad"), T::tral, &["atra"]); + assert_has_taddhitanta("etad", T::tasil, &["atas"]); + assert_has_taddhitanta("etad", T::tral, &["atra"]); } #[test] fn sutra_5_3_6() { - assert_has_taddhitanta(&prati("sarva"), T::dA, &["sarvadA", "sadA"]); + assert_has_taddhitanta("sarva", T::dA, &["sarvadA", "sadA"]); } #[test] fn sutra_5_3_7() { - assert_has_taddhitanta(&prati("kim"), T::tasil, &["kutas"]); - assert_has_taddhitanta(&prati("yad"), T::tasil, &["yatas"]); - assert_has_taddhitanta(&prati("tad"), T::tasil, &["tatas"]); - assert_has_taddhitanta(&prati("bahu"), T::tasil, &["bahutas"]); + assert_has_taddhitanta("kim", T::tasil, &["kutas"]); + assert_has_taddhitanta("yad", T::tasil, &["yatas"]); + assert_has_taddhitanta("tad", T::tasil, &["tatas"]); + assert_has_taddhitanta("bahu", T::tasil, &["bahutas"]); } #[test] fn sutra_5_3_9() { - assert_has_taddhitanta(&prati("pari"), T::tasil, &["paritas"]); - assert_has_taddhitanta(&prati("aBi"), T::tasil, &["aBitas"]); + assert_has_taddhitanta("pari", T::tasil, &["paritas"]); + assert_has_taddhitanta("aBi", T::tasil, &["aBitas"]); } #[test] fn sutra_5_3_10() { - assert_has_taddhitanta(&prati("kim"), T::tral, &["kutra"]); - assert_has_taddhitanta(&prati("yad"), T::tral, &["yatra"]); - assert_has_taddhitanta(&prati("tad"), T::tral, &["tatra"]); - assert_has_taddhitanta(&prati("bahu"), T::tral, &["bahutra"]); + assert_has_taddhitanta("kim", T::tral, &["kutra"]); + assert_has_taddhitanta("yad", T::tral, &["yatra"]); + assert_has_taddhitanta("tad", T::tral, &["tatra"]); + assert_has_taddhitanta("bahu", T::tral, &["bahutra"]); // But, not for idam - assert_has_taddhitanta(&prati("idam"), T::tral, &[]); + assert_has_taddhitanta("idam", T::tral, &[]); } #[ignore] #[test] fn sutra_5_3_11() { - assert_has_taddhitanta(&prati("idam"), T::ha, &["iha"]); + assert_has_taddhitanta("idam", T::ha, &["iha"]); } #[test] fn sutra_5_3_12() { - assert_has_taddhitanta(&prati("kim"), T::at, &["kva"]); + assert_has_taddhitanta("kim", T::at, &["kva"]); } #[test] fn sutra_5_3_13() { - assert_has_taddhitanta(&prati("kim"), T::ha, &["kuha"]); + assert_has_taddhitanta("kim", T::ha, &["kuha"]); } #[test] fn sutra_5_3_15() { - assert_has_taddhitanta(&prati("sarva"), T::dA, &["sarvadA", "sadA"]); - assert_has_taddhitanta(&prati("eka"), T::dA, &["ekadA"]); - assert_has_taddhitanta(&prati("anya"), T::dA, &["anyadA"]); - assert_has_taddhitanta(&prati("kim"), T::dA, &["kadA"]); - assert_has_taddhitanta(&prati("yad"), T::dA, &["yadA"]); - assert_has_taddhitanta(&prati("tad"), T::dA, &["tadA"]); - assert_has_taddhitanta(&prati("idam"), T::dA, &[]); + assert_has_taddhitanta("sarva", T::dA, &["sarvadA", "sadA"]); + assert_has_taddhitanta("eka", T::dA, &["ekadA"]); + assert_has_taddhitanta("anya", T::dA, &["anyadA"]); + assert_has_taddhitanta("kim", T::dA, &["kadA"]); + assert_has_taddhitanta("yad", T::dA, &["yadA"]); + assert_has_taddhitanta("tad", T::dA, &["tadA"]); + assert_has_taddhitanta("idam", T::dA, &[]); } #[test] fn sutra_5_3_16() { - assert_has_taddhitanta(&prati("idam"), T::rhil, &["etarhi"]); + assert_has_taddhitanta("idam", T::rhil, &["etarhi"]); } #[ignore] #[test] fn sutra_5_3_18() { - assert_has_taddhitanta(&prati("idam"), T::dAnIm, &["idAnIm"]); + assert_has_taddhitanta("idam", T::dAnIm, &["idAnIm"]); } #[test] fn sutra_5_3_19() { - assert_has_taddhitanta(&prati("tad"), T::dAnIm, &["tadAnIm"]); + assert_has_taddhitanta("tad", T::dAnIm, &["tadAnIm"]); } #[ignore] #[test] fn sutra_5_3_23() { - assert_has_taddhitanta(&prati("idam"), T::Tamu, &["itTam"]); + assert_has_taddhitanta("idam", T::Tamu, &["itTam"]); } #[test] fn sutra_5_3_24() { - assert_has_taddhitanta(&prati("kim"), T::Tamu, &["kaTam"]); + assert_has_taddhitanta("kim", T::Tamu, &["kaTam"]); } #[test] fn sutra_5_3_25() { - assert_has_taddhitanta(&prati("tad"), T::TAl, &["taTA"]); + assert_has_taddhitanta("tad", T::TAl, &["taTA"]); } #[test] @@ -126,49 +127,131 @@ fn sutra_5_3_29() { #[test] fn sutra_5_3_42() { - assert_has_taddhitanta(&prati("eka"), T::DA, &["ekaDA"]); - assert_has_taddhitanta(&prati("dvi"), T::DA, &["dviDA"]); - assert_has_taddhitanta(&prati("tri"), T::DA, &["triDA"]); - assert_has_taddhitanta(&prati("catur"), T::DA, &["caturDA"]); - assert_has_taddhitanta(&prati("paYcan"), T::DA, &["paYcaDA"]); + // EkaDyam is from 5.3.44. + assert_has_taddhitanta("eka", T::DA, &["ekaDA", "EkaDyam"]); + // dvEDam/trEDam are from 5.3.45. + // dveDA/treDA are from 5.3.46. + assert_has_taddhitanta("dvi", T::DA, &["dviDA", "dvEDam", "dveDA"]); + assert_has_taddhitanta("tri", T::DA, &["triDA", "trEDam", "treDA"]); + assert_has_taddhitanta("catur", T::DA, &["caturDA"]); + assert_has_taddhitanta("paYcan", T::DA, &["paYcaDA"]); +} + +#[test] +fn sutra_5_3_44() { + assert_has_taddhitanta("eka", T::DA, &["ekaDA", "EkaDyam"]); +} + +#[test] +fn sutra_5_3_45_to_sutra_5_3_56() { + assert_has_taddhitanta("dvi", T::DA, &["dviDA", "dvEDam", "dveDA"]); + assert_has_taddhitanta("tri", T::DA, &["triDA", "trEDam", "treDA"]); +} + +#[test] +fn sutra_5_3_47() { + assert_has_taddhitanta("vEyAkaraRa", T::pASap, &["vEyAkaraRapASa"]); + assert_has_taddhitanta("yAjYika", T::pASap, &["yAjYikapASa"]); +} + +#[test] +fn sutra_5_3_52() { + assert_has_taddhitanta("eka", T::Akinic, &["ekAkin"]); +} + +#[test] +fn sutra_5_3_53() { + assert_has_taddhitanta("AQya", T::caraw, &["AQyacara"]); + assert_has_taddhitanta("sukumAra", T::caraw, &["sukumAracara"]); + + let adhyacara = create_taddhitanta("AQyacara", "AQya", T::caraw); + assert_has_sup_1s(&adhyacara, Stri, &["AQyacarI"]); +} + +#[test] +fn sutra_5_3_54() { + assert_has_taddhitanta("devadatta", T::rUpya, &["devadattarUpya"]); + assert_has_taddhitanta("devadatta", T::caraw, &["devadattacara"]); } #[test] fn sutra_5_3_55() { - assert_has_taddhitanta(&prati("AQya"), T::tamap, &["AQyatama"]); - assert_has_taddhitanta(&prati("darSanIya"), T::tamap, &["darSanIyatama"]); - assert_has_taddhitanta(&prati("sukumAra"), T::tamap, &["sukumAratama"]); - assert_has_taddhitanta(&prati("pawu"), T::izWan, &["pawizWa"]); - assert_has_taddhitanta(&prati("laGu"), T::izWan, &["laGizWa"]); - assert_has_taddhitanta(&prati("guru"), T::izWan, &["garizWa"]); - assert_has_taddhitanta(&prati("SrezWa"), T::tamap, &["SrezWatama"]); + assert_has_taddhitanta("AQya", T::tamap, &["AQyatama"]); + assert_has_taddhitanta("darSanIya", T::tamap, &["darSanIyatama"]); + assert_has_taddhitanta("sukumAra", T::tamap, &["sukumAratama"]); + assert_has_taddhitanta("pawu", T::izWan, &["pawizWa"]); + assert_has_taddhitanta("laGu", T::izWan, &["laGizWa"]); + assert_has_taddhitanta("guru", T::izWan, &["garizWa"]); + assert_has_taddhitanta("SrezWa", T::tamap, &["SrezWatama"]); } #[test] fn sutra_5_3_57() { - assert_has_taddhitanta(&prati("AQya"), T::tarap, &["AQyatara"]); - assert_has_taddhitanta(&prati("sukumAra"), T::tarap, &["sukumAratara"]); - assert_has_taddhitanta(&prati("pawu"), T::Iyasun, &["pawIyas"]); + assert_has_taddhitanta("AQya", T::tarap, &["AQyatara"]); + assert_has_taddhitanta("sukumAra", T::tarap, &["sukumAratara"]); + assert_has_taddhitanta("pawu", T::Iyasun, &["pawIyas"]); // TODO: others } +#[test] +fn sutra_5_3_60_to_sutra_5_3_61() { + assert_has_taddhitanta("praSasya", T::Iyasun, &["Sreyas", "jyAyas"]); + assert_has_taddhitanta("praSasya", T::izWan, &["SrezWa", "jyezWa"]); +} + +#[test] +fn sutra_5_3_62() { + assert_has_taddhitanta("vfdDa", T::Iyasun, &["jyAyas", "varzIyas"]); + assert_has_taddhitanta("vfdDa", T::izWan, &["jyezWa", "varzizWa"]); +} + +#[test] +fn sutra_5_3_63() { + assert_has_taddhitanta("antika", T::izWan, &["nedizWa"]); + assert_has_taddhitanta("antika", T::Iyasun, &["nedIyas"]); + assert_has_taddhitanta("bAQa", T::izWan, &["sADizWa"]); + assert_has_taddhitanta("bAQa", T::Iyasun, &["sADIyas"]); +} + +#[test] +fn sutra_5_3_64() { + assert_has_taddhitanta("yuvan", T::izWan, &["kanizWa", "yavizWa"]); + assert_has_taddhitanta("yuvan", T::Iyasun, &["kanIyas", "yavIyas"]); + assert_has_taddhitanta("alpa", T::izWan, &["kanizWa", "alpizWa"]); + assert_has_taddhitanta("alpa", T::Iyasun, &["kanIyas", "alpIyas"]); +} + #[test] fn sutra_5_3_66() { - assert_has_taddhitanta(&prati("vEyAkaraRa"), T::rUpap, &["vEyAkaraRarUpa"]); - assert_has_taddhitanta(&prati("yAjYika"), T::rUpap, &["yAjYikarUpa"]); - assert_has_taddhitanta(&prati("cora"), T::rUpap, &["corarUpa"]); - assert_has_taddhitanta(&prati("dasyu"), T::rUpap, &["dasyurUpa"]); + assert_has_taddhitanta("vEyAkaraRa", T::rUpap, &["vEyAkaraRarUpa"]); + assert_has_taddhitanta("yAjYika", T::rUpap, &["yAjYikarUpa"]); + assert_has_taddhitanta("cora", T::rUpap, &["corarUpa"]); + assert_has_taddhitanta("dasyu", T::rUpap, &["dasyurUpa"]); // TODO: pacatirUpam, etc. } #[test] fn sutra_5_3_67() { - assert_has_taddhitanta(&prati("pawu"), T::kalpap, &["pawukalpa"]); - assert_has_taddhitanta(&prati("pawu"), T::deSya, &["pawudeSya"]); - assert_has_taddhitanta(&prati("pawu"), T::deSIyar, &["pawudeSIya"]); + assert_has_taddhitanta("pawu", T::kalpap, &["pawukalpa"]); + assert_has_taddhitanta("pawu", T::deSya, &["pawudeSya"]); + assert_has_taddhitanta("pawu", T::deSIyar, &["pawudeSIya"]); - assert_has_taddhitanta(&prati("mfdu"), T::kalpap, &["mfdukalpa"]); - assert_has_taddhitanta(&prati("mfdu"), T::deSya, &["mfdudeSya"]); - assert_has_taddhitanta(&prati("mfdu"), T::deSIyar, &["mfdudeSIya"]); + assert_has_taddhitanta("mfdu", T::kalpap, &["mfdukalpa"]); + assert_has_taddhitanta("mfdu", T::deSya, &["mfdudeSya"]); + assert_has_taddhitanta("mfdu", T::deSIyar, &["mfdudeSIya"]); // TODO: pacatikalpam, etc. } + +#[test] +fn sutra_5_3_68() { + assert_has_taddhitanta("pawu", T::bahuc, &["bahupawu"]); + assert_has_taddhitanta("mfdu", T::bahuc, &["bahumfdu"]); + assert_has_taddhitanta("guqa", T::bahuc, &["bahuguqa"]); +} + +#[test] +fn sutra_5_3_69() { + assert_has_taddhitanta("pawu", T::jAtIyar, &["pawujAtIya"]); + assert_has_taddhitanta("mfdu", T::jAtIyar, &["mfdujAtIya"]); + assert_has_taddhitanta("darSanIya", T::jAtIyar, &["darSanIyajAtIya"]); +} diff --git a/vidyut-prakriya/tests/kashika_5_4.rs b/vidyut-prakriya/tests/kashika_5_4.rs index 084ea77..aba90a6 100644 --- a/vidyut-prakriya/tests/kashika_5_4.rs +++ b/vidyut-prakriya/tests/kashika_5_4.rs @@ -1,7 +1,10 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; +use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; +use vidyut_prakriya::args::Unadi; #[test] fn sutra_5_4_3() { @@ -65,7 +68,40 @@ fn sutra_5_4_26() { #[test] fn sutra_5_4_27() { - assert_has_taddhitanta(&prati("deva"), T::tal, &["devatA"]); + assert_has_taddhitanta("deva", T::tal, &["devatA"]); +} + +#[test] +fn sutra_5_4_28() { + assert_has_taddhitanta("avi", T::ka, &["avika"]); +} + +#[test] +fn sutra_5_4_29() { + assert_has_taddhitanta("yAva", T::ka, &["yAvaka"]); + assert_has_taddhitanta("maRi", T::ka, &["maRika"]); +} + +#[test] +fn sutra_5_4_30_to_sutra_5_4_32() { + assert_has_taddhitanta("lohita", T::ka, &["lohitaka"]); +} + +#[test] +fn sutra_5_4_33() { + assert_has_taddhitanta("kAla", T::ka, &["kAlaka"]); +} + +#[test] +fn sutra_5_4_34() { + assert_has_taddhitanta("vinaya", T::Wak, &["vEnayika"]); + assert_has_taddhitanta("samaya", T::Wak, &["sAmayika"]); + assert_has_taddhitanta("upAya", T::Wak, &["OpAyika"]); +} + +#[test] +fn sutra_5_4_35() { + assert_has_taddhitanta("vAc", T::Wak, &["vAcika"]); } #[ignore] @@ -131,6 +167,146 @@ fn sutra_5_4_55() { #[test] fn sutra_5_4_78() { - assert_has_taddhitanta(&prati("brahmavarcas"), T::ac, &["brahmavarcasa"]); - assert_has_taddhitanta(&prati("hastivarcas"), T::ac, &["hastivarcasa"]); + assert_has_sasthi_tatpurusha("brahman", "varcas", &["brahmavarcasa"]); + assert_has_sasthi_tatpurusha("hastin", "varcas", &["hastivarcasa"]); +} + +#[test] +fn sutra_5_4_78_v1() { + assert_has_sasthi_tatpurusha("pallya", "varcas", &["pallyavarcasa"]); + assert_has_sasthi_tatpurusha("rAjan", "varcas", &["rAjavarcasa"]); +} + +#[test] +fn sutra_5_4_79() { + assert_has_avyaya_tatpurusha("ava", "tamas", &["avatamasa"]); + assert_has_avyaya_tatpurusha("sam", "tamas", &["santamasa"]); + // TODO: how to derive this? + assert_has_misc_tatpurusha("anDa", "tamas", &["anDatamasa"]); +} + +#[test] +fn sutra_5_4_80() { + assert_has_misc_tatpurusha("Svas", "vasIya", &["SvovasIya"]); + assert_has_misc_tatpurusha("Svas", "Sreyas", &["SvaHSreyasa", "SvaSSreyasa"]); +} + +#[test] +fn sutra_5_4_81() { + assert_has_avyaya_tatpurusha("anu", "rahas", &["anurahasa"]); + assert_has_avyaya_tatpurusha("ava", "rahas", &["avarahasa"]); + assert_has_misc_tatpurusha("tapta", "rahas", &["taptarahasa"]); +} + +#[test] +fn sutra_5_4_91() { + assert_has_karmadharaya("mahat", "rAjan", &["mahArAja"]); + assert_has_sasthi_tatpurusha("madra", "rAjan", &["madrarAja"]); + assert_has_karmadharaya("parama", "ahan", &["paramAha"]); + assert_has_karmadharaya("uttama", "ahan", &["uttamAha"]); + assert_has_sasthi_tatpurusha("rAjan", "saKi", &["rAjasaKa"]); + assert_has_sasthi_tatpurusha("brAhmaRa", "saKi", &["brAhmaRasaKa"]); + + // TODO: others +} + +#[test] +fn sutra_5_4_95() { + assert_has_sasthi_tatpurusha("grAma", "takzan", &["grAmatakza"]); + assert_has_sasthi_tatpurusha("kOwa", "takzan", &["kOwatakza"]); + + assert_has_sasthi_tatpurusha("rAjan", "takzan", &["rAjatakzan"]); +} + +#[test] +fn sutra_5_4_96() { + assert_has_avyaya_tatpurusha("ati", "Svan", &["atiSva"]); +} + +#[test] +fn sutra_5_4_98() { + assert_has_karmadharaya("uttama", "sakTi", &["uttamasakTa"]); + assert_has_karmadharaya("mfga", "sakTi", &["mfgasakTa"]); + assert_has_karmadharaya("pUrva", "sakTi", &["pUrvasakTa"]); + assert_has_karmadharaya("Palaka", "sakTi", &["PalakasakTa"]); +} + +#[test] +fn sutra_5_4_100() { + assert_has_misc_tatpurusha("arDa", "nO", &["arDanAva"]); +} + +#[test] +fn sutra_5_4_106() { + assert_has_samahara_dvandva(&["vAc", "tvac"], &["vAktvaca"]); + assert_has_samahara_dvandva(&["tvac", "sraj"], &["tvaksraja"]); + + assert_has_samahara_dvandva(&["samid", "dfzada"], &["samiddfzada"]); + assert_has_samahara_dvandva(&["sampad", "dvipad"], &["sampaddvipada"]); + + assert_has_samahara_dvandva(&["vAc", "vipruz"], &["vAgvipruza"]); + assert_has_samahara_dvandva(&["CAtra", "upAnah"], &["CAtropAnaha"]); + assert_has_samahara_dvandva(&["Denu", "goduh"], &["Denugoduha"]); + + // TODO: others +} + +#[ignore] +#[test] +fn sutra_5_4_108() { + assert_has_avyayibhava("upa", "rAjan", &["uparAjam"]); + assert_has_avyayibhava("prati", "rAjan", &["pratirAjam"]); + assert_has_avyayibhava("aDi", "Atman", &["aDyAtmam"]); + assert_has_avyayibhava("prati", "Atman", &["pratyAtmam"]); +} + +#[test] +fn sutra_5_4_132() { + assert_has_bahuvrihi("SArNga", "Danus", &["SArNgaDanvan"]); + assert_has_bahuvrihi("aDijya", "Danus", &["aDijyaDanvan"]); +} + +#[ignore] +#[test] +fn sutra_5_4_134() { + assert_has_bahuvrihi("yuvati", "jAyA", &["yuvajAni"]); + assert_has_bahuvrihi("vfdDa", "jAyA", &["vfdDajAni"]); +} + +#[test] +fn sutra_5_4_135() { + assert_has_bahuvrihi("ud", "ganDa", &["udganDi"]); + assert_has_bahuvrihi("pUti", "ganDa", &["pUtiganDi"]); + assert_has_bahuvrihi("su", "ganDa", &["suganDi"]); + assert_has_bahuvrihi("suraBi", "ganDa", &["suraBiganDi"]); + + assert_has_bahuvrihi("tIvra", "ganDa", &["tIvraganDa"]); + // TODO: suganDa in other sense +} + +#[test] +fn sutra_5_4_148() { + assert_has_bahuvrihi("ud", "kAkuda", &["utkAkud"]); + assert_has_bahuvrihi("vi", "kAkuda", &["vikAkud"]); +} + +#[test] +fn sutra_5_4_149() { + assert_has_bahuvrihi("pUrRa", "kAkuda", &["pUrRakAkud", "pUrRakAkuda"]); +} + +#[test] +fn sutra_5_4_150() { + assert_has_bahuvrihi("su", "hfdaya", &["suhfd", "suhfdaya"]); +} + +#[ignore] +#[test] +fn sutra_5_4_151() { + let sarpis = create_krdanta("sarpis", &[], &d("sf\\px~", Bhvadi), Unadi::isi); + let upanah = create_krdanta("upAnah", &["upa", "AN"], &d("Ra\\ha~^", Divadi), Krt::kvip); + + assert_has_bahuvrihi("vyUQa", "uras", &["vyUQoraska"]); + assert_has_bahuvrihi("priya", &sarpis, &["priyasarpizka"]); + assert_has_bahuvrihi("avamukta", &upanah, &["avamuktopAnatka"]); } diff --git a/vidyut-prakriya/tests/kashika_6_1.rs b/vidyut-prakriya/tests/kashika_6_1.rs index ef1672e..5b840f8 100644 --- a/vidyut-prakriya/tests/kashika_6_1.rs +++ b/vidyut-prakriya/tests/kashika_6_1.rs @@ -408,6 +408,15 @@ fn sutra_6_1_31() { assert_has_tip(&[], &nic(&svi), Lat, &["aSUsavat", "aSiSvayat"]); } +#[ignore] +#[test] +fn sutra_6_1_33() { + let hve = d("hve\\Y", Bhvadi); + assert_has_tip(&[], &hve, Lit, &["juhAva"]); + assert_has_ta(&[], &yan(&hve), Lat, &["johUyate"]); + assert_has_tip(&[], &san(&hve), Lat, &["juhUzati"]); +} + #[test] fn sutra_6_1_38_and_sutra_6_1_39_and_sutra_6_1_40() { let ve = d("ve\\Y", Bhvadi); @@ -1030,6 +1039,22 @@ fn sutra_6_1_114() { assert_has_sandhi("puruzas", "dadAti", &["puruzo dadAti"]); } +#[test] +fn sutra_6_1_125() { + let agni = create_sup_1d("agnI", "agni", Pum); + let vayu = create_sup_1d("vAyU", "vAyu", Pum); + let khatve = create_sup_1d("Kawve", &nyap("KawvA"), Stri); + let male = create_sup_1d("mAle", &nyap("mAlA"), Stri); + let iti = Pada::from_text("iti"); + + assert_has_vakya(&agni, &iti, &["agnI iti"]); + assert_has_vakya(&vayu, &iti, &["vAyU iti"]); + assert_has_vakya(&khatve, &iti, &["Kawve iti"]); + assert_has_vakya(&male, &iti, &["mAle iti"]); + + // TODO: pluta and others +} + #[ignore] #[test] fn sutra_6_1_135() { diff --git a/vidyut-prakriya/tests/kashika_6_3.rs b/vidyut-prakriya/tests/kashika_6_3.rs index 716cdb9..f6dd740 100644 --- a/vidyut-prakriya/tests/kashika_6_3.rs +++ b/vidyut-prakriya/tests/kashika_6_3.rs @@ -20,6 +20,18 @@ fn sutra_6_3_43() { // assert_has_taddhitanta(&prati("brAhmaRI"), T::tamap, &["brAhmaRihata"]); } +#[test] +fn sutra_6_3_46() { + assert_has_karmadharaya("mahat", "deva", &["mahAdeva"]); + assert_has_karmadharaya("mahat", "brAhmaRa", &["mahAbrAhmaRa"]); + assert_has_bahuvrihi("mahat", "bAhu", &["mahAbAhu"]); + assert_has_bahuvrihi("mahat", "bala", &["mahAbala"]); + assert_has_taddhitanta(&prati("mahat"), T::jAtIyar, &["mahAjAtIya"]); + + // samAnAdhikaraNa? + assert_has_sasthi_tatpurusha("mahat", "putra", &["mahatputra"]); +} + #[test] fn sutra_6_3_53() { assert_has_artha_taddhita("pAda", TadVidhyati, T::yat, &["padya"]); diff --git a/vidyut-prakriya/tests/kashika_6_4.rs b/vidyut-prakriya/tests/kashika_6_4.rs index 67f09b5..80de57e 100644 --- a/vidyut-prakriya/tests/kashika_6_4.rs +++ b/vidyut-prakriya/tests/kashika_6_4.rs @@ -73,8 +73,8 @@ fn sutra_6_4_3() { #[test] fn sutra_6_4_4() { - assert_has_sup_6p("tisf", Stri, &["tisfRAm"]); - assert_has_sup_6p("catasf", Stri, &["catasfRAm"]); + assert_has_sup_6p("tri", Stri, &["tisfRAm"]); + assert_has_sup_6p("catur", Stri, &["catasfRAm"]); } #[test] @@ -589,8 +589,8 @@ fn sutra_6_4_48() { assert_has_krdanta(&[], &d("vA\\", Adadi), Krt::tfc, &["vAtf"]); // ArdhadhAtuke - assert_has_taddhitanta(&prati("vfkza"), T::tva, &["vfkzatva"]); - assert_has_taddhitanta(&prati("vfkza"), T::tal, &["vfkzatA"]); + assert_has_taddhitanta("vfkza", T::tva, &["vfkzatva"]); + assert_has_taddhitanta("vfkza", T::tal, &["vfkzatA"]); // Others let hf = d("hf\\Y", Bhvadi); @@ -1085,6 +1085,16 @@ fn sutra_6_4_92() { // assert_has_tip(&[], &nic("", Bhvadi), Lat, &["jYapayati"]); } +#[test] +fn sutra_6_4_94() { + let taapi = nic(&d("ta\\pa~", Bhvadi)); + assert_has_upapada_krdanta("dvizat", &[], &taapi, Krt::Kac, &["dvizantapa"]); + assert_has_upapada_krdanta("para", &[], &taapi, Krt::Kac, &["parantapa"]); + + let daari = nic(&d("dF", Bhvadi)); + assert_has_upapada_krdanta("pur", &[], &daari, Krt::Kac, &["purandara"]); +} + #[ignore] #[test] fn sutra_6_4_96() { @@ -1633,6 +1643,7 @@ fn sutra_6_4_131() { assert_has_sup_6s("vidvas", Pum, &["viduzaH"]); assert_has_sup_3s("vidvas", Pum, &["viduzA"]); assert_has_sup_4s("vidvas", Pum, &["viduze"]); + assert_has_sup_6s("pecivas", Pum, &["pecuzaH"]); assert_has_sup_3s("pecivas", Pum, &["pecuzA"]); assert_has_sup_4s("pecivas", Pum, &["pecuze"]); @@ -1644,17 +1655,19 @@ fn sutra_6_4_133() { assert_has_sup_6s("Svan", Pum, &["SunaH"]); assert_has_sup_3s("Svan", Pum, &["SunA"]); assert_has_sup_4s("Svan", Pum, &["Sune"]); + assert_has_sup_6s("yuvan", Pum, &["yUnaH"]); assert_has_sup_3s("yuvan", Pum, &["yUnA"]); assert_has_sup_4s("yuvan", Pum, &["yUne"]); + assert_has_sup_6s("maGavan", Pum, &["maGonaH"]); assert_has_sup_3s("maGavan", Pum, &["maGonA"]); assert_has_sup_4s("maGavan", Pum, &["maGone"]); // atadDite? - assert_has_taddhitanta(&prati("Svan"), T::aY, &["SOva"]); - assert_has_taddhitanta(&prati("yuvan"), T::aR, &["yOvana"]); - assert_has_taddhitanta(&prati("maGavan"), T::aR, &["mAGavana"]); + assert_has_taddhitanta("Svan", T::aY, &["SOva"]); + assert_has_taddhitanta("yuvan", T::aR, &["yOvana"]); + assert_has_taddhitanta("maGavan", T::aR, &["mAGavana"]); // TODO: others } @@ -1664,6 +1677,7 @@ fn sutra_6_4_134() { assert_has_sup_6s("rAjan", Pum, &["rAjYaH"]); assert_has_sup_3s("rAjan", Pum, &["rAjYA"]); assert_has_sup_4s("rAjan", Pum, &["rAjYe"]); + assert_has_sup_3s("takzan", Pum, &["takzRA"]); assert_has_sup_4s("takzan", Pum, &["takzRe"]); } @@ -1690,6 +1704,7 @@ fn sutra_6_4_136() { fn sutra_6_4_137() { assert_has_sup_3s("parvan", Pum, &["parvaRA"]); assert_has_sup_4s("parvan", Pum, &["parvaRe"]); + assert_has_sup_3s("aTarvan", Pum, &["aTarvaRA"]); assert_has_sup_4s("aTarvan", Pum, &["aTarvaRe"]); @@ -1707,11 +1722,13 @@ fn sutra_6_4_137() { #[test] fn sutra_6_4_140() { - let kilalapa = dhatu_prati("kilAlapA"); + let kilalapa = create_upapada_krdanta("kilAlapA", "kilAla", &[], &d("pA\\", Adadi), Krt::vic); assert_has_sup_2p(&kilalapa, Pum, &["kilAlapaH"]); assert_has_sup_3s(&kilalapa, Pum, &["kilAlapA"]); assert_has_sup_4s(&kilalapa, Pum, &["kilAlape"]); - let shubhamya = dhatu_prati("SuBaMyA"); + + // TODO: how to derive shubhamya? For now, use SuBam as a placeholder so the test works. + let shubhamya = create_upapada_krdanta("SuBaMyA", "SuBam", &[], &d("yA\\", Adadi), Krt::vic); assert_has_sup_2p(&shubhamya, Pum, &["SuBaMyaH"]); assert_has_sup_3s(&shubhamya, Pum, &["SuBaMyA"]); assert_has_sup_4s(&shubhamya, Pum, &["SuBaMye"]); @@ -1739,17 +1756,17 @@ fn sutra_6_4_142() { #[ignore] #[test] fn sutra_6_4_143() { - assert_has_taddhitanta(&prati("kumuda"), T::qmatup, &["kumudvat"]); - assert_has_taddhitanta(&prati("naqa"), T::qmatup, &["naqvat"]); - assert_has_taddhitanta(&prati("vetasa"), T::qmatup, &["vetasvat"]); + assert_has_taddhitanta("kumuda", T::qmatup, &["kumudvat"]); + assert_has_taddhitanta("naqa", T::qmatup, &["naqvat"]); + assert_has_taddhitanta("vetasa", T::qmatup, &["vetasvat"]); // TODO: others - assert_has_taddhitanta(&prati("triMSat"), T::qvun, &["triMSaka"]); + assert_has_taddhitanta("triMSat", T::qvun, &["triMSaka"]); } #[test] fn sutra_6_4_144() { - assert_has_taddhitanta(&prati("agniSarman"), T::iY, &["AgniSarmi"]); - assert_has_taddhitanta(&prati("uquloman"), T::iY, &["Oqulomi"]); + assert_has_taddhitanta("agniSarman", T::iY, &["AgniSarmi"]); + assert_has_taddhitanta("uquloman", T::iY, &["Oqulomi"]); // naH? // taddhite? @@ -1759,165 +1776,185 @@ fn sutra_6_4_144() { #[test] fn sutra_6_4_144_v1() { - assert_has_taddhitanta(&prati("sabrahmacArin"), T::aR, &["sAbrahmacAra"]); - assert_has_taddhitanta(&prati("pIWasarpin"), T::aR, &["pEWasarpa"]); - assert_has_taddhitanta(&prati("kalApin"), T::aR, &["kAlApa"]); - assert_has_taddhitanta(&prati("kuTumin"), T::aR, &["kOTuma"]); - assert_has_taddhitanta(&prati("tEtilin"), T::aR, &["tEtila"]); - assert_has_taddhitanta(&prati("jAjalin"), T::aR, &["jAjala"]); - assert_has_taddhitanta(&prati("lANgalin"), T::aR, &["lANgala"]); - assert_has_taddhitanta(&prati("SilAlin"), T::aR, &["SElAla"]); - assert_has_taddhitanta(&prati("SiKaRqin"), T::aR, &["SEKaRqa"]); - assert_has_taddhitanta(&prati("sukarasadman"), T::aR, &["sOkarasadma"]); - assert_has_taddhitanta(&prati("suparvan"), T::aR, &["sOparva"]); + assert_has_taddhitanta("sabrahmacArin", T::aR, &["sAbrahmacAra"]); + assert_has_taddhitanta("pIWasarpin", T::aR, &["pEWasarpa"]); + assert_has_taddhitanta("kalApin", T::aR, &["kAlApa"]); + assert_has_taddhitanta("kuTumin", T::aR, &["kOTuma"]); + assert_has_taddhitanta("tEtilin", T::aR, &["tEtila"]); + assert_has_taddhitanta("jAjalin", T::aR, &["jAjala"]); + assert_has_taddhitanta("lANgalin", T::aR, &["lANgala"]); + assert_has_taddhitanta("SilAlin", T::aR, &["SElAla"]); + assert_has_taddhitanta("SiKaRqin", T::aR, &["SEKaRqa"]); + assert_has_taddhitanta("sukarasadman", T::aR, &["sOkarasadma"]); + assert_has_taddhitanta("suparvan", T::aR, &["sOparva"]); } #[test] fn sutra_6_4_146() { - assert_has_taddhitanta(&prati("baBru"), T::yaY, &["bABravya"]); - assert_has_taddhitanta(&prati("maRqu"), T::yaY, &["mARqavya"]); - assert_has_taddhitanta(&prati("SaNku"), T::yat, &["SaNkavya"]); - assert_has_taddhitanta(&prati("picu"), T::yat, &["picavya"]); - assert_has_taddhitanta(&prati("kamaRqalu"), T::yat, &["kamaRqalavya"]); - assert_has_taddhitanta(&prati("upagu"), T::aR, &["Opagava"]); - assert_has_taddhitanta(&prati("kapawu"), T::aR, &["kApawava"]); + assert_has_taddhitanta("baBru", T::yaY, &["bABravya"]); + assert_has_taddhitanta("maRqu", T::yaY, &["mARqavya"]); + assert_has_taddhitanta("SaNku", T::yat, &["SaNkavya"]); + assert_has_taddhitanta("picu", T::yat, &["picavya"]); + assert_has_taddhitanta("kamaRqalu", T::yat, &["kamaRqalavya"]); + assert_has_taddhitanta("upagu", T::aR, &["Opagava"]); + assert_has_taddhitanta("kapawu", T::aR, &["kApawava"]); // TODO: svAyamBuva } #[test] fn sutra_6_4_155() { - let patu = prati("pawu"); - assert_has_taddhitanta(&patu, T::izWan, &["pawizWa"]); - assert_has_taddhitanta(&patu, T::imanic, &["pawiman"]); - assert_has_taddhitanta(&patu, T::Iyasun, &["pawIyas"]); - let laghu = prati("laGu"); - assert_has_taddhitanta(&laghu, T::izWan, &["laGizWa"]); - assert_has_taddhitanta(&laghu, T::imanic, &["laGiman"]); - assert_has_taddhitanta(&laghu, T::Iyasun, &["laGIyas"]); + assert_has_taddhitanta("pawu", T::izWan, &["pawizWa"]); + assert_has_taddhitanta("pawu", T::imanic, &["pawiman"]); + assert_has_taddhitanta("pawu", T::Iyasun, &["pawIyas"]); + + assert_has_taddhitanta("laGu", T::izWan, &["laGizWa"]); + assert_has_taddhitanta("laGu", T::imanic, &["laGiman"]); + assert_has_taddhitanta("laGu", T::Iyasun, &["laGIyas"]); } #[test] fn sutra_6_4_156() { - assert_has_taddhitanta(&prati("sTUla"), T::izWan, &["sTavizWa"]); - assert_has_taddhitanta(&prati("sTUla"), T::Iyasun, &["sTavIyas"]); - assert_has_taddhitanta(&prati("dUra"), T::izWan, &["davizWa"]); - assert_has_taddhitanta(&prati("dUra"), T::Iyasun, &["davIyas"]); - assert_has_taddhitanta(&prati("yuvan"), T::izWan, &["yavizWa"]); - assert_has_taddhitanta(&prati("yuvan"), T::Iyasun, &["yavIyas"]); - assert_has_taddhitanta(&prati("hrasva"), T::izWan, &["hrasizWa"]); - assert_has_taddhitanta(&prati("hrasva"), T::imanic, &["hrasiman"]); - assert_has_taddhitanta(&prati("hrasva"), T::Iyasun, &["hrasIyas"]); - assert_has_taddhitanta(&prati("kzipra"), T::izWan, &["kzepizWa"]); - assert_has_taddhitanta(&prati("kzipra"), T::imanic, &["kzepiman"]); - assert_has_taddhitanta(&prati("kzipra"), T::Iyasun, &["kzepIyas"]); - assert_has_taddhitanta(&prati("kzudra"), T::izWan, &["kzodizWa"]); - assert_has_taddhitanta(&prati("kzudra"), T::imanic, &["kzodiman"]); - assert_has_taddhitanta(&prati("kzudra"), T::Iyasun, &["kzodIyas"]); + assert_has_taddhitanta("sTUla", T::izWan, &["sTavizWa"]); + assert_has_taddhitanta("sTUla", T::Iyasun, &["sTavIyas"]); + + assert_has_taddhitanta("dUra", T::izWan, &["davizWa"]); + assert_has_taddhitanta("dUra", T::Iyasun, &["davIyas"]); + + // kanizWa and kanIyas are by 5.3.64. + assert_has_taddhitanta("yuvan", T::izWan, &["yavizWa", "kanizWa"]); + assert_has_taddhitanta("yuvan", T::Iyasun, &["yavIyas", "kanIyas"]); + + assert_has_taddhitanta("hrasva", T::izWan, &["hrasizWa"]); + assert_has_taddhitanta("hrasva", T::imanic, &["hrasiman"]); + assert_has_taddhitanta("hrasva", T::Iyasun, &["hrasIyas"]); + + assert_has_taddhitanta("kzipra", T::izWan, &["kzepizWa"]); + assert_has_taddhitanta("kzipra", T::imanic, &["kzepiman"]); + assert_has_taddhitanta("kzipra", T::Iyasun, &["kzepIyas"]); + + assert_has_taddhitanta("kzudra", T::izWan, &["kzodizWa"]); + assert_has_taddhitanta("kzudra", T::imanic, &["kzodiman"]); + assert_has_taddhitanta("kzudra", T::Iyasun, &["kzodIyas"]); } #[test] fn sutra_6_4_157() { - assert_has_taddhitanta(&prati("priya"), T::izWan, &["prezWa"]); - assert_has_taddhitanta(&prati("priya"), T::imanic, &["preman"]); - assert_has_taddhitanta(&prati("priya"), T::Iyasun, &["preyas"]); - assert_has_taddhitanta(&prati("sTira"), T::izWan, &["sTezWa"]); - assert_has_taddhitanta(&prati("sTira"), T::imanic, &[]); - assert_has_taddhitanta(&prati("sTira"), T::Iyasun, &["sTeyas"]); - assert_has_taddhitanta(&prati("sPira"), T::izWan, &["sPezWa"]); - assert_has_taddhitanta(&prati("sPira"), T::imanic, &[]); - assert_has_taddhitanta(&prati("sPira"), T::Iyasun, &["sPeyas"]); - assert_has_taddhitanta(&prati("uru"), T::izWan, &["varizWa"]); - assert_has_taddhitanta(&prati("uru"), T::imanic, &["variman"]); - assert_has_taddhitanta(&prati("uru"), T::Iyasun, &["varIyas"]); - assert_has_taddhitanta(&prati("bahula"), T::izWan, &["baMhizWa"]); - assert_has_taddhitanta(&prati("bahula"), T::imanic, &["baMhiman"]); - assert_has_taddhitanta(&prati("bahula"), T::Iyasun, &["baMhIyas"]); - assert_has_taddhitanta(&prati("guru"), T::izWan, &["garizWa"]); - assert_has_taddhitanta(&prati("guru"), T::imanic, &["gariman"]); - assert_has_taddhitanta(&prati("guru"), T::Iyasun, &["garIyas"]); - assert_has_taddhitanta(&prati("vfdDa"), T::izWan, &["varzizWa"]); - assert_has_taddhitanta(&prati("vfdDa"), T::imanic, &[]); - assert_has_taddhitanta(&prati("vfdDa"), T::Iyasun, &["varzIyas"]); - assert_has_taddhitanta(&prati("tfpra"), T::izWan, &["trapizWa"]); - assert_has_taddhitanta(&prati("tfpra"), T::imanic, &[]); - assert_has_taddhitanta(&prati("tfpra"), T::Iyasun, &["trapIyas"]); - assert_has_taddhitanta(&prati("dIrGa"), T::izWan, &["drAGizWa"]); - assert_has_taddhitanta(&prati("dIrGa"), T::imanic, &["drAGiman"]); - assert_has_taddhitanta(&prati("dIrGa"), T::Iyasun, &["drAGIyas"]); - assert_has_taddhitanta(&prati("vfndAraka"), T::izWan, &["vfndizWa"]); - assert_has_taddhitanta(&prati("vfndAraka"), T::imanic, &[]); - assert_has_taddhitanta(&prati("vfndAraka"), T::Iyasun, &["vfndIyas"]); + assert_has_taddhitanta("priya", T::izWan, &["prezWa"]); + assert_has_taddhitanta("priya", T::imanic, &["preman"]); + assert_has_taddhitanta("priya", T::Iyasun, &["preyas"]); + + assert_has_taddhitanta("sTira", T::izWan, &["sTezWa"]); + assert_has_taddhitanta("sTira", T::imanic, &[]); + assert_has_taddhitanta("sTira", T::Iyasun, &["sTeyas"]); + + assert_has_taddhitanta("sPira", T::izWan, &["sPezWa"]); + assert_has_taddhitanta("sPira", T::imanic, &[]); + assert_has_taddhitanta("sPira", T::Iyasun, &["sPeyas"]); + + assert_has_taddhitanta("uru", T::izWan, &["varizWa"]); + assert_has_taddhitanta("uru", T::imanic, &["variman"]); + assert_has_taddhitanta("uru", T::Iyasun, &["varIyas"]); + + assert_has_taddhitanta("bahula", T::izWan, &["baMhizWa"]); + assert_has_taddhitanta("bahula", T::imanic, &["baMhiman"]); + assert_has_taddhitanta("bahula", T::Iyasun, &["baMhIyas"]); + + assert_has_taddhitanta("guru", T::izWan, &["garizWa"]); + assert_has_taddhitanta("guru", T::imanic, &["gariman"]); + assert_has_taddhitanta("guru", T::Iyasun, &["garIyas"]); + + // jyezWa and jyAyas are by 5.3.62. + assert_has_taddhitanta("vfdDa", T::izWan, &["varzizWa", "jyezWa"]); + assert_has_taddhitanta("vfdDa", T::imanic, &[]); + assert_has_taddhitanta("vfdDa", T::Iyasun, &["varzIyas", "jyAyas"]); + + assert_has_taddhitanta("tfpra", T::izWan, &["trapizWa"]); + assert_has_taddhitanta("tfpra", T::imanic, &[]); + assert_has_taddhitanta("tfpra", T::Iyasun, &["trapIyas"]); + + assert_has_taddhitanta("dIrGa", T::izWan, &["drAGizWa"]); + assert_has_taddhitanta("dIrGa", T::imanic, &["drAGiman"]); + assert_has_taddhitanta("dIrGa", T::Iyasun, &["drAGIyas"]); + + assert_has_taddhitanta("vfndAraka", T::izWan, &["vfndizWa"]); + assert_has_taddhitanta("vfndAraka", T::imanic, &[]); + assert_has_taddhitanta("vfndAraka", T::Iyasun, &["vfndIyas"]); } #[test] fn sutra_6_4_158() { - assert_has_taddhitanta(&prati("bahu"), T::imanic, &["BUman"]); - assert_has_taddhitanta(&prati("bahu"), T::Iyasun, &["BUyas"]); + assert_has_taddhitanta("bahu", T::imanic, &["BUman"]); + assert_has_taddhitanta("bahu", T::Iyasun, &["BUyas"]); } #[test] fn sutra_6_4_159() { - assert_has_taddhitanta(&prati("bahu"), T::izWan, &["BUyizWa"]); + assert_has_taddhitanta("bahu", T::izWan, &["BUyizWa"]); } #[test] fn sutra_6_4_160() { - assert_has_taddhitanta(&prati("jya"), T::Iyasun, &["jyAyas"]); + assert_has_taddhitanta("jya", T::Iyasun, &["jyAyas"]); } #[test] fn sutra_6_4_161() { - assert_has_taddhitanta(&prati("pfTu"), T::izWan, &["praTizWa"]); - assert_has_taddhitanta(&prati("pfTu"), T::imanic, &["praTiman"]); - assert_has_taddhitanta(&prati("pfTu"), T::Iyasun, &["praTIyas"]); - assert_has_taddhitanta(&prati("mfdu"), T::izWan, &["mradizWa"]); - assert_has_taddhitanta(&prati("mfdu"), T::imanic, &["mradiman"]); - assert_has_taddhitanta(&prati("mfdu"), T::Iyasun, &["mradIyas"]); + assert_has_taddhitanta("pfTu", T::izWan, &["praTizWa"]); + assert_has_taddhitanta("pfTu", T::imanic, &["praTiman"]); + assert_has_taddhitanta("pfTu", T::Iyasun, &["praTIyas"]); + + assert_has_taddhitanta("mfdu", T::izWan, &["mradizWa"]); + assert_has_taddhitanta("mfdu", T::imanic, &["mradiman"]); + assert_has_taddhitanta("mfdu", T::Iyasun, &["mradIyas"]); + // ftaH? - assert_has_taddhitanta(&prati("pawu"), T::izWan, &["pawizWa"]); - assert_has_taddhitanta(&prati("pawu"), T::imanic, &["pawiman"]); - assert_has_taddhitanta(&prati("pawu"), T::Iyasun, &["pawIyas"]); + assert_has_taddhitanta("pawu", T::izWan, &["pawizWa"]); + assert_has_taddhitanta("pawu", T::imanic, &["pawiman"]); + assert_has_taddhitanta("pawu", T::Iyasun, &["pawIyas"]); + // halAdeH? - assert_has_taddhitanta(&prati("fju"), T::izWan, &["fjizWa"]); - assert_has_taddhitanta(&prati("fju"), T::imanic, &["fjiman"]); - assert_has_taddhitanta(&prati("fju"), T::Iyasun, &["fjIyas"]); + assert_has_taddhitanta("fju", T::izWan, &["fjizWa"]); + assert_has_taddhitanta("fju", T::imanic, &["fjiman"]); + assert_has_taddhitanta("fju", T::Iyasun, &["fjIyas"]); + // laGoH? - assert_has_taddhitanta(&prati("kfzRA"), T::izWan, &["kfzRizWa"]); - // TODO: assert_has_taddhitanta(&prati("kfzRA"), T::imanic, &["kfzRiman"]); - assert_has_taddhitanta(&prati("kfzRA"), T::Iyasun, &["kfzRIyas"]); + assert_has_taddhitanta("kfzRA", T::izWan, &["kfzRizWa"]); + + // TODO: assert_has_taddhitanta("kfzRA", T::imanic, &["kfzRiman"]); + assert_has_taddhitanta("kfzRA", T::Iyasun, &["kfzRIyas"]); // TODO: others } #[test] fn sutra_6_4_164() { - assert_has_taddhitanta(&prati("saNkUwin"), T::aR, &["sANkUwina"]); - assert_has_taddhitanta(&prati("saMrAvin"), T::aR, &["sAMrAviRa"]); - assert_has_taddhitanta(&prati("sammArjin"), T::aR, &["sAmmArjina"]); - assert_has_taddhitanta(&prati("sragvin"), T::aR, &["srAgviRa"]); + assert_has_taddhitanta("saNkUwin", T::aR, &["sANkUwina"]); + assert_has_taddhitanta("saMrAvin", T::aR, &["sAMrAviRa"]); + assert_has_taddhitanta("sammArjin", T::aR, &["sAmmArjina"]); + assert_has_taddhitanta("sragvin", T::aR, &["srAgviRa"]); // aRi? - assert_has_taddhitanta(&prati("daRqin"), T::aY, &["dARqa"]); + assert_has_taddhitanta("daRqin", T::aY, &["dARqa"]); } #[test] fn sutra_6_4_165() { - assert_has_taddhitanta(&prati("gATin"), T::aR, &["gATina"]); - assert_has_taddhitanta(&prati("vidaTin"), T::aR, &["vEdaTina"]); - assert_has_taddhitanta(&prati("keSin"), T::aR, &["kESina"]); - assert_has_taddhitanta(&prati("gaRin"), T::aR, &["gARina"]); - assert_has_taddhitanta(&prati("paRin"), T::aR, &["pARina"]); + assert_has_taddhitanta("gATin", T::aR, &["gATina"]); + assert_has_taddhitanta("vidaTin", T::aR, &["vEdaTina"]); + assert_has_taddhitanta("keSin", T::aR, &["kESina"]); + assert_has_taddhitanta("gaRin", T::aR, &["gARina"]); + assert_has_taddhitanta("paRin", T::aR, &["pARina"]); } #[test] fn sutra_6_4_166() { - assert_has_taddhitanta(&prati("SaNKin"), T::aR, &["SANKina"]); - assert_has_taddhitanta(&prati("madrin"), T::aR, &["mAdriRa"]); - assert_has_taddhitanta(&prati("vajrin"), T::aR, &["vAjriRa"]); + assert_has_taddhitanta("SaNKin", T::aR, &["SANKina"]); + assert_has_taddhitanta("madrin", T::aR, &["mAdriRa"]); + assert_has_taddhitanta("vajrin", T::aR, &["vAjriRa"]); } #[test] fn sutra_6_4_167() { - assert_has_taddhitanta(&prati("sAman"), T::aR, &["sAmana"]); - assert_has_taddhitanta(&prati("veman"), T::aR, &["vEmana"]); - assert_has_taddhitanta(&prati("sutvan"), T::aR, &["sOtvana"]); - assert_has_taddhitanta(&prati("jitvan"), T::aR, &["jEtvana"]); + assert_has_taddhitanta("sAman", T::aR, &["sAmana"]); + assert_has_taddhitanta("veman", T::aR, &["vEmana"]); + assert_has_taddhitanta("sutvan", T::aR, &["sOtvana"]); + assert_has_taddhitanta("jitvan", T::aR, &["jEtvana"]); } diff --git a/vidyut-prakriya/tests/kashika_7_1.rs b/vidyut-prakriya/tests/kashika_7_1.rs index b35830e..3dfa7ea 100644 --- a/vidyut-prakriya/tests/kashika_7_1.rs +++ b/vidyut-prakriya/tests/kashika_7_1.rs @@ -693,6 +693,70 @@ fn sutra_7_1_73() { assert_has_sup_1d("pIWa", Napumsaka, &["pIWe"]); } +#[test] +fn sutra_7_1_78() { + let dadat = create_krdanta("dadat", &[], &d("qudA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1s(&dadat, Pum, &["dadat"]); + assert_has_sup_1d(&dadat, Pum, &["dadatO"]); + assert_has_sup_1p(&dadat, Pum, &["dadataH"]); + + let dadhat = create_krdanta("daDat", &[], &d("quDA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1s(&dadhat, Pum, &["daDat"]); + assert_has_sup_1d(&dadhat, Pum, &["daDatO"]); + assert_has_sup_1p(&dadhat, Pum, &["daDataH"]); + + let jakshat = create_krdanta("jakzat", &[], &d("jakza~", Adadi), Krt::Satf); + assert_has_sup_1s(&jakshat, Pum, &["jakzat"]); + assert_has_sup_1d(&jakshat, Pum, &["jakzatO"]); + assert_has_sup_1p(&jakshat, Pum, &["jakzataH"]); + + let jagrat = create_krdanta("jAgrat", &[], &d("jAgf", Adadi), Krt::Satf); + assert_has_sup_1s(&jagrat, Pum, &["jAgrat"]); + assert_has_sup_1d(&jagrat, Pum, &["jAgratO"]); + assert_has_sup_1p(&jagrat, Pum, &["jAgrataH"]); +} + +#[test] +fn sutra_7_1_79() { + let dadat = create_krdanta("dadat", &[], &d("qudA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1p(&dadat, Napumsaka, &["dadati", "dadanti"]); + + let dadhat = create_krdanta("daDat", &[], &d("quDA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1p(&dadhat, Napumsaka, &["daDati", "daDanti"]); + + let jakshat = create_krdanta("jakzat", &[], &d("jakza~", Adadi), Krt::Satf); + assert_has_sup_1p(&jakshat, Napumsaka, &["jakzati", "jakzanti"]); + + let jagrat = create_krdanta("jAgrat", &[], &d("jAgf", Adadi), Krt::Satf); + assert_has_sup_1p(&jagrat, Napumsaka, &["jAgrati", "jAgranti"]); +} + +#[test] +fn sutra_7_1_80() { + let tudat = create_krdanta("tudat", &[], &d("tu\\da~^", Tudadi), Krt::Satf); + assert_has_sup_1d(&tudat, Napumsaka, &["tudatI", "tudantI"]); + assert_has_sup_1s(&tudat, Stri, &["tudatI", "tudantI"]); + + let yaat = create_krdanta("yAt", &[], &d("yA\\", Adadi), Krt::Satf); + assert_has_sup_1d(&yaat, Napumsaka, &["yAtI", "yAntI"]); + assert_has_sup_1s(&yaat, Stri, &["yAtI", "yAntI"]); +} + +#[test] +fn sutra_7_1_81() { + let pacat = create_krdanta("pacat", &[], &d("qupa\\ca~^z", Bhvadi), Krt::Satf); + assert_has_sup_1d(&pacat, Napumsaka, &["pacantI"]); + assert_has_sup_1s(&pacat, Stri, &["pacantI"]); + + let divyat = create_krdanta("dIvyat", &[], &d("divu~", Divadi), Krt::Satf); + assert_has_sup_1d(&divyat, Napumsaka, &["dIvyantI"]); + assert_has_sup_1s(&divyat, Stri, &["dIvyantI"]); + + let sivyat = create_krdanta("sIvyat", &[], &d("zivu~", Divadi), Krt::Satf); + assert_has_sup_1d(&sivyat, Napumsaka, &["sIvyantI"]); + assert_has_sup_1s(&sivyat, Stri, &["sIvyantI"]); +} + #[test] fn sutra_7_1_84() { assert_has_sup_1s("div", Stri, &["dyOH"]); @@ -752,7 +816,6 @@ fn sutra_7_1_88() { assert_has_sup_4s("fBukzin", Pum, &["fBukze"]); } -#[ignore] #[test] fn sutra_7_1_89() { assert_has_sup_1s("pums", Pum, &["pumAn"]); diff --git a/vidyut-prakriya/tests/kashika_8_2.rs b/vidyut-prakriya/tests/kashika_8_2.rs index 3e075af..60e9860 100644 --- a/vidyut-prakriya/tests/kashika_8_2.rs +++ b/vidyut-prakriya/tests/kashika_8_2.rs @@ -21,9 +21,9 @@ fn sutra_8_2_7() { assert_has_sup_1s("rAjan", Pum, &["rAjA"]); assert_has_sup_3d("rAjan", Pum, &["rAjaByAm"]); assert_has_sup_3p("rAjan", Pum, &["rAjaBiH"]); - assert_has_taddhitanta(&prati("rAjan"), T::tal, &["rAjatA"]); - assert_has_taddhitanta(&prati("rAjan"), T::tarap, &["rAjatara"]); - assert_has_taddhitanta(&prati("rAjan"), T::tamap, &["rAjatama"]); + assert_has_taddhitanta("rAjan", T::tal, &["rAjatA"]); + assert_has_taddhitanta("rAjan", T::tarap, &["rAjatara"]); + assert_has_taddhitanta("rAjan", T::tamap, &["rAjatama"]); } #[test] @@ -35,35 +35,35 @@ fn sutra_8_2_8() { #[test] fn sutra_8_2_9() { // makAra-anta - assert_has_taddhitanta(&prati("kim"), T::matup, &["kiMvat"]); - assert_has_taddhitanta(&prati("Sam"), T::matup, &["SaMvat"]); + assert_has_taddhitanta("kim", T::matup, &["kiMvat"]); + assert_has_taddhitanta("Sam", T::matup, &["SaMvat"]); // makAra-upadha - assert_has_taddhitanta(&prati("SamI"), T::matup, &["SamIvat"]); - assert_has_taddhitanta(&prati("dAqimI"), T::matup, &["dAqimIvat"]); + assert_has_taddhitanta("SamI", T::matup, &["SamIvat"]); + assert_has_taddhitanta("dAqimI", T::matup, &["dAqimIvat"]); // avarRa-anta - assert_has_taddhitanta(&prati("vfkza"), T::matup, &["vfkzavat"]); - assert_has_taddhitanta(&prati("plakza"), T::matup, &["plakzavat"]); - assert_has_taddhitanta(&prati("KawvA"), T::matup, &["KawvAvat"]); - assert_has_taddhitanta(&prati("mAlA"), T::matup, &["mAlAvat"]); + assert_has_taddhitanta("vfkza", T::matup, &["vfkzavat"]); + assert_has_taddhitanta("plakza", T::matup, &["plakzavat"]); + assert_has_taddhitanta("KawvA", T::matup, &["KawvAvat"]); + assert_has_taddhitanta("mAlA", T::matup, &["mAlAvat"]); // avarRa-upaDa - assert_has_taddhitanta(&prati("payas"), T::matup, &["payasvat"]); - assert_has_taddhitanta(&prati("yaSas"), T::matup, &["yaSasvat"]); - assert_has_taddhitanta(&prati("BAs"), T::matup, &["BAsvat"]); + assert_has_taddhitanta("payas", T::matup, &["payasvat"]); + assert_has_taddhitanta("yaSas", T::matup, &["yaSasvat"]); + assert_has_taddhitanta("BAs", T::matup, &["BAsvat"]); // mAd? - assert_has_taddhitanta(&prati("agni"), T::matup, &["agnimat"]); - assert_has_taddhitanta(&prati("vAyu"), T::matup, &["vAyumat"]); + assert_has_taddhitanta("agni", T::matup, &["agnimat"]); + assert_has_taddhitanta("vAyu", T::matup, &["vAyumat"]); // avAdibhyaH? - assert_has_taddhitanta(&prati("yava"), T::matup, &["yavamat"]); - assert_has_taddhitanta(&prati("dalmi"), T::matup, &["dalmimat"]); - assert_has_taddhitanta(&prati("Urmi"), T::matup, &["Urmimat"]); + assert_has_taddhitanta("yava", T::matup, &["yavamat"]); + assert_has_taddhitanta("dalmi", T::matup, &["dalmimat"]); + assert_has_taddhitanta("Urmi", T::matup, &["Urmimat"]); } #[test] fn sutra_8_2_10() { - assert_has_taddhitanta(&prati("agnicit"), T::matup, &["agnicitvat"]); - assert_has_taddhitanta(&prati("vidyut"), T::matup, &["vidyutvat"]); - assert_has_taddhitanta(&prati("marut"), T::matup, &["marutvat"]); - assert_has_taddhitanta(&prati("dfzad"), T::matup, &["dfzadvat"]); + assert_has_taddhitanta("agnicit", T::matup, &["agnicitvat"]); + assert_has_taddhitanta("vidyut", T::matup, &["vidyutvat"]); + assert_has_taddhitanta("marut", T::matup, &["marutvat"]); + assert_has_taddhitanta("dfzad", T::matup, &["dfzadvat"]); } #[test] @@ -505,20 +505,25 @@ fn sutra_8_2_42() { assert_has_krdanta(&["vi"], &d("SFY", Kryadi), Krt::kta, &["viSIrRa"]); assert_has_krdanta(&["ni"], &d("gF", Tudadi), Krt::kta, &["nigIrRa"]); assert_has_krdanta(&["ava"], &d("gurvI~\\", Divadi), Krt::kta, &["avagUrRa"]); + // dakArAt let bhid = d("Bi\\di~^r", Rudhadi); assert_has_krdanta(&[], &bhid, Krt::kta, &["Binna"]); assert_has_krdanta(&[], &bhid, Krt::ktavatu, &["Binnavat"]); + let chid = d("Ci\\di~^r", Rudhadi); assert_has_krdanta(&[], &chid, Krt::kta, &["Cinna"]); assert_has_krdanta(&[], &chid, Krt::ktavatu, &["Cinnavat"]); + // radAByAm let kf = d("qukf\\Y", Tanadi); assert_has_krdanta(&[], &kf, Krt::kta, &["kfta"]); assert_has_krdanta(&[], &kf, Krt::ktavatu, &["kftavat"]); + // nizWA? assert_has_krdanta(&[], &kf, Krt::tfc, &["kartf"]); assert_has_krdanta(&[], &d("hf\\Y", Bhvadi), Krt::tfc, &["hartf"]); + // taH assert_has_krdanta(&[], &d("cara~", Bhvadi), Krt::kta, &["carita"]); assert_has_krdanta(&[], &d("muda~\\", Bhvadi), Krt::kta, &["mudita"]); @@ -530,20 +535,25 @@ fn sutra_8_2_43() { let dra = d("drA\\", Adadi); assert_has_krdanta(&["pra"], &dra, Krt::kta, &["pradrARa"]); assert_has_krdanta(&["pra"], &dra, Krt::ktavatu, &["pradrARavat"]); + let mlai = d("mlE\\", Bhvadi); assert_has_krdanta(&[], &mlai, Krt::kta, &["mlAna"]); assert_has_krdanta(&[], &mlai, Krt::ktavatu, &["mlAnavat"]); + // saMyogAdeH let yaa = d("yA\\", Adadi); assert_has_krdanta(&[], &yaa, Krt::kta, &["yAta"]); assert_has_krdanta(&[], &yaa, Krt::ktavatu, &["yAtavat"]); + // AtaH let cyu = d("cyu\\N", Bhvadi); assert_has_krdanta(&[], &cyu, Krt::kta, &["cyuta"]); assert_has_krdanta(&[], &cyu, Krt::ktavatu, &["cyutavat"]); + let plu = d("plu\\N", Bhvadi); assert_has_krdanta(&[], &plu, Krt::kta, &["pluta"]); assert_has_krdanta(&[], &plu, Krt::ktavatu, &["plutavat"]); + // DAtoH assert_has_krdanta(&["nis"], &yaa, Krt::kta, &["niryAta"]); assert_has_krdanta( @@ -822,14 +832,13 @@ fn sutra_8_2_79() { assert_has_tip(&[], &d("Cura~", Tanadi), AshirLin, &["CuryAt"]); } -#[ignore] #[test] fn sutra_8_2_80() { assert_has_sup_2s("adas", Pum, &["amum"]); assert_has_sup_2d("adas", Pum, &["amU"]); assert_has_sup_2p("adas", Pum, &["amUn"]); // TODO: - // assert_has_sup_3s("adas", Pum, &["amunA"]); + assert_has_sup_3s("adas", Pum, &["amunA"]); assert_has_sup_3d("adas", Pum, &["amUByAm"]); // aseH assert_has_sup_1s("adas", Napumsaka, &["adaH"]); diff --git a/vidyut-prakriya/tests/kashika_8_3.rs b/vidyut-prakriya/tests/kashika_8_3.rs index 0cbdf39..891b928 100644 --- a/vidyut-prakriya/tests/kashika_8_3.rs +++ b/vidyut-prakriya/tests/kashika_8_3.rs @@ -4,6 +4,8 @@ use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Taddhita as T; +use vidyut_prakriya::args::Unadi; #[test] fn sutra_8_3_13() { @@ -75,19 +77,19 @@ fn sutra_8_3_23() { assert_has_ta_k(&[], &d("ra\\ma~\\", Bhvadi), Lat, &["ramyate"]); } -#[ignore] #[test] fn sutra_8_3_24() { assert_has_sup_1p("payas", Napumsaka, &["payAMsi"]); assert_has_sup_1p("yaSas", Napumsaka, &["yaSAMsi"]); - assert_has_sup_1p("sarpis", Napumsaka, &["sarpIMzi"]); + let sarpis = create_krdanta("sarpis", &[], &d("sf\\px~", Bhvadi), Unadi::isi); + assert_has_sup_1p(&sarpis, Napumsaka, &["sarpIMzi"]); // makArasya let kram = d("kramu~", Bhvadi); assert_has_ta(&["AN"], &kram, Lrt, &["AkraMsyate"]); assert_has_ta_k(&["AN"], &san(&kram), Lat, &["AcikraMsyate"]); - assert_has_lat(&["aDi"], &san(&d("i\\N", Adadi)), &["aDijigaMsate"]); + assert_has_lat(&["aDi"], &san(&d("i\\N", Adadi)), &["aDijigAMsate"]); // Jali assert_has_ta_k(&[], &d("ra\\ma~\\", Bhvadi), Lat, &["ramyate"]); @@ -142,6 +144,18 @@ fn sutra_8_3_55() { // TODO: apadAntasya } +#[test] +fn sutra_8_3_59() { + assert_has_tip(&[], &d("zivu~", Divadi), Lit, &["sizeva"]); + assert_has_tip(&[], &d("Yizva\\pa~", Adadi), Lit, &["suzvApa"]); + assert_has_sup_7p("agni", Pum, &["agnizu"]); + assert_has_sup_7p("vAyu", Pum, &["vAyuzu"]); + assert_has_sup_7p("kartf", Pum, &["kartfzu"]); + assert_has_sup_7p("hartf", Pum, &["hartfzu"]); + + // TODO: others +} + #[test] fn sutra_8_3_60() { let shas = d("SAsu~", Adadi); @@ -163,6 +177,18 @@ fn sutra_8_3_60() { // TODO: others } +#[test] +fn sutra_8_3_62() { + let svid_nic_san = nic_san(&d("YizvidA~", Bhvadi)); + assert_has_tip(&[], &svid_nic_san, Lat, &["sisvedayizati"]); + + let svad_nic_san = nic_san(&d("zvada~\\", Bhvadi)); + assert_has_tip(&[], &svad_nic_san, Lat, &["sisvAdayizati"]); + + let sah_nic_san = nic_san(&d("zaha~\\", Bhvadi)); + assert_has_tip(&[], &sah_nic_san, Lat, &["sisAhayizati"]); +} + #[test] fn sutra_8_3_61() { let svap = d("Yizva\\pa~", Adadi); @@ -182,6 +208,7 @@ fn sutra_8_3_61() { assert_has_tip(&[], &sic, Lit, &["sizeca"]); assert_has_lat(&[], &san(&svap), &["suzupsati"]); assert_has_tip(&[], &san(&d("zWA\\", Bhvadi)), Lat, &["tizWAsati"]); + // TODO: others } @@ -202,9 +229,99 @@ fn sutra_8_3_63() { fn sutra_8_3_64() { // TODO: others let stha = d("zWA\\", Bhvadi); - assert_has_tip(&["aBi"], &stha, Lit, &["aBitazWO"]); assert_has_tip(&["pari"], &stha, Lit, &["paritazWO"]); + + let sic = d("zi\\ca~^", Tudadi); + assert_has_tip(&["aBi"], &san(&sic), Lat, &["aBizizikzati"]); + assert_has_tip(&["pari"], &san(&sic), Lat, &["parizizikzati"]); + + let sush = d("zu\\Y", Svadi); + assert_has_tip(&["aBi"], &san(&sush), Lat, &["aBisusUzati"]); +} + +#[test] +fn sutra_8_3_65() { + let su = d("zu\\Y", Svadi); + assert_has_tip(&["aBi"], &su, Lat, &["aBizuRoti"]); + assert_has_tip(&["pari"], &su, Lat, &["parizuRoti"]); + assert_has_tip(&["aBi"], &su, Lan, &["aByazuRot"]); + assert_has_tip(&["pari"], &su, Lan, &["paryazuRot"]); + + let suu = d("zU", Tudadi); + assert_has_tip(&["aBi"], &suu, Lat, &["aBizuvati"]); + assert_has_tip(&["pari"], &suu, Lat, &["parizuvati"]); + assert_has_tip(&["aBi"], &suu, Lan, &["aByazuvat"]); + assert_has_tip(&["pari"], &suu, Lan, &["paryazuvat"]); + + let so = d("zo\\", Divadi); + assert_has_tip(&["aBi"], &so, Lat, &["aBizyati"]); + assert_has_tip(&["pari"], &so, Lat, &["parizyati"]); + assert_has_tip(&["aBi"], &so, Lan, &["aByazyat"]); + assert_has_tip(&["pari"], &so, Lan, &["paryazyat"]); + + let stu = d("zwu\\Y", Adadi); + assert_has_tip(&["aBi"], &stu, Lat, &["aBizwOti", "aBizwavIti"]); + assert_has_tip(&["pari"], &stu, Lat, &["parizwOti", "parizwavIti"]); + assert_has_tip(&["aBi"], &stu, Lan, &["aByazwOt", "aByazwavIt"]); + // non-shatva forms are by 8.3.71. + assert_has_tip( + &["pari"], + &stu, + Lan, + &["paryazwOt", "paryazwavIt", "paryastOt", "paryastavIt"], + ); + + let stubh = d("zwuBu~\\", Bhvadi); + assert_has_ta(&["aBi"], &stubh, Lat, &["aBizwoBate"]); + assert_has_ta(&["pari"], &stubh, Lat, &["parizwoBate"]); + assert_has_ta(&["aBi"], &stubh, Lan, &["aByazwoBata"]); + assert_has_ta(&["pari"], &stubh, Lan, &["paryazwoBata"]); + + let sthaa = d("zWA\\", Bhvadi); + assert_has_tip(&["aBi"], &sthaa, Lrt, &["aBizWAsyati"]); + assert_has_tip(&["pari"], &sthaa, Lrt, &["parizWAsyati"]); + assert_has_tip(&["aBi"], &sthaa, Lun, &["aByazWAt"]); + assert_has_tip(&["pari"], &sthaa, Lun, &["paryazWAt"]); + assert_has_tip(&["aBi"], &sthaa, Lit, &["aBitazWO"]); + assert_has_tip(&["pari"], &sthaa, Lit, &["paritazWO"]); + + // TODO: senaya + + let sidh = d("ziDU~", Bhvadi); + assert_has_tip(&["aBi"], &sidh, Lat, &["aBizeDati"]); + assert_has_tip(&["pari"], &sidh, Lat, &["parizeDati"]); + assert_has_tip(&["aBi"], &sidh, Lan, &["aByazeDat"]); + assert_has_tip(&["pari"], &sidh, Lan, &["paryazeDat"]); + + let sic = d("zi\\ca~^", Tudadi); + assert_has_tip(&["aBi"], &sic, Lat, &["aBiziYcati"]); + assert_has_tip(&["pari"], &sic, Lat, &["pariziYcati"]); + assert_has_tip(&["aBi"], &sic, Lan, &["aByaziYcat"]); + assert_has_tip(&["pari"], &sic, Lan, &["paryaziYcat"]); + assert_has_tip(&["aBi"], &san(&sic), Lat, &["aBizizikzati"]); + assert_has_tip(&["pari"], &san(&sic), Lat, &["parizizikzati"]); + + let sanj = d("za\\nja~", Bhvadi); + assert_has_tip(&["aBi"], &sanj, Lat, &["aBizajati"]); + assert_has_tip(&["pari"], &sanj, Lat, &["parizajati"]); + assert_has_tip(&["aBi"], &sanj, Lan, &["aByazajat"]); + assert_has_tip(&["pari"], &sanj, Lan, &["paryazajat"]); + assert_has_tip(&["aBi"], &san(&sanj), Lat, &["aBizizaNkzati"]); + assert_has_tip(&["pari"], &san(&sanj), Lat, &["parizizaNkzati"]); + + let svanj = d("zva\\nja~\\", Bhvadi); + assert_has_ta(&["aBi"], &svanj, Lat, &["aBizvajate"]); + assert_has_ta(&["pari"], &svanj, Lat, &["parizvajate"]); + assert_has_ta(&["aBi"], &svanj, Lan, &["aByazvajata"]); + // non-shatva forms are by 8.3.71. + assert_has_ta(&["pari"], &svanj, Lan, &["paryazvajata", "paryasvajata"]); + assert_has_ta(&["aBi"], &san(&svanj), Lat, &["aBizizvaNkzate"]); + assert_has_ta(&["pari"], &san(&svanj), Lat, &["parizizvaNkzate"]); + + // upasargAt? + assert_has_sandhi("daDi", "siYcati", &["daDi siYcati"]); + assert_has_sandhi("maDu", "siYcati", &["maDu siYcati"]); } #[test] @@ -341,6 +458,9 @@ fn sutra_8_3_70() { assert_has_lan(&["pari"], &svanj, &["paryazvajata", "paryasvajata"]); } +#[test] +fn sutra_8_3_71() {} + #[test] fn sutra_8_3_72() { let syand = d("syandU~\\", Bhvadi); @@ -461,6 +581,14 @@ fn sutra_8_3_110() { // TODO: others? } +#[test] +fn sutra_8_3_111() { + assert_has_taddhitanta(&prati("agni"), T::sAti, &["agnisAt"]); + assert_has_taddhitanta(&prati("daDi"), T::sAti, &["daDisAt"]); + assert_has_sandhi("daDi", "siYcati", &["daDi siYcati"]); + assert_has_sandhi("maDu", "siYcati", &["maDu siYcati"]); +} + #[test] fn sutra_8_3_112() { let sic = d("zi\\ca~^", Tudadi); @@ -495,6 +623,22 @@ fn sutra_8_3_115() { assert_has_lat(&["pari"], &sah, &["parizahate"]); } +#[ignore] +#[test] +fn sutra_8_3_116() { + let stanbh = nic(&d("stanBu~", Kryadi)); + assert_has_tip(&["pari"], &stanbh, Lun, &["paryatastamBat"]); + assert_has_tip(&["aBi"], &stanbh, Lun, &["aByatastamBat"]); + + let siv = nic(&d("zivu~", Divadi)); + assert_has_tip(&["pari"], &siv, Lun, &["paryasIzivat"]); + assert_has_tip(&["ni"], &siv, Lun, &["nyasIzivat"]); + + let sah = nic(&d("zaha~\\", Bhvadi)); + assert_has_tip(&["pari"], &sah, Lun, &["paryasIzahat"]); + assert_has_tip(&["vi"], &sah, Lun, &["vyasIzahat"]); +} + #[test] fn sutra_8_3_117() { let sush = d("zu\\Y", Svadi); diff --git a/vidyut-prakriya/tests/kashika_8_4.rs b/vidyut-prakriya/tests/kashika_8_4.rs index 7b68169..33b7a54 100644 --- a/vidyut-prakriya/tests/kashika_8_4.rs +++ b/vidyut-prakriya/tests/kashika_8_4.rs @@ -489,6 +489,28 @@ fn sutra_8_4_60() { assert_has_sandhi("BavAn", "lunAti", &["BavA~l lunAti"]); } +#[test] +fn sutra_8_4_61() { + let stha = d("zWA\\", Bhvadi); + assert_has_krdanta(&["ud"], &stha, Krt::tfc, &["utTAtf", "utTTAtf"]); + assert_has_krdanta(&["ud"], &stha, Krt::tumun, &["utTAtum", "utTTAtum"]); + assert_has_krdanta(&["ud"], &stha, Krt::tavya, &["utTAtavya", "utTTAtavya"]); + + let stanbh = d("stanBu~", Kryadi); + assert_has_krdanta(&["ud"], &stanbh, Krt::tfc, &["uttamBitf", "utTtamBitf"]); + assert_has_krdanta(&["ud"], &stanbh, Krt::tumun, &["uttamBitum", "utTtamBitum"]); + assert_has_krdanta( + &["ud"], + &stanbh, + Krt::tavya, + &["uttamBitavya", "utTtamBitavya"], + ); + + // sthA-stambhoH? + let snaa = d("zRA\\", Adadi); + assert_has_krdanta(&["ud"], &snaa, Krt::tfc, &["utsnAtf"]); +} + #[test] fn sutra_8_4_62() { assert_has_sandhi("vAk", "hasati", &["vAg Gasati", "vAg hasati"]); diff --git a/vidyut-prakriya/tests/kaumudi_10.rs b/vidyut-prakriya/tests/kaumudi_10.rs index 2dbded4..1532e44 100644 --- a/vidyut-prakriya/tests/kaumudi_10.rs +++ b/vidyut-prakriya/tests/kaumudi_10.rs @@ -20,29 +20,80 @@ fn sk_311() { fn skip_sk_312_to_sk_313() {} #[test] -fn sk_315() { +fn sk_314() { assert_has_sup_1p("jYAna", Napumsaka, &["jYAnAni"]); } #[test] -fn skip_sk_316() {} +fn skip_sk_315() {} + +#[test] +fn sk_316() { + assert_has_sup_1s("katara", Napumsaka, &["katarat"]); + assert_has_sup_1d("katara", Napumsaka, &["katare"]); + assert_has_sup_1p("katara", Napumsaka, &["katarARi"]); + assert_has_sup_ss("katara", Napumsaka, &["katarat"]); + + assert_has_sup_1s("katama", Napumsaka, &["katamat"]); + assert_has_sup_1s("anya", Napumsaka, &["anyat"]); + assert_has_sup_1s("anyatara", Napumsaka, &["anyatarat"]); + assert_has_sup_1s("itara", Napumsaka, &["itarat"]); + + assert_has_sup_1s("ekatara", Napumsaka, &["ekataram"]); + + // TODO: ajaras +} + +#[test] +fn sk_318() { + assert_has_sup_1s("SrIpA", Napumsaka, &["SrIpam"]); + assert_has_sup_4s("SrIpA", Napumsaka, &["SrIpAya"]); +} #[test] fn sk_319() { assert_has_sup_1s("vAri", Napumsaka, &["vAri"]); } -#[ignore] #[test] fn sk_320() { assert_has_sup_1d("vAri", Napumsaka, &["vAriRI"]); assert_has_sup_1p("vAri", Napumsaka, &["vArIRi"]); - assert_has_sup_ss("vAri", Napumsaka, &["vAri", "vAre"]); + // TODO: how to justify vAre? + assert_has_sup_ss("vAri", Napumsaka, &["vAri"]); assert_has_sup_3s("vAri", Napumsaka, &["vAriRA"]); assert_has_sup_4s("vAri", Napumsaka, &["vAriRe"]); assert_has_sup_5s("vAri", Napumsaka, &["vAriRaH"]); assert_has_sup_6d("vAri", Napumsaka, &["vAriRoH"]); assert_has_sup_6p("vAri", Napumsaka, &["vArIRAm"]); - assert_has_sup_7s("vAri", Napumsaka, &["vArIRi"]); - assert_has_sup_7d("vAri", Napumsaka, &["vArIRoH"]); + assert_has_sup_7s("vAri", Napumsaka, &["vAriRi"]); + assert_has_sup_7d("vAri", Napumsaka, &["vAriRoH"]); +} + +#[test] +fn sk_322() { + assert_has_sup_3s("daDi", Napumsaka, &["daDnA"]); +} + +#[ignore] +#[test] +fn sk_323() { + assert_has_sup_1s("pradyo", Napumsaka, &["pradyu"]); + assert_has_sup_1d("pradyo", Napumsaka, &["pradyunI"]); + assert_has_sup_1p("pradyo", Napumsaka, &["pradyUni"]); + assert_has_sup_3s("pradyo", Napumsaka, &["pradyunA"]); + + assert_has_sup_1s("prarE", Napumsaka, &["prari"]); + assert_has_sup_1d("prarE", Napumsaka, &["prariRI"]); + assert_has_sup_1p("prarE", Napumsaka, &["prarIRi"]); + assert_has_sup_3s("prarE", Napumsaka, &["prariRA"]); + assert_has_sup_3d("prarE", Napumsaka, &["prarAByAm"]); + assert_has_sup_3p("prarE", Napumsaka, &["prarABiH"]); + assert_has_sup_6p("prarE", Napumsaka, &["prarIRAm"]); + + assert_has_sup_1s("sunu", Napumsaka, &["sunu"]); + assert_has_sup_1d("sunu", Napumsaka, &["sununI"]); + assert_has_sup_1p("sunu", Napumsaka, &["sunUni"]); + assert_has_sup_3s("sunu", Napumsaka, &["sununA"]); + assert_has_sup_4s("sunu", Napumsaka, &["sunune"]); } diff --git a/vidyut-prakriya/tests/kaumudi_11.rs b/vidyut-prakriya/tests/kaumudi_11.rs index 5b21f09..3a56ce3 100644 --- a/vidyut-prakriya/tests/kaumudi_11.rs +++ b/vidyut-prakriya/tests/kaumudi_11.rs @@ -1,6 +1,11 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::Gana::*; +use vidyut_prakriya::args::Lakara::*; use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Pratipadika; +use vidyut_prakriya::args::SamasaType::*; +use vidyut_prakriya::args::{BaseKrt as Krt, Gana}; #[test] fn sk_324() { @@ -15,20 +20,128 @@ fn sk_324() { assert_has_sup_7p("lih", Pum, &["liwtsu", "liwsu"]); } -#[ignore] #[test] -fn sk_325() { +fn skip_sk_325() {} + +#[test] +fn sk_326() { assert_has_sup_1s("gardaB", Pum, &["gardap"]); - assert_has_sup_1s("duh", Pum, &["Duk"]); - assert_has_sup_1d("duh", Pum, &["duhO"]); - assert_has_sup_1p("duh", Pum, &["duhaH"]); - assert_has_sup_7p("duh", Pum, &["Dukzu"]); + let duh = d("du\\ha~^", Gana::Adadi); + assert_has_krdanta(&[], &duh, Krt::kta, &["dugDa"]); + assert_has_krdanta(&[], &duh, Krt::tfc, &["dogDf"]); + + let duh = dhatu_prati("duh"); + assert_has_sup_1s(&duh, Pum, &["Duk"]); + assert_has_sup_1d(&duh, Pum, &["duhO"]); + assert_has_sup_1p(&duh, Pum, &["duhaH"]); + assert_has_sup_7p(&duh, Pum, &["Dukzu"]); +} + +#[test] +fn sk_327() { + let druh = create_krdanta("druh", &[], &d("dru\\ha~", Divadi), Krt::kvip); + assert_has_sup_1s(&druh, Pum, &["Druk", "Druw"]); + assert_has_sup_1d(&druh, Pum, &["druhO"]); + assert_has_sup_1p(&druh, Pum, &["druhaH"]); + assert_has_sup_5d(&druh, Pum, &["DrugByAm", "DruqByAm"]); + assert_has_sup_7p(&druh, Pum, &["Drukzu", "Druwtsu", "Druwsu"]); + + let vishvavah = + create_upapada_krdanta("viSvavAh", "viSva", &[], &d("va\\ha~^", Bhvadi), Krt::Rvi); + assert_has_sup_1s(&vishvavah, Pum, &["viSvavAw"]); + assert_has_sup_1d(&vishvavah, Pum, &["viSvavAhO"]); + assert_has_sup_1p(&vishvavah, Pum, &["viSvavAhaH"]); + assert_has_sup_2s(&vishvavah, Pum, &["viSvavAham"]); + assert_has_sup_2d(&vishvavah, Pum, &["viSvavAhO"]); } #[test] fn skip_sk_328_to_sk_329() {} +#[test] +fn sk_330() { + let vishvavah = + create_upapada_krdanta("viSvavAh", "viSva", &[], &d("va\\ha~^", Bhvadi), Krt::Rvi); + assert_has_sup_2p(&vishvavah, Pum, &["viSvOhaH"]); + assert_has_sup_3s(&vishvavah, Pum, &["viSvOhA"]); +} + +#[test] +fn skip_sk_331() {} + +#[test] +fn sk_332() { + assert_has_sup_1s("anaquh", Pum, &["anaqvAn"]); +} + +#[test] +fn sk_333() { + assert_has_sup_ss("anaquh", Pum, &["anaqvan"]); + assert_has_sup_1d("anaquh", Pum, &["anaqvAhO"]); + assert_has_sup_1p("anaquh", Pum, &["anaqvAhaH"]); + assert_has_sup_3s("anaquh", Pum, &["anaquhA"]); +} + +#[ignore] +#[test] +fn sk_334() { + assert_has_sup_3d("anaquh", Pum, &["anaqudByAm"]); + assert_has_sup_1s("vidvas", Pum, &["vidvAn"]); + assert_has_krdanta(&[], &d("sransu~\\", Bhvadi), Krt::kta, &["srasta"]); + assert_has_krdanta(&[], &d("Dvansu~\\", Bhvadi), Krt::kta, &["Dvasta"]); +} + +#[test] +fn sk_336() { + let sudiv = create_samasa("sudiv", &["su", "div"], Bahuvrihi); + assert_has_sup_1s(&sudiv, Pum, &["sudyOH"]); + assert_has_sup_1d(&sudiv, Pum, &["sudivO"]); + assert_has_sup_1p(&sudiv, Pum, &["sudivaH"]); + assert_has_sup_2s(&sudiv, Pum, &["sudivam"]); + assert_has_sup_2d(&sudiv, Pum, &["sudivO"]); +} + +#[test] +fn sk_337() { + let sudiv = create_samasa("sudiv", &["su", "div"], Bahuvrihi); + assert_has_sup_3d(&sudiv, Pum, &["sudyuByAm"]); + assert_has_sup_3p(&sudiv, Pum, &["sudyuBiH"]); + + assert_has_sup_1p("catur", Pum, &["catvAraH"]); + assert_has_sup_2p("catur", Pum, &["caturaH"]); + assert_has_sup_3p("catur", Pum, &["caturBiH"]); + assert_has_sup_4p("catur", Pum, &["caturByaH"]); + assert_has_sup_5p("catur", Pum, &["caturByaH"]); +} + +#[test] +fn sk_338() { + // TODO: support dvitvam forms. + assert_has_sup_6p("catur", Pum, &["caturRAm"]); +} + +#[test] +fn skip_sk_339() {} + +#[test] +fn sk_340() { + assert_has_sup_7p("catur", Pum, &["caturzu"]); + + let priyacatur = create_samasa("priyacatur", &["priya", "catur"], Bahuvrihi); + assert_has_sup_1s(&priyacatur, Pum, &["priyacatvAH"]); + assert_has_sup_ss(&priyacatur, Pum, &["priyacatvaH"]); + assert_has_sup_1d(&priyacatur, Pum, &["priyacatvArO"]); + assert_has_sup_1p(&priyacatur, Pum, &["priyacatvAraH"]); + + // TODO: introduce other catur-forms. + + assert_has_sup_1s("kamal", Pum, &["kamal"]); + assert_has_sup_1d("kamal", Pum, &["kamalO"]); + assert_has_sup_1p("kamal", Pum, &["kamalaH"]); + assert_has_sup_7p("kamal", Pum, &["kamalzu"]); +} + #[test] fn sk_342() { assert_has_sup_1s("kim", Pum, &["kaH"]); @@ -85,6 +198,9 @@ fn sk_349() { // TODO: ayaka } +#[test] +fn skip_sk_350() {} + #[test] fn sk_354() { assert_has_sup_1s("yajvan", Pum, &["yajvA"]); @@ -106,12 +222,131 @@ fn sk_355() { #[test] fn skip_sk_356() {} +#[ignore] +#[test] +fn sk_357() { + let vrtrahan = + create_upapada_krdanta("vftrahan", "vftra", &[], &d("ha\\na~", Adadi), Krt::kvip); + assert_has_sup_1s(&vrtrahan, Pum, &["vftrahA"]); + assert_has_sup_ss(&vrtrahan, Pum, &["vftrahan"]); + assert_has_sup_1d(&vrtrahan, Pum, &["vftrahaRO"]); + assert_has_sup_1p(&vrtrahan, Pum, &["vftrahaRaH"]); + assert_has_sup_2s(&vrtrahan, Pum, &["vftrahaRam"]); + assert_has_sup_2d(&vrtrahan, Pum, &["vftrahaRO"]); +} + #[test] fn skip_sk_358() {} +#[test] +fn skip_sk_360() {} + +#[ignore] +#[test] +fn sk_361() { + assert_has_sup_1s("maGavan", Pum, &["maGavAn"]); + assert_has_sup_1s("maGavan", Pum, &["maGavantO"]); + assert_has_sup_1s("maGavan", Pum, &["maGavantaH"]); + assert_has_sup_ss("maGavan", Pum, &["maGavan"]); + assert_has_sup_ss("maGavan", Pum, &["maGavantam"]); + assert_has_sup_ss("maGavan", Pum, &["maGavantO"]); + assert_has_sup_ss("maGavan", Pum, &["maGavataH"]); + assert_has_sup_ss("maGavan", Pum, &["maGavatA"]); + assert_has_sup_ss("maGavan", Pum, &["maGavadByAm"]); + assert_has_sup_ss("maGavan", Pum, &["maGavadByAm"]); +} + +#[test] +fn skip_sk_365_to_sk_366() {} + +#[test] +fn sk_367() { + assert_has_sup_1s("paTin", Pum, &["panTAH"]); + assert_has_sup_1d("paTin", Pum, &["panTAnO"]); + assert_has_sup_1p("paTin", Pum, &["panTAnaH"]); + assert_has_sup_2s("paTin", Pum, &["panTAnam"]); + assert_has_sup_2d("paTin", Pum, &["panTAnO"]); +} + +#[test] +fn sk_368() { + assert_has_sup_2p("paTin", Pum, &["paTaH"]); + assert_has_sup_3s("paTin", Pum, &["paTA"]); + assert_has_sup_3d("paTin", Pum, &["paTiByAm"]); + + assert_has_sup_1s("maTin", Pum, &["manTAH"]); + assert_has_sup_1s("fBukzin", Pum, &["fBukzAH"]); + + // TODO: anfBukzI and others +} + +#[test] +fn skip_sk_369() { + assert_has_sup_1p("paYcan", Pum, &["paYca"]); + assert_has_sup_2p("paYcan", Pum, &["paYca"]); + assert_has_sup_3p("paYcan", Pum, &["paYcaBiH"]); + assert_has_sup_4p("paYcan", Pum, &["paYcaByaH"]); + assert_has_sup_5p("paYcan", Pum, &["paYcaByaH"]); + + // TODO: others +} + #[test] fn skip_sk_371() {} +#[test] +fn skip_sk_374_to_sk_376() {} + +#[test] +fn sk_377() { + let yuj = create_krdanta("yuj", &[], &d("yu\\ji~^r", Rudhadi), Krt::kvin); + assert_has_sup_1s(&yuj, Pum, &["yuN"]); + assert_has_sup_1d(&yuj, Pum, &["yuYjO"]); + assert_has_sup_1p(&yuj, Pum, &["yuYjaH"]); + assert_has_sup_2s(&yuj, Pum, &["yuYjam"]); + assert_has_sup_2d(&yuj, Pum, &["yuYjO"]); + assert_has_sup_2p(&yuj, Pum, &["yujaH"]); + assert_has_sup_3d(&yuj, Pum, &["yugByAm"]); +} + +#[ignore] +#[test] +fn sk_378() { + let yuj = create_krdanta("yuj", &[], &d("yu\\ji~^r", Rudhadi), Krt::kvin); + let suyuj = create_samasa_p("suyuj", &[Pratipadika::from("su"), yuj], Bahuvrihi); + assert_has_sup_1s(&suyuj, Pum, &["suyuk"]); + assert_has_sup_1d(&suyuj, Pum, &["suyujO"]); + assert_has_sup_1p(&suyuj, Pum, &["suyujaH"]); + + // TODO: do others here + + let khanj = create_krdanta("KaYj", &[], &d("Kaji~", Bhvadi), Krt::kvip); + assert_has_sup_1s(&khanj, Pum, &["Kan"]); + assert_has_sup_1d(&khanj, Pum, &["KaYjO"]); + assert_has_sup_1p(&khanj, Pum, &["KaYjaH"]); + + assert_has_sup_1s("rAj", Pum, &["rAw"]); + assert_has_sup_1d("rAj", Pum, &["rAjO"]); + assert_has_sup_1p("rAj", Pum, &["rAjaH"]); + assert_has_sup_7p("rAj", Pum, &["rAwsu", "rAwtsu"]); +} + +#[test] +fn skip_sk_382_to_sk_384() {} + +#[test] +fn skip_sk_386() {} + +#[ignore] +#[test] +fn sk_388() { + assert_has_sup_1p("yuzmad", Pum, &["yUyam"]); + assert_has_sup_1p("asmad", Pum, &["vayam"]); +} + +#[test] +fn skip_sk_389() {} + #[test] fn sk_390() { assert_has_sup_2s("yuzmad", Pum, &["tvAm"]); @@ -144,7 +379,7 @@ fn sk_393() { #[test] fn sk_394() { assert_has_sup_4s("yuzmad", Pum, &["tuByam"]); - assert_has_sup_4d("asmad", Pum, &["mahyam"]); + assert_has_sup_4s("asmad", Pum, &["mahyam"]); } #[test] @@ -181,3 +416,145 @@ fn sk_399() { #[test] fn skip_sk_401_to_sk_406() {} + +#[test] +fn skip_sk_411() {} + +#[test] +fn skip_sk_416() {} + +#[test] +fn skip_sk_426() {} + +#[test] +fn sk_427() { + let dadat = create_krdanta("dadat", &[], &d("qudA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1s(&dadat, Pum, &["dadat"]); + assert_has_sup_1d(&dadat, Pum, &["dadatO"]); + assert_has_sup_1p(&dadat, Pum, &["dadataH"]); +} + +#[test] +fn sk_428() { + let jakshat = create_krdanta("jakzat", &[], &d("jakza~", Adadi), Krt::Satf); + assert_has_sup_1s(&jakshat, Pum, &["jakzat"]); + assert_has_sup_1d(&jakshat, Pum, &["jakzatO"]); + assert_has_sup_1p(&jakshat, Pum, &["jakzataH"]); + + let jagrat = create_krdanta("jAgrat", &[], &d("jAgf", Adadi), Krt::Satf); + assert_has_sup_1s(&jagrat, Pum, &["jAgrat"]); + + let daridrat = create_krdanta("daridrat", &[], &d("daridrA", Adadi), Krt::Satf); + assert_has_sup_1s(&daridrat, Pum, &["daridrat"]); + + let shasat = create_krdanta("SAsat", &[], &d("SAsu~", Adadi), Krt::Satf); + assert_has_sup_1s(&shasat, Pum, &["SAsat"]); + + let cakasat = create_krdanta("cakAsat", &[], &d("cakAsf~", Adadi), Krt::Satf); + assert_has_sup_1s(&cakasat, Pum, &["cakAsat"]); + + // TODO: didhyat, vevyat (needs parasmaipadam, available ad-hoc) + // let didhyat = create_krdanta("dIDyat", &[], &d("dIDIN", Adadi), Krt::Satf); + // assert_has_sup_1s(&didhyat, Pum, &["dIDyat"]); + // let vevyat = create_krdanta("vevyat", &[], &d("vevIN", Adadi), Krt::Satf); + // assert_has_sup_1s(&vevyat, Pum, &["vevyat"]); + + let gup = create_krdanta("gup", &[], &d("gupU~", Bhvadi), Krt::kvip); + assert_has_sup_1s(&gup, Pum, &["gup"]); + assert_has_sup_1d(&gup, Pum, &["gupO"]); + assert_has_sup_1p(&gup, Pum, &["gupaH"]); + assert_has_sup_3d(&gup, Pum, &["gubByAm"]); +} + +#[test] +fn skip_sk_429() {} + +#[test] +fn skip_sk_431() { + let nash = create_krdanta("naS", &[], &d("Ra\\Sa~", Divadi), Krt::kvip); + assert_has_sup_1s(&nash, Pum, &["nak", "naw"]); + assert_has_sup_1d(&nash, Pum, &["naSO"]); + assert_has_sup_1p(&nash, Pum, &["naSaH"]); + assert_has_sup_3d(&nash, Pum, &["nagByAm", "naqByAm"]); +} + +#[test] +fn sk_433() { + let pipathis = create_krdanta("pipaWiz", &[], &san(&d("paWa~", Bhvadi)), Krt::kvip); + assert_has_sup_1s(&pipathis, Pum, &["pipaWIH"]); + assert_has_sup_1d(&pipathis, Pum, &["pipaWizO"]); + assert_has_sup_1p(&pipathis, Pum, &["pipaWizaH"]); + assert_has_sup_3d(&pipathis, Pum, &["pipaWIrByAm"]); +} + +#[test] +fn sk_434() { + let pipathis = create_krdanta("pipaWiz", &[], &san(&d("paWa~", Bhvadi)), Krt::kvip); + assert_has_sup_7p(&pipathis, Pum, &["pipaWIzzu", "pipaWIHzu"]); + + let nins = d("Risi~\\", Adadi); + assert_has_thaas(&[], &nins, Lot, &["niMssva"]); + assert_has_thaas(&[], &nins, Lat, &["niMsse"]); + + assert_has_sup_7p("suhins", Pum, &["suhinsu"]); + assert_has_sup_7p("pums", Pum, &["puMsu"]); + + let cikirsh = create_krdanta("cikIrz", &[], &san(&d("qukf\\Y", Tanadi)), Krt::kvip); + assert_has_sup_1s(&cikirsh, Pum, &["cikIH"]); + assert_has_sup_1d(&cikirsh, Pum, &["cikIrzO"]); + assert_has_sup_1p(&cikirsh, Pum, &["cikIrzaH"]); + + // TODO: fix this. Issue is that our samyogAntasya lopa is buggy. + // assert_has_sup_7p(&cikirsh, Pum, &["cikIrzu"]); + + let taksh = create_krdanta("takz", &[], &d("takzU~", Bhvadi), Krt::kvip); + assert_has_sup_1s(&taksh, Pum, &["taw"]); + assert_has_sup_1d(&taksh, Pum, &["takzO"]); + assert_has_sup_1p(&taksh, Pum, &["takzaH"]); + + let goraksh = create_upapada_krdanta("gorakz", "go", &[], &d("rakza~", Bhvadi), Krt::kvip); + assert_has_sup_1s(&goraksh, Pum, &["goraw"]); + assert_has_sup_1d(&goraksh, Pum, &["gorakzO"]); + assert_has_sup_1p(&goraksh, Pum, &["gorakzaH"]); + + let pis = create_krdanta("pis", &[], &d("pisf~", Bhvadi), Krt::kvip); + let supis = create_samasa_p("supis", &[Pratipadika::from("su"), pis], Bahuvrihi); + assert_has_sup_1s(&supis, Pum, &["supIH"]); + assert_has_sup_1d(&supis, Pum, &["supisO"]); + assert_has_sup_1p(&supis, Pum, &["supisaH"]); + assert_has_sup_3s(&supis, Pum, &["supisA"]); + assert_has_sup_3d(&supis, Pum, &["supIrByAm"]); + assert_has_sup_7p(&supis, Pum, &["supIHzu", "supIzzu"]); +} + +#[test] +fn sk_437() { + assert_has_sup_1s("adas", Pum, &["asO"]); + assert_has_sup_1d("adas", Pum, &["amU"]); + + // TODO: asakO, asukaH +} + +#[test] +fn sk_438() { + assert_has_sup_1p("adas", Pum, &["amI"]); + assert_has_sup_2s("adas", Pum, &["amum"]); + assert_has_sup_2d("adas", Pum, &["amU"]); + assert_has_sup_2p("adas", Pum, &["amUn"]); +} + +#[test] +fn sk_439() { + assert_has_sup_3s("adas", Pum, &["amunA"]); + assert_has_sup_3d("adas", Pum, &["amUByAm"]); + assert_has_sup_3p("adas", Pum, &["amIBiH"]); + assert_has_sup_4s("adas", Pum, &["amuzmE"]); + assert_has_sup_4p("adas", Pum, &["amIByaH"]); + assert_has_sup_5s("adas", Pum, &["amuzmAt"]); + assert_has_sup_6s("adas", Pum, &["amuzya"]); + assert_has_sup_6d("adas", Pum, &["amuyoH"]); + assert_has_sup_6p("adas", Pum, &["amIzAm"]); + assert_has_sup_7s("adas", Pum, &["amuzmin"]); + assert_has_sup_7d("adas", Pum, &["amuyoH"]); + assert_has_sup_7p("adas", Pum, &["amIzu"]); +} diff --git a/vidyut-prakriya/tests/kaumudi_12.rs b/vidyut-prakriya/tests/kaumudi_12.rs new file mode 100644 index 0000000..9e22b6c --- /dev/null +++ b/vidyut-prakriya/tests/kaumudi_12.rs @@ -0,0 +1,153 @@ +extern crate test_utils; +use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; +use vidyut_prakriya::args::Gana::*; +use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Pratipadika; +use vidyut_prakriya::args::SamasaType::*; + +#[test] +fn sk_440() { + let upanah = create_krdanta("upAnah", &["upa", "AN"], &d("Ra\\ha~^", Divadi), Krt::kvip); + assert_has_sup_1s(&upanah, Stri, &["upAnat"]); + assert_has_sup_1d(&upanah, Stri, &["upAnahO"]); + assert_has_sup_1p(&upanah, Stri, &["upAnahaH"]); + assert_has_sup_3d(&upanah, Stri, &["upAnadByAm"]); + assert_has_sup_7p(&upanah, Stri, &["upAnatsu"]); + + let ushnih = create_krdanta("uzRih", &["ud"], &d("zRi\\ha~", Divadi), Krt::kvin); + assert_has_sup_1s(&ushnih, Stri, &["uzRik"]); + assert_has_sup_1d(&ushnih, Stri, &["uzRihO"]); + assert_has_sup_1p(&ushnih, Stri, &["uzRihaH"]); + assert_has_sup_3d(&ushnih, Stri, &["uzRigByAm"]); + assert_has_sup_7p(&ushnih, Stri, &["uzRikzu"]); + + assert_has_sup_1s("div", Stri, &["dyOH"]); + assert_has_sup_1d("div", Stri, &["divO"]); + assert_has_sup_1p("div", Stri, &["divaH"]); + assert_has_sup_7p("div", Stri, &["dyuzu"]); + + let gir = create_krdanta("gir", &[], &d("gF", Kryadi), Krt::kvip); + assert_has_sup_1s(&gir, Stri, &["gIH"]); + assert_has_sup_1d(&gir, Stri, &["girO"]); + assert_has_sup_1p(&gir, Stri, &["giraH"]); + + let pur = create_krdanta("pur", &[], &d("pF", Kryadi), Krt::kvip); + assert_has_sup_1s(&pur, Stri, &["pUH"]); + + assert_has_sup_1p("catur", Stri, &["catasraH"]); + assert_has_sup_6p("catur", Stri, &["catasfRAm"]); + + assert_has_sup_1s("kim", Stri, &["kA"]); + assert_has_sup_1d("kim", Stri, &["ke"]); + assert_has_sup_1p("kim", Stri, &["kAH"]); +} + +#[test] +fn sk_441() { + assert_has_sup_1s("idam", Stri, &["iyam"]); + assert_has_sup_1d("idam", Stri, &["ime"]); + assert_has_sup_1p("idam", Stri, &["imAH"]); + assert_has_sup_2s("idam", Stri, &["imAm"]); + assert_has_sup_2d("idam", Stri, &["ime"]); + assert_has_sup_2p("idam", Stri, &["imAH"]); + assert_has_sup_3s("idam", Stri, &["anayA"]); + assert_has_sup_3d("idam", Stri, &["AByAm"]); + assert_has_sup_3p("idam", Stri, &["ABiH"]); + assert_has_sup_4s("idam", Stri, &["asyE"]); + assert_has_sup_5s("idam", Stri, &["asyAH"]); + assert_has_sup_6d("idam", Stri, &["anayoH"]); + assert_has_sup_6p("idam", Stri, &["AsAm"]); + assert_has_sup_7s("idam", Stri, &["asyAm"]); + assert_has_sup_7p("idam", Stri, &["Asu"]); + + assert_has_sup_1s("sraj", Stri, &["srak"]); + assert_has_sup_1d("sraj", Stri, &["srajO"]); + assert_has_sup_1p("sraj", Stri, &["srajaH"]); + assert_has_sup_3d("sraj", Stri, &["sragByAm"]); + assert_has_sup_7p("sraj", Stri, &["srakzu"]); + + assert_has_sup_1s("tyad", Stri, &["syA"]); + assert_has_sup_1d("tyad", Stri, &["tye"]); + assert_has_sup_1p("tyad", Stri, &["tyAH"]); + + // "evaM tad yad etad" + assert_has_sup_1s("tad", Stri, &["sA"]); + assert_has_sup_1d("tad", Stri, &["te"]); + assert_has_sup_1p("tad", Stri, &["tAH"]); + + assert_has_sup_1s("yad", Stri, &["yA"]); + assert_has_sup_1d("yad", Stri, &["ye"]); + assert_has_sup_1p("yad", Stri, &["yAH"]); + + assert_has_sup_1s("etad", Stri, &["ezA"]); + assert_has_sup_1d("etad", Stri, &["ete"]); + assert_has_sup_1p("etad", Stri, &["etAH"]); + + assert_has_sup_1s("vAc", Stri, &["vAk"]); + assert_has_sup_1d("vAc", Stri, &["vAcO"]); + assert_has_sup_1p("vAc", Stri, &["vAcaH"]); + assert_has_sup_3d("vAc", Stri, &["vAgByAm"]); + assert_has_sup_7p("vAc", Stri, &["vAkzu"]); + + assert_has_sup_1p("ap", Stri, &["ApaH"]); + assert_has_sup_2p("ap", Stri, &["apaH"]); +} + +#[test] +fn sk_442() { + assert_has_sup_3p("ap", Stri, &["adBiH"]); + assert_has_sup_4p("ap", Stri, &["adByaH"]); + assert_has_sup_6p("ap", Stri, &["apAm"]); + assert_has_sup_7p("ap", Stri, &["apsu"]); + + let dish = create_krdanta("diS", &[], &d("di\\Sa~^", Tudadi), Krt::kvin); + assert_has_sup_1s(&dish, Stri, &["dik"]); + assert_has_sup_1d(&dish, Stri, &["diSO"]); + assert_has_sup_1p(&dish, Stri, &["diSaH"]); + assert_has_sup_3d(&dish, Stri, &["digByAm"]); + assert_has_sup_7p(&dish, Stri, &["dikzu"]); + + let drsh = create_krdanta("dfS", &[], &d("df\\Si~r", Tudadi), Krt::kvin); + assert_has_sup_1s(&drsh, Stri, &["dfk"]); + assert_has_sup_1d(&drsh, Stri, &["dfSO"]); + assert_has_sup_1p(&drsh, Stri, &["dfSaH"]); + + assert_has_sup_1s("tviz", Stri, &["tviw"]); + assert_has_sup_1d("tviz", Stri, &["tvizO"]); + assert_has_sup_1p("tviz", Stri, &["tvizaH"]); + assert_has_sup_3d("tviz", Stri, &["tviqByAm"]); + assert_has_sup_7p("tviz", Stri, &["tviwtsu", "tviwsu"]); + + let jush = create_krdanta("juz", &[], &d("juzI~\\", Tudadi), Krt::kvip); + // HACK: technically "saha", but use "sa" for convenience. + let sajush = create_samasa_p("sajuz", &[Pratipadika::from("sa"), jush], Bahuvrihi); + assert_has_sup_1s(&sajush, Stri, &["sajUH"]); + assert_has_sup_1d(&sajush, Stri, &["sajuzO"]); + assert_has_sup_1p(&sajush, Stri, &["sajuzaH"]); + assert_has_sup_3d(&sajush, Stri, &["sajUrByAm"]); + assert_has_sup_7p(&sajush, Stri, &["sajUHzu", "sajUzzu"]); + + let ashis = create_krdanta("ASis", &["AN"], &d("SAsu~\\", Adadi), Krt::kvip); + assert_has_sup_1s(&ashis, Stri, &["ASIH"]); + assert_has_sup_1d(&ashis, Stri, &["ASizO"]); + assert_has_sup_1p(&ashis, Stri, &["ASizaH"]); + assert_has_sup_3d(&ashis, Stri, &["ASIrByAm"]); + + assert_has_sup_1s("adas", Stri, &["asO"]); + assert_has_sup_1d("adas", Stri, &["amU"]); + assert_has_sup_1p("adas", Stri, &["amUH"]); + assert_has_sup_2s("adas", Stri, &["amUm"]); + assert_has_sup_2d("adas", Stri, &["amU"]); + assert_has_sup_2p("adas", Stri, &["amUH"]); + assert_has_sup_3s("adas", Stri, &["amuyA"]); + assert_has_sup_3d("adas", Stri, &["amUByAm"]); + assert_has_sup_3p("adas", Stri, &["amUBiH"]); + assert_has_sup_4s("adas", Stri, &["amuzyE"]); + assert_has_sup_4d("adas", Stri, &["amUByAm"]); + assert_has_sup_4p("adas", Stri, &["amUByaH"]); + assert_has_sup_5s("adas", Stri, &["amuzyAH"]); + assert_has_sup_6d("adas", Stri, &["amuyoH"]); + assert_has_sup_6p("adas", Stri, &["amUzAm"]); + assert_has_sup_7p("adas", Stri, &["amUzu"]); +} diff --git a/vidyut-prakriya/tests/kaumudi_13.rs b/vidyut-prakriya/tests/kaumudi_13.rs new file mode 100644 index 0000000..fda1226 --- /dev/null +++ b/vidyut-prakriya/tests/kaumudi_13.rs @@ -0,0 +1,163 @@ +extern crate test_utils; +use test_utils::*; +use vidyut_prakriya::args::Gana::*; +use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::SamasaType::*; +use vidyut_prakriya::args::{BaseKrt as Krt, Unadi}; + +#[test] +fn sk_443() { + assert_has_sup_3d("ahan", Napumsaka, &["ahoByAm"]); + assert_has_sup_3p("ahan", Napumsaka, &["ahoBiH"]); + + // TODO: extra ahan forms + + assert_has_sup_1s("daRqin", Napumsaka, &["daRqi"]); + assert_has_sup_1d("daRqin", Napumsaka, &["daRqinI"]); + assert_has_sup_1p("daRqin", Napumsaka, &["daRqIni"]); + + assert_has_sup_1s("sragvin", Napumsaka, &["sragvi"]); + assert_has_sup_1d("sragvin", Napumsaka, &["sragviRI"]); + assert_has_sup_1p("sragvin", Napumsaka, &["sragvIRi"]); + + assert_has_sup_1s("vAgmin", Napumsaka, &["vAgmi"]); + assert_has_sup_1d("vAgmin", Napumsaka, &["vAgminI"]); + assert_has_sup_1p("vAgmin", Napumsaka, &["vAgmIni"]); + + assert_has_sup_1p("bahuvftrahan", Napumsaka, &["bahuvftrahARi"]); + assert_has_sup_1p("bahupUzan", Napumsaka, &["bahupUzARi"]); + assert_has_sup_1p("bahvaryaman", Napumsaka, &["bahvaryamARi"]); + + // TODO: others in this section: asfj, etc. + + assert_has_sup_1s("tyad", Napumsaka, &["tyat"]); + assert_has_sup_1d("tyad", Napumsaka, &["tye"]); + assert_has_sup_1p("tyad", Napumsaka, &["tyAni"]); + + assert_has_sup_1s("tad", Napumsaka, &["tat"]); + assert_has_sup_1d("tad", Napumsaka, &["te"]); + assert_has_sup_1p("tad", Napumsaka, &["tAni"]); + + assert_has_sup_1s("yad", Napumsaka, &["yat"]); + assert_has_sup_1d("yad", Napumsaka, &["ye"]); + assert_has_sup_1p("yad", Napumsaka, &["yAni"]); + + // TODO: not sure how to derive enat. + + assert_has_sup_1s("etad", Napumsaka, &["etat"]); + assert_has_sup_1d("etad", Napumsaka, &["ete"]); + assert_has_sup_1p("etad", Napumsaka, &["etAni"]); + + let bebhid = create_krdanta("beBid", &[], &yan(&d("Bi\\di~^r", Rudhadi)), Krt::kvip); + assert_has_sup_1s(&bebhid, Napumsaka, &["beBit"]); + assert_has_sup_1d(&bebhid, Napumsaka, &["beBidI"]); + assert_has_sup_1p(&bebhid, Napumsaka, &["beBidi"]); + + let cecchid = create_krdanta("cecCid", &[], &yan(&d("Ci\\di~^r", Rudhadi)), Krt::kvip); + assert_has_sup_1p(&cecchid, Napumsaka, &["cecCidi"]); + + assert_has_sup_1p("catur", Napumsaka, &["catvAri"]); + + // TODO: go + aYc and permutations + + assert_has_sup_1s("yakft", Napumsaka, &["yakft"]); + assert_has_sup_1d("yakft", Napumsaka, &["yakftI"]); + assert_has_sup_1p("yakft", Napumsaka, &["yakfnti"]); + assert_has_sup_2p("yakft", Napumsaka, &["yakfnti", "yakAni"]); + assert_has_sup_3s("yakft", Napumsaka, &["yaknA", "yakftA"]); + + assert_has_sup_1s("Sakft", Napumsaka, &["Sakft"]); + assert_has_sup_1d("Sakft", Napumsaka, &["SakftI"]); + assert_has_sup_1p("Sakft", Napumsaka, &["Sakfnti"]); + assert_has_sup_2p("Sakft", Napumsaka, &["Sakfnti", "SakAni"]); + assert_has_sup_3s("Sakft", Napumsaka, &["SaknA", "SakftA"]); + + let dadat = create_krdanta("dadat", &[], &d("qudA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1s(&dadat, Napumsaka, &["dadat"]); + assert_has_sup_1d(&dadat, Napumsaka, &["dadatI"]); +} + +#[test] +fn sk_444() { + let dadat = create_krdanta("dadat", &[], &d("qudA\\Y", Juhotyadi), Krt::Satf); + assert_has_sup_1p(&dadat, Napumsaka, &["dadanti", "dadati"]); + + let tudat = create_krdanta("tudat", &[], &d("tu\\da~^", Tudadi), Krt::Satf); + assert_has_sup_1s(&tudat, Napumsaka, &["tudat"]); +} + +#[test] +fn sk_445() { + let tudat = create_krdanta("tudat", &[], &d("tu\\da~^", Tudadi), Krt::Satf); + assert_has_sup_1d(&tudat, Napumsaka, &["tudatI", "tudantI"]); + assert_has_sup_1p(&tudat, Napumsaka, &["tudanti"]); + + let bhaat = create_krdanta("BAt", &[], &d("BA\\", Adadi), Krt::Satf); + assert_has_sup_1s(&bhaat, Napumsaka, &["BAt"]); + assert_has_sup_1d(&bhaat, Napumsaka, &["BAntI", "BAtI"]); + assert_has_sup_1p(&bhaat, Napumsaka, &["BAnti"]); + + let pacat = create_krdanta("pacat", &[], &d("qupa\\ca~^z", Bhvadi), Krt::Satf); + assert_has_sup_1s(&pacat, Napumsaka, &["pacat"]); +} + +#[test] +fn sk_446() { + let pacat = create_krdanta("pacat", &[], &d("qupa\\ca~^z", Bhvadi), Krt::Satf); + assert_has_sup_1d(&pacat, Napumsaka, &["pacantI"]); + assert_has_sup_1p(&pacat, Napumsaka, &["pacanti"]); + + let divyat = create_krdanta("dIvyat", &[], &d("divu~", Divadi), Krt::Satf); + assert_has_sup_1s(&divyat, Napumsaka, &["dIvyat"]); + assert_has_sup_1d(&divyat, Napumsaka, &["dIvyantI"]); + assert_has_sup_1p(&divyat, Napumsaka, &["dIvyanti"]); + + assert_has_sup_1s("svap", Napumsaka, &["svap"]); + assert_has_sup_1d("svap", Napumsaka, &["svapI"]); + assert_has_sup_1p("svap", Napumsaka, &["svAmpi", "svampi"]); + assert_has_sup_3s("svap", Napumsaka, &["svapA"]); + assert_has_sup_3d("svap", Napumsaka, &["svadByAm"]); + assert_has_sup_3p("svap", Napumsaka, &["svadBiH"]); + + let dhanus = create_krdanta("Danus", &[], &d("Dana~", Juhotyadi), Unadi::usi); + assert_has_sup_1s(&dhanus, Napumsaka, &["DanuH"]); + assert_has_sup_1d(&dhanus, Napumsaka, &["DanuzI"]); + assert_has_sup_1p(&dhanus, Napumsaka, &["DanUMzi"]); + assert_has_sup_3s(&dhanus, Napumsaka, &["DanuzA"]); + assert_has_sup_3d(&dhanus, Napumsaka, &["DanurByAm"]); + + // evaM cakzurhavirAdayaH + let caksus = create_krdanta("cakzus", &[], &d("ca\\kzi~\\N", Adadi), Unadi::usi); + assert_has_sup_1s(&caksus, Napumsaka, &["cakzuH"]); + assert_has_sup_1d(&caksus, Napumsaka, &["cakzuzI"]); + assert_has_sup_1p(&caksus, Napumsaka, &["cakzUMzi"]); + assert_has_sup_3s(&caksus, Napumsaka, &["cakzuzA"]); + assert_has_sup_3d(&caksus, Napumsaka, &["cakzurByAm"]); + let havis = create_krdanta("havis", &[], &d("hu\\", Juhotyadi), Unadi::isi); + assert_has_sup_1s(&havis, Napumsaka, &["haviH"]); + assert_has_sup_1d(&havis, Napumsaka, &["havizI"]); + assert_has_sup_1p(&havis, Napumsaka, &["havIMzi"]); + assert_has_sup_3s(&havis, Napumsaka, &["havizA"]); + assert_has_sup_3d(&havis, Napumsaka, &["havirByAm"]); + + let pipathis = create_krdanta("pipaWiz", &[], &san(&d("paWa~", Bhvadi)), Krt::kvip); + assert_has_sup_1s(&pipathis, Napumsaka, &["pipaWIH"]); + assert_has_sup_1d(&pipathis, Napumsaka, &["pipaWizI"]); + assert_has_sup_1p(&pipathis, Napumsaka, &["pipaWizi"]); + assert_has_sup_3d(&pipathis, Napumsaka, &["pipaWIrByAm"]); + + assert_has_sup_1s("payas", Napumsaka, &["payaH"]); + assert_has_sup_1d("payas", Napumsaka, &["payasI"]); + assert_has_sup_1p("payas", Napumsaka, &["payAMsi"]); + assert_has_sup_3s("payas", Napumsaka, &["payasA"]); + assert_has_sup_3d("payas", Napumsaka, &["payoByAm"]); + + let supums = create_samasa("supums", &["su", "pums"], Bahuvrihi); + assert_has_sup_1s(&supums, Napumsaka, &["supum"]); + assert_has_sup_1d(&supums, Napumsaka, &["supuMsI"]); + assert_has_sup_1p(&supums, Napumsaka, &["supumAMsi"]); + + assert_has_sup_1s("adas", Napumsaka, &["adaH"]); + assert_has_sup_1d("adas", Napumsaka, &["amU"]); + assert_has_sup_1p("adas", Napumsaka, &["amUni"]); +} diff --git a/vidyut-prakriya/tests/kaumudi_43.rs b/vidyut-prakriya/tests/kaumudi_43.rs index 71bcb4d..3ac5b04 100644 --- a/vidyut-prakriya/tests/kaumudi_43.rs +++ b/vidyut-prakriya/tests/kaumudi_43.rs @@ -1757,7 +1757,8 @@ fn sk_2301() { let stambh = d("zwaBi~\\", Bhvadi); assert_has_ta(&[], &stambh, Lat, &["stamBate"]); - assert_has_ta(&["ud"], &stambh, Lat, &["uttamBate", "utttamBate"]); + // utTtamBate is justified. See comments on 8.4.61 for why "T" is used. + assert_has_ta(&["ud"], &stambh, Lat, &["uttamBate", "utTtamBate"]); assert_has_ta(&["vi"], &stambh, Lat, &["vistamBate"]); // TODO: zwamBate, wazwamBe diff --git a/vidyut-prakriya/tests/kaumudi_67.rs b/vidyut-prakriya/tests/kaumudi_67.rs index dda48eb..f7276bb 100644 --- a/vidyut-prakriya/tests/kaumudi_67.rs +++ b/vidyut-prakriya/tests/kaumudi_67.rs @@ -23,6 +23,15 @@ fn unadi_1_2() { t.assert_has_krt(&[], &d("i\\R", Adadi), Unadi::uR, &["Ayu"]); } +#[test] +fn unadi_1_3() { + assert_has_krdanta(&[], &d("dF", Kryadi), Unadi::YuR, &["dAru"]); + assert_has_krdanta(&[], &d("zaRa~", Bhvadi), Unadi::YuR, &["sAnu"]); + assert_has_krdanta(&[], &d("janI~", Divadi), Unadi::YuR, &["jAnu"]); + assert_has_krdanta(&[], &d("cara~", Bhvadi), Unadi::YuR, &["cAru"]); + assert_has_krdanta(&[], &d("cawe~", Bhvadi), Unadi::YuR, &["cAwu"]); +} + #[ignore] #[test] fn unadi_1_5() { @@ -30,6 +39,66 @@ fn unadi_1_5() { assert_has_krdanta(&[], &d("tF", Bhvadi), Unadi::YuR, &["tAlu"]); } +#[test] +fn unadi_1_7() { + use Unadi::u; + assert_has_krdanta(&[], &d("Bf\\Y", Bhvadi), u, &["Baru"]); + assert_has_krdanta(&[], &d("quBf\\Y", Juhotyadi), u, &["Baru"]); + assert_has_krdanta(&[], &d("mf\\N", Bhvadi), u, &["maru"]); + assert_has_krdanta(&[], &d("SIN", Adadi), u, &["Sayu"]); + assert_has_krdanta(&[], &d("cara~", Bhvadi), u, &["caru"]); + assert_has_krdanta(&[], &d("tsara~", Bhvadi), u, &["tsaru"]); + assert_has_krdanta(&[], &d("tanu~^", Bhvadi), u, &["tanu"]); + assert_has_krdanta(&[], &d("Dana~", Juhotyadi), u, &["Danu"]); + assert_has_krdanta(&[], &d("qumi\\Y", Bhvadi), u, &["mayu"]); + assert_has_krdanta(&[], &d("wuma\\sjo~", Tudadi), u, &["madgu"]); +} + +#[test] +fn unadi_1_11() { + assert_has_krdanta(&[], &d("syandU~\\", Bhvadi), Unadi::u, &["sinDu"]); +} + +#[test] +fn unadi_1_12() { + assert_has_krdanta(&[], &d("undI~", Rudhadi), Unadi::u, &["indu"]); +} + +#[test] +fn unadi_1_13() { + assert_has_krdanta(&[], &d("Iza~\\", Adadi), Unadi::u, &["izu"]); +} + +#[test] +fn unadi_1_14() { + assert_has_krdanta(&[], &d("ska\\ndi~r", Bhvadi), Unadi::u, &["kandu"]); +} + +#[test] +fn unadi_1_15() { + assert_has_krdanta(&[], &d("sf\\ja~", Tudadi), Unadi::u, &["rajju"]); +} + +#[test] +fn unadi_1_16() { + assert_has_krdanta(&[], &d("kftI~", Rudhadi), Unadi::u, &["tarku"]); +} + +#[test] +fn unadi_1_19() { + assert_has_krdanta(&[], &d("vala~\\", Bhvadi), Unadi::u, &["valgu"]); +} + +#[test] +fn unadi_1_20() { + assert_has_krdanta(&[], &d("So\\", Divadi), Unadi::u, &["SiSu"]); +} + +#[test] +fn unadi_1_21() { + assert_has_krdanta(&[], &d("yA\\", Adadi), Unadi::u, &["yayu"]); +} + #[test] fn unadi_1_45() { assert_has_krdanta(&[], &d("ava~", Bhvadi), Unadi::wizac, &["aviza"]); diff --git a/vidyut-prakriya/tests/kaumudi_8.rs b/vidyut-prakriya/tests/kaumudi_8.rs index ce5437b..8cc0b39 100644 --- a/vidyut-prakriya/tests/kaumudi_8.rs +++ b/vidyut-prakriya/tests/kaumudi_8.rs @@ -1,8 +1,11 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; use vidyut_prakriya::args::Linga::*; +use vidyut_prakriya::args::Pratipadika; +use vidyut_prakriya::args::SamasaType::*; #[test] fn skip_sk_178_to_sk_186() {} @@ -106,14 +109,16 @@ fn sk_209() { #[test] fn skip_sk_210_to_sk_211() {} -#[ignore] #[test] fn sk_212() { assert_has_sup_7p("rAma", Pum, &["rAmezu"]); + assert_has_sup_6s("rAma", Pum, &["rAmasya"]); - assert_has_sup_1s("supis", Pum, &["supIH"]); - assert_has_sup_1d("supis", Pum, &["supisO"]); - assert_has_sup_1p("supis", Pum, &["supisaH"]); + let pis = create_krdanta("pis", &[], &d("pisf~", Bhvadi), Krt::kvip); + let supis = create_samasa_p("supis", &[Pratipadika::from("su"), pis], Bahuvrihi); + assert_has_sup_1s(&supis, Pum, &["supIH"]); + assert_has_sup_1d(&supis, Pum, &["supisO"]); + assert_has_sup_1p(&supis, Pum, &["supisaH"]); } #[test] @@ -163,6 +168,14 @@ fn sk_221() { assert_has_sup_7s("pUrva", Pum, &["pUrvasmin", "pUrve"]); } +#[test] +fn sk_226() { + assert_has_sup_1p("praTama", Pum, &["praTame", "praTamAH"]); + assert_has_sup_1p("dvitaya", Pum, &["dvitaye", "dvitayAH"]); + assert_has_sup_1p("nema", Pum, &["neme", "nemAH"]); + assert_has_sup_4s("dvitIya", Pum, &["dvitIyasmE", "dvitIyAya"]); +} + #[test] fn sk_228() { assert_has_sup_1s("pAda", Pum, &["pAdaH"]); @@ -210,10 +223,43 @@ fn sk_237() { assert_has_sup_7s("yUzan", Pum, &["yUzRi", "yUzaRi"]); } +#[ignore] +#[test] +fn sk_238() { + let dvyahan = create_samasa("dvyahan", &["dvi", "ahan"], Tatpurusha); + assert_has_sup_7s(&dvyahan, Pum, &["dvyahni", "dvyahani", "dvyahne"]); + + let vyahan = create_samasa("vyahan", &["vi", "ahan"], Tatpurusha); + assert_has_sup_7s(&vyahan, Pum, &["vyahni", "vyahani", "vyahne"]); + + let sayahan = create_samasa("sAyAhan", &["sAya", "ahan"], Tatpurusha); + assert_has_sup_7s(&sayahan, Pum, &["sAyAhni", "sAyAhani", "sAyahne"]); + + let vishvapa = create_upapada_krdanta("viSvapA", "viSva", &[], &d("pA\\", Adadi), Krt::vic); + assert_has_sup_1s(&vishvapa, Pum, &["viSvapO"]); +} + #[test] fn sk_239() { - assert_has_sup_1d("viSvapA", Pum, &["viSvapO"]); - assert_has_sup_1p("viSvapA", Pum, &["viSvapAH"]); + let vishvapa = create_upapada_krdanta("viSvapA", "viSva", &[], &d("pA\\", Adadi), Krt::vic); + assert_has_sup_1d(&vishvapa, Pum, &["viSvapO"]); + assert_has_sup_1p(&vishvapa, Pum, &["viSvapAH"]); +} + +#[test] +fn sk_240() { + let vishvapa = create_upapada_krdanta("viSvapA", "viSva", &[], &d("pA\\", Adadi), Krt::vic); + assert_has_sup_2p(&vishvapa, Pum, &["viSvapaH"]); + + assert_has_sup_2p("hAhA", Pum, &["hAhAn"]); + assert_has_sup_3s("hAhA", Pum, &["hAhA"]); + assert_has_sup_4s("hAhA", Pum, &["hAhE"]); + assert_has_sup_5s("hAhA", Pum, &["hAhAH"]); + assert_has_sup_6d("hAhA", Pum, &["hAhOH"]); + assert_has_sup_7s("hAhA", Pum, &["hAhe"]); + + assert_has_sup_1s("hari", Pum, &["hariH"]); + assert_has_sup_1d("hari", Pum, &["harI"]); } #[test] @@ -229,11 +275,10 @@ fn sk_242() { assert_has_sup_2p("hari", Pum, &["harIn"]); } -#[ignore] #[test] fn sk_243() { assert_has_sup_4s("mati", Stri, &["mataye", "matyE"]); - assert_has_sup_4s("vAtapramI", Stri, &["vAtapramye"]); + assert_has_sup_4s(&dhatu_prati("vAtapramI"), Pum, &["vAtapramye"]); assert_has_sup_4s("mAtf", Stri, &["mAtre"]); } @@ -267,7 +312,6 @@ fn sk_247() { #[test] fn skip_sk_248_to_sk_251() {} -#[ignore] #[test] fn sk_252() { // counterexamples @@ -304,9 +348,105 @@ fn sk_255() { #[test] fn skip_sk_258_to_sk_262() {} +#[test] +fn sk_263() { + assert_has_sup_1p("kati", Pum, &["kati"]); + assert_has_sup_2p("kati", Pum, &["kati"]); + assert_has_sup_3p("kati", Pum, &["katiBiH"]); + assert_has_sup_4p("kati", Pum, &["katiByaH"]); + assert_has_sup_5p("kati", Pum, &["katiByaH"]); + assert_has_sup_6p("kati", Pum, &["katInAm"]); + assert_has_sup_7p("kati", Pum, &["katizu"]); + + assert_has_sup_1p("tri", Pum, &["trayaH"]); + assert_has_sup_2p("tri", Pum, &["trIn"]); + assert_has_sup_3p("tri", Pum, &["triBiH"]); + assert_has_sup_4p("tri", Pum, &["triByaH"]); +} + +#[test] +fn sk_264() { + assert_has_sup_6p("tri", Pum, &["trayARAm"]); + // TODO: paramatri, etc. + assert_has_sup_7p("tri", Pum, &["trizu"]); +} + +#[test] +fn skip_sk_266() {} + +#[test] +fn sk_267() { + assert_has_sup_ss("bahuSreyasI", Pum, &["bahuSreyasi"]); + assert_has_sup_2p("bahuSreyasI", Pum, &["bahuSreyasIn"]); +} + +#[test] +fn skip_sk_268() {} + +#[test] +fn sk_269() { + assert_has_sup_4s("bahuSreyasI", Pum, &["bahuSreyasyE"]); + assert_has_sup_6s("bahuSreyasI", Pum, &["bahuSreyasyAH"]); + assert_has_sup_6p("bahuSreyasI", Pum, &["bahuSreyasInAm"]); +} + +#[ignore] +#[test] +fn sk_270() { + assert_has_sup_7s("bahuSreyasI", Pum, &["bahuSreyasyAm"]); + assert_has_sup_1s("atilakzmI", Pum, &["atilakzmIH"]); + // TODO: kumArI +} + +#[test] +fn skip_sk_271() {} + #[test] fn skip_sk_274_to_sk_276() {} +#[test] +fn sk_277() { + assert_has_sup_1s("krozwu", Pum, &["krozwA"]); + assert_has_sup_1d("krozwu", Pum, &["krozwArO"]); + assert_has_sup_1p("krozwu", Pum, &["krozwAraH"]); + assert_has_sup_2s("krozwu", Pum, &["krozwAram"]); + assert_has_sup_2d("krozwu", Pum, &["krozwArO"]); + assert_has_sup_2p("krozwu", Pum, &["krozwUn"]); +} + +#[test] +fn sk_278() { + assert_has_sup_3s("krozwu", Pum, &["krozwrA", "krozwunA"]); + assert_has_sup_4s("krozwu", Pum, &["krozwre", "krozwave"]); +} + +#[test] +fn skip_sk_279() {} + +#[test] +fn sk_280() { + assert_has_sup_6s("krozwu", Pum, &["krozwuH", "krozwoH"]); + assert_has_sup_6p("krozwu", Pum, &["krozwUnAm"]); + assert_has_sup_7s("krozwu", Pum, &["krozwari", "krozwO"]); + assert_has_sup_7d("krozwu", Pum, &["krozwroH", "krozwvoH"]); + + assert_has_sup_1s("hUhU", Pum, &["hUhUH"]); + assert_has_sup_1d("hUhU", Pum, &["hUhvO"]); + assert_has_sup_1p("hUhU", Pum, &["hUhvaH"]); + assert_has_sup_2s("hUhU", Pum, &["hUhUm"]); + assert_has_sup_2d("hUhU", Pum, &["hUhvO"]); + assert_has_sup_2p("hUhU", Pum, &["hUhUn"]); + + assert_has_sup_ss("aticamU", Pum, &["aticamu"]); + assert_has_sup_4s("aticamU", Pum, &["aticamvE"]); + assert_has_sup_5s("aticamU", Pum, &["aticamvAH"]); + assert_has_sup_6s("aticamU", Pum, &["aticamvAH"]); + assert_has_sup_6p("aticamU", Pum, &["aticamUnAm"]); + assert_has_sup_7s("aticamU", Pum, &["aticamvAm"]); + + assert_has_sup_1s("KalapU", Pum, &["KalapUH"]); +} + #[test] fn skip_sk_284() { assert_has_sup_1s("go", Pum, &["gOH"]); diff --git a/vidyut-prakriya/tests/kaumudi_9.rs b/vidyut-prakriya/tests/kaumudi_9.rs index bafd27a..bba1c52 100644 --- a/vidyut-prakriya/tests/kaumudi_9.rs +++ b/vidyut-prakriya/tests/kaumudi_9.rs @@ -1,17 +1,19 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::BaseKrt as Krt; +use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Linga::*; #[test] fn sk_287() { - let rama = nyap("ramA"); + let rama = create_stryanta("ramA", "rama"); assert_has_sup_1d(&rama, Stri, &["rame"]); assert_has_sup_1p(&rama, Stri, &["ramAH"]); } #[test] fn sk_288() { - let rama = nyap("ramA"); + let rama = create_stryanta("ramA", "rama"); assert_has_sup_ss(&rama, Stri, &["rame"]); assert_has_sup_sd(&rama, Stri, &["rame"]); assert_has_sup_sp(&rama, Stri, &["ramAH"]); @@ -22,7 +24,7 @@ fn sk_288() { #[test] fn sk_289() { - let rama = nyap("ramA"); + let rama = create_stryanta("ramA", "rama"); assert_has_sup_3s(&rama, Stri, &["ramayA"]); assert_has_sup_3d(&rama, Stri, &["ramAByAm"]); assert_has_sup_3p(&rama, Stri, &["ramABiH"]); @@ -30,7 +32,7 @@ fn sk_289() { #[test] fn sk_290() { - let rama = nyap("ramA"); + let rama = create_stryanta("ramA", "rama"); assert_has_sup_4s(&rama, Stri, &["ramAyE"]); assert_has_sup_6s(&rama, Stri, &["ramAyAH"]); assert_has_sup_6d(&rama, Stri, &["ramayoH"]); @@ -81,7 +83,7 @@ fn sk_301() { #[test] fn sk_303() { - let shri = dhatu_prati("SrI"); + let shri = create_krdanta("SrI", &[], &d("SriY", Bhvadi), Krt::kvip); assert_has_sup_ss(&shri, Stri, &["SrIH"]); assert_has_sup_4s(&shri, Stri, &["Sriye", "SriyE"]); assert_has_sup_5s(&shri, Stri, &["SriyAH", "SriyaH"]); @@ -93,9 +95,9 @@ fn skip_sk_305() {} #[ignore] #[test] fn sk_306() { - assert_has_sup_1s("krozwf", Stri, &["krozwrI"]); - assert_has_sup_1d("krozwf", Stri, &["krozwryO"]); - assert_has_sup_1p("krozwf", Stri, &["krozwryaH"]); + assert_has_sup_1s("krozwu", Stri, &["krozwrI"]); + assert_has_sup_1d("krozwu", Stri, &["krozwryO"]); + assert_has_sup_1p("krozwu", Stri, &["krozwryaH"]); assert_has_sup_1s("vaDU", Stri, &["vaDUH"]); assert_has_sup_1s("BU", Stri, &["BUH"]);