本次实验是使用Rust语言实现一个简单的计算器,使用的是pest库做语法解析。
添加项目依赖:1
2
3[dependencies]
pest = { version = "2.8.4" }
pest_derive = { version = "2.8.4" }
创建语法文件src/calculator.pest:1
2
3
4
5
6
7
8
9
10
11
12WHITESPACE = _{ " " | "\t" | "\n" }
number = @{ ('0'..'9')+ }
add = @{ "+" }
sub = @{ "-" }
mul = @{ "*" }
div = @{ "/" }
expr = { sum }
sum = { product ~ ((add | sub) ~ product)* }
product = { factor ~ ((mul | div) ~ factor)* }
factor = { number | "(" ~ expr ~ ")" }
创建计算器文件src/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
80
81use pest::Parser;
use pest_derive::Parser;
struct CalculatorParser;
enum BinaryOp {
Add,
Sub,
Mul,
Div,
}
fn eval_expr(pair: pest::iterators::Pair<Rule>) -> i32 {
match pair.as_rule() {
Rule::expr => {
eval_sum(pair.into_inner().next().unwrap())
}
_ => panic!("Expected expr, got {:?}", pair.as_rule()),
}
}
fn eval_sum(pair: pest::iterators::Pair<Rule>) -> i32 {
let mut pairs = pair.into_inner();
let mut result = eval_product(pairs.next().unwrap());
while let Some(op_pair) = pairs.next() {
let op = match op_pair.as_rule() {
Rule::add => BinaryOp::Add,
Rule::sub => BinaryOp::Sub,
_ => panic!("Expected add or sub, got {:?}", op_pair.as_rule()),
};
let right = eval_product(pairs.next().unwrap());
result = match op {
BinaryOp::Add => result + right,
BinaryOp::Sub => result - right,
_ => panic!("Unexpected operator in sum"),
};
}
result
}
fn eval_product(pair: pest::iterators::Pair<Rule>) -> i32 {
let mut pairs = pair.into_inner();
let mut result = eval_factor(pairs.next().unwrap());
while let Some(op_pair) = pairs.next() {
let op = match op_pair.as_rule() {
Rule::mul => BinaryOp::Mul,
Rule::div => BinaryOp::Div,
_ => panic!("Expected mul or div, got {:?}", op_pair.as_rule()),
};
let right = eval_factor(pairs.next().unwrap());
result = match op {
BinaryOp::Mul => result * right,
BinaryOp::Div => result / right,
_ => panic!("Unexpected operator in product"),
};
}
result
}
fn eval_factor(pair: pest::iterators::Pair<Rule>) -> i32 {
match pair.as_rule() {
Rule::number => pair.as_str().parse::<i32>().unwrap(),
Rule::factor => {
let inner = pair.into_inner().next().unwrap();
eval_factor(inner)
}
Rule::expr => eval_expr(pair),
_ => panic!("Expected number, factor, or expr, got {:?}", pair.as_rule()),
}
}
创建测试代码:1
2
3
4
5
6
7
8
9
10
11
12
13
fn test_calculator() {
let test_cases = vec!["1+2*3-4", "10/2+3", "(1+2)*3", "2*(3+4)", "100-50/5"];
for input in test_cases {
let pairs = CalculatorParser::parse(Rule::expr, input).unwrap_or_else(|e| panic!("{}", e));
for pair in pairs {
let result = eval_expr(pair);
println!("{}={}", input, result);
}
}
}
测试一下,结果如下:1
2
3
4
51+2*3-4=3
10/2+3=8
(1+2)*3=9
2*(3+4)=14
100-50/5=90
- 本文作者: killf
- 本文链接: https://www.killf.info/编程语言/Rust/使用Rust写一个简单的计算器/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!