1 mod parser {
2     use pest_derive::Parser;
3 
4     #[derive(Parser)]
5     #[grammar = "../examples/base.pest"]
6     #[grammar = "../examples/calc.pest"]
7     pub struct Parser;
8 }
9 
10 use parser::Rule;
11 use pest::{
12     iterators::Pairs,
13     pratt_parser::{Assoc::*, Op, PrattParser},
14     Parser,
15 };
16 use std::io::{stdin, stdout, Write};
17 
parse_to_str(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> String18 fn parse_to_str(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> String {
19     pratt
20         .map_primary(|primary| match primary.as_rule() {
21             Rule::int => primary.as_str().to_owned(),
22             Rule::expr => parse_to_str(primary.into_inner(), pratt),
23             _ => unreachable!(),
24         })
25         .map_prefix(|op, rhs| match op.as_rule() {
26             Rule::neg => format!("(-{})", rhs),
27             _ => unreachable!(),
28         })
29         .map_postfix(|lhs, op| match op.as_rule() {
30             Rule::fac => format!("({}!)", lhs),
31             _ => unreachable!(),
32         })
33         .map_infix(|lhs, op, rhs| match op.as_rule() {
34             Rule::add => format!("({}+{})", lhs, rhs),
35             Rule::sub => format!("({}-{})", lhs, rhs),
36             Rule::mul => format!("({}*{})", lhs, rhs),
37             Rule::div => format!("({}/{})", lhs, rhs),
38             Rule::pow => format!("({}^{})", lhs, rhs),
39             _ => unreachable!(),
40         })
41         .parse(pairs)
42 }
43 
parse_to_i32(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> i12844 fn parse_to_i32(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> i128 {
45     pratt
46         .map_primary(|primary| match primary.as_rule() {
47             Rule::int => primary.as_str().parse().unwrap(),
48             Rule::expr => parse_to_i32(primary.into_inner(), pratt),
49             _ => unreachable!(),
50         })
51         .map_prefix(|op, rhs| match op.as_rule() {
52             Rule::neg => -rhs,
53             _ => unreachable!(),
54         })
55         .map_postfix(|lhs, op| match op.as_rule() {
56             Rule::fac => (1..lhs + 1).product(),
57             _ => unreachable!(),
58         })
59         .map_infix(|lhs, op, rhs| match op.as_rule() {
60             Rule::add => lhs + rhs,
61             Rule::sub => lhs - rhs,
62             Rule::mul => lhs * rhs,
63             Rule::div => lhs / rhs,
64             Rule::pow => (1..rhs + 1).map(|_| lhs).product(),
65             _ => unreachable!(),
66         })
67         .parse(pairs)
68 }
69 
main()70 fn main() {
71     let pratt = PrattParser::new()
72         .op(Op::infix(Rule::add, Left) | Op::infix(Rule::sub, Left))
73         .op(Op::infix(Rule::mul, Left) | Op::infix(Rule::div, Left))
74         .op(Op::infix(Rule::pow, Right))
75         .op(Op::prefix(Rule::neg))
76         .op(Op::postfix(Rule::fac));
77 
78     let stdin = stdin();
79     let mut stdout = stdout();
80 
81     loop {
82         let source = {
83             print!("> ");
84             let _ = stdout.flush();
85             let mut input = String::new();
86             let _ = stdin.read_line(&mut input);
87             input.trim().to_string()
88         };
89 
90         let pairs = match parser::Parser::parse(Rule::program, &source) {
91             Ok(mut parse_tree) => {
92                 parse_tree
93                     .next()
94                     .unwrap()
95                     .into_inner() // inner of program
96                     .next()
97                     .unwrap()
98                     .into_inner() // inner of expr
99             }
100             Err(err) => {
101                 println!("Failed parsing input: {:}", err);
102                 continue;
103             }
104         };
105 
106         print!("{} => ", source);
107         print!("{} => ", parse_to_str(pairs.clone(), &pratt));
108         println!("{}", parse_to_i32(pairs.clone(), &pratt));
109     }
110 }
111