1use crate::dict;
2use gobble::*;
3
4parser! { (Converter ->String)
5 chars_until(Letter, eoi).map(|(a, _b)| a)
6}
7
8parser! { (EnStringPos -> ())
9 ((Alpha,NumDigit).iplus(),(Alpha,NumDigit,BothAllow).istar()).ig()
10}
11parser! { (MiStringPos -> ())
12 ((MiChar,NumDigit).iplus(),(MiChar,NumDigit,BothAllow).istar()).ig()
13}
14
15parser! { (Extra->String)
16 ("(",(Alpha,NumDigit,WS,MiChar).star(),")").map(|(_,s,_)|s)
17}
18parser! { (MiEntry->String)
19 (string(MiStringPos),maybe(Extra)).map(|(m,e_op)|
20 match e_op {
21 Some(ex)=>format!("{} ({})",m.trim(),ex.trim()),
22 None=>m.trim().to_string(),
23 }
24 )
25}
26parser! { (EnEntry->String)
27 (string(EnStringPos),maybe(Extra)).map(|(m,e_op)|
28 match e_op {
29 Some(ex)=>format!("{} ({})",m.trim(),ex.trim()),
30 None=>m.trim().to_string(),
31 }
32 )
33}
34
35parser! { (Record->dict::Record)
36 or(
37 (ws_(EnEntry),":" ,ws_(MiEntry)).map(|(english,_,michuhu)| dict::Record{english,michuhu}),
38 (ws_(MiEntry),":" ,ws_(EnEntry)).map(|(michuhu,_,english)| dict::Record{english,michuhu})
39 )
40}
41
42parser! { (EmptyLine ->())
43 (Any.except("\n|").istar(),"\n|".one()).ig()
44}
45
46parser! { (RecordLine->dict::Record)
47 middle(
48 maybe(or_ig!("*",(NumDigit.star(),"."))),
49 Record,
50 (maybe(ws__(",")),"\n|".one()),
51 )
52}
53
54parser! { (NextRecord->dict::Record)
55 star_until(EmptyLine,RecordLine).map(|(_,v)|v)
56}
57
58parser! { (Dict->dict::TwoWayMap)
59 (star(NextRecord),star(EmptyLine),ws_(eoi))
60 .map(|(v,_,_)|{
61 let mut res = dict::TwoWayMap::new();
62 for r in v{
63 res.insert(r);
64 }
65 res
66 })
67}
68
69parser! {(Letter->char)
70 or(MLetter,Any.one())
71}
72
73fn consonant(s: &str) -> u32 {
74 match s {
75 "k" => 0xe000,
76 "d" => 0xe001,
77 "ch" | "c" => 0xe002,
78 "s" => 0xe003,
79 "y" => 0xe004,
80 "h" => 0xe005,
81 "f" => 0xe006,
82 "w" => 0xe007,
83 "m" => 0xe008,
84 "j" => 0xe009,
85 "b" => 0xe00a,
86 "n" => 0xe00b,
87 "th" | "t" => 0xe00c,
88 "fl" | "v" => 0xe00d,
89 "l" => 0xe055,
90 "cl" => 0xe056,
91 "bl" => 0xe057,
92 "sh" | "z" => 0xe058,
93 _ => 0xe001,
94 }
95}
96
97fn vowel(c: char) -> u32 {
98 match c {
99 'a' => 14,
100 'b' => 14 * 2,
101 'c' => 14 * 3,
102 'u' => 14 * 4,
103 _ => 0,
104 }
105}
106
107parser! {( MLetter->char)
108 or!(
109 (MCons,maybe(MVowel)).map(|(k,vop)|{
110 std::char::from_u32( consonant(k)+vop.map(|v|vowel(v)).unwrap_or(0)).unwrap_or('#')
111 }),
112 MVowel.map(|v| std::char::from_u32(0xe054 + vowel(v) ).unwrap_or('#'))
113 )
114}
115
116parser! { (MCons->&'static str)
117 or!("cl","k","d","ch","c","sh","s","y","h","fl","v","f","w","m","j","bl","b","n","th","t","l","z")
118}
119
120parser! { (MVowel->char)
121 or!('a','i','o','u')
122}
123
124char_bool!(MiChar, |c| c >= '' && c <= '');
125char_bool!(BothAllow, "?&/ \t~-");