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",
|
||||||
"iced_aw",
|
"iced_aw",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
"peg",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
@ -1684,6 +1685,33 @@ dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"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]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,6 @@ iced_aw = { version = "0.7.0", default-features = false, features = [
|
||||||
"card",
|
"card",
|
||||||
] }
|
] }
|
||||||
itertools = "0.11.0"
|
itertools = "0.11.0"
|
||||||
|
peg = "0.8.2"
|
||||||
serde = { version = "1.0.192", features = ["derive"] }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
serde_json = "1.0.108"
|
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>;
|
type Element<'a> = iced::Element<'a, Message>;
|
||||||
|
|
||||||
|
mod calc;
|
||||||
|
|
||||||
const TEXT_H1: u16 = 30;
|
const TEXT_H1: u16 = 30;
|
||||||
const TEXT_H2: u16 = 25;
|
const TEXT_H2: u16 = 25;
|
||||||
const TEXT_EMPH1: u16 = 17;
|
const TEXT_EMPH1: u16 = 17;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue