1use crate::syntax::{AutomatonType, Machine, MacroType, Program};
2use crate::syntax::{Move, State};
3use crate::syntax::{StateType, Transition};
4
5const ALLOWED_NAME_SYMBOLS: &str = "abcdefghijklmnopqrstuvwxyz0123456789_.";
6const ALLOWED_TAPE_SYMBOLS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*[]-+=/?_:";
7
8enum Parser<'a, T> {
10 Parser(Box<dyn Fn(&'a str) -> Option<(&'a str, T)> + 'a>),
11}
12
13fn fmap<'a, A: 'a, B: 'a, F>(f: F, p: Parser<'a, A>) -> Parser<'a, B>
14where
15 F: Fn(A) -> B + 'a,
16{
17 match p {
18 Parser::Parser(parse) => Parser::Parser(Box::new(move |input| match parse(input) {
19 None => None,
20 Some((input2, x)) => Some((input2, f(x))),
21 })),
22 }
23}
24
25fn char_p<'a>(x: char) -> Parser<'a, char> {
26 Parser::Parser(Box::new(move |input: &'a str| {
27 let mut chars = input.char_indices();
28 match chars.next() {
29 Some((_, c)) if c == x => {
30 let next_index = c.len_utf8();
31 Some((&input[next_index..], c))
32 }
33 _ => None,
34 }
35 }))
36}
37fn pure<'a, T: Clone + 'a>(x: T) -> Parser<'a, T> {
38 Parser::Parser(Box::new(move |input| Some((input, x.clone()))))
39}
40
41fn ap<'a, A: 'a, B: 'a, F>(pf: Parser<'a, F>, pa: Parser<'a, A>) -> Parser<'a, B>
42where
43 F: Fn(A) -> B + 'a,
44{
45 Parser::Parser(Box::new(move |input| {
46 let Parser::Parser(ref pf_inner) = pf;
47 let Parser::Parser(ref pa_inner) = pa;
48 pf_inner(input).and_then(|(input1, f)| pa_inner(input1).map(|(input2, x)| (input2, f(x))))
49 }))
50}
51
52fn empty<'a, T: 'a>() -> Parser<'a, T> {
53 Parser::Parser(Box::new(|_| None))
54}
55
56fn or<'a, T: 'a>(p1: Parser<'a, T>, p2: Parser<'a, T>) -> Parser<'a, T> {
57 Parser::Parser(Box::new(move |input| {
58 let Parser::Parser(ref p1_inner) = p1;
59 let Parser::Parser(ref p2_inner) = p2;
60 p1_inner(input).or_else(|| p2_inner(input))
61 }))
62}
63
64fn string_p<'a>(s: &'a str) -> Parser<'a, String> {
65 s.chars().fold(pure(String::new()), |acc, c| {
66 let f = |s: &String, ch: char| {
67 let mut new_s = s.clone();
68 new_s.push(ch);
69 new_s
70 };
71 ap(
72 fmap(
73 move |s| {
74 let s = s.clone();
75 move |ch| f(&s, ch)
76 },
77 acc,
78 ),
79 char_p(c),
80 )
81 })
82}
83
84fn span_p<'a, F>(f: F) -> Parser<'a, String>
85where
86 F: Fn(char) -> bool + 'a,
87{
88 Parser::Parser(Box::new(move |input: &'a str| {
89 let token: String = input.chars().take_while(|&c| f(c)).collect();
90 let len = token.chars().map(|c| c.len_utf8()).sum();
91 if !token.is_empty() {
92 Some((&input[len..], token))
93 } else {
94 Some((input, String::new()))
95 }
96 }))
97}
98
99fn not_null<'a, T: 'a + Clone>(p: Parser<'a, Vec<T>>) -> Parser<'a, Vec<T>> {
100 Parser::Parser(Box::new(move |input| {
101 let Parser::Parser(ref inner) = p;
102 inner(input).and_then(|(input2, xs)| {
103 if xs.is_empty() {
104 None
105 } else {
106 Some((input2, xs))
107 }
108 })
109 }))
110}
111
112fn not_nulls<'a>(p: Parser<'a, String>) -> Parser<'a, String> {
113 Parser::Parser(Box::new(move |input| {
114 let Parser::Parser(ref inner) = p;
115 inner(input).and_then(|(input2, xs)| {
116 if xs.is_empty() {
117 None
118 } else {
119 Some((input2, xs))
120 }
121 })
122 }))
123}
124
125fn sep_by<'a, A: 'a, B: 'a>(sep: Parser<'a, A>, element: Parser<'a, B>) -> Parser<'a, Vec<B>> {
126 let rest = Parser::Parser(Box::new(move |input| {
127 let Parser::Parser(ref sep_inner) = sep;
128 let Parser::Parser(ref element_inner) = element;
129 let mut result = Vec::new();
130 let mut current_input = input;
131 if let Some((input2, first)) = element_inner(current_input) {
132 result.push(first);
133 current_input = input2;
134 while let Some((input3, _)) = sep_inner(current_input) {
135 if let Some((input4, next)) = element_inner(input3) {
136 result.push(next);
137 current_input = input4;
138 } else {
139 break;
140 }
141 }
142 Some((current_input, result))
143 } else {
144 Some((input, Vec::new()))
145 }
146 }));
147 rest
148}
149
150fn ws<'a>() -> Parser<'a, String> {
151 span_p(|c| c == ' ' || c == '\n')
152}
153
154fn ws2<'a>() -> Parser<'a, String> {
155 fmap(
156 |chars: Vec<char>| chars.into_iter().collect::<String>(),
157 not_null(fmap(|s: String| s.chars().collect::<Vec<char>>(), ws())),
158 )
159}
160fn number_p<'a>() -> Parser<'a, i32> {
161 Parser::Parser(Box::new(move |input| {
162 let Parser::Parser(ref inner) = span_p(|c| "0123456789".contains(c));
163 inner(input).and_then(|(input2, s)| match s.parse::<i32>() {
164 Ok(num) => Some((input2, num)),
165 Err(_) => None,
166 })
167 }))
168}
169
170fn word_p<'a>() -> Parser<'a, String> {
171 span_p(|c| ALLOWED_NAME_SYMBOLS.contains(c))
172}
173
174fn tape_p<'a>() -> Parser<'a, String> {
175 span_p(|c| ALLOWED_TAPE_SYMBOLS.contains(c))
176}
177
178fn symbol_p<'a>() -> Parser<'a, char> {
179 ALLOWED_TAPE_SYMBOLS
180 .chars()
181 .fold(empty(), |acc, c| or(acc, char_p(c)))
182}
183
184fn move_p<'a>() -> Parser<'a, Move> {
185 or(
186 fmap(|_| Move::Left, char_p('L')),
187 or(
188 fmap(|_| Move::Right, char_p('R')),
189 fmap(|_| Move::Neutral, char_p('N')),
190 ),
191 )
192}
193fn transition_p<'a>() -> Parser<'a, Transition> {
194 fmap(
195 |(s, (t, (m, n)))| Transition {
196 read_symbol: s,
197 write_symbol: t,
198 move_symbol: m,
199 new_state: n,
200 },
201 ap(
202 ap(
203 ap(
204 fmap(
205 |s| move |t| move |m| move |n| (s, (t, (m, n))),
206 ws().and_then(symbol_p())
207 .and_keep(ws())
208 .and_keep(char_p('/')),
209 ),
210 ws().and_then(symbol_p())
211 .and_keep(ws())
212 .and_keep(char_p(',')),
213 ),
214 ws().and_then(move_p())
215 .and_keep(ws())
216 .and_keep(string_p("->")),
217 ),
218 ws().and_then(word_p()).and_keep(ws()).and_keep(char_p(';')),
219 ),
220 )
221}
222
223fn some<'a, T: 'a + Clone>(p: Parser<'a, T>) -> Parser<'a, Vec<T>> {
224 not_null(many(p))
225}
226
227fn many<'a, T: 'a>(p: Parser<'a, T>) -> Parser<'a, Vec<T>> {
228 Parser::Parser(Box::new(move |mut input| {
229 let Parser::Parser(ref inner) = p;
230 let mut result = Vec::new();
231 while let Some((input2, x)) = inner(input) {
232 result.push(x);
233 input = input2;
234 }
235 Some((input, result))
236 }))
237}
238
239fn and_then<'a, A: 'a, B: 'a>(self_p: Parser<'a, A>, next: Parser<'a, B>) -> Parser<'a, B> {
240 Parser::Parser(Box::new(move |input| {
241 let Parser::Parser(ref self_inner) = self_p;
242 self_inner(input).and_then(|(input2, _)| {
243 let Parser::Parser(ref next_inner) = next;
244 next_inner(input2)
245 })
246 }))
247}
248
249fn and_keep<'a, A: 'a + Clone, B: 'a>(self_p: Parser<'a, A>, next: Parser<'a, B>) -> Parser<'a, A> {
250 Parser::Parser(Box::new(move |input| {
251 let Parser::Parser(ref self_inner) = self_p;
252 self_inner(input).and_then(|(input2, a)| {
253 let Parser::Parser(ref next_inner) = next;
254 next_inner(input2).map(|(input3, _)| (input3, a.clone()))
255 })
256 }))
257}
258
259trait ParserExt<'a, T: 'a> {
260 fn and_then<B: 'a>(self, next: Parser<'a, B>) -> Parser<'a, B>;
261 fn and_keep<B: 'a>(self, next: Parser<'a, B>) -> Parser<'a, T>
262 where
263 T: Clone;
264}
265impl<'a, T: 'a> ParserExt<'a, T> for Parser<'a, T> {
266 fn and_then<B: 'a>(self, next: Parser<'a, B>) -> Parser<'a, B> {
267 and_then(self, next)
268 }
269 fn and_keep<B: 'a>(self, next: Parser<'a, B>) -> Parser<'a, T>
270 where
271 T: Clone,
272 {
273 and_keep(self, next)
274 }
275}
276
277fn state_p<'a>() -> Parser<'a, StateType> {
278 let make_transitions_block_p = || {
280 char_p('{')
281 .and_then(ws())
282 .and_then(some(transition_p()))
283 .and_keep(ws())
284 .and_keep(char_p('}'))
285 };
286
287 let reject_p = string_p("reject")
289 .and_then(ws2())
290 .and_then(string_p("state"))
291 .and_then(ws2())
292 .and_then(not_nulls(word_p()))
293 .and_keep(ws())
294 .and_keep(char_p(';'));
295
296 let accept_p = string_p("accept")
298 .and_then(ws2())
299 .and_then(string_p("state"))
300 .and_then(ws2())
301 .and_then(not_nulls(word_p()))
302 .and_keep(ws())
303 .and_keep(char_p(';'));
304
305 let initial_p = string_p("initial")
307 .and_then(ws2())
308 .and_then(string_p("state"))
309 .and_then(ws2())
310 .and_then(not_nulls(word_p()))
311 .and_keep(ws());
312
313 let normal_p = string_p("state")
314 .and_then(ws())
315 .and_then(not_nulls(word_p()))
316 .and_keep(ws());
317
318 or(
320 or(
321 fmap(|name: String| StateType::Reject(name), reject_p),
322 fmap(|name: String| StateType::Accept(name), accept_p),
323 ),
324 or(
325 ap(
326 fmap(
327 |name: String| {
328 let name_clone = name.clone();
329 move |transitions| {
330 StateType::State(
331 name_clone.clone(),
332 State {
333 transitions: Box::new(transitions),
334 initial: true,
335 },
336 )
337 }
338 },
339 initial_p,
340 ),
341 make_transitions_block_p(),
342 ),
343 ap(
344 fmap(
345 |name: String| {
346 let name_clone = name.clone();
347 move |transitions| {
348 StateType::State(
349 name_clone.clone(),
350 State {
351 transitions: Box::new(transitions),
352 initial: false,
353 },
354 )
355 }
356 },
357 normal_p,
358 ),
359 make_transitions_block_p(),
360 ),
361 ),
362 )
363}
364
365fn complement_p<'a>() -> Parser<'a, MacroType> {
366 fmap(
367 |name| MacroType::Complement(name),
368 string_p("complement")
369 .and_then(ws())
370 .and_then(char_p('('))
371 .and_then(ws())
372 .and_then(not_nulls(word_p()))
373 .and_keep(ws())
374 .and_keep(char_p(')')),
375 )
376}
377
378fn sep_by_word_p<'a>() -> Parser<'a, Vec<String>> {
379 sep_by(
380 ws().and_then(char_p(',')).and_keep(ws()),
381 not_nulls(word_p()),
382 )
383}
384
385fn intersect_p<'a>() -> Parser<'a, MacroType> {
386 fmap(
387 |names| MacroType::Intersect(Box::new(names)),
388 string_p("intersect")
389 .and_then(ws())
390 .and_then(char_p('('))
391 .and_then(ws())
392 .and_then(not_null(sep_by_word_p()))
393 .and_keep(ws())
394 .and_keep(char_p(')')),
395 )
396}
397
398fn reunion_p<'a>() -> Parser<'a, MacroType> {
399 fmap(
400 |names| MacroType::Reunion(Box::new(names)),
401 string_p("reunion")
402 .and_then(ws())
403 .and_then(char_p('('))
404 .and_then(ws())
405 .and_then(not_null(sep_by_word_p()))
406 .and_keep(ws())
407 .and_keep(char_p(')')),
408 )
409}
410
411fn chain_p<'a>() -> Parser<'a, MacroType> {
412 fmap(
413 |names| MacroType::Chain(Box::new(names)),
414 string_p("chain")
415 .and_then(ws())
416 .and_then(char_p('('))
417 .and_then(ws())
418 .and_then(not_null(sep_by_word_p()))
419 .and_keep(ws())
420 .and_keep(char_p(')')),
421 )
422}
423
424fn repeat_p<'a>() -> Parser<'a, MacroType> {
425 fmap(
426 |(name, n)| MacroType::Repeat(name, n as u32),
427 ap(
428 fmap(
429 |name| move |n| (name.clone(), n),
430 string_p("repeat")
431 .and_then(ws())
432 .and_then(char_p('('))
433 .and_then(ws())
434 .and_then(not_nulls(word_p()))
435 .and_keep(ws()),
436 ),
437 char_p(',')
438 .and_then(ws())
439 .and_then(number_p())
440 .and_keep(ws())
441 .and_keep(char_p(')')),
442 ),
443 )
444}
445
446fn move_mp<'a>() -> Parser<'a, MacroType> {
447 fmap(
448 |(mv, n)| MacroType::Move(mv, n as u32),
449 ap(
450 fmap(
451 |mv| move |n| (mv, n),
452 string_p("move")
453 .and_then(ws())
454 .and_then(char_p('('))
455 .and_then(ws())
456 .and_then(move_p())
457 .and_keep(ws()),
458 ),
459 char_p(',')
460 .and_then(ws())
461 .and_then(number_p())
462 .and_keep(ws())
463 .and_keep(char_p(')')),
464 ),
465 )
466}
467
468fn override_p<'a>() -> Parser<'a, MacroType> {
469 fmap(
470 |((mv, n), sym)| MacroType::Override(mv, n as u32, sym),
471 ap(
472 ap(
473 fmap(
474 |mv| move |n| move |sym| ((mv, n), sym),
475 string_p("override")
476 .and_then(ws())
477 .and_then(char_p('('))
478 .and_then(ws())
479 .and_then(move_p())
480 .and_keep(ws()),
481 ),
482 char_p(',')
483 .and_then(ws())
484 .and_then(number_p())
485 .and_keep(ws())
486 .and_keep(char_p(','))
487 .and_keep(ws()),
488 ),
489 char_p('\'')
490 .and_then(symbol_p())
491 .and_keep(char_p('\''))
492 .and_keep(ws())
493 .and_keep(char_p(')')),
494 ),
495 )
496}
497
498fn place_p<'a>() -> Parser<'a, MacroType> {
499 fmap(
500 |tape| MacroType::Place(tape),
501 string_p("place")
502 .and_then(ws())
503 .and_then(char_p('('))
504 .and_then(ws())
505 .and_then(char_p('"'))
506 .and_then(tape_p())
507 .and_keep(char_p('"'))
508 .and_keep(ws())
509 .and_keep(char_p(')')),
510 )
511}
512
513fn shift_p<'a>() -> Parser<'a, MacroType> {
514 fmap(
515 |(mv, n)| MacroType::Shift(mv, n as u32),
516 ap(
517 fmap(
518 |mv| move |n| (mv, n),
519 string_p("shift")
520 .and_then(ws())
521 .and_then(char_p('('))
522 .and_then(ws())
523 .and_then(move_p())
524 .and_keep(ws()),
525 ),
526 char_p(',')
527 .and_then(ws())
528 .and_then(number_p())
529 .and_keep(ws())
530 .and_keep(char_p(')')),
531 ),
532 )
533}
534
535fn macro_p<'a>() -> Parser<'a, AutomatonType> {
536 fmap(
537 |(name, macro_kw)| AutomatonType::Macro(name, macro_kw),
538 ap(
539 fmap(
540 |name: String| move |macro_kw| (name.clone(), macro_kw),
541 string_p("automaton")
542 .and_then(ws2())
543 .and_then(not_nulls(word_p()))
544 .and_keep(ws())
545 .and_keep(char_p('='))
546 .and_keep(ws()),
547 ),
548 or(
549 complement_p(),
550 or(
551 intersect_p(),
552 or(
553 reunion_p(),
554 or(
555 chain_p(),
556 or(
557 repeat_p(),
558 or(move_mp(), or(override_p(), or(place_p(), shift_p()))),
559 ),
560 ),
561 ),
562 ),
563 ),
564 )
565 .and_keep(ws())
566 .and_keep(char_p(';')),
567 )
568}
569
570fn pair_p<'a>() -> Parser<'a, (String, String)> {
571 ap(
572 fmap(|a: String| move |b: String| (a.clone(), b), word_p()),
573 ws2().and_then(word_p()),
574 )
575}
576
577fn machine_p<'a>() -> Parser<'a, AutomatonType> {
578 fmap(
579 |(name, (pairs, states))| {
580 AutomatonType::Machine(
581 name,
582 Machine {
583 components: Box::new(pairs),
584 states: Box::new(states),
585 },
586 )
587 },
588 ap(
589 ap(
590 fmap(
591 |name: String| {
592 let name_clone = name.clone();
594 move |pairs: Vec<(String, String)>| {
595 let name_clone2 = name_clone.clone();
596 let pairs_clone = pairs.clone();
597 move |states| (name_clone2.clone(), (pairs_clone.clone(), states))
598 }
599 },
600 string_p("automaton")
601 .and_then(ws2())
602 .and_then(not_nulls(word_p()))
603 .and_keep(ws()),
604 ),
605 char_p('(')
606 .and_then(sep_by(ws().and_then(char_p(',')).and_keep(ws()), pair_p()))
607 .and_keep(char_p(')'))
608 .and_keep(ws()),
609 ),
610 char_p('{')
611 .and_then(ws())
612 .and_then(some(state_p().and_keep(ws())))
613 .and_keep(char_p('}')),
614 ),
615 )
616}
617
618fn automata_p<'a>() -> Parser<'a, AutomatonType> {
619 or(macro_p(), machine_p())
620}
621
622fn program_p<'a>() -> Parser<'a, Program> {
623 fmap(
624 |automata| Program {
625 automata: Box::new(automata),
626 },
627 many(ws().and_then(automata_p()).and_keep(ws())),
628 )
629}
630
631pub fn parse_move(input: &str) -> Option<Move> {
632 let Parser::Parser(parse) = move_p();
633 match parse(input) {
634 None => None,
635 Some((_, move_symbol)) => Some(move_symbol),
636 }
637}
638
639pub fn parse_transition(input: &str) -> Option<Transition> {
640 let Parser::Parser(parse) = transition_p();
641 match parse(input) {
642 None => None,
643 Some((_, transition)) => Some(transition),
644 }
645}
646
647pub fn parse_state(input: &str) -> Option<StateType> {
648 let Parser::Parser(parse) = state_p();
649 match parse(input) {
650 None => None,
651 Some((_, state)) => Some(state),
652 }
653}
654
655pub fn parse_automaton(input: &str) -> Option<AutomatonType> {
656 let Parser::Parser(parse) = automata_p();
657 match parse(input) {
658 None => None,
659 Some((_, automaton)) => Some(automaton),
660 }
661}
662
663pub fn parse_program(input: &str) -> Option<Program> {
664 let Parser::Parser(parse) = program_p();
665 match parse(input) {
666 None => None,
667 Some((_, program)) => Some(program),
668 }
669}