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