Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[not ready for review yet] Allow calc expressions when parsing numbers #7308

Closed
wants to merge 17 commits into from
Closed
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Simplify the calc AST simplification code

  • Loading branch information
dzbarsky committed Aug 21, 2015
commit c3fca863c990da525e35182115304039f3116a0c
@@ -462,31 +462,58 @@ pub mod specified {
}
}

fn simplify_product(node: CalcProductNode) -> Result<CalcAstNode, ()> {
fn simplify_value_numerically(node: &CalcValueNode) -> Option<CSSFloat> {
match node {
&CalcValueNode::Number(number) => Some(number),
&CalcValueNode::Sum(box ref sum) => Calc::simplify_sum_numerically(sum),
_ => None
}
}

fn simplify_sum_numerically(node: &CalcSumNode) -> Option<CSSFloat> {
let node = node.clone();
let mut sum = 0.;
for product in node.products {
match Calc::simplify_product_numerically(product) {
Some(number) => sum += number,
_ => return None
}
}
Some(sum)
}

fn simplify_product_numerically(node: CalcProductNode) -> Option<CSSFloat> {
let mut product = 1.;
for value in node.values {
match Calc::simplify_value_numerically(&value) {
Some(number) => product *= number,
_ => return None
}
}
Some(product)
}

fn simplify_products(node: CalcProductNode) -> Result<CalcAstNode, ()> {
let mut multiplier = 1.;
let mut node_with_unit: Option<CalcAstNode> = None;
let mut node_hack: CalcAstNode;
let mut node_with_unit = None;
for node in node.values {
node_hack = try!(Calc::simplify_value(node));
if let CalcAstNode::Value(CalcValueNode::Number(n)) = node_hack {
multiplier *= n;
} else if node_with_unit.is_none() {
node_with_unit = Some(node_hack);
} else {
return Err(());
match Calc::simplify_value_numerically(&node) {
Some(number) => multiplier *= number,
_ if node_with_unit.is_none() => node_with_unit = Some(node),
_ => return Err(()),
}
}

match node_with_unit {
None => Ok(CalcAstNode::Value(CalcValueNode::Number(multiplier))),
Some(CalcAstNode::Add(sum)) =>
Some(CalcValueNode::Sum(box sum)) =>
Ok(CalcAstNode::Add(CalcSumNode {
products: sum.products
.iter()
.map(|p| Calc::multiply_product(p, multiplier))
.collect()
})),
Some(CalcAstNode::Value(ref value)) =>
Some(ref value) =>
Ok(CalcAstNode::Value(Calc::multiply_value(value, multiplier))),
}
}
@@ -509,10 +536,12 @@ pub mod specified {
}
}

fn simplify_sum(node: CalcSumNode) -> Result<CalcAstNode, ()> {
pub fn parse(input: &mut Parser) -> Result<Calc, ()> {
let ast = try!(Calc::parse_sum(input));

let mut simplified = Vec::new();
for node in node.products {
let node = try!(Calc::simplify_product(node));
for node in ast.products {
let node = try!(Calc::simplify_products(node));
match node {
CalcAstNode::Value(value) => simplified.push(value),
CalcAstNode::Add(sum) => {
@@ -566,119 +595,6 @@ pub mod specified {
}
}

fn viewport_node(length: ViewportPercentageLength) -> CalcValueNode {
CalcValueNode::Length(Length::ViewportPercentage(length))
}
fn font_node(length: FontRelativeLength) -> CalcValueNode {
CalcValueNode::Length(Length::FontRelative(length))
}

let mut new_values = Vec::new();
if let Some(absolute) = absolute {
new_values.push(CalcValueNode::Length(Length::Absolute(Au(absolute))));
}
if let Some(vw) = vw {
new_values.push(viewport_node(ViewportPercentageLength::Vw(vw)));
}
if let Some(vh) = vh {
new_values.push(viewport_node(ViewportPercentageLength::Vh(vh)));
}
if let Some(vmin) = vmin {
new_values.push(viewport_node(ViewportPercentageLength::Vmin(vmin)));
}
if let Some(vmax) = vmax {
new_values.push(viewport_node(ViewportPercentageLength::Vmax(vmax)));
}
if let Some(em) = em {
new_values.push(font_node(FontRelativeLength::Em(em)));
}
if let Some(ex) = ex {
new_values.push(font_node(FontRelativeLength::Ex(ex)));
}
if let Some(rem) = rem {
new_values.push(font_node(FontRelativeLength::Rem(rem)));
}
if let Some(number) = number {
new_values.push(CalcValueNode::Number(number));
}

assert!(new_values.len() > 0);
if new_values.len() == 1 {
Ok(CalcAstNode::Value(new_values[0].clone()))
} else {
let new_products = new_values.iter()
.map(|v| CalcProductNode { values: vec!(v.clone()) })
.collect();
Ok(CalcAstNode::Add(CalcSumNode {products: new_products} ))
}
}

fn simplify_value(node: CalcValueNode) -> Result<CalcAstNode, ()> {
match node {
CalcValueNode::Sum(box sum) => Calc::simplify_sum(sum),
node => Ok(CalcAstNode::Value(node))
}
}

pub fn parse(input: &mut Parser) -> Result<Calc, ()> {

let ast = try!(Calc::parse_sum(input));
let ast = try!(Calc::simplify_sum(ast));

println!("Simlified ast {:?} ", ast);

let mut absolute = None;
let mut vw = None;
let mut vh = None;
let mut vmax = None;
let mut vmin = None;
let mut em = None;
let mut ex = None;
let mut rem = None;
let mut percentage = None;

let values = match ast {
CalcAstNode::Add(sum) => {
let mut values = Vec::new();
for product in sum.products {
assert!(product.values.len() == 1);
values.push(product.values[0].clone());
}
values
},
CalcAstNode::Value(value) => vec!(value)
};

for value in values {
match value {
CalcValueNode::Percentage(p) =>
percentage = Some(p),
CalcValueNode::Length(Length::Absolute(Au(au))) =>
absolute = Some(au),
CalcValueNode::Length(Length::ViewportPercentage(v)) =>
match v {
ViewportPercentageLength::Vw(val) =>
vw = Some(val),
ViewportPercentageLength::Vh(val) =>
vh = Some(val),
ViewportPercentageLength::Vmin(val) =>
vmin = Some(val),
ViewportPercentageLength::Vmax(val) =>
vmax = Some(val),
},
CalcValueNode::Length(Length::FontRelative(f)) =>
match f {
FontRelativeLength::Em(val) =>
em = Some(val),
FontRelativeLength::Ex(val) =>
ex = Some(val),
FontRelativeLength::Rem(val) =>
rem = Some(val),
},
_ => return Err(())
}
}

Ok(Calc {
absolute: absolute.map(Au),
vw: vw.map(ViewportPercentageLength::Vw),
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.