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