은는이가을를 (Rust로 한국어 조사 채우기)

게임 대잔치용 봇 만들다가…

지바고이(가) 100p를 획득했습니다! 라고 할 수도 있지만 그건 멋있지 않으니까 구현했다.

pub fn fill_josa(input: &str) -> String {
    let chars = input.chars();
    let mut former = '\0';
    let mut escape = false;
    let mut res = String::new();

    for c in chars {
        match c {
            '`' => {
                if escape {
                    res.push('`');
                }
                escape = !escape;
            },
            '은' | '는' if escape => {
                escape = false;
                former = if has_final_consonant(former) {'은'} else {'는'};
                res.push(former);
            },
            '이' | '가' if escape => {
                escape = false;
                former = if has_final_consonant(former) {'이'} else {'가'};
                res.push(former);
            },
            '을' | '를' if escape => {
                escape = false;
                former = if has_final_consonant(former) {'을'} else {'를'};
                res.push(former);
            },
            _ => {
                escape = false;                
                former = c;
                res.push(c);
            }
        }
    }

    res
}

fn has_final_consonant(c: char) -> bool {
    let code = c as u32;
    if code < 0xAC00 || code > 0xD7A3 {
        return false;
    }
    let final_consonant_index = (code - 0xAC00) % 28;
    final_consonant_index != 0
}

fn main() {
    assert_eq!(
        fill_josa("밥`을 먹었다. 빵`는 먹지 않았다. ``왜 그랬어?``")),
        "밥을 먹었다. 빵은 먹지 않았다. `왜 그랬어?`"
}