1#[macro_use]
2use crate::*;
3
4#[cfg(not(feature = "no-std"))] use core::fmt;
5#[cfg(feature = "no-std")] use alloc::fmt;
6#[cfg(feature = "no-std")] use alloc::string::String;
7#[cfg(feature = "no-std")] use alloc::vec::Vec;
8use nom::{
9 IResult,
10 branch::alt,
11 sequence::{tuple as nom_tuple, pair},
12 combinator::{opt, eof, peek},
13 multi::{many1, many_till, many0, separated_list1,separated_list0},
14 bytes::complete::{take_until, take_while},
15 Err,
16 Err::Failure
17};
18
19use std::collections::HashMap;
20use colored::*;
21
22use crate::*;
23
24pub static MICROMIKA_WAVE: &[&str] = &[
28 "╭◉╮", "╭◉─", "╭◉╯", "╭◉─", "╭◉╯", "╭◉─", "╭◉╮", " "
29];
30
31pub static MICROMIKA_SLEEP: &[&str] = &[
32 "╭◉╮", "╭⦾╮", "╭⊚╮", "╭⊙╮", "╭◯╮"
33];
34
35pub static MICROMIKA_WAKE: &[&str] = &[
36 "╭◯╮", "╭⊙╮", "╭⊚╮", "╭⦾╮", "╭◉╮"
37];
38
39pub static MICROMIKA_BLINK: &[&str] = &[
40 "╭◉╮", "╭⊖╮", "╭◉╮", "╭⊖╮", "╭◉╮", "╭◉╮", "╭◉╮", "╭◉╮"
41];
42
43pub static MICROMIKA_PULSE: &[&str] = &[
44 "╭◉╮", "╭⦾╮", "╭⊚╮", "╭⊙╮", "╭⊚╮", "╭⦾╮", "╭◉╮"
45];
46
47pub static MICROMIKA_RAISE: &[&str] = &[
48 "╭◉╮", "─◉─", "╰◉╯"
49];
50
51pub static MICROMIKA_FLAP: &[&str] = &[
52 "╭◉╮", "─◉─", "╰◉╯", "─◉─", "╭◉╮"
53];
54
55pub static MICROMIKA_ATTENTION: &[&str] = &[
56 "╭◉╯", "╭◉╯", "╭◉╯","╭◉╯","╭◉╯", "╭◉─", "╭◉╯", "╭◉─",
57];
58
59pub fn mika_section(input: ParseString) -> ParseResult<MikaSection> {
64 let msg = "Expects ⸥ to close speech bubble";
65 let (input, (_, r)) = range(mika_section_open)(input)?;
66 let (input, elements) = section(input)?;
67 let (input, _) = label!(mika_section_close, msg, r)(input)?;
68 Ok((input, MikaSection { elements }))
69}
70
71pub fn mika_arm_left(input: ParseString) -> ParseResult<MikaArm> {
76 let (input, tok) = alt((
77 tag("Ɔ∞"), tag("›─"), tag("›⌣"), tag("·¬"), tag("-◡"), tag("ᗑ"), tag("ᕦ"), tag("~"), tag("⌣"), tag("╭"), tag("⸌"), tag("⸸"), tag("─"), tag("ᓂ"), tag("ᓇ"), tag("╰"), ))(input)?;
94 let arm = match tok.chars().collect::<String>().as_str() {
95 "ᗑ" => MikaArm::BatWing,
96 "Ɔ∞" => MikaArm::BigGripperLeft,
97 "ᕦ" => MikaArm::CurlLeft,
98 "~" => MikaArm::Dance,
99 "›⌣" | "⌣" => MikaArm::GestureLeft,
100 "›─" => MikaArm::GripperLeft,
101 "╭" => MikaArm::Left,
102 "⸌" => MikaArm::RaisedLeft,
103 "·¬" => MikaArm::ShootLeft,
104 "-◡" => MikaArm::ShrugLeft,
105 "⸸" => MikaArm::Sword,
106 "─" => MikaArm::Point,
107 "ᓂ" => MikaArm::PunchLeft,
108 "ᓇ" => MikaArm::PunchLowLeft,
109 "╰" => MikaArm::UpLeft,
110 _ => unreachable!(),
111 };
112 Ok((input, arm))
113}
114
115pub fn mika_arm_right(input: ParseString) -> ParseResult<MikaArm> {
116 let (input, tok) = alt((
117 tag("∞C"), tag("─‹"), tag("⌣‹"), tag("⌐·"), tag("◡-"), tag("ᗑ"), tag("ᕤ"), tag("~"), tag("⌣"), tag("╮"), tag("⸍"), tag("ᗢ"), tag("─"), tag("ᓀ"), tag("ᓄ"), tag("╯"), ))(input)?;
134 let arm = match tok.chars().collect::<String>().as_str() {
135 "ᗑ" => MikaArm::BatWing,
136 "∞C" => MikaArm::BigGripperRight,
137 "ᕤ" => MikaArm::CurlRight,
138 "~" => MikaArm::Dance,
139 "⌣‹" | "⌣" => MikaArm::GestureRight,
140 "─‹" => MikaArm::GripperRight,
141 "╮" => MikaArm::Right,
142 "⸍" => MikaArm::RaisedRight,
143 "⌐·" => MikaArm::ShootRight,
144 "◡-" => MikaArm::ShrugRight,
145 "ᗢ" => MikaArm::Shield,
146 "─" => MikaArm::Point,
147 "ᓀ" => MikaArm::PunchRight,
148 "ᓄ" => MikaArm::PunchLowRight,
149 "╯" => MikaArm::UpRight,
150 _ => unreachable!(),
151 };
152 Ok((input, arm))
153}
154
155const LEFT_EYE_ORDER: &[MikaEyeLeft] = &[
161 MikaEyeLeft::Shades, MikaEyeLeft::Content, MikaEyeLeft::Confused, MikaEyeLeft::Crying, MikaEyeLeft::Dazed, MikaEyeLeft::Dead, MikaEyeLeft::EyesSqueezed, MikaEyeLeft::SuperSqueezed, MikaEyeLeft::Glaring, MikaEyeLeft::Happy, MikaEyeLeft::Normal, MikaEyeLeft::PeerRight, MikaEyeLeft::PeerStraight, MikaEyeLeft::Pleased, MikaEyeLeft::Resolved, MikaEyeLeft::RollingEyes, MikaEyeLeft::Sad, MikaEyeLeft::Scared, MikaEyeLeft::Sleeping, MikaEyeLeft::Smiling, MikaEyeLeft::Squinting, MikaEyeLeft::Surprised, MikaEyeLeft::TearingUp, MikaEyeLeft::Unimpressed, MikaEyeLeft::Wired, ];
187
188const RIGHT_EYE_ORDER: &[MikaEyeRight] = &[
189 MikaEyeRight::Content,
190 MikaEyeRight::Confused,
191 MikaEyeRight::Crying,
192 MikaEyeRight::Dazed,
193 MikaEyeRight::Dead,
194 MikaEyeRight::EyesSqueezed,
195 MikaEyeRight::SuperSqueezed,
196 MikaEyeRight::Glaring,
197 MikaEyeRight::Happy,
198 MikaEyeRight::Normal,
199 MikaEyeRight::PeerRight,
200 MikaEyeRight::PeerStraight,
201 MikaEyeRight::Pleased,
202 MikaEyeRight::Resolved,
203 MikaEyeRight::RollingEyes,
204 MikaEyeRight::Sad,
205 MikaEyeRight::Scared,
206 MikaEyeRight::Shades, MikaEyeRight::Sleeping,
208 MikaEyeRight::Smiling,
209 MikaEyeRight::Squinting,
210 MikaEyeRight::Surprised,
211 MikaEyeRight::TearingUp,
212 MikaEyeRight::Unimpressed,
213 MikaEyeRight::Wired,
214];
215
216const NOSE_ORDER: &[MikaNose] = &[
217 MikaNose::Normal,
218 MikaNose::Open,
219 MikaNose::Back,
220 MikaNose::Stage1,
221 MikaNose::Stage2,
222 MikaNose::Stage3,
223 MikaNose::Blink,
224 MikaNose::Wide,
225 MikaNose::Error,
226 MikaNose::Filled,
227 MikaNose::FlatMouth,
228 MikaNose::Hexagon,
229 MikaNose::Pentagon,
230 MikaNose::Hexagon2,
231 MikaNose::HexagonOpen,
232];
233
234const EXPRESSIONS: &[MikaExpression] = &[
237 MikaExpression::Content,
238 MikaExpression::Confused,
239 MikaExpression::Crying,
240 MikaExpression::Dazed,
241 MikaExpression::Dead,
242 MikaExpression::EyesSqueezed,
243 MikaExpression::SuperSqueezed,
244 MikaExpression::Glaring,
245 MikaExpression::Happy,
246 MikaExpression::Normal,
247 MikaExpression::PeerRight,
248 MikaExpression::PeerStraight,
249 MikaExpression::Pleased,
250 MikaExpression::Resolved,
251 MikaExpression::RollingEyes,
252 MikaExpression::Sad,
253 MikaExpression::Scared,
254 MikaExpression::Shades,
255 MikaExpression::Sleeping,
256 MikaExpression::Smiling,
257 MikaExpression::Squinting,
258 MikaExpression::Surprised,
259 MikaExpression::TearingUp,
260 MikaExpression::Unimpressed,
261 MikaExpression::Wired,
262];
263
264pub fn mika_eye_left(input: ParseString) -> ParseResult<MikaEyeLeft> {
265 for &variant in LEFT_EYE_ORDER {
266 if let Ok((rest, _)) = tag(variant.symbol())(input.clone()) {
267 return Ok((rest, variant));
268 }
269 }
270 Err(nom::Err::Error(ParseError {
271 cause_range: SourceRange::default(),
272 remaining_input: input,
273 error_detail: ParseErrorDetail {
274 message: "Expected Mika left eye",
275 annotation_rngs: Vec::new(),
276 },
277 }))
278}
279
280pub fn mika_eye_right(input: ParseString) -> ParseResult<MikaEyeRight> {
281 for &variant in RIGHT_EYE_ORDER {
282 if let Ok((rest, _)) = tag(variant.symbol())(input.clone()) {
283 return Ok((rest, variant));
284 }
285 }
286 Err(nom::Err::Error(ParseError {
287 cause_range: SourceRange::default(),
288 remaining_input: input,
289 error_detail: ParseErrorDetail {
290 message: "Expected Mika right eye",
291 annotation_rngs: Vec::new(),
292 },
293 }))
294}
295
296pub fn mika_nose(input: ParseString) -> ParseResult<MikaNose> {
298 for &variant in NOSE_ORDER {
299 if let Ok((rest, _)) = tag(variant.symbol())(input.clone()) {
300 return Ok((rest, variant));
301 }
302 }
303 Err(nom::Err::Error(ParseError {
304 cause_range: SourceRange::default(),
305 remaining_input: input,
306 error_detail: ParseErrorDetail {
307 message: "Expected Mika nose",
308 annotation_rngs: Vec::new(),
309 },
310 }))
311}
312
313pub fn mika_expression_inner(input: ParseString) -> ParseResult<MikaExpression> {
315 let (input, left) = mika_eye_left(input)?;
316 let (input, nose) = mika_nose(input)?;
317
318 let expr = EXPRESSIONS.iter().find(|&&e| {
319 let (l, n, _) = e.symbols();
320 l == left && n == nose
321 });
322
323 match expr {
324 Some(&expr) => {
325 let (_, _, right) = expr.symbols();
326 let (input, _) = tag(right.symbol())(input)?;
327 Ok((input, expr))
328 }
329 None => Err(nom::Err::Error(ParseError {
330 cause_range: SourceRange::default(),
331 remaining_input: input,
332 error_detail: ParseErrorDetail {
333 message: "Unrecognized Mika expression",
334 annotation_rngs: Vec::new(),
335 },
336 })),
337 }
338}
339
340pub fn micro_mika(input: ParseString) -> ParseResult<Mika> {
345 let (input, left_arm) = mika_arm_left(input)?;
346 let (input, nose) = mika_nose(input)?;
347 let (input, right_arm) = mika_arm_right(input)?;
348 Ok((input, Mika::Micro(MicroMika{ left_arm, nose, right_arm})))
349}
350
351pub fn mini_mika(input: ParseString) -> ParseResult<Mika> {
353 let (input, left_arm) = opt(mika_arm_left)(input)?;
354 let (input, _) = left_parenthesis(input)?;
355 let (input, right_arm_left) = opt(mika_arm_right)(input)?;
356 let (input, expression) = mika_expression_inner(input)?;
357 let (input, left_arm_right) = opt(mika_arm_left)(input)?;
358 let (input, _) = right_parenthesis(input)?;
359 let (input, right_arm) = opt(mika_arm_right)(input)?;
360 Ok((input, Mika::Mini(MiniMika { expression, left_arm: left_arm.or(right_arm_left), right_arm: right_arm.or(left_arm_right) })))
361}
362
363pub fn mika(input: ParseString) -> ParseResult<(Mika,Option<MikaSection>)> {
365 let (input, mika) = alt((mini_mika, micro_mika))(input)?;
366 let (input, _) = whitespace0(input)?;
367 let (input, mika_section) = opt(mika_section)(input)?;
368 let (input, _) = whitespace0(input)?;
369 Ok((input, (mika, mika_section)))
370}