Clean up parsing code for specified transform values

This commit is contained in:
Anthony Ramine 2017-07-05 14:38:37 +02:00
parent ee95bda3bf
commit 5f1cb084d0

View file

@ -959,248 +959,176 @@ ${helpers.predefined_type(
} }
// Allow unitless zero angle for rotate() and skew() to align with gecko // 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) fn parse_internal<'i, 't>(
-> Result<SpecifiedValue,ParseError<'i>> { context: &ParserContext,
input: &mut Parser<'i, 't>,
prefixed: bool,
) -> Result<SpecifiedValue,ParseError<'i>> {
use style_traits::{Separator, Space};
if input.try(|input| input.expect_ident_matching("none")).is_ok() { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new())) return Ok(SpecifiedValue(Vec::new()))
} }
let mut result = Vec::new(); Ok(SpecifiedValue(Space::parse(input, |input| {
loop { let function = input.expect_function()?;
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| { input.parse_nested_block(|input| {
// Standard matrix parsing. let result = match_ignore_ascii_case! { &function,
if !prefixed { "matrix" => {
let values = input.parse_comma_separated(|input| { let a = specified::parse_number(context, 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 {
input.expect_comma()?; input.expect_comma()?;
if i < 3 { let b = specified::parse_number(context, input)?;
values.push(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 {
// Standard matrix parsing.
let e = specified::parse_number(context, input)?;
input.expect_comma()?;
let f = specified::parse_number(context, input)?;
Ok(SpecifiedOperation::Matrix { a, b, c, d, e, f })
} else { } else {
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal // Non-standard prefixed matrix parsing for -moz-transform.
// homogeneous components. transform accepts only number. let e = LoPoNumber::parse(context, input)?;
lengths.push(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" => { "matrix3d" => {
input.parse_nested_block(|input| { let m11 = specified::parse_number(context, input)?;
// Standard matrix3d parsing.
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 {
input.expect_comma()?; input.expect_comma()?;
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal let m12 = specified::parse_number(context, input)?;
// homogeneous components. transform accepts only number. input.expect_comma()?;
if i < 11 || i > 13 { let m13 = specified::parse_number(context, input)?;
values.push(specified::parse_number(context, input)?); input.expect_comma()?;
} else if i == 13 { let m14 = specified::parse_number(context, input)?;
// m43 input.expect_comma()?;
length_or_number = Some(LengthOrNumber::parse(context, input)?); 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 {
// Standard matrix3d parsing.
let m41 = specified::parse_number(context, input)?;
input.expect_comma()?;
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 { } else {
// m41 and m42 // Non-standard prefixed matrix parsing for -moz-transform.
lops.push(LoPoNumber::parse(context, input)?); 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" => { "translate" => {
input.parse_nested_block(|input| {
let sx = specified::LengthOrPercentage::parse(context, input)?; let sx = specified::LengthOrPercentage::parse(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() { if input.try(|input| input.expect_comma()).is_ok() {
let sy = specified::LengthOrPercentage::parse(context, input)?; let sy = specified::LengthOrPercentage::parse(context, input)?;
result.push(SpecifiedOperation::Translate(sx, Some(sy))); Ok(SpecifiedOperation::Translate(sx, Some(sy)))
} else { } else {
result.push(SpecifiedOperation::Translate(sx, None)); Ok(SpecifiedOperation::Translate(sx, None))
} }
Ok(true)
})?
}, },
"translatex" => { "translatex" => {
input.parse_nested_block(|input| {
let tx = specified::LengthOrPercentage::parse(context, input)?; let tx = specified::LengthOrPercentage::parse(context, input)?;
result.push(SpecifiedOperation::TranslateX(tx)); Ok(SpecifiedOperation::TranslateX(tx))
Ok(true)
})?
}, },
"translatey" => { "translatey" => {
input.parse_nested_block(|input| {
let ty = specified::LengthOrPercentage::parse(context, input)?; let ty = specified::LengthOrPercentage::parse(context, input)?;
result.push(SpecifiedOperation::TranslateY(ty)); Ok(SpecifiedOperation::TranslateY(ty))
Ok(true)
})?
}, },
"translatez" => { "translatez" => {
input.parse_nested_block(|input| {
let tz = specified::Length::parse(context, input)?; let tz = specified::Length::parse(context, input)?;
result.push(SpecifiedOperation::TranslateZ(tz)); Ok(SpecifiedOperation::TranslateZ(tz))
Ok(true)
})?
}, },
"translate3d" => { "translate3d" => {
input.parse_nested_block(|input| {
let tx = specified::LengthOrPercentage::parse(context, input)?; let tx = specified::LengthOrPercentage::parse(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let ty = specified::LengthOrPercentage::parse(context, input)?; let ty = specified::LengthOrPercentage::parse(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let tz = specified::Length::parse(context, input)?; let tz = specified::Length::parse(context, input)?;
result.push(SpecifiedOperation::Translate3D(tx, ty, tz)); Ok(SpecifiedOperation::Translate3D(tx, ty, tz))
Ok(true)
})?
}, },
"scale" => { "scale" => {
input.parse_nested_block(|input| {
let sx = specified::parse_number(context, input)?; let sx = specified::parse_number(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() { if input.try(|input| input.expect_comma()).is_ok() {
let sy = specified::parse_number(context, input)?; let sy = specified::parse_number(context, input)?;
result.push(SpecifiedOperation::Scale(sx, Some(sy))); Ok(SpecifiedOperation::Scale(sx, Some(sy)))
} else { } else {
result.push(SpecifiedOperation::Scale(sx, None)); Ok(SpecifiedOperation::Scale(sx, None))
} }
Ok(true)
})?
}, },
"scalex" => { "scalex" => {
input.parse_nested_block(|input| {
let sx = specified::parse_number(context, input)?; let sx = specified::parse_number(context, input)?;
result.push(SpecifiedOperation::ScaleX(sx)); Ok(SpecifiedOperation::ScaleX(sx))
Ok(true)
})?
}, },
"scaley" => { "scaley" => {
input.parse_nested_block(|input| {
let sy = specified::parse_number(context, input)?; let sy = specified::parse_number(context, input)?;
result.push(SpecifiedOperation::ScaleY(sy)); Ok(SpecifiedOperation::ScaleY(sy))
Ok(true)
})?
}, },
"scalez" => { "scalez" => {
input.parse_nested_block(|input| {
let sz = specified::parse_number(context, input)?; let sz = specified::parse_number(context, input)?;
result.push(SpecifiedOperation::ScaleZ(sz)); Ok(SpecifiedOperation::ScaleZ(sz))
Ok(true)
})?
}, },
"scale3d" => { "scale3d" => {
input.parse_nested_block(|input| {
let sx = specified::parse_number(context, input)?; let sx = specified::parse_number(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let sy = specified::parse_number(context, input)?; let sy = specified::parse_number(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let sz = specified::parse_number(context, input)?; let sz = specified::parse_number(context, input)?;
result.push(SpecifiedOperation::Scale3D(sx, sy, sz)); Ok(SpecifiedOperation::Scale3D(sx, sy, sz))
Ok(true)
})?
}, },
"rotate" => { "rotate" => {
input.parse_nested_block(|input| {
let theta = specified::Angle::parse_with_unitless(context, input)?; let theta = specified::Angle::parse_with_unitless(context, input)?;
result.push(SpecifiedOperation::Rotate(theta)); Ok(SpecifiedOperation::Rotate(theta))
Ok(true)
})?
}, },
"rotatex" => { "rotatex" => {
input.parse_nested_block(|input| {
let theta = specified::Angle::parse_with_unitless(context, input)?; let theta = specified::Angle::parse_with_unitless(context, input)?;
result.push(SpecifiedOperation::RotateX(theta)); Ok(SpecifiedOperation::RotateX(theta))
Ok(true)
})?
}, },
"rotatey" => { "rotatey" => {
input.parse_nested_block(|input| {
let theta = specified::Angle::parse_with_unitless(context, input)?; let theta = specified::Angle::parse_with_unitless(context, input)?;
result.push(SpecifiedOperation::RotateY(theta)); Ok(SpecifiedOperation::RotateY(theta))
Ok(true)
})?
}, },
"rotatez" => { "rotatez" => {
input.parse_nested_block(|input| {
let theta = specified::Angle::parse_with_unitless(context, input)?; let theta = specified::Angle::parse_with_unitless(context, input)?;
result.push(SpecifiedOperation::RotateZ(theta)); Ok(SpecifiedOperation::RotateZ(theta))
Ok(true)
})?
}, },
"rotate3d" => { "rotate3d" => {
input.parse_nested_block(|input| {
let ax = specified::parse_number(context, input)?; let ax = specified::parse_number(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let ay = specified::parse_number(context, input)?; let ay = specified::parse_number(context, input)?;
@ -1208,56 +1136,36 @@ ${helpers.predefined_type(
let az = specified::parse_number(context, input)?; let az = specified::parse_number(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let theta = specified::Angle::parse_with_unitless(context, input)?; let theta = specified::Angle::parse_with_unitless(context, input)?;
// TODO(gw): Check the axis can be normalized!! // TODO(gw): Check that the axis can be normalized.
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta)); Ok(SpecifiedOperation::Rotate3D(ax, ay, az, theta))
Ok(true)
})?
}, },
"skew" => { "skew" => {
input.parse_nested_block(|input| { let ax = specified::Angle::parse_with_unitless(context, input)?;
let theta_x = specified::Angle::parse_with_unitless(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() { if input.try(|input| input.expect_comma()).is_ok() {
let theta_y = specified::Angle::parse_with_unitless(context, input)?; let ay = specified::Angle::parse_with_unitless(context, input)?;
result.push(SpecifiedOperation::Skew(theta_x, Some(theta_y))); Ok(SpecifiedOperation::Skew(ax, Some(ay)))
} else { } else {
result.push(SpecifiedOperation::Skew(theta_x, None)); Ok(SpecifiedOperation::Skew(ax, None))
} }
Ok(true)
})?
}, },
"skewx" => { "skewx" => {
input.parse_nested_block(|input| { let theta = specified::Angle::parse_with_unitless(context, input)?;
let theta_x = specified::Angle::parse_with_unitless(context, input)?; Ok(SpecifiedOperation::SkewX(theta))
result.push(SpecifiedOperation::SkewX(theta_x));
Ok(true)
})?
}, },
"skewy" => { "skewy" => {
input.parse_nested_block(|input| { let theta = specified::Angle::parse_with_unitless(context, input)?;
let theta_y = specified::Angle::parse_with_unitless(context, input)?; Ok(SpecifiedOperation::SkewY(theta))
result.push(SpecifiedOperation::SkewY(theta_y));
Ok(true)
})?
}, },
"perspective" => { "perspective" => {
input.parse_nested_block(|input| {
let d = specified::Length::parse_non_negative(context, input)?; let d = specified::Length::parse_non_negative(context, input)?;
result.push(SpecifiedOperation::Perspective(d)); Ok(SpecifiedOperation::Perspective(d))
Ok(true)
})?
}, },
_ => false _ => Err(()),
}; };
if !valid_fn { result
return Err(StyleParseError::UnexpectedFunction(name).into()); .map_err(|()| StyleParseError::UnexpectedFunction(function).into())
} })
} })?))
if !result.is_empty() {
Ok(SpecifiedValue(result))
} else {
Err(StyleParseError::UnspecifiedError.into())
}
} }
/// Parses `transform` property. /// Parses `transform` property.