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