1#![allow(dead_code)]
2
3use crate::syntax::{
4 AutomatonType, Machine, MacroType, Move, Program, State, StateType, Transition,
5};
6
7const ALLOWED_NAME_SYMBOLS: &str = "abcdefghijklmnopqrstuvwxyz0123456789_.";
8const ALLOWED_TAPE_SYMBOLS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*[]-+=/?_:";
9const BREAK_SYMBOLS: &str = "(){};=, \n\"\'";
10
11fn allowed_name(x: &char) -> bool {
13 ALLOWED_NAME_SYMBOLS.contains(*x)
14}
15
16fn allowed_tape(x: &char) -> bool {
18 ALLOWED_TAPE_SYMBOLS.contains(*x)
19}
20
21fn literal(x: &char) -> bool {
23 !BREAK_SYMBOLS.contains(*x)
24}
25
26#[derive(Copy, Clone, PartialEq, Debug)]
28pub struct Leftover<'a> {
29 pub input: &'a str,
30 pub row: u32,
31 pub col: u32,
32}
33
34impl<'a> Leftover<'a> {
36 fn advance(&mut self) -> Option<char> {
38 let mut chars = self.input.chars();
39 match chars.next() {
40 Some(c) => {
41 self.input = chars.as_str();
42 if c != '\n' {
43 self.col += 1;
44 } else {
45 self.row += 1;
46 self.col = 0;
47 }
48 Some(c)
49 }
50 None => None,
51 }
52 }
53 fn look(&self) -> Option<char> {
55 match self.input.chars().nth(0) {
56 Some(c) => Some(c),
57 None => None,
58 }
59 }
60 fn advance_literal(&mut self) -> usize {
62 let index = self
63 .input
64 .char_indices()
65 .find(|(_, c)| !literal(c))
66 .map(|(i, _)| i)
67 .unwrap_or(self.input.len());
68 self.col += index as u32;
69 index
70 }
71 fn look_literal(&self) -> &str {
73 let index = self
74 .input
75 .char_indices()
76 .find(|(_, c)| !literal(c))
77 .map(|(i, _)| i)
78 .unwrap_or(self.input.len());
79
80 &self.input[..index]
81 }
82}
83
84trait IsEmpty {
86 fn is_empty(&self) -> bool;
87}
88
89impl<T> IsEmpty for Vec<T> {
90 fn is_empty(&self) -> bool {
91 self.len() == 0
92 }
93}
94
95impl IsEmpty for &str {
96 fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99}
100
101struct Parser<'a, T> {
103 parse: Box<dyn Fn(Leftover<'a>) -> Option<(Leftover<'a>, Result<T, String>)> + 'a>,
104}
105
106impl<'a, T: 'a> Parser<'a, T> {
108 fn fmap<B: 'a, F>(self, f: F) -> Parser<'a, B>
110 where
111 F: Fn(T) -> B + 'a,
112 {
113 Parser {
114 parse: Box::new(move |input| match (self.parse)(input) {
115 None => None,
116 Some((leftover, res)) => Some((
117 leftover,
118 match res {
119 Err(msg) => Err(msg),
120 Ok(x) => Ok(f(x)),
121 },
122 )),
123 }),
124 }
125 }
126
127 fn ap<A: 'a, B: 'a>(self, p: Parser<'a, A>) -> Parser<'a, B>
129 where
130 T: Fn(A) -> B,
131 {
132 Parser {
133 parse: Box::new(move |input| match (self.parse)(input) {
134 None => None,
135 Some((leftover1, res1)) => match res1 {
136 Err(msg) => Some((leftover1, Err(msg))),
137 Ok(f) => match (p.parse)(leftover1) {
138 None => None,
139 Some((leftover2, res2)) => Some((
140 leftover2,
141 match res2 {
142 Err(msg) => Err(msg),
143 Ok(x) => Ok(f(x)),
144 },
145 )),
146 },
147 },
148 }),
149 }
150 }
151
152 fn left<B: 'a>(self, p: Parser<'a, B>) -> Parser<'a, T> {
154 Parser {
155 parse: Box::new(move |input| match (self.parse)(input) {
156 None => None,
157 Some((leftover1, res1)) => match res1 {
158 Err(msg) => Some((leftover1, Err(msg))),
159 Ok(x) => match (p.parse)(leftover1) {
160 None => None,
161 Some((leftover2, res2)) => match res2 {
162 Err(msg) => Some((leftover2, Err(msg))),
163 Ok(_) => Some((leftover2, Ok(x))),
164 },
165 },
166 },
167 }),
168 }
169 }
170
171 fn right<B: 'a>(self, p: Parser<'a, B>) -> Parser<'a, B> {
173 Parser {
174 parse: Box::new(move |input| match (self.parse)(input) {
175 None => None,
176 Some((leftover1, res1)) => match res1 {
177 Err(msg) => Some((leftover1, Err(msg))),
178 Ok(_) => match (p.parse)(leftover1) {
179 None => None,
180 Some((leftover2, res2)) => match res2 {
181 Err(msg) => Some((leftover2, Err(msg))),
182 Ok(y) => Some((leftover2, Ok(y))),
183 },
184 },
185 },
186 }),
187 }
188 }
189
190 fn or(self, p2: Parser<'a, T>) -> Parser<'a, T> {
192 Parser {
193 parse: Box::new(move |input| match (self.parse)(input) {
194 Some(output) => Some(output),
195 None => (p2.parse)(input),
196 }),
197 }
198 }
199
200 fn condition<C>(self, cond: C) -> Parser<'a, T>
202 where
203 C: Fn(&T) -> bool + 'a,
204 {
205 Parser {
206 parse: Box::new(move |input| match (self.parse)(input) {
207 None => None,
208 Some((leftover, res)) => match res {
209 Ok(results) => {
210 if cond(&results) {
211 Some((leftover, Ok(results)))
212 } else {
213 None
214 }
215 }
216 err => Some((leftover, err)),
217 },
218 }),
219 }
220 }
221
222 fn condition_e<C>(self, cond: C, msg: &'a str) -> Parser<'a, T>
224 where
225 C: Fn(&T) -> bool + 'a,
226 {
227 Parser {
228 parse: Box::new(move |input| match (self.parse)(input) {
229 None => None,
230 Some((leftover, res)) => Some((
231 leftover,
232 match res {
233 Ok(results) => {
234 if cond(&results) {
235 Ok(results)
236 } else {
237 Err(msg.to_string())
238 }
239 }
240 err => err,
241 },
242 )),
243 }),
244 }
245 }
246
247 fn not_null(self) -> Parser<'a, T>
249 where
250 T: IsEmpty,
251 {
252 self.condition(|v| !v.is_empty())
253 }
254
255 fn not_null_e(self, msg: &'a str) -> Parser<'a, T>
257 where
258 T: IsEmpty,
259 {
260 self.condition_e(|v| !v.is_empty(), msg)
261 }
262
263 fn many(self) -> Parser<'a, Vec<T>> {
265 Parser {
266 parse: Box::new(move |input| {
267 let mut results = Vec::new();
268 let mut current_input = input;
269 while let Some((next_input, res)) = (self.parse)(current_input) {
270 match res {
271 Err(msg) => return Some((next_input, Err(msg))),
272 Ok(x) => {
273 results.push(x);
274 current_input = next_input;
275 }
276 }
277 }
278 Some((current_input, Ok(results)))
279 }),
280 }
281 }
282
283 fn some(self) -> Parser<'a, Vec<T>> {
285 self.many().not_null()
286 }
287
288 fn span<C>(self, cond: C) -> Parser<'a, Vec<T>>
290 where
291 C: Fn(&T) -> bool + 'a,
292 {
293 self.condition(cond).many()
294 }
295
296 fn span_e<C>(self, cond: C, msg: &'a str) -> Parser<'a, Vec<T>>
298 where
299 C: Fn(&T) -> bool + 'a,
300 {
301 self.condition_e(cond, msg).many()
302 }
303
304 fn raise(self, msg: &'a str) -> Parser<'a, T> {
306 Parser {
307 parse: Box::new(move |input| match (self.parse)(input) {
308 Some(result) => Some(result),
309 None => Some((input, Err(msg.to_string()))),
310 }),
311 }
312 }
313 fn raise_look(self, msg: &'a str) -> Parser<'a, T> {
315 Parser {
316 parse: Box::new(move |input| match (self.parse)(input) {
317 Some(result) => Some(result),
318 None => Some((
319 input,
320 Err(format!(
321 "{}{}",
322 msg,
323 match input.look() {
324 None => "no more input".to_string(),
325 Some(c) => c.to_string(),
326 }
327 )),
328 )),
329 }),
330 }
331 }
332 fn raise_literal(self, prefix: &'a str, msg: &'a str, postfix: &'a str) -> Parser<'a, T> {
334 Parser {
335 parse: Box::new(move |input| match (self.parse)(input) {
336 Some(result) => Some(result),
337 None => Some((
338 input,
339 Err(format!(
340 "{}{}{}{}",
341 prefix,
342 msg,
343 postfix,
344 input.look_literal()
345 )),
346 )),
347 }),
348 }
349 }
350}
351
352fn any_char_p<'a>() -> Parser<'a, char> {
354 Parser {
355 parse: Box::new(move |mut input| {
356 let current = input.advance();
357 match current {
358 None => None,
359 Some(c) => Some((input, Ok(c))),
360 }
361 }),
362 }
363}
364
365fn char_p<'a>(x: char) -> Parser<'a, char> {
367 Parser {
368 parse: Box::new(move |mut input| {
369 let current = input.advance();
370 match current {
371 None => None,
372 Some(c) if c != x => None,
373 _ => Some((input, Ok(x))),
374 }
375 }),
376 }
377}
378
379fn char_pe<'a>(x: char) -> Parser<'a, char> {
381 Parser {
382 parse: Box::new(move |mut input| {
383 let current = input.advance();
384 match current {
385 None => Some((input, Err(format!("Expected {} found no more input", x)))),
386 Some(c) if c != x => Some((input, Err(format!("Expected {} found {}", x, c)))),
387 _ => Some((input, Ok(x))),
388 }
389 }),
390 }
391}
392
393fn not_char_p<'a>(x: char) -> Parser<'a, ()> {
395 Parser {
396 parse: Box::new(move |input| match input.look() {
397 Some(c) if c == x => None,
398 _ => Some((input, Ok(()))),
399 }),
400 }
401}
402
403fn move_pe<'a>() -> Parser<'a, Move> {
405 (char_p('L').fmap(|_| Move::Left))
406 .or(char_p('R').fmap(|_| Move::Right))
407 .or(char_p('N').fmap(|_| Move::Neutral))
408 .raise_look("Expected move symbol found ")
409}
410
411fn ws0<'a>() -> Parser<'a, &'a str> {
413 char_p(' ').many().fmap(|_| "")
414}
415
416fn ws1<'a>() -> Parser<'a, &'a str> {
418 (char_p(' ').or(char_p('\n'))).many().fmap(|_| "")
419}
420
421fn symbol_p<'a>() -> Parser<'a, char> {
423 any_char_p().condition(allowed_tape)
424}
425
426fn symbol_pe<'a>() -> Parser<'a, char> {
428 symbol_p().raise_look("Expected tape symbol found ")
429}
430
431fn literal_p<'a>() -> Parser<'a, &'a str> {
433 Parser {
434 parse: Box::new(|mut input| {
435 let index = input.advance_literal();
436 let lit = &input.input[..index];
437 input.input = &input.input[index..];
438 Some((input, Ok(lit)))
439 }),
440 }
441}
442
443fn word_pe<'a>() -> Parser<'a, &'a str> {
445 literal_p()
446 .condition(|s| s.chars().all(|c| allowed_name(&c)))
447 .raise_literal("", "Forbidden symbol in word ", "")
448}
449
450fn tape_pe<'a>() -> Parser<'a, &'a str> {
452 literal_p()
453 .condition(|s| s.chars().all(|c| allowed_tape(&c)))
454 .raise_literal("", "Forbidden symbol in tape sequence ", "")
455}
456
457fn string_p<'a>(s: &'a str) -> Parser<'a, &'a str> {
459 Parser {
460 parse: Box::new(move |mut input| {
461 let mut chars = s.chars();
462 while let Some(expected) = chars.next() {
463 match input.advance() {
464 Some(c) if c == expected => {}
465 _ => return None,
466 }
467 }
468 Some((input, Ok(s)))
469 }),
470 }
471}
472
473fn string_pe<'a>(s: &'a str) -> Parser<'a, &'a str> {
475 string_p(s).raise_literal("Expected ", s, " found ")
476}
477
478fn fmake<'a, A: 'a, B: 'a, F>(f: F) -> Parser<'a, F>
480where
481 F: Fn(A) -> B + 'a,
482 F: Clone,
483{
484 Parser {
485 parse: Box::new(move |input| Some((input, Ok(f.clone())))),
486 }
487}
488
489fn transition_pe<'a>() -> Parser<'a, Transition> {
491 fmake(|read_sym| {
492 move |write_sym| move |move_sym| move |new_state| (read_sym, write_sym, move_sym, new_state)
493 })
494 .ap(ws1().right(symbol_pe()).left(ws0()).left(char_pe('/')))
495 .ap(ws0().right(symbol_pe()).left(ws0()).left(char_pe(',')))
496 .ap(ws0().right(move_pe()).left(ws1()).left(string_pe("->")))
497 .ap(ws0().right(
498 word_pe()
499 .not_null_e("Expected new state")
500 .left(ws0())
501 .left(char_pe(';')),
502 ))
503 .fmap(
504 |(read_symbol, write_symbol, move_symbol, new_state)| Transition {
505 read_symbol,
506 write_symbol,
507 move_symbol,
508 new_state: new_state.to_string(),
509 },
510 )
511}
512
513fn ws2<'a>() -> Parser<'a, &'a str> {
515 (char_p(' ').or(char_p('\n')))
516 .some()
517 .fmap(|_| "")
518 .raise("Expected space")
519}
520
521fn not_followed<'a>(x: char, y: char) -> Parser<'a, char> {
523 Parser {
524 parse: Box::new(move |mut input| {
525 let current = input.advance();
526 match current {
527 None => None,
528 Some(c) if c != x => Some((input, Ok(x))),
529 _ => match input.look() {
530 None => Some((input, Ok(x))),
531 Some(z) if z != y => Some((input, Ok(x))),
532 _ => None,
533 },
534 }
535 }),
536 }
537}
538
539fn comment_pe<'a>() -> Parser<'a, &'a str> {
541 string_p("--")
542 .right(any_char_p().span(|x| *x != '\n'))
543 .or(string_p("{-")
544 .right(not_followed('-', '}').many())
545 .left(string_pe("-}")))
546 .fmap(|_| "")
547}
548
549fn ws3<'a>() -> Parser<'a, &'a str> {
551 ws1().left(comment_pe().right(ws1()).many())
552}
553
554fn state_pe<'a>() -> Parser<'a, StateType> {
556 let final_p = fmake(|b: bool| {
557 move |s: &str| {
558 if b {
559 StateType::Accept(s.to_string())
560 } else {
561 StateType::Reject(s.to_string())
562 }
563 }
564 })
565 .ap(string_p("reject")
566 .fmap(|_| false)
567 .or(string_p("accept").fmap(|_| true)))
568 .ap(ws2()
569 .right(string_pe("state"))
570 .right(ws2())
571 .right(word_pe().not_null_e("Expected state name"))
572 .left(ws0())
573 .left(char_pe(';')));
574 let initial_p = || (string_p("initial").right(ws2()).fmap(|_| true)).or(ws1().fmap(|_| false));
575 let arrow_p = fmake(move |b: bool| {
576 move |from: &'a str| {
577 move |to: &'a str| {
578 StateType::State(
579 from.to_string(),
580 State {
581 initial: b,
582 transitions: Box::new(vec![Transition {
583 read_symbol: '_',
584 write_symbol: '_',
585 move_symbol: Move::Neutral,
586 new_state: to.to_string(),
587 }]),
588 },
589 )
590 }
591 }
592 })
593 .ap(initial_p())
594 .ap(string_pe("state")
595 .right(ws2())
596 .right(word_pe().not_null_e("Expected state name")))
597 .ap(ws1()
598 .right(string_p("->"))
599 .right(ws1())
600 .right(word_pe().not_null_e("Expected state name"))
601 .left(ws0())
602 .left(char_pe(';')));
603 let tr_p = ws3()
604 .right(not_char_p('}').right(transition_pe()).left(ws3()).many())
605 .not_null_e("States can't have 0 transitions");
606 let normal_p = fmake(move |b| {
607 move |from: &'a str| {
608 move |trans| {
609 StateType::State(
610 from.to_string(),
611 State {
612 initial: b,
613 transitions: Box::new(trans),
614 },
615 )
616 }
617 }
618 })
619 .ap(initial_p())
620 .ap(string_pe("state")
621 .right(ws2())
622 .right(word_pe().not_null_e("Expected state name")))
623 .ap(ws1().right(char_pe('{')).right(tr_p).left(char_pe('}')));
624 final_p.or(arrow_p).or(normal_p)
625}
626
627fn sep_by<'a, B: 'a>(
629 p1: Parser<'a, &'a str>,
630 p2: Parser<'a, &'a str>,
631 sep: Parser<'a, B>,
632) -> Parser<'a, Vec<&'a str>> {
633 fmake(move |element: &'a str| {
634 move |mut list: Vec<&'a str>| {
635 list.insert(0, element);
636 list
637 }
638 })
639 .ap(p1)
640 .ap(sep.right(p2).many())
641 .or(Parser {
642 parse: Box::new(move |input| Some((input, Ok(vec![])))),
643 })
644}
645
646fn sep_by2<'a, B: 'a>(
648 p1: Parser<'a, (&'a str, &'a str)>,
649 p2: Parser<'a, (&'a str, &'a str)>,
650 sep: Parser<'a, B>,
651) -> Parser<'a, Vec<(&'a str, &'a str)>> {
652 fmake(move |element: (&'a str, &'a str)| {
653 move |mut list: Vec<(&'a str, &'a str)>| {
654 list.insert(0, element);
655 list
656 }
657 })
658 .ap(p1)
659 .ap(sep.right(p2).many())
660 .or(Parser {
661 parse: Box::new(move |input| Some((input, Ok(vec![])))),
662 })
663}
664
665fn comma_p<'a>() -> Parser<'a, char> {
667 ws1().right(char_p(',')).left(ws1())
668}
669
670fn pair_p<'a>() -> Parser<'a, (&'a str, &'a str)> {
672 fmake(move |first: &'a str| move |second: &'a str| (first, second))
673 .ap(word_pe().not_null())
674 .ap(ws2().right(word_pe()))
675}
676
677fn pair_pe<'a>() -> Parser<'a, (&'a str, &'a str)> {
679 fmake(move |first: &'a str| move |second: &'a str| (first, second))
680 .ap(word_pe().not_null_e("Expected component type"))
681 .ap(ws2().right(word_pe().not_null_e("Expected component name")))
682}
683
684fn machine_pe<'a>() -> Parser<'a, AutomatonType> {
686 fmake(move |name: &'a str| {
687 move |components: Vec<(&'a str, &'a str)>| {
688 move |states| {
689 AutomatonType::Machine(
690 name.to_string(),
691 Machine {
692 components: Box::new(
693 components
694 .iter()
695 .map(|(c_type, c_name)| (c_type.to_string(), c_name.to_string()))
696 .collect(),
697 ),
698 states: Box::new(states),
699 },
700 )
701 }
702 }
703 })
704 .ap(string_p("automaton")
705 .right(ws2())
706 .right(word_pe().not_null_e("Expected automaton name"))
707 .left(ws1()))
708 .ap(not_char_p('=')
709 .right(char_pe('('))
710 .right(ws1())
711 .right(sep_by2(pair_p(), pair_pe(), comma_p()))
712 .left(ws1())
713 .left(char_pe(')'))
714 .left(ws1()))
715 .ap(char_pe('{')
716 .right(ws3())
717 .right(
718 not_char_p('}')
719 .right(state_pe())
720 .left(ws3())
721 .many()
722 .not_null_e("Automaton can't have 0 states"),
723 )
724 .left(char_pe('}')))
725}
726
727fn number_pe<'a>() -> Parser<'a, u32> {
729 literal_p()
730 .fmap(|s| s.to_string())
731 .condition(|s| s.chars().all(|c| c >= '0' && c <= '9'))
732 .raise_literal("", "Expected number literal found ", "")
733 .fmap(|s| s.parse::<u32>().unwrap())
734}
735
736fn complement_pe<'a>() -> Parser<'a, MacroType> {
738 string_p("complement")
739 .right(ws1())
740 .right(char_pe('('))
741 .right(ws1())
742 .right(word_pe())
743 .not_null_e("Expected component name")
744 .left(char_pe(')'))
745 .fmap(|component: &'a str| MacroType::Complement(component.to_string()))
746}
747
748fn intersect_pe<'a>() -> Parser<'a, MacroType> {
749 string_p("intersect")
750 .right(ws1())
751 .right(char_pe('('))
752 .right(ws1())
753 .right(sep_by(
754 word_pe().not_null_e("Expected component list"),
755 word_pe(),
756 comma_p(),
757 ))
758 .condition_e(|v| v.len() > 1, "Expected two or more components")
759 .left(char_pe(')'))
760 .fmap(|components| {
761 MacroType::Intersect(Box::new(components.iter().map(|c| c.to_string()).collect()))
762 })
763}
764
765fn reunion_pe<'a>() -> Parser<'a, MacroType> {
766 string_p("reunion")
767 .right(ws1())
768 .right(char_pe('('))
769 .right(ws1())
770 .right(sep_by(
771 word_pe().not_null_e("Expected component list"),
772 word_pe(),
773 comma_p(),
774 ))
775 .condition_e(|v| v.len() > 1, "Expected two or more components")
776 .left(char_pe(')'))
777 .fmap(|components| {
778 MacroType::Reunion(Box::new(components.iter().map(|c| c.to_string()).collect()))
779 })
780}
781
782fn chain_pe<'a>() -> Parser<'a, MacroType> {
783 string_p("chain")
784 .right(ws1())
785 .right(char_pe('('))
786 .right(ws1())
787 .right(sep_by(
788 word_pe().not_null_e("Expected component list"),
789 word_pe(),
790 comma_p(),
791 ))
792 .condition_e(|v| v.len() > 1, "Expected two or more components")
793 .left(char_pe(')'))
794 .fmap(|components| {
795 MacroType::Chain(Box::new(components.iter().map(|c| c.to_string()).collect()))
796 })
797}
798
799fn repeat_pe<'a>() -> Parser<'a, MacroType> {
800 fmake(move |num| move |component: &'a str| MacroType::Repeat(num, component.to_string()))
801 .ap(string_p("repeat")
802 .right(ws1())
803 .right(char_pe('('))
804 .right(ws1())
805 .right(number_pe())
806 .left(ws1()))
807 .ap(char_pe(',')
808 .right(ws1())
809 .right(word_pe().not_null_e("Expected component name"))
810 .left(ws1())
811 .left(char_pe(')')))
812}
813
814fn move_mpe<'a>() -> Parser<'a, MacroType> {
815 fmake(move |move_symbol| move |num| MacroType::Move(move_symbol, num))
816 .ap(string_p("move")
817 .right(ws1())
818 .right(char_pe('('))
819 .right(ws1())
820 .right(move_pe())
821 .left(ws1()))
822 .ap(char_pe(',')
823 .right(ws1())
824 .right(number_pe())
825 .left(ws1())
826 .left(char_pe(')')))
827}
828
829fn override_pe<'a>() -> Parser<'a, MacroType> {
830 fmake(move |move_symbol| {
831 move |num| move |tape_symbol| MacroType::Override(move_symbol, num, tape_symbol)
832 })
833 .ap(string_p("override")
834 .right(ws1())
835 .right(char_pe('('))
836 .right(ws1())
837 .right(move_pe())
838 .left(ws1()))
839 .ap(char_pe(',').right(ws1()).right(number_pe()).left(ws1()))
840 .ap(char_pe(',')
841 .right(ws1())
842 .right(char_pe('\''))
843 .right(symbol_pe())
844 .left(char_pe('\''))
845 .left(ws1())
846 .left(char_pe(')')))
847}
848
849fn place_pe<'a>() -> Parser<'a, MacroType> {
850 string_p("place")
851 .right(ws1())
852 .right(char_pe('('))
853 .right(ws1())
854 .right(char_pe('\"'))
855 .right(tape_pe())
856 .left(char_pe('\"'))
857 .left(ws1())
858 .left(char_pe(')'))
859 .fmap(move |content: &'a str| MacroType::Place(content.to_string()))
860}
861
862fn shift<'a>() -> Parser<'a, MacroType> {
863 fmake(move |move_symbol| move |num| MacroType::Shift(move_symbol, num))
864 .ap(string_p("shift")
865 .right(ws1())
866 .right(char_pe('('))
867 .right(ws1())
868 .right(move_pe())
869 .left(ws1()))
870 .ap(char_pe(',')
871 .right(ws1())
872 .right(number_pe())
873 .left(ws1())
874 .left(char_pe(')')))
875}
876
877fn macro_pe<'a>() -> Parser<'a, AutomatonType> {
879 fmake(move |name: &'a str| move |macro_type| AutomatonType::Macro(name.to_string(), macro_type))
880 .ap(string_p("automaton")
881 .right(ws2())
882 .right(word_pe())
883 .not_null_e("Expected automaton name"))
884 .left(ws1())
885 .left(char_p('='))
886 .left(ws1())
887 .ap(complement_pe()
888 .or(intersect_pe())
889 .or(reunion_pe())
890 .or(chain_pe())
891 .or(repeat_pe())
892 .or(move_mpe())
893 .or(override_pe())
894 .or(place_pe())
895 .or(shift())
896 .raise_literal("", "Expected macro keyword found ", ""))
897 .left(ws0())
898 .left(char_pe(';'))
899}
900
901fn automaton_pe<'a>() -> Parser<'a, AutomatonType> {
903 macro_pe().or(machine_pe())
904}
905
906fn done_p<'a>() -> Parser<'a, ()> {
908 Parser {
909 parse: Box::new(move |input| match input.look() {
910 Some(_) => None,
911 _ => Some((input, Ok(()))),
912 }),
913 }
914}
915
916fn program_pe<'a>() -> Parser<'a, Program> {
918 ws3()
919 .right(automaton_pe())
920 .left(ws3())
921 .many()
922 .left(done_p().raise_literal("", "Expected automaton found unexpected keyword ", ""))
923 .fmap(move |automata| Program {
924 automata: Box::new(automata),
925 })
926}
927
928pub fn parse_move(input: &str) -> Result<Move, String> {
931 match (move_pe().parse)(Leftover {
932 input,
933 row: 0,
934 col: 0,
935 }) {
936 None => panic!("move parser should never return none"),
937 Some((_, res)) => res,
938 }
939}
940
941pub fn parse_transition(input: &str) -> Result<Transition, String> {
942 match (transition_pe().parse)(Leftover {
943 input,
944 row: 0,
945 col: 0,
946 }) {
947 None => panic!("transition parser should never return none"),
948 Some((_, res)) => res,
949 }
950}
951
952pub fn parse_state(input: &str) -> Result<StateType, String> {
953 match (state_pe().parse)(Leftover {
954 input,
955 row: 0,
956 col: 0,
957 }) {
958 None => panic!("state parser should never return none"),
959 Some((_, res)) => res,
960 }
961}
962
963pub fn parse_automaton(input: &str) -> Result<AutomatonType, String> {
964 match (automaton_pe().parse)(Leftover {
965 input,
966 row: 0,
967 col: 0,
968 }) {
969 None => panic!("automaton parser should never return none"),
970 Some((_, res)) => res,
971 }
972}
973
974pub fn parse_program(input: &str) -> Result<Program, (Leftover, String)> {
975 match (program_pe().parse)(Leftover {
976 input,
977 row: 0,
978 col: 0,
979 }) {
980 None => panic!("program parser should never return none"),
981 Some((leftover, res)) => match res {
982 Ok(prog) => Ok(prog),
983 Err(err) => Err((leftover, err)),
984 },
985 }
986}