1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::dict;
use gobble::*;

parser! { (Converter ->String)
    chars_until(Letter, eoi).map(|(a, _b)| a)
}

parser! { (EnStringPos -> ())
    ((Alpha,NumDigit).iplus(),(Alpha,NumDigit,BothAllow).istar()).ig()
}
parser! { (MiStringPos -> ())
    ((MiChar,NumDigit).iplus(),(MiChar,NumDigit,BothAllow).istar()).ig()
}

parser! { (Extra->String)
    ("(",(Alpha,NumDigit,WS,MiChar).star(),")").map(|(_,s,_)|s)
}
parser! { (MiEntry->String)
    (string(MiStringPos),maybe(Extra)).map(|(m,e_op)|
        match e_op {
            Some(ex)=>format!("{} ({})",m.trim(),ex.trim()),
            None=>m.trim().to_string(),
        }
    )
}
parser! { (EnEntry->String)
    (string(EnStringPos),maybe(Extra)).map(|(m,e_op)|
        match e_op {
            Some(ex)=>format!("{} ({})",m.trim(),ex.trim()),
            None=>m.trim().to_string(),
        }
    )
}

parser! { (Record->dict::Record)
    or(
        (ws_(EnEntry),":" ,ws_(MiEntry)).map(|(english,_,michuhu)| dict::Record{english,michuhu}),
        (ws_(MiEntry),":" ,ws_(EnEntry)).map(|(michuhu,_,english)| dict::Record{english,michuhu})
    )
}

parser! { (EmptyLine ->())
    (Any.except("\n|").istar(),"\n|".one()).ig()
}

parser! { (RecordLine->dict::Record)
    middle(
        maybe(or_ig!("*",(NumDigit.star(),"."))),
        Record,
        (maybe(ws__(",")),"\n|".one()),
    )
}

parser! { (NextRecord->dict::Record)
    star_until(EmptyLine,RecordLine).map(|(_,v)|v)
}

parser! { (Dict->dict::TwoWayMap)
    (star(NextRecord),star(EmptyLine),ws_(eoi))
        .map(|(v,_,_)|{
            let mut res = dict::TwoWayMap::new();
            for r in v{
                res.insert(r);
            }
            res
       })
}

parser! {(Letter->char)
    or(MLetter,Any.one())
}

fn consonant(s: &str) -> u32 {
    match s {
        "k" => 0xe000,
        "d" => 0xe001,
        "ch" | "c" => 0xe002,
        "s" => 0xe003,
        "y" => 0xe004,
        "h" => 0xe005,
        "f" => 0xe006,
        "w" => 0xe007,
        "m" => 0xe008,
        "j" => 0xe009,
        "b" => 0xe00a,
        "n" => 0xe00b,
        "th" | "t" => 0xe00c,
        "fl" | "v" => 0xe00d,
        "l" => 0xe055,
        "cl" => 0xe056,
        "bl" => 0xe057,
        "sh" | "z" => 0xe058,
        _ => 0xe001,
    }
}

fn vowel(c: char) -> u32 {
    match c {
        'a' => 14,
        'b' => 14 * 2,
        'c' => 14 * 3,
        'u' => 14 * 4,
        _ => 0,
    }
}

parser! {( MLetter->char)
    or!(
        (MCons,maybe(MVowel)).map(|(k,vop)|{
            std::char::from_u32( consonant(k)+vop.map(|v|vowel(v)).unwrap_or(0)).unwrap_or('#')
        }),
        MVowel.map(|v| std::char::from_u32(0xe054 + vowel(v) ).unwrap_or('#'))
    )
}

parser! { (MCons->&'static str)
    or!("cl","k","d","ch","c","sh","s","y","h","fl","v","f","w","m","j","bl","b","n","th","t","l","z")
}

parser! { (MVowel->char)
    or!('a','i','o','u')
}

char_bool!(MiChar, |c| c >= '' && c <= '');
char_bool!(BothAllow, "?&/ \t~-");