• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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