Add a calculator parser
This commit is contained in:
parent
94c5ddfae5
commit
af6e1ef334
4 changed files with 113 additions and 0 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
|
@ -711,6 +711,7 @@ dependencies = [
|
|||
"iced",
|
||||
"iced_aw",
|
||||
"itertools",
|
||||
"peg",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
|
@ -1684,6 +1685,33 @@ dependencies = [
|
|||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peg"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61"
|
||||
dependencies = [
|
||||
"peg-macros",
|
||||
"peg-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peg-macros"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90"
|
||||
dependencies = [
|
||||
"peg-runtime",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peg-runtime"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
|
|
|
|||
|
|
@ -13,5 +13,6 @@ iced_aw = { version = "0.7.0", default-features = false, features = [
|
|||
"card",
|
||||
] }
|
||||
itertools = "0.11.0"
|
||||
peg = "0.8.2"
|
||||
serde = { version = "1.0.192", features = ["derive"] }
|
||||
serde_json = "1.0.108"
|
||||
|
|
|
|||
82
src/calc.rs
Normal file
82
src/calc.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
peg::parser! {
|
||||
pub grammar calc_parser() for str {
|
||||
rule number() -> f64 = n:$(['0'..='9']+ ("." ['0'..='9']*)?) {? n.parse().or(Err("f64"))}
|
||||
|
||||
rule _ = quiet!{[' ' | '\n' | '\t']*}
|
||||
|
||||
pub rule calc() -> f64 =
|
||||
_ v:precedence!{
|
||||
"-" _ x:(@) { std::ops::Neg::neg(x) }
|
||||
"+" _ x:(@) { x }
|
||||
--
|
||||
x:(@) _ "+" _ y:@ { x + y }
|
||||
x:(@) _ "-" _ y:@ { x - y }
|
||||
--
|
||||
x:(@) _ "*" _ y:@ { x * y }
|
||||
x:(@) _ "/" _ y:@ { x / y }
|
||||
--
|
||||
n:number() { n }
|
||||
"(" _ e:calc() _ ")" { e }
|
||||
} _ { v }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::calc_parser;
|
||||
|
||||
#[test]
|
||||
fn prefix_plus() {
|
||||
assert_eq!(calc_parser::calc("+1"), Ok(1.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefix_minus() {
|
||||
assert_eq!(calc_parser::calc("-1"), Ok(-1.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum() {
|
||||
assert_eq!(calc_parser::calc("1+1"), Ok(2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prod() {
|
||||
assert_eq!(calc_parser::calc("2*2"), Ok(4.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn div() {
|
||||
assert_eq!(calc_parser::calc("6/3"), Ok(2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub() {
|
||||
assert_eq!(calc_parser::calc("6-3"), Ok(3.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn literal() {
|
||||
assert_eq!(calc_parser::calc("2"), Ok(2.));
|
||||
assert_eq!(calc_parser::calc("2."), Ok(2.));
|
||||
assert_eq!(calc_parser::calc("2.0"), Ok(2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn whitespace_infix() {
|
||||
assert_eq!(
|
||||
calc_parser::calc("- (1+ ( 1 * 3) / 6-1)"),
|
||||
Ok(-0.5)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn whitespace_prefix() {
|
||||
assert_eq!(calc_parser::calc(" 1+1"), Ok(2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn whitespace_suffix() {
|
||||
assert_eq!(calc_parser::calc("1+1 "), Ok(2.));
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
type Element<'a> = iced::Element<'a, Message>;
|
||||
|
||||
mod calc;
|
||||
|
||||
const TEXT_H1: u16 = 30;
|
||||
const TEXT_H2: u16 = 25;
|
||||
const TEXT_EMPH1: u16 = 17;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue