12 个版本 (6 个稳定版)
3.0.0 | 2024年3月31日 |
---|---|
2.0.0 | 2019年6月17日 |
1.2.1 | 2019年6月16日 |
1.2.0 | 2019年1月1日 |
0.1.5 | 2018年8月28日 |
#43 in 数学
673 每月下载量
用于 typenum-consts
37KB
861 行
RSC,Rust 代码计算器
更新:crate 更新到 3.0,请参阅 变更日志。
RSC 是一个手写的科学计算器,用于解释字符串中的方程。 RSC 设计得很好,可以很好地完成一项工作,使任何人都可以通过添加更多功能来扩展它。
RSC 旨在超越 Wirth 定律。 因此,RSC 将不会接收很多新增功能。 它仍会接收与效率相关的更新。
库
use rsc::{tokenize, parse, Interpreter};
// Maybe you write a wrapper function
fn evaluate(input: &str, interpreter: &mut Interpreter<f64>) -> Result<f64, ()> {
// You have to call each function in the pipeline, but this gives you the most
// control over error handling and performance.
match tokenize(input) { // Step 1: splits input into symbols, words, and numbers
Ok(tokens) => match parse(&tokens) { // Step 2: builds an Expr using tokens
Ok(expr) => match interpreter.eval(&expr) { // Step 3: interprets the Expr
Ok(result) => println!("{}", result),
Err(interpret_error) => eprintln!("{:?}", interpret_error),
},
Err(parse_error) => eprintln!("{:?}", parse_error),
},
Err(tokenize_error) => eprintln!("{:?}", tokenize_error),
}
}
fn main() {
// Constructs an f64 interpreter with included variables
let mut interpreter = Interpreter::default();
evaluate("5^2", &mut interpreter); // prints "25"
evaluate("x = 3", &mut interpreter); // prints "3"
evaluate("x(3) + 1", &mut interpreter); // prints "10"
}
变量存储在 解释器
中
use rsc::{tokenize, parse, Interpreter, Variant, InterpretError};
// assume you still had your evaluate function above
fn main() {
// Create a completely empty interpreter for f64 calculations
let mut i = Interpreter::<f64>::new();
// Create some variables
i.set_var(String::from("pi"), Variant::Num(std::f64::consts::PI));
i.set_var(String::from("double"), Variant::Function(|name, args| {
if args.len() < 1 {
Err(InterpretError::TooFewArgs(name, 1))
} else if args.len() > 1 {
Err(InterpretError::TooManyArgs(name, 1))
} else {
Ok(args[0] * 2) // get the only argument and double it
}
}));
evaluate("double(pi)", &mut i); // prints "6.283185307179586"
}
由于可能存在冗余检查函数是否接收了正确的参数数量(如果您愿意这么做的话),我创建了一个名为 ensure_arg_count
的辅助函数。上面的函数重新定义了
use rsc::ensure_arg_count;
i.set_var(String::from("double"), Variant::Function(|name, args| {
// return Err if args are not within the min and max count
ensure_arg_count(1, 1, args.len(), name)?;
Ok(args[0] * 2)
}));
可执行文件
您可能需要首先将 RSC 构建为可执行文件
cargo build --release --features=executable
需要 executable
功能来告诉 crate 仅将某些依赖项用于可执行版本,用于终端中的颜色和参数解析。
用法
RSC interactive expression interpreter.
Try "help" for commands and examples.
>sqrt(15+3)
:4.242640687119285
>:square root
>sqrt(15, 3)
Function "sqrt" received more than the maximum 1 argument.
> |-5|
:5
>abs(-5)
:5
>sqrt(4)(2)
^ UnexpectedToken(Token { value: Symbol(LP), span: 7..8 })
>(sqrt(4))(2)
:4
>x = 1.24
:1.24
>x(4)
:4.96
>vars
factorial(..)
sqrt(..)
abs(..)
x = 1.24
e = 2.718281828459045
pi = 3.141592653589793
tau = 6.283185307179586
可以直接将表达式传递给 rsc
$ rsc "12/sqrt(128)"
1.0606601717798212
您可以传递各种标志。尝试
rsc -tev
$ rsc -h
rsc 3.0.0
A scientific calculator for the terminal.
USAGE:
rsc [FLAGS] [expr]
FLAGS:
-e, --expr Prints the expression tree
-h, --help Prints help information
--no-color Prevents colored text
-t, --tokens Prints the tokens
-v, --vars Prints variable map
-V, --version Prints version information
ARGS:
<expr>
关于性能的说明
- 词法分析器是迭代的,很容易进行优化。
- 解析器是一个 LL(2) 递归下降解析器,这是我想到的最简单、最蛮力的解析解决方案。它很容易理解和维护,但不是最有效的。解析器目前是三个阶段中最慢的。
解释器::评估
函数使用递归以保持简单。移除递归可以防止不必要的帧指针的推送和弹出,并启用更好的缓存,从而提供更好的性能。- 欢迎提交性能改进的 PR,这可能是很容易的!
稳定性
RSC 不会对其语法进行任何重大更改。它将保持一致性很长时间。创建不同版本的 RSC 是分叉者的责任。它也将永远保持相同的开源权限。
许可证
RSC 是 MIT 许可证。RSC 将始终免费修改和使用,无需署名。
依赖项
~0–10MB
~49K SLoC