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