From 2eb44349ee2f75a577c92411d410285d4cfb8d0a Mon Sep 17 00:00:00 2001 From: Arun Prasad Date: Sun, 10 Dec 2023 21:23:20 -0800 Subject: [PATCH] [prakriya] Increase Kaumudi test coverage Quality: - Substantially increase test coverage in Kaumudi 43 - 52. - Add around 70 new tests. - Model varttikas explicitly and consistently with the `Varttika` variant. - Add varttikas and Dhatupatha gana-sutras to `data/`. - Fix various small typos in `dhatupatha.tsv`. - Increase performance by around 10%. We did this mainly by reducing use of `CompactString` in routines that focus on string manipulation and avoiding an unnecessary allocation in the `it_samjna` rules. - Add broad support for kaNDvAdi-dhAtus. - Add better support for iT-Agama rules with liT. API: - Upgrade wasm API to more richly model the effects of a rule. - Update web frontend to hide empty terms and show varttika text. Development: - Add `create_all_tinantas` script to generate all tinantas and write them to one file. --- Cargo.lock | 1 + vidyut-lipi/src/lib.rs | 119 +++- vidyut-prakriya/Cargo.toml | 1 + vidyut-prakriya/Makefile | 24 +- .../data/dhatupatha-ganasutras.tsv | 18 + vidyut-prakriya/data/dhatupatha.tsv | 10 +- vidyut-prakriya/data/varttikas.tsv | 93 +++ .../examples/create_all_tinantas.rs | 105 +++ .../examples/create_tinantas_babylon.rs | 99 +-- vidyut-prakriya/src/angasya.rs | 99 +-- vidyut-prakriya/src/angasya/abhyasasya.rs | 17 +- vidyut-prakriya/src/angasya/asiddhavat.rs | 141 ++-- vidyut-prakriya/src/angasya/guna_vrddhi.rs | 25 +- vidyut-prakriya/src/angasya/subanta.rs | 5 +- vidyut-prakriya/src/ardhadhatuka.rs | 8 +- vidyut-prakriya/src/args/dhatu.rs | 11 +- vidyut-prakriya/src/args/krt.rs | 3 + vidyut-prakriya/src/args/taddhita.rs | 17 +- vidyut-prakriya/src/args/unadi.rs | 11 +- vidyut-prakriya/src/ashtadhyayi.rs | 35 +- vidyut-prakriya/src/atidesha.rs | 74 +- vidyut-prakriya/src/atmanepada.rs | 79 ++- vidyut-prakriya/src/core/prakriya.rs | 105 ++- vidyut-prakriya/src/core/tag.rs | 2 + vidyut-prakriya/src/core/term.rs | 81 ++- vidyut-prakriya/src/core/term_view.rs | 35 +- vidyut-prakriya/src/dhatu_gana.rs | 3 + vidyut-prakriya/src/dhatu_karya.rs | 131 +++- vidyut-prakriya/src/dhatupatha.rs | 22 +- vidyut-prakriya/src/dvitva.rs | 4 +- vidyut-prakriya/src/ganapatha.rs | 33 +- vidyut-prakriya/src/it_agama.rs | 169 +++-- vidyut-prakriya/src/it_samjna.rs | 353 ++++----- vidyut-prakriya/src/krt/basic.rs | 42 +- vidyut-prakriya/src/krt/unadipatha.rs | 115 ++- vidyut-prakriya/src/samasa.rs | 3 +- vidyut-prakriya/src/samjna.rs | 8 +- vidyut-prakriya/src/sanadi.rs | 26 +- vidyut-prakriya/src/stem_gana.rs | 7 + vidyut-prakriya/src/stritva.rs | 5 +- .../src/taddhita/matvartha_prakarana.rs | 2 +- .../src/taddhita/panchami_prakarana.rs | 3 +- vidyut-prakriya/src/taddhita/pragdivyatiya.rs | 19 +- vidyut-prakriya/src/taddhita/pragvahatiya.rs | 5 +- vidyut-prakriya/src/taddhita/pragvatiya.rs | 156 +++- vidyut-prakriya/src/taddhita/prakkritiya.rs | 11 +- .../src/taddhita/samasanta_prakarana.rs | 3 +- .../src/taddhita/svarthika_prakarana.rs | 3 +- vidyut-prakriya/src/taddhita/utils.rs | 2 - vidyut-prakriya/src/tripadi/pada_8_2.rs | 48 +- vidyut-prakriya/src/tripadi/pada_8_3.rs | 20 +- vidyut-prakriya/src/tripadi/pada_8_4.rs | 5 +- vidyut-prakriya/src/uttarapade.rs | 4 +- vidyut-prakriya/src/vikarana.rs | 50 +- vidyut-prakriya/src/wasm.rs | 74 +- vidyut-prakriya/test_utils/src/lib.rs | 48 +- vidyut-prakriya/tests/kashika_1_1.rs | 3 +- vidyut-prakriya/tests/kashika_1_3.rs | 37 + vidyut-prakriya/tests/kashika_3_1.rs | 10 +- vidyut-prakriya/tests/kashika_5_1.rs | 318 +++++++++ vidyut-prakriya/tests/kashika_6_4.rs | 82 ++- vidyut-prakriya/tests/kashika_7_1.rs | 20 +- vidyut-prakriya/tests/kashika_7_2.rs | 51 +- vidyut-prakriya/tests/kashika_7_3.rs | 26 +- vidyut-prakriya/tests/kashika_7_4.rs | 23 + vidyut-prakriya/tests/kashika_8_2.rs | 24 +- vidyut-prakriya/tests/kaumudi_43.rs | 126 ++-- vidyut-prakriya/tests/kaumudi_44.rs | 73 +- vidyut-prakriya/tests/kaumudi_45.rs | 3 +- vidyut-prakriya/tests/kaumudi_46.rs | 185 +++-- vidyut-prakriya/tests/kaumudi_47.rs | 5 +- vidyut-prakriya/tests/kaumudi_48.rs | 44 +- vidyut-prakriya/tests/kaumudi_50.rs | 13 +- vidyut-prakriya/tests/kaumudi_51.rs | 111 ++- vidyut-prakriya/tests/kaumudi_52.rs | 670 +++++++++++++++++- vidyut-prakriya/tests/kaumudi_54.rs | 5 +- vidyut-prakriya/tests/kaumudi_58.rs | 68 ++ vidyut-prakriya/tests/kaumudi_67.rs | 67 ++ vidyut-prakriya/tests/regressions.rs | 2 +- vidyut-prakriya/www/index.html | 60 +- vidyut-prakriya/www/static/app.js | 142 ++-- 81 files changed, 3612 insertions(+), 1148 deletions(-) create mode 100644 vidyut-prakriya/data/dhatupatha-ganasutras.tsv create mode 100644 vidyut-prakriya/data/varttikas.tsv create mode 100644 vidyut-prakriya/examples/create_all_tinantas.rs create mode 100644 vidyut-prakriya/tests/kaumudi_58.rs diff --git a/Cargo.lock b/Cargo.lock index 034d1cc..d525702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1022,6 +1022,7 @@ dependencies = [ "sha2 0.10.6", "sha256", "test_utils", + "vidyut-lipi", "wasm-bindgen", ] diff --git a/vidyut-lipi/src/lib.rs b/vidyut-lipi/src/lib.rs index 190be2f..133c89d 100644 --- a/vidyut-lipi/src/lib.rs +++ b/vidyut-lipi/src/lib.rs @@ -1,17 +1,19 @@ +//! Hacky transliteration functions that other crates might need. #![doc = include_str!("../README.md")] #![deny(missing_docs)] #![deny(clippy::unwrap_used)] -//! Hacky transliteration functions that other crates might need. use std::cmp; /// Defines the available transliteration schemes. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] pub enum Scheme { /// SlP1 transliteration. Slp1, /// IAST transliteration. Iast, + /// Devanagari. + Devanagari, } fn map_char(cur: &str) -> Option<&'static str> { @@ -87,13 +89,118 @@ fn iast_to_slp1(input: &str) -> String { ret } +fn slp1_to_devanagari(text: &str) -> String { + const VIRAMA: char = '\u{094D}'; + + let mut ret = String::new(); + for c in text.chars() { + let out = match c { + 'a' => "अ", + 'A' => "आ", + 'i' => "इ", + 'I' => "ई", + 'u' => "उ", + 'U' => "ऊ", + 'f' => "ऋ", + 'F' => "ॠ", + 'x' => "ऌ", + 'X' => "ॡ", + 'e' => "ए", + 'E' => "ऐ", + 'o' => "ओ", + 'O' => "औ", + '~' => "\u{0901}", + 'M' => "\u{0902}", + 'H' => "\u{0903}", + 'k' => "क", + 'K' => "ख", + 'g' => "ग", + 'G' => "घ", + 'N' => "ङ", + 'c' => "च", + 'C' => "छ", + 'j' => "ज", + 'J' => "झ", + 'Y' => "ञ", + 'w' => "ट", + 'W' => "ठ", + 'q' => "ड", + 'Q' => "ढ", + 'R' => "ण", + 't' => "त", + 'T' => "थ", + 'd' => "द", + 'D' => "ध", + 'n' => "न", + 'p' => "प", + 'P' => "फ", + 'b' => "ब", + 'B' => "भ", + 'm' => "म", + 'y' => "य", + 'r' => "र", + 'l' => "ल", + 'v' => "व", + 'S' => "श", + 'z' => "ष", + 's' => "स", + 'h' => "ह", + 'L' => "ळ", + other => { + ret.push(other); + continue; + } + }; + + let vowel_mark = match c { + 'a' => Some(""), + 'A' => Some("\u{093E}"), + 'i' => Some("\u{093F}"), + 'I' => Some("\u{0940}"), + 'u' => Some("\u{0941}"), + 'U' => Some("\u{0942}"), + 'f' => Some("\u{0943}"), + 'F' => Some("\u{0944}"), + 'x' => Some("\u{0962}"), + 'X' => Some("\u{0963}"), + 'e' => Some("\u{0947}"), + 'E' => Some("\u{0948}"), + 'o' => Some("\u{094B}"), + 'O' => Some("\u{094C}"), + _ => None, + }; + + if ret.chars().last() == Some(VIRAMA) && vowel_mark.is_some() { + // Pop virama and add. + ret.pop(); + ret += vowel_mark.expect("ok"); + } else { + ret += out; + } + + let is_consonant = "kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL".contains(c); + if is_consonant { + ret.push(VIRAMA); + } + } + ret +} + /// Transliterates the given input text. /// -/// Only the IAST -> SLP1 mapping is defined. All other mappings will panic. +/// ### Panics +/// +/// Only the IAST -> SLP1 and SLP1 -> Devanagari mappings are defined. All other mappings will +/// panic. pub fn transliterate(input: &str, from: Scheme, to: Scheme) -> String { - assert!(from == Scheme::Iast); - assert!(to == Scheme::Slp1); - iast_to_slp1(input) + use Scheme::*; + if from == Iast && to == Slp1 { + iast_to_slp1(input) + } else if from == Slp1 && to == Devanagari { + slp1_to_devanagari(input) + } else { + panic!("Unsupported scheme combination: {from:?} -> {to:?}") + } } #[cfg(test)] diff --git a/vidyut-prakriya/Cargo.toml b/vidyut-prakriya/Cargo.toml index e63b182..e087b50 100644 --- a/vidyut-prakriya/Cargo.toml +++ b/vidyut-prakriya/Cargo.toml @@ -26,6 +26,7 @@ console_error_panic_hook = "0.1.7" [dev-dependencies] test_utils = { path = "test_utils" } +vidyut-lipi = { path = "../vidyut-lipi" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/vidyut-prakriya/Makefile b/vidyut-prakriya/Makefile index d45bd1a..8088758 100644 --- a/vidyut-prakriya/Makefile +++ b/vidyut-prakriya/Makefile @@ -53,40 +53,40 @@ test_tinantas: cargo build --release ../target/release/test_tinantas \ --test-cases test-files/tinantas-basic-kartari.csv \ - --hash "ff57ac933f1a44a21285448f1b064d1b4464a7aee650981cb30244c8ee3ed111" + --hash "28293a6aa746f04dff1a5c3b822396c236df269460d691bd137ba01a2c80557f" ../target/release/test_tinantas \ --test-cases test-files/tinantas-nic-kartari.csv \ - --hash "263fa8bc08eeb912ffe4daa876452a1bea1a4117620d4e3d86aa876f03795140" + --hash "5d508a8b3a52ebe92a1524b0b51bbed90e27301f265669aa8e7a887d55bf1eff" ../target/release/test_tinantas \ --test-cases test-files/tinantas-san-kartari.csv \ - --hash "c9c2c2e79eecf4a6bbe105537ceb64f77004ce3ff3b53a07a4ac410f0131de0e" + --hash "ef278531cd45ba1df9af60e5b4b8ef582fdbe7a7eb31478fe35b9600c42380fc" ../target/release/test_tinantas \ --test-cases test-files/tinantas-yan-kartari.csv \ - --hash "585c83fa6a241d7f31d2b12e7382e65d05b3f7703edaa1609ee3617810aa74d2" + --hash "be90fccc6f3907862cf820969094fd958b44b58a447a7a6369edbecde75d8cd4" ../target/release/test_tinantas \ --test-cases test-files/tinantas-yan-luk-kartari.csv \ - --hash "9168fb70bce7903708004da407dfe1c14aedc199ab770c2ee524b7f573233cfc" + --hash "aec7b4524b159e195e38ce4b0e5e1335940b60cb41606ba31d1b9fbd010f7d11" ../target/release/test_tinantas \ --test-cases test-files/tinantas-basic-karmani.csv \ - --hash "63d076bf9d8b88d7a03f224626410ec2be751f2b50ef0f0777c5cddcecad3dfd" + --hash "b3621fe5bf2295f2f1d15270aa26b9fc973450126cd4a551e53f91571e4d531c" ../target/release/test_tinantas \ --test-cases test-files/tinantas-nic-karmani.csv \ - --hash "2b9aa1158d26ce7a9da28f7ec8685ce61554daa3f8434770aec3e16e000eefe2" + --hash "f4760cd6da0496f6db82f1812ba168a18e8cde4e5dffafee815e1e88d19abb36" ../target/release/test_tinantas \ --test-cases test-files/tinantas-san-karmani.csv \ - --hash "e60669056aec2124c27c8d60f3cebe19b75e11d193e87522458be06291db221f" + --hash "089160604d7a5a40f8f71e1234cccc3667135b3e2654c4ac346677727e5aae80" ../target/release/test_tinantas \ --test-cases test-files/tinantas-yan-karmani.csv \ - --hash "7e0ed1e074eff8eb104dc88b8cf7525d1e28b8686bb82dccb9d036a4696caed7" + --hash "260a684b78e4e66a68f89366c07850d1680a72424e2934392678359289a1916b" test_krdantas: cargo build --release ../target/release/test_krdantas \ --test-cases test-files/krdantas-ktvA.csv \ - --hash "6d480b70491153eeac8958d5f66c32e4e3e428f54c6e0fc2d75154889642ef7b" + --hash "59470473bec6cb2d2254217d604a2302c6ee8926571441b3281004a30abc81ce" ../target/release/test_krdantas \ --test-cases test-files/krdantas-kta.csv \ - --hash "bb99612ddcc34a66aff16553ed325f8b1a09d4bfcc920f86d312c959c6b1800b" + --hash "2ce641122f4c6ac243acb348d376f35586c5f960ea338b9b1f7b79f0f72e3c12" test_subantas: cargo run --bin test_subantas -- \ @@ -102,7 +102,7 @@ check_rule_coverage: # Profiles the program's execution time on OSX. This command will probably not # work on other operating systems. profile-time-osx: - cargo instruments -t time --release --bin create_test_file + cargo instruments -t time --release --example create_all_tinantas > /dev/null # Other diff --git a/vidyut-prakriya/data/dhatupatha-ganasutras.tsv b/vidyut-prakriya/data/dhatupatha-ganasutras.tsv new file mode 100644 index 0000000..bb5c46d --- /dev/null +++ b/vidyut-prakriya/data/dhatupatha-ganasutras.tsv @@ -0,0 +1,18 @@ +01.0933_GawAdayo mitaH +01.0934_janIjFzkanasuraYjo'mantASca +01.0935_jvalahvalahmalanamAmanupasargAdvA +01.0936_glAsnAvanuvamAM ca +01.0937_na kamyamicamAm +01.0938_Samo darSane +01.0939_yamo'parivezaRe +01.0940_sKadiravapariByAM ca +02.0076_carkarItaM ca +04.0162_svAdaya oditaH +10.0493_jYapAdayo mitaH +10.0494_nAnye mito'hetO +10.0495_kusma nAmno vA +10.0496_A kusmAdAtmanepadinaH +10.0497_A garvAdAtmanepadinaH +10.0498_A DfzAdvA +10.0499_A svadaH sakarmakAt +10.0500_hantyarTASca diff --git a/vidyut-prakriya/data/dhatupatha.tsv b/vidyut-prakriya/data/dhatupatha.tsv index 19e8145..fe2d759 100644 --- a/vidyut-prakriya/data/dhatupatha.tsv +++ b/vidyut-prakriya/data/dhatupatha.tsv @@ -781,7 +781,7 @@ code dhatu artha 01.0780 Iza~ uYCe 01.0781 kaza~ hiMsAyAm 01.0782 Kaza~ hiMsAyAm -01.0783 Siza~ hiMsAyAm +01.0783 Si\\za~ hiMsAyAm 01.0784 jaza~ hiMsAyAm 01.0785 Jaza~ hiMsAyAm 01.0786 Saza~ hiMsAyAm @@ -1246,7 +1246,7 @@ code dhatu artha 03.0002 YiBI\ Baye 03.0003 hrI\ lajjAyAm 03.0004 pF pAlanapUraRayoH -03.0005 pf pAlanapUraRayoH +03.0005 pf\ pAlanapUraRayoH 03.0006 quBf\Y DAraRapozaRayoH 03.0007 mA\N mAne Sabde ca 03.0008 o~hA\N gatO @@ -1785,7 +1785,7 @@ code dhatu artha 10.0034 kuwwa~ CedanaBartsanayoH 10.0035 puwwa~ alpIBAve 10.0036 cuwwa~ alpIBAve -10.0037 awwa~ anAdare +10.0037 adwa~ anAdare 10.0038 zuwwa~ anAdare 10.0039 lunwa~ steye 10.0040 lunWa~ steye @@ -1810,7 +1810,7 @@ code dhatu artha 10.0059 Sliza~ SlezaRe 10.0060 paTi~ gatO 10.0061 piCa~ kuwwane -10.0062 Cada~ saMvaraRe +10.0062 Cadi~ saMvaraRe 10.0063 SraRa~ dAne 10.0064 taqa~ AGAte 10.0065 Kaqa~ Bedane @@ -2086,7 +2086,7 @@ code dhatu artha 10.0335 ruja~ hiMsAyAm 10.0336 zvada~ AsvAdane 10.0337 svAda~ AsvAdane -10.0338 yuja~ saMyamane +10.0338 yu\ja~ saMyamane 10.0339 pfca~ saMyamane 10.0340 arca~ pUjAyAm 10.0341 zaha~ marzaRe diff --git a/vidyut-prakriya/data/varttikas.tsv b/vidyut-prakriya/data/varttikas.tsv new file mode 100644 index 0000000..f519391 --- /dev/null +++ b/vidyut-prakriya/data/varttikas.tsv @@ -0,0 +1,93 @@ +1.1.33.1 viBAzAprakaraRe tIyasya NitsUpasaNKyAnam +1.2.1.1 vyaceH kuwAditvamanasIti vaktavyam +1.2.6.1 SranTigranTidamBisvaYjInAmiti vaktavyam +1.3.3.1 ira itsaMjJA vAcyA +1.3.22.1 ANaH pratijYAyAm +1.3.29.1 dfSeSceti vaktavyam +1.3.30.1 upasargAdasyatyUhrorvA vacanam +1.4.60.3 duraH zatvaRatvayorupasargatvapratizeDo vaktavyaH +1.4.65.1 antaHSabdasya aNkiviDiRatvezu upasargasaMjYA vaktavyA +2.1.37.1 BayaBItaBItiBIBiriti vaktavyam +2.4.45.1 iRvadika iti vaktavyam +2.4.54.1 varjane pratizeDo vaktavyaH +2.4.56.2 valAdAvArDaDAtuke vezyate +3.1.11.1 ojaso'psaraso nityamitarezAM viBAzayA +3.1.14.1 satrakazwakakzakfcCragahaneByaH kaRvacikIrzAyAm iti vaktavyam +3.1.15.2 tapasaH parasmEpadaM ca +3.1.16.1 PenAcceti vaktavyam +3.1.17.1 sudinadurdinanIhareByaSceti vaktavyam +3.1.17.2 awAwwASIkAkowApowAsowApruzwApluzwAgrahaRaM kartavyam +3.1.22.1 sUcisUtramUtryawyartyaSUrRotInAM grahaRaM +3.1.25.1 arTavedasatyAnAmApugvaktavyaH +3.1.35.1 kAsyanekAca iti vaktavyam +3.1.36.1 UrRoteSca pratizeDo vaktavyaH +3.1.44.1 spfSamfSakfzatfpadfpAM cleH sijvA vaktavyaH +3.1.48.1 RiSridrusruzu kamerupasaMKyAnaM kartavyam +3.1.96.1 vasestavyat kartari Ricca +3.1.96.2 kelimara upasaNKyAnam +3.1.97.1 takiSasicatiyatijanInAmupasaNKyAnam +3.1.97.2 hano vA vaDa ca +3.1.100.1 carerANi cAgurO +3.2.8.1 pibateH surASIDvoriti vaktavyam +3.2.9.1 SaktilANgalANkuSayazwitomaraGawaGawIDanuzzu graherupasaNKyAnam +3.2.9.2 sUtre ca DAryarTe +3.2.60.1 samAnAnyayoSceti vaktavyam +3.2.174.1 krukannapi vaktavyaH +3.2.178.1 kvibvacipracCAyatastukawaprujuSrIRAM dIrGo'saMprasAraRaM ca +3.3.125.1 KanerqaqarekekavakA vAcyAH +4.1.6.1 DAtorugitaH pratizeDaH +4.1.68.1 SvaSurasyokArAkAralopaSca +4.1.97.1 vyAsavaruqanizAdacaRqAlabimbAnAm iti vaktavyam +4.1.128.1 cawakAc ceti vaktavyam +4.2.28.1 CaprakaraRe pENgAkzIputrAdiBya upasaNKyAnam +4.2.28.2 SatarudrAcCaSca GaSca +4.2.40.1 gaRikAyASca yaY vaktavyaH +4.2.42.1 pfzWAdupasaNKyAnam +4.2.43.1 gajAcceti vaktavyam +4.2.93.1 avArapArAdvigfhItAdapi viparItAcceti vaktavyam +4.4.41.1 aDarmAcceti vaktavyam +4.4.49.1 narAcceti vaktavyam +5.1.6.1 yatprakaraRe raTAcca +5.1.33.1 kevalAyASceti vaktavyam +5.1.38.2 saMnipAtAcceti vaktavyam +5.1.74.1 kroSaSatayojanaSatayorupasaNKyAnam +5.1.77.1 AhftaprakaraRe vArijaNgalasTalkAntArapUrvapadAdupasaNKyAnam +5.1.77.2 ajapaTaSaNkupaTAByAM copasaNKyAnam +5.1.77.3 maDukamaricayoraR sTalAt +5.2.29.1 alAbUtilomABaNgAByo rajasyupasaNKyAnam +5.2.112.1 anyeByo'pi dfSyata iti vaktavyam +5.4.3.1 caYcabfhayorupasaNKyAnam +5.4.78.1 palyarAjaByAM ca +6.1.3.3 Irzyates tftIyasya dve Bavata iti vaktavyam +6.1.64.1 subDAtuzWivuzvazkatInAM satvapratizeDo vaktavyaH +6.1.64.2 zWivu ityasya dvitIyasTakArazWakAraSca izyate +6.3.11.1 antAcca +6.3.118.1 anutsAhaBrAtfpitFRAm ityeva +6.4.16.1 gameriNAdeSasyeti vaktavyam +6.4.24.2 raYjerRO mfgaramaRa upasaNKyAnaM kartavyam +6.4.24.3 GinuRi ca raYjerupasaNKyAnaM kartavyam +6.4.34.1 kvO ca SAsa ittvaM BavatIti vaktavyam +6.4.34.2 kvippratyaye tu tasya api BavatIti vaktavyam +6.4.84.1 dfnkarapunaH pUrvasya Buvo yaRvaktavyaH +6.4.114.1 daridrAterArDaDAtuke lopo vaktavyaH +6.4.114.2 adyatanyAM veti vaktavyam +6.4.120.1 damBeretvaM vaktavyam +6.4.122.1 SranTeSceti vaktavyam +6.4.144.1 nAnatasya wilope sabrahmacAripIWasarpikalApikuTumitEtilijAjalilANgaliSilAliSiKaRqisUkarasadmasuparvaRAmupasaNKyAnaM kartavyam +6.4.148.1 yasyetyONaH SyAM pratizeDo vaktavyaH +6.4.155.1 RAvizWavat prAtipadikasya kAryaM BavatIti vaktavyam +7.1.26.1 ekatarAtpratizeDo vaktavyaH +7.1.59.1 Se tfmPAdInAmupasaNKyAnaM kartavyam +7.1.90.1 oto Riditi vAcyam +7.2.49.1 tanipatidaridrARAmupasaNKyAnam +7.2.68.1 dfSeSceti vaktavyam +7.3.34.1 anAcamikamivamInAm iti vaktavyam +7.3.37.1 lugAgamastu tasya vaktavyaH +7.3.37.2 DUYprIYornugvaktavyaH +7.4.3.1 kARyAdInAM ceti vaktavyam +7.4.30.1 hanterhisAyAM yaNi GnIBAvo vaktavyaH +7.4.54.1 sani rADo hiMsAyAmaca is vaktavyaH +7.4.90.1 rIgftvata iti vaktavyam +8.2.8.1 NAvuttarapade pratizeDasya pratizeDo vaktavyaH +8.2.8.3 vA napuMsakAnAm iti vaktavyam +8.3.118.1 svaYjerupasaNKyAnaM kartavyam diff --git a/vidyut-prakriya/examples/create_all_tinantas.rs b/vidyut-prakriya/examples/create_all_tinantas.rs new file mode 100644 index 0000000..754e9d9 --- /dev/null +++ b/vidyut-prakriya/examples/create_all_tinantas.rs @@ -0,0 +1,105 @@ +//! Creates a very large list of tinantas. This list includes all combinations of: +//! +//! - Around 2000 dhatus from our dhatupatha +//! - 2 prayogas +//! - 5 sanAdi combinations (none, nic, san, yan, yan-luk) +//! - 10 lakaras +//! - 3 purushas +//! - 3 vacanas +//! +//! These combinations produce around 2000 x 2 x 5 x 10 x 3 x 3 = 1.8 million tinantas. +use serde::Serialize; +use std::error::Error; +use std::io; +use vidyut_prakriya::args::{Lakara, Prayoga, Purusha, Sanadi, Tinanta, Vacana}; +use vidyut_prakriya::{Dhatupatha, Vyakarana}; + +#[derive(Debug, Serialize)] +struct Row<'a> { + padas: String, + dhatu: &'a str, + gana: &'static str, + number: u16, + prayoga: &'static str, + lakara: &'static str, + purusha: &'static str, + vacana: &'static str, +} + +fn run(dhatupatha: Dhatupatha) -> Result<(), Box> { + let sanadi_choices = vec![ + vec![], + vec![Sanadi::san], + vec![Sanadi::Ric], + vec![Sanadi::yaN], + vec![Sanadi::yaNluk], + ]; + + let mut wtr = csv::Writer::from_writer(io::stdout()); + let v = Vyakarana::builder().log_steps(false).build(); + + for entry in dhatupatha { + let dhatu = entry.dhatu(); + for sanadis in &sanadi_choices { + for prayoga in &[Prayoga::Kartari, Prayoga::Karmani] { + for lakara in Lakara::iter() { + for purusha in Purusha::iter() { + for vacana in Vacana::iter() { + let tinanta = Tinanta::builder() + .dhatu(dhatu.clone().with_sanadi(&sanadis)) + .prayoga(*prayoga) + .purusha(*purusha) + .vacana(*vacana) + .lakara(*lakara) + .build()?; + + let prakriyas = v.derive_tinantas(&tinanta); + if prakriyas.is_empty() { + continue; + } + + let dhatu_text = &dhatu.upadesha().expect("ok"); + let mut padas: Vec<_> = prakriyas.iter().map(|p| p.text()).collect(); + padas.sort(); + let padas = padas.join("|"); + + let row = Row { + padas, + dhatu: dhatu_text, + gana: dhatu.gana().expect("ok").as_str(), + number: entry.number(), + lakara: lakara.as_str(), + purusha: purusha.as_str(), + vacana: vacana.as_str(), + prayoga: prayoga.as_str(), + }; + + wtr.serialize(row)?; + } + } + } + } + } + } + + wtr.flush()?; + Ok(()) +} + +fn main() { + let dhatus = match Dhatupatha::from_path("data/dhatupatha.tsv") { + Ok(res) => res, + Err(err) => { + println!("{}", err); + std::process::exit(1); + } + }; + + match run(dhatus) { + Ok(()) => (), + Err(err) => { + eprintln!("{}", err); + std::process::exit(1); + } + } +} diff --git a/vidyut-prakriya/examples/create_tinantas_babylon.rs b/vidyut-prakriya/examples/create_tinantas_babylon.rs index a5d054c..c86af39 100644 --- a/vidyut-prakriya/examples/create_tinantas_babylon.rs +++ b/vidyut-prakriya/examples/create_tinantas_babylon.rs @@ -17,6 +17,7 @@ //! ``` use clap::Parser; +use vidyut_lipi::{transliterate, Scheme}; use vidyut_prakriya::args::*; use vidyut_prakriya::dhatupatha::Entry as DhatuEntry; use vidyut_prakriya::{Dhatupatha, Vyakarana}; @@ -43,104 +44,8 @@ struct BabylonEntry { html_row: String, } -/// A *very* simple transliterator. -/// -/// TODO: use `vidyut-lipi` instead once it is stable. fn to_devanagari(text: &str) -> String { - const VIRAMA: char = '\u{094D}'; - - let mut ret = String::new(); - for c in text.chars() { - let out = match c { - 'a' => "अ", - 'A' => "आ", - 'i' => "इ", - 'I' => "ई", - 'u' => "उ", - 'U' => "ऊ", - 'f' => "ऋ", - 'F' => "ॠ", - 'x' => "ऌ", - 'X' => "ॡ", - 'e' => "ए", - 'E' => "ऐ", - 'o' => "ओ", - 'O' => "औ", - '~' => "\u{0901}", - 'M' => "\u{0902}", - 'H' => "\u{0903}", - 'k' => "क", - 'K' => "ख", - 'g' => "ग", - 'G' => "घ", - 'N' => "ङ", - 'c' => "च", - 'C' => "छ", - 'j' => "ज", - 'J' => "झ", - 'Y' => "ञ", - 'w' => "ट", - 'W' => "ठ", - 'q' => "ड", - 'Q' => "ढ", - 'R' => "ण", - 't' => "त", - 'T' => "थ", - 'd' => "द", - 'D' => "ध", - 'n' => "न", - 'p' => "प", - 'P' => "फ", - 'b' => "ब", - 'B' => "भ", - 'm' => "म", - 'y' => "य", - 'r' => "र", - 'l' => "ल", - 'v' => "व", - 'S' => "श", - 'z' => "ष", - 's' => "स", - 'h' => "ह", - 'L' => "ळ", - other => { - ret.push(other); - continue; - } - }; - - let vowel_mark = match c { - 'a' => Some(""), - 'A' => Some("\u{093E}"), - 'i' => Some("\u{093F}"), - 'I' => Some("\u{0940}"), - 'u' => Some("\u{0941}"), - 'U' => Some("\u{0942}"), - 'f' => Some("\u{0943}"), - 'F' => Some("\u{0944}"), - 'x' => Some("\u{0962}"), - 'X' => Some("\u{0963}"), - 'e' => Some("\u{0947}"), - 'E' => Some("\u{0948}"), - 'o' => Some("\u{094B}"), - 'O' => Some("\u{094C}"), - _ => None, - }; - - if ret.chars().last() == Some(VIRAMA) && vowel_mark.is_some() { - // Pop virama and add. - ret.pop(); - ret += vowel_mark.expect("ok"); - } else { - ret += out; - } - - let is_consonant = "kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL".contains(c); - if is_consonant { - ret.push(VIRAMA); - } - } - ret + transliterate(&text, Scheme::Slp1, Scheme::Devanagari) } /// Removes svarita and anudAtta from the dhatu (for easier searching) diff --git a/vidyut-prakriya/src/angasya.rs b/vidyut-prakriya/src/angasya.rs index fb87c06..0156434 100644 --- a/vidyut-prakriya/src/angasya.rs +++ b/vidyut-prakriya/src/angasya.rs @@ -24,9 +24,7 @@ use crate::ac_sandhi; use crate::args::Gana::*; 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::{Prakriya, Rule}; +use crate::core::{Prakriya, Rule, Rule::Varttika, Tag as T, Term}; use crate::dhatu_gana as gana; use crate::it_samjna; use crate::sounds as al; @@ -73,7 +71,7 @@ fn try_do_dirgha(p: &mut Prakriya, i_anga: usize) -> Option<()> { 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~", "gami~"])) && n.has_u("san") { if anga.has_u("gami~") { - p.step(Rule::Varttika("6.4.16", "1")); + p.step(Varttika("6.4.16.1")); } // Per varttika, include only "gami~", not "ga\\mx~". let code = "6.4.16"; @@ -150,15 +148,15 @@ pub fn maybe_do_jha_adesha(p: &mut Prakriya) -> Option<()> { let i_base = p.find_prev_where(i, |t| !t.is_empty())?; let base = p.get(i_base)?; - if base.has_tag(T::Abhyasta) { + if base.is_abhyasta() { // juhvati - p.run_at("7.1.4", i, op::adi("at")); + p.run_at("7.1.4", i, |t| t.set_adi("at")); } else if !base.has_antya('a') && tin.is_atmanepada() { // kurvate - p.run_at("7.1.5", i, op::adi("at")); + p.run_at("7.1.5", i, |t| t.set_adi("at")); } else { // Bavanti - p.run_at("7.1.3", i, op::adi("ant")); + p.run_at("7.1.3", i, |t| t.set_adi("ant")); } let base = p.get(i_base)?; @@ -180,7 +178,7 @@ pub fn maybe_do_jha_adesha(p: &mut Prakriya) -> Option<()> { } fn replace_pha_dha_and_others(t: &Term) -> Option<&'static str> { - if t.has_adi(&*PHA_DHA_KHA_CHA_GHA) { + if t.has_adi(&*PHA_DHA_KHA_CHA_GHA) && !t.is_unadi() { let sub = match t.adi()? { 'P' => "Ayan", 'Q' => "ey", @@ -386,7 +384,7 @@ fn try_add_num_agama_for_dhatu_before_asiddhavat(p: &mut Prakriya) -> Option<()> /// Example: jaBate -> jamBate /// /// (7.1.58 - 7.1.83) -fn try_add_num_agama_for_dhatu(p: &mut Prakriya) -> Option<()> { +fn try_add_num_agama_for_dhatu_after_asiddhavat(p: &mut Prakriya) -> Option<()> { let i = p.find_first(T::Dhatu)?; // 7.1.58 (idito nuM dhAtoH) is in `dhatu_karya`, so we skip it here. @@ -398,7 +396,7 @@ fn try_add_num_agama_for_dhatu(p: &mut Prakriya) -> Option<()> { 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, add_num); + p.run_at(Varttika("7.1.59.1"), i, add_num); } let anga = p.get(i)?; @@ -600,7 +598,7 @@ fn try_change_anga_before_y(p: &mut Prakriya, i: usize) -> Option<()> { p.run_at("7.4.27", i, op::antya("rI")); } } else if anga.has_u("ha\\na~") && n.has_u("yaN") { - p.optional_run_at("7.4.30.v1", i, op::text("GnI")); + p.optional_run_at(Varttika("7.4.30.1"), 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")); @@ -649,7 +647,7 @@ fn try_anga_changes_to_t(p: &mut Prakriya, i_anga: usize) -> Option<()> { } else { p.run_at(code, i_anga, op::antya("i")); } - } else if anga.has_text_in(&["SA", "CA"]) { + } else if anga.has_u_in(&["So\\", "Co\\"]) { 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")); @@ -688,7 +686,7 @@ pub fn try_add_or_remove_nit(p: &mut Prakriya) -> Option<()> { if anga.has_text("go") && last.is_sarvanamasthana() { p.add_tag_at("7.1.90", i, T::Rit); } else if anga.has_antya('o') && last.is_sarvanamasthana() { - p.add_tag_at("7.1.90.v1", i, T::Rit); + p.add_tag_at(Varttika("7.1.90.1"), i, T::Rit); } else if last.has_u("Ral") && last.has_tag(T::Uttama) { p.optional_run_at("7.1.91", i, |t| { t.remove_tag(T::Rit); @@ -1121,6 +1119,12 @@ fn try_cani_after_guna(p: &mut Prakriya) -> Option<()> { let sub = al::to_hrasva(dhatu.upadha()?)?; p.optional_run_at("7.4.3", i, op::upadha(&sub.to_string())); return Some(()); + } else if dhatu.has_u_in(&[ + "kaRa~", "raRa~", "vaRa~", "SraRa~", "BaRa~", "heWa~", "lupa~", + ]) { + let sub = al::to_hrasva(dhatu.upadha()?)?; + p.optional_run_at(Rule::Varttika("7.4.3.1"), i, op::upadha(&sub.to_string())); + return Some(()); } let dhatu = p.get(i)?; @@ -1239,22 +1243,22 @@ fn try_add_agama_before_ni(p: &mut Prakriya) -> Option<()> { return None; } - let optional_append_agama = |rule, p: &mut Prakriya, i, sub| -> bool { + fn optional_append_agama(rule: impl Into, p: &mut Prakriya, i: usize, sub: &str) -> bool { if p.optional_run(rule, |p| op::insert_agama_after(p, i, sub)) { it_samjna::run(p, i + 1).expect("ok"); true } else { false } - }; + } let mut blocked = false; if dhatu.has_u("pA\\") && dhatu.has_gana(Adadi) { - op::append_agama("7.3.37.v1", p, i, "lu~k"); + op::append_agama(Varttika("7.3.37.1"), p, i, "lu~k"); blocked = true; } else if dhatu.has_text_in(&["prI", "DU"]) { // Optional per Haradatta (see commentary on prIY in siddhAnta-kaumudI) - blocked = optional_append_agama("7.3.37.v2", p, i, "nu~k"); + blocked = optional_append_agama(Varttika("7.3.37.2"), p, i, "nu~k"); } else if dhatu.has_u("vA\\") { blocked = optional_append_agama("7.3.38", p, i, "ju~k"); } else if dhatu.has_text_in(&["lI", "lA"]) { @@ -1302,6 +1306,14 @@ pub fn run_before_stritva(p: &mut Prakriya) -> Option<()> { Some(()) } +fn for_angas(p: &mut Prakriya, func: impl Fn(&mut Prakriya, usize)) { + for i in 0..p.terms().len() { + if p.has(i, |t| t.is_anga()) { + func(p, i); + } + } +} + pub fn run_before_dvitva(p: &mut Prakriya) -> Option<()> { try_add_iit_agama(p); try_shiti(p); @@ -1324,21 +1336,31 @@ pub fn run_before_dvitva(p: &mut Prakriya) -> Option<()> { try_halah_shnah_shanac(p, i); } + // TODO: move this rule to a better place. + { + let i = p.terms().len() - 1; + let last = p.terms().last()?; + if i > 0 && p.has(i - 1, |t| t.has_antya('A')) && last.has_u("Ral") { + op::adesha("7.1.34", p, i, "O"); + } + } + try_add_num_agama_for_dhatu_before_asiddhavat(p); - for i in 0..p.terms().len() { + asiddhavat::try_add_a_agama(p); + for_angas(p, |p, i| { asiddhavat::run_before_guna(p, i); - } + }); // Must follow asiddhavat rules 6.4.37 and 6.4.42. - for i in 0..p.terms().len() { + for_angas(p, |p, i| { try_do_dirgha(p, i); - } + }); // Must follow `try_do_dirgha` (6.4.2). try_pvadinam_hrasva(p); // num-Agama must come after asiddhavat rule 6.4.24, which causes na-lopa. // Exception: naS num-Agama, which is deleted in 6.4.32; - try_add_num_agama_for_dhatu(p); + try_add_num_agama_for_dhatu_after_asiddhavat(p); try_sic_vrddhi(p); try_cani_before_guna(p); @@ -1350,31 +1372,35 @@ pub fn run_before_dvitva(p: &mut Prakriya) -> Option<()> { // // Must run before abhyasa rules to avoid "mitAm hrasva" (jYIpsati). // Must run before `try_ni_adesha` for "lyapi laghupUrvAt" (praRamayya) - asiddhavat::run_for_ni(p); + for_angas(p, |p, i| { + asiddhavat::run_before_ni_at_index(p, i); + }); // Must run after guna. (cayyAt) // Must run after ac-sandhi of dhatu. (cayyAt) // Must run after it-Agama has been added. - asiddhavat::try_ni_adesha(p); + for_angas(p, |p, i| { + asiddhavat::try_ni_adesha_at_index(p, i); + }); // Must apply again after guna for aBUv + t -> aBUt. ac_sandhi::try_lopo_vyor_vali(p); - for i in 0..p.terms().len() { + for_angas(p, |p, i| { try_change_anga_before_y(p, i); - } + }); // Must precede ft-AdeSa (f -> ir) try_change_anga_before_an(p); // Substitutions for `f` and `F` - for index in 0..p.terms().len() { - try_dhatu_rt_adesha(p, index); - } + for_angas(p, |p, i| { + try_dhatu_rt_adesha(p, i); + }); - for i in 0..p.terms().len() { + for_angas(p, |p, i| { asiddhavat::run_after_guna(p, i); - } + }); // krti tuk-Agama can occur only after guna. try_add_piti_krti_tuk(p); @@ -1392,15 +1418,6 @@ pub fn run_after_dvitva(p: &mut Prakriya) -> Option<()> { asiddhavat::run_after_dvitva(p, i); } - // TODO: move this rule to a better place. - { - let i = p.terms().len() - 1; - let last = p.terms().last()?; - if i > 0 && p.has(i - 1, |t| t.has_antya('A')) && last.has_u("Ral") { - op::adesha("7.1.34", p, i, "O"); - } - } - // Must come before asiddhavat rule 6.4.78 (e.g. "iyarti", ekahalmadhya) abhyasasya::run(p); diff --git a/vidyut-prakriya/src/angasya/abhyasasya.rs b/vidyut-prakriya/src/angasya/abhyasasya.rs index 89abae0..cb96e69 100644 --- a/vidyut-prakriya/src/angasya/abhyasasya.rs +++ b/vidyut-prakriya/src/angasya/abhyasasya.rs @@ -8,13 +8,14 @@ Runs rules that modify the abhyāsa. use crate::args::Gana; use crate::core::operators as op; +use crate::core::term::TermString; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::{Prakriya, Rule}; use crate::dhatu_gana as gana; use crate::it_samjna; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; -use compact_str::CompactString; use lazy_static::lazy_static; lazy_static! { @@ -31,8 +32,8 @@ lazy_static! { } /// Simplifies the abhyasa per 7.4.60. -fn try_haladi(text: &str) -> CompactString { - let mut ret = CompactString::from(""); +fn try_haladi(text: &str) -> TermString { + let mut ret = TermString::from(""); for (i, c) in text.chars().enumerate() { if al::is_hal(c) { if i == 0 { @@ -47,8 +48,8 @@ fn try_haladi(text: &str) -> CompactString { } /// Simplifies the abhyasa per 7.4.61. -fn try_shar_purva(text: &str) -> CompactString { - let mut ret = CompactString::from(""); +fn try_shar_purva(text: &str) -> TermString { + let mut ret = TermString::from(""); for (i, c) in text.chars().enumerate() { if i == 0 { assert!(SHAR.contains(c)); @@ -88,7 +89,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.optional_run_at("7.4.54.v1", i, op::upadha("is")); + do_abhyasa_lopa = p.optional_run_at(Varttika("7.4.54.1"), i, op::upadha("is")); } else if dhatu.has_u_in(&["A\\px~", "jYapa~", "fDu~"]) { // Ipsati, jYIpsati, Irtsati let code = "7.4.55"; @@ -372,7 +373,7 @@ fn try_rules_for_slu(p: &mut Prakriya, i: usize) -> Option<()> { } else if dhatu.has_u_in(&["quBf\\Y", "mA\\N", "o~hA\\N"]) { // biBarti, mimIte, jihIte p.run_at("7.4.76", i, op::antya("i")); - } else if dhatu.has_u_in(&["f\\", "pf", "pF"]) && dhatu.has_gana(Gana::Juhotyadi) { + } else if dhatu.has_u_in(&["f\\", "pf\\", "pF"]) && dhatu.has_gana(Gana::Juhotyadi) { // iyarti, piparti (allowed by both `pf` and `pF`) p.run_at("7.4.77", i, op::antya("i")); } else if dhatu.has_u("gA\\") && dhatu.has_gana(Gana::Juhotyadi) { @@ -477,7 +478,7 @@ fn try_rules_for_yan(p: &mut Prakriya, i_abhyasa: usize) -> Option<()> { } else if dhatu.has_antya('f') { op::insert_agama_at("7.4.92", p, i_dhatu, "rIk"); } else { - op::insert_agama_at("7.4.90.v1", p, i_dhatu, "rIk"); + op::insert_agama_at(Varttika("7.4.90.1"), p, i_dhatu, "rIk"); } } } else if abhyasa.has_antya('a') { diff --git a/vidyut-prakriya/src/angasya/asiddhavat.rs b/vidyut-prakriya/src/angasya/asiddhavat.rs index 707b5d8..4ee754d 100644 --- a/vidyut-prakriya/src/angasya/asiddhavat.rs +++ b/vidyut-prakriya/src/angasya/asiddhavat.rs @@ -14,6 +14,7 @@ see the `angasya` module. use crate::ac_sandhi; use crate::args::{Artha, Gana, TaddhitaArtha}; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::{Prakriya, Rule, Tag as T, Term, TermView}; use crate::dhatu_gana as gana; use crate::it_samjna; @@ -406,7 +407,7 @@ fn try_et_adesha_and_abhyasa_lopa_for_lit(p: &mut Prakriya, i: usize) -> Option< if dhatu.has_text("daB") && dhatu.has_u("danBu~") { // varttika stated before 6.4.121, so Tal is excluded. if !thali_seti { - p.run("6.4.120.v1", op_et_abhyasa_lopa); + p.run(Varttika("6.4.120.1"), op_et_abhyasa_lopa); } } else if (dhatu.has_u("tF") && dhatu.has_text("tar")) || dhatu.has_text_in(&["Pal", "Baj", "trap"]) @@ -414,7 +415,7 @@ fn try_et_adesha_and_abhyasa_lopa_for_lit(p: &mut Prakriya, i: usize) -> Option< // teratuH, PelatuH, BejatuH, trepatuH p.run("6.4.122", op_et_abhyasa_lopa); } else if dhatu.has_text("SraT") && dhatu.has_u("SranTa~") { - p.run("6.4.122.v1", op_et_abhyasa_lopa); + p.run(Varttika("6.4.122.1"), op_et_abhyasa_lopa); } else if dhatu.has_text("graT") { // TODO: attested, but can't find the rule for it. p.run("???", op_et_abhyasa_lopa); @@ -461,9 +462,10 @@ 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 i_n = p.find_next_where(i, |t| !t.is_lupta())?; let n = p.pratyaya(i_n)?; - if !n.has_tag(T::Ardhadhatuka) { + if !n.last().is_ardhadhatuka() || n.last().is_unadi() { return None; } @@ -503,6 +505,7 @@ fn try_ardhadhatuke(p: &mut Prakriya, i: usize) -> Option<()> { Some(()) } + fn try_upadha_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { let i_n = p.find_next_where(i, |t| !t.is_empty())?; @@ -537,17 +540,22 @@ fn try_upadha_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { } else if anga.has_text("ranj") { if n.first().is_ni_pratyaya() { // "rañjerṇau mṛgaramaṇa upasaṅkhyānaṃ kartavyam" - p.optional_run_at("6.4.24.v2", i, op::upadha("")); + p.optional_run_at(Varttika("6.4.24.2"), 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("")); + p.run_at(Varttika("6.4.24.3"), 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.optional_run_at("6.4.27", i, op::upadha("")); } - } else if anga.has_text_in(&["danS", "sanj", "svanj"]) && n.has_u("Sap") { - // daSati + } else if anga.has_text_in(&["danS", "sanj", "svanj"]) + && n.has_u("Sap") + && anga.has_gana(Gana::Bhvadi) + { + // daSati, ... + // + // But, daMSati when using daSi~ (curAdi). p.run_at("6.4.25", i, op::upadha("")); } else if anga.has_text("syand") && n.has_u("GaY") { p.optional_run("6.4.28", op::nipatana("syada")); @@ -560,11 +568,11 @@ fn try_upadha_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { 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")); + p.run_at(Varttika("6.4.34.1"), 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")); + p.run_at(Varttika("6.4.34.2"), i, op::upadha("i")); } Some(()) @@ -666,7 +674,7 @@ fn try_antya_nalopa(p: &mut Prakriya, i: usize) -> Option<()> { Some(()) } -fn try_add_a_agama(p: &mut Prakriya) -> Option<()> { +pub fn try_add_a_agama(p: &mut Prakriya) -> Option<()> { let _i = p.find_last(T::Dhatu)?; let tin = p.terms().last()?; @@ -695,10 +703,6 @@ fn try_add_a_agama(p: &mut Prakriya) -> Option<()> { } pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { - if i == 0 { - try_add_a_agama(p); - } - try_upadha_nalopa(p, i); try_antya_nalopa(p, i); try_ardhadhatuke(p, i); @@ -728,7 +732,7 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { } else if anga.has_u("daridrA") && n.has_tag(T::Ardhadhatuka) { if p.terms().last()?.has_lakshana("lu~N") { // Varttika. - if p.optional_run("6.4.114.v2", |_| {}) { + if p.optional_run(Varttika("6.4.114.2"), |_| {}) { return None; } } else if n.last().has_u_in(&["san", "Rvul", "lyuw"]) { @@ -739,7 +743,7 @@ pub fn run_before_guna(p: &mut Prakriya, i: usize) -> Option<()> { // Should replace just the last sound, but sak-Agama causes issues // here. // TODO: what is the correct prakriya here? - p.run_at("6.4.114.v1", i, op::text("daridr")); + p.run_at(Varttika("6.4.114.1"), i, op::text("daridr")); } let dhatu = p.get(i)?; @@ -824,7 +828,7 @@ fn run_for_final_i_or_u(p: &mut Prakriya, i_anga: usize) -> Option<()> { } else if anga.has_text("BU") && p.has_prev_non_empty(i_anga, |t| t.has_text_in(&["dfn", "kara", "punar"])) { - p.run_at("6.4.84.v1", i_anga, op::antya("v")); + p.run_at(Varttika("6.4.84.1"), i_anga, op::antya("v")); } let anga = p.get(i_anga)?; @@ -851,11 +855,8 @@ fn run_for_final_i_or_u(p: &mut Prakriya, i_anga: usize) -> Option<()> { } /// Runs asiddhavat rules that alter a Ri suffix. -pub fn try_ni_adesha(p: &mut Prakriya) -> Option<()> { - let i_ni = p.find_last_where(|t| t.is_ni_pratyaya())?; - if i_ni == 0 { - return None; - } +pub fn try_ni_adesha_at_index(p: &mut Prakriya, i_ni: usize) -> Option<()> { + let _ni = p.get_if(i_ni, |t| t.is_ni_pratyaya())?; let i_dhatu = p.find_prev_where(i_ni, |t| !t.is_empty())?; let n = p.pratyaya(i_ni + 1)?; @@ -884,21 +885,18 @@ pub fn try_ni_adesha(p: &mut Prakriya) -> Option<()> { } p.debug("No checks matched"); } - /* - * guna -> ac sandhi -> lopa (cayyAt) - */ Some(()) } /// Runs asiddhavat rules that alter a Ri suffix. -pub fn run_for_ni(p: &mut Prakriya) -> Option<()> { - let i_ni = p.find_last_where(|t| t.is_ni_pratyaya())?; - if i_ni == 0 { +pub fn run_before_ni_at_index(p: &mut Prakriya, i_ni: usize) -> Option<()> { + if !p.has(i_ni, |t| t.is_ni_pratyaya()) { return None; } - let i_dhatu = i_ni - 1; + // Find the mula dhatu. Avoid checking for `pratyaya` so we keep nAmadhAtus. + let i_dhatu = p.find_prev_where(i_ni, |t| t.is_dhatu() && !t.is_empty())?; let n = p.pratyaya(i_ni + 1)?; let dhatu = p.get(i_dhatu)?; let ni = p.get(i_ni)?; @@ -917,13 +915,32 @@ pub fn run_for_ni(p: &mut Prakriya) -> Option<()> { } else if n.has_u_in(&["isi~", "mani~n", "zwran", "kvi~p"]) { p.run_at("6.4.97", i_dhatu, op::upadha_hrasva); } - } 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.optional_run("6.4.93", |_| {}); - } - if run { - p.run_at("6.4.92", i_dhatu, op::upadha_hrasva); + } else if dhatu.has_tag(T::mit) { + // mittva, which shortens the dhatu's vowel. + // + // These rules specify "upadha," but a few dhatus don't fit this category. To support + // them, replace the last vowel instead. + let last_vowel = dhatu.last_vowel()?; + let is_cin_namuloh = n.has_u_in(&["ciR", "Ramu~l"]); + if dhatu.has_u("kraTa~") && !is_cin_namuloh { + // krATayati, by nipAtana from 2.3.53. + // + // But, we have akraTi/akrATi for ciR-Ramul. + p.step(Rule::Kaumudi("2353")); + } else { + p.run_at("6.4.92", i_dhatu, |t| { + let sub = al::to_hrasva(last_vowel).expect("is vowel"); + t.set_last_vowel(&sub.to_string()); + }); + + let dhatu = p.get(i_dhatu)?; + let last_vowel = dhatu.last_vowel()?; + if is_cin_namuloh { + p.optional_run_at("6.4.93", i_dhatu, |t| { + let sub = al::to_dirgha(last_vowel).expect("is vowel"); + t.set_last_vowel(&sub.to_string()); + }); + } } } } @@ -967,12 +984,34 @@ pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { "pra", "sTa", "sPa", "var", "baMh", "gar", "varz", "trap", "drAG", "vfnd", ]; - let bha = p.get_if(i, |t| t.has_tag(T::Bha))?; + let bha = p.get(i)?; + let i_next = p.find_next_where(i, |t| !t.is_empty())?; + let next = p.get(i_next)?; + + if !(bha.has_tag(T::Bha) || (bha.is_pratipadika() && next.has_u("Ric"))) { + // The second case refers to e.g. "pawu + Ric -> pawayati" + return None; + } + + let mut ishtavat = false; + if next.has_u("Ric") { + // HACK to avoid running thes rules. The proper fix is to run this function once. + if bha.has_tag(T::FlagPratipadikaTiLopa) { + return None; + } + + p.run_at(Varttika("6.4.155.1"), i, |t| { + t.add_tag(T::FlagPratipadikaTiLopa) + }); + ishtavat = true; + } + + let bha = p.get(i)?; let bha_prati = p.nyapu_pratipadika(i)?; - let next = p.get(i + 1)?; + let next = p.get(i_next)?; let taddhita = next.is_taddhita(); - if next.has_u_in(&["izWan", "imani~c", "Iyasu~n"]) { + if next.has_u_in(&["izWan", "imani~c", "Iyasu~n"]) || ishtavat { if bha.has_text_in(&["sTUla", "dUra", "yuvan", "hrasva", "kzipra", "kzudra"]) { // sTavizWa, ... p.run_at("6.4.156", i, |t| { @@ -1038,6 +1077,7 @@ pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { } p.run_at("6.4.138", i_end, |t| t.set_adi("")); } else if bha.has_antya('n') { + let mut block_lopa = false; if taddhita { let n = bha.len(); let ani = next.has_u("aR"); @@ -1059,7 +1099,7 @@ pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { "sukarasadman", "suparvan", ]) { - p.run_at("6.4.144.v1", i, op::ti("")); + p.run_at(Varttika("6.4.144.1"), i, op::ti("")); } else if ani && bha.ends_with("in") { let n = bha.len(); if bha.has_text_in(&["gATin", "vidaTin", "keSin", "gaRin", "paRin"]) { @@ -1074,35 +1114,42 @@ pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { } } else if ani && bha.ends_with("an") { p.step("6.4.167"); + block_lopa = true; } else if bha.ends_with("an") && next.has_adi('y') && !p.has_artha(Artha::Taddhita(TaddhitaArtha::TatraBhava)) { // TODO: expand conditions here. p.step("6.4.168"); + block_lopa = true; } else if bha.has_text_in(&["Atman", "aDvan"]) && next.has_u("Ka") { p.step("6.4.169"); - } else if bha.has_text("ahan") { + block_lopa = true; + } else if bha.has_u("ahan") { if next.has_u_in(&["wac", "KA"]) { p.run_at("6.4.145", i, op::ti("")); } } else { // This takes priority over 6.4.134 below. p.run_at("6.4.144", i, op::ti("")); + block_lopa = true; } - } else if bha.ends_with("an") { - let mut blocked = false; + } + + let bha = p.get(i)?; + let next = p.get(i + 1)?; + if bha.ends_with("an") && !block_lopa { let n = bha.len(); if n >= 4 && (bha.ends_with("man") || bha.ends_with("van")) && HAL.contains(bha.get_at(n - 4)?) { p.step("6.4.137"); - blocked = true; + block_lopa = true; } else if next.has_u_in(&["Ni", "SI"]) { - blocked = p.optional_run("6.4.136", |_| {}); + block_lopa = p.optional_run("6.4.136", |_| {}); } - if !blocked { + if !block_lopa { p.run_at("6.4.134", i, op::upadha("")); } } @@ -1156,7 +1203,7 @@ pub fn try_bhasya_for_index(p: &mut Prakriya, i: usize) -> Option<()> { { if next.has_u("SI") { // Pale, ... - p.step("6.4.148.v1"); + p.step(Varttika("6.4.148.1")); } else if bha.has_text_in(&["sUrya", "tizya", "agastya", "matsya"]) { p.run_at("6.4.149", i, |t| { t.set_antya(""); diff --git a/vidyut-prakriya/src/angasya/guna_vrddhi.rs b/vidyut-prakriya/src/angasya/guna_vrddhi.rs index 4a1685f..4c2188f 100644 --- a/vidyut-prakriya/src/angasya/guna_vrddhi.rs +++ b/vidyut-prakriya/src/angasya/guna_vrddhi.rs @@ -1,8 +1,7 @@ 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::core::Rule::Varttika; +use crate::core::{Code, Prakriya, Rule, Tag as T, Term, TermView}; use crate::sounds as al; use crate::sounds::{s, Set}; use lazy_static::lazy_static; @@ -247,7 +246,7 @@ fn try_nnit_vrddhi(p: &mut Prakriya, i_anga: usize, i_n: usize) -> Option<()> { } else if anga.has_upadha('a') { if anga.has_u_in(&["kamu~\\", "wuvama~"]) { // akAmi, avAmi - p.step("7.3.34.v1") + p.step(Varttika("7.3.34.1")) } // pAcayati @@ -268,6 +267,9 @@ fn try_vrddhi_adesha(p: &mut Prakriya, i_anga: usize, i_n: usize) -> Option<()> let mut gp = GunaVrddhiPrakriya::new(p, i_anga, i_n); gp.check_guna_vrddhi_blocks(); gp.try_run("7.2.114", |t| t.try_upadha_vrddhi()); + } else if anga.has_text("mfj") && n.last().is_knit() && n.has_adi(&*AC) && !n.last().is_krt() { + // mfjanti, mArjanti, ... + p.optional_run_at(Rule::Kaumudi("2473"), i_anga, |t| t.try_upadha_vrddhi()); } else if n.first().is_taddhita() { try_taddhita_vrddhi(p, i_anga, i_n); } else { @@ -445,6 +447,17 @@ fn run_for_index(p: &mut Prakriya, i_anga: usize) -> Option<()> { let anga = p.get(i_anga)?; let n = p.get(i_n)?; + if anga.is_dhatu() + && anga.has_gana(Gana::Tanadi) + && anga.has_u_in(&["kziRu~^", "fRu~^", "tfRu~^", "GfRu~^"]) + && n.has_u("u") + { + // kziRoti, kzeRoti, ... + p.optional_add_tag_at(Rule::Kaumudi("2547"), i_anga, T::FlagGunaApavada); + } + + let anga = p.get(i_anga)?; + let n = p.get(i_n)?; if anga.has_u("jAgf") && !n.has_u_in(&["kvin", "ciR", "Ral"]) && !p.pratyaya(i_n)?.has_tag(T::Nit) @@ -471,7 +484,9 @@ fn run_for_index(p: &mut Prakriya, i_anga: usize) -> Option<()> { pub fn run(p: &mut Prakriya) -> Option<()> { for i in 0..p.terms().len() { - if p.has(i, |t| t.is_anga()) { + if p.has(i, |t| { + t.is_anga() && !t.has_tag_in(&[T::FlagAntyaAcSandhi, T::FlagPratipadikaTiLopa]) + }) { run_for_index(p, i); } } diff --git a/vidyut-prakriya/src/angasya/subanta.rs b/vidyut-prakriya/src/angasya/subanta.rs index 8ff0a19..728aed6 100644 --- a/vidyut-prakriya/src/angasya/subanta.rs +++ b/vidyut-prakriya/src/angasya/subanta.rs @@ -9,6 +9,7 @@ favor of more generic modules like `angasya.rs`. */ use crate::angasya::asiddhavat; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::{Prakriya, Rule, Tag as T, Term}; use crate::it_samjna; use crate::samjna; @@ -258,7 +259,7 @@ fn try_sup_adesha(p: &mut Prakriya, i_anga: usize, i_sup: usize) -> Option<()> { // asmaByam, yuzmaByam op::adesha("7.1.30", p, i_sup, "Byam"); } - } else if sup.all(&[T::V5, T::Ekavacana]) { + } else if sup.last().has_all_tags(&[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") { @@ -287,7 +288,7 @@ fn try_napumsaka_su_am_adesha(p: &mut Prakriya, i_anga: usize) -> Option<()> { { if anga.has_text("ekatara") { // ekataram - p.step("7.1.26.v1"); + p.step(Varttika("7.1.26.1")); } else { // anyat op::adesha("7.1.25", p, i_sup, "adq"); diff --git a/vidyut-prakriya/src/ardhadhatuka.rs b/vidyut-prakriya/src/ardhadhatuka.rs index d379737..5c54260 100644 --- a/vidyut-prakriya/src/ardhadhatuka.rs +++ b/vidyut-prakriya/src/ardhadhatuka.rs @@ -30,7 +30,7 @@ fn will_cause_guna(n: &TermView) -> bool { let is_apit = !n.has_tag(T::pit); !( // Parasmaipada Ashir-liN will use yAsuT-Agama, which is kit. - (n.has_lakshana("li~N") && n.all(&[T::Ardhadhatuka, T::Parasmaipada])) + (n.has_lakshana("li~N") && n.last().has_all_tags(&[T::Ardhadhatuka, T::Parasmaipada])) // sArvadhAtukam apit will be Nit. || (n.has_tag(T::Sarvadhatuka) && is_apit) // apit liT when not after samyoga will be kit. @@ -82,7 +82,7 @@ pub fn dhatu_adesha_before_pada(p: &mut Prakriya, la: Lakara) { } if use_khya { // AkSAtA, AkSAtum, AkSAtavya, ... - let ksha = p.optionally(Varttika("2.4.54", "1"), |rule, p| { + let ksha = p.optionally(Varttika("2.4.54.1"), |rule, p| { op::upadesha_no_it(p, i, "kSAY"); // Remove tags set by `ca\kzi~\N` p.set(i, |t| { @@ -151,7 +151,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt } } } else if dhatu.has_u_in(&["i\\R", "i\\k"]) { - let code_invat = "2.4.45.v1"; + let code_invat = Varttika("2.4.45.1"); let is_ik = dhatu.has_u("i\\k"); let n = p.pratyaya(j)?; @@ -232,7 +232,7 @@ fn try_dhatu_adesha_before_vikarana(p: &mut Prakriya, la: Option) -> Opt 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~") { - run = !p.optionally("2.4.56.v2", |rule, p| p.step(rule)); + run = !p.optionally(Varttika("2.4.56.2"), |rule, p| p.step(rule)); } if run { // aniT-tva comes from anudAtta in upadesha. diff --git a/vidyut-prakriya/src/args/dhatu.rs b/vidyut-prakriya/src/args/dhatu.rs index 43f0312..411c5fa 100644 --- a/vidyut-prakriya/src/args/dhatu.rs +++ b/vidyut-prakriya/src/args/dhatu.rs @@ -23,7 +23,7 @@ pub enum Gana { Svadi, /// The sixth gaṇa, whose first dhatu is `tud`. Tudadi, - /// The seventh gaṇa, whose first dhatu is `rudh`. + /// The seventh gaṇa, whose first dhatu is `ruD`. Rudhadi, /// The eighth gaṇa, whose first dhatu is `tan`. Tanadi, @@ -31,6 +31,8 @@ pub enum Gana { Kryadi, /// The tenth gaṇa, whose first dhatu is `cur`. Curadi, + /// The kandvAdi gaṇa, whose first dhatu is `kaRqU`. + Kandvadi, } enum_boilerplate!(Gana, { @@ -44,6 +46,7 @@ enum_boilerplate!(Gana, { Tanadi => "8", Kryadi => "9", Curadi => "10", + Kandvadi => "kandu", }); /// Defines an antargana. @@ -66,6 +69,9 @@ enum_boilerplate!(Gana, { /// or requiring callers to follow our specific conventions.) #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum Antargana { + /// Antargana of *bhU* gana. A dhatu in this antargana uses a shortened vowel when followed by + /// Ric-pratyaya. + Ghatadi, /// Antargana of *tud* gana. Pratyayas that follow dhatus in kut-Adi will generally be marked /// Nit per 1.2.1. Required because of duplicates like `juqa~`. Kutadi, @@ -73,7 +79,7 @@ pub enum Antargana { /// optionaly uses Ric-pratyaya when taking an object. Required because of duplicates like /// `tuji~`. Asvadiya, - /// Antargana of *cur* gana ending with `Dfza~`. A dhatu in this antargana optionaly uses + /// Antargana of *cur* gana ending with `Dfza~`. A dhatu in this antargana optionally uses /// Ric-pratyaya. Required because of duplicates like `SraTa~`. Adhrshiya, /// Antargana of *cur* gana ending with `kusma~`. A dhatu in this antargana is always @@ -82,6 +88,7 @@ pub enum Antargana { } enum_boilerplate!(Antargana, { + Ghatadi => "GawAdi", Kutadi => "kuwAdi", Akusmiya => "AkusmIya", Asvadiya => "AsvadIya", diff --git a/vidyut-prakriya/src/args/krt.rs b/vidyut-prakriya/src/args/krt.rs index a344afb..7af6fa2 100644 --- a/vidyut-prakriya/src/args/krt.rs +++ b/vidyut-prakriya/src/args/krt.rs @@ -17,6 +17,8 @@ use wasm_bindgen::prelude::wasm_bindgen; pub enum BaseKrt { /// -a a, + /// -a, + aN, /// -a ac, /// -a @@ -221,6 +223,7 @@ pub enum BaseKrt { enum_boilerplate!(BaseKrt, { a => "a", + aN => "aN", ac => "ac", aR => "aR", atfn => "atf~n", diff --git a/vidyut-prakriya/src/args/taddhita.rs b/vidyut-prakriya/src/args/taddhita.rs index 1f82026..31f52dc 100644 --- a/vidyut-prakriya/src/args/taddhita.rs +++ b/vidyut-prakriya/src/args/taddhita.rs @@ -58,6 +58,8 @@ pub enum Taddhita { izWan, /// -Ika, Ikak, + /// -Ika, + Ikan, /// -Iyas Iyasun, /// -eRya @@ -380,6 +382,7 @@ enum_boilerplate!(Taddhita, { ilac => "ilac", izWan => "izWan", Ikak => "Ikak", + Ikan => "Ikan", Iyasun => "Iyasu~n", eRya => "eRya", Erak => "Erak", @@ -611,7 +614,7 @@ pub enum TaddhitaArtha { Unchati, /// What is protected. (4.4.33) TadRakshati, - /// Who does this. ($.4.34) + /// Who does this. (4.4.34) Karoti, /// What one kills. (4.4.35) Hanti, @@ -683,6 +686,8 @@ pub enum TaddhitaArtha { TadAsyaTadAsminSyat, /// What is bought with this. (5.1.37) TenaKritam, + /// For the sake of this, when the meaning is a relation or appearance. (5.1.38) + TasyaNimittamSamyogotpattau, /// Sown with this. (5.1.45) TasyaVapa, /// In which this is an interest, rent, profit, tax, or bribe. (5.1.47) @@ -691,6 +696,8 @@ pub enum TaddhitaArtha { TadDharatiVahatiAvahati, /// What is capable of this, or holds this, or cooks this. (5.152) SambhavatiAharatiPacati, + /// The measure of this. (5.1.57) + TadAsyaParimanam, /// One deserves this. (5.1.63) TadArhati, /// One performs this. (5.1.72) @@ -701,6 +708,14 @@ pub enum TaddhitaArtha { Gacchati, /// Who deserves approach (5.1.74 vArttika) AbhigamanamArhati, + /// What is conveyed by that way. (5.1.77) + Ahrtam, + /// Completed by this time. (5.1.79) + TenaNirvrttam, + /// For which time one instructs, is paid, existed, or will exist. (5.1.80) + TamAdhisteBhrtoBhutoBhavi, + /// Age. (5.1.81) + Vayasi, /// The existence of which. (5.1.119) TasyaBhava, /// A place of growing, when that place is a field. (5.2.1) diff --git a/vidyut-prakriya/src/args/unadi.rs b/vidyut-prakriya/src/args/unadi.rs index 85e53e0..854bbfb 100644 --- a/vidyut-prakriya/src/args/unadi.rs +++ b/vidyut-prakriya/src/args/unadi.rs @@ -35,8 +35,10 @@ pub enum Unadi { aRqan, /// -ata atac, - /// -ati + /// -at ati, + /// -ati + ati_, /// -atra atran, /// -atri @@ -443,7 +445,7 @@ pub enum Unadi { qaw, /// -qati qati, - /// -qavatu + /// -avat qavatu, /// -qimi qimi, @@ -457,7 +459,7 @@ pub enum Unadi { qU, /// -qE qE, - /// -qEsi + /// -Es qEsi, /// -qo qo, @@ -645,6 +647,7 @@ enum_boilerplate!(Unadi, { aRqan => "aRqan", atac => "atac", ati => "ati~", + ati_ => "ati", atran => "atran", atrin => "atrin", aTa => "aTa", @@ -855,7 +858,7 @@ enum_boilerplate!(Unadi, { qumsun => "qumsun", qU => "qU", qE => "qE", - qEsi => "qEsi", + qEsi => "qEsi~", qo => "qo", qosi => "qosi", qO => "qO", diff --git a/vidyut-prakriya/src/ashtadhyayi.rs b/vidyut-prakriya/src/ashtadhyayi.rs index d01d768..7cb14c4 100644 --- a/vidyut-prakriya/src/ashtadhyayi.rs +++ b/vidyut-prakriya/src/ashtadhyayi.rs @@ -86,19 +86,21 @@ fn prepare_dhatu(p: &mut Prakriya, dhatu: &Dhatu, is_ardhadhatuka: bool) -> Resu // Defer tripadi until we add other pratyayas. } - for s in dhatu.sanadi() { - sanadi::try_add_optional(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)?; - // Defer tripadi until we add other pratyayas. + if let Dhatu::Mula(_) = dhatu { + for s in dhatu.sanadi() { + // HACK: reset padas for next sanadi. + p.remove_tag(Tag::Parasmaipada); + p.remove_tag(Tag::Atmanepada); + + sanadi::try_add_optional(p, *s)?; + samjna::run(p); + atmanepada::run(p); + run_main_rules(p, None, false)?; + // Defer tripadi until we add other pratyayas. + } } - if !dhatu.sanadi().is_empty() { - p.debug("~~~~~~~~~~~~~~ completed dhatu ~~~~~~~~~~~~~~~~~~") - } + p.debug("~~~~~~~~~~~~~~ completed dhatu ~~~~~~~~~~~~~~~~~~"); Ok(()) } @@ -197,14 +199,17 @@ fn prepare_pratipadika(p: &mut Prakriya, pratipadika: &Pratipadika) -> Result<() fn prepare_taddhitanta(p: &mut Prakriya, args: &Taddhitanta) -> Result<()> { let taddhita = args.taddhita(); + prepare_pratipadika(p, args.pratipadika())?; + samjna::run(p); + // If defined, set the meaning condition that this prakriya must follow. + // + // Set `artha` *after* `prepare_pratipadika` to avoid clobbering `artha` when dealing with + // nested taddhitantas. if let Some(artha) = args.artha() { p.set_artha(Artha::Taddhita(artha)); } - prepare_pratipadika(p, args.pratipadika())?; - samjna::run(p); - let added = taddhita::run(p, taddhita); if !added { if cfg!(debug_assertions) { @@ -312,6 +317,8 @@ fn run_main_rules(p: &mut Prakriya, lakara: Option, is_ardhadhatuka: boo // Must run before it-Agama. angasya::try_cinvat_for_bhave_and_karmani_prayoga(p); + // Must run before it_agama rules since it affects how those rules are applied. + atidesha::run_before_it_agama(p); // Depends on jha_adesha since it conditions on the first sound. it_agama::run_before_attva(p); // Should come before atidesha rules for ju[hve --> hU]zati (san is kit). diff --git a/vidyut-prakriya/src/atidesha.rs b/vidyut-prakriya/src/atidesha.rs index 60f056a..e0ec7ba 100644 --- a/vidyut-prakriya/src/atidesha.rs +++ b/vidyut-prakriya/src/atidesha.rs @@ -5,8 +5,9 @@ atidesha (1.2.1 - 1.2.17) use crate::args::Antargana; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::Tag as T; -use crate::core::{Code, Prakriya}; +use crate::core::{Prakriya, Rule}; use crate::sounds::{s, Set}; use lazy_static::lazy_static; @@ -30,40 +31,40 @@ impl<'a> AtideshaPrakriya<'a> { AtideshaPrakriya { p, added: false } } - fn optional(&mut self, rule: Code, func: impl Fn(&mut Prakriya)) { + fn optional(&mut self, rule: impl Into, func: impl Fn(&mut Prakriya)) { self.added = self.p.optional_run(rule, func); } - fn optional_block(&mut self, rule: Code) { + fn optional_block(&mut self, rule: impl Into) { self.added = self.p.optional_run(rule, |_| {}); } - fn add_nit(&mut self, rule: Code, i: usize) { + fn add_nit(&mut self, rule: impl Into, i: usize) { self.p.add_tag_at(rule, i, T::Nit); self.added = true; } - fn optional_add_nit(&mut self, rule: Code, i: usize) { + fn optional_add_nit(&mut self, rule: impl Into, i: usize) { self.added = self.p.optional_run_at(rule, i, |t| t.add_tag(T::Nit)); } - fn add_kit(&mut self, rule: Code, i: usize) { + fn add_kit(&mut self, rule: impl Into, i: usize) { self.p.add_tag_at(rule, i, T::kit); self.added = true; } - fn optional_add_kit(&mut self, rule: Code, i: usize) { + fn optional_add_kit(&mut self, rule: impl Into, i: usize) { 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) { + fn remove_kit(&mut self, rule: impl Into, i: usize) { self.p.run_at(rule, i, |t| t.remove_tag(T::kit)); self.added = true; } - fn optional_remove_kit(&mut self, rule: Code, i: usize) { + fn optional_remove_kit(&mut self, rule: impl Into, i: usize) { self.added = self.p.optional_run_at(rule, i, |t| t.remove_tag(T::kit)); } } @@ -89,7 +90,7 @@ fn try_add_nit(p: &mut Prakriya, i: usize) -> Option<()> { { // vyaceḥ kuṭāditvamanasīti tu neha pravartate, anasīti paryudāsena kṛnmātraviṣayatvāt // -- SK 655 - ap.add_nit("1.2.1.v1", i_n); + ap.add_nit(Varttika("1.2.1.1"), i_n); } else if cur.has_u_in(&["o~vijI~\\", "o~vijI~"]) && iti { // Just for these `vij` dhatus, according to the Kashika. ap.add_nit("1.2.2", i_n); @@ -113,19 +114,7 @@ fn try_add_kit_for_various_pratyayas(p: &mut Prakriya, i: usize) -> Option } let i_n = n.end(); - - let apit = !n.has_tag(T::pit); - let n_is_lit = n.has_lakshana("li~w"); - - if !cur.is_samyoganta() && n_is_lit && !n.has_tag(T::pit) { - wrap.add_kit("1.2.5", i_n); - } else if cur.has_text_in(&["BU", "inD"]) && n_is_lit && apit { - // baBUva - wrap.add_kit("1.2.6", i_n); - } else if n_is_lit && cur.has_text_in(&["SranT", "granT", "danB", "svanj"]) && apit { - // 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"]) + if cur.has_text_in(&["mfq", "mfd", "guD", "kuz", "kliS", "vad", "vas"]) && n.last().has_u("ktvA") { // mfqitvA, mfditvA, ... @@ -253,6 +242,38 @@ fn try_remove_kit_for_set_pratyaya(p: &mut Prakriya, i: usize) -> Option<()> { Some(()) } +fn run_before_it_agama_at_index(p: &mut Prakriya, i: usize) -> Option<()> { + let mut ap = AtideshaPrakriya::new(p); + + let cur = ap.p.get(i)?; + let n = ap.p.pratyaya(i + 1)?; + if cur.is_agama() { + return None; + } + + let i_n = n.end(); + + let apit = !n.has_tag(T::pit); + let n_is_lit = n.has_lakshana("li~w"); + + if !cur.is_samyoganta() && n_is_lit && !n.has_tag(T::pit) { + ap.add_kit("1.2.5", i_n); + } else if cur.has_text_in(&["BU", "inD"]) && n_is_lit && apit { + // baBUva + ap.add_kit("1.2.6", i_n); + } else if n_is_lit && cur.has_text_in(&["SranT", "granT", "danB", "svanj"]) { + if apit { + // Optional per Siddhanta-kaumudi. + ap.optional_add_kit(Varttika("1.2.6.1"), i_n); + } + // TODO: sudhAkara in SK 2559 describes an option for SaSrATa, etc. but the derivation + // seems hazy, e.g. how do we do vrddhi with kit? Is it that "ata upadhAyAH" can't be + // blocked by knit? + } + + Some(()) +} + fn run_before_attva_at_index(p: &mut Prakriya, i: usize) -> Option<()> { try_add_nit(p, i); let added_1 = try_add_kit_for_various_pratyayas(p, i).unwrap_or(false); @@ -265,6 +286,13 @@ fn run_before_attva_at_index(p: &mut Prakriya, i: usize) -> Option<()> { Some(()) } +/// Runs atidesha rules that must apply before it-agama. +pub fn run_before_it_agama(p: &mut Prakriya) { + for i in 0..p.terms().len() { + run_before_it_agama_at_index(p, i); + } +} + /// Runs most atidesha rules. pub fn run_before_attva(p: &mut Prakriya) { for i in 0..p.terms().len() { diff --git a/vidyut-prakriya/src/atmanepada.rs b/vidyut-prakriya/src/atmanepada.rs index afa32c5..eb230ba 100644 --- a/vidyut-prakriya/src/atmanepada.rs +++ b/vidyut-prakriya/src/atmanepada.rs @@ -13,8 +13,9 @@ use crate::args::Gana; use crate::core::Rule::Kaumudi; +use crate::core::Rule::Varttika; use crate::core::Tag as T; -use crate::core::{Code, Prakriya, Rule}; +use crate::core::{Prakriya, Rule}; use crate::dhatu_gana::{DYUT_ADI, VRT_ADI}; const GAMY_RCCHI: &[(&str, Gana)] = &[ @@ -94,7 +95,7 @@ impl<'a> PadaPrakriya<'a> { } /// Marks this prakriya as AtmanepadI. - fn atma(&mut self, rule: Code) { + fn atma(&mut self, rule: impl Into) { self.p.run(rule, op_atmanepada); } @@ -104,12 +105,12 @@ impl<'a> PadaPrakriya<'a> { } /// Marks this prakriya as parasmaipadI. - fn para(&mut self, rule: Code) { + fn para(&mut self, rule: impl Into) { self.p.run(rule, op_parasmaipada); } /// Marks this prakriya as parasmaipadI. - fn optional_para(&mut self, rule: Code) { + fn optional_para(&mut self, rule: impl Into) { self.p.optional_run(rule, op_parasmaipada); } } @@ -122,12 +123,21 @@ pub fn run(p: &mut Prakriya) -> Option<()> { // Exclude "san" per 1.3.62. // TODO: handle this better. - let i = p.find_last_where(|t| t.is_dhatu() && !t.has_u("san"))?; + let i = p.find_last_where(|t| t.is_dhatu() && !t.has_u_in(&["san", "yak"]))?; let has_upasargas = p.find_prev_where(i, |t| t.is_upasarga()).is_some(); if p.is_bhave_or_karmani() { p.run("1.3.13", op_atmanepada); return None; + } else if p.has(i, |t| t.has_u("Ric")) + && i > 0 + && p.has(i - 1, |t| t.has_tag(T::Nit) && t.has_gana(Gana::Curadi)) + { + // Special exception for zmiN + Ric -- for the Nit to have scope, we must treat this dhatu as + // Atmanepada. + p.step(Kaumudi("2567")); + p.run("1.3.12", op_atmanepada); + return None; } let mut pp = PadaPrakriya::new(p, i); @@ -163,7 +173,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { } else if pp.is(&["sam", "ava", "pra", "vi"], &["zWA\\"]) { pp.atma("1.3.22"); } else if pp.is(&["AN"], &["zWA\\"]) { - pp.optional_atma("1.3.22.v1"); + pp.optional_atma(Varttika("1.3.22.1")); } else if pp.is(&[], &["zWA\\"]) { pp.optional_atma("1.3.23"); } else if pp.is(&["ud"], &["zWA\\"]) { @@ -178,19 +188,25 @@ pub fn run(p: &mut Prakriya) -> Option<()> { } else if pp.is_exactly(&["sam"], GAMY_RCCHI) { pp.optional_atma("1.3.29"); } else if pp.is(&["sam"], &["dfS"]) { - pp.optional_atma("1.3.29.v1"); + pp.optional_atma(Varttika("1.3.29.1")); } else if pp.is(&["ni", "sam", "upa", "vi"], &["hve\\Y"]) { pp.atma("1.3.30"); } else if has_upasargas && dhatu.has_u_in(&["asu~", "Uha~\\"]) { - let code = "1.3.30.v1"; + let code = Varttika("1.3.30.1"); if dhatu.has_u("asu~") { pp.optional_atma(code); } else { pp.optional_para(code); } } else if pp.is(&["AN"], &["hve\\Y"]) { + // Ahvayate pp.optional_atma("1.3.31"); - // 1.3.32 - 1.3.37 can be handled with 1.3.72. + } else if pp.is(&["aDi"], &["qukf\\Y"]) { + // aDikurute, aDikaroti + pp.optional_atma("1.3.33"); + } else if pp.is(&["vi"], &["qukf\\Y"]) { + // vikurute, vikaroti + pp.optional_atma("1.3.34"); } else if pp.is(&[], &["kramu~"]) { if pp.is(&["upa", "parA"], &["kramu~"]) { pp.optional_atma("1.3.39"); @@ -314,18 +330,47 @@ pub fn run(p: &mut Prakriya) -> Option<()> { } else if dhatu.has_tag_in(&[T::Yit, T::svaritet]) { // karoti, kurute pp.optional_atma("1.3.72"); - } else if pp - .p - .find_last_where(|t| t.is_pratyaya() && t.has_u("Ric")) - .is_some() - { - // corayati, corayate - pp.optional_atma("1.3.74"); + } else if i > 0 && dhatu.has_u("Ric") { + const BUDH_ADI: &[&str] = &[ + "bu\\Da~\\", + "yu\\Da~\\", + "Ra\\Sa~", + "janI~\\", + "i\\N", + "pru\\N", + "dru\\", + "sru\\", + ]; + + let default = "1.3.74"; + let mula = pp.p.get(i - 1)?; + // -3 since list is [upasarga, sup-luk, dhatu, nic]. + // let has_aa = i >= 3 && pp.p.has(i - 3, |t| t.has_u("AN")); + // let has_pari = i >= 3 && pp.p.has(i - 3, |t| t.has_u("pari")); + if mula.has_u_in(BUDH_ADI) { + // boDayati, ... + pp.para("1.3.86"); + /* + } else if (mula.has_u("pA\\") && mula.has_gana(Gana::Bhvadi)) + || mula.has_u("damu~") + || (has_aa && mula.has_u("yama~")) + || (has_aa && mula.has_u("yasu~")) + || (has_pari && mula.has_u("mu\\ha~")) + || mula.has_u_in(&["ruca~\\", "nftI~", "vada~", "va\\sa~"]) + { + // pAyayate, ... + pp.p.step("1.3.89"); + pp.atma(default); + */ + } else { + // corayati, corayate + pp.optional_atma(default); + } } // Otherwise, use parasmaipada by default. if pp.p.has_tag(T::Kartari) && !pp.p.has_tag(T::Atmanepada) { - // Bavati + // Bavati, ... pp.para("1.3.78"); } diff --git a/vidyut-prakriya/src/core/prakriya.rs b/vidyut-prakriya/src/core/prakriya.rs index 2e39a61..db60907 100644 --- a/vidyut-prakriya/src/core/prakriya.rs +++ b/vidyut-prakriya/src/core/prakriya.rs @@ -25,7 +25,7 @@ pub enum Rule { /// A varttika on the Ashtadhyayi. The first string is an adhyaya-pada-sutra string, e.g. /// "3.1.68",a nd the second string is an integer corresponding to the vArttika's position on /// the sutra, e.g. "2" for the second vArttika on some sUtra. - Varttika(&'static str, &'static str), + Varttika(&'static str), /// 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. The string here is a gana-sutra string, e.g. "1.1". @@ -48,7 +48,7 @@ impl Rule { pub fn code(&self) -> &'static str { match self { Self::Ashtadhyayi(x) => x, - Self::Varttika(x, _) => x, + Self::Varttika(x) => x, Self::Dhatupatha(x) => x, Self::Unadipatha(x) => x, Self::Linganushasana(x) => x, @@ -77,8 +77,7 @@ impl From<&'static str> for Rule { #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct Step { rule: Rule, - result: Vec, - active: Option, + result: Vec, } impl Step { @@ -88,14 +87,29 @@ impl Step { } /// The result of applying `rule`. - pub fn result(&self) -> &Vec { + pub fn result(&self) -> &Vec { &self.result } +} + +/// One of the terms in the derivation. +#[derive(Clone, Debug, Hash, Eq, PartialEq)] +pub struct StepTerm { + text: String, + // NOTE: keep `tags` private. + tags: EnumSet, + was_changed: bool, +} - /// Returns the index of the item in `result` that was modified, or `None` if the rule modified - /// either more than one term or no terms. - pub fn active(&self) -> Option { - self.active +impl StepTerm { + /// The current text of this term. + pub fn text(&self) -> &str { + &self.text + } + + /// Whether the term was changed in the current step. + pub fn was_changed(&self) -> bool { + self.was_changed } } @@ -662,7 +676,7 @@ impl Prakriya { ) -> bool { if let Some(term) = self.get_mut(index) { func(term); - self.step_at(rule.into(), index); + self.step(rule.into()); true } else { false @@ -741,26 +755,58 @@ impl Prakriya { /// 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 result = self.terms.iter().map(|t| t.text_with_svaras()).collect(); - self.history.push(Step { - rule: rule.into(), - result, - active: None, - }) + if !self.config.log_steps { + return; } - } - /// Adds `rule` and the current derivation state to the derivation history. - pub(crate) fn step_at(&mut self, rule: impl Into, index: usize) { - if self.config.log_steps { - let result = self.terms.iter().map(|t| t.text_with_svaras()).collect(); - self.history.push(Step { - rule: rule.into(), - result, - active: Some(index), + let mut result: Vec = self + .terms + .iter() + .map(|t| { + let mut tags = t.tags; + // HACK: remove a flag that is not added by any rule, to avoid spurious + // highlighting. + // TODO: move flags to their own field to avoid these and similar issues, and so + // that we might refactor `Tag` into a `Samjna` type in the future. + tags.remove(Tag::FlagIttva); + StepTerm { + text: t.text_with_svaras(), + tags, + was_changed: false, + } }) + .collect(); + + if let Some(prev) = self.history.last() { + let prev = prev.result(); + let had_insertion = prev.len() < result.len(); + let mut any_changed = false; + for i in 0..result.len() { + if let (Some(t_cur), Some(t_prev)) = (result.get_mut(i), prev.get(i)) { + let was_changed = t_prev.text != t_cur.text || t_prev.tags != t_cur.tags; + t_cur.was_changed = was_changed; + any_changed |= was_changed; + + if was_changed && had_insertion { + // Assume that when a term has been inserted, all other terms are the same. + // This assumption doesn't always hold, but it's good enough for now. + break; + } + } + } + if had_insertion && !any_changed { + // We inserted a new term, but all the terms we checked are still the same. So, the + // changed term must be at the end. + result.last_mut().expect("non-empty").was_changed = true; + } + } else { + result.iter_mut().for_each(|x| x.was_changed = true); } + + self.history.push(Step { + rule: rule.into(), + result, + }) } // Optional rules @@ -816,8 +862,11 @@ impl Prakriya { pub(crate) fn debug(&mut self, text: impl AsRef) { self.history.push(Step { rule: Rule::Ashtadhyayi(" "), - result: vec![text.as_ref().to_string()], - active: None, + result: vec![StepTerm { + text: text.as_ref().to_string(), + tags: EnumSet::new(), + was_changed: false, + }], }); } diff --git a/vidyut-prakriya/src/core/tag.rs b/vidyut-prakriya/src/core/tag.rs index ec0a8cf..ad13459 100644 --- a/vidyut-prakriya/src/core/tag.rs +++ b/vidyut-prakriya/src/core/tag.rs @@ -234,6 +234,8 @@ pub enum Tag { FlagTrjvat, + FlagPratipadikaTiLopa, + // Flags on the `Prakriya`. FlagNaAdeshadi, FlagSaAdeshadi, diff --git a/vidyut-prakriya/src/core/term.rs b/vidyut-prakriya/src/core/term.rs index b335a7b..25e3fb8 100644 --- a/vidyut-prakriya/src/core/term.rs +++ b/vidyut-prakriya/src/core/term.rs @@ -3,11 +3,34 @@ use crate::core::Tag; use crate::sounds; use crate::sounds::Pattern; use crate::sounds::{s, Set}; -use compact_str::CompactString; use enumset::EnumSet; use lazy_static::lazy_static; +// Abstracts our choice of String type so we can try other implementations. +// +// Setup: +// cargo build --release --example create_all_tinantas +// hyperfine "../target/release/examples/create_all_tinantas > /dev/null" +// +// With `CompactString`: +// Benchmark 1: ../target/release/examples/create_all_tinantas > /dev/null +// Time (mean ± σ): 97.769 s ± 0.608 s [User: 97.294 s, System: 0.288 s] +// Range (min … max): 96.984 s … 99.231 s 10 runs +// +// With `String`: +// Benchmark 1: ../target/release/examples/create_all_tinantas > /dev/null +// Time (mean ± σ): 86.631 s ± 0.831 s [User: 86.209 s, System: 0.257 s] +// Range (min … max): 85.141 s … 87.937 s 10 runs +// +// My guess is that the overhead of allocating `String` is lower than the overhead of checking +// bounds on `CompactString`. +// +// TODO: investigate whether other uses of `CompactString` in the crate can be migrated to +// `String`. Early indications are that doing so makes the program slower than just using +// `CompactString` everywhere. +pub(crate) type TermString = String; + lazy_static! { static ref AC: Set = s("ac"); } @@ -33,7 +56,7 @@ pub(crate) enum Svara { /// 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 +/// Its main field is `text`, a `TermString` 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` @@ -52,25 +75,25 @@ pub struct Term { /// /// This field is changed only when there is a full substitution, e.g. substitution of `ktvA` /// with `lyap`. - pub(crate) u: Option, + pub(crate) u: Option, /// The text of this term. This string contains sound changes such as guna, vrddhi, lopa, etc. - pub(crate) text: CompactString, + pub(crate) text: TermString, /// The svara that applies to this term. pub(crate) svara: Option, + /// Various metadata associated with this term. + pub(crate) tags: EnumSet, /// 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. /// /// For a complete example in English, see S. C. Vasu's commentary on rule 1.1.59, part (e). - sthanivat: CompactString, - /// Various metadata associated with this term. - tags: EnumSet, + sthanivat: TermString, /// If this term is a dhatu, the dhatu's gana. gana: Option, /// If this term is a dhatu, the dhatu's antargana. antargana: Option, /// All upadeshas that this term has had. This field is called `lakshanas` per rule 1.1.62 /// (*pratyayalopa pratyaylakshanam*). - lakshanas: Vec, + lakshanas: Vec, } impl Term { @@ -80,9 +103,9 @@ impl Term { /// Creates a new upadesha. pub fn make_upadesha(s: &str) -> Self { Term { - u: Some(CompactString::from(s)), - text: CompactString::from(s), - sthanivat: CompactString::from(s), + u: Some(TermString::from(s)), + text: TermString::from(s), + sthanivat: TermString::from(s), tags: EnumSet::new(), gana: None, antargana: None, @@ -95,8 +118,8 @@ impl Term { pub fn make_text(s: &str) -> Self { Term { u: None, - text: CompactString::from(s), - sthanivat: CompactString::from(s), + text: TermString::from(s), + sthanivat: TermString::from(s), tags: EnumSet::new(), gana: None, antargana: None, @@ -143,7 +166,7 @@ impl Term { ret } - pub fn sthanivat(&self) -> &CompactString { + pub fn sthanivat(&self) -> &TermString { &self.sthanivat } @@ -152,12 +175,12 @@ impl Term { self.text.chars().filter(|c| AC.contains(*c)).count() } - /// Wrapper over `CompactString::len`. + /// Wrapper over `TermString::len`. pub fn len(&self) -> usize { self.text.len() } - /// Wrapper over `CompactString::chars`. + /// Wrapper over `TermString::chars`. pub fn chars(&self) -> std::str::Chars<'_> { self.text.chars() } @@ -182,6 +205,10 @@ impl Term { self.text.chars().rev().nth(1) } + pub fn last_vowel(&self) -> Option { + self.chars().rev().filter(|c| sounds::is_ac(*c)).next() + } + /// Returns the sound at index `i` if it exists. pub fn get_at(&self, i: usize) -> Option { self.text.as_bytes().get(i).map(|x| *x as char) @@ -213,10 +240,7 @@ impl Term { } pub fn has_last_vowel(&self, pattern: impl Pattern) -> bool { - self.matches_sound_pattern( - self.chars().rev().filter(|c| sounds::is_ac(*c)).next(), - pattern, - ) + self.matches_sound_pattern(self.last_vowel(), pattern) } /// Returns whether the term has a sound at index `i` that matches the given pattern. @@ -664,6 +688,19 @@ impl Term { } } + pub fn set_last_vowel(&mut self, s: &str) { + let result = self + .text + .bytes() + .enumerate() + .rev() + .filter(|(_, c)| sounds::is_ac(*c as char)) + .next(); + if let Some((i, _)) = result { + self.set_at(i, s); + } + } + /// Replaces the character at index `i` with the given value. pub fn set_at(&mut self, i: usize, s: &str) { self.text.replace_range(i..=i, s); @@ -671,7 +708,7 @@ impl Term { /// Sets the term's upadesha to the given value. pub fn set_u(&mut self, s: &str) { - self.u = Some(CompactString::from(s)); + self.u = Some(TermString::from(s)); } /// Sets the term's text to the given value. @@ -726,7 +763,7 @@ impl Term { pub fn save_lakshana(&mut self) { if let Some(u) = &self.u { - self.lakshanas.push(CompactString::new(u)); + self.lakshanas.push(TermString::from(u)); } } diff --git a/vidyut-prakriya/src/core/term_view.rs b/vidyut-prakriya/src/core/term_view.rs index 2bfc216..6e6b94a 100644 --- a/vidyut-prakriya/src/core/term_view.rs +++ b/vidyut-prakriya/src/core/term_view.rs @@ -65,7 +65,6 @@ impl<'a> TermView<'a> { } /// Returns this view's text. - #[allow(unused)] pub fn text(&self) -> String { let mut ret = String::from(""); for t in self.slice() { @@ -145,25 +144,12 @@ impl<'a> TermView<'a> { 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.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() } @@ -229,10 +215,7 @@ impl<'a> TermView<'a> { } pub fn has_u_in(&self, us: &[&str]) -> bool { - match self.slice().first() { - Some(t) => t.has_u_in(us), - None => false, - } + self.last().has_u_in(us) } pub fn has_tag(&self, tag: Tag) -> bool { @@ -240,21 +223,11 @@ impl<'a> TermView<'a> { } pub fn has_lakshana(&self, s: &str) -> bool { - self.slice().iter().any(|t| t.has_lakshana(s)) + self.last().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 + self.last().has_lakshana_in(items) } pub fn has_tag_in(&self, tags: &[Tag]) -> bool { @@ -275,7 +248,7 @@ impl<'a> TermView<'a> { } pub fn is_knit(&self) -> bool { - self.has_tag_in(&[Tag::kit, Tag::Nit]) + self.last().has_tag_in(&[Tag::kit, Tag::Nit]) } } diff --git a/vidyut-prakriya/src/dhatu_gana.rs b/vidyut-prakriya/src/dhatu_gana.rs index 461a605..f5f535b 100644 --- a/vidyut-prakriya/src/dhatu_gana.rs +++ b/vidyut-prakriya/src/dhatu_gana.rs @@ -2,6 +2,9 @@ /// Dhatus that are `mit` per DP.01.0933. /// These dhatus will use a hrasva vowel per 6.4.92. +/// +/// Range: 1.0867 - 1.0932) +#[allow(unused)] pub const GHAT_ADI: &[&str] = &[ "Gawa~\\", "vyaTa~\\", diff --git a/vidyut-prakriya/src/dhatu_karya.rs b/vidyut-prakriya/src/dhatu_karya.rs index 1cfc6ef..5a71add 100644 --- a/vidyut-prakriya/src/dhatu_karya.rs +++ b/vidyut-prakriya/src/dhatu_karya.rs @@ -13,12 +13,20 @@ use crate::args::Antargana; use crate::args::Gana; use crate::core::errors::*; use crate::core::operators as op; +use crate::core::Rule::Kaumudi; +use crate::core::Rule::Varttika; 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::samjna; +use crate::sounds::{s, Set}; +use lazy_static::lazy_static; + +lazy_static! { + static ref HAL: Set = s("hal"); +} /// Adds the mula-dhatu to the prakriya. fn add_mula_dhatu(p: &mut Prakriya, dhatu: &Muladhatu) { @@ -37,6 +45,21 @@ fn add_samjnas(p: &mut Prakriya, i: usize) { }; } +fn hacky_unclear_has_samyoga_before_a(t: &Term) -> bool { + // TODO: this prinicple seems to apply widely but SK applies it narrowly. Not sure why. For + // now, restrict to the specific dhatus that SK mentions. + t.has_u_in(&["mUtra", "katra", "karta", "garva"]) + /* + let len = t.text.len(); + if len < 3 { + false + } else { + // katra, mUtra, ... + t.has_antya('a') && t.has_at(len - 2, &*HAL) && t.has_at(len - 3, &*HAL) + } + */ +} + /// Tries applying the gana sutras in the Dhatupatha. /// /// These sutras define various properties over collections of dhatus. @@ -49,24 +72,31 @@ fn try_run_gana_sutras(p: &mut Prakriya, i: usize) -> Option<()> { let is_divadi = dhatu.has_gana(Divadi); let is_curadi = dhatu.has_gana(Curadi); - let has_upasarga = p.find_prev_where(i, |t| t.is_upasarga()).is_some(); + let has_upasarga = p.has_prev_non_empty(i, |t| t.is_upasarga()); // Exceptions to the general mittva rules below. let mut is_mit_blocked = false; if is_bhvadi { if dhatu.has_text_in(&["kam", "am", "cam"]) { + // kAmayate, Amayati, cAmayati p.step(DP("01.0937")); is_mit_blocked = true; } else if dhatu.has_u("Samo~") { is_mit_blocked = p.optional_run(DP("01.0938"), |_| {}) - } else if dhatu.has_text("yam") && is_bhvadi { - 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"])) - { - p.step(DP("01.0940")); + } else if dhatu.has_u("yama~") && is_bhvadi && p.has_prev_non_empty(i, |t| t.has_u("AN")) { + // AyAmayati + // (include only "yama~ aparivezaRe") + p.step(DP("01.0939")); is_mit_blocked = true; + } else if dhatu.has_u("sKadi~\\r") { + if p.has_prev_non_empty(i, |t| t.has_u_in(&["ava", "pari"])) { + // avasKAdayati, parisKAdayati + p.step(DP("01.0940")); + is_mit_blocked = true; + } else if p.has_prev_non_empty(i, |t| t.has_u("apa")) { + // apasKAdayati, apasKadayati + is_mit_blocked = p.optional_run(Kaumudi("2353"), |_| {}); + } } } @@ -78,7 +108,7 @@ fn try_run_gana_sutras(p: &mut Prakriya, i: usize) -> Option<()> { p.optional_add_tag_at(DP("01.0935"), i, T::mit); } else if dhatu.has_text_in(&["glE", "snA", "van", "vam"]) && !has_upasarga { p.optional_add_tag_at(DP("01.0936"), i, T::mit); - } else if (dhatu.has_u_in(&["janI~\\", "jFz", "knasu~", "ra\\nja~^"]) && is_divadi) + } else if (is_divadi && dhatu.has_u_in(&["janI~\\", "jFz", "knasu~", "ra\\nja~^"])) || dhatu.ends_with("am") { if is_curadi { @@ -86,8 +116,21 @@ fn try_run_gana_sutras(p: &mut Prakriya, i: usize) -> Option<()> { } else { p.add_tag_at(DP("01.0934"), i, T::mit); } - } else if is_bhvadi && dhatu.has_u_in(gana::GHAT_ADI) { + } else if is_bhvadi && dhatu.has_antargana(Antargana::Ghatadi) { p.add_tag_at(DP("01.0933"), i, T::mit); + } else if is_bhvadi + && dhatu.has_u_in(&[ + "dala~", + "vala~\\", + "sKala~", + "raRa~", + "Dvana~", + "trapU~\\z", + "kzE\\", + ]) + { + // dalayati, valayati, ... + p.add_tag_at(DP("01.0944"), i, T::mit); } let dhatu = p.get(i)?; @@ -97,28 +140,64 @@ fn try_run_gana_sutras(p: &mut Prakriya, i: usize) -> Option<()> { ]) { // sUna, dUna, dIna, ... p.add_tag_at(DP("04.0162"), i, T::odit); + } else if dhatu.has_u("Sa\\ka~^") { + // SaktA, SakitA + p.optional_run_at(Kaumudi("2514"), i, |t| t.remove_tag(T::Anudatta)); + } + } else if dhatu.has_gana(Gana::Tudadi) { + if dhatu.has_u("vi\\dx~^") { + // vettA, veditA + p.optional_run_at(Kaumudi("2542"), i, |t| t.remove_tag(T::Anudatta)); + } + } else if dhatu.has_gana(Gana::Tanadi) { + if dhatu.has_u("vanu~\\") { + // vanute, vanoti + p.optional_run_at(Kaumudi("2547"), i, |t| t.remove_tag(T::anudattet)); } } else if is_curadi { if dhatu.has_u_in(gana::JNAP_ADI) { p.add_tag_at(DP("10.0493"), i, T::mit); } + // First decide Ric-pratyaya, since this affects the scope of AkusmIya, etc. let dhatu = p.get(i)?; - if dhatu.has_antargana(Antargana::Akusmiya) { - p.run(DP("10.0496"), |p| p.add_tag(T::Atmanepada)); - } else if dhatu.has_u_in(gana::AA_GARVIYA) { - p.run(DP("10.0497"), |p| p.add_tag(T::Atmanepada)); - } else if dhatu.has_antargana(Antargana::Adhrshiya) { - p.optional_run_at(DP("10.0498"), i, |t| t.add_tag(T::FlagNoNic)); + if dhatu.has_antargana(Antargana::Adhrshiya) { + p.optional_add_tag_at(DP("10.0498"), i, T::FlagNoNic); } else if dhatu.has_antargana(Antargana::Asvadiya) { - p.optional_run_at(DP("10.0499"), i, |t| t.add_tag(T::FlagNoNic)); - } - /* + p.optional_add_tag_at(DP("10.0499"), i, T::FlagNoNic); } else if dhatu.has_tag(T::idit) { // cintayati, cintati, ... - p.optional_run_at(Rule::Kaumudi("2564"), i, |t| t.add_tag(T::FlagNoNic)); + p.optional_add_tag_at(Kaumudi("2564"), i, T::FlagNoNic); + } else if dhatu.has_antya('F') { + // pArayati, parati, ... + p.optional_add_tag_at(Kaumudi("2565"), i, T::FlagNoNic); + } else if dhatu.has_tag_in(&[T::Yit, T::udit]) { + // cayayati, cayati, ... + p.optional_add_tag_at(Kaumudi("2570"), i, T::FlagNoNic); + } else if dhatu.has_u("Guzi~r") { + // Gozayati, Gozati, ... + p.optional_add_tag_at(Kaumudi("2571"), i, T::FlagNoNic); + } else if dhatu.has_tag(T::Idit) { + // pUrayati, pUrati, ... + p.optional_add_tag_at(Kaumudi("2572"), i, T::FlagNoNic); + } else if dhatu.has_u("pata") { + let va_nijanta = p.optional_add_tag_at(Kaumudi("2573.1"), i, T::FlagNoNic); + if !va_nijanta { + p.optional_run_at(Kaumudi("2573.2"), i, |t| t.set_antya("")); + } + } else if hacky_unclear_has_samyoga_before_a(dhatu) { + // katrayati, katrati, ... + p.optional_add_tag_at(Kaumudi("2573.3"), i, T::FlagNoNic); + } + + let dhatu = p.get(i)?; + if !dhatu.has_tag(T::FlagNoNic) { + if dhatu.has_antargana(Antargana::Akusmiya) { + p.run(DP("10.0496"), |p| p.add_tag(T::Atmanepada)); + } else if dhatu.has_u_in(gana::AA_GARVIYA) { + p.run(DP("10.0497"), |p| p.add_tag(T::Atmanepada)); + } } - */ } Some(()) @@ -129,10 +208,10 @@ fn try_satva_and_natva(p: &mut Prakriya, i: usize) -> Option<()> { if dhatu.has_adi('z') { if dhatu.has_text_in(&["zWiv", "zvazk"]) { // Varttika -- no change for zWiv or zvask - p.step("6.1.64.v1"); + p.step(Varttika("6.1.64.1")); } else if dhatu.has_prefix_in(&["zw", "zW", "zR", "zaR"]) { // Varttika -- also change the next sound - p.run_at("6.1.64.v2", i, |t| { + p.run_at(Varttika("6.1.64.2"), i, |t| { match &t.text[..2] { "zw" => t.text.replace_range(..2, "st"), "zW" => t.text.replace_range(..2, "sT"), @@ -160,7 +239,7 @@ fn try_satva_and_natva(p: &mut Prakriya, i: usize) -> Option<()> { t.set_adi("n"); }); } else if dhatu.has_u("DraRa~") { - p.run_at(Rule::Kaumudi("2318"), i, |t| { + p.run_at(Kaumudi("2318"), i, |t| { t.set_text("Dran"); }); } @@ -224,6 +303,10 @@ pub fn run(p: &mut Prakriya, dhatu: &Muladhatu) -> Result<()> { // Standard dhatus. it_samjna::run(p, i_dhatu)?; add_samjnas(p, i_dhatu); + + if p.has(i_dhatu, |t| t.is_empty()) { + return Err(Error::invalid_upadesha(dhatu.upadesha())); + } } try_satva_and_natva(p, i_dhatu); diff --git a/vidyut-prakriya/src/dhatupatha.rs b/vidyut-prakriya/src/dhatupatha.rs index 671da99..a5de060 100644 --- a/vidyut-prakriya/src/dhatupatha.rs +++ b/vidyut-prakriya/src/dhatupatha.rs @@ -184,21 +184,25 @@ impl IntoIterator for Dhatupatha { } fn maybe_find_antargana(gana: Gana, number: u16) -> Option { - if gana == Gana::Tudadi && (93..=137).contains(&number) { - // Check number explicitly because some roots are duplicated within tudAdi - // but outside this gana (e.g. juq). + if gana == Gana::Bhvadi && (867..=932).contains(&number) { + // Need to check range explicitly because some of these roots appear multiple times in the + // gana, e.g. svana~. + Some(Antargana::Ghatadi) + } else if gana == Gana::Tudadi && (93..=137).contains(&number) { + // Need to check range explicitly because some of these roots appear multiple times in the + // gana, e.g. juqa~. Some(Antargana::Kutadi) } else if gana == Gana::Curadi && (192..=236).contains(&number) { - // Need to check range explicitly because some of these roots appear - // multiple times in the gana, e.g. lakza~. + // Need to check range explicitly because some of these roots appear multiple times in the + // gana, e.g. lakza~. Some(Antargana::Akusmiya) } else if gana == Gana::Curadi && (279..=337).contains(&number) { - // Need to check range explicitly because some of these roots appear - // multiple times in the gana, e.g. tuji~. + // Need to check range explicitly because some of these roots appear multiple times in the + // gana, e.g. tuji~. Some(Antargana::Asvadiya) } else if gana == Gana::Curadi && (338..=388).contains(&number) { - // Need to check range explicitly because some of these roots appear - // multiple times in the gana, e.g. SraTa~. + // Need to check range explicitly because some of these roots appear multiple times in the + // gana, e.g. SraTa~. Some(Antargana::Adhrshiya) } else { None diff --git a/vidyut-prakriya/src/dvitva.rs b/vidyut-prakriya/src/dvitva.rs index 1a331d7..86ac277 100644 --- a/vidyut-prakriya/src/dvitva.rs +++ b/vidyut-prakriya/src/dvitva.rs @@ -92,7 +92,7 @@ fn try_dvitva(rule: Code, p: &mut Prakriya, i_dhatu: usize) -> Option<()> { p.set(i_dhatu, |t| t.add_tag(T::Dvitva)); }); if !done { - p.run(Varttika("6.1.3", "3"), |p| { + p.run(Varttika("6.1.3.3"), |p| { // Irzy + i + [sa] + sa let mut abhyasa = Term::make_text(&p.get(i_pratyaya).expect("").text); abhyasa.add_tags(&[T::Abhyasa, T::FlagIttva]); @@ -252,6 +252,7 @@ fn try_dvitva(rule: Code, p: &mut Prakriya, i_dhatu: usize) -> Option<()> { /// /// - `i` should point to a dhatu. fn run_at_index(p: &mut Prakriya, i: usize) -> Option<()> { + p.debug("run at index"); let dhatu = p.get_mut(i)?; debug_assert!(dhatu.is_dhatu()); @@ -299,6 +300,7 @@ fn run_at_index(p: &mut Prakriya, i: usize) -> Option<()> { /// /// For more details, see rule 1.1.59 ("dvirvacane 'ci"). pub fn try_dvirvacane_aci(p: &mut Prakriya) -> Option<()> { + p.debug("try_dvirvacane_aci"); // Select !pratyaya to avoid sanAdi, which are also labeled as Dhatu. let filter = |t: &Term| t.is_dhatu() && !t.has_tag_in(&[T::Dvitva, T::Pratyaya]); diff --git a/vidyut-prakriya/src/ganapatha.rs b/vidyut-prakriya/src/ganapatha.rs index 0d89057..5115b82 100644 --- a/vidyut-prakriya/src/ganapatha.rs +++ b/vidyut-prakriya/src/ganapatha.rs @@ -355,11 +355,14 @@ pub const SUKHA_ADI: &[&str] = &[ ]; /// 3.1.27 kaRqvAdiByo yak (35) +#[allow(unused)] pub const KANDU_ADI: &[&str] = &[ - "kaRqUY", "mantu", "hraRIY", "valgu", "astra", "manas", "mahIN", "lew", "low", "iras", "iraj", - "iraY", "dravas", "meDA", "kuzuBa", "magaDa", "tantas", "pampas", "suKa", "duHKa", "sapara", - "ara", "Bizaj", "BizRaj", "izuDa", "caraRa", "curaRa", "BuraRa", "turaRa", "gadgada", "elA", - "kelA", "KelA", "liw", "low", + "kaRqUY", "mantu", "mantuY", "valgu", "asu~", "asU", "asUY", "lew", "low", "lelA", "iras", + "iraj", "iraY", "uzas", "veda", "meDA", "kuzuBa", "magaDa", "tantas", "pampas", "suKa", + "duHKa", "sapara", "arara", "BizajU", "BizRaj", "izuDa", "caraRa", "varaRa", "curaRa", + "turaRa", "BuraRa", "gadgada", "elA", "kelA", "KelA", "ilA", "leKA", "leKa", "liwa", "lAwa", + "hfRIN", "mahIN", "reKA", "dravas", "tiras", "agada", "uras", "taraRa", "payas", "samBUyas", + "ambara", "saMvara", ]; /// 4.1.4 ajAdyataz wAp (54) @@ -1694,6 +1697,28 @@ pub const APUPA_ADI: &[&str] = &[ /// 5.1.20 asamAse nizkAdiByaH (148) pub const NISHKA_ADI: &[&str] = &["nizka", "paRa", "pAda", "mAza", "vAha", "droRa", "zazwi"]; +/// 5.1.64 CedAdiByo nityam (151) +pub const CHEDA_ADI: &[&str] = &[ + "Ceda", + "Beda", + "droha", + "doha", + "narti", + "narta", + "karza", + "tIrTa", + "samprayoga", + "viprayoga", + "prayoga", + "viprakarza", + "prezaRa", + "sampraSna", + "vipraSna", + "vikarza", + "virAga", + "viraNga", +]; + /// 5.1.66 daRqAdiByaH (152) pub const DANDA_ADI: &[&str] = &[ "daRqa", diff --git a/vidyut-prakriya/src/it_agama.rs b/vidyut-prakriya/src/it_agama.rs index a8858bf..f0b9beb 100644 --- a/vidyut-prakriya/src/it_agama.rs +++ b/vidyut-prakriya/src/it_agama.rs @@ -28,8 +28,9 @@ Order of operations: use crate::args::Gana::*; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::Tag as T; -use crate::core::{Code, Prakriya}; +use crate::core::{Prakriya, Rule}; use crate::core::{Term, TermView}; use crate::dhatu_gana as gana; use crate::it_samjna; @@ -53,13 +54,23 @@ fn is_hacky_eka_ac(p: &Prakriya, i: usize) -> bool { /// Returns whether the given term is vet by 7.2.44. /// /// We wrap this condition in its own function because other rules need to check it as well. -fn is_generally_vet(anga: &Term) -> bool { +fn is_svarati_suti(anga: &Term) -> bool { // > vakṣyati svaratisūtisūyatidhūñūdito vā 7.2.44। vidhūtaḥ। vidhūtavān। guhū gūḍhaḥ। gūḍhavān। // > udito vā vṛdhu vṛddhaḥ। // -- Kashikavrtti on 7.2.15. anga.has_u_in(&["svf", "zUN", "DUY"]) || anga.has_tag(T::Udit) } +/// Returns whether the given term is vet by 7.2.45. +fn is_radh_adi(anga: &Term) -> bool { + anga.has_gana(Divadi) && anga.has_u_in(gana::RADH_ADI) +} + +fn is_krta_crta(anga: &Term) -> bool { + const KRTA_CRTA: &[&str] = &["kftI~", "cftI~", "u~Cfdi~^r", "u~tfdi~^r", "nftI~"]; + anga.has_u_in(KRTA_CRTA) +} + /// Returns whether the given term is ever vet in any rule. /// /// This condition is necessary for 7.2.14. @@ -67,7 +78,7 @@ fn is_ever_vet(anga: &Term) -> bool { // > vakṣyati svaratisūtisūyatidhūñūdito vā 7.2.44। vidhūtaḥ। vidhūtavān। guhū gūḍhaḥ। gūḍhavān। // > udito vā vṛdhu vṛddhaḥ। // -- Kashikavrtti on 7.2.15. - is_generally_vet(anga) || anga.has_tag(T::udit) || anga.has_u_in(gana::RADH_ADI) + is_svarati_suti(anga) || is_radh_adi(anga) || anga.has_tag(T::udit) } /// A wrapper for `Prakriya` that allows at most one it-Agama rule to be added to the derivation. @@ -112,12 +123,12 @@ impl<'a> ItPrakriya<'a> { } /// Inserts it-Agama and prevents further rules. - fn try_add(&mut self, rule: Code) { + fn try_add(&mut self, rule: impl Into) { self.try_add_with(rule, |_| {}) } /// Inserts it-Agama and prevents further rules. - fn try_add_with(&mut self, rule: Code, func: impl Fn(&mut Prakriya)) { + fn try_add_with(&mut self, rule: impl Into, func: impl Fn(&mut Prakriya)) { if !self.done { let agama = Term::make_agama("iw"); self.p.insert_before(self.i_next, agama); @@ -130,7 +141,8 @@ impl<'a> ItPrakriya<'a> { } /// Optionally inserts it-Agama and returns whether the rule was applied. - fn optional_try_add(&mut self, rule: Code) -> bool { + fn optional_try_add(&mut self, rule: impl Into) -> bool { + let rule = rule.into(); if !self.done { if self.p.is_allowed(rule) { self.try_add(rule); @@ -145,7 +157,7 @@ impl<'a> ItPrakriya<'a> { } // Blocks it-Agama and prevents further rules. - fn try_block(&mut self, rule: Code) { + fn try_block(&mut self, rule: impl Into) { if !self.done { self.p.step(rule); } @@ -153,7 +165,8 @@ impl<'a> ItPrakriya<'a> { } // Optionally blocks it-Agama. - fn optional_try_block(&mut self, rule: Code) { + fn optional_try_block(&mut self, rule: impl Into) { + let rule = rule.into(); if !self.done { if self.p.is_allowed(rule) { self.try_block(rule); @@ -184,7 +197,7 @@ fn try_dirgha_for_it_agama(p: &mut Prakriya, i_it: usize) -> Option<()> { if !n.has_tag(T::Cinvat) { p.run_at("7.2.37", i_it, op::text("I")); } - } else if dhatu.has_antya('F') || dhatu.has_text("vf") { + } else if dhatu.has_antya('F') || dhatu.has_u_in(&["vfN", "vfY"]) { if last.has_lakshana("li~N") { p.step("7.2.39"); } else if n.slice().iter().any(|t| t.has_u("si~c")) && last.is_parasmaipada() { @@ -204,14 +217,19 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option return None; } + if n.last().is_unadi() { + return None; + } + let ktvi = n.last().has_u("ktvA"); if n.has_u("kvasu~") { + // kvasu~ rules should take priority over `li~w` below. let anga = ip.anga(); if anga.has_text_in(&["gam", "han", "vid", "viS"]) { ip.optional_try_add("7.2.68"); } else if anga.has_text("dfS") { - ip.optional_try_add("7.2.68.v1"); + ip.optional_try_add(Varttika("7.2.68.1")); } let anga = ip.anga(); @@ -243,71 +261,70 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option ip.try_block(code); } } else if n.has_lakshana("li~w") { - if is_generally_vet(anga) { - // Per SK, 7.2.44 allows iw-Agama here. - ip.optional_try_add("7.2.44"); - ip.done = true; - } - - let anga = ip.anga(); - let n = ip.next(); - // These rules are always aniT. - if anga.has_text_in(&["kf", "sf", "Bf", "vf", "stu", "dru", "sru", "Sru"]) { + if anga.has_text("vf") && n.has_u("Tal") { + // Exception to krAdi-niyama. + ip.try_add("7.2.64"); + } else if anga.has_text_in(&["kf", "sf", "Bf", "vf", "stu", "dru", "sru", "Sru"]) { ip.try_block("7.2.13"); - } else if n.has_u("Tal") { - // Rule 7.2.61 ("acas tAsvat ...") conditions on whether tAs would receive it-Agama. - // Estimate this by reproducing other it rules. - let rule_7_2_10 = anga.has_tag(T::Anudatta) && is_hacky_eka_ac(ip.p, ip.i_anga); - let is_anit_for_tas = rule_7_2_10; - - if (anga.has_antya(&*AC) || anga.text.contains('a')) && is_anit_for_tas { - // Concise summary of rules: - // - The roots in 7.2.13 are aniT. All others are seT by valAdi (7.2.35). - // - However, there are the following exceptions for Tal: - // - roots ending in `f` (except `f`) are aniT. - // - roots ending in a vowel and roots with a middle 'a' are veT. - // - other roots listed in rules explicitly (e.g. in 7.2.66) - let code = if anga.has_antya(&*AC) { - Some("7.2.61") - } else if !anga.has_u("vayi~") { - // quick HACK to prevent *uvayTa. - Some("7.2.62") - } else { - None - }; - - if let Some(code) = code { - // The last root is "vyeY" per siddhAntakaumudI. - if anga.has_u_in(&["a\\da~", "f\\", "vye\\Y"]) { - ip.try_add("7.2.66"); - } else if !anga.has_antya('f') { - // 7.2.63 Rto bhAradvAjasya - // In Bharadvaja's opinion, rule 7.2.61 applies only for final R. So for all - // other roots, this condition is optional: - if ip.p.is_allowed(code) { - ip.try_add(code); + } else { + // Normally, these options allow seT. Here, they allow aniT due to krAdi-niyama. + let shryukah_kiti = anga.has_antya(&*UK) && n.last().has_tag(T::kit); + if is_svarati_suti(anga) && !shryukah_kiti { + ip.optional_try_block("7.2.44"); + } else if is_radh_adi(anga) && !shryukah_kiti { + ip.optional_try_block("7.2.45"); + } else if is_krta_crta(anga) && n.has_adi('s') && !shryukah_kiti { + ip.optional_try_block("7.2.57"); + } + + let anga = ip.anga(); + let n = ip.next(); + if n.has_u("Tal") && !ip.done { + // Rule 7.2.61 ("acas tAsvat ...") conditions on whether tAs would receive it-Agama. + // Estimate this by reproducing other it rules. + let rule_7_2_10 = anga.has_tag(T::Anudatta) && is_hacky_eka_ac(ip.p, ip.i_anga); + let is_anit_for_tas = rule_7_2_10; + + if (anga.has_antya(&*AC) || anga.text.contains('a')) && is_anit_for_tas { + let code = if anga.has_u_in(&["Gasx~", "vayi~"]) { + // Skip these because they are not eligible per tAs, per KV on 7.2.61. + None + } else if anga.has_antya(&*AC) { + Some("7.2.61") + } else { + Some("7.2.62") + }; + + if let Some(code) = code { + // The last root is "vyeY" per siddhAntakaumudI. + if anga.has_u_in(&["a\\da~", "f\\", "vye\\Y"]) { + ip.try_add("7.2.66"); + } else if !anga.has_antya('f') { + // 7.2.63 Rto bhAradvAjasya + // In Bharadvaja's opinion, rule 7.2.61 applies only for final R. So for all + // other roots, this condition is optional: + if ip.p.is_allowed(code) { + ip.try_add(code); + } else { + ip.p.decline(code); + ip.try_block(code); + } } else { - ip.p.decline(code); ip.try_block(code); } - } else { - ip.try_block(code); } + } else if anga.has_text_in(&["sfj", "dfS"]) { + // By default, these will be seT. So the option allows aniT. + ip.optional_try_block("7.2.65"); } - } else if anga.has_text_in(&["sfj", "dfS"]) { - // By default, these will be seT. So the option allows aniT. - ip.optional_try_block("7.2.65"); } - } - if !ip.done { - // The effect of 7.2.13 is that all other anudatta roots are considerd `sew` by - // default. - ip.p.step("7.2.13"); - let anga = ip.anga(); - let n = ip.next(); - if n.has_adi(&*VAL) && anga.has_tag(T::Anudatta) { - ip.try_add("7.2.35"); + if !ip.done { + let n = ip.next(); + if n.has_adi(&*VAL) { + ip.p.step("7.2.13"); + ip.try_add("7.2.35"); + } } } } else if n.has_u("sya") { @@ -358,8 +375,8 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option } } else if anga.has_u_in(&["tanu~^", "patx~", "daridrA"]) { // titanizati, titaMsati, titAMsati, ... - if !ip.optional_try_add("7.2.49.v1") { - ip.try_block("7.2.49.v1"); + if !ip.optional_try_add(Varttika("7.2.49.1")) { + ip.try_block(Varttika("7.2.49.1")); } } else if anga.has_u_in(&["zmi\\N", "pUN", "f\\", "anjU~", "aSU~\\"]) { ip.try_add("7.2.74"); @@ -480,12 +497,11 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option let has_parasmaipada = ip.p.has_tag(T::Parasmaipada); let se = n.has_adi('s'); - let krta_crta = &["kftI~", "cftI~", "u~Cfdi~^r", "u~tfdi~^r", "nftI~"]; let ishu_saha = &["izu~", "zaha~\\", "luBa~", "ruza~", "riza~"]; if ip.done { // Do nothing - } else if anga.has_u_in(gana::RADH_ADI) && n.has_adi(&*VAL) { + } else if is_radh_adi(anga) && n.has_adi(&*VAL) { // All of these roots are in scope for 7.2.10 (aniT). // So, this option allows seT. ip.optional_try_add("7.2.45"); @@ -497,7 +513,7 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option } } else if anga.has_u_in(ishu_saha) && n.has_adi('t') { ip.optional_try_block("7.2.48"); - } else if anga.has_u_in(krta_crta) && se && !n.has_u("si~c") { + } else if is_krta_crta(anga) && se && !n.has_u("si~c") { // kartsyati, kartizyati, ... ip.optional_try_block("7.2.57"); } else if anga.has_text("gam") && has_parasmaipada && se { @@ -526,7 +542,7 @@ fn run_valadau_ardhadhatuke_before_attva_for_term(ip: &mut ItPrakriya) -> Option let n = ip.next(); let last = ip.p.terms().last()?; if n.has_adi(&*VAL) && !ip.done { - if is_generally_vet(anga) { + if is_svarati_suti(anga) { // Synchronize choice of "it" with the choice of lun-vikarana in 3.1.45: // - if lun and using ksa, must use anit. // - if lun and not using ksa, must use set. @@ -588,8 +604,9 @@ fn run_sarvadhatuke_for_term(ip: &mut ItPrakriya) -> Option<()> { let anga = ip.anga(); let i_n = ip.i_next; - let tin = n.last(); + let se = || n.has_text_in(&["se", "sva"]); + let dhve = || n.has_text_in(&["Dve", "Dvam"]) && n.has_lakshana_in(&["la~w", "lo~w"]); let is_aprkta = n.slice().iter().map(|t| t.len()).sum::() == 1; if anga.has_u("a\\da~") && is_aprkta { op::insert_agama_at("7.3.100", ip.p, i_n, "aw"); @@ -615,10 +632,10 @@ fn run_sarvadhatuke_for_term(ip: &mut ItPrakriya) -> Option<()> { // roditi, svapiti, Svasiti, aniti, jakziti ip.try_add("7.2.76"); } - } else if anga.has_text("IS") && n.has_adi('s') { + } else if anga.has_text("IS") && se() { // ISize, ISizva ip.try_add("7.2.77"); - } else if anga.has_text_in(&["Iq", "jan", "IS"]) && tin.has_text_in(&["se", "Dve"]) { + } else if anga.has_u_in(&["Iqa~\\", "janI~\\", "jana~", "ISa~\\"]) && (se() || dhve()) { // IqiDve, janiDve // // See kAshika on 7.2.78 for inclusion of IS here. diff --git a/vidyut-prakriya/src/it_samjna.rs b/vidyut-prakriya/src/it_samjna.rs index 146faab..8847f7a 100644 --- a/vidyut-prakriya/src/it_samjna.rs +++ b/vidyut-prakriya/src/it_samjna.rs @@ -4,13 +4,28 @@ //! //! 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::args::Gana; use crate::core::errors::*; use crate::core::Prakriya; +use crate::core::Rule::Varttika; use crate::core::{Tag as T, Term}; use crate::sounds::{s, Set}; -use compact_str::CompactString; use lazy_static::lazy_static; +// Common constants. Benchmark indicates that switching to `const` has negligible or negative +// impact: +// +// lazy_static: +// Benchmark 1: ../target/release/create_tinantas > /dev/null +// Time (mean ± σ): 7.604 s ± 0.095 s [User: 7.545 s, System: 0.021 s] +// Range (min … max): 7.502 s … 7.793 s 10 runs +// +// const: +// Benchmark 1: ../target/release/create_tinantas > /dev/null +// Time (mean ± σ): 7.768 s ± 0.122 s [User: 7.714 s, System: 0.021 s] +// Range (min … max): 7.596 s … 7.984 s 10 runs +// +// The poor results for `const` are surprising to me. I'm not sure how to explain them. lazy_static! { // FIXME: find a better approach for `s`. static ref AC: Set = s("ac"); @@ -21,91 +36,47 @@ lazy_static! { static ref LASHAKU: Set = s("l S ku~"); } -fn get_adi(s: &CompactString) -> Option { +fn get_adi(s: &str) -> 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", "jAhac", "wIwac"]) -} - -fn is_lashaku_exempt(t: &Term) -> bool { - t.has_u_in(&["kAmyac"]) -} - -/// 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)?; - - // If the text contains `yu~` or `vu~`, skip lopa of nasal vowels so that rule 7.1.1 - // (yuvoranAkau) can apply. - if term.is_pratyaya() && (term.text.contains("yu~") || term.text.contains("vu~")) { - return None; +fn is_exempt_from_cutu(t: &Term) -> bool { + // The sounds C, J, W, and Q are replaced later in the grammar. If we substitute them now, + // those rules will become vyartha. + if t.has_adi(&*CUTU_EXCEPTION) { + true + } else { + t.is_taddhita() && t.has_u_in(&["jAtIyar", "caraw", "cuYcup", "caRap", "jAhac", "wIwac"]) } +} - let mut i = 0; - let bytes = before.as_bytes(); - let mut after = CompactString::from(""); - let mut should_mark_rule = false; - - while let Some(u) = bytes.get(i) { - let c = *u as char; - - if AC.contains(c) { - if let Some(b'~') = bytes.get(i + 1) { - should_mark_rule = true; - // Nasal vowel: parse as it. - term.add_tag(T::parse_it(c).ok()?); - let maybe_tag = match bytes.get(i + 2) { - Some(b'^') => Some(T::svaritet), - Some(b'\\') => Some(T::anudattet), - _ => None, - }; - let shift = if let Some(tag) = maybe_tag { - term.add_tag(tag); - 3 - } else { - 2 - }; - - i += shift; - } else { - // Non-nasal vowel: get accent. - let maybe_tag = match bytes.get(i + 1) { - Some(b'^') => Some(T::Svarita), - Some(b'\\') => Some(T::Anudatta), - _ => None, - }; - let shift = if let Some(tag) = maybe_tag { - term.add_tag(tag); - 2 - } else { - 1 - }; - after.push(c); - i += shift; - } - } else { - after.push(c); - i += 1; - } +fn is_exempt_from_lakshaku(t: &Term) -> bool { + const LAKARAS: &[&str] = &[ + "la~w", "li~w", "lu~w", "lf~w", "le~w", "lo~w", "la~N", "li~N", "lu~N", "lf~N", + ]; + + if t.has_tag(T::La) && t.has_u_in(LAKARAS) { + // Keep the first "l" of the lakAras. Otherwise, rule 3.4.77 will become vyartha. + true + } else if t.is_unadi() && t.has_u_in(&["kan", "Ka"]) { + true + } else { + t.is_pratyaya() && t.has_u_in(&["kAmyac"]) } +} - if before != &after { - before.replace_range(.., &after); - if should_mark_rule { - p.run_at("1.3.2", i_term, |_| {}); - } +fn get_upadesha(t: &Term) -> Result<&str> { + match &t.u { + Some(s) => Ok(&s), + None => Err(Error::invalid_upadesha(&t.text)), } - - Some(()) } /// Runs rules that identify and remove it letters from the term at index `i`. /// /// (1.3.2 - 1.3.9) -pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { - let t = match p.get(i) { +pub fn run(p: &mut Prakriya, i_term: usize) -> Result<()> { + let t = match p.get(i_term) { Some(t) => t, None => return Ok(()), }; @@ -115,42 +86,96 @@ pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { return Ok(()); } + if t.is_dhatu() + && t.has_gana(Gana::Kandvadi) + && (t.has_antya('s') || t.has_antya('w') || t.has_antya('j')) + { + return Ok(()); + } + // All it sounds are removed at once by 1.3.9 "tasya lopaH". Before then, keep the text in the // term unchanged. Instead, mutate a new temporary string and copy it over as part of 1.3.9. - let mut temp: CompactString = match &t.u { - Some(s) => s.clone(), - None => { - return Err(Error::invalid_upadesha(&t.text)); - } - }; + let mut changed = false; + let mut i_start = 0; + let mut i_end = t.text.len(); // Varttika: `i~r` is its own it. let mut irit = false; - if let Some(t) = p.get_mut(i) { - if let Some(prefix) = temp.strip_suffix("i~r") { - temp.truncate(prefix.len()); - t.add_tag(T::irit); - irit = true; - } else if let Some(prefix) = temp.strip_suffix("i~^r") { - temp.truncate(prefix.len()); - t.add_tags(&[T::irit, T::svaritet]); - irit = true; - } + if p.has(i_term, |t| t.has_suffix_in(&["i~r", "i~^r", "i~\\r"])) { + let ir_slice = t.text.rfind(|c| c == 'i').expect("present"); + i_end = ir_slice; + + p.run_at(Varttika("1.3.3.1"), i_term, |t| { + let suffix = &t.text[ir_slice..]; + if suffix == "i~^r" { + t.add_tags(&[T::irit, T::svaritet]); + } else if suffix == "i~\\r" { + t.add_tags(&[T::irit, T::anudattet]); + } else { + t.add_tag(T::irit); + } + }); + + irit = true; + changed = true; } - run_1_3_2(p, i, &mut temp); + // Rule 1.3.2 ("upadeśe janunāsika iṭ"). + let mut is_yu_vu = false; + if let Some(t) = p.get_mut(i_term) { + // If the text contains `yu~` or `vu~`, skip lopa of nasal vowels so that rule 7.1.1 + // (yuvoranAkau) can apply. + is_yu_vu = t.is_pratyaya() && (t.text.contains("yu~") || t.text.contains("vu~")); + if !is_yu_vu { + let mut should_mark_rule = false; + + let upadesha = &get_upadesha(t)?[..i_end]; + for i in 0..upadesha.len() { + let upadesha = &get_upadesha(t)?[..i_end]; + let bytes = upadesha.as_bytes(); + let c = *bytes.get(i).expect("present") as char; + + if !AC.contains(c) { + continue; + } - let t = match p.get(i) { - Some(t) => t, - None => return Ok(()), - }; + let next = match bytes.get(i + 1) { + Some(b) => *b, + None => continue, + }; - let antya = match t.antya() { - Some(x) => x, - None => return Err(Error::invalid_upadesha(&t.text)), - }; + if next == b'~' { + should_mark_rule = true; + let maybe_tag = match bytes.get(i + 2) { + Some(b'^') => Some(T::svaritet), + Some(b'\\') => Some(T::anudattet), + _ => None, + }; + + t.add_tag(T::parse_it(c)?); + if let Some(tag) = maybe_tag { + t.add_tag(tag); + }; + } else if next == b'\\' { + t.add_tag(T::Anudatta); + } else if next == b'^' { + t.add_tag(T::Svarita); + } + } + + if should_mark_rule { + p.run_at("1.3.2", i_term, |_| {}); + changed = true; + } + } + } + + if let Some(t) = p.get(i_term) { + let antya = match t.antya() { + Some(x) => x, + None => return Err(Error::invalid_upadesha(&t.text)), + }; - if let Some(t) = p.get_mut(i) { if HAL.contains(antya) && !irit { let vibhaktau_tusmah = t.is_vibhakti() && TUSMA.contains(antya); @@ -167,74 +192,75 @@ pub fn run(p: &mut Prakriya, i: usize) -> Result<()> { if vibhaktau_tusmah && !is_vibhakti_exception { p.step("1.3.4"); } else { - p.add_tag_at("1.3.3", i, T::parse_it(antya)?); - temp.truncate(temp.len() - 1); + p.add_tag_at("1.3.3", i_term, T::parse_it(antya)?); + changed = true; + i_end -= 1; } } } - let mut temp_slice = &temp[..]; - if let Some(t) = p.get_mut(i) { - // Apply 1.3.5 only for non-pratyayas. This way, we avoid including qu-pratyaya, etc. - if !t.is_pratyaya() { - let mut matched = false; + if let Some(t) = p.get(i_term) { + let upadesha = get_upadesha(t)?; + let adi = match get_adi(&upadesha) { + Some(x) => x, + None => return Err(Error::invalid_upadesha(&upadesha)), + }; + + if t.is_pratyaya() { + if adi == 'z' { + p.add_tag_at("1.3.6", i_term, T::parse_it(adi)?); + changed = true; + i_start += 1; + } else if CUTU.contains(adi) && !is_exempt_from_cutu(t) { + p.add_tag_at("1.3.7", i_term, T::parse_it(adi)?); + changed = true; + i_start += 1; + } else if !t.is_taddhita() && t.has_adi(&*LASHAKU) && !is_exempt_from_lakshaku(t) { + p.add_tag_at("1.3.8", i_term, T::parse_it(adi)?); + changed = true; + i_start += 1; + } + } else { + // Apply 1.3.5 only for non-pratyayas. This way, we avoid including qu-pratyaya, etc. for (it, tag) in [("Yi", T::YIt), ("wu", T::wvit), ("qu", T::qvit)] { - if temp.strip_prefix(it).is_some() { - temp_slice = &temp_slice[it.len()..]; - t.add_tag(tag); - matched = true; + if upadesha.strip_prefix(it).is_some() { + p.add_tag_at("1.3.5", i_term, tag); + changed = true; + i_start += it.len(); + break; } } - if matched { - p.run_at("1.3.5", i, |_| {}); - } } } - let adi = match get_adi(&temp) { - Some(x) => x, - None => return Err(Error::invalid_upadesha(&temp)), - }; - - if let Some(t) = p.get_mut(i) { - if t.is_pratyaya() { - if t.is_unadi() && t.has_u_in(&["kan"]) { - // Do nothing. - } else if adi == 'z' { - temp_slice = &temp_slice[1..]; - p.add_tag_at("1.3.6", i, T::parse_it(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) { - t.add_tag(T::parse_it(adi)?); - temp_slice = &temp_slice[1..]; - } - p.step("1.3.7"); - } else if !t.has_tag(T::Taddhita) && t.has_adi(&*LASHAKU) && !is_lashaku_exempt(t) { - // Keep the first "l" of the lakAras. - // Otherwise, rule 3.4.77 will become vyartha. - const LAKARAS: &[&str] = &[ - "la~w", "li~w", "lu~w", "lf~w", "le~w", "lo~w", "la~N", "li~N", "lu~N", "lf~N", - ]; - if !t.has_u_in(&LAKARAS) { - temp_slice = &temp_slice[1..]; - p.add_tag_at("1.3.8", i, T::parse_it(adi)?); + if changed { + p.run_at("1.3.9", i_term, |t| { + // Remove it-samjnas, excluding nasal vowels. + t.text.truncate(i_end); + t.text.drain(..i_start); + + // Remove accents. + t.text.retain(|c| c != '\\' && c != '^'); + + // Remove nasal vowels. + if !is_yu_vu { + while let Some(i_nasal) = t.text.find('~') { + if i_nasal > 0 { + t.text.drain(i_nasal - 1..i_nasal + 1); + } } } - } - } - if let Some(t) = p.get_mut(i) { - if temp_slice != t.text { - p.run_at("1.3.9", i, |t| { - t.set_text(temp_slice); - if t.has_tag(T::zit) && t.has_adi('w') { - t.set_adi("t"); - } - t.maybe_save_sthanivat(); - }); - } + // TODO: justify this change. + if t.has_tag(T::zit) && t.has_adi('w') { + t.set_adi("t"); + } + + t.maybe_save_sthanivat(); + }); + } else { + // Remove accents. This should happen even if `changed` is false. + p.set(i_term, |t| t.text.retain(|c| c != '\\' && c != '^')); } Ok(()) @@ -274,9 +300,9 @@ mod tests { ), ]; - for (raw, text, tags) in tests { + for (raw, expected, tags) in tests { let t = check(Term::make_upadesha(raw)); - assert_eq!(t.text, text); + assert_eq!(expected, t.text); assert!(t.has_all_tags(&tags)); } } @@ -292,12 +318,12 @@ mod tests { ("AtAm", "AtAm", vec![]), ]; - for (raw, text, tags) in tests { + for (raw, expected, tags) in tests { let mut start = Term::make_upadesha(raw); start.add_tag(T::Vibhakti); let t = check(start); - assert_eq!(t.text, text); + assert_eq!(expected, t.text); assert!(t.has_all_tags(&tags)); } } @@ -307,14 +333,17 @@ mod tests { let tests = [ ("kta", "ta", vec![T::Pratyaya, T::kit]), ("Ric", "i", vec![T::Pratyaya, T::Rit, T::cit]), - ("la~w", "l", vec![T::Pratyaya, T::adit, T::wit]), + ("la~w", "l", vec![T::Pratyaya, T::La, T::adit, T::wit]), ]; - for (raw, text, tags) in tests { + for (raw, expected, tags) in tests { let mut start = Term::make_upadesha(raw); start.add_tag(T::Pratyaya); - let t = check(start); + if raw == "la~w" { + start.add_tag(T::La); + } - assert_eq!(t.text, text, "{text}"); + let t = check(start); + assert_eq!(expected, t.text); assert!(t.has_all_tags(&tags), "Missing one or more of `{tags:?}`"); } } diff --git a/vidyut-prakriya/src/krt/basic.rs b/vidyut-prakriya/src/krt/basic.rs index e9f9184..ed4eea6 100644 --- a/vidyut-prakriya/src/krt/basic.rs +++ b/vidyut-prakriya/src/krt/basic.rs @@ -218,7 +218,7 @@ fn try_add_various_pratyayas(kp: &mut KrtPrakriya) { kp.try_add("3.2.173", Aru); } else if dhatu.has_text("BI") { if kp.expects_krt(kruka) { - kp.try_add(Varttika("3.2.174", "1"), kruka); + kp.try_add(Varttika("3.2.174.1"), kruka); } else if kp.expects_krt(kru) { kp.try_add("3.2.174", kru); } else { @@ -461,10 +461,10 @@ fn try_add_various_pratyayas(kp: &mut KrtPrakriya) { kp.try_add("3.3.120", GaY); } else if dhatu.has_u("Kanu~^") { kp.optional_try_add("3.3.125", Ga); - kp.optional_try_add(Varttika("3.3.125", "1"), qa); - kp.optional_try_add(Varttika("3.3.125", "2"), qara); - kp.optional_try_add(Varttika("3.3.125", "3"), ika); - kp.optional_try_add(Varttika("3.3.125", "4"), ikavaka); + kp.optional_try_add(Varttika("3.3.125.1:1"), qa); + kp.optional_try_add(Varttika("3.3.125.1:2"), qara); + kp.optional_try_add(Varttika("3.3.125.1:3"), ika); + kp.optional_try_add(Varttika("3.3.125.1:4"), ikavaka); } // Base case @@ -558,7 +558,7 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { && dhatu.has_u("pA\\") && dhatu.has_gana(Gana::Bhvadi) { - kp.try_add(Varttika("3.2.8", "1"), wak); + kp.try_add(Varttika("3.2.8.1"), wak); } else if dhatu.has_u("hf\\Y") { if kp.has_upapada("AN") { // tAcCIlye @@ -571,10 +571,10 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if upapada.has_text_in(&[ "Sakti", "lANgala", "aNkuSa", "yazwi", "tomara", "Gawa", "GaWI", "Danus", ]) { - kp.try_add(Varttika("3.2.9", "1"), ac); + kp.try_add(Varttika("3.2.9.1"), ac); } else if upapada.has_text("sUtra") { // dhAri-arthe - kp.optional_try_add(Varttika("3.2.9", "2"), ac); + kp.optional_try_add(Varttika("3.2.9.2"), ac); } } else if !upasarge && dhatu.has_antya('A') { kp.try_add("3.2.3", ka); @@ -785,7 +785,7 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if upapada.has_text_in(TYAD_ADI) && dhatu.has_u("df\\Si~r") { kp.try_add("3.2.60", krt); } else if upapada.has_text_in(&["samAna", "anya"]) && dhatu.has_u("df\\Si~r") { - kp.try_add(Varttika("3.2.60", "1"), krt); + kp.try_add(Varttika("3.2.60.1"), krt); } else if krt == kvin { if !upapada.has_text("udaka") && dhatu.has_text("spfS") { kp.try_add("3.2.58", kvin); @@ -880,7 +880,7 @@ fn try_add_upapada_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if dhatu.has_text("Sri") { // SrI // TODO: others - kp.p.run_at(Varttika("3.2.178", "1"), i_dhatu, |t| t.set_antya("I")); + kp.p.run_at(Varttika("3.2.178.1"), i_dhatu, |t| t.set_antya("I")); } } @@ -938,12 +938,12 @@ 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.optional_run_at(Varttika("3.1.96", "1"), i + 1, |t| t.add_tag(T::Rit)); + kp.p.optional_run_at(Varttika("3.1.96.1"), i + 1, |t| t.add_tag(T::Rit)); } } K::kelimar => { - kp.try_add("3.1.96.v2", krt); + kp.try_add(Varttika("3.1.96.2"), krt); } // "ya" (3.1.97 - 3.1.132) @@ -985,7 +985,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { } else if dhatu.has_u_in(&["gada~", "madI~", "cara~", "ya\\ma~"]) && !upasarge { kp.try_add("3.1.100", K::yat); } else if dhatu.has_u("cara~") && kp.has_upapada("AN") { - kp.optional_try_add(Varttika("3.1.100", "1"), K::yat); + kp.optional_try_add(Varttika("3.1.100.1"), K::yat); } else if !upasarge && dhatu.has_text("vad") && supi { kp.try_add("3.1.106", K::yat); kp.try_add("3.1.106", K::kyap); @@ -1017,7 +1017,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { if (dhatu.has_antya('u') || dhatu.has_antya('U')) && !avashyaka_blocked { kp.optional_try_add("3.1.125", K::Ryat); } else if dhatu.has_u("ha\\na~") { - kp.optional_try_add_with("3.1.97.v2", K::yat, |p| { + kp.optional_try_add_with(Varttika("3.1.97.2"), K::yat, |p| { p.set(i_dhatu, |t| t.set_text("vaD")); }); } @@ -1029,7 +1029,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { // Sapya, laBya, japya kp.try_add("3.1.98", K::yat); } else if dhatu.has_u_in(&["taka~", "Sasu~\\", "cate~^", "yatI~\\", "janI~\\"]) { - kp.try_add(Varttika("3.1.97", "1"), K::yat); + kp.try_add(Varttika("3.1.97.1"), K::yat); } else if dhatu.has_antya('f') || dhatu.has_antya('F') || dhatu.has_antya(&*HAL) { kp.try_add("3.1.124", K::Ryat); } else if dhatu.has_antya(&*AC) { @@ -1146,7 +1146,7 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { kp.try_add(code, krt); } else { // suSarmA, prAtaritvan, vijAvA, rez, ... - kp.try_add("3.2.76", krt); + kp.try_add("3.2.75", krt); } } @@ -1336,6 +1336,12 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { } } + K::aN => { + if dhatu.has_antya('A') && upasarge { + kp.try_add_with("3.3.106", krt, |p| p.add_tag(T::Stri)); + } + } + K::yuc => { if dhatu.has_u_in(&["Ric", "Asa~\\", "SranTa~"]) { kp.try_add_with("3.3.107", krt, |p| p.add_tag(T::Stri)); @@ -1356,7 +1362,9 @@ fn try_add_krt(p: &mut Prakriya, krt: BaseKrt) -> Option { K::Kal => { // TODO: restrict - kp.try_add("3.3.126", krt); + if kp.upapada().is_some() { + kp.try_add("3.3.126", krt); + } } K::ktic => { diff --git a/vidyut-prakriya/src/krt/unadipatha.rs b/vidyut-prakriya/src/krt/unadipatha.rs index ebdf47c..6fa2036 100644 --- a/vidyut-prakriya/src/krt/unadipatha.rs +++ b/vidyut-prakriya/src/krt/unadipatha.rs @@ -30,8 +30,10 @@ Points against: We found the points against more convincing and have stored these pratyayas in two separate enums. */ use crate::args::{Krt, Unadi}; +use crate::core::operators as op; use crate::core::Tag as T; use crate::core::{Prakriya, Rule}; +use crate::it_samjna; use crate::krt::utils::KrtPrakriya; use crate::sounds::{s, Set}; use lazy_static::lazy_static; @@ -56,6 +58,14 @@ fn set_text(text: &'static str) -> impl Fn(&mut Prakriya) { } } +/// A helper function that replaces the first sound of the dhatu. +fn set_adi(text: &'static str) -> impl Fn(&mut Prakriya) { + move |p| { + let i_dhatu = p.terms().len() - 2; + p.set(i_dhatu, |t| t.set_adi(text)); + } +} + /// A helper function that replaces the last sound of the dhatu. fn set_antya(text: &'static str) -> impl Fn(&mut Prakriya) { move |p| { @@ -246,6 +256,7 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { } U::ati => { if dhatu.has_text_in(&["mah"]) { + // mahat kp.try_add_with(UP("2.84"), krt, |p| { p.set(i_dhatu + 1, |t| t.add_tags(&[T::Sit, T::fdit])); }); @@ -371,7 +382,6 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { | U::Asa | U::Anuk => { let code = UP("4.2"); - let has_u = |u| dhatu.has_u(u); match krt { U::katnic if dhatu.has_u("f\\") => { @@ -410,10 +420,10 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { kp.try_add(code, krt); } // TODO: kavaca? - U::Asa if has_u("yu") => { + U::Asa if dhatu.has_u("yu") => { kp.try_add(code, krt); } - U::Anuk if has_u("kfSa~") => { + U::Anuk if dhatu.has_u("kfSa~") => { kp.try_add(code, krt); } _ => (), @@ -455,6 +465,7 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { } U::kvin => { if dhatu.has_u_in(&["jF", "SFY", "stFY", "jAgf"]) { + // jIrvi, SIrvi, stIrvi, jAgfvi kp.try_add(UP("4.54"), krt); } } @@ -475,11 +486,13 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { } U::ama => { if dhatu.has_text_in(&["kal", "kard"]) { + // kalama, karmada kp.try_add(UP("4.83"), krt); } } U::kindac => { if dhatu.has_text_in(&["kuR", "pul"]) { + // kuRinda, pulinda kp.try_add(UP("4.84"), krt); } } @@ -499,6 +512,102 @@ pub fn try_add_unadi(p: &mut Prakriya, krt: Unadi) -> Option { kp.try_add(UP("4.188"), krt); } } + U::Uma => { + if dhatu.has_u("guDa~") { + // goDUma + kp.try_add(UP("5.2"), krt); + } + } + U::Uran => { + if dhatu.has_u("masI~") { + // masUra + kp.try_add(UP("5.3"), krt); + } else if dhatu.has_u("zWA\\") { + // sTUra + kp.try_add_with(UP("5.4"), krt, mark_as(T::kit)); + } + } + U::ati_ => { + if dhatu.has_u("pA\\") { + // pAti, sampAti + kp.try_add(UP("5.5"), krt); + } else if dhatu.has_u("vA\\") { + // vAti + kp.try_add_with(UP("5.6"), krt, mark_as(T::nit)); + } else if dhatu.has_u("f\\") { + // arati + kp.try_add_with(UP("5.7"), krt, mark_as(T::nit)); + } + } + U::kna => { + if dhatu.has_u("tfhU~") { + // tfRa + kp.try_add_with(UP("5.8"), krt, set_antya("")); + } + } + U::qEsi => { + if has_upasarga("ud") && dhatu.has_u("ci\\Y") { + // uccEH + kp.try_add(UP("5.12"), krt); + } else if has_upasarga("ni") && dhatu.has_u("ci\\Y") { + // nIcEH + kp.try_add_with(UP("5.13"), krt, |p| p.set(i - 1, |t| t.set_antya("I"))); + } + } + U::yat => { + if dhatu.has_u("pUY") { + // puRya + let added = kp.try_add_with(UP("5.15"), krt, |p| { + p.set(i, |t| t.set_antya("u")); + op::insert_agama_after(p, i, "Ru~k"); + }); + if added { + it_samjna::run(kp.p, i + 1).expect("ok"); + } + } + } + U::Ka => { + if dhatu.has_u("mu\\ha~") { + // mUrKa + kp.try_add_with(UP("5.22"), krt, |p| { + p.set(i, |t| t.set_text("mUr")); + }); + } else if dhatu.has_u("Ra\\ha~^") { + // naKa + kp.try_add_with(UP("5.23"), krt, set_antya("")); + } else if dhatu.has_u("SIN") { + // SiKA + // TODO: why strI? + kp.try_add_with(UP("5.24"), krt, set_antya("i")); + } + } + U::UKa => { + if dhatu.has_u("mA\\N") { + // mayUKa + kp.try_add_with(UP("5.25"), krt, set_text("may")); + } + } + U::wan => { + if dhatu.has_u("janI~\\") { + // jawA + // TODO: why strI? + kp.try_add_with(UP("5.30"), krt, set_antya("")); + } + } + U::an => { + if dhatu.has_text("kliS") { + // keSa + kp.try_add_with(UP("5.33"), krt, |p| { + p.set(i, |t| t.find_and_replace_text("l", "")) + }); + } + } + U::itac => { + if dhatu.has_text("Pal") { + // palita + kp.try_add_with(UP("5.34"), krt, set_adi("p")); + } + } U::amac => { if dhatu.has_u("praTa~\\") { // praTama diff --git a/vidyut-prakriya/src/samasa.rs b/vidyut-prakriya/src/samasa.rs index ce1a7e3..e6d8ee1 100644 --- a/vidyut-prakriya/src/samasa.rs +++ b/vidyut-prakriya/src/samasa.rs @@ -1,6 +1,7 @@ use crate::args::Samasa; use crate::args::SamasaType; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::{Prakriya, Rule}; use crate::core::{Term, TermView}; @@ -257,7 +258,7 @@ fn decide_samasa_type(p: &mut Prakriya, args: &Samasa) -> Option { sp.mark_tatpurusha("2.1.37"); } else if uttara.has_text_in(&["BIta", "BIti", "BI"]) { // vfkaBIta, ... - sp.mark_tatpurusha("2.1.37.v1"); + sp.mark_tatpurusha(Varttika("2.1.37.1")); } else if uttara.has_text_in(&["apeta", "apoQa", "mukta", "patita", "apatrasta"]) { // suKApeta, ... sp.mark_tatpurusha("2.1.38"); diff --git a/vidyut-prakriya/src/samjna.rs b/vidyut-prakriya/src/samjna.rs index 54468fb..dc0f292 100644 --- a/vidyut-prakriya/src/samjna.rs +++ b/vidyut-prakriya/src/samjna.rs @@ -1,6 +1,7 @@ //! Rules that add various samjnas (labels) to the terms in the grammar. use crate::core::operators as op; use crate::core::Prakriya; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::Term; use crate::ganapatha as gana; @@ -20,9 +21,8 @@ fn is_tiya(t: &Term) -> bool { t.has_u_in(&["dvitIya", "tftIya"]) } -fn is_vatu(_: &Term) -> bool { - // HACK: placeholder - false +fn is_vatu(t: &Term) -> bool { + t.has_u("vatu~p") } fn is_dati(t: &Term) -> bool { @@ -165,7 +165,7 @@ fn try_run_for_pratipadika_at_index(p: &mut Prakriya, i: usize) -> Option<()> { 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)); + p.optional_run_at(Varttika("1.1.33.1"), i, add_tag(T::Sarvanama)); } else if prati.has_u_in(gana::SARVA_ADI) || prati.has_u_in(USES_DATARA_DATAMA) { let mut sarvanama = true; if prati.has_u_in(PURVA_ADI) && jasi { diff --git a/vidyut-prakriya/src/sanadi.rs b/vidyut-prakriya/src/sanadi.rs index 236e00b..48166d2 100644 --- a/vidyut-prakriya/src/sanadi.rs +++ b/vidyut-prakriya/src/sanadi.rs @@ -134,9 +134,14 @@ fn try_add(p: &mut Prakriya, sanadi: Option<&Sanadi>, is_ardhadhatuka: bool) -> sp.add("3.1.11", kyaN.as_str()); if sp.p.has(i_base, |t| t.has_antya('s')) { // payAyate, payasyate, ... - sp.p.optional_run_at(Varttika("3.1.11", "1"), i_base, |t| t.set_antya("")); + sp.p.optional_run_at(Varttika("3.1.11.1"), i_base, |t| t.set_antya("")); } } + } else if sup && matches!(sanadi, Some(Ric)) { + // pawayati, ... + sp.add_with(Rule::Dhatupatha("10.0502"), Ric.as_str(), |p| { + p.set(i_base + 1, |t| t.add_tag(T::FlagNoArdhadhatuka)); + }); } else if sup && base.has_text_in(gana::BHRSHA_ADI) { // BfSAyate, .. sp.add_with("3.1.12", kyaN.as_str(), |p| { @@ -154,14 +159,14 @@ fn try_add(p: &mut Prakriya, sanadi: Option<&Sanadi>, is_ardhadhatuka: bool) -> sp.add("3.1.14", kyaN.as_str()); } else if sup && base.has_text_in(&["satra", "kakza", "kfcCra", "gahana"]) { // kazwAyate, ... - sp.add(Varttika("3.1.14", "1"), kyaN.as_str()); + sp.add(Varttika("3.1.14.1"), kyaN.as_str()); } else if sup && base.has_text_in(&["romanTa", "tapas"]) { let is_tapas = base.has_text("tapas"); // romanTAyate, ... sp.add("3.1.15", kyaN.as_str()); // tapasyati, ... if is_tapas { - sp.p.run_at(Varttika("3.1.15", "1"), sp.p.terms().len() - 1, |t| { + sp.p.run_at(Varttika("3.1.15.2"), sp.p.terms().len() - 1, |t| { t.remove_tag(T::Nit) }); } @@ -170,20 +175,20 @@ fn try_add(p: &mut Prakriya, sanadi: Option<&Sanadi>, is_ardhadhatuka: bool) -> sp.add("3.1.16", kyaN.as_str()); } else if sup && base.has_text("Pena") { // PenAyate, ... - sp.add(Varttika("3.1.16", "1"), kyaN.as_str()); + sp.add(Varttika("3.1.16.1"), kyaN.as_str()); } else if sup && base.has_text_in(&["Sabda", "vEra", "kalaha", "aBra", "kaRva", "meGa"]) { // SabdAyate, ... sp.add("3.1.17", kyaN.as_str()); } else if sup && base.has_text_in(&["sudina", "durdina", "nIhAra"]) { // sudinAyate, ... - sp.add(Varttika("3.1.17", "1"), kyaN.as_str()); + sp.add(Varttika("3.1.17.1"), kyaN.as_str()); } else if sup && base.has_text_in(&[ "awA", "awwA", "SIkA", "kowA", "powA", "sowA", "kazwA", "pruzwA", "pluzwA", ]) { // awAyate, ... - sp.add(Varttika("3.1.17", "2"), kyaN.as_str()); + sp.add(Varttika("3.1.17.2"), kyaN.as_str()); } else if sup && base.has_text_in(gana::SUKHA_ADI) { // suKAyate, ... sp.add("3.1.18", kyaN.as_str()); @@ -220,7 +225,7 @@ fn try_add(p: &mut Prakriya, sanadi: Option<&Sanadi>, is_ardhadhatuka: bool) -> .has(i_base - 1, |t| t.has_u_in(&["sUca", "sUtra", "mUtra"]))) || base.has_u_in(&["awa~", "f\\", "aSa~", "aSU~\\", "UrRuY"]) { - sp.add("3.1.22.v1", yaN.as_str()); + sp.add(Varttika("3.1.22.1"), yaN.as_str()); } else if base.is_ekac() && base.has_adi(&*HAL) { sp.add("3.1.22", yaN.as_str()); } @@ -250,17 +255,20 @@ fn try_add(p: &mut Prakriya, sanadi: Option<&Sanadi>, is_ardhadhatuka: bool) -> let base = sp.p.get(i_base)?; if sup && base.has_text_in(&["satya", "arTa", "veda"]) { // satyApayati, arTApayati, vedApayati - op::insert_agama_at(Varttika("3.1.25", "1"), sp.p, i_base + 2, "Apu~k"); + op::insert_agama_at(Varttika("3.1.25.1"), sp.p, i_base + 2, "Apu~k"); } } else if matches!(sanadi, Some(Ric)) { + // kArayati, ... sp.add("3.1.26", Ric.as_str()); - } else if base.has_u_in(gana::KANDU_ADI) { + } else if base.has_gana(Kandvadi) { // kaNDUyati, ... // // "dvivadhāḥ kaṇḍvādayo, dhātavaḥ prātipādikāni ca. tatra dhātvadhikārād // dhātubhyaḥ eva pratyayo vidhīyate, na tu prātipadikebhyaḥ" // // -- KV on 3.1.27. + // + // We avoid `has_u_in` because it turns up too many false positives, e.g. "asu~" (asyati). sp.add("3.1.27", "yak"); } else if base.has_u_in(AYADAYA) { let mut can_add_pratyaya = true; diff --git a/vidyut-prakriya/src/stem_gana.rs b/vidyut-prakriya/src/stem_gana.rs index 51895f4..aecd26a 100644 --- a/vidyut-prakriya/src/stem_gana.rs +++ b/vidyut-prakriya/src/stem_gana.rs @@ -13,6 +13,13 @@ pub const LAUKIKA_SANKHYA: &[&str] = &[ "dvAdaSan", "trayodaSan", "zoqaSan", + "viMSati", + "triMSat", + "catvAriMSat", + "pAYcASat", + "zazwi", + "saptati", + "aSIti", "Sata", "sahasra", ]; diff --git a/vidyut-prakriya/src/stritva.rs b/vidyut-prakriya/src/stritva.rs index 9580385..7b74813 100644 --- a/vidyut-prakriya/src/stritva.rs +++ b/vidyut-prakriya/src/stritva.rs @@ -15,6 +15,7 @@ Generally, these pratyayas are of two types: */ use crate::core::errors::Error; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::Term; use crate::core::{Prakriya, Rule}; @@ -239,7 +240,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { sp.try_add("4.1.68", UN); } else if last.has_text("SvaSura") { // SvaSrUH - sp.try_add_with("4.1.68.v1", UN, |p| { + sp.try_add_with(Varttika("4.1.68.1"), UN, |p| { p.set(i_prati, |t| t.set_text("SvaSr")); }); } else if sp.p.is_chandasi() && last.has_text_in(&["kadru", "kamaRqalu"]) { @@ -270,7 +271,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { sp.try_add("4.1.5", NIp); } else if last.has_tag_in(&[T::udit, T::fdit, T::xdit]) { if last.is_dhatu() { - sp.block("4.1.6.v1"); + sp.block(Varttika("4.1.6.1")); } else { // BavatI, pacantI, ... sp.try_add("4.1.6", NIp); diff --git a/vidyut-prakriya/src/taddhita/matvartha_prakarana.rs b/vidyut-prakriya/src/taddhita/matvartha_prakarana.rs index 3fcf7eb..e0a30a5 100644 --- a/vidyut-prakriya/src/taddhita/matvartha_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/matvartha_prakarana.rs @@ -123,7 +123,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } // BrAtfvala, ... - tp.try_add(Varttika("5.2.112", "1"), valac); + tp.try_add(Varttika("5.2.112.1"), valac); let prati = tp.prati(); if prati.ends_with("as") || prati.has_text_in(&["mAyA", "meDA", "sraj"]) { diff --git a/vidyut-prakriya/src/taddhita/panchami_prakarana.rs b/vidyut-prakriya/src/taddhita/panchami_prakarana.rs index 8f14123..269e1e7 100644 --- a/vidyut-prakriya/src/taddhita/panchami_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/panchami_prakarana.rs @@ -1,6 +1,7 @@ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; @@ -153,7 +154,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.try_add("5.2.29", kawac); } else if prati.has_text_in(&["alAbU", "tila", "umA", "BaNgA"]) { // alAbUkawa, ... - tp.try_add("5.2.29.v1", kawac); + tp.try_add(Varttika("5.2.29.1"), kawac); } else if prati.has_text("ava") { // avakawa, ... let code = "5.2.30"; diff --git a/vidyut-prakriya/src/taddhita/pragdivyatiya.rs b/vidyut-prakriya/src/taddhita/pragdivyatiya.rs index ba1a346..a753434 100644 --- a/vidyut-prakriya/src/taddhita/pragdivyatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragdivyatiya.rs @@ -7,6 +7,7 @@ use crate::args::Taddhita; use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::ganapatha as gana; use crate::it_samjna; @@ -52,7 +53,7 @@ fn try_shaishika_rules(tp: &mut TaddhitaPrakriya, rule: &'static str) { let sub = if prati.has_text("rAzwra") { Ga } else { Ka }; tp.try_add("4.2.93", sub); } else if prati.has_text_in(&["avAra", "pAra", "pArAvara"]) { - tp.try_add("4.2.93.v1", Ka); + tp.try_add(Varttika("4.2.93.1"), Ka); } else if prati.has_text("grAma") { let code = "4.2.94"; tp.try_add(code, ya); @@ -339,11 +340,15 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } else if prati.has_text("kulawA") { tp.optional_try_add_with("4.1.127", Qak, |p| p.set(i_prati, |t| t.set_antya("in"))); } else if prati.has_text("cawakA") { + // cAwakEra tp.try_add("4.1.128", Erak); } else if prati.has_text("cawaka") { - tp.try_add("4.1.128.v1", Erak); + // cAwakEra + tp.try_add(Varttika("4.1.128.1"), Erak); } else if prati.has_text("goDA") { + // gODera tp.try_add("4.1.129", Qrak); + // gODAra tp.try_add("4.1.130", Arak); } else if prati.has_text("pitfzvasf") { tp.try_add("4.1.132", CaR); @@ -384,7 +389,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { p.set(i_prati, |t| t.set_antya("aka")); }); } else if prati.has_text_in(&["vyAsa", "varuqa", "nizAda", "caRqAla", "bimba"]) { - tp.try_add_with("4.1.97.v1", iY, |p| { + tp.try_add_with(Varttika("4.1.97.1"), iY, |p| { p.set(i_prati, |t| t.set_antya("aka")); }); } else if prati.has_antya('a') { @@ -504,7 +509,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { p.set(i_prati, |t| t.find_and_replace_text("ptAt", "ptf")) }); } else if prati.has_text("Satarudra") { - let code = "4.2.28.v2"; + let code = Varttika("4.2.28.2"); tp.try_add(code, Ga); tp.try_add(code, Ca); } else if prati.has_text("mahendra") { @@ -555,15 +560,15 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } tp.try_add("4.2.41", WaY); } else if prati.has_text("gaRikA") { - tp.try_add("4.2.40.v1", yaY); + tp.try_add(Varttika("4.2.40.1"), yaY); } else if prati.has_text_in(&["brAhmaRa", "mARava", "vAqava"]) { tp.try_add("4.2.42", yan); } else if prati.has_text("pfzWa") { - tp.try_add("4.2.42.v1", yan); + tp.try_add(Varttika("4.2.42.1"), yan); } else if prati.has_text_in(&["grAma", "jana", "banDu", "sahAya"]) { tp.try_add("4.2.43", tal); } else if prati.has_text("gaja") { - tp.try_add("4.2.43.v1", tal); + tp.try_add(Varttika("4.2.43.1"), tal); } else if prati.has_text_in(gana::KHANDIKA_ADI) { tp.try_add("4.2.45", aY); } else if true diff --git a/vidyut-prakriya/src/taddhita/pragvahatiya.rs b/vidyut-prakriya/src/taddhita/pragvahatiya.rs index 5405432..b9be7f9 100644 --- a/vidyut-prakriya/src/taddhita/pragvahatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragvahatiya.rs @@ -7,6 +7,7 @@ use crate::args::Taddhita; use crate::args::TaddhitaArtha::*; use crate::core::operators as op; use crate::core::Rule; +use crate::core::Rule::Varttika; use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; @@ -220,7 +221,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { if prati.has_text("Darma") { tp.try_add("4.4.41", P::Wak); } else if prati.has_text("aDarma") { - tp.try_add("4.4.41.v1", P::Wak); + tp.try_add(Varttika("4.4.41.1"), P::Wak); } }); @@ -269,7 +270,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } else if prati.has_antya('f') { tp.try_add("4.4.49", P::aY); } else if prati.has_text("nara") { - tp.try_add("4.4.49.v1", P::aY); + tp.try_add(Varttika("4.4.49.1"), P::aY); } else { tp.try_add("4.4.47", P::Wak); } diff --git a/vidyut-prakriya/src/taddhita/pragvatiya.rs b/vidyut-prakriya/src/taddhita/pragvatiya.rs index 4604085..df1cdbf 100644 --- a/vidyut-prakriya/src/taddhita/pragvatiya.rs +++ b/vidyut-prakriya/src/taddhita/pragvatiya.rs @@ -5,64 +5,100 @@ 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::core::operators as op; +use crate::core::{Rule, Term}; use crate::ganapatha as gana; +use crate::it_samjna; use crate::taddhita::utils::TaddhitaPrakriya; use crate::Rule::Varttika; -fn try_base_cases(tp: &mut TaddhitaPrakriya, _code: &'static str) { +fn try_base_cases(tp: &mut TaddhitaPrakriya, _code: impl Into) { use Taddhita as P; tp.try_add("5.1.18", P::WaY); } +fn is_parimana(t: &Term) -> bool { + t.has_text_in(&["prasTa", "kuqava"]) +} + +fn is_kala(t: &Term) -> bool { + t.has_text_in(&["mAsa", "arDamAsa", "saMvatsara", "ahan"]) +} + /// Overrides WaY (5.1.18) up to 5.1.63 inclusive. fn try_base_cases_arhiya(tp: &mut TaddhitaPrakriya, code: &'static str) { + tp.p.debug("try_base_cases_arhiya"); use Taddhita as P; let prati = tp.prati(); - if !prati.has_text("gopucCa") && !prati.is_sankhya() { - tp.try_add("5.1.19", P::Wak); - } else if prati.has_text_in(gana::NISHKA_ADI) && !prati.is_samasa() { + if prati.has_text_in(gana::NISHKA_ADI) && !prati.is_samasa() { + // nEzkika tp.try_add("5.1.20", P::Wak); - } else if prati.has_text("Sata") && !prati.is_samasa() { - // Satika, Satya - let code = "5.1.21"; - tp.try_add(code, P::Wan); - tp.try_add(code, P::yat); + } else if prati.has_text_in(&["SatamAna", "viMSatika", "sahasra", "vasana"]) { + tp.optional_try_add("5.1.27", P::aR); + } else if prati.is_sankhya() && !prati.has_suffix_in(&["ti", "Sat"]) { + if prati.has_text("Sata") && !prati.is_samasa() { + // Satika, Satya + let code = "5.1.21"; + tp.try_add(code, P::Wan); + tp.try_add(code, P::yat); + } else if prati.has_u("vatu~p") { + let i_prati = tp.i_prati; + // tAvatika + tp.optional_try_add_with("5.1.23", P::kan, |p| { + op::insert_agama_after(p, i_prati, "iw"); + it_samjna::run(p, i_prati + 1).expect("ok"); + }); + } + // Sataka + tp.try_add("5.1.22", P::kan); + } else if prati.has_text_in(&["viMSati", "triMSat"]) { + tp.try_add("5.1.24", P::qvun); } else if prati.has_text("kaMsa") { + // kaMsika tp.try_add("5.1.25", P::wiWan); } else if prati.has_text("SUrpa") { tp.optional_try_add("5.1.26", P::aY); - } else if prati.has_text_in(&["SatamAna", "viMSatika", "sahasra", "vasana"]) { - tp.optional_try_add("5.1.27", P::aR); - } else if prati.is_sankhya() && !prati.has_prefix_in(&["ti", "Sat"]) { - tp.try_add("5.1.22", P::kan); + } else if prati.has_text("KArI") { + // KArIka + tp.try_add(Varttika("5.1.33.1"), P::Ikan); + } else if prati.has_text_in(&["dviSARa", "triSARa"]) { + let code = "5.1.36"; + tp.try_add(code, P::yat); + tp.try_add(code, P::aR); + } else if !prati.has_text("gopucCa") && !prati.is_sankhya() && !is_parimana(prati) { + // Base case + tp.try_add("5.1.19", P::Wak); } - try_base_cases(tp, code); + if !tp.had_match { + try_base_cases(tp, code); + } } pub fn run(tp: &mut TaddhitaPrakriya) { use Taddhita::*; tp.with_context(TenaKritam, |tp| { + try_base_cases_arhiya(tp, "5.1.37"); + }); + + tp.with_context(TasyaNimittamSamyogotpattau, |tp| { let prati = tp.prati(); - if prati.has_tag(T::Sankhya) { - tp.try_add("5.1.22", kan); - } else if prati.has_text_in(&["viMSati", "triMSat"]) { - tp.try_add("5.1.24", qvun); - } else if prati.has_text("kaMsa") { - tp.try_add("5.1.25", wiWan); - } else if prati.has_text("SUrpA") { - tp.optional_try_add("5.1.26", aY); - } else if prati.has_text_in(&["SatamAna", "viMSatika", "sahasra", "vasana"]) { - tp.try_add("5.1.27", aR); - } else if prati.has_text_in(&["dviSARa", "triSARa"]) { - let code = "5.1.36"; + if prati.has_text("putra") { + // putrya, putrIya + let code = "5.1.40"; tp.try_add(code, yat); - tp.try_add(code, aR); + tp.try_add(code, Ca); + } else if prati.has_text_in(&["sarvaBUmi", "pfTivI"]) { + // sArvaBOma, pArTiva + let sub = if prati.has_text("sarvaBUmi") { aR } else { aY }; + tp.try_add("5.1.41", sub); } else { - try_base_cases_arhiya(tp, "5.1.37"); + if prati.has_text("sannipAta") { + tp.p.step(Varttika("5.1.38.2")); + } + try_base_cases_arhiya(tp, "5.1.38"); } }); @@ -108,7 +144,16 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(TadArhati, |tp| { let prati = tp.prati(); - if prati.has_text_in(gana::DANDA_ADI) { + if prati.has_text_in(gana::CHEDA_ADI) { + // CEdika, ... + try_base_cases_arhiya(tp, "5.1.64"); + } else if prati.has_text("SIrSacCeda") { + // SERSacCedika, SIrSacCedya + let code = "5.1.65"; + tp.try_add(code, yat); + try_base_cases_arhiya(tp, code); + } else if prati.has_text_in(gana::DANDA_ADI) { + // daRqya, ... tp.try_add("5.1.66", yat); } else if prati.has_text("pAtra") { let code = "5.1.68"; @@ -126,6 +171,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { let t = if prati.has_text("yajYa") { Ga } else { KaY }; tp.try_add("5.1.71", t); } else if tp.p.is_chandasi() { + // udakya, ... tp.try_add("5.1.67", yat); } else { try_base_cases_arhiya(tp, "5.1.63"); @@ -146,6 +192,20 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } }); + fn try_uttarapatha_rules(tp: &mut TaddhitaPrakriya) { + let prati = tp.prati(); + if prati.has_text("uttarapaTa") { + // OttarapaTika + try_base_cases(tp, "5.1.77"); + } else if prati.has_text_in(&["vAripaTa", "jaNgalapaTa", "sTalapaTa", "kAntArapaTa"]) { + // vAripaTika, ... + try_base_cases(tp, Varttika("5.1.77.1")); + } else if prati.has_text_in(&["ajapaTa", "SaNkupaTa"]) { + // AjapaTika, ... + try_base_cases(tp, Varttika("5.1.77.2")); + } + } + tp.with_context(Gacchati, |tp| { let i_prati = tp.i_prati; let prati = tp.prati(); @@ -154,13 +214,47 @@ pub fn run(tp: &mut TaddhitaPrakriya) { } else if prati.has_text("paTin") { tp.try_add("5.1.75", zkan); tp.try_add_with("5.1.76", Ra, |p| p.set(i_prati, |t| t.set_text("panTa"))); + } else { + try_uttarapatha_rules(tp); } }); tp.with_context(AbhigamanamArhati, |tp| { let prati = tp.prati(); if prati.has_text_in(&["kroSaSata", "yojanaSata"]) { - tp.try_add(Varttika("5.1.74", "1"), WaY); + tp.try_add(Varttika("5.1.74.1"), WaY); + } + }); + + if tp.prati().has_text("sTalapaTa") { + // sTAlapaTa + tp.try_add(Varttika("5.1.77.3"), aR); + } + + tp.with_context(Ahrtam, try_uttarapatha_rules); + + tp.with_context(TenaNirvrttam, |tp| { + if is_kala(tp.prati()) { + try_base_cases(tp, "5.1.79"); + } + }); + + tp.with_context(TamAdhisteBhrtoBhutoBhavi, |tp| { + let prati = tp.prati(); + if prati.has_text("samA") { + // samIna + tp.try_add("5.1.85", Ka); + } else if is_kala(prati) { + try_base_cases(tp, "5.1.80"); + } + }); + + tp.with_context(Vayasi, |tp| { + if tp.prati().has_text("mAsa") { + // mAsya, mAsIna + let code = "5.1.81"; + tp.try_add(code, yat); + tp.try_add(code, KaY); } }); diff --git a/vidyut-prakriya/src/taddhita/prakkritiya.rs b/vidyut-prakriya/src/taddhita/prakkritiya.rs index 19bc296..a677a7d 100644 --- a/vidyut-prakriya/src/taddhita/prakkritiya.rs +++ b/vidyut-prakriya/src/taddhita/prakkritiya.rs @@ -5,6 +5,7 @@ Implements the taddhita rules in the "prAk krItAc CaH" section of pada 5.1. */ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; +use crate::core::Rule::Varttika; use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; @@ -13,7 +14,7 @@ fn try_base_cases(tp: &mut TaddhitaPrakriya, _rule: &'static str) { let prati = tp.prati(); if prati.has_text("kambala") { tp.optional_try_add("5.1.3", yat); - } else if prati.has_text("havis") || prati.has_text_in(gana::APUPA_ADI) { + } else if prati.has_text_in(&["AmikzA", "puroqASa"]) || prati.has_text_in(gana::APUPA_ADI) { tp.optional_try_add("5.1.4", yat); } @@ -33,7 +34,13 @@ pub fn run(tp: &mut TaddhitaPrakriya) { tp.with_context(TasmaiHitam, |tp| { let prati = tp.prati(); - if prati.has_text_in(&["Kala", "yava", "mAza", "tila", "vfza", "brahman"]) { + if prati.has_text_in(&["danta", "kaRWa", "ozWa", "nABi", "nAsikA"]) { + // TODO: support the class, not just specific examples. + tp.try_add("5.1.6", yat); + if tp.prati().has_text("nAsikA") { + tp.p.run_at(Varttika("5.1.6.1"), tp.i_prati, |t| t.set_text("nas")); + } + } else if prati.has_text_in(&["Kala", "yava", "mAza", "tila", "vfza", "brahman"]) { tp.try_add("5.1.7", yat); } else if prati.has_text_in(&["aja", "avi"]) { tp.try_add("5.1.8", Tyan); diff --git a/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs b/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs index 87d1d14..8226c05 100644 --- a/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/samasanta_prakarana.rs @@ -5,6 +5,7 @@ Implements the taddhita rules in the "samAsAntAH" section of pada 5.4. */ use crate::args::Taddhita; use crate::args::Taddhita::*; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::{Prakriya, Rule}; use crate::ganapatha as gana; @@ -66,7 +67,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { add("5.4.78", p, ac); } else if purva.has_text_in(&["pallya", "rAjan"]) { // pallyavarcasa, ... - add("5.4.78.v1", p, ac); + add(Varttika("5.4.78.1"), p, ac); } } else if purva.has_text_in(&["ava", "sam", "anDa"]) && uttara.has_text("tamas") { // avatamasam, ... diff --git a/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs b/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs index f258d97..92e7561 100644 --- a/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs +++ b/vidyut-prakriya/src/taddhita/svarthika_prakarana.rs @@ -1,5 +1,6 @@ use crate::args::Taddhita::*; use crate::args::TaddhitaArtha::*; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::ganapatha as gana; use crate::taddhita::utils::TaddhitaPrakriya; @@ -83,7 +84,7 @@ pub fn run(tp: &mut TaddhitaPrakriya) { if prati.has_text_in(gana::STHULA_ADI) { tp.try_add("5.4.3", kan); } else if prati.has_text_in(&["caYcat", "bfhat"]) { - tp.try_add("5.4.3.v1", kan); + tp.try_add(Varttika("5.4.3.1"), kan); } else { // 5.4.3 is an apavAda to 5.3.69. tp.try_add("5.3.69", jAtIyar); diff --git a/vidyut-prakriya/src/taddhita/utils.rs b/vidyut-prakriya/src/taddhita/utils.rs index cbd287c..10435da 100644 --- a/vidyut-prakriya/src/taddhita/utils.rs +++ b/vidyut-prakriya/src/taddhita/utils.rs @@ -110,14 +110,12 @@ impl<'a> TaddhitaPrakriya<'a> { let rule = rule.into(); if cfg!(debug_assertions) { - /* self.p.debug(format!( "Try {}: {} + {:?}", rule.code(), &self.prati().text, taddhita, )); - */ } self.had_match = true; diff --git a/vidyut-prakriya/src/tripadi/pada_8_2.rs b/vidyut-prakriya/src/tripadi/pada_8_2.rs index ab3a909..23186fb 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_2.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_2.rs @@ -2,11 +2,12 @@ use crate::args::Gana; use crate::core::char_view::{get_at, get_term_and_offset_indices, CharPrakriya}; use crate::core::iterators::xy_rule; use crate::core::operators as op; +use crate::core::term::TermString; +use crate::core::Rule::Varttika; use crate::core::{Prakriya, Rule, Tag as T, Term}; use crate::dhatu_gana; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; -use compact_str::CompactString; use lazy_static::lazy_static; lazy_static! { @@ -66,11 +67,11 @@ fn try_na_lopa(p: &mut Prakriya) -> Option<()> { if p.has_tag(T::Napumsaka) { // "vA napuMsakAnAm" // (nAman, nAma) - blocked = p.optional_run("8.2.8.v1", |_| {}); + blocked = p.optional_run(Varttika("8.2.8.3"), |_| {}); } else if sup.has_u("Ni") && p.find_next_where(i_prati, |t| t.is_samasa()).is_some() { // carmatilaH, ... - p.step(Rule::Varttika("8.2.8", "1")); + p.step(Rule::Varttika("8.2.8.1")); } else { // sambuddhi: yogin, Atman // ni: vyoman, Sarman, etc. (vedic) @@ -80,7 +81,7 @@ fn try_na_lopa(p: &mut Prakriya) -> Option<()> { } let prati = p.get(i_prati)?; - if !blocked && !prati.is_upasarga() { + if !blocked && !prati.is_upasarga() && !prati.has_tag(T::FlagPratipadikaTiLopa) { // rAjA, rAjaByAm, ... // (these can be called `pada` by 1.4.17. // HACK to ignore upasargas for unnI, due to multiple passes of @@ -259,6 +260,10 @@ fn try_lopa_of_samyoganta_and_s(p: &mut Prakriya) { let mut num_hals = 0; if let Some((i_term, i_offset)) = get_term_and_offset_indices(p, i) { + if p.has(i_term, |t| t.has_tag(T::FlagPratipadikaTiLopa)) { + return false; + } + for i in i_term..p.terms().len() { let start = if i == i_term { i_offset } else { 0 }; let cur = p.get(i).expect("ok"); @@ -302,7 +307,10 @@ fn try_lopa_of_samyoganta_and_s(p: &mut Prakriya) { if p.is_pada(i) && p.has(i, |t| !t.is_empty()) { loop { let view = p.custom_view(0, i)?; - if view.last().has_tag(T::FlagAntyaAcSandhi) { + if view + .last() + .has_tag_in(&[T::FlagAntyaAcSandhi, T::FlagPratipadikaTiLopa]) + { // This term doesn't actually end in a final consonant, so it is not in scope. break; } @@ -350,15 +358,17 @@ fn try_ha_adesha(p: &mut Prakriya) -> Option<()> { }; if jhali_or_ante { - if is_dhatu { - let dhatu = p.get(i)?; - if dhatu.has_u_in(DRUHA_ADI) { + let dhatu = p.get(i)?; + // Explicitly check for `h` to bypass unAdi derivations like mUrKa, naKa, ... + if is_dhatu && dhatu.has_antya('h') { + if dhatu.has_u_in(DRUHA_ADI) && dhatu.has_antya('h') { + // drogDA, ... 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") { p.run_at("8.2.35", i, op::antya("T")); - } else if dhatu.has_adi('d') && dhatu.has_antya('h') { + } else if dhatu.has_adi('d') { p.run_at("8.2.32", i, op::antya("G")); } } @@ -436,6 +446,10 @@ fn per_term_1a(p: &mut Prakriya) -> Option<()> { } })?; + if x.has_tag_in(&[T::FlagPratipadikaTiLopa, T::FlagAntyaAcSandhi]) { + continue; + } + let is_ante = p.is_pada(i); let is_jhali = match p.find_next_where(i, |t| !t.is_empty()) { Some(j) => { @@ -500,14 +514,18 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { if c.is_none() { continue; } - let c = c.expect("ok"); + let t = c.expect("ok"); // 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) || is_sa_sajush(p, i); + let is_pada = p.is_pada(i) && !(t.is_upasarga() && !t.has_u("ud")); + let has_exception = t.has_antya(&*JHAL_TO_JASH_EXCEPTIONS) || is_sa_sajush(p, i); - if c.has_antya(&*JHAL) && !has_exception && is_pada && !c.has_tag(T::FlagAntyaAcSandhi) { - let key = c.antya()?; + if t.has_antya(&*JHAL) + && !has_exception + && is_pada + && !t.has_tag_in(&[T::FlagAntyaAcSandhi, T::FlagPratipadikaTiLopa]) + { + let key = t.antya()?; let sub = JHAL_TO_JASH.get(key)?; p.run_at("8.2.39", i, op::antya(&sub.to_string())); } @@ -834,7 +852,7 @@ fn try_lengthen_dhatu_vowel(p: &mut Prakriya) { let dhatu = &p.terms()[i]; let n = dhatu.len(); p.set(i, |t| { - t.text = CompactString::from(&t.text[..n - 3]) + &sub + &t.text[n - 2..] + t.text = TermString::from(&t.text[..n - 3]) + &sub + &t.text[n - 2..] }); }); } diff --git a/vidyut-prakriya/src/tripadi/pada_8_3.rs b/vidyut-prakriya/src/tripadi/pada_8_3.rs index 685c413..a894c0b 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_3.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_3.rs @@ -2,8 +2,9 @@ use crate::args::Gana; 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::Rule; +use crate::core::Rule::Varttika; use crate::core::Tag as T; use crate::core::Term; use crate::it_samjna; @@ -257,28 +258,28 @@ impl<'a> ShaPrakriya<'a> { } } - fn try_block(&mut self, rule: Code) { + fn try_block(&mut self, rule: impl Into) { if !self.done { self.p.step(rule); } self.done = true; } - fn try_shatva(&mut self, rule: Code) { + fn try_shatva(&mut self, rule: impl Into) { if !self.done { self.p.run(rule, |p| p.set_char_at(self.i_char, "z")); } self.done = true; } - fn try_run_with(&mut self, rule: Code, func: impl Fn(&mut Prakriya)) { + fn try_run_with(&mut self, rule: impl Into, func: impl Fn(&mut Prakriya)) { if !self.done { - self.p.run(rule, func); + self.p.run(rule.into(), func); } self.done = true; } - fn optional_try_shatva(&mut self, rule: Code) -> bool { + fn optional_try_shatva(&mut self, rule: impl Into) -> bool { if !self.done { let done = self .p @@ -358,7 +359,9 @@ fn run_shatva_rules_at_char_index(sp: &mut ShaPrakriya, text: &str) -> Option<() sp.try_run_with("8.3.118", |p| p.set(i_abhyasa, |t| t.set_adi("z"))); } else if t.has_u("zva\\nja~\\") && has_abhyasa { // parizasvaje, ... - sp.try_run_with("8.3.118.v1", |p| p.set(i_abhyasa, |t| t.set_adi("z"))); + sp.try_run_with(Varttika("8.3.118.1"), |p| { + p.set(i_abhyasa, |t| t.set_adi("z")) + }); } } @@ -406,7 +409,7 @@ fn run_shatva_rules_at_char_index(sp: &mut ShaPrakriya, text: &str) -> Option<() ("zwu\\Y", Adadi), ("zwuBu~\\", Bhvadi), ("zWA\\", Bhvadi), - // TODO: senaya -- but, not listed in our dhatupatha? + // TODO: senaya (senA + Ric) ("ziDa~", Bhvadi), ("ziDU~", Bhvadi), ("zi\\ca~^", Tudadi), @@ -520,7 +523,6 @@ fn run_shatva_rules_at_char_index(sp: &mut ShaPrakriya, text: &str) -> Option<() let term = sp.term(); if term.has_tag(T::FlagSaAdeshadi) && !abhyasa_vyavaya && !term.is_abhyasa() { sp.try_block("8.3.111"); - sp.p.dump(); } } diff --git a/vidyut-prakriya/src/tripadi/pada_8_4.rs b/vidyut-prakriya/src/tripadi/pada_8_4.rs index f9f816e..e02db6d 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_4.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_4.rs @@ -3,6 +3,7 @@ use crate::core::char_view::{ get_at, get_term_and_offset_indices, get_term_index_at, xy, xyz, CharPrakriya, }; use crate::core::operators as op; +use crate::core::Rule::Varttika; use crate::core::{Prakriya, Rule, Tag as T, Term}; use crate::sounds as al; use crate::sounds::{map, s, Map, Set}; @@ -147,10 +148,10 @@ fn try_natva_for_span(p: &mut Prakriya, text: &str, i_rs: usize, i_n: usize) -> } else if y.has_lakshana("lo~w") && y.has_u("ni") { if x.has_u("dur") { // TODO: extend - p.step("1.4.60.v3"); + p.step(Varttika("1.4.60.3")); } else if x.has_u("antar") { // TODO: extend - p.step("1.4.65.v1"); + p.step(Varttika("1.4.65.1")); } else { // pravapARi p.run("8.4.16", |p| p.set_char_at(i_n, "R")); diff --git a/vidyut-prakriya/src/uttarapade.rs b/vidyut-prakriya/src/uttarapade.rs index 1cd0397..cd29763 100644 --- a/vidyut-prakriya/src/uttarapade.rs +++ b/vidyut-prakriya/src/uttarapade.rs @@ -66,7 +66,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { p.add_tag_at("6.3.11", i_purva_sup, T::Aluk); } else if purva.has_text("anta") && uttara.has_text("guru") { // anteguru - p.add_tag_at("6.3.11.v1", i_purva_sup, T::Aluk); + p.add_tag_at(Varttika("6.3.11.1"), i_purva_sup, T::Aluk); } else if purva.has_text_in(&["prAvfz", "Sarad", "kAla", "div"]) && uttara.has_text("ja") { // prAvfzija, ... p.add_tag_at("6.3.15", i_purva_sup, T::Aluk); @@ -144,7 +144,7 @@ pub fn run(p: &mut Prakriya) -> Option<()> { // utsAhavala, ... // TODO: "putra" not part of the varttika, but then how do we derive // putravala? - p.step(Varttika("6.3.118", "1")); + p.step(Varttika("6.3.118.1")); } else { // AsutIvala, ... let antya = purva.antya()?; diff --git a/vidyut-prakriya/src/vikarana.rs b/vidyut-prakriya/src/vikarana.rs index 68f0178..285b802 100644 --- a/vidyut-prakriya/src/vikarana.rs +++ b/vidyut-prakriya/src/vikarana.rs @@ -19,9 +19,7 @@ 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::core::{Prakriya, Rule, Rule::Varttika, Tag as T, Term}; use crate::dhatu_gana::{DYUT_ADI, PUSH_ADI, TAN_ADI}; use crate::it_samjna; use crate::sounds::{s, Set}; @@ -80,7 +78,9 @@ 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.optional_run("3.1.44.v1", |p| op::upadesha_no_it(p, i + 1, "si~c")) { + if p.optional_run(Varttika("3.1.44.1"), |p| { + op::upadesha_no_it(p, i + 1, "si~c") + }) { return None; } } @@ -98,25 +98,30 @@ fn maybe_replace_cli_with_ksa(p: &mut Prakriya, i: usize) -> Option<()> { || t.has_tag(T::xdit) }; - let mut added = false; let dhatu = p.get(i)?; let to_ksa = replace_with(i + 1, "ksa"); - if dhatu.has_text("Sliz") && dhatu.has_gana(Divadi) { + let mut added = false; + let mut had_slish = false; + if dhatu.has_gana(Divadi) && dhatu.has_u("Sli\\za~") { // aSlizat, aSlikzat + // + // This blocks all other options below. added = p.optional_run("3.1.46", to_ksa); + had_slish = true; } let to_ksa = replace_with(i + 1, "ksa"); if !added && xyz(p, i, |x, _, z| { - pushadi_dyutadi_ldit(x) && z.has_tag(T::Parasmaipada) + z.has_tag(T::Parasmaipada) && pushadi_dyutadi_ldit(x) }) { // Takes priority over "Sala igupaDAt ..." (3.1.45) p.run("3.1.55", |p| op::upadesha_no_it(p, i + 1, "aN")); - } else if !added && p.has(i, shal_igupadha_anit) { + } else if !had_slish && p.has(i, shal_igupadha_anit) { let dhatu = p.get(i)?; if dhatu.has_text("dfS") { + // adrAkzIt, ... p.step("3.1.47") } else if dhatu.has_tag(T::Udit) { p.optional_run("3.1.45", |p| { @@ -149,7 +154,7 @@ fn maybe_replace_cli_with_can(p: &mut Prakriya, i: usize) -> Option<()> { p.run("3.1.48", to_can); } else if dhatu.has_u("kamu~\\") { // acIkamat - p.run("3.1.48.v1", to_can); + p.run(Varttika("3.1.48.1"), to_can); } else if dhatu.has_text_in(&["De", "Svi"]) { // adaDAt, aSiSviyat p.optional_run("3.1.49", to_can); @@ -283,7 +288,7 @@ fn add_kr_bhu_or_as_after_am_pratyaya(p: &mut Prakriya) { let mut ran = false; if !ran { // corayAmbaBUva, ... - ran = p.optional_run("3.1.40:BU", |p| { + ran = p.optional_run("3.1.40:1", |p| { let mut dhatu = Term::make_dhatu("BU", Bhvadi, None); dhatu.set_text("BU"); dhatu.add_tag(T::Dhatu); @@ -301,7 +306,7 @@ fn add_kr_bhu_or_as_after_am_pratyaya(p: &mut Prakriya) { } if !ran { // corayAmAsa, ... - ran = p.optional_run("3.1.40:as", |p| { + ran = p.optional_run("3.1.40:2", |p| { let mut dhatu = Term::make_dhatu("asa~", Adadi, None); dhatu.set_text("as"); dhatu.add_tag(T::Dhatu); @@ -342,15 +347,6 @@ pub fn try_add_am_pratyaya_for_lit(p: &mut Prakriya) -> Option<()> { if dhatu.has_text("kAs") || dhatu.is_pratyaya() { // kAsAYcakre; corayAYcakre p.run("3.1.35", add_aam); - } else if !dhatu.is_ekac() && !dhatu.has_text_in(&["jAgf", "UrRu"]) { - // jAgf is handled separately below. - p.run("3.1.35.v1", add_aam); - } else if dhatu.has_adi(&*IC) && dhatu.is_guru() && !dhatu.has_u("fCa~") { - // IkzAYcakre - p.run("3.1.36", add_aam); - } else if dhatu.has_text_in(&["day", "ay", "As"]) { - // dayAYcakre - 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.optional_run("3.1.38", add_aam); @@ -363,6 +359,20 @@ pub fn try_add_am_pratyaya_for_lit(p: &mut Prakriya) -> Option<()> { } else { return None; } + } else if dhatu.has_text("UrRu") { + p.step(Rule::Varttika("3.1.36.1")); + return None; + } else if !dhatu.is_ekac() { + if dhatu.has_u("daridrA") && p.optional_run(Rule::Kaumudi("2483"), |_| {}) { + return None; + } + p.run(Varttika("3.1.35.1"), add_aam); + } else if dhatu.has_adi(&*IC) && dhatu.is_guru() && !dhatu.has_u("fCa~") { + // IkzAYcakre + p.run("3.1.36", add_aam); + } else if dhatu.has_text_in(&["day", "ay", "As"]) { + // dayAYcakre + p.run("3.1.37", add_aam); } else if dhatu.has_text_in(&["BI", "hrI", "hu"]) || dhatu.has_u("quBf\\Y") { let add_sluvat_am = |p: &mut Prakriya| { let mut aam = Term::make_upadesha("Am"); diff --git a/vidyut-prakriya/src/wasm.rs b/vidyut-prakriya/src/wasm.rs index b7a52a9..333b8de 100644 --- a/vidyut-prakriya/src/wasm.rs +++ b/vidyut-prakriya/src/wasm.rs @@ -12,7 +12,7 @@ JavaScript callers can use them more idiomatically. */ use crate::args::*; use crate::core::Rule; -use crate::core::{Prakriya, Step}; +use crate::core::{Prakriya, Step, StepTerm}; use crate::dhatupatha::Dhatupatha; use serde::Serialize; extern crate console_error_panic_hook; @@ -27,15 +27,44 @@ extern "C" { fn error(s: &str); } +/// A rule that was applied in the derivation. +/// +/// We use this data to look up the rule's text in the frontend. +#[allow(non_snake_case)] +#[derive(Serialize)] +pub struct WebRule { + /// The source of this rule (sutrapatha, varttika, etc.) + source: String, + /// The (numeric) code that was applied for this step of the derivation. + code: String, +} + +/// A single term in the derivation history. +#[allow(non_snake_case)] +#[derive(Serialize)] +pub struct WebStepTerm { + /// The text in the term. + text: String, + /// Whether or not this term was changed from the previous step. + wasChanged: bool, +} + +impl From<&StepTerm> for WebStepTerm { + fn from(x: &StepTerm) -> Self { + Self { + text: x.text().to_string(), + wasChanged: x.was_changed(), + } + } +} + /// A lightweight `Step` that exposes fewer private fields than the native `Step` struct. #[derive(Serialize)] pub struct WebStep { - /// The rule that was applied for this step of the derivation. - rule: String, + /// The rule that created this step. + rule: WebRule, /// The result of applying the given rule. - result: Vec, - /// If defined, the index in `result` that was changed by `rule`. - active: Option, + result: Vec, } /// A lightweight `Prakriya` that exposes fewer private fields than the native `Prakriya` struct. @@ -48,19 +77,18 @@ pub struct WebPrakriya { } impl Rule { - /// Converts a `Rule` to a string suitable for web display. - /// - /// We return SLP1 strings, which the frontend will transliterate to the user's chosen script. - fn as_web_string(&self) -> String { + /// The text this rule comes from. + fn source(&self) -> &str { + use Rule::*; match self { - Self::Ashtadhyayi(s) => s.to_string(), - Self::Varttika(s, v) => format!("vArttika {s} ({v})"), - Self::Dhatupatha(s) => format!("DAtupAWa {s}"), - Self::Kashika(s) => format!("kASikA {s}"), - Self::Linganushasana(s) => format!("liNgA {s}"), - Self::Kaumudi(s) => format!("kOmudI {s}"), - Self::Unadipatha(s) => format!("uRAdi {s}"), - Self::Phit(s) => format!("Piw {s}"), + Ashtadhyayi(_) => "ashtadhyayi", + Varttika(_) => "varttika", + Dhatupatha(_) => "dhatupatha", + Kashika(_) => "kashika", + Linganushasana(_) => "linganushasanam", + Kaumudi(_) => "kaumudi", + Unadipatha(_) => "unadi", + Phit(_) => "phit", } } } @@ -69,10 +97,12 @@ impl Rule { fn to_web_history(history: &[Step]) -> Vec { history .iter() - .map(|x| WebStep { - rule: x.rule().as_web_string(), - result: x.result().clone(), - active: x.active(), + .map(|step| WebStep { + rule: WebRule { + source: step.rule().source().to_string(), + code: step.rule().code().to_string(), + }, + result: step.result().iter().map(|t| t.into()).collect(), }) .collect() } diff --git a/vidyut-prakriya/test_utils/src/lib.rs b/vidyut-prakriya/test_utils/src/lib.rs index 7a70fe6..94afd01 100644 --- a/vidyut-prakriya/test_utils/src/lib.rs +++ b/vidyut-prakriya/test_utils/src/lib.rs @@ -77,6 +77,21 @@ pub fn d_kutadi(u: &str, g: Gana) -> Dhatu { Dhatu::Mula(mula) } +pub fn d_akusmiya(u: &str, g: Gana) -> Dhatu { + let mula = Muladhatu::new(u, g).with_antargana(Antargana::Akusmiya); + Dhatu::Mula(mula) +} + +pub fn d_adhrshiya(u: &str, g: Gana) -> Dhatu { + let mula = Muladhatu::new(u, g).with_antargana(Antargana::Adhrshiya); + Dhatu::Mula(mula) +} + +pub fn d_ghatadi(u: &str, g: Gana) -> Dhatu { + let mula = Muladhatu::new(u, g).with_antargana(Antargana::Ghatadi); + Dhatu::Mula(mula) +} + pub fn san(dhatu: &Dhatu) -> Dhatu { dhatu.clone().with_sanadi(&[Sanadi::san]) } @@ -137,6 +152,19 @@ pub fn taddhitanta(prati: impl Into, taddhita: Taddhita) -> Taddhit .unwrap() } +pub fn artha_taddhitanta( + prati: impl Into, + artha: TaddhitaArtha, + taddhita: Taddhita, +) -> Taddhitanta { + Taddhitanta::builder() + .pratipadika(prati.into()) + .artha(artha) + .taddhita(taddhita) + .build() + .unwrap() +} + /// Shorthand for building a pratipadika that ends with NI/Ap. pub fn nyap(text: &str) -> Pratipadika { Pratipadika::nyap(text) @@ -942,10 +970,7 @@ fn derive_vakyas(first: &str, second: &str) -> Vec { // ------------------ /// Sanitizes our test results by making them deterministic and predictable. -fn sanitize_results(mut results: Vec) -> Vec { - results.sort_by_key(|p| p.text()); - results.dedup_by_key(|p| p.text()); - +fn sanitize_results(results: Vec) -> Vec { results .into_iter() .filter(|p| { @@ -958,7 +983,7 @@ fn sanitize_results(mut results: Vec) -> Vec { fn debug_text(rule: Rule) -> String { match rule { Rule::Ashtadhyayi(x) => x.to_string(), - Rule::Varttika(x, y) => format!("{x} v{y}"), + Rule::Varttika(x) => format!("vA {x}"), Rule::Dhatupatha(x) => format!("DA {x}"), Rule::Kashika(x) => format!("kA {x}"), Rule::Kaumudi(x) => format!("kO {x}"), @@ -973,14 +998,14 @@ pub fn print_all_prakriyas(prakriyas: &[Prakriya]) { for p in prakriyas { for step in p.history() { let mut result = String::new(); - for (i, text) in step.result().iter().enumerate() { + for (i, t) in step.result().iter().enumerate() { if i != 0 { result += " + "; } - if step.active() == Some(i) { - result += &format!("[{text}]"); + if t.was_changed() { + result += &format!("[{}]", t.text()); } else { - result += text; + result += t.text(); } } println!("{} --> {}", debug_text(step.rule()), result); @@ -1011,8 +1036,5 @@ pub fn assert_has_results(prakriyas: Vec, expected: &[&str]) { print_all_prakriyas(&prakriyas); } - assert_eq!( - actuals, expected, - "expected: {expected:#?}, actual: {actuals:#?}" - ); + assert_eq!(expected, actuals); } diff --git a/vidyut-prakriya/tests/kashika_1_1.rs b/vidyut-prakriya/tests/kashika_1_1.rs index 703e909..6f70ce3 100644 --- a/vidyut-prakriya/tests/kashika_1_1.rs +++ b/vidyut-prakriya/tests/kashika_1_1.rs @@ -112,7 +112,8 @@ fn sutra_1_1_5() { assert_has_tas(&[], &ci, Lat, &["cinutaH"]); assert_has_jhi(&[], &ci, Lat, &["cinvanti"]); assert_has_tinantas(&[], &mfj, Lat, P::Prathama, Dvi, &["mfzwaH"]); - assert_has_tinantas(&[], &mfj, Lat, P::Prathama, Bahu, &["mfjanti"]); + // mArjanti per SK. + assert_has_tinantas(&[], &mfj, Lat, P::Prathama, Bahu, &["mfjanti", "mArjanti"]); // git assert_has_krdanta(&[], &d("ji\\", Bhvadi), Krt::ksnu, &["jizRu"]); diff --git a/vidyut-prakriya/tests/kashika_1_3.rs b/vidyut-prakriya/tests/kashika_1_3.rs index 93defa2..1a315a4 100644 --- a/vidyut-prakriya/tests/kashika_1_3.rs +++ b/vidyut-prakriya/tests/kashika_1_3.rs @@ -303,6 +303,17 @@ fn sutra_1_3_31() { assert_has_lat(&["AN"], &han, &["Ahvayati", "Ahvayate"]); } +#[test] +fn sutra_1_3_33() { + assert_has_lit(&["aDi"], &d("qukf\\Y", Tanadi), &["aDicakre", "aDicakAra"]); + assert_has_lat(&["aDi"], &d("qukf\\Y", Tanadi), &["aDikaroti", "aDikurute"]); +} + +#[test] +fn sutra_1_3_34() { + assert_has_lat(&["vi"], &d("qukf\\Y", Tanadi), &["vikurute", "vikaroti"]); +} + #[test] fn sutra_1_3_38() { let kram = d("kramu~", Bhvadi); @@ -703,6 +714,32 @@ fn sutra_1_3_84_and_sutra_1_3_85() { assert_has_lat(&["upa"], &ram, &["uparamati", "uparamate"]); } +#[test] +fn sutra_1_3_86() { + assert_has_lat(&[], &nic(&d("bu\\Da~\\", Divadi)), &["boDayati"]); + assert_has_lat(&[], &nic(&d("yu\\Da~\\", Divadi)), &["yoDayati"]); + assert_has_lat(&[], &nic(&d("Ra\\Sa~", Divadi)), &["nASayati"]); + assert_has_lat(&[], &nic(&d("janI~\\", Divadi)), &["janayati"]); + assert_has_lat(&["aDi"], &nic(&d("i\\N", Adadi)), &["aDyApayati"]); + assert_has_lat(&[], &nic(&d("pru\\N", Bhvadi)), &["prAvayati"]); + assert_has_lat(&[], &nic(&d("dru\\", Bhvadi)), &["drAvayati"]); + assert_has_lat(&[], &nic(&d("sru\\", Bhvadi)), &["srAvayati"]); +} + +#[ignore] +#[test] +fn sutra_1_3_89() { + assert_has_lat(&[], &nic(&d("pA\\", Bhvadi)), &["pAyayate"]); + assert_has_lat(&[], &nic(&d("damu~", Divadi)), &["damayate"]); + assert_has_lat(&["AN"], &nic(&d("yama~", Bhvadi)), &["AyAmayate"]); + assert_has_lat(&["AN"], &nic(&d("yasu~", Divadi)), &["AyAsayate"]); + assert_has_lat(&["pari"], &nic(&d("mu\\ha~", Divadi)), &["parimohayate"]); + assert_has_lat(&[], &nic(&d("ruca~\\", Bhvadi)), &["rocayate"]); + assert_has_lat(&[], &nic(&d("nftI~", Divadi)), &["nartayate"]); + assert_has_lat(&[], &nic(&d("vada~", Bhvadi)), &["vAdayate"]); + assert_has_lat(&[], &nic(&d("va\\sa~", Bhvadi)), &["vAsayate"]); +} + #[test] fn sutra_1_3_90() { let kyas = |prati| Dhatu::nama(Pratipadika::basic(prati), None); diff --git a/vidyut-prakriya/tests/kashika_3_1.rs b/vidyut-prakriya/tests/kashika_3_1.rs index d3a2477..8ca2474 100644 --- a/vidyut-prakriya/tests/kashika_3_1.rs +++ b/vidyut-prakriya/tests/kashika_3_1.rs @@ -229,14 +229,13 @@ fn sutra_3_1_19() { assert_has_ta(&[], &nama("citra"), Lat, &["citrIyate"]); } -#[ignore] #[test] fn sutra_3_1_20() { let nama = |prati| Dhatu::nama(p(prati), None); assert_has_ta(&["ud"], &nama("pucCa"), Lat, &["utpucCayate"]); assert_has_ta(&["pari"], &nama("pucCa"), Lat, &["paripucCayate"]); assert_has_ta(&["sam"], &nama("BARqa"), Lat, &["samBARqayate"]); - assert_has_ta(&["sam"], &nama("cIvara"), Lat, &["saYcIvarayAte"]); + assert_has_ta(&["sam"], &nama("cIvara"), Lat, &["saYcIvarayate"]); } #[ignore] @@ -332,6 +331,12 @@ fn sutra_3_1_26() { // TODO: add others } +#[test] +fn sutra_3_1_27() { + let kandu = d("kaRqUY", Kandvadi); + assert_has_lat(&[], &kandu, &["kaRqUyati", "kaRqUyate"]); +} + #[test] fn sutra_3_1_28() { let pan = &d("paRa~\\", Bhvadi); @@ -394,6 +399,7 @@ fn sutra_3_1_35() { ); // TODO: amantre } + #[test] fn sutra_3_1_36() { assert_has_lit( diff --git a/vidyut-prakriya/tests/kashika_5_1.rs b/vidyut-prakriya/tests/kashika_5_1.rs index 55b2afb..230ee1e 100644 --- a/vidyut-prakriya/tests/kashika_5_1.rs +++ b/vidyut-prakriya/tests/kashika_5_1.rs @@ -34,6 +34,21 @@ fn sutra_5_1_3() { assert_has_artha_taddhita("kambala", TasmaiHitam, T::Ca, &["kambalIya"]); } +#[test] +fn sutra_5_1_4() { + assert_has_artha_taddhita("AmikzA", TasmaiHitam, T::yat, &["Amikzya"]); + assert_has_artha_taddhita("AmikzA", TasmaiHitam, T::Ca, &["AmikzIya"]); + + assert_has_artha_taddhita("puroqASa", TasmaiHitam, T::yat, &["puroqASya"]); + assert_has_artha_taddhita("puroqASa", TasmaiHitam, T::Ca, &["puroqASIya"]); + + assert_has_artha_taddhita("apUpa", TasmaiHitam, T::yat, &["apUpya"]); + assert_has_artha_taddhita("apUpa", TasmaiHitam, T::Ca, &["apUpIya"]); + + assert_has_artha_taddhita("taRqula", TasmaiHitam, T::yat, &["taRqulya"]); + assert_has_artha_taddhita("taRqula", TasmaiHitam, T::Ca, &["taRqulIya"]); +} + #[ignore] #[test] fn sutra_5_1_5() { @@ -46,6 +61,20 @@ fn sutra_5_1_5() { assert_has_artha_taddhita("apUpa", TasmaiHitam, T::Ca, &["apUpIya"]); } +#[test] +fn sutra_5_1_6() { + assert_has_artha_taddhita("danta", TasmaiHitam, T::yat, &["dantya"]); + assert_has_artha_taddhita("kaRWa", TasmaiHitam, T::yat, &["kaRWya"]); + assert_has_artha_taddhita("ozWa", TasmaiHitam, T::yat, &["ozWya"]); + assert_has_artha_taddhita("nABi", TasmaiHitam, T::yat, &["nABya"]); + assert_has_artha_taddhita("nAsikA", TasmaiHitam, T::yat, &["nasya"]); +} + +#[test] +fn sutra_5_1_6_v1() { + assert_has_artha_taddhita("nAsikA", TasmaiHitam, T::yat, &["nasya"]); +} + #[test] fn sutra_5_1_7() { assert_has_artha_taddhita("Kala", TasmaiHitam, T::yat, &["Kalya"]); @@ -122,6 +151,13 @@ fn sutra_5_1_15() { assert_blocked("varDrI", artha, T::Ca); } +#[test] +fn sutra_5_1_16() { + let artha = TadAsyaTadAsminSyat; + assert_has_artha_taddhita("prAkAra", artha, T::Ca, &["prAkArIya"]); + assert_has_artha_taddhita("prAsAda", artha, T::Ca, &["prAsAdIya"]); +} + #[test] fn sutra_5_1_17() { let artha = TadAsyaTadAsminSyat; @@ -137,6 +173,34 @@ fn sutra_5_1_18() { } #[ignore] +#[test] +fn sutra_5_1_19() { + assert_has_artha_taddhita("nizka", TenaKritam, T::Wak, &["nEzkika"]); + assert_has_artha_taddhita("paRa", TenaKritam, T::Wak, &["pARika"]); + + assert_has_artha_taddhita("gopucCa", TenaKritam, T::Wak, &[]); + assert_has_artha_taddhita("gopucCa", TenaKritam, T::WaY, &["gOpucCika"]); + assert_has_artha_taddhita("zazwi", TenaKritam, T::Wak, &[]); + assert_has_artha_taddhita("zazwi", TenaKritam, T::WaY, &["zAzwika"]); +} + +#[ignore] +#[test] +fn sutra_5_1_20() { + assert_has_artha_taddhita("nizka", TenaKritam, T::Wak, &["nEzkika"]); + assert_has_artha_taddhita("paRa", TenaKritam, T::Wak, &["pARika"]); + assert_has_artha_taddhita("pAda", TenaKritam, T::Wak, &["pAdika"]); + assert_has_artha_taddhita("mAza", TenaKritam, T::Wak, &["mAzika"]); + // TODO: others +} + +#[test] +fn sutra_5_1_21() { + assert_has_artha_taddhita("Sata", TenaKritam, T::Wan, &["Satika"]); + assert_has_artha_taddhita("Sata", TenaKritam, T::yat, &["Satya"]); + assert_has_artha_taddhita("Sata", TenaKritam, T::kan, &["Sataka"]); +} + #[test] fn sutra_5_1_22() { assert_has_taddhita("paYca", T::kan, &["paYcaka"]); @@ -147,6 +211,175 @@ fn sutra_5_1_22() { assert_has_taddhita("catvAriMSat", T::WaY, &["cAtvAriMSatka"]); } +#[test] +fn sutra_5_1_23() { + let tavat = artha_taddhitanta("tad", Parimana, T::vatup); + assert_has_artha_taddhita(&tavat, TenaKritam, T::kan, &["tAvatka", "tAvatika"]); + + let yavat = artha_taddhitanta("yad", Parimana, T::vatup); + assert_has_artha_taddhita(&yavat, TenaKritam, T::kan, &["yAvatka", "yAvatika"]); +} + +#[test] +fn sutra_5_1_25() { + assert_has_artha_taddhita("kaMsa", TenaKritam, T::wiWan, &["kaMsika"]); + assert_has_artha_taddhita("kaMsa", TenaKritam, T::WaY, &[]); +} + +#[test] +fn sutra_5_1_26() { + assert_has_artha_taddhita("SUrpa", TenaKritam, T::aY, &["SOrpa"]); + assert_has_artha_taddhita("SUrpa", TenaKritam, T::WaY, &["SOrpika"]); +} + +#[test] +fn sutra_5_1_27() { + assert_has_artha_taddhita("SatamAna", TenaKritam, T::aR, &["SAtamAna"]); + assert_has_artha_taddhita("viMSatika", TenaKritam, T::aR, &["vEMSatika"]); + assert_has_artha_taddhita("sahasra", TenaKritam, T::aR, &["sAhasra"]); + assert_has_artha_taddhita("vasana", TenaKritam, T::aR, &["vAsana"]); +} + +#[test] +fn sutra_5_1_37() { + let artha = TenaKritam; + assert_has_artha_taddhita("saptati", artha, T::WaY, &["sAptatika"]); + assert_has_artha_taddhita("aSIti", artha, T::WaY, &["ASItika"]); + assert_has_artha_taddhita("nizka", artha, T::Wak, &["nEzkika"]); + assert_has_artha_taddhita("paRa", artha, T::Wak, &["pARika"]); + assert_has_artha_taddhita("pAda", artha, T::Wak, &["pAdika"]); + assert_has_artha_taddhita("mAza", artha, T::Wak, &["mAzika"]); + assert_has_artha_taddhita("Sata", artha, T::yat, &["Satya"]); + assert_has_artha_taddhita("Sata", artha, T::Wan, &["Satika"]); + + assert_has_artha_taddhita("dvi", artha, T::kan, &["dvika"]); + assert_has_artha_taddhita("tri", artha, T::kan, &["trika"]); + assert_has_artha_taddhita("paYcan", artha, T::kan, &["paYcaka"]); + + assert_has_artha_taddhita("mudra", artha, T::Wak, &["mOdrika"]); +} + +#[test] +fn sutra_5_1_38() { + let artha = TasyaNimittamSamyogotpattau; + assert_has_artha_taddhita("Sata", artha, T::yat, &["Satya"]); + assert_has_artha_taddhita("Sata", artha, T::Wan, &["Satika"]); + assert_has_artha_taddhita("sahasra", artha, T::aR, &["sAhasra"]); +} + +#[test] +fn sutra_5_1_38_v2() { + let artha = TasyaNimittamSamyogotpattau; + assert_has_artha_taddhita("sannipAta", artha, T::Wak, &["sAnnipAtika"]); +} + +#[test] +fn sutra_5_1_40() { + let artha = TasyaNimittamSamyogotpattau; + assert_has_artha_taddhita("putra", artha, T::Ca, &["putrIya"]); + assert_has_artha_taddhita("putra", artha, T::yat, &["putrya"]); +} + +#[ignore] +#[test] +fn sutra_5_1_41() { + let artha = TasyaNimittamSamyogotpattau; + assert_has_artha_taddhita("sarvaBUmi", artha, T::aR, &["sArvaBOma"]); + assert_has_artha_taddhita("pfTivI", artha, T::aY, &["pArTiva"]); +} + +#[test] +fn sutra_5_1_45() { + let artha = TasyaVapa; + assert_has_artha_taddhita("prasTa", artha, T::WaY, &["prAsTika"]); + assert_has_artha_taddhita("droRa", artha, T::Wak, &["drORika"]); + assert_has_artha_taddhita("KArI", artha, T::Ikan, &["KArIka"]); +} + +#[test] +fn sutra_5_1_46() { + let artha = TasyaVapa; + let patrika = artha_taddhitanta("pAtra", artha, T::zWan); + assert_has_sup_1s(&patrika, Pum, &["pAtrikaH"]); + assert_has_sup_1s(&patrika, Stri, &["pAtrikI"]); +} + +#[test] +fn sutra_5_1_47() { + let artha = TadAsminVrddhiAyaLabhaSulkaUpada; + assert_has_artha_taddhita("paYcan", artha, T::kan, &["paYcaka"]); + assert_has_artha_taddhita("saptan", artha, T::kan, &["saptaka"]); + assert_has_artha_taddhita("Sata", artha, T::yat, &["Satya"]); + assert_has_artha_taddhita("Sata", artha, T::Wan, &["Satika"]); + assert_has_artha_taddhita("sahasra", artha, T::aR, &["sAhasra"]); +} + +#[test] +fn sutra_5_1_49() { + let artha = TadAsminVrddhiAyaLabhaSulkaUpada; + assert_has_artha_taddhita("BAga", artha, T::yat, &["BAgya"]); + assert_has_artha_taddhita("BAga", artha, T::Wan, &["BAgika"]); + assert_has_artha_taddhita("BAga", artha, T::WaY, &[]); +} + +#[ignore] +#[test] +fn sutra_5_1_50() { + let kd = |x, y| karmadharaya(x, y); + + let artha = TadDharatiVahatiAvahati; + assert_has_artha_taddhita(kd("vaMSa", "BAra"), artha, T::Wak, &["vAMSaBArika"]); + assert_has_artha_taddhita(kd("kuwaja", "BAra"), artha, T::Wak, &["kOwajaBArika"]); + assert_has_artha_taddhita(kd("balvaja", "BAra"), artha, T::Wak, &["bAlvajaBArika"]); + + assert_has_artha_taddhita(kd("vrIhi", "BAra"), artha, T::Wak, &[]); + + assert_has_artha_taddhita("vaMSa", artha, T::Wak, &["vAMSika"]); + assert_has_artha_taddhita("kuwaja", artha, T::Wak, &["kOwajika"]); + assert_has_artha_taddhita("balvaja", artha, T::Wak, &["bAlvajika"]); +} + +#[test] +fn sutra_5_1_51() { + let artha = TadDharatiVahatiAvahati; + assert_has_artha_taddhita("vasna", artha, T::Wan, &["vasnika"]); + assert_has_artha_taddhita("dravya", artha, T::kan, &["dravyaka"]); +} + +#[test] +fn sutra_5_1_52() { + let artha = SambhavatiAharatiPacati; + assert_has_artha_taddhita("prasTa", artha, T::WaY, &["prAsTika"]); + assert_has_artha_taddhita("kuqava", artha, T::WaY, &["kOqavika"]); + assert_has_artha_taddhita("KArI", artha, T::Ikan, &["KArIka"]); +} + +#[test] +fn sutra_5_1_53() { + let artha = SambhavatiAharatiPacati; + assert_has_artha_taddhita("AQaka", artha, T::Ka, &["AQakIna"]); + assert_has_artha_taddhita("AQaka", artha, T::Wak, &["AQakika"]); + + assert_has_artha_taddhita("Acita", artha, T::Ka, &["AcitIna"]); + assert_has_artha_taddhita("Acita", artha, T::Wak, &["Acitika"]); + + assert_has_artha_taddhita("pAtra", artha, T::Ka, &["pAtrIRa"]); + assert_has_artha_taddhita("pAtra", artha, T::Wak, &["pAtrika"]); +} + +#[ignore] +#[test] +fn sutra_5_1_57() { + let artha = TadAsyaParimanam; + assert_has_artha_taddhita("prasTa", artha, T::WaY, &["prAsTika"]); + + assert_has_artha_taddhita("Sata", artha, T::Wan, &["Satika"]); + assert_has_artha_taddhita("Sata", artha, T::yat, &["Satya"]); + assert_has_artha_taddhita("sahasra", artha, T::aR, &["sAhasra"]); + assert_has_artha_taddhita("droRa", artha, T::Wak, &["drORika"]); + assert_has_artha_taddhita("kuqava", artha, T::WaY, &["kOqavika"]); +} + #[test] fn sutra_5_1_63() { assert_has_artha_taddhita("SvetacCatra", TadArhati, T::Wak, &["SvEtacCatrika"]); @@ -156,6 +389,19 @@ fn sutra_5_1_63() { assert_has_artha_taddhita("sahasra", TadArhati, T::aR, &["sAhasra"]); } +#[test] +fn sutra_5_1_64() { + assert_has_artha_taddhita("Ceda", TadArhati, T::Wak, &["CEdika"]); + assert_has_artha_taddhita("Beda", TadArhati, T::Wak, &["BEdika"]); + assert_has_artha_taddhita("viraNg", TadArhati, T::Wak, &["vEraNgika"]); +} + +#[test] +fn sutra_5_1_65() { + assert_has_artha_taddhita("SIrSacCeda", TadArhati, T::Wak, &["SErSacCedika"]); + assert_has_artha_taddhita("SIrSacCeda", TadArhati, T::yat, &["SIrSacCedya"]); +} + #[test] fn sutra_5_1_66() { assert_has_artha_taddhita("daRqa", TadArhati, T::yat, &["daRqya"]); @@ -233,6 +479,78 @@ fn sutra_5_1_75() { assert_has_sup_1s(&pathika, Stri, &["paTikI"]); } +#[test] +fn sutra_5_1_76() { + assert_has_artha_taddhita("paTin", Gacchati, T::Ra, &["pAnTa"]); + // nityam? + assert_has_artha_taddhita("paTin", Gacchati, T::zkan, &["paTika"]); +} + +#[test] +fn sutra_5_1_77() { + assert_has_artha_taddhita("uttarapaTa", Gacchati, T::WaY, &["OttarapaTika"]); + assert_has_artha_taddhita("uttarapaTa", Ahrtam, T::WaY, &["OttarapaTika"]); +} + +#[test] +fn sutra_5_1_77_v1() { + assert_has_artha_taddhita("vAripaTa", Gacchati, T::WaY, &["vAripaTika"]); + assert_has_artha_taddhita("vAripaTa", Ahrtam, T::WaY, &["vAripaTika"]); + + assert_has_artha_taddhita("jaNgalapaTa", Gacchati, T::WaY, &["jANgalapaTika"]); + assert_has_artha_taddhita("jaNgalapaTa", Ahrtam, T::WaY, &["jANgalapaTika"]); + + assert_has_artha_taddhita("sTalapaTa", Gacchati, T::WaY, &["sTAlapaTika"]); + assert_has_artha_taddhita("sTalapaTa", Ahrtam, T::WaY, &["sTAlapaTika"]); + + assert_has_artha_taddhita("kAntArapaTa", Gacchati, T::WaY, &["kAntArapaTika"]); + assert_has_artha_taddhita("kAntArapaTa", Ahrtam, T::WaY, &["kAntArapaTika"]); +} + +#[test] +fn sutra_5_1_77_v2() { + assert_has_artha_taddhita("ajapaTa", Gacchati, T::WaY, &["AjapaTika"]); + assert_has_artha_taddhita("ajapaTa", Ahrtam, T::WaY, &["AjapaTika"]); + + assert_has_artha_taddhita("SaNkupaTa", Gacchati, T::WaY, &["SANkupaTika"]); + assert_has_artha_taddhita("SaNkupaTa", Ahrtam, T::WaY, &["SANkupaTika"]); +} + +#[test] +fn sutra_5_1_77_v3() { + assert_has_taddhita("sTalapaTa", T::aR, &["sTAlapaTa"]); +} + +#[test] +fn sutra_5_1_79() { + assert_has_artha_taddhita("mAsa", TenaNirvrttam, T::WaY, &["mAsika"]); + assert_has_artha_taddhita("arDamAsa", TenaNirvrttam, T::WaY, &["ArDamAsika"]); + assert_has_artha_taddhita("saMvatsara", TenaNirvrttam, T::WaY, &["sAMvatsarika"]); + assert_has_artha_taddhita("ahan", TenaNirvrttam, T::WaY, &["Ahnika"]); +} + +#[test] +fn sutra_5_1_80() { + let artha = TamAdhisteBhrtoBhutoBhavi; + assert_has_artha_taddhita("mAsa", artha, T::WaY, &["mAsika"]); +} + +#[test] +fn sutra_5_1_81() { + assert_has_artha_taddhita("mAsa", Vayasi, T::yat, &["mAsya"]); + assert_has_artha_taddhita("mAsa", Vayasi, T::KaY, &["mAsIna"]); + + // vayasi? + assert_has_artha_taddhita("mAsa", TenaNirvrttam, T::WaY, &["mAsika"]); +} + +#[test] +fn sutra_5_1_85() { + let artha = TamAdhisteBhrtoBhutoBhavi; + assert_has_artha_taddhita("samA", artha, T::Ka, &["samIna"]); + assert_blocked("samA", artha, T::WaY); +} + #[test] fn sutra_5_1_105() { assert_has_taddhita("ftu", T::aR, &["Artava"]); diff --git a/vidyut-prakriya/tests/kashika_6_4.rs b/vidyut-prakriya/tests/kashika_6_4.rs index 710b8f1..9449934 100644 --- a/vidyut-prakriya/tests/kashika_6_4.rs +++ b/vidyut-prakriya/tests/kashika_6_4.rs @@ -830,6 +830,7 @@ fn sutra_6_4_63() { // aci? assert_has_lat(&["upa"], &yan(&di), &["upadedIyate"]); + // kNiti? assert_has_krdanta(&["upa"], &di, Krt::lyuw, &["upadAna"]); } @@ -845,6 +846,15 @@ fn sutra_6_4_64() { assert_has_tas(&[], &stha, Lit, &["tasTatuH"]); assert_has_jhi(&[], &stha, Lit, &["tasTuH"]); + let daa = d("qudA\\Y", Juhotyadi); + assert_has_upapada_krdanta("go", &[], &daa, Krt::ka, &["goda"]); + assert_has_upapada_krdanta("kambala", &[], &daa, Krt::ka, &["kambalada"]); + + // Niti? + let dhaa = d("quDA\\Y", Juhotyadi); + assert_has_krdanta(&["pra"], &daa, Krt::aN, &["pradA"]); + assert_has_krdanta(&["pra"], &dhaa, Krt::aN, &["praDA"]); + // ArdhadhAtuke? assert_has_jhi(&[], &d("yA\\", Adadi), Lat, &["yAnti"]); assert_has_jhi(&[], &d("vA\\", Adadi), Lat, &["vAnti"]); @@ -852,8 +862,6 @@ fn sutra_6_4_64() { // aci assert_has_ta_k(&[], &d("glE\\", Bhvadi), Lat, &["glAyate"]); assert_has_iw(&[], &d("qudA\\Y", Juhotyadi), AshirLin, &["dAsIya"]); - - // TODO: others } #[test] @@ -1166,6 +1174,46 @@ fn sutra_6_4_85() { assert_has_sup_1p(&pratibhu, Stri, &["pratiBuvaH"]); } +#[test] +fn sutra_6_4_87() { + let hu = d("hu\\", Juhotyadi); + assert_has_jhi(&[], &hu, Lat, &["juhvati"]); + assert_has_jhi(&[], &hu, Lot, &["juhvatu"]); + assert_has_krdanta(&[], &hu, Krt::Satf, &["juhvat"]); + + let su = d("zu\\Y", Svadi); + assert_has_jhi(&[], &su, Lat, &["sunvanti"]); + assert_has_jhi(&[], &su, Lot, &["sunvantu"]); + assert_has_jhi(&[], &su, Lan, &["asunvan"]); + + // huSnuvoH? + assert_has_jhi(&[], &yan_luk(&d("yu", Adadi)), Lat, &["yoyuvati"]); + assert_has_jhi(&[], &yan_luk(&d("ru", Adadi)), Lat, &["roruvati"]); + + // sArvadhAtuke? + assert_has_tas( + &[], + &hu, + Lit, + &[ + "juhuvatuH", + "juhavAYcakratuH", + "juhavAmAsatuH", + "juhavAmbaBUvatuH", + ], + ); + assert_has_jhi( + &[], + &hu, + Lit, + &["juhuvuH", "juhavAYcakruH", "juhavAmAsuH", "juhavAmbaBUvuH"], + ); + + // asaMyogapUrvasya? + assert_has_jhi(&[], &d("A\\px~", Svadi), Lat, &["Apnuvanti"]); + assert_has_jhi(&[], &d("rA\\Da~", Svadi), Lat, &["rADnuvanti"]); +} + #[test] fn sutra_6_4_88() { let bhu = d("BU", Bhvadi); @@ -1200,8 +1248,9 @@ fn sutra_6_4_90_and_sutra_6_4_91() { #[test] fn sutra_6_4_92() { - assert_has_tip(&[], &nic(&d("Gawa~\\", Bhvadi)), Lat, &["Gawayati"]); - assert_has_tip(&[], &nic(&d("vyaTa~\\", Bhvadi)), Lat, &["vyaTayati"]); + let d_g = d_ghatadi; + assert_has_tip(&[], &nic(&d_g("Gawa~\\", Bhvadi)), Lat, &["Gawayati"]); + assert_has_tip(&[], &nic(&d_g("vyaTa~\\", Bhvadi)), Lat, &["vyaTayati"]); assert_has_tip(&[], &nic(&d("janI~\\", Divadi)), Lat, &["janayati"]); assert_has_tip( &[], @@ -1210,9 +1259,28 @@ fn sutra_6_4_92() { &["rajayati", "raYjayati"], ); - // TODO: not sure - // assert_has_tip(&[], &nic("Samu~", Bhvadi), Lat, &["Samayati"]); - // assert_has_tip(&[], &nic("", Bhvadi), Lat, &["jYapayati"]); + assert_has_tip(&[], &nic(&d("Samu~", Bhvadi)), Lat, &["Samayati"]); + assert_has_tip(&[], &d("jYapa~", Curadi), Lat, &["jYapayati"]); +} + +#[test] +fn sutra_6_4_93() { + let sham = d("Samu~", Bhvadi); + let tam = d("tamu~", Divadi); + assert_has_ta_k(&[], &nic(&sham), Lun, &["aSami", "aSAmi"]); + assert_has_ta_k(&[], &nic(&tam), Lun, &["atami", "atAmi"]); + + assert_has_krdanta(&[], &nic(&sham), Krt::Ramul, &["Samam", "SAmam"]); + assert_has_krdanta(&[], &nic(&tam), Krt::Ramul, &["tamam", "tAmam"]); + + let nic_nic = |d: &Dhatu| d.clone().with_sanadi(&[Sanadi::Ric, Sanadi::Ric]); + assert_has_krdanta(&[], &nic_nic(&sham), Krt::Satf, &["Samayat"]); + assert_has_ta_k(&[], &nic_nic(&sham), Lun, &["aSami", "aSAmi"]); + assert_has_krdanta(&[], &nic_nic(&sham), Krt::Ramul, &["Samam", "SAmam"]); + + assert_has_tip(&[], &yan_nic(&sham), Lat, &["SaMSamayati"]); + assert_has_ta_k(&[], &yan_nic(&sham), Lun, &["aSaMSami", "aSaMSAmi"]); + assert_has_krdanta(&[], &yan_nic(&sham), Krt::Ramul, &["SaMSamam", "SaMSAmam"]); } #[test] diff --git a/vidyut-prakriya/tests/kashika_7_1.rs b/vidyut-prakriya/tests/kashika_7_1.rs index d21ac7c..7f7bb9b 100644 --- a/vidyut-prakriya/tests/kashika_7_1.rs +++ b/vidyut-prakriya/tests/kashika_7_1.rs @@ -367,23 +367,24 @@ fn sutra_7_1_36() { #[ignore] #[test] fn sutra_7_1_37() { + use Krt::ktvA; let kf = d("qukf\\Y", Tanadi); let hf = d("hf\\Y", Bhvadi); - assert_has_krdanta(&["pra"], &kf, Krt::ktvA, &["prakftya"]); - assert_has_krdanta(&["pra"], &hf, Krt::ktvA, &["prahftya"]); + assert_has_krdanta(&["pra"], &kf, ktvA, &["prakftya"]); + assert_has_krdanta(&["pra"], &hf, ktvA, &["prahftya"]); assert_has_upapada_krdanta( Pratipadika::avyaya("pArSvataH"), &[], &kf, - Krt::ktvA, + ktvA, &["pArSvataHkftya"], ); - assert_has_krdanta(&["nAnA"], &kf, Krt::ktvA, &["nAnAkftya"]); - assert_has_krdanta(&["dviDA"], &kf, Krt::ktvA, &["dviDAkftya"]); + assert_has_krdanta(&["nAnA"], &kf, ktvA, &["nAnAkftya"]); + assert_has_krdanta(&["dviDA"], &kf, ktvA, &["dviDAkftya"]); // samAse - assert_has_krdanta(&[], &kf, Krt::ktvA, &["kftvA"]); - assert_has_krdanta(&[], &hf, Krt::ktvA, &["hftvA"]); + assert_has_krdanta(&[], &kf, ktvA, &["kftvA"]); + assert_has_krdanta(&[], &hf, ktvA, &["hftvA"]); // TODO: others } @@ -541,8 +542,9 @@ fn sutra_7_1_62() { assert_has_krdanta(&[], &radh, Krt::tavya, &["raDitavya", "radDavya"]); assert_has_krdanta(&[], &radh, Krt::lyuw, &["ranDana"]); assert_has_krdanta(&[], &radh, Krt::Rvul, &["ranDaka"]); - assert_has_vas(&[], &radh, Lit, &["raranDiva"]); - assert_has_mas(&[], &radh, Lit, &["raranDima"]); + // reDva, reDma by 7.2.45. + assert_has_vas(&[], &radh, Lit, &["raranDiva", "reDva"]); + assert_has_mas(&[], &radh, Lit, &["raranDima", "reDma"]); // TODO: redhivas (we get *redhvas instead) } diff --git a/vidyut-prakriya/tests/kashika_7_2.rs b/vidyut-prakriya/tests/kashika_7_2.rs index cc523e4..d62738f 100644 --- a/vidyut-prakriya/tests/kashika_7_2.rs +++ b/vidyut-prakriya/tests/kashika_7_2.rs @@ -1144,13 +1144,7 @@ fn sutra_7_2_65() { #[test] fn sutra_7_2_66() { - // TODO: check jaGasTa - assert_has_sip( - &[], - &d("a\\da~", Adadi), - Lit, - &["AdiTa", "jaGasiTa", "jaGasTa"], - ); + assert_has_sip(&[], &d("a\\da~", Adadi), Lit, &["AdiTa", "jaGasiTa"]); assert_has_sip(&[], &d("f\\", Bhvadi), Lit, &["AriTa"]); assert_has_sip(&[], &d("vye\\Y", Bhvadi), Lit, &["vivyayiTa"]); } @@ -1273,23 +1267,32 @@ fn sutra_7_2_76() { #[test] fn sutra_7_2_77() { - let is = d("ISa~\\", Adadi); - assert_has_tinantas( - &[], - &is, - Lakara::Lat, - Purusha::Madhyama, - Vacana::Eka, - &["ISize"], - ); - assert_has_tinantas( - &[], - &is, - Lakara::Lot, - Purusha::Madhyama, - Vacana::Eka, - &["ISizva"], - ); + let ish = d("ISa~\\", Adadi); + assert_has_thaas(&[], &ish, Lat, &["ISize"]); + assert_has_thaas(&[], &ish, Lot, &["ISizva"]); +} + +#[ignore] +#[test] +fn sutra_7_2_78() { + let id = d("Iqa~\\", Adadi); + assert_has_dhvam(&[], &id, Lat, &["IqiDve"]); + assert_has_dhvam(&[], &id, Lot, &["IqiDvam"]); + assert_has_thaas(&[], &id, Lat, &["Iqize"]); + assert_has_thaas(&[], &id, Lot, &["Iqizva"]); + + // TODO: let jan = d("janI~\\", Divadi); + + // HACK: force atmanepada by adding anudAttet. + let jan = d("jana~", Juhotyadi); + assert_has_thaas(&["vi", "ati"], &jan, Lat, &["vyatijajYize"]); + assert_has_thaas(&["vi", "ati"], &jan, Lot, &["vyatijajYizva"]); + assert_has_dhvam(&["vi", "ati"], &jan, Lat, &["vyatijajYiDve"]); + assert_has_dhvam(&["vi", "ati"], &jan, Lot, &["vyatijajYiDvam"]); + + let ish = d("ISa~\\", Adadi); + assert_has_dhvam(&[], &ish, Lat, &["ISiDve"]); + assert_has_dhvam(&[], &ish, Lot, &["ISiDvam"]); } #[test] diff --git a/vidyut-prakriya/tests/kashika_7_3.rs b/vidyut-prakriya/tests/kashika_7_3.rs index 82b8b38..46ec8af 100644 --- a/vidyut-prakriya/tests/kashika_7_3.rs +++ b/vidyut-prakriya/tests/kashika_7_3.rs @@ -239,19 +239,7 @@ fn sutra_7_3_50() { } #[test] -fn sutra_7_3_52() { - let pac = d("qupa\\ca~^z", Bhvadi); - assert_has_krdanta(&[], &pac, 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_krdanta(&[], &pac, Krt::Ryat, &["pAkya", "pAcya"]); - assert_has_krdanta(&[], &d("va\\ca~", Bhvadi), Krt::Ryat, &["vAkya", "vAcya"]); - assert_has_krdanta(&[], &d("ri\\ci~^r", Bhvadi), Krt::Ryat, &["rekya", "recya"]); -} - -#[test] -fn sutra_7_3_53() { +fn sutra_7_3_51() { // is assert_has_taddhita("sarpis", T::Wak, &["sArpizka"]); // us @@ -268,6 +256,18 @@ fn sutra_7_3_53() { assert_has_taddhita("yakft", T::Wak, &["yAkftka"]); } +#[test] +fn sutra_7_3_52() { + let pac = d("qupa\\ca~^z", Bhvadi); + assert_has_krdanta(&[], &pac, 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_krdanta(&[], &pac, Krt::Ryat, &["pAkya", "pAcya"]); + assert_has_krdanta(&[], &d("va\\ca~", Bhvadi), Krt::Ryat, &["vAkya", "vAcya"]); + assert_has_krdanta(&[], &d("ri\\ci~^r", Bhvadi), Krt::Ryat, &["rekya", "recya"]); +} + #[test] fn sutra_7_3_54() { let han = d("ha\\na~", Adadi); diff --git a/vidyut-prakriya/tests/kashika_7_4.rs b/vidyut-prakriya/tests/kashika_7_4.rs index 4aa1c73..f8f88e7 100644 --- a/vidyut-prakriya/tests/kashika_7_4.rs +++ b/vidyut-prakriya/tests/kashika_7_4.rs @@ -437,6 +437,18 @@ fn sutra_7_4_40() { assert_has_krdanta(&["ava"], &do_, Krt::tfc, &["avadAtf"]); } +#[test] +fn sutra_7_4_41() { + use Krt::{kta, ktavatu}; + let sho = d("So\\", Divadi); + assert_has_krdanta(&["ni"], &sho, kta, &["niSita", "niSAta"]); + assert_has_krdanta(&["ni"], &sho, ktavatu, &["niSitavat", "niSAtavat"]); + + let cho = d("Co\\", Divadi); + assert_has_krdanta(&["ava"], &cho, kta, &["avacCita", "avacCAta"]); + assert_has_krdanta(&["ava"], &cho, ktavatu, &["avacCitavat", "avacCAtavat"]); +} + #[test] fn sutra_7_4_42() { let dhaa = d("quDA\\Y", Juhotyadi); @@ -563,6 +575,7 @@ fn sutra_7_4_54() { assert_has_tip(&[], &san(&d("quDA\\Y", Juhotyadi)), Lat, &["Ditsati"]); assert_has_lat(&["AN"], &san(&d("ra\\Ba~\\", Bhvadi)), &["Aripsate"]); assert_has_lat(&["AN"], &san(&d("qula\\Ba~\\z", Bhvadi)), &["Alipsate"]); + // SiSakizati seems justified because Sa\\kx~ is optionally sew. assert_has_lat(&[], &san(&d("Sa\\kx~", Svadi)), &["Sikzati"]); assert_has_lat(&[], &san(&d("patx~", Bhvadi)), &["pitsati", "pipatizati"]); assert_has_lat(&["pra"], &san(&d("pa\\da~\\", Divadi)), &["prapitsate"]); @@ -586,6 +599,16 @@ fn sutra_7_4_55() { // si? -- see jijYapayizati and ardiDizati above. } +#[test] +fn sutra_7_4_56() { + assert_has_tip( + &[], + &san(&d("danBu~", Svadi)), + Lat, + &["Dipsati", "DIpsati", "didamBizati"], + ); +} + #[test] fn sutra_7_4_58() { let qauk = d("QOkf~\\", Bhvadi); diff --git a/vidyut-prakriya/tests/kashika_8_2.rs b/vidyut-prakriya/tests/kashika_8_2.rs index 70bd228..72fa903 100644 --- a/vidyut-prakriya/tests/kashika_8_2.rs +++ b/vidyut-prakriya/tests/kashika_8_2.rs @@ -690,21 +690,17 @@ fn sutra_8_2_55() { #[test] fn sutra_8_2_56() { - assert_has_krdanta(&[], &d("Ru\\da~^", Tudadi), Krt::kta, &["nunna", "nutta"]); - assert_has_krdanta(&[], &d("vi\\da~\\", Rudhadi), Krt::kta, &["vinna", "vitta"]); - assert_has_krdanta( - &["sam"], - &d("undI~", Rudhadi), - Krt::kta, - &["samunna", "samutta"], - ); - assert_has_krdanta(&[], &d("trE\\N", Bhvadi), Krt::kta, &["trARa", "trAta"]); - assert_has_krdanta(&[], &d("GrA\\", Bhvadi), Krt::kta, &["GrARa", "GrAta"]); - assert_has_krdanta(&[], &d("hrI\\", Juhotyadi), Krt::kta, &["hrIRa", "hrIta"]); + use Krt::kta; + assert_has_krdanta(&[], &d("Ru\\da~^", Tudadi), kta, &["nunna", "nutta"]); + assert_has_krdanta(&[], &d("vi\\da~\\", Rudhadi), kta, &["vinna", "vitta"]); + assert_has_krdanta(&["sam"], &d("undI~", Rudhadi), kta, &["samunna", "samutta"]); + assert_has_krdanta(&[], &d("trE\\N", Bhvadi), kta, &["trARa", "trAta"]); + assert_has_krdanta(&[], &d("GrA\\", Bhvadi), kta, &["GrARa", "GrAta"]); + assert_has_krdanta(&[], &d("hrI\\", Juhotyadi), kta, &["hrIRa", "hrIta"]); // only for vinatti - assert_has_krdanta(&[], &d("vida~", Adadi), Krt::kta, &["vidita"]); - assert_has_krdanta(&[], &d("vi\\da~\\", Divadi), Krt::kta, &["vinna"]); - assert_has_krdanta(&[], &d("vi\\dx~^", Tudadi), Krt::kta, &["vinna"]); + assert_has_krdanta(&[], &d("vida~", Adadi), kta, &["vidita"]); + assert_has_krdanta(&[], &d("vi\\da~\\", Divadi), kta, &["vinna"]); + assert_has_krdanta(&[], &d("vi\\dx~^", Tudadi), kta, &["vinna", "vidita"]); } #[test] diff --git a/vidyut-prakriya/tests/kaumudi_43.rs b/vidyut-prakriya/tests/kaumudi_43.rs index 3ac5b04..e7feabf 100644 --- a/vidyut-prakriya/tests/kaumudi_43.rs +++ b/vidyut-prakriya/tests/kaumudi_43.rs @@ -2766,7 +2766,6 @@ fn sk_2338() { assert_has_jhi(&[], &aksh, Lun, &["AkzizuH", "AkzuH"]); } -#[ignore] #[test] fn sk_2339() { let taksh = d("takzU~", Bhvadi); @@ -2808,7 +2807,7 @@ fn sk_2339() { let khash = d("Kaza~", Bhvadi); assert_has_tip(&[], &khash, Lit, &["caKAza"]); - let shish = d("Siza~", Bhvadi); + let shish = d("Si\\za~", Bhvadi); assert_has_tip(&[], &shish, Lit, &["SiSeza"]); assert_has_sip(&[], &shish, Lit, &["SiSeziTa"]); assert_has_tip(&[], &shish, Lut, &["SezwA"]); @@ -3164,7 +3163,7 @@ fn sk_2352() { assert_has_tip(&[], &klp, Lrn, &["akalpsyat"]); assert_has_ta(&[], &klp, Lrn, &["akalpizyata", "akalpsyata"]); - let ghatt = d("Gawa~\\", Bhvadi); + let ghatt = d_ghatadi("Gawa~\\", Bhvadi); assert_has_ta(&[], &ghatt, Lat, &["Gawate"]); assert_has_ta(&[], &ghatt, Lit, &["jaGawe"]); assert_has_tip(&[], &nic(&ghatt), Lat, &["Gawayati"]); @@ -3178,89 +3177,100 @@ fn sk_2352() { assert_has_ta(&[], &vyath, Lat, &["vyaTate"]); } -#[ignore] +// TODO: review carefully for missing forms. #[test] fn sk_2353() { - let vyath = d("vyaTa~\\", Bhvadi); + // The Kaumudi defines Gaw-Adi in a way that is inconsistent with dhatupatha.tsv. To allow + // these tests to function, explicitly mark dhatus as Gaw-Adi with `d_ghatadi`: + let d_g = d_ghatadi; + + let vyath = d_g("vyaTa~\\", Bhvadi); assert_has_ta(&[], &vyath, Lit, &["vivyaTe"]); - let prath = d("praTa~\\", Bhvadi); + let prath = d_g("praTa~\\", Bhvadi); assert_has_ta(&[], &prath, Lit, &["papraTe"]); - let pras = d("prasa~\\", Bhvadi); + let pras = d_g("prasa~\\", Bhvadi); assert_has_ta(&[], &pras, Lit, &["paprase"]); - // TODO: patch 6.4.93 to match on an-upadha for kzanj - let kshanj = d("kzaji~\\", Bhvadi); + let kshanj = d_g("kzaji~\\", Bhvadi); assert_has_ta_k(&[], &nic(&kshanj), Lun, &["akzaYji", "akzAYji"]); assert_has_krdanta(&[], &nic(&kshanj), Krt::Ramul, &["kzaYjam", "kzAYjam"]); - let jvar = d("jvara~", Bhvadi); + let jvar = d_g("jvara~", Bhvadi); assert_has_tip(&[], &jvar, Lat, &["jvarati"]); - let gad = d("gaqa~", Bhvadi); + let gad = d_g("gaqa~", Bhvadi); assert_has_tip(&[], &gad, Lat, &["gaqati"]); - let hed = d("heqa~", Bhvadi); + let hed = d_g("heqa~", Bhvadi); assert_has_tip(&[], &hed, Lat, &["heqati"]); assert_has_tip(&[], &hed, Lit, &["jiheqa"]); assert_has_tip(&[], &nic(&hed), Lat, &["hiqayati"]); - assert_has_ta_k(&[], &hed, Lun, &["ahiqi", "ahIqi"]); + assert_has_ta_k(&[], &nic(&hed), Lun, &["ahiqi", "ahIqi"]); - let hed_anadare = d("heqf~", Bhvadi); + // This dhatu is outside of ghaT-Adi, so it doesn't receive mittva. + let hed_anadare = d("heqf~\\", Bhvadi); assert_has_tip(&[], &nic(&hed_anadare), Lat, &["heqayati"]); - let stak = d("zwaka~", Bhvadi); + let stak = d_g("zwaka~", Bhvadi); assert_has_tip(&[], &stak, Lat, &["stakati"]); - let kakh = d("kaKe~", Bhvadi); + let kakh = d_g("kaKe~", Bhvadi); assert_has_tip(&[], &kakh, Lun, &["akaKIt"]); - let kan = d("kaRa~", Bhvadi); + let kan = d_g("kaRa~", Bhvadi); assert_has_tip(&[], &kan, Lit, &["cakARa"]); - let ran = d("raRa~", Bhvadi); + let ran = d_g("raRa~", Bhvadi); assert_has_tip(&[], &ran, Lit, &["rarARa"]); - let krath = d("kraTa~", Bhvadi); + let krath = d_g("kraTa~", Bhvadi); assert_has_tip(&[], &nic(&krath), Lat, &["krATayati"]); - assert_has_ta_k(&[], &krath, Lun, &["akraTi", "akrATi"]); - assert_has_krdanta(&[], &krath, Krt::Ramul, &["kraTam", "krATam"]); + assert_has_ta_k(&[], &nic(&krath), Lun, &["akraTi", "akrATi"]); + assert_has_krdanta(&[], &nic(&krath), Krt::Ramul, &["kraTam", "krATam"]); - let van = d("vana~", Bhvadi); + let van = d_g("vana~", Bhvadi); assert_has_tip(&["pra"], &nic(&van), Lat, &["pravanayati"]); - let jval = d("jvala~", Bhvadi); + let jval = d_g("jvala~", Bhvadi); assert_has_tip(&["pra"], &nic(&jval), Lat, &["prajvalayati"]); - let hval = d("hvala~", Bhvadi); + let hval = d_g("hvala~", Bhvadi); assert_has_tip(&["pra"], &nic(&hval), Lat, &["prahvalayati"]); - let hmal = d("hmala~", Bhvadi); + let hmal = d_g("hmala~", Bhvadi); assert_has_tip(&["pra"], &nic(&hmal), Lat, &["prahmalayati"]); - let dr = d("dF", Bhvadi); + let dr = d_g("dF", Bhvadi); assert_has_tip(&[], &nic(&dr), Lat, &["darayati"]); - let nr = d("nF", Bhvadi); + // nayAdanyatra nArayati -- but, in our dhatupatha, nF only ever has the meaning "naye"! As a + // quick HACK, check the nF outside of bhvAdi-gana. + let nr = d("nF", Kryadi); assert_has_tip(&[], &nic(&nr), Lat, &["nArayati"]); - let shra = d("SrA", Bhvadi); + let shra = d_g("SrA", Bhvadi); assert_has_tip(&[], &nic(&shra), Lat, &["Srapayati"]); - let cal = d("cala~", Bhvadi); + // pAkAd anyatra SrApayati -- but, in our dhatupatha, SrA only ever has the meaning "pAke"! As + // a quick HACK, check the SrA outside of bhvAdi-gana. + let shra_fake = d("SrA\\", Adadi); + assert_has_tip(&[], &nic(&shra_fake), Lat, &["SrApayati"]); + + let cal = d_g("cala~", Bhvadi); assert_has_tip(&[], &nic(&cal), Lat, &["calayati"]); - let chad = d("CadiH", Bhvadi); + let chad = d_g("CadiH", Bhvadi); assert_has_tip(&[], &nic(&chad), Lat, &["Cadayati"]); - let lad = d("laqa~", Bhvadi); + let lad = d_g("laqa~", Bhvadi); assert_has_tip(&[], &nic(&lad), Lat, &["laqayati"]); - let mad = d("madI~", Bhvadi); + let mad = d_g("madI~", Bhvadi); assert_has_tip(&[], &nic(&mad), Lat, &["madayati"]); - let dhvan = d("Dvana~", Bhvadi); + let dhvan = d_g("Dvana~", Bhvadi); assert_has_tip(&[], &nic(&dhvan), Lat, &["Dvanayati"]); let dal = d("dala~", Bhvadi); @@ -3278,35 +3288,54 @@ fn sk_2353() { let kshai = d("kzE\\", Bhvadi); assert_has_tip(&[], &nic(&kshai), Lat, &["kzapayati"]); - let svan = d("svana~", Bhvadi); + let svan = d_g("svana~", Bhvadi); assert_has_tip(&[], &nic(&svan), Lat, &["svanayati"]); - assert_has_tip(&[], &nic(&svan), Lat, &["jArayati"]); + let jr = d("jFz", Divadi); + assert_has_tip(&[], &nic(&jr), Lat, &["jarayati"]); + + let jrnati = d("jF", Kryadi); + assert_has_tip(&[], &nic(&jrnati), Lat, &["jArayati"]); - assert_has_tip(&[], &nic(&svan), Lat, &["jvalayati"]); - assert_has_tip(&[], &nic(&svan), Lat, &["jvAlayati"]); - assert_has_tip(&[], &nic(&svan), Lat, &["prajvalayati"]); + let jval = d_g("jvala~", Bhvadi); + assert_has_tip(&[], &nic(&jval), Lat, &["jvalayati", "jvAlayati"]); + assert_has_tip(&["pra"], &nic(&jval), Lat, &["prajvalayati"]); + + let kam = d("kamu~\\", Bhvadi); + assert_has_ta(&[], &kam, Lat, &["kAmayate"]); + + let am = d("ama~", Bhvadi); + assert_has_tip(&[], &nic(&am), Lat, &["Amayati"]); - assert_has_ta(&[], &nic(&svan), Lat, &["kAmayate"]); + let cam = d("camu~", Bhvadi); + assert_has_tip(&[], &nic(&cam), Lat, &["cAmayati"]); - assert_has_tip(&[], &nic(&svan), Lat, &["Amayati"]); + let sham = d_g("Samo~", Bhvadi); + assert_has_tip(&["ni"], &nic(&sham), Lat, &["niSAmayati", "niSamayati"]); + assert_has_krdanta(&["ni"], &nic(&sham), Krt::ktvA, &["niSAmya", "niSamayya"]); - assert_has_tip(&[], &nic(&svan), Lat, &["cAmayati"]); + let yam_pariveshane = d_g("yama~", Bhvadi); + assert_has_tip(&["AN"], &nic(&yam_pariveshane), Lat, &["AyAmayati"]); - let sham = d("Samo~", Bhvadi); - assert_has_tip(&["ni"], &nic(&sham), Lat, &["niSAmayati"]); + let yam_uparame = d_g("ya\\ma~", Bhvadi); + assert_has_tip(&[], &nic(&yam_uparame), Lat, &["yamayati"]); - assert_has_tip(&[], &nic(&sham), Lat, &["AyAmayati"]); + let skhad = d_g("sKadi~\\r", Bhvadi); + assert_has_tip(&["ava"], &nic(&skhad), Lat, &["avasKAdayati"]); + assert_has_tip(&["pari"], &nic(&skhad), Lat, &["parisKAdayati"]); - let skhad = d("sKadi~\\r", Bhvadi); - assert_has_tip(&["ava"], &skhad, Lat, &["avasKAdayati"]); - assert_has_tip(&["pari"], &skhad, Lat, &["parisKAdayati"]); + assert_has_tip( + &["apa"], + &nic(&skhad), + Lat, + &["apasKAdayati", "apasKadayati"], + ); } #[test] fn sk_2354() { // paPaRiTa is in KV 6.4.125. - let phan = d("PaRa~", Bhvadi); + let phan = d_ghatadi("PaRa~", Bhvadi); assert_has_tas(&[], &phan, Lit, &["PeRatuH", "paPaRatuH"]); assert_has_jhi(&[], &phan, Lit, &["PeRuH", "paPaRuH"]); assert_has_sip(&[], &phan, Lit, &["PeRiTa", "paPaRiTa"]); @@ -3868,7 +3897,6 @@ fn sk_2380() { assert_has_sip(&[], &svr, Lit, &["sasvariTa", "sasvarTa"]); } -#[ignore] #[test] fn sk_2381() { let svr = d("svf", Bhvadi); diff --git a/vidyut-prakriya/tests/kaumudi_44.rs b/vidyut-prakriya/tests/kaumudi_44.rs index 2e22bb2..15eb031 100644 --- a/vidyut-prakriya/tests/kaumudi_44.rs +++ b/vidyut-prakriya/tests/kaumudi_44.rs @@ -11,7 +11,6 @@ fn sk_2423() { assert_has_jhi(&[], &ad, Lat, &["adanti"]); } -#[ignore] #[test] fn sk_2424() { // AduH justified by KV 2.4.40. @@ -205,10 +204,29 @@ fn sk_2437() { ); } +#[test] +fn sk_2438() { + let caksh = d("ca\\kzi~\\N", Adadi); + assert_has_tip(&[], &caksh, Lun, &["aKyat", "akSAsIt"]); + assert_has_ta(&[], &caksh, Lun, &["aKyata", "akSAsta"]); + + let ir = d("Ira~\\", Adadi); + assert_has_ta(&[], &ir, Lat, &["Irte"]); + assert_has_ta(&[], &ir, Lit, &["IrAYcakre", "IrAmAsa", "IrAmbaBUva"]); + assert_has_ta(&[], &ir, Lut, &["IritA"]); + assert_has_ta(&[], &ir, Lrt, &["Irizyate"]); + assert_has_ta(&[], &ir, Lot, &["IrtAm"]); + assert_has_thaas(&[], &ir, Lot, &["Irzva"]); + assert_has_dhvam(&[], &ir, Lot, &["IrDvam"]); + assert_has_ta(&[], &ir, Lun, &["Erizwa"]); + + let id = d("Iqa~\\", Adadi); + assert_has_ta(&[], &id, Lat, &["Iwwe"]); +} + #[test] fn skip_sk_2439() {} -#[ignore] #[test] fn sk_2440() { let id = d("Iqa~\\", Adadi); @@ -522,7 +540,6 @@ fn sk_2456() { assert_has_tip(&[], &i, AshirLin, &["IyAt"]); } -#[ignore] #[test] fn sk_2457() { let i = d("i\\R", Adadi); @@ -530,7 +547,7 @@ fn sk_2457() { assert_has_tip(&["aBi"], &i, AshirLin, &["aBIyAt"]); assert_has_tip(&["sam", "AN"], &i, AshirLin, &["sameyAt"]); - assert_has_tip(&["sam"], &i, AshirLin, &["samIyAt"]); + assert_has_tip(&["sam"], &d("I", Bhvadi), AshirLin, &["samIyAt"]); } #[test] @@ -753,6 +770,15 @@ fn sk_2471() { } #[ignore] +#[test] +fn sk_2472() { + let as_ = d("asa~", Adadi); + assert_has_tip(&["prAdus"], &as_, VidhiLin, &["prAduHzyAt", "prAduzzyAt"]); + assert_has_jhi(&["ni"], &as_, Lat, &["nizanti"]); + assert_has_jhi(&["prAdus"], &as_, Lat, &["prAduHzanti", "prAduzzanti"]); + assert_has_tas(&["aBi"], &as_, Lat, &["aBistaH"]); +} + #[test] fn sk_2473() { let mrj = d("mfjU~", Adadi); @@ -761,9 +787,9 @@ fn sk_2473() { assert_has_jhi(&[], &mrj, Lat, &["mfjanti", "mArjanti"]); assert_has_tip(&[], &mrj, Lit, &["mamArja"]); assert_has_tas(&[], &mrj, Lit, &["mamArjatuH", "mamfjatuH"]); - assert_has_sip(&[], &mrj, Lat, &["mamArjiTa", "mamArzWa"]); + assert_has_sip(&[], &mrj, Lit, &["mamArjiTa", "mamArzWa"]); assert_has_tip(&[], &mrj, Lut, &["mArjitA", "mArzwA"]); - assert_has_tip(&[], &mrj, Lot, &["mfqQi", "mrzwAt"]); + assert_has_sip(&[], &mrj, Lot, &["mfqQi", "mfzwAt"]); assert_has_tip(&[], &mrj, Lan, &["amArw"]); assert_has_mip(&[], &mrj, Lan, &["amArjam"]); assert_has_tip(&[], &mrj, Lun, &["amArjIt", "amArkzIt"]); @@ -894,7 +920,6 @@ fn sk_2482() { assert_has_tas(&[], &daridra, Lat, &["daridritaH"]); } -#[ignore] #[test] fn sk_2483() { let daridra = d("daridrA", Adadi); @@ -904,23 +929,43 @@ fn sk_2483() { &[], &daridra, Lit, - &["daridrAYcakAra", "daridrAmbaBUva", "daridrAmAsa"], + &[ + "daridrAYcakAra", + "daridrAmbaBUva", + "daridrAmAsa", + "dadaridrO", + ], + ); + assert_has_tas( + &[], + &daridra, + Lit, + &[ + "daridrAYcakratuH", + "daridrAmbaBUvatuH", + "daridrAmAsatuH", + "dadaridratuH", + ], ); - assert_has_tip(&[], &daridra, Lit, &["dadaridrO"]); - assert_has_tas(&[], &daridra, Lit, &["dadaridratuH"]); assert_has_tip(&[], &daridra, Lut, &["daridritA"]); assert_has_tip(&[], &daridra, Lan, &["adaridrAt"]); assert_has_tas(&[], &daridra, Lan, &["adaridritAm"]); assert_has_jhi(&[], &daridra, Lan, &["adaridruH"]); assert_has_tip(&[], &daridra, VidhiLin, &["daridriyAt"]); assert_has_tip(&[], &daridra, AshirLin, &["daridryAt"]); - assert_has_tip(&[], &daridra, Lun, &["adiridrIt", "adaridrAsIt"]); + assert_has_tip(&[], &daridra, Lun, &["adaridrIt", "adaridrAsIt"]); let cakas = d("cakAsf~", Adadi); assert_has_tip(&[], &cakas, Lat, &["cakAsti"]); - assert_has_tip(&[], &cakas, Lat, &["cakAsati"]); - assert_has_tip(&[], &cakas, Lat, &["cakAsAMcakAra"]); - assert_has_tip(&[], &cakas, Lat, &["cakAdDi"]); + assert_has_jhi(&[], &cakas, Lat, &["cakAsati"]); + assert_has_tip( + &[], + &cakas, + Lit, + &["cakAsAYcakAra", "cakAsAmAsa", "cakAsAmbaBUva"], + ); + // We can't support cakAdDi per "sica evetyeke" because this blocks "tAs + Dve -> tADve". + assert_has_sip(&[], &cakas, Lot, &["cakADi", "cakAstAt"]); } #[test] diff --git a/vidyut-prakriya/tests/kaumudi_45.rs b/vidyut-prakriya/tests/kaumudi_45.rs index 559e14d..ca7bbb4 100644 --- a/vidyut-prakriya/tests/kaumudi_45.rs +++ b/vidyut-prakriya/tests/kaumudi_45.rs @@ -75,7 +75,6 @@ fn sk_2494() { assert_has_tip(&[], &pr, Lit, &["papAra"]); } -#[ignore] #[test] fn sk_2495() { let prr = d("pF", Juhotyadi); @@ -90,7 +89,7 @@ fn sk_2495() { assert_has_tip(&[], &prr, Lun, &["apArIt"]); assert_has_tas(&[], &prr, Lun, &["apArizwAm"]); - let pr = d("pf", Juhotyadi); + let pr = d("pf\\", Juhotyadi); assert_has_tip(&[], &pr, Lat, &["piparti"]); assert_has_tas(&[], &pr, Lat, &["pipftaH"]); assert_has_jhi(&[], &pr, Lat, &["piprati"]); diff --git a/vidyut-prakriya/tests/kaumudi_46.rs b/vidyut-prakriya/tests/kaumudi_46.rs index 9b0cee1..f2b3a43 100644 --- a/vidyut-prakriya/tests/kaumudi_46.rs +++ b/vidyut-prakriya/tests/kaumudi_46.rs @@ -20,8 +20,7 @@ fn sk_2505() { let siv = d("zivu~", Divadi); assert_has_tip(&["pari"], &siv, Lat, &["parizIvyati"]); - // TODO: is parisizeva allowed? - assert_has_tip(&["pari"], &siv, Lit, &["parizizeva", "parisizeva"]); + assert_has_tip(&["pari"], &siv, Lit, &["parizizeva"]); assert_has_tip(&["ni"], &siv, Lun, &["nyazevIt", "nyasevIt"]); let snus = d("zRusu~", Divadi); @@ -43,7 +42,6 @@ fn sk_2505() { assert_has_tip(&[], &nrt, Lit, &["nanarta"]); } -#[ignore] #[test] fn sk_2506() { let nrt = d("nftI~", Divadi); @@ -403,49 +401,58 @@ fn sk_2513() { assert_has_tip(&[], &shlish, Lrt, &["Slekzyati"]); } -#[ignore] #[test] fn sk_2514() { - let x = d("Sli\\za~", Divadi); - // TODO: samAslikzat - assert_has_ta_k(&[], &x, Lun, &["aSlezi"]); - assert_has_aataam(&[], &x, Lun, &["aSlikzAtAm"]); - assert_has_jha(&[], &x, Lun, &["aSlikzata"]); - assert_has_thaas(&[], &x, Lun, &["aSlizWAH"]); - assert_has_dhvam(&[], &x, Lun, &["aSliQvam"]); - - assert_has_tip(&[], &x, Lat, &["Sakyati"]); - assert_has_tip(&[], &x, Lat, &["SaSAka"]); - assert_has_tip(&[], &x, Lat, &["SekiTa"]); - assert_has_tip(&[], &x, Lat, &["SaSakTa"]); - assert_has_ta(&[], &x, Lit, &["Seke"]); - assert_has_tip(&[], &x, Lut, &["SaktA"]); - assert_has_tip(&[], &x, Lrt, &["Sakzyati"]); - assert_has_ta(&[], &x, Lrt, &["Sakzyate"]); - assert_has_tip(&[], &x, Lat, &["aSakat"]); - assert_has_tip(&[], &x, Lat, &["aSakta"]); - assert_has_tip(&[], &x, Lut, &["SakitA"]); - assert_has_tip(&[], &x, Lrt, &["Sakizyati"]); - assert_has_tip(&[], &x, Lat, &["svidyati"]); - assert_has_tip(&[], &x, Lat, &["sizveda"]); - assert_has_tip(&[], &x, Lat, &["sizvediTa"]); - assert_has_tip(&[], &x, Lut, &["svettA"]); - assert_has_tip(&[], &x, Lat, &["asvidat"]); - assert_has_tip(&[], &x, Lut, &["krodDA"]); - assert_has_tip(&[], &x, Lrt, &["krotsyati"]); - assert_has_tip(&[], &x, Lut, &["kzodDA"]); - assert_has_tip(&[], &x, Lat, &["SuDyati"]); - assert_has_tip(&[], &x, Lat, &["SuSoDa"]); - assert_has_tip(&[], &x, Lut, &["SodDA"]); - assert_has_tip(&[], &x, Lat, &["siDyati"]); - assert_has_tip(&[], &x, Lut, &["sedDA"]); - assert_has_tip(&[], &x, Lrt, &["setsyati"]); - assert_has_tip(&[], &x, Lat, &["asiDat"]); - assert_has_tip(&[], &x, Lat, &["raDyati"]); - assert_has_tas(&[], &x, Lit, &["raranDatuH"]); + let shlish = d("Sli\\za~", Divadi); + assert_has_tip(&[], &shlish, Lun, &["aSlikzat", "aSlizat"]); + assert_has_tip(&["sam", "AN"], &shlish, Lun, &["samASlizat", "samASlikzat"]); + assert_has_ta_k(&[], &shlish, Lun, &["aSlezi"]); + assert_has_aataam_k(&[], &shlish, Lun, &["aSlikzAtAm"]); + assert_has_jha_k(&[], &shlish, Lun, &["aSlikzata", "aSlikzanta"]); + assert_has_thaas_k(&[], &shlish, Lun, &["aSlizWAH", "aSlikzaTAH"]); + assert_has_dhvam_k(&[], &shlish, Lun, &["aSliqQvam", "aSlikzaDvam"]); + + let shak = d("Sa\\ka~^", Divadi); + assert_has_tip(&[], &shak, Lat, &["Sakyati"]); + assert_has_tip(&[], &shak, Lit, &["SaSAka"]); + assert_has_sip(&[], &shak, Lit, &["SekiTa", "SaSakTa"]); + assert_has_ta(&[], &shak, Lit, &["Seke"]); + assert_has_tip(&[], &shak, Lut, &["SaktA", "SakitA"]); + assert_has_tip(&[], &shak, Lrt, &["Sakzyati", "Sakizyati"]); + assert_has_ta(&[], &shak, Lrt, &["Sakzyate", "Sakizyate"]); + assert_has_tip(&[], &shak, Lun, &["aSakat"]); + assert_has_ta(&[], &shak, Lun, &["aSakta", "aSakizwa"]); + + let svid = d("zvi\\dA~", Divadi); + assert_has_tip(&[], &svid, Lat, &["svidyati"]); + assert_has_tip(&[], &svid, Lit, &["sizveda"]); + assert_has_sip(&[], &svid, Lit, &["sizvediTa"]); + assert_has_tip(&[], &svid, Lut, &["svettA"]); + assert_has_tip(&[], &svid, Lun, &["asvidat"]); + + let krudh = d("kru\\Da~", Divadi); + assert_has_tip(&[], &krudh, Lut, &["krodDA"]); + assert_has_tip(&[], &krudh, Lrt, &["krotsyati"]); + + let kshudh = d("kzu\\Da~", Divadi); + assert_has_tip(&[], &kshudh, Lut, &["kzodDA"]); + + let shudh = d("Su\\Da~", Divadi); + assert_has_tip(&[], &shudh, Lat, &["SuDyati"]); + assert_has_tip(&[], &shudh, Lit, &["SuSoDa"]); + assert_has_tip(&[], &shudh, Lut, &["SodDA"]); + + let sidh = d("zi\\Du~", Divadi); + assert_has_tip(&[], &sidh, Lat, &["siDyati"]); + assert_has_tip(&[], &sidh, Lut, &["sedDA"]); + assert_has_tip(&[], &sidh, Lrt, &["setsyati"]); + assert_has_tip(&[], &sidh, Lun, &["asiDat"]); + + let radh = d("ra\\Da~", Divadi); + assert_has_tip(&[], &radh, Lat, &["raDyati"]); + assert_has_tas(&[], &radh, Lit, &["raranDatuH"]); } -#[ignore] #[test] fn sk_2515() { let radh = d("ra\\Da~", Divadi); @@ -466,10 +473,9 @@ fn sk_2516() { assert_has_tip(&[], &nash, Lit, &["nanASa"]); assert_has_tas(&[], &nash, Lit, &["neSatuH"]); // nanaMzWa is from SK 2517. - assert_has_sip(&[], &nash, Lat, &["neSiTa", "nanaMzWa"]); + assert_has_sip(&[], &nash, Lit, &["neSiTa", "nanaMzWa"]); } -#[ignore] #[test] fn sk_2517() { let nash = d("Ra\\Sa~", Divadi); @@ -484,6 +490,97 @@ fn sk_2517() { assert_has_tip(&["pra"], &nash, Lat, &["praRaSyati"]); } +#[test] +fn sk_2518() { + let nash = d("Ra\\Sa~", Divadi); + assert_has_tip(&["pra"], &nash, Lut, &["praRaSitA", "pranaMzwA"]); + assert_has_tip(&["pra"], &nash, Lrt, &["pranaNkzyati", "praRaSizyati"]); + + let trp = d("tf\\pa~", Divadi); + assert_has_sip(&[], &trp, Lit, &["tatarpiTa", "tatrapTa", "tatarpTa"]); + assert_has_tip(&[], &trp, Lut, &["tarpitA", "tarptA", "traptA"]); + assert_has_tip( + &[], + &trp, + Lun, + &["atArpsIt", "atrApsIt", "atarpIt", "atfpat"], + ); + + let druh = d("dru\\ha~", Divadi); + assert_has_sip(&[], &druh, Lit, &["dudrogDa", "dudroQa", "dudrohiTa"]); + assert_has_tip(&[], &druh, Lut, &["drohitA", "drogDA", "droQA"]); + assert_has_tip(&[], &druh, Lrt, &["drohizyati", "Drokzyati"]); + assert_has_tip(&[], &druh, Lun, &["adruhat"]); + + let muh = d("mu\\ha~", Divadi); + assert_has_tip(&[], &muh, Lat, &["muhyati"]); + assert_has_sip(&[], &muh, Lit, &["mumohiTa", "mumogDa", "mumoQa"]); + assert_has_tip(&[], &muh, Lut, &["mogDA", "moQA", "mohitA"]); + assert_has_tip(&[], &muh, Lrt, &["mohizyati", "mokzyati"]); + assert_has_tip(&[], &muh, Lun, &["amuhat"]); + + let snuh = d("zRu\\ha~", Divadi); + assert_has_tip(&[], &snuh, Lat, &["snuhyati"]); + assert_has_tip(&[], &snuh, Lit, &["suzRoha"]); + assert_has_sip(&[], &snuh, Lit, &["suzRohiTa", "suzRogDa", "suzRoQa"]); + assert_has_vas(&[], &snuh, Lit, &["suzRuhiva", "suzRuhva"]); + assert_has_tip(&[], &snuh, Lut, &["snohitA", "snogDA", "snoQA"]); + assert_has_tip(&[], &snuh, Lrt, &["snohizyati", "snokzyati"]); + assert_has_tip(&[], &snuh, Lun, &["asnuhat"]); + + let snih = d("zRi\\ha~", Divadi); + assert_has_tip(&[], &snih, Lat, &["snihyati"]); + assert_has_tip(&[], &snih, Lit, &["sizReha"]); +} + +#[test] +fn sk_2519() { + let sham = d("Samu~", Divadi); + assert_has_tas(&[], &sham, Lit, &["SematuH"]); + assert_has_sip(&[], &sham, Lit, &["SemiTa"]); + assert_has_tip(&[], &sham, Lut, &["SamitA"]); + assert_has_tip(&[], &sham, Lun, &["aSamat"]); + + let tam = d("tamu~", Divadi); + assert_has_tip(&[], &tam, Lat, &["tAmyati"]); + assert_has_tip(&[], &tam, Lut, &["tamitA"]); + assert_has_tip(&[], &tam, Lun, &["atamat"]); + + let dam = d("damu~", Divadi); + assert_has_tip(&[], &dam, Lun, &["adamat"]); + + let shram = d("Sramu~", Divadi); + assert_has_tip(&[], &shram, Lat, &["SrAmyati"]); + assert_has_tip(&[], &shram, Lun, &["aSramat"]); + + // Bramati from KV, etc. + let bhram = d("Bramu~", Divadi); + assert_has_tip(&[], &bhram, Lat, &["BrAmyati", "Bramati"]); + assert_has_tip(&[], &bhram, Lun, &["aBramat"]); + + let ksham = d("kzamU~", Divadi); + assert_has_tip(&[], &ksham, Lat, &["kzAmyati"]); + assert_has_sip(&[], &ksham, Lit, &["cakzamiTa", "cakzanTa"]); + assert_has_vas(&[], &ksham, Lit, &["cakzamiva", "cakzaRva"]); + assert_has_mas(&[], &ksham, Lit, &["cakzamima", "cakzaRma"]); + assert_has_tip(&[], &ksham, Lut, &["kzamitA", "kzantA"]); + + // TODO: kzAmyati kzAnti kzamate kzamA + + let klam = d("klamu~", Divadi); + assert_has_tip(&[], &klam, Lat, &["klAmyati", "klAmati"]); + assert_has_tip(&[], &klam, Lun, &["aklamat"]); + + let mad = d("madI~", Divadi); + assert_has_tip(&[], &mad, Lat, &["mAdyati"]); + assert_has_tip(&[], &mad, Lun, &["amadat"]); + + let as_ = d("asu~", Divadi); + assert_has_tip(&[], &as_, Lat, &["asyati"]); + assert_has_tip(&[], &as_, Lit, &["Asa"]); + assert_has_tip(&[], &as_, Lut, &["asitA"]); +} + #[test] fn sk_2520() { let as_ = d("asu~", Divadi); diff --git a/vidyut-prakriya/tests/kaumudi_47.rs b/vidyut-prakriya/tests/kaumudi_47.rs index 0d6d124..7b96738 100644 --- a/vidyut-prakriya/tests/kaumudi_47.rs +++ b/vidyut-prakriya/tests/kaumudi_47.rs @@ -89,20 +89,19 @@ fn sk_2526() { assert_has_ta(&[], &kr, Lun, &["akfta"]); } -#[ignore] #[test] fn sk_2527() { let vr = d("vfY", Svadi); assert_has_sip(&[], &vr, Lit, &["vavariTa"]); assert_has_vas(&[], &vr, Lit, &["vavfva"]); assert_has_vahi(&[], &vr, Lit, &["vavfvahe"]); - assert_has_tip(&[], &vr, Lut, &["varitA"]); + // varItA by 7.2.38. + assert_has_tip(&[], &vr, Lut, &["varitA", "varItA"]); } #[test] fn skip_sk_2528() {} -#[ignore] #[test] fn sk_2529() { let vr = d("vfY", Svadi); diff --git a/vidyut-prakriya/tests/kaumudi_48.rs b/vidyut-prakriya/tests/kaumudi_48.rs index b819b89..70b6693 100644 --- a/vidyut-prakriya/tests/kaumudi_48.rs +++ b/vidyut-prakriya/tests/kaumudi_48.rs @@ -314,7 +314,6 @@ fn sk_2536() { assert_has_tip(&[], &sphur, Lat, &["sPurati"]); } -#[ignore] #[test] fn sk_2537() { // nissPurati and nizzPurati are justified. @@ -346,30 +345,40 @@ fn sk_2537() { assert_has_tip(&[], &gu, Lut, &["gutA"]); assert_has_tip(&[], &gu, Lrt, &["guzyati"]); assert_has_tip(&[], &gu, Lun, &["aguzIt"]); - // TODO: SK has agUtAm? assert_has_tas(&[], &gu, Lun, &["agutAm"]); assert_has_jhi(&[], &gu, Lun, &["aguzuH"]); + // "Adyasya DruvatItyAdi guvativat" let dhru = d_kutadi("Dru\\", Tudadi); - assert_has_sip(&[], &dhru, Lit, &["duDruviTa"]); - assert_has_tip(&[], &dhru, Lut, &["DruvitA"]); - assert_has_tip(&[], &dhru, Lrt, &["Druvizyati"]); - assert_has_tip(&[], &dhru, AshirLin, &["DrUvyAt"]); - assert_has_tip(&[], &dhru, Lun, &["aDruvIt"]); - assert_has_tas(&[], &dhru, Lun, &["aDruvizwAm"]); - - let kuu = d("kUN", Tudadi); + assert_has_sip(&[], &dhru, Lit, &["duDruviTa", "duDruTa"]); + assert_has_tip(&[], &dhru, Lut, &["DrutA"]); + assert_has_tip(&[], &dhru, Lrt, &["Druzyati"]); + assert_has_tip(&[], &dhru, Lun, &["aDruzIt"]); + assert_has_tas(&[], &dhru, Lun, &["aDrutAm"]); + assert_has_jhi(&[], &dhru, Lun, &["aDruzuH"]); + + // "dvitIyastu sew" + let dhruv = d_kutadi("Druva~", Tudadi); + assert_has_tip(&[], &dhruv, Lut, &["DruvitA"]); + assert_has_sip(&[], &dhruv, Lit, &["duDruviTa"]); + assert_has_tip(&[], &dhruv, Lut, &["DruvitA"]); + assert_has_tip(&[], &dhruv, Lrt, &["Druvizyati"]); + assert_has_tip(&[], &dhruv, AshirLin, &["DrUvyAt"]); + assert_has_tip(&[], &dhruv, Lun, &["aDruvIt"]); + assert_has_tas(&[], &dhruv, Lun, &["aDruvizwAm"]); + + let kuu = d_kutadi("kUN", Tudadi); assert_has_ta(&[], &kuu, Lut, &["kuvitA"]); assert_has_ta(&[], &kuu, Lun, &["akuvizwa"]); - let ku = d("ku\\N", Tudadi); + let ku = d_kutadi("ku\\N", Tudadi); assert_has_ta(&[], &ku, Lut, &["kutA"]); assert_has_ta(&[], &ku, Lun, &["akuta"]); let pr = d("pf\\N", Tudadi); assert_has_ta(&["vi", "AN"], &pr, Lat, &["vyApriyate"]); assert_has_ta(&["vi", "AN"], &pr, Lit, &["vyApapre"]); - assert_has_aataam(&["vi", "AN"], &pr, Lat, &["vyApaprAte"]); + assert_has_aataam(&["vi", "AN"], &pr, Lit, &["vyApaprAte"]); assert_has_ta(&["vi", "AN"], &pr, Lrt, &["vyAparizyate"]); assert_has_ta(&["vi", "AN"], &pr, Lun, &["vyApfta"]); assert_has_aataam(&["vi", "AN"], &pr, Lun, &["vyApfzAtAm"]); @@ -527,7 +536,6 @@ fn sk_2541() { assert_has_ta(&[], &mil, Lit, &["mimile"]); } -#[ignore] #[test] fn sk_2542() { let muc = d("mu\\cx~^", Tudadi); @@ -552,7 +560,6 @@ fn sk_2542() { assert_has_tip(&[], &vid, Lit, &["viveda"]); assert_has_ta(&[], &vid, Lit, &["vivide"]); assert_has_tip(&[], &vid, Lut, &["veditA", "vettA"]); - // TODO: is pariveditA justified? assert_has_tip(&["pari"], &vid, Lut, &["parivettA", "pariveditA"]); let lip = d("li\\pa~^", Tudadi); @@ -566,10 +573,10 @@ fn sk_2542() { assert_has_tip(&[], &sic, Lat, &["siYcati"]); assert_has_ta(&[], &sic, Lat, &["siYcate"]); assert_has_tip(&[], &sic, Lun, &["asicat"]); - assert_has_tip(&[], &sic, Lun, &["asicata", "asikta"]); + assert_has_ta(&[], &sic, Lun, &["asicata", "asikta"]); assert_has_tip(&["aBi"], &sic, Lat, &["aBiziYcati"]); assert_has_tip(&["aBi"], &sic, Lan, &["aByaziYcat"]); - assert_has_tip(&[], &sic, Lit, &["aBizizeca"]); + assert_has_tip(&["aBi"], &sic, Lit, &["aBizizeca"]); let krt = d("kftI~", Tudadi); assert_has_tip(&[], &krt, Lat, &["kfntati"]); @@ -584,6 +591,7 @@ fn sk_2542() { assert_has_tip(&[], &khid, Lut, &["KettA"]); let pish = d("piSa~", Tudadi); - assert_has_tip(&[], &pish, Lat, &["piMSati", "peSati"]); - assert_has_tip(&[], &pish, Lot, &["piMSatu"]); + assert_has_tip(&[], &pish, Lat, &["piMSati"]); + assert_has_tip(&[], &pish, Lut, &["peSitA"]); + assert_has_tip(&[], &pish, Lot, &["piMSatu", "piMSatAt"]); } diff --git a/vidyut-prakriya/tests/kaumudi_50.rs b/vidyut-prakriya/tests/kaumudi_50.rs index 1d67997..c1b36fd 100644 --- a/vidyut-prakriya/tests/kaumudi_50.rs +++ b/vidyut-prakriya/tests/kaumudi_50.rs @@ -3,7 +3,6 @@ use test_utils::*; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; -#[ignore] #[test] fn sk_2547() { let tan = d("tanu~^", Tanadi); @@ -31,17 +30,19 @@ fn sk_2547() { assert_has_ta(&[], &kshan, Lun, &["akzata", "akzaRizwa"]); assert_has_thaas(&[], &kshan, Lun, &["akzaTAH", "akzaRizWAH"]); + // Per SK, `u` indicates optional upaDA-guna. + // This seems to extend to fRu, tfRu, GfRu, etc. per other sources. let kshin = d("kziRu~^", Tanadi); assert_has_tip(&[], &kshin, Lat, &["kziRoti", "kzeRoti"]); assert_has_sip(&[], &kshin, Lut, &["kzeRitAsi"]); assert_has_thaas(&[], &kshin, Lut, &["kzeRitAse"]); assert_has_tip(&[], &kshin, Lun, &["akzeRIt"]); - assert_has_tip(&[], &kshin, Lun, &["akzita", "akzeRizwa"]); + assert_has_ta(&[], &kshin, Lun, &["akzita", "akzeRizwa"]); let rn = d("fRu~^", Tanadi); - assert_has_tip(&[], &rn, Lat, &["arRoti"]); - assert_has_tas(&[], &rn, Lat, &["arRutaH"]); - assert_has_jhi(&[], &rn, Lat, &["arRvanti"]); + assert_has_tip(&[], &rn, Lat, &["arRoti", "fRoti"]); + assert_has_tas(&[], &rn, Lat, &["arRutaH", "fRutaH"]); + assert_has_jhi(&[], &rn, Lat, &["arRvanti", "fRvanti"]); assert_has_tip(&[], &rn, Lit, &["AnarRa"]); assert_has_ta(&[], &rn, Lit, &["AnfRe"]); assert_has_thaas(&[], &rn, Lut, &["arRitAse"]); @@ -51,7 +52,7 @@ fn sk_2547() { let trn = d("tfRu~^", Tanadi); assert_has_tip(&[], &trn, Lat, &["tfRoti", "tarRoti"]); - assert_has_ta(&[], &trn, Lat, &["tfRute"]); + assert_has_ta(&[], &trn, Lat, &["tfRute", "tarRute"]); let ghrn = d("GfRu~^", Tanadi); assert_has_tip(&[], &ghrn, Lit, &["jaGarRa"]); diff --git a/vidyut-prakriya/tests/kaumudi_51.rs b/vidyut-prakriya/tests/kaumudi_51.rs index 633b78d..0a4a7f6 100644 --- a/vidyut-prakriya/tests/kaumudi_51.rs +++ b/vidyut-prakriya/tests/kaumudi_51.rs @@ -55,7 +55,6 @@ fn sk_2554() { assert_has_tip(&[], &si, Lut, &["setA"]); } -#[ignore] #[test] fn sk_2555() { let sku = d("sku\\Y", Kryadi); @@ -78,7 +77,7 @@ fn sk_2555() { assert_has_tip(&["ava"], &stambh, Lit, &["avatazwamBa", "avatastamBa"]); assert_has_tip(&["vi"], &stambh, Lun, &["vyazwaBat", "vyazwamBIt"]); - let stumbh = d("stu\\nBu~", Kryadi); + let stumbh = d("stunBu~", Kryadi); assert_has_tip(&[], &stumbh, Lat, &["stuBnoti", "stuBnAti"]); } @@ -184,8 +183,7 @@ fn sk_2558() { assert_has_tip(&[], &dhu, Lat, &["DunAti"]); assert_has_ta(&[], &dhu, Lat, &["DunIte"]); assert_has_sip(&[], &dhu, Lit, &["duDaviTa", "duDoTa"]); - // dudhUva seems justified. - assert_has_vas(&[], &dhu, Lit, &["duDuviva", "duDUva"]); + assert_has_vas(&[], &dhu, Lit, &["duDuviva"]); assert_has_tip(&[], &dhu, Lut, &["DotA", "DavitA"]); assert_has_tip(&[], &dhu, Lun, &["aDAvIt"]); assert_has_ta(&[], &dhu, Lun, &["aDavizwa", "aDozwa"]); @@ -220,7 +218,6 @@ fn sk_2558() { assert_has_tas(&[], &r, Lun, &["ArizwAm"]); } -#[ignore] #[test] fn sk_2559() { let jya = d("jyA\\", Kryadi); @@ -240,38 +237,44 @@ fn sk_2559() { let bandh = d("ba\\nDa~", Kryadi); assert_has_tip(&[], &bandh, Lat, &["baDnAti"]); - assert_has_sip(&[], &bandh, Lit, &["babanDiTa"]); - assert_has_tip(&[], &bandh, Lut, &["banDA"]); - assert_has_tas(&[], &bandh, Lut, &["banDArO"]); + // babandDa, etc. are supported by other sources. + assert_has_sip(&[], &bandh, Lit, &["babanDiTa", "babandDa", "babanDa"]); + assert_has_tip(&[], &bandh, Lut, &["banDA", "bandDA"]); + assert_has_tas(&[], &bandh, Lut, &["banDArO", "bandDArO"]); assert_has_tip(&[], &bandh, Lrt, &["Bantsyati"]); - assert_has_sip(&[], &bandh, Lot, &["baDAna"]); - assert_has_tip(&[], &bandh, Lun, &["aBAnsIt"]); - assert_has_tas(&[], &bandh, Lun, &["abAnDAm"]); - assert_has_jhi(&[], &bandh, Lun, &["aBAntsu"]); + assert_has_sip(&[], &bandh, Lot, &["baDAna", "baDnItAt"]); + assert_has_tip(&[], &bandh, Lun, &["aBAntsIt"]); + assert_has_tas(&[], &bandh, Lun, &["abAnDAm", "abAndDAm"]); + assert_has_jhi(&[], &bandh, Lun, &["aBAntsuH"]); let vr = d("vfN", Kryadi); assert_has_ta(&[], &vr, Lat, &["vfRIte"]); assert_has_ta(&[], &vr, Lit, &["vavre"]); assert_has_thaas(&[], &vr, Lit, &["vavfze"]); assert_has_dhvam(&[], &vr, Lit, &["vavfQve"]); - assert_has_tip(&[], &vr, Lut, &["varitA", "varItA"]); - assert_has_tip(&[], &vr, Lun, &["avarizwa", "avarIzwa", "avfta"]); + assert_has_ta(&[], &vr, Lut, &["varitA", "varItA"]); + assert_has_ta(&[], &vr, Lun, &["avarizwa", "avarIzwa", "avfta"]); let shranth = d("SranTa~", Kryadi); assert_has_tip(&[], &shranth, Lat, &["SraTnAti"]); - assert_has_tas(&[], &shranth, Lit, &["SreTatuH"]); - assert_has_jhi(&[], &shranth, Lit, &["SreTuH"]); - assert_has_sip(&[], &shranth, Lit, &["SreTiTa", "SaSrATa"]); + // SaSranTatuH and SasranTuH are not supported by KV or SK, but they are allowed by other + // grammarians. + assert_has_tas(&[], &shranth, Lit, &["SreTatuH", "SaSranTatuH"]); + assert_has_jhi(&[], &shranth, Lit, &["SreTuH", "SaSranTuH"]); + assert_has_sip(&[], &shranth, Lit, &["SaSranTiTa"]); + // TODO: SaSrATa, SaSraTa, SreTiTa by sudhAkara-mata. But, adding this makes the derivation of + // SaSrATa unclear. let kunth = d("kunTa~", Kryadi); assert_has_tip(&[], &kunth, Lat, &["kuTnAti"]); assert_has_tip(&[], &kunth, Lit, &["cukunTa"]); - assert_has_tip(&[], &kunth, Lit, &["cukoTa"]); + let kuth = d("kuTa~", Kryadi); + assert_has_tip(&[], &kuth, Lit, &["cukoTa"]); let mrd = d("mfda~", Kryadi); assert_has_tip(&[], &mrd, Lat, &["mfdnAti"]); - assert_has_sip(&[], &mrd, Lot, &["mfdAna"]); + assert_has_sip(&[], &mrd, Lot, &["mfdAna", "mfdnItAt"]); let mrd = d("mfqa~", Kryadi); assert_has_tip(&[], &mrd, Lat, &["mfqRAti"]); @@ -284,6 +287,76 @@ fn sk_2559() { assert_has_tip(&[], &kush, Lut, &["kozitA"]); } +#[ignore] +#[test] +fn sk_2560() { + let kush = d("kuza~", Kryadi); + assert_has_tip(&["nir"], &kush, Lut, &["nizkozitA", "nizkozwA"]); + // aniT -> ksa -> nirakukzat + assert_has_tip(&["nir"], &kush, Lun, &["nirakozIt", "nirakukzat"]); + + let kshubh = d("kzuBa~", Kryadi); + assert_has_tip(&[], &kshubh, Lat, &["kzuBnAti"]); + assert_has_tas(&[], &kshubh, Lat, &["kzuBnItaH"]); + assert_has_tip(&[], &kshubh, Lut, &["kzoBitA"]); + assert_has_sip(&[], &kshubh, Lot, &["kzuBAna", "kzuBnItAt"]); + + let nabh = d("RaBa~", Kryadi); + assert_has_tip(&[], &nabh, Lat, &["naBnAti"]); + + let tubh = d("tuBa~", Kryadi); + assert_has_tip(&[], &tubh, Lat, &["tuBnAti"]); + + assert_has_ta(&[], &d("RaBa~\\", Bhvadi), Lat, &["naBate"]); + assert_has_ta(&[], &d("tuBa~\\", Bhvadi), Lat, &["toBate"]); + assert_has_tip(&[], &d("RaBa~", Divadi), Lat, &["naByati"]); + assert_has_tip(&[], &d("tuBa~", Divadi), Lat, &["tuByati"]); + + let klish = d("kliSU~", Kryadi); + assert_has_tip(&[], &klish, Lat, &["kliSnAti"]); + assert_has_tip(&[], &klish, Lut, &["kleSitA", "klezwA"]); + assert_has_tip(&[], &klish, Lun, &["akleSIt", "aklikzat"]); + + let ash = d("aSa~", Kryadi); + assert_has_tip(&[], &ash, Lat, &["aSnAti"]); + assert_has_tip(&[], &ash, Lit, &["ASa"]); + + let dhras = d("u~Drasa~", Kryadi); + assert_has_tip(&[], &dhras, Lat, &["DrasnAti"]); + + let x = d("uDrasa~", Kryadi); + assert_has_tip( + &[], + &x, + Lit, + &["uDrasAYcakAra", "uDrasAmAsa", "uDrasAmbaBUva"], + ); + + let ish = d("iza~", Kryadi); + assert_has_tip(&[], &ish, Lat, &["izRAti"]); + assert_has_tip(&[], &ish, Lut, &["ezitA"]); + // TODO: iw-vikalpa? + + let x = d("vi\\za~", Kryadi); + assert_has_tip(&[], &x, Lat, &["vizRAti"]); + assert_has_tip(&[], &x, Lut, &["vezwA"]); + + let prush = d("pruza~", Kryadi); + assert_has_tip(&[], &prush, Lat, &["pruzRAti"]); + + let plush = d("pluza~", Kryadi); + assert_has_tip(&[], &plush, Lat, &["pluzRAti"]); + + let push = d("puza~", Kryadi); + assert_has_tip(&[], &push, Lut, &["pozitA"]); + + let mush = d("muza~", Kryadi); + assert_has_tip(&[], &mush, Lut, &["mozitA"]); + + let khac = d("Kaca~", Kryadi); + assert_has_tip(&[], &khac, Lat, &["KacYAti"]); +} + #[test] fn sk_2561() { let khav = d("Kava~", Kryadi); diff --git a/vidyut-prakriya/tests/kaumudi_52.rs b/vidyut-prakriya/tests/kaumudi_52.rs index bb20881..c533954 100644 --- a/vidyut-prakriya/tests/kaumudi_52.rs +++ b/vidyut-prakriya/tests/kaumudi_52.rs @@ -1,7 +1,9 @@ extern crate test_utils; use test_utils::*; +use vidyut_prakriya::args::Dhatu; use vidyut_prakriya::args::Gana::*; use vidyut_prakriya::args::Lakara::*; +use vidyut_prakriya::args::Sanadi; #[test] fn sk_2563() { @@ -9,7 +11,6 @@ fn sk_2563() { assert_has_tip(&[], &cur, Lat, &["corayati"]); } -#[ignore] #[test] fn sk_2564() { let cur = d("cura~", Curadi); @@ -28,14 +29,46 @@ fn sk_2564() { let cint = d("citi~", Curadi); assert_has_tip(&[], &cint, Lat, &["cintayati", "cintati"]); - assert_has_tip(&[], &cint, Lun, &["acicintat"]); + assert_has_tip(&[], &cint, Lun, &["acicintat", "acintIt"]); assert_has_tip(&[], &cint, AshirLin, &["cintyAt"]); assert_has_ta_k(&[], &cint, Lat, &["cintyate"]); + assert_has_tip(&[], &cint, VidhiLin, &["cintayet", "cintet"]); - // TODO: cintati, etc. + // TODO: jagARa not capturable right now. + + let yantr = d("yatri~", Curadi); + assert_has_tip(&[], &yantr, Lat, &["yantrayati", "yantrati"]); + + let sphund = d("sPuqi~", Curadi); + assert_has_tip(&[], &sphund, Lat, &["sPuRqayati", "sPuRqati"]); + + let sphunt = d("sPuwi~", Curadi); + assert_has_tip(&[], &sphunt, Lat, &["sPuRwayati", "sPuRwati"]); + + // "evaM kudritatrimatrizu" for "kundrati" + let kundr = d("kudri~", Curadi); + assert_has_tip(&[], &kundr, Lat, &["kundrayati", "kundrati"]); + + // "evaM kudritatrimatrizu" for "kundrati" + let lad = d("laqa~", Curadi); + assert_has_tip(&[], &lad, Lat, &["lAqayati"]); + + let mind = d("midi~", Curadi); + assert_has_tip(&[], &mind, Lat, &["mindayati", "mindati"]); + + let oland = d("olaqi~", Curadi); + assert_has_tip(&[], &oland, Lat, &["olaRqayati", "olaRqati"]); + + let land = d("o~laqi~", Curadi); + assert_has_tip(&[], &land, Lat, &["laRqayati", "laRqati"]); + + let uland = d("ulaqi~", Curadi); + assert_has_tip(&[], &uland, Lat, &["ulaRqayati", "ulaRqati"]); + + let pid = d("pIqa~", Curadi); + assert_has_tip(&[], &pid, Lat, &["pIqayati"]); } -#[ignore] #[test] fn sk_2565() { let pid = d("pIqa~", Curadi); @@ -45,8 +78,10 @@ fn sk_2565() { assert_has_tip(&[], &badh, Lat, &["bADayati"]); let pr = d("pF", Curadi); - assert_has_tip(&[], &pr, Lat, &["pArayati"]); - // TODO: parati? + assert_has_tip(&[], &pr, Lat, &["pArayati", "parati"]); + + let prath = d("praTa~", Curadi); + assert_has_tip(&[], &prath, Lat, &["prATayati"]); } #[test] @@ -58,17 +93,624 @@ fn sk_2566() { assert_has_tip(&[], &prth, Lat, &["parTayati"]); } +#[test] +fn sk_2567() { + let prth = d("pfTa~", Curadi); + assert_has_tip(&[], &prth, Lun, &["apIpfTat", "apaparTat"]); + + let path = d("paTa~", Curadi); + assert_has_tip(&[], &path, Lat, &["pATayati"]); + + let sanb = d("zanba~", Curadi); + assert_has_tip(&[], &sanb, Lat, &["sambayati"]); + assert_has_tip(&[], &sanb, Lun, &["asasambat"]); + + let shanb = d("Sanba~", Curadi); + assert_has_tip(&[], &shanb, Lun, &["aSaSambat"]); + + let kutt = d("kuwwa~", Curadi); + assert_has_tip(&[], &kutt, Lat, &["kuwwayati"]); + + // "ayaM dopaDaH" + let att = d("adwa~", Curadi); + assert_has_tip(&[], &att, Lat, &["awwayati"]); + assert_has_tip(&[], &att, Lun, &["Awwiwat"]); + + let lunth = d("lunWa~", Curadi); + assert_has_tip(&[], &lunth, Lat, &["luRWayati"]); + assert_has_tip(&[], &d("luWi~", Bhvadi), Lat, &["luRWati"]); + + let tunj = d("tuji~", Curadi); + assert_has_tip(&[], &tunj, Lat, &["tuYjayati", "tuYjati"]); + + let pinj = d("piji~", Curadi); + assert_has_tip(&[], &pinj, Lat, &["piYjayati", "piYjati"]); + + let pis = d("pisa~", Curadi); + assert_has_tip(&[], &pis, Lat, &["pesayati"]); + assert_has_tip(&[], &d("pisf~", Bhvadi), Lat, &["pesati"]); + + let smit = d("smiwa~", Curadi); + assert_has_tip(&[], &smit, Lun, &["asismiwat"]); + + let smi = d("zmiN", Curadi); + assert_has_tip(&[], &smi, Lat, &[]); + assert_has_ta(&[], &smi, Lat, &["smAyayate"]); + + let panth = d("paTi~", Curadi); + assert_has_tip(&[], &panth, Lat, &["panTayati", "panTati"]); + + let chand = d("Cadi~", Curadi); + assert_has_tip(&[], &chand, Lat, &["Candayati", "Candati"]); + + let shran = d("SraRa~", Curadi); + assert_has_tip(&["vi"], &shran, Lat, &["viSrARayati"]); + + let tad = d("taqa~", Curadi); + assert_has_tip(&[], &tad, Lat, &["tAqayati"]); + + let khad = d("Kaqa~", Curadi); + assert_has_tip(&[], &khad, Lat, &["KAqayati"]); + + let khand = d("Kaqi~", Curadi); + assert_has_tip(&[], &khand, Lat, &["KaRqayati", "KaRqati"]); + + let kand = d("kaqi~", Curadi); + assert_has_tip(&[], &kand, Lat, &["kaRqayati", "kaRqati"]); + + let kunth = d("kuWi~", Curadi); + assert_has_tip(&["ava"], &kunth, Lat, &["avakuRWayati", "avakuRWati"]); + + let nakk = d("nakka~", Curadi); + assert_has_tip(&["pra"], &nakk, Lat, &["pranakkayati"]); + + let tul = d("tula~", Curadi); + assert_has_tip(&[], &tul, Lat, &["tolayati"]); + assert_has_tip( + &[], + &tul, + Lit, + &["tolayAYcakAra", "tolayAmAsa", "tolayAmbaBUva"], + ); + assert_has_tip(&[], &tul, Lun, &["atUtulat"]); + + // TODO: tulayati, tulanA + + let dul = d("dula~", Curadi); + assert_has_tip(&[], &dul, Lat, &["dolayati"]); + assert_has_tip( + &[], + &dul, + Lit, + &["dolayAYcakAra", "dolayAmAsa", "dolayAmbaBUva"], + ); + assert_has_tip(&[], &dul, Lun, &["adUdulat"]); + + let kal = d("kala~", Curadi); + assert_has_tip(&[], &kal, Lat, &["kAlayati"]); + + let pand = d("paqi~", Curadi); + assert_has_tip(&[], &pand, Lat, &["paRqayati", "paRqati"]); + + let pans = d("pasi~", Curadi); + assert_has_tip(&[], &pans, Lat, &["paMsayati", "paMsati"]); + + let camp = d("capi~", Curadi); + assert_has_tip(&[], &camp, Lat, &["campayati", "campati"]); + + let kshamp = d("kzapi~", Curadi); + assert_has_tip(&[], &kshamp, Lat, &["kzampayati", "kzampati"]); +} + +#[test] +fn skip_sk_2568() { + let jnap = d("jYapa~", Curadi); + assert_has_tip(&[], &jnap, Lat, &["jYapayati"]); + + let yam = d("yama~", Curadi); + assert_has_tip(&[], &yam, Lat, &["yamayati"]); + + let cah = d("caha~", Curadi); + assert_has_tip(&[], &cah, Lat, &["cahayati"]); + assert_has_tip(&[], &cah, Lun, &["acIcahat"]); + // TODO: acacahat ? + + let cap = d("capa~", Curadi); + assert_has_tip(&[], &cap, Lat, &["capayati"]); + + let rah = d("raha~", Curadi); + assert_has_tip(&[], &rah, Lun, &["arIrahat"]); + // TODO: ararahat? + + let bal = d("bala~", Curadi); + assert_has_tip(&[], &bal, Lat, &["balayati"]); +} + #[test] fn skip_sk_2569() {} +#[test] +fn skip_sk_2570() { + let ci = d("ciY", Curadi); + assert_has_tip(&[], &ci, Lat, &["capayati", "cayayati", "cayati"]); + assert_has_ta(&[], &ci, Lat, &["capayate", "cayayate", "cayate"]); + assert_has_tip( + &["pra", "ni"], + &ci, + Lat, + &[ + "pranicapayati", + "praRicapayati", + "pranicayayati", + "praRicayayati", + "pranicayati", + "praRicayati", + ], + ); + + let tank = d("waki~", Curadi); + assert_has_tip(&[], &tank, Lat, &["waNkayati", "waNkati"]); + + let dhus = d("DUsa~", Curadi); + assert_has_tip(&[], &dhus, Lat, &["DUsayati"]); + + let shunt = d("SuWi~", Curadi); + assert_has_tip(&[], &shunt, Lat, &["SuRWayati", "SuRWati"]); + + let gaj = d("gaja~", Curadi); + assert_has_tip(&[], &gaj, Lat, &["gAjayati"]); + + let marj = d("mArja~", Curadi); + assert_has_tip(&[], &marj, Lat, &["mArjayati"]); + + let marc = d("marca~", Curadi); + assert_has_tip(&[], &marc, Lat, &["marcayati"]); + + let panc = d("paci~", Curadi); + assert_has_tip(&[], &panc, Lat, &["paYcayati", "paYcati"]); + // no paYcate for paci~ (curAdi) + assert_has_ta(&[], &panc, Lat, &["paYcayate"]); + assert_has_ta(&[], &d("paci~\\", Bhvadi), Lat, &["paYcate"]); + + let tij = d("tija~", Curadi); + assert_has_tip(&[], &tij, Lat, &["tejayati"]); +} + +#[test] +fn sk_2571() { + let kirt = d("kFta~", Curadi); + assert_has_tip(&[], &kirt, Lat, &["kIrtayati"]); + assert_has_tip(&[], &kirt, Lun, &["acIkftat", "acikIrtat"]); + + let kumb = d("kubi~", Curadi); + assert_has_tip(&[], &kumb, Lat, &["kumbayati", "kumbati"]); + + let il = d("ila~", Curadi); + assert_has_tip(&[], &il, Lat, &["elayati"]); + assert_has_tip(&[], &il, Lun, &["Elilat"]); + + let jans = d("jasi~", Curadi); + assert_has_tip(&[], &jans, Lat, &["jaMsayati", "jaMsati"]); + + // start of AkusmIya + + let cit = d_akusmiya("cita~", Curadi); + assert_has_lat(&[], &cit, &["cetayate"]); + assert_has_lun(&[], &cit, &["acIcitata"]); + + let dansh = d_akusmiya("daSi~", Curadi); + assert_has_tip(&[], &dansh, Lat, &["daMSati"]); + + let dans = d_akusmiya("dasi~", Curadi); + assert_has_ta(&[], &dans, Lat, &["daMsayate"]); + assert_has_tip(&[], &dans, Lat, &["daMsati"]); + + let tantr = d_akusmiya("tatri~", Curadi); + assert_has_ta(&[], &tantr, Lat, &["tantrayate"]); + + let bast = d_akusmiya("basta~", Curadi); + assert_has_ta(&[], &bast, Lat, &["bastayate"]); + + let gandh = d_akusmiya("ganDa~", Curadi); + assert_has_ta(&[], &gandh, Lat, &["ganDayate"]); + + let sham = d_akusmiya("Sama~", Curadi); + assert_has_ta(&[], &sham, Lat, &["SAmayate"]); + + let vrsh = d_akusmiya("vfza~", Curadi); + assert_has_ta(&[], &vrsh, Lat, &["varzayate"]); + + let mad = d_akusmiya("mada~", Curadi); + assert_has_ta(&[], &mad, Lat, &["mAdayate"]); + + let gr = d_akusmiya("gf", Curadi); + assert_has_ta(&[], &gr, Lat, &["gArayate"]); + + let vid = d_akusmiya("vida~", Curadi); + assert_has_ta(&[], &vid, Lat, &["vedayate"]); + // TODO: vindati? + assert_has_tip(&[], &d("vi\\dx~^", Tudadi), Lat, &["vindati"]); + + let man = d_akusmiya("mAna~", Curadi); + assert_has_ta(&[], &man, Lat, &["mAnayate"]); + + let yu = d_akusmiya("yu", Curadi); + assert_has_ta(&[], &yu, Lat, &["yAvayate"]); + + let kusm = d_akusmiya("kusma~", Curadi); + assert_has_ta(&[], &kusm, Lat, &["kusmayate"]); + assert_has_ta(&[], &kusm, Lun, &["acukusmata"]); + + // end of AkusmIya + + let shabd = d("Sabda~", Curadi); + assert_has_tip(&["prati"], &shabd, Lat, &["pratiSabdayati"]); + assert_has_tip(&[], &shabd, Lat, &["Sabdayati"]); + + let kan = d("kaRa~", Curadi); + assert_has_tip(&[], &kan, Lat, &["kARayati"]); + assert_has_tip(&[], &kan, Lun, &["acIkaRat", "acakARat"]); + + let jambh = d("jaBi~", Curadi); + assert_has_tip(&[], &jambh, Lat, &["jamBayati", "jamBati"]); + + let sud = d("zUda~", Curadi); + assert_has_tip(&[], &sud, Lat, &["sUdayati"]); + assert_has_tip(&[], &sud, Lun, &["asUzudat"]); + + let jas = d("jasu~", Curadi); + assert_has_tip(&[], &jas, Lat, &["jAsayati", "jasati"]); + + let pas = d("paSa~", Curadi); + assert_has_tip(&[], &pas, Lat, &["pASayati"]); + + let am = d("ama~", Curadi); + assert_has_tip(&[], &am, Lat, &["Amayati"]); + assert_has_tip(&["AN"], &nic(&d("ama~", Bhvadi)), Lat, &["Amayati"]); + + assert_has_ta(&[], &d("sPuwa~\\", Bhvadi), Lat, &["sPowate"]); + assert_has_tip(&[], &d("sPuwa~", Tudadi), Lat, &["sPuwati"]); + + let ghat = d("Gawa~", Curadi); + assert_has_tip(&[], &ghat, Lat, &["GAwayati"]); + + let div = d("divu~", Curadi); + assert_has_tip(&[], &div, Lat, &["devayati", "devati"]); + + let arj = d("arja~", Curadi); + assert_has_tip(&[], &arj, Lat, &["arjayati"]); + + let ghush = d("Guzi~r", Curadi); + assert_has_tip(&[], &ghush, Lat, &["Gozayati", "Gozati"]); + assert_has_tip(&[], &ghush, Lun, &["aGuzat", "aGozIt", "ajUGuzat"]); + + // TODO: curAdi or bhvAdi? + let krand = d("kranda~", Curadi); + assert_has_tip(&["AN"], &krand, Lat, &["Akrandayati"]); + + let tans = d("tasi~", Curadi); + assert_has_tip(&["ava"], &tans, Lat, &["avataMsayati", "avataMsati"]); + + let bhush = d("BUza~", Curadi); + assert_has_tip(&[], &bhush, Lat, &["BUzayati"]); + + let jna = d("jYA", Curadi); + assert_has_tip(&["AN"], &jna, Lat, &["AjYApayati"]); + + // aSarDIt by udit --> Ric-vikalpa + let shrd = d("SfDu~", Curadi); + assert_has_tip(&[], &shrd, Lun, &["aSaSarDat", "aSISfDat", "aSarDIt"]); + + let anc = d("ancu~", Curadi); + assert_has_tip(&[], &anc, Lat, &["aYcayati", "aYcati"]); + + let ling = d("ligi~", Curadi); + assert_has_tip(&[], &ling, Lat, &["liNgayati", "liNgati"]); + + let mud = d("muda~", Curadi); + assert_has_tip(&[], &mud, Lat, &["modayati"]); + + let dhras = d("u~Drasa~", Curadi); + assert_has_tip(&[], &dhras, Lat, &["DrAsayati", "Drasati"]); + + let udhras = d("uDrasa~", Curadi); + assert_has_tip(&[], &udhras, Lat, &["uDrAsayati"]); + + let cyu = d("cyu", Curadi); + assert_has_tip(&[], &cyu, Lat, &["cyAvayati"]); + + let cyus = d("cyusa~", Curadi); + assert_has_tip(&[], &cyus, Lat, &["cyosayati"]); + + let bhu = d("BU", Curadi); + assert_has_tip(&[], &bhu, Lat, &["BAvayati"]); + + let krp = d("kfpa~", Curadi); + assert_has_tip(&[], &krp, Lat, &["kalpayati"]); + + let gras = d("grasa~", Curadi); + assert_has_tip(&[], &gras, Lat, &["grAsayati"]); + + let push = d("puza~", Curadi); + assert_has_tip(&[], &push, Lat, &["pozayati"]); + + let dal = d("dala~", Curadi); + assert_has_tip(&[], &dal, Lat, &["dAlayati"]); + + let pat = d("pawa~", Curadi); + assert_has_tip(&[], &pat, Lat, &["pAwayati"]); + + let put = d("puwa~", Curadi); + assert_has_tip(&[], &put, Lat, &["powayati"]); + + let lut = d("luwa~", Curadi); + assert_has_tip(&[], &lut, Lat, &["lowayati"]); + + let tunj = d("tuji~", Curadi); + assert_has_tip(&[], &tunj, Lat, &["tuYjayati", "tuYjati"]); + + let pinj = d("piji~", Curadi); + assert_has_tip(&[], &pinj, Lat, &["piYjayati", "piYjati"]); + + let ghat = d("Gawa~", Curadi); + assert_has_tip(&[], &ghat, Lat, &["GAwayati"]); + + let ghant = d("Gawi~", Curadi); + assert_has_tip(&[], &ghant, Lat, &["GaRwayati", "GaRwati"]); +} + +#[test] +fn sk_2572() { + let lok = d("lokf~", Curadi); + assert_has_tip(&[], &lok, Lun, &["alulokat"]); + + let loc = d("locf~", Curadi); + assert_has_tip(&[], &loc, Lun, &["alulocat"]); + + let vrt = d("vftu~", Curadi); + assert_has_tip(&[], &vrt, Lat, &["vartayati", "vartati"]); + + let vrdh = d("vfDu~", Curadi); + assert_has_tip(&[], &vrdh, Lat, &["varDayati", "varDati"]); + + let pur = d("pUrI~", Curadi); + assert_has_tip(&[], &pur, Lat, &["pUrayati", "pUrati"]); + + let svad = d("zvada~", Curadi); + assert_has_tip(&[], &svad, Lun, &["asizvadat"]); + + let svaad = d("svAda~", Curadi); + assert_has_tip(&[], &svaad, Lun, &["asisvadat"]); + + // start of ADfzIya + let yuj = d_adhrshiya("yu\\ja~", Curadi); + assert_has_tip(&[], &yuj, Lat, &["yojayati", "yojati"]); + assert_has_tip(&[], &yuj, Lun, &["ayUyujat", "ayOkzIt"]); +} + +#[test] +fn sk_2573() { + let gana = d("gaRa", Curadi); + assert_has_tip(&[], &gana, Lun, &["ajIgaRat", "ajagaRat"]); + + let raha = d("raha", Curadi); + assert_has_tip(&[], &raha, Lun, &["ararahat"]); + + let stana = d("stana", Curadi); + assert_has_tip(&[], &stana, Lat, &["stanayati"]); + + let gada = d("gada", Curadi); + assert_has_tip(&[], &gada, Lat, &["gadayati"]); + assert_has_tip(&[], &gada, Lun, &["ajagadat"]); + + let pata = d("pata", Curadi); + assert_has_tip(&[], &pata, Lat, &["patayati", "patati", "pAtayati"]); + assert_has_tip( + &[], + &pata, + Lit, + &[ + "patAYcakAra", + "patAmAsa", + "patAmbaBUva", + "patayAYcakAra", + "patayAmAsa", + "patayAmbaBUva", + "pAtayAYcakAra", + "pAtayAmAsa", + "pAtayAmbaBUva", + ], + ); + // Neelesh ji confirms that apapatat is also justified. + assert_has_tip(&[], &pata, Lun, &["apatIt", "apIpatat", "apapatat"]); + + let pasha = d("paza", Curadi); + assert_has_tip(&[], &pasha, Lat, &["pazayati"]); + + let svara = d("svara", Curadi); + assert_has_tip(&[], &svara, Lat, &["svarayati"]); + + let raca = d("raca", Curadi); + assert_has_tip(&[], &raca, Lat, &["racayati"]); + + let maha = d("maha", Curadi); + assert_has_tip(&[], &maha, Lat, &["mahayati"]); + assert_has_tip(&[], &d("maha~", Bhvadi), Lat, &["mahati"]); + + let sara = d("sAra", Curadi); + assert_has_tip(&[], &sara, Lat, &["sArayati"]); + + let kfpa = d("kfpa", Curadi); + assert_has_tip(&[], &kfpa, Lat, &["kfpayati"]); + + let shratha = d("SraTa", Curadi); + assert_has_tip(&[], &shratha, Lat, &["SraTayati"]); + + let bham = d("BAma", Curadi); + assert_has_tip(&[], &bham, Lun, &["abaBAmat"]); + + let suc = d("sUca", Curadi); + assert_has_tip(&[], &suc, Lat, &["sUcayati"]); + + let goma = d("goma", Curadi); + assert_has_tip(&[], &goma, Lun, &["ajugomat"]); + + let kumara = d("kumAra", Curadi); + assert_has_tip(&[], &kumara, Lun, &["acukumArat"]); + + let sama = d("sAma", Curadi); + assert_has_tip(&[], &sama, Lun, &["asasAmat"]); + // TODO: sAma sAntvane? + + let vela = d("vela", Curadi); + assert_has_tip(&[], &vela, Lat, &["velayati"]); + + let kala = d("kAla", Curadi); + assert_has_tip(&[], &kala, Lat, &["kAlayati"]); + + let vata = d("vAta", Curadi); + assert_has_tip(&[], &vata, Lat, &["vAtayati"]); + assert_has_tip(&[], &vata, Lun, &["avavAtat"]); + + let gavesha = d("gaveza", Curadi); + assert_has_tip(&[], &gavesha, Lun, &["ajagavezat"]); + + let nivasa = d("nivAsa", Curadi); + assert_has_tip(&[], &nivasa, Lun, &["aninivAsat"]); + + let sabhaja = d("saBAja", Curadi); + assert_has_tip(&[], &sabhaja, Lat, &["saBAjayati"]); + + let una = d("Una", Curadi); + assert_has_tip(&[], &una, Lat, &["Unayati"]); + assert_has_tip(&[], &una, Lun, &["Onanat"]); + + let dhvan = d("Dvana", Curadi); + assert_has_tip(&[], &dhvan, Lun, &["adaDvanat"]); + + let kuta = d("kUwa", Curadi); + assert_has_tip(&[], &kuta, Lat, &["kUwayati"]); + + let sanketa = d("sanketa", Curadi); + assert_has_tip(&[], &sanketa, Lat, &["saNketayati"]); + + let grama = d("grAma", Curadi); + assert_has_tip(&[], &grama, Lat, &["grAmayati"]); + + let kuna = d("kuRa", Curadi); + assert_has_tip(&[], &kuna, Lat, &["kuRayati"]); + + let guna = d("guRa", Curadi); + assert_has_tip(&[], &guna, Lat, &["guRayati"]); + + let keta = d("keta", Curadi); + assert_has_tip(&[], &keta, Lat, &["ketayati"]); + assert_has_tip(&["aBi"], &keta, Lat, &["aBiketayati"]); + + let stena = d("stena", Curadi); + assert_has_tip(&[], &stena, Lun, &["atistenat"]); + + // start of AgarvIya + + let pada = d("pada", Curadi); + assert_has_lat(&[], &pada, &["padayate"]); + assert_has_lun(&[], &pada, &["apapadata"]); + + let grha = d("gfha", Curadi); + assert_has_lat(&[], &grha, &["gfhayate"]); + + let mfga = d("mfga", Curadi); + assert_has_lat(&[], &mfga, &["mfgayate"]); + // TODO: how is this kaRqvAdi? + assert_has_lat(&[], &d("mfga", Kandvadi), &["mfgyati"]); + + let sthula = d("sTUla", Curadi); + assert_has_lat(&[], &sthula, &["sTUlayate"]); + assert_has_lun(&[], &sthula, &["atusTUlata"]); + + let artha = d("arTa", Curadi); + assert_has_lat(&[], &artha, &["arTayate"]); + assert_has_lun(&[], &artha, &["ArtaTata"]); + + let satra = d("satra", Curadi); + assert_has_lun(&[], &satra, &["asasatrata"]); + // TODO: assert_has_lat(&[], &san(&satra), &["sisatrayizate"]); + + let garva = d("garva", Curadi); + assert_has_lat(&[], &garva, &["garvayate", "garvati"]); + + // end of AgarvIya + + let sutra = d("sUtra", Curadi); + assert_has_tip(&[], &sutra, Lat, &["sUtrayati"]); + assert_has_tip(&[], &sutra, Lun, &["asusUtrat"]); + + let mutra = d("mUtra", Curadi); + assert_has_tip(&[], &mutra, Lat, &["mUtrayati", "mUtrati"]); + + let para = d("pAra", Curadi); + assert_has_tip(&[], ¶, Lun, &["apapArat"]); + + let tira = d("tIra", Curadi); + assert_has_tip(&[], &tira, Lun, &["atitIrat"]); + + let put = d("puwa", Curadi); + assert_has_tip(&[], &put, Lat, &["puwayati"]); + + let dhek = d("Deka", Curadi); + assert_has_tip(&[], &dhek, Lun, &["adiDekat"]); + + let katra = d("katra", Curadi); + assert_has_tip(&[], &katra, Lat, &["katrayati", "katrati"]); + + let karta = d("karta", Curadi); + assert_has_tip(&[], &karta, Lat, &["kartayati", "kartati"]); + + let pati = Dhatu::nama("pawu".into(), Some(Sanadi::Ric)); + assert_has_tip(&[], &pati, Lat, &["pawayati"]); + // TODO: pawayati, apIpawat, apapawat, ... +} + #[test] fn sk_2574() { - // TODO: add more - - // ac-Adi dhatus with can-pratyaya and ak-lopa - // TODO: why does the SK have AndaDat and not AndiDat? - assert_has_tip(&[], &d("anDa", Curadi), Lun, &["AndaDat"]); - assert_has_tip(&[], &d("anka", Curadi), Lun, &["AYcakat"]); - assert_has_tip(&[], &d("anga", Curadi), Lun, &["AYjagat"]); - assert_has_tip(&[], &d("vyaya", Curadi), Lun, &["avavyayat"]); + // "citrati" seems justified. TODO: double-check. + let citra = d("citra", Curadi); + assert_has_tip(&[], &citra, Lat, &["citrayati"]); + + let vant = d("vawi~", Curadi); + assert_has_tip(&[], &vant, Lat, &["vaRwayati", "vaRwati"]); + + let lanj = d("laji~", Curadi); + assert_has_tip(&[], &lanj, Lat, &["laYjayati", "laYjati"]); + + // TODO: vaRwApayati, laYjApayati + + let stoma = d("stoma", Curadi); + assert_has_tip(&[], &stoma, Lun, &["atustomat"]); + + let andha = &d("anDa", Curadi); + assert_has_tip(&[], &andha, Lun, &["AndaDat"]); + + let anka = &d("anka", Curadi); + assert_has_tip(&[], &anka, Lun, &["AYcakat"]); + + let anga = &d("anga", Curadi); + assert_has_tip(&[], &anga, Lun, &["AYjagat"]); + + let vyaya = &d("vyaya", Curadi); + assert_has_tip(&[], &vyaya, Lun, &["avavyayat"]); + + let cheda = d("Ceda", Curadi); + assert_has_tip(&[], &cheda, Lun, &["acicCedat"]); + + let chada = d("Cada", Curadi); + assert_has_tip(&[], &chada, Lat, &["Cadayati"]); + + let varna = d("varRa", Curadi); + assert_has_tip(&[], &varna, Lat, &["varRayati"]); + + let parna = d("parRa", Curadi); + assert_has_tip(&[], &parna, Lun, &["apaparRat"]); + + // TODO: hastayate, pAdayate, ... } diff --git a/vidyut-prakriya/tests/kaumudi_54.rs b/vidyut-prakriya/tests/kaumudi_54.rs index b58090c..004b6e0 100644 --- a/vidyut-prakriya/tests/kaumudi_54.rs +++ b/vidyut-prakriya/tests/kaumudi_54.rs @@ -261,9 +261,10 @@ fn sk_2623() { assert_has_tip(&[], &san(&d("Sa\\kx~", Svadi)), Lat, &["Sikzati"]); + // SiSakizati seems justified because Sa\\kx~ is optionally seT. let shak = &d("Sa\\ka~^", Divadi); - assert_has_tip(&[], &san(&shak), Lat, &["Sikzati"]); - assert_has_ta(&[], &san(&shak), Lat, &["Sikzate"]); + assert_has_tip(&[], &san(&shak), Lat, &["Sikzati", "SiSakizati"]); + assert_has_ta(&[], &san(&shak), Lat, &["Sikzate", "SiSakizate"]); assert_has_ta(&[], &san(&d("pa\\da~\\", Divadi)), Lat, &["pitsate"]); diff --git a/vidyut-prakriya/tests/kaumudi_58.rs b/vidyut-prakriya/tests/kaumudi_58.rs new file mode 100644 index 0000000..f25b70c --- /dev/null +++ b/vidyut-prakriya/tests/kaumudi_58.rs @@ -0,0 +1,68 @@ +extern crate test_utils; +use test_utils::*; +use vidyut_prakriya::args::Gana::*; + +#[test] +fn sk_2678() { + let kandu = d("kaRqUY", Kandvadi); + assert_has_lat(&[], &kandu, &["kaRqUyati", "kaRqUyate"]); + + let mantu = d("mantu", Kandvadi); + assert_has_lat(&[], &mantu, &["mantUyati"]); + + let mantu = d("mantuY", Kandvadi); + assert_has_lat(&[], &mantu, &["mantUyati", "mantUyate"]); + + let valgu = d("valgu", Kandvadi); + assert_has_lat(&[], &valgu, &["valgUyati"]); + + let as_ = d("asu~", Kandvadi); + assert_has_lat(&[], &as_, &["asyati"]); + + let asu = d("asU", Kandvadi); + assert_has_lat(&[], &asu, &["asUyati"]); + + let asu = d("asUY", Kandvadi); + assert_has_lat(&[], &asu, &["asUyati", "asUyate"]); + + let lew = d("lew", Kandvadi); + assert_has_lat(&[], &lew, &["lewyati"]); + assert_has_lut(&[], &lew, &["lewitA"]); + + let low = d("low", Kandvadi); + assert_has_lat(&[], &low, &["lowyati"]); + assert_has_lut(&[], &low, &["lowitA"]); + + let iras = d("iras", Kandvadi); + assert_has_lat(&[], &iras, &["irasyati"]); + + let iraj = d("iraj", Kandvadi); + assert_has_lat(&[], &iraj, &["irajyati"]); + + let ira = d("iraY", Kandvadi); + assert_has_lat(&[], &ira, &["Iryati", "Iryate"]); + + let medha = d("meDA", Kandvadi); + assert_has_lat(&[], &medha, &["meDAyati"]); + + let kushubha = d("kuzuBa", Kandvadi); + assert_has_lat(&[], &kushubha, &["kuzuByati"]); + + let sukha = d("suKa", Kandvadi); + assert_has_lat(&[], &sukha, &["suKyati"]); + + let duhkha = d("duHKa", Kandvadi); + assert_has_lat(&[], &duhkha, &["duHKyati"]); + + let lekha = d("leKa", Kandvadi); + assert_has_lat(&[], &lekha, &["leKyati"]); + + let lita = d("liwa", Kandvadi); + assert_has_lat(&[], &lita, &["liwyati"]); + + let mahi = d("mahIN", Kandvadi); + assert_has_lat(&[], &mahi, &["mahIyate"]); + + let uras = d("uras", Kandvadi); + assert_has_lat(&[], &uras, &["urasyati"]); +} diff --git a/vidyut-prakriya/tests/kaumudi_67.rs b/vidyut-prakriya/tests/kaumudi_67.rs index f7276bb..2ab824e 100644 --- a/vidyut-prakriya/tests/kaumudi_67.rs +++ b/vidyut-prakriya/tests/kaumudi_67.rs @@ -416,6 +416,73 @@ fn unadi_4_189() { assert_has_krdanta(&[], &d("rapa~", Bhvadi), Unadi::asun, &["repas"]); } +#[test] +fn unadi_5_2() { + assert_has_krdanta(&[], &d("guDa~", Divadi), Unadi::Uma, &["goDUma"]); +} + +#[test] +fn unadi_5_3() { + assert_has_krdanta(&[], &d("masI~", Divadi), Unadi::Uran, &["masUra"]); +} + +#[test] +fn unadi_5_4() { + assert_has_krdanta(&[], &d("zWA\\", Bhvadi), Unadi::Uran, &["sTUra"]); +} + +#[test] +fn unadi_5_5() { + assert_has_krdanta(&[], &d("pA\\", Adadi), Unadi::ati_, &["pAti"]); +} + +#[test] +fn unadi_5_6() { + assert_has_krdanta(&[], &d("vA\\", Adadi), Unadi::ati_, &["vAti"]); +} + +#[test] +fn unadi_5_7() { + assert_has_krdanta(&[], &d("f\\", Bhvadi), Unadi::ati_, &["arati"]); +} + +#[test] +fn unadi_5_8() { + assert_has_krdanta(&[], &d("tfhU~", Tudadi), Unadi::kna, &["tfRa"]); +} + +#[ignore] +#[test] +fn unadi_5_12() { + assert_has_krdanta(&["ud"], &d("ci\\Y", Svadi), Unadi::qEsi, &["uccEH"]); +} + +#[ignore] +#[test] +fn unadi_5_13() { + assert_has_krdanta(&["ni"], &d("ci\\Y", Svadi), Unadi::qEsi, &["nIcEH"]); +} + +#[test] +fn unadi_5_15() { + assert_has_krdanta(&[], &d("pUY", Kryadi), Unadi::yat, &["puRya"]); +} + +#[test] +fn unadi_5_22() { + assert_has_krdanta(&[], &d("mu\\ha~", Divadi), Unadi::Ka, &["mUrKa"]); +} + +#[test] +fn unadi_5_23() { + assert_has_krdanta(&[], &d("Ra\\ha~^", Divadi), Unadi::Ka, &["naKa"]); +} + +#[test] +fn unadi_5_25() { + assert_has_krdanta(&[], &d("mA\\N", Divadi), Unadi::UKa, &["mayUKa"]); +} + #[test] fn unadi_5_68() { assert_has_krdanta(&[], &d("praTa~\\", Bhvadi), Unadi::amac, &["praTama"]); diff --git a/vidyut-prakriya/tests/regressions.rs b/vidyut-prakriya/tests/regressions.rs index bb790eb..3564b71 100644 --- a/vidyut-prakriya/tests/regressions.rs +++ b/vidyut-prakriya/tests/regressions.rs @@ -6,7 +6,7 @@ use vidyut_prakriya::args::Lakara::*; #[test] fn ambibat() { - assert_has_tip(&[], &d("abi~", Curadi), Lun, &["Ambibat"]); + assert_has_tip(&[], &nic(&d("abi~", Bhvadi)), Lun, &["Ambibat"]); } #[test] diff --git a/vidyut-prakriya/www/index.html b/vidyut-prakriya/www/index.html index 443bf5d..29ce49e 100644 --- a/vidyut-prakriya/www/index.html +++ b/vidyut-prakriya/www/index.html @@ -104,12 +104,12 @@

@@ -221,32 +221,32 @@

+

Note: the krt-pratyaya forms below overgenerate and might use + pratyayas that are not explicitly allowed for this dhatu.

- + +
@@ -320,12 +320,12 @@

diff --git a/vidyut-prakriya/www/static/app.js b/vidyut-prakriya/www/static/app.js index 16c98e1..8c39b49 100644 --- a/vidyut-prakriya/www/static/app.js +++ b/vidyut-prakriya/www/static/app.js @@ -34,6 +34,7 @@ function parseSutras(tsv) { return sutras; } const sutras = fetch("/static/data/sutrapatha.tsv").then(resp => resp.text()).then(text => parseSutras(text)); +const varttikas = fetch("/static/data/varttikas.tsv").then(resp => resp.text()).then(text => parseSutras(text)); // Parse a dhatupatha string into separate objects. function parseDhatus(text) { @@ -57,7 +58,7 @@ class Vidyut { constructor(dhatupatha) { this.wasm = VidyutWasm.init(dhatupatha); this.dhatus = parseDhatus(dhatupatha); - console.log("constructed Vidyut."); + console.log("Constructed Vidyut."); } @@ -100,39 +101,6 @@ class Vidyut { // Frontend // =================================================== -// Krts that create ordinary nouns. -const NOMINAL_KRTS = [ - BaseKrt.GaY, - BaseKrt.lyuw, - BaseKrt.Rvul, - BaseKrt.tfc, - BaseKrt.kvip, -]; - -// Krts that are generally called *participles*. -const PARTICIPLE_KRTS = [ - BaseKrt.tavya, - BaseKrt.anIyar, - BaseKrt.yat, - BaseKrt.Ryat, - - BaseKrt.Satf, - BaseKrt.SAnac, - - BaseKrt.kta, - BaseKrt.ktavatu, - - BaseKrt.kvasu, - BaseKrt.kAnac, -]; - -// Krts that create avyayas. -const AVYAYA_KRTS = [ - BaseKrt.tumun, - BaseKrt.ktvA, - BaseKrt.Ramul, -]; - // What to call these params in the URL. const Params = { Dhatu: "dhatu", @@ -190,6 +158,7 @@ const App = () => ({ // data sutras: {}, + varttikas: {}, // Transliteration script (devanagari, iast, telugu, etc.) script: 'devanagari', @@ -203,7 +172,7 @@ const App = () => ({ // Vidyut needs its own copy of the dhatupatha. this.vidyut = new Vidyut(dhatupatha); - console.log("initialized vidyut-prakriya WASM bindings."); + console.log("Initialized vidyut-prakriya WASM bindings."); this.dhatus = this.vidyut.dhatus; @@ -232,6 +201,7 @@ const App = () => ({ }); this.sutras = await sutras; + this.varttikas = await varttikas; }, // Mutators @@ -302,7 +272,6 @@ const App = () => ({ this.activePada = p; if (p.type === "subanta") { this.supPrakriya = this.createPrakriya(); - console.log(this.supPrakriya); } else { this.dhatuPrakriya = this.createPrakriya(); } @@ -400,9 +369,51 @@ const App = () => ({ return Sanscript.t(removeSlpSvaras(s), 'slp1', this.script); }, - sutraText(rule) { - const text = this.sutras[rule]; - return text ? this.deva(text) : ''; + renderStepRule(rule) { + if (rule.source === "ashtadhyayi") { + let text = this.sutras[rule.code]; + return text ? this.deva(text) : ''; + } else if (rule.source === "varttika") { + let text = this.varttikas[rule.code]; + text = this.deva(text || ""); + if (text) { + return `${text}`; + } else { + return ''; + } + } else { + return "(missing)" + } + }, + + renderStepRuleLinkText(rule) { + let prefix = ""; + if (rule.source === "varttika") { + prefix = "vArttika "; + } else if (rule.source === "kaumudi") { + prefix = "kOmudI "; + } else if (rule.source === "unadi") { + prefix = "uRAdi "; + } else if (rule.source === "linganushasanam") { + prefix = "liNgA "; + } else if (rule.source === "dhatupatha") { + prefix = "DAtupAWa "; + } else if (rule.source === "phit") { + prefix = "Piw "; + } + + const text = prefix + rule.code; + return this.deva(text).replaceAll('।', '.') + }, + + renderStepRuleLink(rule) { + if (rule.source === "ashtadhyayi" || rule.source === "varttika") { + return "https://ashtadhyayi.com/sutraani/" + rule.code; + } else if (rule.source === "kaumudi") { + return "https://ashtadhyayi.com/sutraani/sk" + rule.code; + } else { + return "https://ashtadhyayi.com"; + } }, entryString(entries) { @@ -411,7 +422,7 @@ const App = () => ({ }, stepClasses(step) { - const code = step.rule; + const code = step.rule.code; let minor = new Set(["1.3.1", "1.3.2", "1.3.3", "1.3.4", "1.3.5", "1.3.6", "1.3.7", "1.3.8", "1.3.9", "1.2.45", "1.2.46", "3.4.114", "1.1.43", "1.4.14", "1.4.58", "1.4.59", "1.4.60", "1.4.80", "3.1.32", "6.1.4", "6.1.5", "8.4.68", "3.4.113", "2.3.48", "1.4.17", "2.3.49", "1.4.7", ]); @@ -424,12 +435,16 @@ const App = () => ({ renderStepResult(step) { let res = ""; - step.result.forEach((val, i) => { + step.result.forEach((term, i) => { + // Skip empty terms since traditional prakriyas expect this to be done. + if (term.text.length === 0) { + return; + } if (res.length !== 0) { res += ' + '; } - let text = Sanscript.t(removeSlpSvaras(val), 'slp1', this.script); - if (i === step.active) { + let text = Sanscript.t(removeSlpSvaras(term.text), 'slp1', this.script); + if (term.wasChanged) { text = `${text}` } res += text; @@ -695,32 +710,32 @@ const App = () => ({ const sanadi = this.sanadi; let ret = []; - [NOMINAL_KRTS, PARTICIPLE_KRTS, AVYAYA_KRTS].forEach((list) => { - let table = []; - list.forEach((krt) => { - const args = { - dhatu, - krt, - upasarga, - sanadi, - }; + const krts = Object.values(BaseKrt).filter(Number.isInteger); + + krts.forEach((krt) => { + const args = { + dhatu, + krt, + upasarga, + sanadi, + }; - const prakriyas = this.vidyut.deriveKrdantas(args) - let padas = []; - prakriyas.forEach((p) => { - padas.push({ - text: p.text, - type: "krdanta", - args - }); + const prakriyas = this.vidyut.deriveKrdantas(args) + let padas = []; + prakriyas.forEach((p) => { + padas.push({ + text: p.text, + type: "krdanta", + args }); + }); - table.push({ + if (padas.length !== 0) { + ret.push({ title: BaseKrt[krt], padas, }); - }); - ret.push(table); + } }); return ret; }, @@ -762,7 +777,6 @@ const App = () => ({ results.push(laResults); } - console.log(results); return results; }, });