1 #[macro_use]
2 extern crate nom;
3
4 use std::fmt;
5 use std::fmt::{Display, Debug, Formatter};
6
7 use std::str;
8 use std::str::FromStr;
9
10 use nom::{IResult, digit, multispace};
11
12 pub enum Expr {
13 Value(i64),
14 Add(Box<Expr>, Box<Expr>),
15 Sub(Box<Expr>, Box<Expr>),
16 Mul(Box<Expr>, Box<Expr>),
17 Div(Box<Expr>, Box<Expr>),
18 Paren(Box<Expr>),
19 }
20
21 pub enum Oper {
22 Add,
23 Sub,
24 Mul,
25 Div,
26 }
27
28 impl Display for Expr {
fmt(&self, format: &mut Formatter) -> fmt::Result29 fn fmt(&self, format: &mut Formatter) -> fmt::Result {
30 use self::Expr::*;
31 match *self {
32 Value(val) => write!(format, "{}", val),
33 Add(ref left, ref right) => write!(format, "{} + {}", left, right),
34 Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
35 Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
36 Div(ref left, ref right) => write!(format, "{} / {}", left, right),
37 Paren(ref expr) => write!(format, "({})", expr),
38 }
39 }
40 }
41
42 impl Debug for Expr {
fmt(&self, format: &mut Formatter) -> fmt::Result43 fn fmt(&self, format: &mut Formatter) -> fmt::Result {
44 use self::Expr::*;
45 match *self {
46 Value(val) => write!(format, "{}", val),
47 Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right),
48 Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right),
49 Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right),
50 Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right),
51 Paren(ref expr) => write!(format, "[{:?}]", expr),
52 }
53 }
54 }
55
56 named!(parens< Expr >, delimited!(
57 delimited!(opt!(multispace), tag!("("), opt!(multispace)),
58 map!(map!(expr, Box::new), Expr::Paren),
59 delimited!(opt!(multispace), tag!(")"), opt!(multispace))
60 )
61 );
62
63 named!(factor< Expr >, alt_complete!(
64 map!(
65 map_res!(
66 map_res!(
67 delimited!(opt!(multispace), digit, opt!(multispace)),
68 str::from_utf8
69 ),
70 FromStr::from_str
71 ),
72 Expr::Value)
73 | parens
74 )
75 );
76
fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr77 fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
78 remainder.into_iter().fold(initial, |acc, pair| {
79 let (oper, expr) = pair;
80 match oper {
81 Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)),
82 Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)),
83 Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)),
84 Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)),
85 }
86 })
87 }
88
89 named!(term< Expr >, chain!(
90 initial: factor ~
91 remainder: many0!(
92 alt!(
93 chain!(tag!("*") ~ mul: factor, || { (Oper::Mul, mul) }) |
94 chain!(tag!("/") ~ div: factor, || { (Oper::Div, div) })
95 )
96 ),
97 || fold_exprs(initial, remainder))
98 );
99
100 named!(expr< Expr >, chain!(
101 initial: term ~
102 remainder: many0!(
103 alt!(
104 chain!(tag!("+") ~ add: term, || { (Oper::Add, add) }) |
105 chain!(tag!("-") ~ sub: term, || { (Oper::Sub, sub) })
106 )
107 ),
108 || fold_exprs(initial, remainder))
109 );
110
111 #[test]
factor_test()112 fn factor_test() {
113 assert_eq!(factor(&b" 3 "[..]).map(|x| format!("{:?}", x)),
114 IResult::Done(&b""[..], String::from("3")));
115 }
116
117 #[test]
term_test()118 fn term_test() {
119 assert_eq!(term(&b" 3 * 5 "[..]).map(|x| format!("{:?}", x)),
120 IResult::Done(&b""[..], String::from("(3 * 5)")));
121 }
122
123 #[test]
expr_test()124 fn expr_test() {
125 assert_eq!(expr(&b" 1 + 2 * 3 "[..]).map(|x| format!("{:?}", x)),
126 IResult::Done(&b""[..], String::from("(1 + (2 * 3))")));
127 assert_eq!(expr(&b" 1 + 2 * 3 / 4 - 5 "[..]).map(|x| format!("{:?}", x)),
128 IResult::Done(&b""[..], String::from("((1 + ((2 * 3) / 4)) - 5)")));
129 assert_eq!(expr(&b" 72 / 2 / 3 "[..]).map(|x| format!("{:?}", x)),
130 IResult::Done(&b""[..], String::from("((72 / 2) / 3)")));
131 }
132
133 #[test]
parens_test()134 fn parens_test() {
135 assert_eq!(expr(&b" ( 1 + 2 ) * 3 "[..]).map(|x| format!("{:?}", x)),
136 IResult::Done(&b""[..], String::from("([(1 + 2)] * 3)")));
137 }
138