parens/
parens.rs

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