1 extern crate pest;
2 
3 use std::io::{self, Write};
4 
5 use pest::error::Error;
6 use pest::iterators::Pairs;
7 use pest::{state, ParseResult, Parser, ParserState};
8 
9 #[allow(dead_code, non_camel_case_types)]
10 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
11 enum Rule {
12     expr,
13     paren,
14     paren_end,
15 }
16 
17 struct ParenParser;
18 
19 impl Parser<Rule> for ParenParser {
parse(rule: Rule, input: &str) -> Result<Pairs<Rule>, Error<Rule>>20     fn parse(rule: Rule, input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
21         fn expr(state: Box<ParserState<'_, Rule>>) -> ParseResult<Box<ParserState<'_, Rule>>> {
22             state.sequence(|s| s.repeat(paren).and_then(|s| s.end_of_input()))
23         }
24 
25         fn paren(state: Box<ParserState<'_, Rule>>) -> ParseResult<Box<ParserState<'_, Rule>>> {
26             state.rule(Rule::paren, |s| {
27                 s.sequence(|s| {
28                     s.match_string("(")
29                         .and_then(|s| {
30                             s.optional(|s| {
31                                 s.sequence(|s| {
32                                     s.lookahead(true, |s| s.match_string("("))
33                                         .and_then(|s| s.repeat(paren))
34                                 })
35                             })
36                         })
37                         .and_then(|s| s.rule(Rule::paren_end, |s| s.match_string(")")))
38                 })
39             })
40         }
41 
42         state(input, |state| match rule {
43             Rule::expr => expr(state),
44             Rule::paren => paren(state),
45             _ => unreachable!(),
46         })
47     }
48 }
49 
50 #[derive(Debug)]
51 struct Paren(Vec<Paren>);
52 
expr(pairs: Pairs<Rule>) -> Vec<Paren>53 fn expr(pairs: Pairs<Rule>) -> Vec<Paren> {
54     pairs
55         .filter(|p| p.as_rule() == Rule::paren)
56         .map(|p| Paren(expr(p.into_inner())))
57         .collect()
58 }
59 
main()60 fn main() {
61     loop {
62         let mut line = String::new();
63 
64         print!("> ");
65         io::stdout().flush().unwrap();
66 
67         io::stdin().read_line(&mut line).unwrap();
68         line.pop();
69 
70         match ParenParser::parse(Rule::expr, &line) {
71             Ok(pairs) => println!("{:?}", expr(pairs)),
72             Err(e) => println!("\n{}", e),
73         };
74     }
75 }
76