tossicat 0.8.0

입력된 단어에 맞게 같이 입력된 토시(조사)를 적절하게 변환하는 라이브러리
Documentation
//! # 입력된 토시(tossi)가 어떤 것인지 알아내 저장하는 토시 구조체를 구현한 모듈
//!
//! 사용자가 입력한 토시를 변환해서 저장하고,
//! 변환한 값을 토대로 어떤 종류인지 분류한 다음 분류한 결과를 저장한다.
//! 사용법은 아래와 같다.
//!
//! ```rust, ignore
//! let test_tossi = "으로";
//! let temp = Tossi::new(test_tossi);
//! println!("토시 종류: {:?}", temp.kind);
//! ```
//!
//! 실행 결과는 다음과 같다.
//!
//! ```ignore
//! 토시 종류: Ro
//! ```
//!
//! '토시 종류(TossiKind)'의 토시 영어명 표시명은
//! 이 프로젝트 안에 있는 다음 파일을 참고한다.
//!
//! - docs/terms.md

use crate::filter::filter_only_significant;

pub enum TossiKind {
    Deun,
    Deunji,
    Deunka,
    Eul,
    Ida,
    Indeul,
    Injeuk,
    Ka,
    Ko,
    Myeo,
    Na,
    Nama,
    Neun,
    Ni,
    Rado,
    Rago,
    Ran,
    Rang,
    Raya,
    Ro,
    Robuteo,
    Roseo,
    Rosseo,
    Wa,
    Yamalro,
    Ya,
    Yeo,
    Illang,
    Ji,
    Jiman,
    Nikka,
    Geon,
    Geodeun,
    Geona,
    Nya,
    Ramyeon,
    Raseo,
    Raneun,
    Eyo,
    Eotda,
    Eoseo,
    Rodo,
    Roman,
    Roneun,
    Roui,
    Rani,
    Randa,
    Ramyeonseo,
    Radeunka,
    Radeunji,
    Yo,
    Eotdeon,
    Ragoneun,
    Roseoui,
    Others,
}
/// ## 토시 변환 방식을 분류하는 열거형
///
/// 한국어 조사(토시)는 앞 단어의 받침(종성) 유무에 따라 형태가 달라진다.
/// 이 열거형은 그 변환 방식을 다음과 같이 분류한다.
///
/// - `Blank`: 받침 유무에 따라 형태가 달라지는 일반적인 경우 (예: 은/는, 을/를, 과/와)
/// - `RiEulAndBlank`: 받침이 'ㄹ'일 때 특수 처리하는 경우 (예: "서울로", "학교로")
/// - `OnlyKa`: '가/이' 조사의 특수 변환
/// - `LastJamoNieun`: 받침 없는 체언에 'ㄴ' 받침을 추가하는 경우 (예: "철수" → "철순들")
/// - `LastJamoRieul`: 받침 없는 체언에 'ㄹ' 받침을 추가하는 경우 (예: "가구" → "가굴랑")
/// - `Nothing`: 변환하지 않는 경우
pub enum TransTossiWhen {
    Blank,
    RiEulAndBlank,
    OnlyKa,
    LastJamoNieun,
    LastJamoRieul,
    Nothing,
}

pub struct Tossi {
    pub kind: TossiKind,
    pub when: TransTossiWhen,
}

impl Tossi {
    pub fn new(raw: &str) -> Self {
        let temp_modified = filter_only_significant(raw);
        // 앞에서 변환 것을 토대로 글자 수에 따라 조사 종류를 찾는다.
        let temp_kind = match temp_modified.len() {
            1 => one_letter(temp_modified[0]),
            2 => two_letters(&temp_modified),
            3 => three_letters(&temp_modified),
            4 => four_letters(&temp_modified),
            _ => TossiKind::Others,
        };
        // 토시 종류에 따라 변환 방식을 결정한다.
        // 대부분의 조사는 받침 유무에 따라 형태가 달라지는 Blank 방식이고,
        // 아래 나열된 것들만 특수한 변환 방식을 사용한다.
        let temp_trans_tossi_when = match temp_kind {
            // 받침 없는 체언에 'ㄹ' 받침을 추가하는 토시 (예: "가구" → "가굴랑")
            TossiKind::Illang => TransTossiWhen::LastJamoRieul,
            // 받침 없는 체언에 'ㄴ' 받침을 추가하는 토시 (예: "철수" → "철순들")
            TossiKind::Indeul | TossiKind::Injeuk => TransTossiWhen::LastJamoNieun,
            // '가/이' 조사의 특수 변환
            TossiKind::Ka => TransTossiWhen::OnlyKa,
            // 받침이 'ㄹ'일 때 '으'가 붙지 않는 토시 (예: "서울로", "학교로")
            TossiKind::Ro
            | TossiKind::Robuteo
            | TossiKind::Roseo
            | TossiKind::Rosseo
            | TossiKind::Rodo
            | TossiKind::Roman
            | TossiKind::Roneun
            | TossiKind::Roui
            | TossiKind::Roseoui => TransTossiWhen::RiEulAndBlank,
            // 처리할 수 없는 토시
            TossiKind::Others => TransTossiWhen::Nothing,
            // 그 외 받침 유무에 따라 형태가 달라지는 일반적인 조사
            _ => TransTossiWhen::Blank,
        };
        Self {
            kind: temp_kind,
            when: temp_trans_tossi_when,
        }
    }
}

/// ## 한 글자로 된 토시를 분류하는 함수
/// 한 글자로 된 토시가 들어오면 이를 종류 별로 분류하는 함수
/// 추가한 순서대로 아래에 추가하고 있습니다.
/// 정렬할 필요 없습니다.
fn one_letter(element: char) -> TossiKind {
    match element {
        '' | '' => TossiKind::Neun,
        '' | '' => TossiKind::Ka,
        '' | '' => TossiKind::Eul,
        '' | '' => TossiKind::Wa,
        '' => TossiKind::Ro,
        '' => TossiKind::Ida,
        '' => TossiKind::Na,
        '' => TossiKind::Rang,
        '' => TossiKind::Ran,
        '' => TossiKind::Myeo,
        '' => TossiKind::Ko,
        '' => TossiKind::Ni,
        '' => TossiKind::Deun,
        '' => TossiKind::Yeo,
        '' | '' => TossiKind::Ya,
        '' => TossiKind::Ji,
        '' => TossiKind::Geon,
        '' => TossiKind::Nya,
        '' => TossiKind::Yo,
        _ => TossiKind::Others,
    }
}

/// ## 두 글자로 된 토시를 분류하는 함수
/// 두 글자로 된 토시가 들어오면 이를 종류 별로 분류하는 함수
/// 추가한 순서대로 아래에 추가하고 있습니다.
/// 정렬할 필요 없습니다.
fn two_letters(elements: &[char]) -> TossiKind {
    match (elements[0], elements[1]) {
        ('', '') => TossiKind::Ro,
        ('', '') => TossiKind::Roseo,
        ('', '') => TossiKind::Rosseo,
        ('', '') => TossiKind::Ida,
        ('', '') => TossiKind::Na,
        ('', '') => TossiKind::Rang,
        ('', '') => TossiKind::Ran,
        ('', '') => TossiKind::Nama,
        ('', '') => TossiKind::Myeo,
        ('', '') => TossiKind::Ko,
        ('', '') => TossiKind::Ni,
        ('', '') => TossiKind::Deun,
        ('', '') => TossiKind::Deunji,
        ('', '') => TossiKind::Deunka,
        ('', '') => TossiKind::Yeo,
        ('', '') => TossiKind::Raya,
        ('', '') => TossiKind::Rado,
        ('', '') => TossiKind::Indeul,
        ('', '') => TossiKind::Injeuk,
        ('', '') => TossiKind::Rago,
        ('', '') => TossiKind::Illang,
        ('', '') => TossiKind::Ji,
        ('', '') => TossiKind::Jiman,
        ('', '') => TossiKind::Nikka,
        ('', '') => TossiKind::Geon,
        ('', '') => TossiKind::Geodeun,
        ('', '') => TossiKind::Geona,
        ('', '') => TossiKind::Nya,
        ('', '') => TossiKind::Ramyeon,
        ('', '') => TossiKind::Raseo,
        ('', '') => TossiKind::Raneun,
        ('', '') => TossiKind::Eyo,
        ('', '') => TossiKind::Eyo,
        ('', '') => TossiKind::Eotda,
        ('', '') => TossiKind::Eotda,
        ('', '') => TossiKind::Eotdeon,
        ('', '') => TossiKind::Eotdeon,
        ('', '') => TossiKind::Eoseo,
        ('', '') => TossiKind::Eoseo,
        ('', '') => TossiKind::Rodo,
        ('', '') => TossiKind::Roman,
        ('', '') => TossiKind::Roneun,
        ('', '') => TossiKind::Roui,
        ('', '') => TossiKind::Rani,
        ('', '') => TossiKind::Randa,
        ('', '') => TossiKind::Yo,
        (_, _) => TossiKind::Others,
    }
}

/// ## 세 글자로 된 토시를 분류하는 함수
/// 세 글자로 된 토시가 들어오면 이를 종류 별로 분류하는 함수
/// 추가한 순서대로 아래에 추가하고 있습니다.
/// 정렬할 필요 없습니다.
fn three_letters(elements: &[char]) -> TossiKind {
    match (elements[0], elements[1], elements[2]) {
        ('', '', '') => TossiKind::Roseo,
        ('', '', '') => TossiKind::Rosseo,
        ('', '', '') => TossiKind::Robuteo,
        ('', '', '') => TossiKind::Nama,
        ('', '', '') => TossiKind::Yamalro,
        ('', '', '') => TossiKind::Deunji,
        ('', '', '') => TossiKind::Deunka,
        ('', '', '') => TossiKind::Raya,
        ('', '', '') => TossiKind::Rado,
        ('', '', '') => TossiKind::Rago,
        ('', '', '') => TossiKind::Jiman,
        ('', '', '') => TossiKind::Nikka,
        ('', '', '') => TossiKind::Geodeun,
        ('', '', '') => TossiKind::Geona,
        ('', '', '') => TossiKind::Ramyeon,
        ('', '', '') => TossiKind::Raseo,
        ('', '', '') => TossiKind::Raneun,
        ('', '', '') => TossiKind::Eyo,
        ('', '', '') => TossiKind::Eotda,
        ('', '', '') => TossiKind::Eotdeon,
        ('', '', '') => TossiKind::Eoseo,
        ('', '', '') => TossiKind::Rodo,
        ('', '', '') => TossiKind::Roman,
        ('', '', '') => TossiKind::Roneun,
        ('', '', '') => TossiKind::Roui,
        ('', '', '') => TossiKind::Rani,
        ('', '', '') => TossiKind::Randa,
        ('', '', '') => TossiKind::Ramyeonseo,
        ('', '', '') => TossiKind::Radeunka,
        ('', '', '') => TossiKind::Radeunji,
        ('', '', '') => TossiKind::Ragoneun,
        ('', '', '') => TossiKind::Roseoui,
        (_, _, _) => TossiKind::Others,
    }
}

/// ## 네 글자로 된 토시를 분류하는 함수
/// 네 글자로 된 토시가 들어오면 이를 종류 별로 분류하는 함수
/// 추가한 순서대로 아래에 추가하고 있습니다.
/// 정렬할 필요 없습니다.
fn four_letters(elements: &[char]) -> TossiKind {
    match (elements[0], elements[1], elements[2], elements[3]) {
        ('', '', '', '') => TossiKind::Robuteo,
        ('', '', '', '') => TossiKind::Yamalro,
        ('', '', '', '') => TossiKind::Ramyeonseo,
        ('', '', '', '') => TossiKind::Radeunka,
        ('', '', '', '') => TossiKind::Radeunji,
        ('', '', '', '') => TossiKind::Ragoneun,
        ('', '', '', '') => TossiKind::Roseoui,
        (_, _, _, _) => TossiKind::Others,
    }
}