1use crate::analysis::mlist::MorphemeList;
18use crate::analysis::node::{LatticeNode, PathCost, ResultNode};
19use crate::analysis::Mode;
20use crate::dic::subset::InfoSubset;
21use crate::dic::word_id::WordId;
22use crate::dic::word_info::{WordInfo, WordInfoData, WordInfoResolver};
23use crate::dic::{DictionaryAccess, LexiconAccess};
24use crate::error::{SudachiError, SudachiResult};
25use crate::input_text::InputTextIndex;
26use std::borrow::Cow;
27use std::cell::Ref;
28use std::fmt::{Debug, Display, Formatter};
29use std::ops::Deref;
30
31pub enum MorphemeSurface<'a> {
37 Input(Ref<'a, str>),
38 Headword(&'a str),
39}
40
41impl Deref for MorphemeSurface<'_> {
42 type Target = str;
43
44 fn deref(&self) -> &Self::Target {
45 match self {
46 MorphemeSurface::Input(surface) => surface.deref(),
47 MorphemeSurface::Headword(surface) => surface,
48 }
49 }
50}
51
52impl AsRef<str> for MorphemeSurface<'_> {
53 fn as_ref(&self) -> &str {
54 self.deref()
55 }
56}
57
58impl Debug for MorphemeSurface<'_> {
59 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
60 Debug::fmt(self.deref(), f)
61 }
62}
63
64impl Display for MorphemeSurface<'_> {
65 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
66 Display::fmt(self.deref(), f)
67 }
68}
69
70mod private {
71 pub trait Sealed {}
72}
73
74pub trait MorphemeView: private::Sealed {
80 type Dictionary: DictionaryAccess;
81
82 #[doc(hidden)]
83 fn dict(&self) -> &Self::Dictionary;
84
85 #[doc(hidden)]
86 fn subset(&self) -> InfoSubset;
87
88 fn begin(&self) -> usize;
90
91 fn end(&self) -> usize;
93
94 fn begin_c(&self) -> usize;
96
97 fn end_c(&self) -> usize;
99
100 fn surface(&self) -> MorphemeSurface<'_>;
102
103 fn part_of_speech_id(&self) -> u16 {
105 self.get_word_info().pos_id()
106 }
107
108 fn word_id(&self) -> WordId;
110
111 fn get_word_info(&self) -> &WordInfo;
113
114 fn self_morpheme(&self) -> MorphemeRef<'_, Self::Dictionary>;
115
116 fn resolver<'a>(&'a self) -> &'a dyn WordInfoResolver
117 where
118 Self::Dictionary: 'a,
119 {
120 self.dict().lexicon()
121 }
122
123 fn part_of_speech<'a>(&'a self) -> &'a [String]
125 where
126 Self::Dictionary: 'a,
127 {
128 self.dict()
129 .grammar()
130 .pos_components(self.part_of_speech_id())
131 }
132
133 fn dictionary_form<'a>(&'a self) -> &'a str
137 where
138 Self::Dictionary: 'a,
139 {
140 self.get_word_info().dictionary_form(self.resolver())
141 }
142
143 fn dictionary_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, Self::Dictionary>>
151 where
152 Self::Dictionary: Clone,
153 {
154 resolve_referenced_form_morpheme(
155 self,
156 InfoSubset::DICTIONARY_FORM,
157 WordInfoData::dictionary_form_word_id,
158 )
159 }
160
161 fn normalized_form<'a>(&'a self) -> &'a str
166 where
167 Self::Dictionary: 'a,
168 {
169 self.get_word_info().normalized_form(self.resolver())
170 }
171
172 fn normalized_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, Self::Dictionary>>
180 where
181 Self::Dictionary: Clone,
182 {
183 resolve_referenced_form_morpheme(
184 self,
185 InfoSubset::NORMALIZED_FORM,
186 WordInfoData::normalized_form_word_id,
187 )
188 }
189
190 fn reading_form<'a>(&'a self) -> &'a str
194 where
195 Self::Dictionary: 'a,
196 {
197 self.get_word_info().reading_form(self.resolver())
198 }
199
200 fn is_oov(&self) -> bool {
202 self.word_id().is_oov()
203 }
204
205 fn dictionary_id(&self) -> i32 {
209 let wid = self.word_id();
210 if wid.is_oov() {
211 -1
212 } else {
213 wid.dict().as_raw() as i32
214 }
215 }
216
217 fn synonym_group_ids(&self) -> &[i32] {
218 self.get_word_info().synonym_group_ids()
219 }
220
221 fn user_data(&self) -> &str {
223 self.get_word_info().user_data()
224 }
225}
226
227pub(crate) fn validate_dictionary_word_id<D: DictionaryAccess>(
228 dict: &D,
229 word_id: WordId,
230) -> SudachiResult<()> {
231 if word_id == WordId::INVALID || word_id.is_oov() || word_id.is_special() {
232 return Err(SudachiError::InvalidWordId(word_id));
233 }
234
235 dict.lexicon().get_word_param_checked(word_id).map(|_| ())
236}
237
238#[allow(clippy::result_large_err)]
239fn resolve_referenced_form_morpheme<'a, M, F>(
240 morpheme: &'a M,
241 reference_subset: InfoSubset,
242 form_word_id: F,
243) -> SudachiResult<MorphemeRef<'a, M::Dictionary>>
244where
245 M: MorphemeView + ?Sized,
246 M::Dictionary: Clone,
247 F: FnOnce(&WordInfoData) -> WordId,
248{
249 let word_id = morpheme.word_id();
250 if word_id.is_oov() || word_id.is_special() {
251 return Ok(morpheme.self_morpheme());
252 }
253
254 let word_info = morpheme
255 .dict()
256 .lexicon()
257 .get_word_info_subset(word_id, reference_subset)?;
258 let form_word_id = form_word_id(word_info.borrow_data());
259 if form_word_id == WordId::INVALID
260 || form_word_id == word_id
261 || form_word_id.is_oov()
262 || form_word_id.is_special()
263 {
264 return Ok(morpheme.self_morpheme());
265 }
266
267 let materialized_subset = (morpheme.subset() | InfoSubset::HEADWORD).normalize();
268
269 SingleMorpheme::from_word_id(morpheme.dict().clone(), form_word_id, materialized_subset)
270 .map(Box::new)
271 .map(MorphemeRef::Single)
272}
273
274pub struct Morpheme<'a, D> {
276 list: &'a MorphemeList<D>,
277 index: usize,
278}
279
280impl<D> Clone for Morpheme<'_, D> {
281 fn clone(&self) -> Self {
282 *self
283 }
284}
285
286impl<D> Copy for Morpheme<'_, D> {}
287
288impl<D: DictionaryAccess + Clone> Morpheme<'_, D> {
289 #[deprecated(note = "use split_into", since = "0.6.1")]
291 pub fn split(&self, mode: Mode) -> SudachiResult<MorphemeList<D>> {
292 #[allow(deprecated)]
293 self.list.split(mode, self.index)
294 }
295}
296
297impl<'a, D: DictionaryAccess> Morpheme<'a, D> {
298 pub(crate) fn for_list(list: &'a MorphemeList<D>, index: usize) -> Self {
299 Morpheme { list, index }
300 }
301
302 #[inline]
303 pub(crate) fn node(&self) -> &ResultNode {
304 self.list.node(self.index)
305 }
306
307 pub fn part_of_speech(&self) -> &[String] {
309 <Self as MorphemeView>::part_of_speech(self)
310 }
311
312 pub fn begin(&self) -> usize {
314 self.list.input().to_orig_byte_idx(self.node().begin())
315 }
316
317 pub fn end(&self) -> usize {
319 self.list.input().to_orig_byte_idx(self.node().end())
320 }
321
322 pub fn begin_c(&self) -> usize {
324 self.list.input().to_orig_char_idx(self.node().begin())
325 }
326
327 pub fn end_c(&self) -> usize {
329 self.list.input().to_orig_char_idx(self.node().end())
330 }
331
332 pub fn surface(&self) -> Ref<'_, str> {
334 let inp = self.list.input();
335 Ref::map(inp, |i| i.orig_slice(self.node().bytes_range()))
336 }
337
338 pub fn part_of_speech_id(&self) -> u16 {
339 <Self as MorphemeView>::part_of_speech_id(self)
340 }
341
342 pub fn dictionary_form(&self) -> &str {
346 <Self as MorphemeView>::dictionary_form(self)
347 }
348
349 pub fn dictionary_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, D>>
351 where
352 D: Clone,
353 {
354 <Self as MorphemeView>::dictionary_form_morpheme(self)
355 }
356
357 pub fn normalized_form(&self) -> &str {
362 <Self as MorphemeView>::normalized_form(self)
363 }
364
365 pub fn normalized_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, D>>
367 where
368 D: Clone,
369 {
370 <Self as MorphemeView>::normalized_form_morpheme(self)
371 }
372
373 pub fn reading_form(&self) -> &str {
377 <Self as MorphemeView>::reading_form(self)
378 }
379
380 pub fn is_oov(&self) -> bool {
382 <Self as MorphemeView>::is_oov(self)
383 }
384
385 pub fn word_id(&self) -> WordId {
387 self.node().word_id()
388 }
389
390 pub fn dictionary_id(&self) -> i32 {
394 <Self as MorphemeView>::dictionary_id(self)
395 }
396
397 pub fn synonym_group_ids(&self) -> &[i32] {
398 <Self as MorphemeView>::synonym_group_ids(self)
399 }
400
401 pub fn user_data(&self) -> &str {
403 <Self as MorphemeView>::user_data(self)
404 }
405
406 pub fn get_word_info(&self) -> &WordInfo {
407 self.node().word_info()
408 }
409
410 pub fn index(&self) -> usize {
412 self.index
413 }
414
415 pub fn split_into(&self, mode: Mode, out: &mut MorphemeList<D>) -> SudachiResult<bool> {
419 self.list.split_into(mode, self.index, out)
420 }
421
422 pub fn total_cost(&self) -> i32 {
424 self.node().total_cost()
425 }
426}
427
428impl<D> private::Sealed for Morpheme<'_, D> {}
429
430impl<D: DictionaryAccess> MorphemeView for Morpheme<'_, D> {
431 type Dictionary = D;
432
433 fn dict(&self) -> &D {
434 self.list.dict()
435 }
436
437 fn subset(&self) -> InfoSubset {
438 self.list.subset()
439 }
440
441 fn begin(&self) -> usize {
442 Morpheme::begin(self)
443 }
444
445 fn end(&self) -> usize {
446 Morpheme::end(self)
447 }
448
449 fn begin_c(&self) -> usize {
450 Morpheme::begin_c(self)
451 }
452
453 fn end_c(&self) -> usize {
454 Morpheme::end_c(self)
455 }
456
457 fn surface(&self) -> MorphemeSurface<'_> {
458 MorphemeSurface::Input(Morpheme::surface(self))
459 }
460
461 fn word_id(&self) -> WordId {
462 Morpheme::word_id(self)
463 }
464
465 fn get_word_info(&self) -> &WordInfo {
466 Morpheme::get_word_info(self)
467 }
468
469 fn self_morpheme(&self) -> MorphemeRef<'_, D> {
470 MorphemeRef::ListItem(*self)
471 }
472}
473
474impl<D: DictionaryAccess> Debug for Morpheme<'_, D> {
475 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
476 f.debug_struct("Morpheme")
477 .field("surface", &self.surface())
478 .field("pos", &self.part_of_speech())
479 .field("normalized_form", &self.normalized_form())
480 .field("reading_form", &self.reading_form())
481 .field("dictionary_form", &self.dictionary_form())
482 .finish()
483 }
484}
485
486pub struct SingleMorpheme<D> {
488 dict: D,
489 word_id: WordId,
490 word_info: WordInfo,
491 subset: InfoSubset,
492 begin: usize,
493 end: usize,
494 begin_c: usize,
495 end_c: usize,
496}
497
498impl<D: Clone> Clone for SingleMorpheme<D> {
499 fn clone(&self) -> Self {
500 Self {
501 dict: self.dict.clone(),
502 word_id: self.word_id,
503 word_info: self.word_info.clone(),
504 subset: self.subset,
505 begin: self.begin,
506 end: self.end,
507 begin_c: self.begin_c,
508 end_c: self.end_c,
509 }
510 }
511}
512
513impl<D: DictionaryAccess> SingleMorpheme<D> {
514 pub fn from_word_id(dict: D, word_id: WordId, subset: InfoSubset) -> SudachiResult<Self> {
520 validate_dictionary_word_id(&dict, word_id)?;
521 let subset = (subset | InfoSubset::HEADWORD).normalize();
522 let word_info = dict.lexicon().get_word_info_subset(word_id, subset)?;
523 let surface = word_info.headword(dict.lexicon());
524 let end = surface.len();
525 let end_c = surface.chars().count();
526
527 Ok(Self {
528 dict,
529 word_id,
530 word_info,
531 subset,
532 begin: 0,
533 end,
534 begin_c: 0,
535 end_c,
536 })
537 }
538
539 pub fn oov(
540 dict: D,
541 pos_id: u16,
542 surface: String,
543 reading: String,
544 normalized_form: String,
545 dictionary_form: String,
546 ) -> SudachiResult<Self> {
547 if pos_id as usize >= dict.grammar().pos_list.len() {
548 return Err(SudachiError::InvalidPartOfSpeech(pos_id.to_string()));
549 }
550 let end = surface.len();
551 let end_c = surface.chars().count();
552 let word_id = WordId::oov(pos_id as u32);
553 let word_info = WordInfo::new_with_strings(
554 pos_id as i16,
555 end as i16,
556 word_id,
557 surface,
558 reading,
559 normalized_form,
560 dictionary_form,
561 );
562
563 Ok(Self {
564 dict,
565 word_id,
566 word_info,
567 subset: InfoSubset::all(),
568 begin: 0,
569 end,
570 begin_c: 0,
571 end_c,
572 })
573 }
574
575 pub(crate) fn subset(&self) -> InfoSubset {
576 self.subset
577 }
578
579 pub(crate) fn dict(&self) -> &D {
580 &self.dict
581 }
582
583 pub fn begin(&self) -> usize {
585 self.begin
586 }
587
588 pub fn end(&self) -> usize {
590 self.end
591 }
592
593 pub fn begin_c(&self) -> usize {
595 self.begin_c
596 }
597
598 pub fn end_c(&self) -> usize {
600 self.end_c
601 }
602
603 pub fn surface(&self) -> &str {
605 self.word_info.headword(self.dict.lexicon())
606 }
607
608 pub fn word_id(&self) -> WordId {
610 self.word_id
611 }
612
613 pub fn get_word_info(&self) -> &WordInfo {
614 &self.word_info
615 }
616}
617
618impl<D: DictionaryAccess + Clone> SingleMorpheme<D> {
619 pub fn part_of_speech(&self) -> &[String] {
621 <Self as MorphemeView>::part_of_speech(self)
622 }
623
624 pub fn split(&self, mode: Mode) -> SudachiResult<Vec<SingleMorpheme<D>>> {
631 let split_subset = match mode {
632 Mode::A => InfoSubset::SPLIT_A,
633 Mode::B => InfoSubset::SPLIT_B,
634 Mode::C => return Ok(vec![self.clone()]),
635 };
636
637 let word_info = if self.subset.contains(split_subset) {
638 Cow::Borrowed(&self.word_info)
639 } else {
640 Cow::Owned(
641 self.dict
642 .lexicon()
643 .get_word_info_subset(self.word_id, (self.subset | split_subset).normalize())?,
644 )
645 };
646
647 let splits = if mode == Mode::A {
648 word_info.a_unit_split()
649 } else {
650 word_info.b_unit_split()
651 };
652
653 if splits.is_empty() {
654 return Ok(vec![self.clone()]);
655 }
656
657 if let [word_id] = splits {
658 if *word_id == self.word_id {
659 return Ok(vec![self.clone()]);
660 }
661
662 let mut morpheme =
663 SingleMorpheme::from_word_id(self.dict.clone(), *word_id, self.subset)?;
664 morpheme.begin = self.begin;
665 morpheme.end = self.end;
666 morpheme.begin_c = self.begin_c;
667 morpheme.end_c = self.end_c;
668 return Ok(vec![morpheme]);
669 }
670
671 let mut result = Vec::with_capacity(splits.len());
672 let mut begin = self.begin;
673 let mut begin_c = self.begin_c;
674 for &word_id in splits {
675 let mut morpheme =
676 SingleMorpheme::from_word_id(self.dict.clone(), word_id, self.subset)?;
677 let end = begin + morpheme.surface().len();
678 let end_c = begin_c + morpheme.surface().chars().count();
679 morpheme.begin = begin;
680 morpheme.end = end;
681 morpheme.begin_c = begin_c;
682 morpheme.end_c = end_c;
683 begin = end;
684 begin_c = end_c;
685 result.push(morpheme);
686 }
687
688 Ok(result)
689 }
690
691 pub fn part_of_speech_id(&self) -> u16 {
692 <Self as MorphemeView>::part_of_speech_id(self)
693 }
694
695 pub fn dictionary_form(&self) -> &str {
697 <Self as MorphemeView>::dictionary_form(self)
698 }
699
700 pub fn dictionary_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, D>> {
702 <Self as MorphemeView>::dictionary_form_morpheme(self)
703 }
704
705 pub fn normalized_form(&self) -> &str {
707 <Self as MorphemeView>::normalized_form(self)
708 }
709
710 pub fn normalized_form_morpheme(&self) -> SudachiResult<MorphemeRef<'_, D>> {
712 <Self as MorphemeView>::normalized_form_morpheme(self)
713 }
714
715 pub fn reading_form(&self) -> &str {
717 <Self as MorphemeView>::reading_form(self)
718 }
719
720 pub fn is_oov(&self) -> bool {
722 <Self as MorphemeView>::is_oov(self)
723 }
724
725 pub fn dictionary_id(&self) -> i32 {
727 <Self as MorphemeView>::dictionary_id(self)
728 }
729
730 pub fn synonym_group_ids(&self) -> &[i32] {
731 <Self as MorphemeView>::synonym_group_ids(self)
732 }
733
734 pub fn user_data(&self) -> &str {
736 <Self as MorphemeView>::user_data(self)
737 }
738}
739
740impl<D> private::Sealed for SingleMorpheme<D> {}
741
742impl<D: DictionaryAccess + Clone> MorphemeView for SingleMorpheme<D> {
743 type Dictionary = D;
744
745 fn dict(&self) -> &D {
746 &self.dict
747 }
748
749 fn subset(&self) -> InfoSubset {
750 self.subset
751 }
752
753 fn begin(&self) -> usize {
754 SingleMorpheme::begin(self)
755 }
756
757 fn end(&self) -> usize {
758 SingleMorpheme::end(self)
759 }
760
761 fn begin_c(&self) -> usize {
762 SingleMorpheme::begin_c(self)
763 }
764
765 fn end_c(&self) -> usize {
766 SingleMorpheme::end_c(self)
767 }
768
769 fn surface(&self) -> MorphemeSurface<'_> {
770 MorphemeSurface::Headword(SingleMorpheme::surface(self))
771 }
772
773 fn word_id(&self) -> WordId {
774 SingleMorpheme::word_id(self)
775 }
776
777 fn get_word_info(&self) -> &WordInfo {
778 SingleMorpheme::get_word_info(self)
779 }
780
781 fn self_morpheme(&self) -> MorphemeRef<'_, D> {
782 MorphemeRef::Single(Box::new(self.clone()))
783 }
784}
785
786impl<D: DictionaryAccess + Clone> Debug for SingleMorpheme<D> {
787 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
788 f.debug_struct("SingleMorpheme")
789 .field("surface", &self.surface())
790 .field("pos", &self.part_of_speech())
791 .field("normalized_form", &self.normalized_form())
792 .field("reading_form", &self.reading_form())
793 .field("dictionary_form", &self.dictionary_form())
794 .finish()
795 }
796}
797
798#[non_exhaustive]
800pub enum MorphemeRef<'a, D> {
801 ListItem(Morpheme<'a, D>),
802 Single(Box<SingleMorpheme<D>>),
803}
804
805impl<D: Clone> Clone for MorphemeRef<'_, D> {
806 fn clone(&self) -> Self {
807 match self {
808 MorphemeRef::ListItem(m) => MorphemeRef::ListItem(*m),
809 MorphemeRef::Single(m) => MorphemeRef::Single(m.clone()),
810 }
811 }
812}
813
814impl<D: DictionaryAccess + Clone> MorphemeRef<'_, D> {
815 pub fn user_data(&self) -> &str {
817 <Self as MorphemeView>::user_data(self)
818 }
819}
820
821impl<D> private::Sealed for MorphemeRef<'_, D> {}
822
823impl<D: DictionaryAccess + Clone> MorphemeView for MorphemeRef<'_, D> {
824 type Dictionary = D;
825
826 fn dict(&self) -> &D {
827 match self {
828 MorphemeRef::ListItem(m) => m.dict(),
829 MorphemeRef::Single(m) => m.dict(),
830 }
831 }
832
833 fn subset(&self) -> InfoSubset {
834 match self {
835 MorphemeRef::ListItem(m) => m.subset(),
836 MorphemeRef::Single(m) => m.subset(),
837 }
838 }
839
840 fn begin(&self) -> usize {
841 match self {
842 MorphemeRef::ListItem(m) => m.begin(),
843 MorphemeRef::Single(m) => m.begin(),
844 }
845 }
846
847 fn end(&self) -> usize {
848 match self {
849 MorphemeRef::ListItem(m) => m.end(),
850 MorphemeRef::Single(m) => m.end(),
851 }
852 }
853
854 fn begin_c(&self) -> usize {
855 match self {
856 MorphemeRef::ListItem(m) => m.begin_c(),
857 MorphemeRef::Single(m) => m.begin_c(),
858 }
859 }
860
861 fn end_c(&self) -> usize {
862 match self {
863 MorphemeRef::ListItem(m) => m.end_c(),
864 MorphemeRef::Single(m) => m.end_c(),
865 }
866 }
867
868 fn surface(&self) -> MorphemeSurface<'_> {
869 match self {
870 MorphemeRef::ListItem(m) => MorphemeSurface::Input(m.surface()),
871 MorphemeRef::Single(m) => MorphemeSurface::Headword(m.surface()),
872 }
873 }
874
875 fn word_id(&self) -> WordId {
876 match self {
877 MorphemeRef::ListItem(m) => m.word_id(),
878 MorphemeRef::Single(m) => m.word_id(),
879 }
880 }
881
882 fn get_word_info(&self) -> &WordInfo {
883 match self {
884 MorphemeRef::ListItem(m) => m.get_word_info(),
885 MorphemeRef::Single(m) => m.get_word_info(),
886 }
887 }
888
889 fn self_morpheme(&self) -> MorphemeRef<'_, D> {
890 self.clone()
891 }
892}
893
894impl<D: DictionaryAccess + Clone> Debug for MorphemeRef<'_, D> {
895 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
896 match self {
897 MorphemeRef::ListItem(m) => Debug::fmt(m, f),
898 MorphemeRef::Single(m) => Debug::fmt(m, f),
899 }
900 }
901}