From 78aca9356638db1f162d8ab51849d689cfc2cc07 Mon Sep 17 00:00:00 2001 From: RobertasJ Date: Sun, 20 Oct 2024 10:19:01 +0200 Subject: [PATCH] added parenthesis and term parsing + eval --- crates/torin/src/values/size.rs | 48 +++++++++++++++++++++++---------- crates/torin/tests/size.rs | 41 +++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/crates/torin/src/values/size.rs b/crates/torin/src/values/size.rs index 2c1c347b2..8e25d571f 100644 --- a/crates/torin/src/values/size.rs +++ b/crates/torin/src/values/size.rs @@ -1,15 +1,8 @@ -use std::{ - ops::Deref, - slice::Iter, -}; +use std::{ops::Deref, slice::Iter}; pub use euclid::Rect; -use crate::{ - geometry::Length, - measure::Phase, - scaled::Scaled, -}; +use crate::{geometry::Length, measure::Phase, scaled::Scaled}; #[derive(PartialEq, Clone, Debug)] pub enum Size { @@ -171,6 +164,8 @@ pub enum DynamicCalculation { Mul, Div, Add, + OpenParenthesis, + ClosedParenthesis, Percentage(f32), RootPercentage(f32), Pixels(f32), @@ -191,6 +186,8 @@ impl std::fmt::Display for DynamicCalculation { DynamicCalculation::Mul => f.write_str("*"), DynamicCalculation::Div => f.write_str("/"), DynamicCalculation::Add => f.write_str("+"), + DynamicCalculation::OpenParenthesis => f.write_str("("), + DynamicCalculation::ClosedParenthesis => f.write_str(")"), DynamicCalculation::Percentage(p) => f.write_fmt(format_args!("{p}%")), DynamicCalculation::RootPercentage(p) => f.write_fmt(format_args!("{p}v")), DynamicCalculation::Pixels(s) => f.write_fmt(format_args!("{s}")), @@ -235,7 +232,7 @@ impl<'a> DynamicCalculationEvaluator<'a> { fn parse_expression(&mut self, min_precedence: usize) -> Option { // Parse left-hand side value self.current = self.calcs.next(); - let mut lhs = self.parse_value()?; + let mut lhs = self.parse_term()?; while let Some(operator_precedence) = self.operator_precedence() { // Return if minimal precedence is reached. @@ -273,19 +270,41 @@ impl<'a> DynamicCalculationEvaluator<'a> { /// percentage = number, "%" ; /// pixels = number ; /// ``` - fn parse_value(&mut self) -> Option { + fn parse_term(&mut self) -> Option { + let mut lhs = None; + // set to true so that the first value is multiplied and counts as normal syntax + let mut last_is_seperator = true; + + while let Some((rhs, seperator)) = self.parse_value() { + if last_is_seperator || seperator { + lhs = Some(lhs.unwrap_or(1.0) * rhs); + } else { + return None; + } + last_is_seperator = seperator; + } + + lhs + } + + fn parse_value(&mut self) -> Option<(f32, bool)> { match self.current? { DynamicCalculation::Percentage(value) => { self.current = self.calcs.next(); - Some((self.parent_value / 100.0 * value).round()) + Some(((self.parent_value / 100.0 * value).round(), false)) } DynamicCalculation::RootPercentage(value) => { self.current = self.calcs.next(); - Some((self.root_value / 100.0 * value).round()) + Some(((self.root_value / 100.0 * value).round(), false)) } DynamicCalculation::Pixels(value) => { self.current = self.calcs.next(); - Some(*value) + Some((*value, false)) + } + DynamicCalculation::OpenParenthesis => { + let val = self.parse_expression(0); + self.current = self.calcs.next(); + Some((val?, true)) } _ => None, } @@ -296,6 +315,7 @@ impl<'a> DynamicCalculationEvaluator<'a> { match self.current? { DynamicCalculation::Add | DynamicCalculation::Sub => Some(1), DynamicCalculation::Mul | DynamicCalculation::Div => Some(2), + DynamicCalculation::OpenParenthesis => Some(0), _ => None, } } diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index f7e89a96a..e48054101 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -1,8 +1,5 @@ use euclid::Length; -use torin::{ - prelude::*, - test_utils::*, -}; +use torin::{prelude::*, test_utils::*}; #[test] pub fn unsized_parent_with_child_with_margin() { @@ -892,4 +889,40 @@ pub fn test_calc() { ), Some((PARENT_VALUE * 0.5) - (PARENT_VALUE * 0.20)) ); + + assert_eq!( + run_calculations( + &vec![ + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + ], + PARENT_VALUE, + PARENT_VALUE + ), + Some(10.0) + ); + + assert_eq!( + run_calculations( + &vec![ + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(20.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + ], + PARENT_VALUE, + PARENT_VALUE + ), + Some((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) + ); }