1 use std::fmt;
2 use std::fmt::{Debug, Display, Formatter};
3 
4 use std::str::FromStr;
5 
6 use winnow::prelude::*;
7 use winnow::{
8     ascii::{digit1 as digits, multispace0 as multispaces},
9     combinator::alt,
10     combinator::delimited,
11     combinator::repeat,
12     token::one_of,
13 };
14 
15 #[derive(Debug, Clone)]
16 pub enum Expr {
17     Value(i64),
18     Add(Box<Expr>, Box<Expr>),
19     Sub(Box<Expr>, Box<Expr>),
20     Mul(Box<Expr>, Box<Expr>),
21     Div(Box<Expr>, Box<Expr>),
22     Paren(Box<Expr>),
23 }
24 
25 impl Expr {
eval(&self) -> i6426     pub fn eval(&self) -> i64 {
27         match self {
28             Self::Value(v) => *v,
29             Self::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
30             Self::Sub(lhs, rhs) => lhs.eval() - rhs.eval(),
31             Self::Mul(lhs, rhs) => lhs.eval() * rhs.eval(),
32             Self::Div(lhs, rhs) => lhs.eval() / rhs.eval(),
33             Self::Paren(expr) => expr.eval(),
34         }
35     }
36 }
37 
38 impl Display for Expr {
fmt(&self, format: &mut Formatter<'_>) -> fmt::Result39     fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
40         use Expr::{Add, Div, Mul, Paren, Sub, Value};
41         match *self {
42             Value(val) => write!(format, "{}", val),
43             Add(ref left, ref right) => write!(format, "{} + {}", left, right),
44             Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
45             Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
46             Div(ref left, ref right) => write!(format, "{} / {}", left, right),
47             Paren(ref expr) => write!(format, "({})", expr),
48         }
49     }
50 }
51 
expr(i: &mut &str) -> PResult<Expr>52 pub fn expr(i: &mut &str) -> PResult<Expr> {
53     let init = term.parse_next(i)?;
54 
55     repeat(0.., (one_of(['+', '-']), term))
56         .fold(
57             move || init.clone(),
58             |acc, (op, val): (char, Expr)| {
59                 if op == '+' {
60                     Expr::Add(Box::new(acc), Box::new(val))
61                 } else {
62                     Expr::Sub(Box::new(acc), Box::new(val))
63                 }
64             },
65         )
66         .parse_next(i)
67 }
68 
term(i: &mut &str) -> PResult<Expr>69 fn term(i: &mut &str) -> PResult<Expr> {
70     let init = factor.parse_next(i)?;
71 
72     repeat(0.., (one_of(['*', '/']), factor))
73         .fold(
74             move || init.clone(),
75             |acc, (op, val): (char, Expr)| {
76                 if op == '*' {
77                     Expr::Mul(Box::new(acc), Box::new(val))
78                 } else {
79                     Expr::Div(Box::new(acc), Box::new(val))
80                 }
81             },
82         )
83         .parse_next(i)
84 }
85 
factor(i: &mut &str) -> PResult<Expr>86 fn factor(i: &mut &str) -> PResult<Expr> {
87     delimited(
88         multispaces,
89         alt((digits.try_map(FromStr::from_str).map(Expr::Value), parens)),
90         multispaces,
91     )
92     .parse_next(i)
93 }
94 
parens(i: &mut &str) -> PResult<Expr>95 fn parens(i: &mut &str) -> PResult<Expr> {
96     delimited("(", expr, ")")
97         .map(|e| Expr::Paren(Box::new(e)))
98         .parse_next(i)
99 }
100 
101 #[test]
factor_test()102 fn factor_test() {
103     let input = "3";
104     let expected = Ok(("", String::from("Value(3)")));
105     assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
106 
107     let input = " 12";
108     let expected = Ok(("", String::from("Value(12)")));
109     assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
110 
111     let input = "537 ";
112     let expected = Ok(("", String::from("Value(537)")));
113     assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
114 
115     let input = "  24     ";
116     let expected = Ok(("", String::from("Value(24)")));
117     assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
118 }
119 
120 #[test]
term_test()121 fn term_test() {
122     let input = " 12 *2 /  3";
123     let expected = Ok(("", String::from("Div(Mul(Value(12), Value(2)), Value(3))")));
124     assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
125 
126     let input = " 12 *2 /  3";
127     let expected = Ok(("", String::from("Div(Mul(Value(12), Value(2)), Value(3))")));
128     assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
129 
130     let input = " 2* 3  *2 *2 /  3";
131     let expected = Ok((
132         "",
133         String::from("Div(Mul(Mul(Mul(Value(2), Value(3)), Value(2)), Value(2)), Value(3))"),
134     ));
135     assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
136 
137     let input = " 48 /  3/2";
138     let expected = Ok(("", String::from("Div(Div(Value(48), Value(3)), Value(2))")));
139     assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
140 }
141 
142 #[test]
expr_test()143 fn expr_test() {
144     let input = " 1 +  2 ";
145     let expected = Ok(("", String::from("Add(Value(1), Value(2))")));
146     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
147 
148     let input = " 12 + 6 - 4+  3";
149     let expected = Ok((
150         "",
151         String::from("Add(Sub(Add(Value(12), Value(6)), Value(4)), Value(3))"),
152     ));
153     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
154 
155     let input = " 1 + 2*3 + 4";
156     let expected = Ok((
157         "",
158         String::from("Add(Add(Value(1), Mul(Value(2), Value(3))), Value(4))"),
159     ));
160     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
161 }
162 
163 #[test]
parens_test()164 fn parens_test() {
165     let input = " (  2 )";
166     let expected = Ok(("", String::from("Paren(Value(2))")));
167     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
168 
169     let input = " 2* (  3 + 4 ) ";
170     let expected = Ok((
171         "",
172         String::from("Mul(Value(2), Paren(Add(Value(3), Value(4))))"),
173     ));
174     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
175 
176     let input = "  2*2 / ( 5 - 1) + 3";
177     let expected = Ok((
178         "",
179         String::from("Add(Div(Mul(Value(2), Value(2)), Paren(Sub(Value(5), Value(1)))), Value(3))"),
180     ));
181     assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
182 }
183