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 #[allow(dead_code)]
52 struct Paren(Vec<Paren>);
53
expr(pairs: Pairs<Rule>) -> Vec<Paren>54 fn expr(pairs: Pairs<Rule>) -> Vec<Paren> {
55 pairs
56 .filter(|p| p.as_rule() == Rule::paren)
57 .map(|p| Paren(expr(p.into_inner())))
58 .collect()
59 }
60
main()61 fn main() {
62 loop {
63 let mut line = String::new();
64
65 print!("> ");
66 io::stdout().flush().unwrap();
67
68 io::stdin().read_line(&mut line).unwrap();
69 line.pop();
70
71 let parsed = ParenParser::parse(Rule::expr, &line);
72 #[cfg(feature = "miette-error")]
73 let parsed = parsed
74 .map_err(Error::into_miette)
75 .map_err(miette::Report::from);
76
77 match parsed {
78 Ok(pairs) => println!("{:?}", expr(pairs)),
79 // To print pest errors, use Display formatting.
80 #[cfg(not(feature = "miette-error"))]
81 Err(e) => eprintln!("\n{}", e),
82 // To print miette errors, use Debug formatting.
83 #[cfg(feature = "miette-error")]
84 Err(e) => eprintln!("\n{:?}", e),
85 };
86 }
87 }
88