From 5f1cb084d07b232544c3a220542c7f76c130a7fa Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 5 Jul 2017 14:38:37 +0200 Subject: [PATCH] Clean up parsing code for specified transform values --- .../style/properties/longhand/box.mako.rs | 404 +++++++----------- 1 file changed, 156 insertions(+), 248 deletions(-) diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 3f70a05bf41..0dffc85bc2d 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -959,248 +959,176 @@ ${helpers.predefined_type( } // Allow unitless zero angle for rotate() and skew() to align with gecko - fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool) - -> Result> { + fn parse_internal<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + prefixed: bool, + ) -> Result> { + use style_traits::{Separator, Space}; + if input.try(|input| input.expect_ident_matching("none")).is_ok() { return Ok(SpecifiedValue(Vec::new())) } - let mut result = Vec::new(); - loop { - let name = match input.try(|i| i.expect_function()) { - Ok(name) => name, - Err(_) => break, - }; - let valid_fn = match_ignore_ascii_case! { - &name, - "matrix" => { - input.parse_nested_block(|input| { - // Standard matrix parsing. + Ok(SpecifiedValue(Space::parse(input, |input| { + let function = input.expect_function()?; + input.parse_nested_block(|input| { + let result = match_ignore_ascii_case! { &function, + "matrix" => { + let a = specified::parse_number(context, input)?; + input.expect_comma()?; + let b = specified::parse_number(context, input)?; + input.expect_comma()?; + let c = specified::parse_number(context, input)?; + input.expect_comma()?; + let d = specified::parse_number(context, input)?; + input.expect_comma()?; if !prefixed { - let values = input.parse_comma_separated(|input| { - specified::parse_number(context, input) - })?; - if values.len() != 6 { - return Err(StyleParseError::UnspecifiedError.into()) - } - - result.push(SpecifiedOperation::Matrix { - a: values[0], - b: values[1], - c: values[2], - d: values[3], - e: values[4], - f: values[5], - }); - return Ok(true); - } - - // Non-standard prefixed matrix parsing. - // - // -moz-transform accepts LengthOrPercentageOrNumber in the - // nondiagonal homogeneous components. transform accepts only number. - let mut values = Vec::with_capacity(4); - let mut lengths = Vec::with_capacity(2); - - // Consume first number - values.push(specified::parse_number(context, input)?); - - // Parse other 5 number/LengthOrPercentageOrNumber - for i in 0..5 { + // Standard matrix parsing. + let e = specified::parse_number(context, input)?; input.expect_comma()?; - if i < 3 { - values.push(specified::parse_number(context, input)?); - } else { - // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal - // homogeneous components. transform accepts only number. - lengths.push(LoPoNumber::parse(context, input)?) - } + let f = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::Matrix { a, b, c, d, e, f }) + } else { + // Non-standard prefixed matrix parsing for -moz-transform. + let e = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let f = LoPoNumber::parse(context, input)?; + Ok(SpecifiedOperation::PrefixedMatrix { a, b, c, d, e, f }) } - - result.push(SpecifiedOperation::PrefixedMatrix { - a: values[0], - b: values[1], - c: values[2], - d: values[3], - e: lengths[0].clone(), - f: lengths[1].clone(), - }); - Ok(true) - })? - }, - "matrix3d" => { - input.parse_nested_block(|input| { - // Standard matrix3d parsing. + }, + "matrix3d" => { + let m11 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m12 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m13 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m14 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m21 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m22 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m23 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m24 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m31 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m32 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m33 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m34 = specified::parse_number(context, input)?; + input.expect_comma()?; if !prefixed { - let values = input.parse_comma_separated(|i| specified::parse_number(context, i))?; - if values.len() != 16 { - return Err(StyleParseError::UnspecifiedError.into()) - } - - result.push(SpecifiedOperation::Matrix3D { - m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3], - m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7], - m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11], - m41: values[12], m42: values[13], m43: values[14], m44: values[15] - }); - return Ok(true); - } - - // Non-standard prefixed matrix3d parsing. - // - // -moz-transform accepts LengthOrPercentageOrNumber in the - // nondiagonal homogeneous components. transform accepts only number. - let mut values = Vec::with_capacity(13); - let mut lops = Vec::with_capacity(2); - let mut length_or_number = None; - - // Parse first number - values.push(specified::parse_number(context, input)?); - - // Parse other 15 number/LengthOrPercentageOrNumber - for i in 0..15 { + // Standard matrix3d parsing. + let m41 = specified::parse_number(context, input)?; input.expect_comma()?; - // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal - // homogeneous components. transform accepts only number. - if i < 11 || i > 13 { - values.push(specified::parse_number(context, input)?); - } else if i == 13 { - // m43 - length_or_number = Some(LengthOrNumber::parse(context, input)?); - } else { - // m41 and m42 - lops.push(LoPoNumber::parse(context, input)?); - } + let m42 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m43 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m44 = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::Matrix3D { + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44, + }) + } else { + // Non-standard prefixed matrix parsing for -moz-transform. + let m41 = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let m42 = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let m43 = LengthOrNumber::parse(context, input)?; + input.expect_comma()?; + let m44 = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::PrefixedMatrix3D { + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44, + }) } - - result.push(SpecifiedOperation::PrefixedMatrix3D { - m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3], - m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7], - m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11], - m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(), - m44: values[12] - }); - Ok(true) - })? - }, - "translate" => { - input.parse_nested_block(|input| { + }, + "translate" => { let sx = specified::LengthOrPercentage::parse(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { let sy = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::Translate(sx, Some(sy))); + Ok(SpecifiedOperation::Translate(sx, Some(sy))) } else { - result.push(SpecifiedOperation::Translate(sx, None)); + Ok(SpecifiedOperation::Translate(sx, None)) } - Ok(true) - })? - }, - "translatex" => { - input.parse_nested_block(|input| { + }, + "translatex" => { let tx = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::TranslateX(tx)); - Ok(true) - })? - }, - "translatey" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateX(tx)) + }, + "translatey" => { let ty = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::TranslateY(ty)); - Ok(true) - })? - }, - "translatez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateY(ty)) + }, + "translatez" => { let tz = specified::Length::parse(context, input)?; - result.push(SpecifiedOperation::TranslateZ(tz)); - Ok(true) - })? - }, - "translate3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateZ(tz)) + }, + "translate3d" => { let tx = specified::LengthOrPercentage::parse(context, input)?; input.expect_comma()?; let ty = specified::LengthOrPercentage::parse(context, input)?; input.expect_comma()?; let tz = specified::Length::parse(context, input)?; - result.push(SpecifiedOperation::Translate3D(tx, ty, tz)); - Ok(true) - })? - }, - "scale" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Translate3D(tx, ty, tz)) + }, + "scale" => { let sx = specified::parse_number(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { let sy = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::Scale(sx, Some(sy))); + Ok(SpecifiedOperation::Scale(sx, Some(sy))) } else { - result.push(SpecifiedOperation::Scale(sx, None)); + Ok(SpecifiedOperation::Scale(sx, None)) } - Ok(true) - })? - }, - "scalex" => { - input.parse_nested_block(|input| { + }, + "scalex" => { let sx = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleX(sx)); - Ok(true) - })? - }, - "scaley" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleX(sx)) + }, + "scaley" => { let sy = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleY(sy)); - Ok(true) - })? - }, - "scalez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleY(sy)) + }, + "scalez" => { let sz = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleZ(sz)); - Ok(true) - })? - }, - "scale3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleZ(sz)) + }, + "scale3d" => { let sx = specified::parse_number(context, input)?; input.expect_comma()?; let sy = specified::parse_number(context, input)?; input.expect_comma()?; let sz = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::Scale3D(sx, sy, sz)); - Ok(true) - })? - }, - "rotate" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Scale3D(sx, sy, sz)) + }, + "rotate" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::Rotate(theta)); - Ok(true) - })? - }, - "rotatex" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Rotate(theta)) + }, + "rotatex" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateX(theta)); - Ok(true) - })? - }, - "rotatey" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateX(theta)) + }, + "rotatey" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateY(theta)); - Ok(true) - })? - }, - "rotatez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateY(theta)) + }, + "rotatez" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateZ(theta)); - Ok(true) - })? - }, - "rotate3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateZ(theta)) + }, + "rotate3d" => { let ax = specified::parse_number(context, input)?; input.expect_comma()?; let ay = specified::parse_number(context, input)?; @@ -1208,56 +1136,36 @@ ${helpers.predefined_type( let az = specified::parse_number(context, input)?; input.expect_comma()?; let theta = specified::Angle::parse_with_unitless(context, input)?; - // TODO(gw): Check the axis can be normalized!! - result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta)); - Ok(true) - })? - }, - "skew" => { - input.parse_nested_block(|input| { - let theta_x = specified::Angle::parse_with_unitless(context, input)?; + // TODO(gw): Check that the axis can be normalized. + Ok(SpecifiedOperation::Rotate3D(ax, ay, az, theta)) + }, + "skew" => { + let ax = specified::Angle::parse_with_unitless(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { - let theta_y = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::Skew(theta_x, Some(theta_y))); + let ay = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::Skew(ax, Some(ay))) } else { - result.push(SpecifiedOperation::Skew(theta_x, None)); + Ok(SpecifiedOperation::Skew(ax, None)) } - Ok(true) - })? - }, - "skewx" => { - input.parse_nested_block(|input| { - let theta_x = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::SkewX(theta_x)); - Ok(true) - })? - }, - "skewy" => { - input.parse_nested_block(|input| { - let theta_y = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::SkewY(theta_y)); - Ok(true) - })? - }, - "perspective" => { - input.parse_nested_block(|input| { + }, + "skewx" => { + let theta = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::SkewX(theta)) + }, + "skewy" => { + let theta = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::SkewY(theta)) + }, + "perspective" => { let d = specified::Length::parse_non_negative(context, input)?; - result.push(SpecifiedOperation::Perspective(d)); - Ok(true) - })? - }, - _ => false - }; - if !valid_fn { - return Err(StyleParseError::UnexpectedFunction(name).into()); - } - } - - if !result.is_empty() { - Ok(SpecifiedValue(result)) - } else { - Err(StyleParseError::UnspecifiedError.into()) - } + Ok(SpecifiedOperation::Perspective(d)) + }, + _ => Err(()), + }; + result + .map_err(|()| StyleParseError::UnexpectedFunction(function).into()) + }) + })?)) } /// Parses `transform` property.