/
calculator.rs
79 lines (63 loc) · 1.85 KB
/
calculator.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use std::str::FromStr;
use Symbol;
rusty_peg! {
parser Calculator<'input> {
EXPR: u32 =
ADD_SUB_EXPR;
PAREN_EXPR: u32 =
("(" <e:EXPR> ")") => e;
ADD_SUB_EXPR: u32 =
fold(<lhs:MUL_DIV_EXPR>,
("+" <rhs:MUL_DIV_EXPR>) => { lhs + rhs },
("-" <rhs:MUL_DIV_EXPR>) => { lhs - rhs });
MUL_DIV_EXPR: u32 =
fold(<lhs:ATOM_EXPR>,
("*" <rhs:ATOM_EXPR>) => { lhs * rhs },
("/" <rhs:ATOM_EXPR>) => { lhs / rhs });
ATOM_EXPR: u32 =
(NUMBER / PAREN_EXPR);
NUMBER: u32 =
(<s:NUMBER_STRING>) => u32::from_str(s).unwrap();
NUMBER_STRING: &'input str =
regex(r"[0-9]+");
}
}
#[test]
fn parse_expr() {
let mut classy = Calculator::new(());
// If we don't get the order of ops right, we'll get the wrong
// result here. In pairticular:
//
// ((((3+5)*11)/3)+1) == 33
// (3 + 5*(11/3) + 1) == 19
let result =
EXPR.parse_complete(&mut classy,
"3 + 5*11/3 + 1").unwrap();
assert_eq!(result, 22);
}
#[test]
fn parse_parens() {
let mut classy = Calculator::new(());
let result =
EXPR.parse_complete(&mut classy,
"3 + 5*(11/3) + 1").unwrap();
assert_eq!(result, 19);
}
#[test]
fn parse_number() {
let mut classy = Calculator::new(());
let result = EXPR.parse_complete(&mut classy, "22").unwrap();
assert_eq!(result, 22);
}
#[test]
fn parse_plus() {
let mut classy = Calculator::new(());
let result = EXPR.parse_complete(&mut classy, "19 + 3").unwrap();
assert_eq!(result, 22);
}
#[test]
fn parse_mul() {
let mut classy = Calculator::new(());
let result = EXPR.parse_complete(&mut classy, "11 * 2").unwrap();
assert_eq!(result, 22);
}