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