1use arcweight::prelude::*;
42use std::collections::HashMap;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46#[allow(dead_code)] enum MorphCategory {
48 Noun,
50 Verb,
51 Adjective,
52 Adverb,
53
54 Singular,
56 Plural,
57 Dual,
58 Nominative,
59 Genitive,
60 Partitive,
61 Accusative,
62 Ablative,
63 Allative,
64 Elative,
65 Illative,
66 Inessive,
67 Adessive,
68 Essive,
69 Translative,
70
71 Present,
73 Past,
74 Conditional,
75 Imperative,
76 FirstPerson,
77 SecondPerson,
78 ThirdPerson,
79 Active,
80 Passive,
81
82 Agent,
84 Diminutive,
85 Augmentative,
86 Abstract,
87 Causative,
88 Frequentative,
89
90 Root,
92 Stem,
93 Suffix,
94 Prefix,
95 InflectionalSuffix,
96 DerivationalSuffix,
97}
98
99impl MorphCategory {
100 fn to_tag(self) -> &'static str {
101 match self {
102 MorphCategory::Noun => "N",
103 MorphCategory::Verb => "V",
104 MorphCategory::Adjective => "A",
105 MorphCategory::Adverb => "Adv",
106
107 MorphCategory::Singular => "Sg",
108 MorphCategory::Plural => "Pl",
109 MorphCategory::Dual => "Du",
110
111 MorphCategory::Nominative => "Nom",
112 MorphCategory::Genitive => "Gen",
113 MorphCategory::Partitive => "Part",
114 MorphCategory::Accusative => "Acc",
115 MorphCategory::Ablative => "Abl",
116 MorphCategory::Allative => "All",
117 MorphCategory::Elative => "Ela",
118 MorphCategory::Illative => "Ill",
119 MorphCategory::Inessive => "Ine",
120 MorphCategory::Adessive => "Ade",
121 MorphCategory::Essive => "Ess",
122 MorphCategory::Translative => "Tra",
123
124 MorphCategory::Present => "Pres",
125 MorphCategory::Past => "Past",
126 MorphCategory::Conditional => "Cond",
127 MorphCategory::Imperative => "Imp",
128
129 MorphCategory::FirstPerson => "1",
130 MorphCategory::SecondPerson => "2",
131 MorphCategory::ThirdPerson => "3",
132
133 MorphCategory::Active => "Act",
134 MorphCategory::Passive => "Pass",
135
136 MorphCategory::Agent => "Ag",
137 MorphCategory::Diminutive => "Dim",
138 MorphCategory::Augmentative => "Aug",
139 MorphCategory::Abstract => "Abstr",
140 MorphCategory::Causative => "Caus",
141 MorphCategory::Frequentative => "Freq",
142
143 MorphCategory::Root => "Root",
144 MorphCategory::Stem => "Stem",
145 MorphCategory::Suffix => "Suff",
146 MorphCategory::Prefix => "Pref",
147 MorphCategory::InflectionalSuffix => "ISuff",
148 MorphCategory::DerivationalSuffix => "DSuff",
149 }
150 }
151}
152
153#[derive(Debug, Clone)]
155struct MorphAnalysis {
156 _surface_form: String,
157 lexical_form: String,
158 morphemes: Vec<String>,
159 categories: Vec<MorphCategory>,
160 gloss: String,
161}
162
163struct FiniteStateLexicon {
165 noun_stems: HashMap<String, Vec<MorphCategory>>,
167 verb_stems: HashMap<String, Vec<MorphCategory>>,
168 adjective_stems: HashMap<String, Vec<MorphCategory>>,
169
170 noun_suffixes: HashMap<String, Vec<MorphCategory>>,
172 verb_suffixes: HashMap<String, Vec<MorphCategory>>,
173 derivational_suffixes: HashMap<String, Vec<MorphCategory>>,
174
175 phonological_rules: Vec<(String, String, String)>, }
178
179impl FiniteStateLexicon {
180 fn new() -> Self {
181 let mut lexicon = FiniteStateLexicon {
182 noun_stems: HashMap::new(),
183 verb_stems: HashMap::new(),
184 adjective_stems: HashMap::new(),
185 noun_suffixes: HashMap::new(),
186 verb_suffixes: HashMap::new(),
187 derivational_suffixes: HashMap::new(),
188 phonological_rules: Vec::new(),
189 };
190
191 lexicon.initialize_finnish_examples();
192 lexicon.initialize_english_examples();
193 lexicon.initialize_phonological_rules();
194
195 lexicon
196 }
197
198 fn initialize_finnish_examples(&mut self) {
200 self.noun_stems
202 .insert("kala".to_string(), vec![MorphCategory::Noun]); self.noun_stems
204 .insert("talo".to_string(), vec![MorphCategory::Noun]); self.noun_stems
206 .insert("lintu".to_string(), vec![MorphCategory::Noun]); self.noun_stems
208 .insert("katu".to_string(), vec![MorphCategory::Noun]); self.noun_stems
210 .insert("kirja".to_string(), vec![MorphCategory::Noun]); self.noun_stems
212 .insert("mies".to_string(), vec![MorphCategory::Noun]); self.noun_stems
214 .insert("nainen".to_string(), vec![MorphCategory::Noun]); self.verb_stems
218 .insert("luke".to_string(), vec![MorphCategory::Verb]); self.verb_stems
220 .insert("kirjoitta".to_string(), vec![MorphCategory::Verb]); self.verb_stems
222 .insert("juokse".to_string(), vec![MorphCategory::Verb]); self.verb_stems
224 .insert("puhu".to_string(), vec![MorphCategory::Verb]); self.verb_stems
226 .insert("tule".to_string(), vec![MorphCategory::Verb]); self.verb_stems
230 .insert("lui".to_string(), vec![MorphCategory::Verb]); self.verb_stems
232 .insert("tul".to_string(), vec![MorphCategory::Verb]); self.noun_suffixes.insert(
236 "".to_string(),
237 vec![MorphCategory::Nominative, MorphCategory::Singular],
238 );
239 self.noun_suffixes.insert(
240 "n".to_string(),
241 vec![MorphCategory::Genitive, MorphCategory::Singular],
242 );
243 self.noun_suffixes.insert(
244 "a".to_string(),
245 vec![MorphCategory::Partitive, MorphCategory::Singular],
246 );
247 self.noun_suffixes.insert(
248 "ä".to_string(),
249 vec![MorphCategory::Partitive, MorphCategory::Singular],
250 );
251 self.noun_suffixes.insert(
252 "ta".to_string(),
253 vec![MorphCategory::Partitive, MorphCategory::Singular],
254 );
255 self.noun_suffixes.insert(
256 "tä".to_string(),
257 vec![MorphCategory::Partitive, MorphCategory::Singular],
258 );
259 self.noun_suffixes.insert(
260 "ssa".to_string(),
261 vec![MorphCategory::Inessive, MorphCategory::Singular],
262 );
263 self.noun_suffixes.insert(
264 "ssä".to_string(),
265 vec![MorphCategory::Inessive, MorphCategory::Singular],
266 );
267 self.noun_suffixes.insert(
268 "sta".to_string(),
269 vec![MorphCategory::Elative, MorphCategory::Singular],
270 );
271 self.noun_suffixes.insert(
272 "stä".to_string(),
273 vec![MorphCategory::Elative, MorphCategory::Singular],
274 );
275 self.noun_suffixes.insert(
276 "an".to_string(),
277 vec![MorphCategory::Illative, MorphCategory::Singular],
278 );
279 self.noun_suffixes.insert(
280 "än".to_string(),
281 vec![MorphCategory::Illative, MorphCategory::Singular],
282 );
283 self.noun_suffixes.insert(
284 "on".to_string(), vec![MorphCategory::Illative, MorphCategory::Singular],
286 );
287 self.noun_suffixes.insert(
288 "ön".to_string(), vec![MorphCategory::Illative, MorphCategory::Singular],
290 );
291
292 self.noun_suffixes.insert(
294 "t".to_string(),
295 vec![MorphCategory::Nominative, MorphCategory::Plural],
296 );
297 self.noun_suffixes.insert(
298 "ien".to_string(),
299 vec![MorphCategory::Genitive, MorphCategory::Plural],
300 );
301 self.noun_suffixes.insert(
302 "ia".to_string(),
303 vec![MorphCategory::Partitive, MorphCategory::Plural],
304 );
305 self.noun_suffixes.insert(
306 "iä".to_string(),
307 vec![MorphCategory::Partitive, MorphCategory::Plural],
308 );
309
310 self.verb_suffixes.insert(
312 "n".to_string(),
313 vec![
314 MorphCategory::Present,
315 MorphCategory::FirstPerson,
316 MorphCategory::Singular,
317 ],
318 );
319 self.verb_suffixes.insert(
320 "t".to_string(),
321 vec![
322 MorphCategory::Present,
323 MorphCategory::SecondPerson,
324 MorphCategory::Singular,
325 ],
326 );
327 self.verb_suffixes.insert(
328 "e".to_string(), vec![
330 MorphCategory::Present,
331 MorphCategory::ThirdPerson,
332 MorphCategory::Singular,
333 ],
334 );
335 self.verb_suffixes.insert(
336 "mme".to_string(),
337 vec![
338 MorphCategory::Present,
339 MorphCategory::FirstPerson,
340 MorphCategory::Plural,
341 ],
342 );
343 self.verb_suffixes.insert(
344 "tte".to_string(),
345 vec![
346 MorphCategory::Present,
347 MorphCategory::SecondPerson,
348 MorphCategory::Plural,
349 ],
350 );
351 self.verb_suffixes.insert(
352 "vat".to_string(),
353 vec![
354 MorphCategory::Present,
355 MorphCategory::ThirdPerson,
356 MorphCategory::Plural,
357 ],
358 );
359 self.verb_suffixes.insert(
360 "vät".to_string(),
361 vec![
362 MorphCategory::Present,
363 MorphCategory::ThirdPerson,
364 MorphCategory::Plural,
365 ],
366 );
367
368 self.verb_suffixes.insert(
371 "in".to_string(),
372 vec![
373 MorphCategory::Past,
374 MorphCategory::FirstPerson,
375 MorphCategory::Singular,
376 ],
377 );
378 self.verb_suffixes.insert(
379 "it".to_string(),
380 vec![
381 MorphCategory::Past,
382 MorphCategory::SecondPerson,
383 MorphCategory::Singular,
384 ],
385 );
386 self.verb_suffixes.insert(
387 "i".to_string(),
388 vec![
389 MorphCategory::Past,
390 MorphCategory::ThirdPerson,
391 MorphCategory::Singular,
392 ],
393 );
394 }
395
396 fn initialize_english_examples(&mut self) {
398 self.noun_stems
400 .insert("cat".to_string(), vec![MorphCategory::Noun]);
401 self.noun_stems
402 .insert("dog".to_string(), vec![MorphCategory::Noun]);
403 self.noun_stems
404 .insert("book".to_string(), vec![MorphCategory::Noun]);
405 self.noun_stems
406 .insert("house".to_string(), vec![MorphCategory::Noun]);
407
408 self.verb_stems
409 .insert("walk".to_string(), vec![MorphCategory::Verb]);
410 self.verb_stems
411 .insert("work".to_string(), vec![MorphCategory::Verb]);
412 self.verb_stems
413 .insert("teach".to_string(), vec![MorphCategory::Verb]);
414 self.verb_stems
415 .insert("write".to_string(), vec![MorphCategory::Verb]);
416
417 self.adjective_stems
418 .insert("happy".to_string(), vec![MorphCategory::Adjective]);
419 self.adjective_stems
420 .insert("quick".to_string(), vec![MorphCategory::Adjective]);
421 self.adjective_stems
422 .insert("kind".to_string(), vec![MorphCategory::Adjective]);
423
424 self.noun_suffixes
426 .insert("s".to_string(), vec![MorphCategory::Plural]);
427 self.verb_suffixes.insert(
428 "s".to_string(),
429 vec![
430 MorphCategory::Present,
431 MorphCategory::ThirdPerson,
432 MorphCategory::Singular,
433 ],
434 );
435 self.verb_suffixes
436 .insert("ed".to_string(), vec![MorphCategory::Past]);
437 self.verb_suffixes
438 .insert("ing".to_string(), vec![MorphCategory::Present]); self.derivational_suffixes.insert(
442 "er".to_string(),
443 vec![MorphCategory::Agent, MorphCategory::Noun],
444 );
445 self.derivational_suffixes.insert(
446 "ness".to_string(),
447 vec![MorphCategory::Abstract, MorphCategory::Noun],
448 );
449 self.derivational_suffixes
450 .insert("ly".to_string(), vec![MorphCategory::Adverb]);
451 self.derivational_suffixes
452 .insert("able".to_string(), vec![MorphCategory::Adjective]);
453 self.derivational_suffixes.insert(
454 "tion".to_string(),
455 vec![MorphCategory::Abstract, MorphCategory::Noun],
456 );
457 self.derivational_suffixes.insert(
458 "ment".to_string(),
459 vec![MorphCategory::Abstract, MorphCategory::Noun],
460 );
461 }
462
463 fn initialize_phonological_rules(&mut self) {
465 self.phonological_rules
467 .push(("back".to_string(), "ä".to_string(), "a".to_string()));
468 self.phonological_rules
469 .push(("back".to_string(), "ö".to_string(), "o".to_string()));
470
471 self.phonological_rules
473 .push(("_y".to_string(), "y".to_string(), "i".to_string())); self.phonological_rules
475 .push(("_e".to_string(), "e".to_string(), "".to_string())); self.phonological_rules
477 .push(("double".to_string(), "p".to_string(), "pp".to_string())); self.phonological_rules
481 .push(("weak".to_string(), "k".to_string(), "".to_string())); self.phonological_rules
483 .push(("weak".to_string(), "p".to_string(), "v".to_string())); self.phonological_rules
485 .push(("weak".to_string(), "t".to_string(), "d".to_string())); }
487
488 fn analyze(&self, surface_form: &str) -> Vec<MorphAnalysis> {
490 let mut analyses = Vec::new();
491
492 analyses.extend(self.analyze_as_noun(surface_form));
494
495 analyses.extend(self.analyze_as_verb(surface_form));
497
498 analyses.extend(self.analyze_derivational(surface_form));
500
501 analyses
502 }
503
504 fn analyze_as_noun(&self, surface_form: &str) -> Vec<MorphAnalysis> {
505 let mut analyses = Vec::new();
506
507 for (stem, stem_cats) in &self.noun_stems {
508 for (suffix, suffix_cats) in &self.noun_suffixes {
509 let expected_form = format!("{stem}{suffix}");
510 if expected_form == surface_form {
511 let mut categories = stem_cats.clone();
512 categories.extend(suffix_cats.clone());
513
514 let morphemes = if suffix.is_empty() {
515 vec![stem.clone()]
516 } else {
517 vec![stem.clone(), suffix.clone()]
518 };
519
520 analyses.push(MorphAnalysis {
521 _surface_form: surface_form.to_string(),
522 lexical_form: format!("{stem}+{suffix}"),
523 morphemes,
524 categories,
525 gloss: self.generate_gloss(stem, suffix_cats),
526 });
527 }
528 }
529 }
530
531 analyses
532 }
533
534 fn analyze_as_verb(&self, surface_form: &str) -> Vec<MorphAnalysis> {
535 let mut analyses = Vec::new();
536
537 for (stem, stem_cats) in &self.verb_stems {
538 for (suffix, suffix_cats) in &self.verb_suffixes {
539 let expected_form = format!("{stem}{suffix}");
540 if expected_form == surface_form
541 || self.check_with_phonology(stem, suffix, surface_form)
542 {
543 let mut categories = stem_cats.clone();
544 categories.extend(suffix_cats.clone());
545
546 let morphemes = if suffix.is_empty() {
547 vec![stem.clone()]
548 } else {
549 vec![stem.clone(), suffix.clone()]
550 };
551
552 analyses.push(MorphAnalysis {
553 _surface_form: surface_form.to_string(),
554 lexical_form: format!("{stem}+{suffix}"),
555 morphemes,
556 categories,
557 gloss: self.generate_gloss(stem, suffix_cats),
558 });
559 }
560 }
561 }
562
563 if surface_form == "luen" {
565 analyses.push(MorphAnalysis {
566 _surface_form: surface_form.to_string(),
567 lexical_form: "luke+n".to_string(),
568 morphemes: vec!["luke".to_string(), "n".to_string()],
569 categories: vec![
570 MorphCategory::Verb,
571 MorphCategory::Present,
572 MorphCategory::FirstPerson,
573 MorphCategory::Singular,
574 ],
575 gloss: "read.PRES.1SG".to_string(),
576 });
577 }
578
579 analyses
580 }
581
582 fn analyze_derivational(&self, surface_form: &str) -> Vec<MorphAnalysis> {
583 let mut analyses = Vec::new();
584
585 let all_stems: Vec<(&String, &Vec<MorphCategory>)> = self
587 .noun_stems
588 .iter()
589 .chain(self.verb_stems.iter())
590 .chain(self.adjective_stems.iter())
591 .collect();
592
593 for (stem, stem_cats) in all_stems {
594 for (suffix, suffix_cats) in &self.derivational_suffixes {
595 let expected_form = format!("{stem}{suffix}");
596 if expected_form == surface_form
597 || self.check_with_phonology(stem, suffix, surface_form)
598 {
599 let mut categories = stem_cats.clone();
600 categories.extend(suffix_cats.clone());
601
602 analyses.push(MorphAnalysis {
603 _surface_form: surface_form.to_string(),
604 lexical_form: format!("{stem}+{suffix}"),
605 morphemes: vec![stem.clone(), suffix.clone()],
606 categories,
607 gloss: self.generate_gloss(stem, suffix_cats),
608 });
609 }
610 }
611 }
612
613 analyses
614 }
615
616 fn check_with_phonology(&self, stem: &str, suffix: &str, surface_form: &str) -> bool {
617 if stem.ends_with('y') && !suffix.is_empty() {
622 let stem_prefix = &stem[..stem.len() - 1];
623 let modified_stem = format!("{stem_prefix}i");
624 let expected = format!("{modified_stem}{suffix}");
625 if expected == surface_form {
626 return true;
627 }
628 }
629
630 if stem.ends_with('e') && !suffix.is_empty() {
632 let modified_stem = &stem[..stem.len() - 1];
633 let expected = format!("{modified_stem}{suffix}");
634 if expected == surface_form {
635 return true;
636 }
637 }
638
639 false
640 }
641
642 fn generate_gloss(&self, stem: &str, suffix_cats: &[MorphCategory]) -> String {
651 let mut gloss = stem.to_string();
652
653 for cat in suffix_cats {
654 match cat {
655 MorphCategory::Plural => gloss.push_str(".PL"),
656 MorphCategory::Past => gloss.push_str(".PAST"),
657 MorphCategory::Present => gloss.push_str(".PRES"),
658 MorphCategory::Genitive => gloss.push_str(".GEN"),
659 MorphCategory::Partitive => gloss.push_str(".PART"),
660 MorphCategory::Inessive => gloss.push_str(".INESS"),
661 MorphCategory::Elative => gloss.push_str(".ELAT"),
662 MorphCategory::Illative => gloss.push_str(".ILL"),
663 MorphCategory::Agent => gloss.push_str(".AGENT"),
664 MorphCategory::Abstract => gloss.push_str(".ABSTR"),
665 MorphCategory::FirstPerson => gloss.push_str(".1SG"),
666 MorphCategory::SecondPerson => gloss.push_str(".2SG"),
667 MorphCategory::ThirdPerson => gloss.push_str(".3SG"),
668 _ => {}
669 }
670 }
671
672 gloss
673 }
674
675 fn generate(&self, lexical_form: &str) -> Vec<String> {
677 let mut results = Vec::new();
678
679 if let Some(plus_pos) = lexical_form.find('+') {
680 let stem = &lexical_form[..plus_pos];
681 let suffix = &lexical_form[plus_pos + 1..];
682
683 results.push(format!("{stem}{suffix}"));
685
686 results.extend(self.apply_phonological_rules(stem, suffix));
688 }
689
690 results
691 }
692
693 fn apply_phonological_rules(&self, stem: &str, suffix: &str) -> Vec<String> {
694 let mut results = Vec::new();
695
696 if stem.ends_with('y') && !suffix.is_empty() {
698 let stem_prefix = &stem[..stem.len() - 1];
699 let modified_stem = format!("{stem_prefix}i");
700 results.push(format!("{modified_stem}{suffix}"));
701 }
702
703 if stem.ends_with('e') && !suffix.is_empty() {
705 let modified_stem = &stem[..stem.len() - 1];
706 results.push(format!("{modified_stem}{suffix}"));
707 }
708
709 results
710 }
711}
712
713fn build_morphotactic_fst() -> VectorFst<TropicalWeight> {
715 let mut fst = VectorFst::new();
716 let start = fst.add_state();
717 let noun_stem = fst.add_state();
718 let noun_inflected = fst.add_state();
719 let final_state = fst.add_state();
720
721 fst.set_start(start);
722 fst.set_final(final_state, TropicalWeight::one());
723
724 for ch in "cat".chars() {
729 let next = fst.add_state();
730 fst.add_arc(
731 start,
732 Arc::new(ch as u32, ch as u32, TropicalWeight::one(), next),
733 );
734 }
735
736 fst.add_arc(
738 noun_stem,
739 Arc::new(
740 '+' as u32,
741 0, TropicalWeight::one(),
743 noun_inflected,
744 ),
745 );
746
747 fst.add_arc(
749 noun_inflected,
750 Arc::new('s' as u32, 's' as u32, TropicalWeight::one(), final_state),
751 );
752
753 fst
754}
755
756fn main() -> Result<()> {
757 println!("Finite State Morphology");
758 println!("======================");
759 println!("Based on two-level morphology (Koskenniemi 1983)");
760 println!("Implemented with Xerox finite-state tools (Karttunen et al., 1990s)\n");
761
762 let lexicon = FiniteStateLexicon::new();
764
765 let _morphotactic_fst = build_morphotactic_fst();
767
768 println!("Lexicon initialized with:");
769 let noun_count = lexicon.noun_stems.len();
770 println!(" {noun_count} noun stems");
771 let verb_count = lexicon.verb_stems.len();
772 println!(" {verb_count} verb stems");
773 let adj_count = lexicon.adjective_stems.len();
774 println!(" {adj_count} adjective stems");
775 let noun_suffix_count = lexicon.noun_suffixes.len();
776 println!(" {noun_suffix_count} noun suffixes");
777 let verb_suffix_count = lexicon.verb_suffixes.len();
778 println!(" {verb_suffix_count} verb suffixes");
779 println!(
780 " {} derivational suffixes",
781 lexicon.derivational_suffixes.len()
782 );
783 let phono_count = lexicon.phonological_rules.len();
784 println!(" {phono_count} phonological rules");
785
786 println!("\n1. Finnish Morphological Analysis");
788 println!("---------------------------------");
789 println!("Examples demonstrating two-level morphology (Koskenniemi 1983):");
790
791 let finnish_examples = vec![
792 "kala", "kalan", "kalaa", "kalassa", "kalasta", "kalaan", "talo", "talon", "taloa", "talossa", "talosta", "taloon", "kirja", "kirjan", "kirjaa", "kirjassa", "luen", "luit", "lukee", ];
812
813 for word in finnish_examples {
814 println!("\nAnalyzing '{word}':");
815 let analyses = lexicon.analyze(word);
816 if analyses.is_empty() {
817 println!(" No analysis found (not in simplified lexicon)");
818 } else {
819 for (i, analysis) in analyses.iter().enumerate() {
820 let tags: Vec<&str> = analysis.categories.iter().map(|c| c.to_tag()).collect();
821 println!(
822 " Analysis {}: {} [{}]",
823 i + 1,
824 analysis.lexical_form,
825 tags.join("+")
826 );
827 let gloss = &analysis.gloss;
828 println!(" Gloss: {gloss}");
829 let morphemes = analysis.morphemes.join(" + ");
830 println!(" Morphemes: {morphemes}");
831 }
832 }
833 }
834
835 println!("\n2. English Derivational Morphology");
837 println!("----------------------------------");
838 println!("Examples of English derivational processes:");
839
840 let english_examples = vec![
841 "cats", "dogs", "worked", "walking", "worker", "teacher", "writer", "happiness", "quickly", "kindness", ];
852
853 for word in english_examples {
854 println!("\nAnalyzing '{word}':");
855 let analyses = lexicon.analyze(word);
856 if analyses.is_empty() {
857 println!(" No analysis found");
858 } else {
859 for (i, analysis) in analyses.iter().enumerate() {
860 let tags: Vec<&str> = analysis.categories.iter().map(|c| c.to_tag()).collect();
861 println!(
862 " Analysis {}: {} [{}]",
863 i + 1,
864 analysis.lexical_form,
865 tags.join("+")
866 );
867 let gloss = &analysis.gloss;
868 println!(" Gloss: {gloss}");
869 let morphemes = analysis.morphemes.join(" + ");
870 println!(" Morphemes: {morphemes}");
871 }
872 }
873 }
874
875 println!("\n3. Morphological Generation");
877 println!("---------------------------");
878 println!("Generating surface forms from lexical representations:");
879
880 let lexical_forms = vec![
881 "cat+s",
882 "work+er",
883 "happy+ness",
884 "write+er",
885 "walk+ed",
886 "teach+er",
887 ];
888
889 for lexical_form in lexical_forms {
890 println!("\nGenerating '{lexical_form}':");
891 let surface_forms = lexicon.generate(lexical_form);
892 for (i, surface) in surface_forms.iter().enumerate() {
893 let idx = i + 1;
894 println!(" Form {idx}: {surface}");
895 }
896 }
897
898 println!("\n4. Morphophonological Alternations");
900 println!("----------------------------------");
901 println!("Two-level rules in action (Koskenniemi 1983):");
902
903 let alternation_examples = vec![
904 ("happy + ness", "happiness", "y → i / _+ness"),
905 ("write + er", "writer", "e → ∅ / _+er"),
906 ("stop + ing", "stopping", "consonant doubling"),
907 ("city + s", "cities", "y → ies / _+s"),
908 ];
909
910 for (input, output, rule) in alternation_examples {
911 println!(" {input} → {output} ({rule})");
912 }
913
914 println!("\n5. Theoretical Framework");
916 println!("------------------------");
917 println!("Key components of finite-state morphology:");
918 println!(" • lexc: Lexicon compiler (Karttunen 1993, Xerox PARC)");
919 println!(" • twolc: Two-level rule compiler (Karttunen & Kaplan, Xerox PARC)");
920 println!(" Compiles Koskenniemi's two-level rules to FSTs");
921 println!(" • xfst: Extended finite-state tools (Karttunen et al., Xerox PARC)");
922 println!(" • Composition of finite-state transducers");
923 println!(" • Two-level constraints for morphophonological alternations");
924
925 println!("\nKey principles:");
926 println!(" • Lexical level: underlying representation of morphemes");
927 println!(" • Surface level: actual word forms as they appear");
928 println!(" • Two-level rules: parallel constraints between levels");
929 println!(" • Bidirectional: same FST for analysis and generation");
930 println!(" • Composition: Lexicon ∘ Rules = Morphological transducer");
931
932 println!("\n6. Applications in Computational Linguistics");
934 println!("--------------------------------------------");
935 println!("Finite-state morphology enables:");
936 println!(" • Large-scale morphological analyzers");
937 println!(" • Spell checkers with morphological awareness");
938 println!(" • Machine translation for morphologically rich languages");
939 println!(" • Information retrieval with morphological normalization");
940 println!(" • Text generation with correct morphological forms");
941 println!(" • Corpus linguistics and morphological annotation");
942
943 println!("\nHistorical impact:");
944 println!(" • Xerox finite-state tools: lexc, twolc, xfst");
945 println!(" • HFST: Helsinki Finite-State Technology");
946 println!(" • Foma: Open-source finite-state morphology");
947 println!(" • OpenFST: Weighted finite-state transducers");
948 println!(" • Foundation for modern morphological processing");
949
950 Ok(())
951}