Auto merge of #16752 - jdm:css-parse-error, r=SimonSapin

Report more informative CSS errors

This requires https://github.com/servo/rust-cssparser/pull/143 for the final commit. There's no better way to split that work up, unfortunately, and it's extremely easy to bitrot. I would appreciate if we could expedite reviewing this work.

This is the work necessary to enable https://bugzilla.mozilla.org/show_bug.cgi?id=1352669. It makes sense to merge it separately because it's so much effort to keep it up to date with the ongoing Stylo work.

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16752)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-06-09 14:31:48 -07:00 committed by GitHub
commit 061cb5f48e
123 changed files with 2212 additions and 1513 deletions

View file

@ -7,15 +7,16 @@
#![deny(missing_docs)]
use context::QuirksMode;
use cssparser::{DeclarationListParser, parse_important};
use cssparser::{DeclarationListParser, parse_important, ParserInput};
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
use error_reporting::ParseErrorReporter;
use error_reporting::{ParseErrorReporter, ContextualParseError};
use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error};
use properties::animated_properties::AnimationValue;
use selectors::parser::SelectorParseError;
use shared_lock::Locked;
use std::fmt;
use std::slice::Iter;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylesheets::{CssRuleType, Origin, UrlExtraData};
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
use super::*;
@ -875,7 +876,8 @@ pub fn parse_style_attribute(input: &str,
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
quirks_mode);
parse_property_declaration_list(&context, &mut Parser::new(input))
let mut input = ParserInput::new(input);
parse_property_declaration_list(&context, &mut Parser::new(&mut input))
}
/// Parse a given property declaration. Can result in multiple
@ -896,10 +898,11 @@ pub fn parse_one_declaration_into(declarations: &mut SourcePropertyDeclaration,
Some(CssRuleType::Style),
parsing_mode,
quirks_mode);
Parser::new(input).parse_entirely(|parser| {
let mut input = ParserInput::new(input);
Parser::new(&mut input).parse_entirely(|parser| {
PropertyDeclaration::parse_into(declarations, id, &context, parser)
.map_err(|_| ())
})
.map_err(|e| e.into())
}).map_err(|_| ())
}
/// A struct to parse property declarations.
@ -910,23 +913,26 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Prelude = ();
type AtRule = Importance;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Declaration = Importance;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Importance, ()> {
let id = try!(PropertyId::parse(name.into()));
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<Importance, ParseError<'i>> {
let id = try!(PropertyId::parse(name));
input.parse_until_before(Delimiter::Bang, |input| {
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
.map_err(|_| ())
.map_err(|e| e.into())
})?;
let importance = match input.try(parse_important) {
Ok(()) => Importance::Important,
Err(()) => Importance::Normal,
Err(_) => Importance::Normal,
};
// In case there is still unparsed text in the declaration, we should roll back.
input.expect_exhausted()?;
@ -952,12 +958,12 @@ pub fn parse_property_declaration_list(context: &ParserContext,
Ok(importance) => {
block.extend(iter.parser.declarations.drain(), importance);
}
Err(range) => {
Err(err) => {
iter.parser.declarations.clear();
let pos = range.start;
let message = format!("Unsupported property declaration: '{}'",
iter.input.slice(range));
log_css_error(iter.input, pos, &*message, &context);
let pos = err.span.start;
let error = ContextualParseError::UnsupportedPropertyDeclaration(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, &context);
}
}
}

View file

@ -33,9 +33,9 @@
% endif
#[allow(unused_variables)]
#[inline]
pub fn parse(context: &ParserContext,
input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
% if allow_quirks:
specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
% elif needs_context:
@ -87,12 +87,16 @@
pub mod single_value {
#[allow(unused_imports)]
use cssparser::Parser;
use cssparser::{Parser, BasicParseError};
#[allow(unused_imports)]
use parser::{Parse, ParserContext};
#[allow(unused_imports)]
use properties::ShorthandId;
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
#[allow(unused_imports)]
use style_traits::{ParseError, StyleParseError};
#[allow(unused_imports)]
use values::computed::{Context, ToComputedValue};
#[allow(unused_imports)]
use values::{computed, specified};
@ -207,7 +211,8 @@
% endif
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
#[allow(unused_imports)]
use parser::parse_space_or_comma_separated;
@ -266,7 +271,7 @@
pub mod ${property.ident} {
% if not property.derived_from:
#[allow(unused_imports)]
use cssparser::Parser;
use cssparser::{Parser, BasicParseError, Token};
#[allow(unused_imports)]
use parser::{Parse, ParserContext};
#[allow(unused_imports)]
@ -287,8 +292,12 @@
#[allow(unused_imports)]
use properties::style_structs;
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
#[allow(unused_imports)]
use stylearc::Arc;
#[allow(unused_imports)]
use style_traits::{ParseError, StyleParseError};
#[allow(unused_imports)]
use values::computed::{Context, ToComputedValue};
#[allow(unused_imports)]
use values::{computed, generics, specified};
@ -423,12 +432,12 @@
% endif
}
% if not property.derived_from:
pub fn parse_specified(context: &ParserContext, input: &mut Parser)
pub fn parse_specified<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
% if property.boxed:
-> Result<Box<SpecifiedValue>, ()> {
-> Result<Box<SpecifiedValue>, ParseError<'i>> {
parse(context, input).map(|result| Box::new(result))
% else:
-> Result<SpecifiedValue, ()> {
-> Result<SpecifiedValue, ParseError<'i>> {
% if property.allow_quirks:
parse_quirky(context, input, specified::AllowQuirks::Yes)
% else:
@ -436,11 +445,11 @@
% endif
% endif
}
pub fn parse_declared(context: &ParserContext, input: &mut Parser)
-> Result<PropertyDeclaration, ()> {
pub fn parse_declared<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<PropertyDeclaration, ParseError<'i>> {
match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(keyword) => Ok(PropertyDeclaration::CSSWideKeyword(LonghandId::${property.camel_case}, keyword)),
Err(()) => {
Err(_) => {
input.look_for_var_functions();
let start = input.position();
let specified = parse_specified(context, input);
@ -487,7 +496,7 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
define_css_keyword_enum! { T:
% for value in keyword.values_for(product):
"${value}" => ${to_rust_ident(value)},
@ -495,7 +504,7 @@
}
impl Parse for T {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
T::parse(input)
}
}
@ -518,7 +527,7 @@
}
}
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
}
@ -716,14 +725,14 @@
SpecifiedValue::${to_rust_ident(values.split()[0])}
}
#[inline]
pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
impl Parse for SpecifiedValue {
#[inline]
fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
}
@ -764,9 +773,11 @@
use parser::ParserContext;
use properties::{PropertyDeclaration, SourcePropertyDeclaration, MaybeBoxed};
use properties::{ShorthandId, LonghandId, UnparsedValue, longhands};
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
use std::fmt;
use stylearc::Arc;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
pub struct Longhands {
% for sub_property in shorthand.sub_properties:
@ -838,8 +849,8 @@
/// Parse the given shorthand and fill the result into the
/// `declarations` vector.
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> {
input.look_for_var_functions();
let start = input.position();
let value = input.parse_entirely(|input| parse_value(context, input));
@ -872,7 +883,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -890,7 +901,8 @@
use values::generics::rect::Rect;
use values::specified;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let rect = Rect::parse_with(context, input, |_c, i| {
% if allow_quirks:
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
@ -1114,7 +1126,8 @@
use values::computed::${length_type};
${length_type}::${initial_value}
}
fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
% if logical:
let ret = ${length_type}::parse(context, input);
% else:
@ -1123,7 +1136,7 @@
// Keyword values don't make sense in the block direction; don't parse them
% if "block" in name:
if let Ok(${length_type}::ExtremumLength(..)) = ret {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
% endif
ret.map(SpecifiedValue)

View file

@ -27,12 +27,13 @@ use properties::longhands::transform::computed_value::T as TransformList;
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
use properties::longhands::visibility::computed_value::T as Visibility;
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")] use servo_atoms::Atom;
use smallvec::SmallVec;
use std::cmp;
#[cfg(feature = "gecko")] use std::collections::HashMap;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
use super::ComputedValues;
use values::CSSFloat;
use values::{Auto, Either};
@ -99,9 +100,9 @@ impl TransitionProperty {
}
/// Parse a transition-property value.
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = try!(input.expect_ident());
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"all" => Ok(TransitionProperty::All),
% for prop in data.longhands:
% if prop.animatable:
@ -118,7 +119,7 @@ impl TransitionProperty {
None => Ok(TransitionProperty::Unsupported((&*ident).into()))
}
}
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
}
/// Get a transition property from a property declaration.
@ -476,7 +477,7 @@ impl AnimationValue {
/// Construct an AnimationValue from a property declaration
pub fn from_declaration(decl: &PropertyDeclaration, context: &mut Context,
initial: &ComputedValues) -> Option<Self> {
use error_reporting::RustLogReporter;
use error_reporting::create_error_reporter;
use properties::LonghandId;
use properties::DeclaredValue;
@ -539,7 +540,7 @@ impl AnimationValue {
},
PropertyDeclaration::WithVariables(id, ref variables) => {
let custom_props = context.style().custom_properties();
let reporter = RustLogReporter;
let reporter = create_error_reporter();
match id {
% for prop in data.longhands:
% if prop.animatable:

View file

@ -128,17 +128,20 @@ ${helpers.predefined_type("background-image", "ImageLayer",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"repeat-x" => Ok(SpecifiedValue::RepeatX),
"repeat-y" => Ok(SpecifiedValue::RepeatY),
_ => {
let horizontal = try!(RepeatKeyword::from_ident(&ident));
let vertical = input.try(RepeatKeyword::parse).ok();
Ok(SpecifiedValue::Other(horizontal, vertical))
}
}
_ => Err(()),
}).or_else(|()| {
let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident)
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
let horizontal = try!(horizontal);
let vertical = input.try(RepeatKeyword::parse).ok();
Ok(SpecifiedValue::Other(horizontal, vertical))
})
}
</%helpers:vector_longhand>

View file

@ -161,8 +161,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
}
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None)
}
@ -175,7 +175,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
if !result.is_empty() {
Ok(SpecifiedValue::Colors(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -272,7 +272,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let first = try!(RepeatKeyword::parse(input));
let second = input.try(RepeatKeyword::parse).ok();

View file

@ -113,16 +113,17 @@
}
/// Parse a display value.
pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
match_ignore_ascii_case! { &try!(input.expect_ident()),
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
% for value in values:
"${value}" => {
Ok(computed_value::T::${to_rust_ident(value)})
},
% endfor
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
impl ComputedValueAsSpecified for SpecifiedValue {}
@ -292,16 +293,18 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
}
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
/// | <percentage> | <length>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|_| {
match_ignore_ascii_case! { &try!(input.expect_ident()),
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
% for keyword in vertical_align_keywords:
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
% endfor
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
})
}
@ -500,17 +503,19 @@ ${helpers.predefined_type("transition-delay",
}
impl Parse for SpecifiedValue {
fn parse(context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) {
Ok(SpecifiedValue(Some(name)))
} else {
input.expect_ident_matching("none").map(|()| SpecifiedValue(None))
input.expect_ident_matching("none").map(|_| SpecifiedValue(None)).map_err(|e| e.into())
}
}
}
no_viewport_percentage!(SpecifiedValue);
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -560,14 +565,15 @@ ${helpers.predefined_type("animation-timing-function",
}
impl Parse for SpecifiedValue {
fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
return Ok(SpecifiedValue::Infinite)
}
let number = try!(input.expect_number());
if number < 0.0 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(SpecifiedValue::Number(number))
@ -587,7 +593,8 @@ ${helpers.predefined_type("animation-timing-function",
}
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -948,8 +955,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
}
// Allow unitless zero angle for rotate() and skew() to align with gecko
fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
-> Result<SpecifiedValue,()> {
fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool)
-> Result<SpecifiedValue,ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -960,7 +967,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
Ok(name) => name,
Err(_) => break,
};
match_ignore_ascii_case! {
let valid_fn = match_ignore_ascii_case! {
&name,
"matrix" => {
try!(input.parse_nested_block(|input| {
@ -970,7 +977,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
specified::parse_number(context, input)
}));
if values.len() != 6 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
result.push(SpecifiedOperation::Matrix {
@ -981,7 +988,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
e: values[4],
f: values[5],
});
return Ok(());
return Ok(true);
}
// Non-standard prefixed matrix parsing.
@ -1014,7 +1021,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
e: lengths[0].clone(),
f: lengths[1].clone(),
});
Ok(())
Ok(true)
}))
},
"matrix3d" => {
@ -1023,7 +1030,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
if !prefixed {
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
if values.len() != 16 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
result.push(SpecifiedOperation::Matrix3D {
@ -1032,7 +1039,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
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(());
return Ok(true);
}
// Non-standard prefixed matrix3d parsing.
@ -1069,7 +1076,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
m44: values[12]
});
Ok(())
Ok(true)
}))
},
"translate" => {
@ -1081,28 +1088,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Translate(sx, None));
}
Ok(())
Ok(true)
}))
},
"translatex" => {
try!(input.parse_nested_block(|input| {
let tx = try!(specified::LengthOrPercentage::parse(context, input));
result.push(SpecifiedOperation::TranslateX(tx));
Ok(())
Ok(true)
}))
},
"translatey" => {
try!(input.parse_nested_block(|input| {
let ty = try!(specified::LengthOrPercentage::parse(context, input));
result.push(SpecifiedOperation::TranslateY(ty));
Ok(())
Ok(true)
}))
},
"translatez" => {
try!(input.parse_nested_block(|input| {
let tz = try!(specified::Length::parse(context, input));
result.push(SpecifiedOperation::TranslateZ(tz));
Ok(())
Ok(true)
}))
},
"translate3d" => {
@ -1113,7 +1120,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
try!(input.expect_comma());
let tz = try!(specified::Length::parse(context, input));
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
Ok(())
Ok(true)
}))
},
"scale" => {
@ -1125,28 +1132,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Scale(sx, None));
}
Ok(())
Ok(true)
}))
},
"scalex" => {
try!(input.parse_nested_block(|input| {
let sx = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleX(sx));
Ok(())
Ok(true)
}))
},
"scaley" => {
try!(input.parse_nested_block(|input| {
let sy = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleY(sy));
Ok(())
Ok(true)
}))
},
"scalez" => {
try!(input.parse_nested_block(|input| {
let sz = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleZ(sz));
Ok(())
Ok(true)
}))
},
"scale3d" => {
@ -1157,35 +1164,35 @@ ${helpers.predefined_type("scroll-snap-coordinate",
try!(input.expect_comma());
let sz = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
Ok(())
Ok(true)
}))
},
"rotate" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::Rotate(theta));
Ok(())
Ok(true)
}))
},
"rotatex" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateX(theta));
Ok(())
Ok(true)
}))
},
"rotatey" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateY(theta));
Ok(())
Ok(true)
}))
},
"rotatez" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateZ(theta));
Ok(())
Ok(true)
}))
},
"rotate3d" => {
@ -1199,7 +1206,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
let theta = try!(specified::Angle::parse_with_unitless(context, input));
// TODO(gw): Check the axis can be normalized!!
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
Ok(())
Ok(true)
}))
},
"skew" => {
@ -1211,51 +1218,56 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Skew(theta_x, None));
}
Ok(())
Ok(true)
}))
},
"skewx" => {
try!(input.parse_nested_block(|input| {
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::SkewX(theta_x));
Ok(())
Ok(true)
}))
},
"skewy" => {
try!(input.parse_nested_block(|input| {
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::SkewY(theta_y));
Ok(())
Ok(true)
}))
},
"perspective" => {
try!(input.parse_nested_block(|input| {
let d = try!(specified::Length::parse_non_negative(context, input));
result.push(SpecifiedOperation::Perspective(d));
Ok(())
Ok(true)
}))
},
_ => return Err(())
_ => false
};
if !valid_fn {
return Err(StyleParseError::UnexpectedFunction(name).into());
}
}
if !result.is_empty() {
Ok(SpecifiedValue(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
/// Parses `transform` property.
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_internal(context, input, false)
}
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
/// in the nondiagonal homogeneous components of matrix and matrix3d.
#[inline]
pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse_prefixed<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_internal(context, input, true)
}
@ -1771,7 +1783,8 @@ ${helpers.predefined_type("transform-origin",
}
/// none | strict | content | [ size || layout || style || paint ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue::empty();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
@ -1784,21 +1797,22 @@ ${helpers.predefined_type("transform-origin",
while let Ok(name) = input.try(|input| input.expect_ident()) {
let flag = match_ignore_ascii_case! { &name,
"layout" => LAYOUT,
"style" => STYLE,
"paint" => PAINT,
_ => return Err(())
"layout" => Some(LAYOUT),
"style" => Some(STYLE),
"paint" => Some(PAINT),
_ => None
};
let flag = match flag {
Some(flag) if !result.contains(flag) => flag,
_ => return Err(SelectorParseError::UnexpectedIdent(name).into())
};
if result.contains(flag) {
return Err(())
}
result.insert(flag);
}
if !result.is_empty() {
Ok(result)
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -1900,18 +1914,23 @@ ${helpers.single_keyword("-moz-orient",
}
/// auto | <animateable-feature>#
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(computed_value::T::Auto)
} else {
input.parse_comma_separated(|i| {
let ident = i.expect_ident()?;
match_ignore_ascii_case! { &ident,
let bad_keyword = match_ignore_ascii_case! { &ident,
"will-change" | "none" | "all" | "auto" |
"initial" | "inherit" | "unset" | "default" => return Err(()),
_ => {},
"initial" | "inherit" | "unset" | "default" => true,
_ => false,
};
if bad_keyword {
Err(SelectorParseError::UnexpectedIdent(ident.into()).into())
} else {
Ok(Atom::from(ident))
}
Ok((Atom::from(ident)))
}).map(SpecifiedValue::AnimateableFeatures)
}
}
@ -1976,9 +1995,10 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
TOUCH_ACTION_AUTO
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"auto" => Ok(TOUCH_ACTION_AUTO),
"none" => Ok(TOUCH_ACTION_NONE),
"manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
@ -1997,7 +2017,7 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
}
},
_ => Err(()),
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
#[cfg(feature = "gecko")]

View file

@ -43,7 +43,8 @@
pub fn get_initial_value() -> computed_value::T {
RGBA::new(0, 0, 0, 255) // black
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
}
@ -118,7 +119,7 @@
}
impl SystemColor {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
#[cfg(feature = "gecko")]
use std::ascii::AsciiExt;
static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
@ -133,7 +134,7 @@
return Ok(color)
}
}
Err(())
Err(SelectorParseError::UnexpectedIdent(ident).into())
}
}
% endif

View file

@ -8,7 +8,6 @@
<%helpers:longhand name="content" boxed="True" animation_value_type="none"
spec="https://drafts.csswg.org/css-content/#propdef-content">
use cssparser::Token;
use values::computed::ComputedValueAsSpecified;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
@ -157,8 +156,8 @@
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
// no-close-quote ]+
// TODO: <uri>, attr(<identifier>)
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
return Ok(SpecifiedValue::Normal)
}
@ -185,43 +184,50 @@
content.push(ContentItem::String(value.into_owned()))
}
Ok(Token::Function(name)) => {
content.push(try!(match_ignore_ascii_case! { &name,
"counter" => input.parse_nested_block(|input| {
let result = match_ignore_ascii_case! { &name,
"counter" => Some(input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned();
let style = parse_counter_style(context, input);
Ok(ContentItem::Counter(name, style))
}),
"counters" => input.parse_nested_block(|input| {
})),
"counters" => Some(input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned();
try!(input.expect_comma());
let separator = try!(input.expect_string()).into_owned();
let style = parse_counter_style(context, input);
Ok(ContentItem::Counters(name, separator, style))
}),
})),
% if product == "gecko":
"attr" => input.parse_nested_block(|input| {
"attr" => Some(input.parse_nested_block(|input| {
Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
}),
})),
% endif
_ => return Err(())
}));
_ => None
};
match result {
Some(result) => content.push(try!(result)),
None => return Err(StyleParseError::UnexpectedFunction(name).into())
}
}
Ok(Token::Ident(ident)) => {
match_ignore_ascii_case! { &ident,
"open-quote" => content.push(ContentItem::OpenQuote),
"close-quote" => content.push(ContentItem::CloseQuote),
"no-open-quote" => content.push(ContentItem::NoOpenQuote),
"no-close-quote" => content.push(ContentItem::NoCloseQuote),
let valid = match_ignore_ascii_case! { &ident,
"open-quote" => { content.push(ContentItem::OpenQuote); true },
"close-quote" => { content.push(ContentItem::CloseQuote); true },
"no-open-quote" => { content.push(ContentItem::NoOpenQuote); true },
"no-close-quote" => { content.push(ContentItem::NoCloseQuote); true },
_ => return Err(())
_ => false,
};
if !valid {
return Err(SelectorParseError::UnexpectedIdent(ident).into())
}
}
Err(_) => break,
_ => return Err(())
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into())
}
}
if content.is_empty() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(SpecifiedValue::Items(content))
}
@ -233,8 +239,6 @@
use style_traits::ToCss;
use values::CustomIdent;
use cssparser::Token;
#[derive(Debug, Clone, PartialEq)]
pub struct SpecifiedValue(pub Vec<(CustomIdent, specified::Integer)>);
@ -315,11 +319,13 @@
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
parse_common(context, 1, input)
}
pub fn parse_common(context: &ParserContext, default_value: i32, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse_common<'i, 't>(context: &ParserContext, default_value: i32, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -328,7 +334,7 @@
loop {
let counter_name = match input.next() {
Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
Ok(_) => return Err(()),
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(_) => break,
};
let counter_delta = input.try(|input| specified::parse_integer(context, input))
@ -339,7 +345,7 @@
if !counters.is_empty() {
Ok(SpecifiedValue(counters))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -349,7 +355,8 @@
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
use super::counter_increment::parse_common;
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_common(context, 0, input)
}
</%helpers:longhand>

View file

@ -27,7 +27,8 @@ ${helpers.predefined_type("opacity",
pub type T = Shadow;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<specified::Shadow, ParseError<'i>> {
specified::Shadow::parse(context, input, false)
}
</%helpers:vector_longhand>
@ -263,7 +264,8 @@ ${helpers.predefined_type("clip",
computed_value::T::new(Vec::new())
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut filters = Vec::new();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(filters))
@ -290,23 +292,24 @@ ${helpers.predefined_type("clip",
"drop-shadow" => specified::Shadow::parse(context, input, true)
.map(SpecifiedFilter::DropShadow),
% endif
_ => Err(())
_ => Err(StyleParseError::UnexpectedFunction(function_name.clone()).into())
}
})));
} else if filters.is_empty() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
} else {
return Ok(SpecifiedValue(filters))
}
}
}
fn parse_factor(input: &mut Parser) -> Result<::values::CSSFloat, ()> {
fn parse_factor<'i, 't>(input: &mut Parser<'i, 't>) -> Result<::values::CSSFloat, ParseError<'i>> {
use cssparser::Token;
match input.next() {
Ok(Token::Number(value)) if value.value.is_sign_positive() => Ok(value.value),
Ok(Token::Percentage(value)) if value.unit_value.is_sign_positive() => Ok(value.unit_value),
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into())
}
}

View file

@ -92,7 +92,7 @@ macro_rules! impl_gecko_keyword_from_trait {
use cssparser::{CssStringWriter, Parser, serialize_identifier};
use std::fmt::{self, Write};
use Atom;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
pub use self::FontFamily as SingleComputedValue;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
@ -154,7 +154,7 @@ macro_rules! impl_gecko_keyword_from_trait {
}
/// Parse a font-family value
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(value) = input.try(|input| input.expect_string()) {
return Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(&*value),
@ -294,7 +294,8 @@ macro_rules! impl_gecko_keyword_from_trait {
/// <family-name>#
/// <family-name> = <string> | [ <ident>+ ]
/// TODO: <generic-family>
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
@ -348,7 +349,7 @@ macro_rules! impl_gecko_keyword_from_trait {
}
}
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
}
}
@ -374,11 +375,11 @@ macro_rules! impl_gecko_keyword_from_trait {
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
/// because we want the former to exclude generic family keywords.
impl Parse for FamilyName {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match FontFamily::parse(input) {
Ok(FontFamily::FamilyName(name)) => Ok(name),
Ok(FontFamily::Generic(_)) |
Err(()) => Err(())
Ok(FontFamily::Generic(_)) => Err(StyleParseError::UnspecifiedError.into()),
Err(e) => Err(e)
}
}
}
@ -444,17 +445,21 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(|input| {
match_ignore_ascii_case! { &try!(input.expect_ident()),
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let result: Result<_, ParseError> = input.try(|input| {
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
"normal" => Ok(SpecifiedValue::Normal),
"bold" => Ok(SpecifiedValue::Bold),
"bolder" => Ok(SpecifiedValue::Bolder),
"lighter" => Ok(SpecifiedValue::Lighter),
_ => Err(())
}
}).or_else(|()| {
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
});
result.or_else(|_| {
SpecifiedValue::from_int(input.expect_integer()?)
.map_err(|()| StyleParseError::UnspecifiedError.into())
})
}
@ -489,7 +494,7 @@ ${helpers.single_keyword_system("font-variant-caps",
/// Used in @font-face, where relative keywords are not allowed.
impl Parse for computed_value::T {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match parse(context, input)? {
% for weight in range(100, 901, 100):
SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
@ -497,7 +502,7 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
SpecifiedValue::Bolder |
SpecifiedValue::Lighter => Err(()),
SpecifiedValue::Lighter => Err(StyleParseError::UnspecifiedError.into()),
SpecifiedValue::System(..) => unreachable!(),
}
}
@ -683,17 +688,18 @@ ${helpers.single_keyword_system("font-variant-caps",
pub use self::KeywordSize::*;
impl KeywordSize {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! {&*input.expect_ident()?,
"xx-small" => XXSmall,
"x-small" => XSmall,
"small" => Small,
"medium" => Medium,
"large" => Large,
"x-large" => XLarge,
"xx-large" => XXLarge,
_ => return Err(())
})
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! {&*ident,
"xx-small" => Ok(XXSmall),
"x-small" => Ok(XSmall),
"small" => Ok(Small),
"medium" => Ok(Medium),
"large" => Ok(Large),
"x-large" => Ok(XLarge),
"xx-large" => Ok(XXLarge),
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -906,15 +912,16 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// <length> | <percentage> | <absolute-size> | <relative-size>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
parse_quirky(context, input, AllowQuirks::No)
}
/// Parses a font-size, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<SpecifiedValue, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<SpecifiedValue, ParseError<'i>> {
use self::specified::LengthOrPercentage;
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
return Ok(SpecifiedValue::Length(lop))
@ -924,11 +931,12 @@ ${helpers.single_keyword_system("font-variant-caps",
return Ok(SpecifiedValue::Keyword(kw, 1.))
}
match_ignore_ascii_case! {&*input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! {&*ident,
"smaller" => Ok(SpecifiedValue::Smaller),
"larger" => Ok(SpecifiedValue::Larger),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
impl SpecifiedValue {
@ -1150,7 +1158,8 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// none | <number>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
use values::specified::Number;
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
@ -1200,9 +1209,11 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue { weight: true, style: true }
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue { weight: false, style: false };
match_ignore_ascii_case! { &try!(input.expect_ident()),
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
"none" => Ok(result),
"weight" => {
result.weight = true;
@ -1219,7 +1230,7 @@ ${helpers.single_keyword_system("font-variant-caps",
Ok(result)
},
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
#[cfg(feature = "gecko")]
@ -1364,7 +1375,8 @@ ${helpers.single_keyword_system("font-kerning",
/// swash(<feature-value-name>) ||
/// ornaments(<feature-value-name>) ||
/// annotation(<feature-value-name>) ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantAlternates::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1373,25 +1385,26 @@ ${helpers.single_keyword_system("font-kerning",
while let Ok(ident) = input.try(|input| input.expect_ident()) {
let flag = match_ignore_ascii_case! { &ident,
"stylistic" => STYLISTIC,
"historical-forms" => HISTORICAL_FORMS,
"styleset" => STYLESET,
"character-variant" => CHARACTER_VARIANT,
"swash" => SWASH,
"ornaments" => ORNAMENTS,
"annotation" => ANNOTATION,
_ => return Err(()),
"stylistic" => Some(STYLISTIC),
"historical-forms" => Some(HISTORICAL_FORMS),
"styleset" => Some(STYLESET),
"character-variant" => Some(CHARACTER_VARIANT),
"swash" => Some(SWASH),
"ornaments" => Some(ORNAMENTS),
"annotation" => Some(ANNOTATION),
_ => None,
};
let flag = match flag {
Some(flag) if !result.intersects(flag) => flag,
_ => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
if result.intersects(flag) {
return Err(())
}
result.insert(flag);
}
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -1400,9 +1413,9 @@ ${helpers.single_keyword_system("font-kerning",
macro_rules! exclusive_value {
(($value:ident, $set:expr) => $ident:ident) => {
if $value.intersects($set) {
return Err(())
None
} else {
$ident
Some($ident)
}
}
}
@ -1507,7 +1520,8 @@ macro_rules! exclusive_value {
/// <east-asian-width-values> = [ full-width | proportional-width ]
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantEastAsian::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1534,7 +1548,11 @@ macro_rules! exclusive_value {
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
"ruby" =>
exclusive_value!((result, RUBY) => RUBY),
_ => return Err(()),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1542,7 +1560,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1659,7 +1677,8 @@ macro_rules! exclusive_value {
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantLigatures::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1687,7 +1706,11 @@ macro_rules! exclusive_value {
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
"no-contextual" =>
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
_ => return Err(()),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1695,7 +1718,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1808,7 +1831,8 @@ macro_rules! exclusive_value {
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantNumeric::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1824,16 +1848,20 @@ macro_rules! exclusive_value {
"lining-nums" =>
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
"oldstyle-nums" =>
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS ),
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS),
"proportional-nums" =>
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS ),
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS),
"tabular-nums" =>
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS ),
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS),
"diagonal-fractions" =>
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS ),
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS),
"stacked-fractions" =>
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS ),
_ => return Err(()),
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1841,7 +1869,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1890,7 +1918,8 @@ ${helpers.single_keyword_system("font-variant-position",
}
/// normal | <feature-tag-value>#
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(context, input).map(SpecifiedValue::Value)
}
</%helpers:longhand>
@ -1924,7 +1953,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
/// normal | <feature-tag-value>#
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(context, input)
}
</%helpers:longhand>
@ -2054,13 +2084,14 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
/// normal | <string>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
Ok(SpecifiedValue::Normal)
} else {
input.expect_string().map(|cow| {
SpecifiedValue::Override(cow.into_owned())
})
}).map_err(|e| e.into())
}
}
@ -2108,9 +2139,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
computed_value::T(atom!(""))
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2133,9 +2165,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2206,7 +2239,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if let Ok(i) = input.try(|i| i.expect_integer()) {
return Ok(SpecifiedValue::Relative(i))
}
@ -2281,9 +2315,10 @@ ${helpers.single_keyword("-moz-math-variant",
Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2308,7 +2343,9 @@ ${helpers.single_keyword("-moz-math-variant",
use app_units::Au;
use cssparser::Parser;
use properties::longhands;
use selectors::parser::SelectorParseError;
use std::hash::{Hash, Hasher};
use style_traits::ParseError;
use values::computed::{ToComputedValue, Context};
<%
system_fonts = """caption icon menu message-box small-caption status-bar
@ -2427,13 +2464,14 @@ ${helpers.single_keyword("-moz-math-variant",
}
impl SystemFont {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! { &*input.expect_ident()?,
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &*ident,
% for font in system_fonts:
"${font}" => SystemFont::${to_camel_case(font)},
"${font}" => Ok(SystemFont::${to_camel_case(font)}),
% endfor
_ => return Err(())
})
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
}

View file

@ -174,7 +174,8 @@ ${helpers.single_keyword("image-rendering",
}
// from-image | <angle> | [<angle>? flip]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
// Handle from-image
Ok(SpecifiedValue { angle: None, flipped: false })
@ -185,7 +186,7 @@ ${helpers.single_keyword("image-rendering",
// Handle <angle> | <angle> flip
let angle = input.try(|input| Angle::parse(context, input)).ok();
if angle.is_none() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();

View file

@ -183,7 +183,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
Ok(SpecifiedValue(0))
} else {
@ -195,33 +196,34 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
loop {
let result = input.try(|i| {
match_ignore_ascii_case! { &i.expect_ident()?,
let result: Result<_, ParseError> = input.try(|i| {
let ident = i.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"fill" => Ok(FILL),
"stroke" => Ok(STROKE),
"markers" => Ok(MARKERS),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
});
match result {
Ok(val) => {
if (seen & (1 << val)) != 0 {
// don't parse the same ident twice
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
} else {
value |= val << (pos * SHIFT);
seen |= 1 << val;
pos += 1;
}
}
Err(()) => break,
Err(_) => break,
}
}
if value == 0 {
// couldn't find any keyword
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
// fill in rest
for i in pos..COUNT {
@ -285,7 +287,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let i = input.expect_ident()?;
CustomIdent::from_ident(i, &["all", "none", "auto"])
}

View file

@ -113,11 +113,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
let mut first = None;
let mut second = None;
match Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes) {
Err(()) => (),
Err(_) => (),
Ok(length) => {
first = Some(length);
if let Ok(len) = input.try(|i| Length::parse_non_negative_quirky(context, i, AllowQuirks::Yes)) {
@ -126,7 +127,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
}
match (first, second) {
(None, None) => Err(()),
(None, None) => Err(StyleParseError::UnspecifiedError.into()),
(Some(length), None) => {
Ok(SpecifiedValue {
horizontal: length,

View file

@ -179,7 +179,8 @@ ${helpers.single_keyword("text-align-last",
MatchParent,
MozCenterOrInherit,
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
// MozCenterOrInherit cannot be parsed, only set directly on th elements
if let Ok(key) = input.try(computed_value::T::parse) {
Ok(SpecifiedValue::Keyword(key))
@ -255,7 +256,8 @@ ${helpers.single_keyword("text-align-last",
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub use self::computed_value::T as SpecifiedValue;
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(input)
}
% endif
@ -415,7 +417,8 @@ ${helpers.predefined_type("word-spacing",
pub type T = Shadow;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<specified::Shadow, ParseError<'i>> {
specified::Shadow::parse(context, input, true)
}
</%helpers:vector_longhand>
@ -577,7 +580,8 @@ ${helpers.predefined_type("word-spacing",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None);
}
@ -603,7 +607,7 @@ ${helpers.predefined_type("word-spacing",
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape),
(Some(fill), Err(_)) => KeywordValue::Fill(fill),
(None, Ok(shape)) => KeywordValue::Shape(shape),
_ => return Err(()),
_ => return Err(StyleParseError::UnspecifiedError.into()),
};
Ok(SpecifiedValue::Keyword(keyword_value))
}
@ -636,7 +640,8 @@ ${helpers.predefined_type("word-spacing",
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if let Ok(horizontal) = input.try(|input| HorizontalWritingModeValue::parse(input)) {
let vertical = try!(VerticalWritingModeValue::parse(input));
Ok(SpecifiedValue(horizontal, vertical))

View file

@ -89,7 +89,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
SpecifiedValue::CounterStyle(style)
} else {
@ -126,7 +127,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(Either::Second(None_))
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
% if product == "gecko":
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
if let Either::First(ref mut url) = value {
@ -142,7 +144,6 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
<%helpers:longhand name="quotes" animation_value_type="none"
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
use cssparser::Token;
use std::borrow::Cow;
use std::fmt;
use style_traits::ToCss;
@ -187,7 +188,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
])
}
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -196,19 +198,20 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
loop {
let first = match input.next() {
Ok(Token::QuotedString(value)) => value.into_owned(),
Ok(_) => return Err(()),
Err(()) => break,
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(_) => break,
};
let second = match input.next() {
Ok(Token::QuotedString(value)) => value.into_owned(),
_ => return Err(()),
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => return Err(e.into()),
};
quotes.push((first, second))
}
if !quotes.is_empty() {
Ok(SpecifiedValue(quotes))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>

View file

@ -46,14 +46,15 @@ ${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentc
pub type T = super::SpecifiedValue;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
.and_then(|result| {
if let Either::Second(BorderStyle::hidden) = result {
// The outline-style property accepts the same values as
// border-style, except that 'hidden' is not a legal outline
// style.
Err(())
Err(SelectorParseError::UnexpectedIdent("hidden".into()).into())
} else {
Ok(result)
}

View file

@ -91,37 +91,43 @@
}
impl Parse for computed_value::Keyword {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<computed_value::Keyword, ParseError<'i>> {
use std::ascii::AsciiExt;
use style_traits::cursor::Cursor;
let ident = try!(input.expect_ident());
if ident.eq_ignore_ascii_case("auto") {
Ok(computed_value::Keyword::Auto)
} else {
Cursor::from_css_keyword(&ident).map(computed_value::Keyword::Cursor)
Cursor::from_css_keyword(&ident)
.map(computed_value::Keyword::Cursor)
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
}
#[cfg(feature = "gecko")]
fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
fn parse_image<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<computed_value::Image, ParseError<'i>> {
Ok(computed_value::Image {
url: try!(SpecifiedUrl::parse(context, input)),
hotspot: match input.try(|input| input.expect_number()) {
Ok(number) => Some((number, try!(input.expect_number()))),
Err(()) => None,
Err(_) => None,
},
})
}
#[cfg(not(feature = "gecko"))]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::Keyword::parse(context, input)
}
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
#[cfg(feature = "gecko")]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| parse_image(context, input)) {
@ -129,7 +135,7 @@
image.url.build_image_value();
images.push(image)
}
Err(()) => break,
Err(_) => break,
}
try!(input.expect_comma());
}

View file

@ -339,27 +339,32 @@ ${helpers.predefined_type("object-position",
}
/// [ row | column ] || dense
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
use self::computed_value::AutoFlow;
let mut value = None;
let mut dense = false;
while !input.is_exhausted() {
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
let success = match_ignore_ascii_case! { &ident,
"row" if value.is_none() => {
value = Some(AutoFlow::Row);
continue
true
},
"column" if value.is_none() => {
value = Some(AutoFlow::Column);
continue
true
},
"dense" if !dense => {
dense = true;
continue
true
},
_ => return Err(())
_ => false
};
if !success {
return Err(SelectorParseError::UnexpectedIdent(ident).into());
}
}
@ -369,7 +374,7 @@ ${helpers.predefined_type("object-position",
dense: dense,
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -435,7 +440,8 @@ ${helpers.predefined_type("object-position",
Either::Second(None_)
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -457,13 +463,15 @@ ${helpers.predefined_type("object-position",
impl ComputedValueAsSpecified for TemplateAreas {}
impl Parse for TemplateAreas {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let mut strings = vec![];
while let Ok(string) = input.try(Parser::expect_string) {
strings.push(string.into_owned().into_boxed_str());
}
TemplateAreas::from_vec(strings)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
}

View file

@ -129,7 +129,8 @@ ${helpers.single_keyword("mask-origin",
background_size::get_initial_value()
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
background_size::parse(context, input)
}
</%helpers:longhand>

View file

@ -40,7 +40,8 @@ ${helpers.single_keyword("table-layout", "auto fixed",
}
// never parse it, only set via presentation attribute
fn parse(_: &ParserContext, _: &mut Parser) -> Result<SpecifiedValue, ()> {
Err(())
fn parse<'i, 't>(_: &ParserContext, _: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>

View file

@ -104,7 +104,8 @@
sides_are_logical: true,
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let first = try!(Side::parse(context, input));
let second = input.try(|input| Side::parse(context, input)).ok();
Ok(SpecifiedValue {
@ -113,13 +114,14 @@
})
}
impl Parse for Side {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Side, ParseError<'i>> {
if let Ok(ident) = input.try(|input| input.expect_ident()) {
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"clip" => Ok(Side::Clip),
"ellipsis" => Ok(Side::Ellipsis),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
} else {
Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
}
@ -216,34 +218,39 @@ ${helpers.single_keyword("unicode-bidi",
SpecifiedValue::empty()
}
/// none | [ underline || overline || line-through || blink ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue::empty();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(result)
}
let mut empty = true;
while input.try(|input| {
if let Ok(ident) = input.expect_ident() {
match_ignore_ascii_case! { &ident,
"underline" => if result.contains(UNDERLINE) { return Err(()) }
else { empty = false; result.insert(UNDERLINE) },
"overline" => if result.contains(OVERLINE) { return Err(()) }
else { empty = false; result.insert(OVERLINE) },
"line-through" => if result.contains(LINE_THROUGH) { return Err(()) }
else { empty = false; result.insert(LINE_THROUGH) },
"blink" => if result.contains(BLINK) { return Err(()) }
else { empty = false; result.insert(BLINK) },
_ => return Err(())
loop {
let result: Result<_, ParseError> = input.try(|input| {
match input.expect_ident() {
Ok(ident) => {
(match_ignore_ascii_case! { &ident,
"underline" => if result.contains(UNDERLINE) { Err(()) }
else { empty = false; result.insert(UNDERLINE); Ok(()) },
"overline" => if result.contains(OVERLINE) { Err(()) }
else { empty = false; result.insert(OVERLINE); Ok(()) },
"line-through" => if result.contains(LINE_THROUGH) { Err(()) }
else { empty = false; result.insert(LINE_THROUGH); Ok(()) },
"blink" => if result.contains(BLINK) { Err(()) }
else { empty = false; result.insert(BLINK); Ok(()) },
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
} else {
return Err(());
Err(e) => return Err(e.into())
}
Ok(())
}).is_ok() {
});
if result.is_err() {
break;
}
}
if !empty { Ok(result) } else { Err(()) }
if !empty { Ok(result) } else { Err(StyleParseError::UnspecifiedError.into()) }
}
% if product == "servo":

View file

@ -76,11 +76,12 @@ ${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet"
impl ComputedValueAsSpecified for SpecifiedValue {}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
match try!(input.expect_integer()) {
0 => Ok(computed_value::T(false)),
1 => Ok(computed_value::T(true)),
_ => Err(()),
_ => Err(StyleParseError::UnspecifiedError.into()),
}
}

View file

@ -20,6 +20,7 @@ use stylearc::{Arc, UniqueArc};
use app_units::Au;
#[cfg(feature = "servo")] use cssparser::RGBA;
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
use cssparser::ParserInput;
use error_reporting::ParseErrorReporter;
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
use computed_values;
@ -33,9 +34,10 @@ use media_queries::Device;
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
use properties::animated_properties::TransitionProperty;
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
use shared_lock::StylesheetGuards;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError};
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
#[cfg(feature = "servo")] use values::Either;
use values::generics::text::LineHeight;
@ -185,6 +187,7 @@ macro_rules! unwrap_or_initial {
pub mod shorthands {
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseError};
use values::specified;
<%include file="/shorthand/serialize.mako.rs" />
@ -213,9 +216,11 @@ pub mod shorthands {
use parser::ParserContext;
use properties::{SourcePropertyDeclaration, AllShorthand, ShorthandId, UnparsedValue};
use stylearc::Arc;
use style_traits::{ParseError, StyleParseError};
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
// This function is like the parse() that is generated by
// helpers:shorthand, but since the only values for the 'all'
// shorthand when not just a single CSS-wide keyword is one
@ -239,7 +244,7 @@ pub mod shorthands {
}));
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
}
@ -414,6 +419,7 @@ impl PropertyDeclarationIdSet {
{
f(&
::custom_properties::substitute(css, first_token_type, custom_properties)
.ok()
.and_then(|css| {
// As of this writing, only the base URL is used for property values:
//
@ -425,7 +431,8 @@ impl PropertyDeclarationIdSet {
None,
PARSING_MODE_DEFAULT,
quirks_mode);
Parser::new(&css).parse_entirely(|input| {
let mut input = ParserInput::new(&css);
Parser::new(&mut input).parse_entirely(|input| {
match from_shorthand {
None => {
longhands::${property.ident}
@ -434,7 +441,7 @@ impl PropertyDeclarationIdSet {
Some(ShorthandId::All) => {
// No need to parse the 'all' shorthand as anything other than a CSS-wide
// keyword, after variable substitution.
Err(())
Err(SelectorParseError::UnexpectedIdent("all".into()).into())
}
% for shorthand in data.shorthands_except_all():
% if property in shorthand.sub_properties:
@ -448,7 +455,7 @@ impl PropertyDeclarationIdSet {
% endfor
_ => unreachable!()
}
})
}).ok()
})
.unwrap_or(
// Invalid at computed-value time.
@ -500,10 +507,11 @@ impl CSSWideKeyword {
}
impl Parse for CSSWideKeyword {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
input.expect_exhausted()?;
CSSWideKeyword::from_ident(&ident).ok_or(())
CSSWideKeyword::from_ident(&ident)
.ok_or(SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -946,7 +954,7 @@ impl PropertyId {
/// Returns a given property from the string `s`.
///
/// Returns Err(()) for unknown non-custom properties
pub fn parse(property_name: Cow<str>) -> Result<Self, ()> {
pub fn parse<'i>(property_name: Cow<'i, str>) -> Result<Self, ParseError<'i>> {
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
}
@ -971,7 +979,7 @@ impl PropertyId {
match static_id(&property_name) {
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
None => Err(()),
None => Err(SelectorParseError::UnexpectedIdent(property_name).into()),
}
}
@ -1095,24 +1103,6 @@ impl HasViewportPercentage for PropertyDeclaration {
}
}
/// The result of parsing a property declaration.
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum PropertyDeclarationParseError {
/// The property declaration was for an unknown property.
UnknownProperty,
/// The property declaration was for a disabled experimental property.
ExperimentalProperty,
/// The property declaration contained an invalid value.
InvalidValue,
/// The declaration contained an animation property, and we were parsing
/// this as a keyframe block (so that property should be ignored).
///
/// See: https://drafts.csswg.org/css-animations/#keyframes
AnimationPropertyInKeyframeBlock,
/// The property is not allowed within a page rule.
NotAllowedInPageRule,
}
impl fmt::Debug for PropertyDeclaration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(self.id().to_css(f));
@ -1407,9 +1397,9 @@ impl PropertyDeclaration {
PropertyId::Custom(name) => {
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword),
Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) {
Err(_) => match ::custom_properties::SpecifiedValue::parse(context, input) {
Ok(value) => DeclaredValueOwned::Value(value),
Err(()) => return Err(PropertyDeclarationParseError::InvalidValue),
Err(_) => return Err(PropertyDeclarationParseError::InvalidValue),
}
};
declarations.push(PropertyDeclaration::Custom(name, value));
@ -1442,7 +1432,7 @@ impl PropertyDeclaration {
declarations.push(value);
Ok(())
},
Err(()) => Err(PropertyDeclarationParseError::InvalidValue),
Err(_) => Err(PropertyDeclarationParseError::InvalidValue),
}
% else:
Err(PropertyDeclarationParseError::UnknownProperty)
@ -1485,9 +1475,9 @@ impl PropertyDeclaration {
% endif
Ok(())
},
Err(()) => {
Err(_) => {
shorthands::${shorthand.ident}::parse_into(declarations, context, input)
.map_err(|()| PropertyDeclarationParseError::InvalidValue)
.map_err(|_| PropertyDeclarationParseError::InvalidValue)
}
}
}

View file

@ -32,7 +32,8 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut background_color = None;
% for name in "image position_x position_y repeat size attachment origin clip".split():
@ -42,7 +43,7 @@
// background-color can only be in the last element, so if it
// is parsed anywhere before, the value is invalid.
if background_color.is_some() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
% for name in "image position repeat size attachment origin clip".split():
@ -107,7 +108,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
@ -194,7 +195,8 @@
use values::specified::AllowQuirks;
use values::specified::position::Position;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut position_x = background_position_x::SpecifiedValue(Vec::new());
let mut position_y = background_position_y::SpecifiedValue(Vec::new());
let mut any = false;
@ -207,7 +209,7 @@
Ok(())
})?;
if !any {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

View file

@ -20,7 +20,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
use values::generics::rect::Rect;
use values::specified::{AllowQuirks, BorderSideWidth};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let rect = Rect::parse_with(context, input, |_, i| {
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
})?;
@ -43,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
</%helpers:shorthand>
pub fn parse_border(context: &ParserContext, input: &mut Parser)
-> Result<(specified::Color,
specified::BorderStyle,
specified::BorderSideWidth), ()> {
pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(specified::Color,
specified::BorderStyle,
specified::BorderSideWidth), ParseError<'i>> {
use values::specified::{Color, BorderStyle, BorderSideWidth};
let _unused = context;
let mut color = None;
@ -82,7 +83,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
style.unwrap_or(BorderStyle::none),
width.unwrap_or(BorderSideWidth::Medium)))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -101,7 +102,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
alias="${maybe_moz_logical_alias(product, (side, logical), '-moz-border-%s')}"
spec="${spec}">
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let (color, style, width) = try!(super::parse_border(context, input));
Ok(expanded! {
border_${to_rust_ident(side)}_color: color,
@ -139,7 +141,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
_moz_border_bottom_colors, _moz_border_left_colors};
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
use properties::longhands::{border_image_source, border_image_width};
@ -209,7 +212,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
use values::specified::border::BorderRadius;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let radii = try!(BorderRadius::parse(context, input));
Ok(expanded! {
border_top_left_radius: radii.top_left,
@ -242,12 +246,13 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
use properties::longhands::{border_image_source, border_image_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "outset repeat slice source width".split():
let mut border_image_${name} = border_image_${name}::get_initial_specified_value();
% endfor
try!(input.try(|input| {
let result: Result<_, ParseError> = input.try(|input| {
% for name in "outset repeat slice source width".split():
let mut ${name} = None;
% endfor
@ -256,7 +261,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
if let Ok(value) = input.try(|input| border_image_slice::parse(context, input)) {
slice = Some(value);
// Parse border image width and outset, if applicable.
let maybe_width_outset: Result<_, ()> = input.try(|input| {
let maybe_width_outset: Result<_, ParseError> = input.try(|input| {
try!(input.expect_delim('/'));
// Parse border image width, if applicable.
@ -269,7 +274,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
border_image_outset::parse(context, input)
}).ok();
if w.is_none() && o.is_none() {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
else {
Ok((w, o))
@ -305,9 +310,10 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
});
try!(result);
Ok(expanded! {
% for name in "outset repeat slice source width".split():

View file

@ -11,29 +11,33 @@
use properties::longhands::overflow_x::SpecifiedValue;
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% if product == "gecko":
let moz_kw_found = input.try(|i| match_ignore_ascii_case! {
&i.expect_ident()?,
"-moz-scrollbars-horizontal" => {
Ok(expanded! {
overflow_x: SpecifiedValue::scroll,
overflow_y: SpecifiedValue::hidden,
})
}
"-moz-scrollbars-vertical" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::scroll,
})
}
"-moz-scrollbars-none" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::hidden,
})
}
_ => Err(())
let moz_kw_found = input.try(|i| {
let ident = i.expect_ident()?;
(match_ignore_ascii_case! {
&ident,
"-moz-scrollbars-horizontal" => {
Ok(expanded! {
overflow_x: SpecifiedValue::scroll,
overflow_y: SpecifiedValue::hidden,
})
}
"-moz-scrollbars-vertical" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::scroll,
})
}
"-moz-scrollbars-none" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::hidden,
})
}
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
});
if moz_kw_found.is_ok() {
return moz_kw_found
@ -88,14 +92,16 @@ macro_rules! try_parse_one {
use properties::longhands::transition_${prop};
% endfor
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
struct SingleTransition {
% for prop in "property duration timing_function delay".split():
transition_${prop}: transition_${prop}::SingleSpecifiedValue,
% endfor
}
fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
fn parse_one_transition<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SingleTransition,ParseError<'i>> {
% for prop in "property duration timing_function delay".split():
let mut ${prop} = None;
% endfor
@ -123,7 +129,7 @@ macro_rules! try_parse_one {
% endfor
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -202,14 +208,16 @@ macro_rules! try_parse_one {
use properties::longhands::animation_${prop};
% endfor
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
struct SingleAnimation {
% for prop in props:
animation_${prop}: animation_${prop}::SingleSpecifiedValue,
% endfor
}
fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
fn parse_one_animation<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SingleAnimation,ParseError<'i>> {
% for prop in props:
let mut ${prop} = None;
% endfor
@ -237,7 +245,7 @@ macro_rules! try_parse_one {
// If nothing is parsed, this is an invalid entry.
if parsed == 0 {
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(SingleAnimation {
% for prop in props:
@ -303,7 +311,8 @@ macro_rules! try_parse_one {
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
use properties::longhands::scroll_snap_type_x;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let result = try!(scroll_snap_type_x::parse(context, input));
Ok(expanded! {
scroll_snap_type_x: result,
@ -331,7 +340,8 @@ macro_rules! try_parse_one {
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
use properties::longhands::transform;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
Ok(expanded! {
transform: transform::parse_prefixed(context, input)?,
})

View file

@ -8,7 +8,8 @@
extra_prefixes="moz" spec="https://drafts.csswg.org/css-multicol/#propdef-columns">
use properties::longhands::{column_count, column_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut column_count = None;
let mut column_width = None;
@ -40,7 +41,7 @@
let values = autos + column_count.iter().len() + column_width.iter().len();
if values == 0 || values > 2 {
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(expanded! {
column_count: unwrap_or_initial!(column_count),
@ -65,7 +66,8 @@
use properties::longhands::{column_rule_width, column_rule_style};
use properties::longhands::column_rule_color;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "width style color".split():
let mut column_rule_${name} = None;
% endfor
@ -92,7 +94,7 @@
column_rule_color: unwrap_or_initial!(column_rule_color),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}

View file

@ -38,7 +38,8 @@
% endif
use self::font_family::SpecifiedValue as FontFamily;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut nb_normals = 0;
let mut style = None;
let mut variant_caps = None;
@ -97,7 +98,7 @@
}
if size.is_none() ||
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
Some(try!(LineHeight::parse(context, input)))
@ -239,7 +240,8 @@
% endfor
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut nb_normals = 0;
let mut caps = None;
loop {
@ -264,7 +266,7 @@
}
let count = count(&caps) + nb_normals;
if count == 0 || count > 1 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),

View file

@ -9,7 +9,8 @@
spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
use values::specified::UrlOrNone;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
use parser::Parse;
let url = UrlOrNone::parse(context, input)?;

View file

@ -9,7 +9,8 @@
spec="https://drafts.csswg.org/css-text-decor-3/#text-emphasis-property">
use properties::longhands::{text_emphasis_color, text_emphasis_style};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut color = None;
let mut style = None;
@ -34,7 +35,7 @@
text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -56,7 +57,8 @@
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut color = None;
let mut width = None;
loop {
@ -82,7 +84,7 @@
_webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}

View file

@ -10,7 +10,8 @@
use properties::longhands::{list_style_image, list_style_position, list_style_type};
use values::{Either, None_};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
// `none` is ambiguous until we've finished parsing the shorthands, so we count the number
// of times we see it.
let mut nones = 0u8;
@ -19,7 +20,7 @@
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
nones = nones + 1;
if nones > 2 {
return Err(())
return Err(SelectorParseError::UnexpectedIdent("none".into()).into())
}
any = true;
continue
@ -104,7 +105,7 @@
list_style_type: unwrap_or_initial!(list_style_type),
})
}
_ => Err(()),
_ => Err(StyleParseError::UnspecifiedError.into()),
}
}

View file

@ -35,7 +35,8 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "image mode position_x position_y size repeat origin clip composite".split():
let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new());
% endfor
@ -103,7 +104,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
@ -180,7 +181,8 @@
use values::specified::position::Position;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut position_x = mask_position_x::SpecifiedValue(Vec::new());
let mut position_y = mask_position_y::SpecifiedValue(Vec::new());
let mut any = false;
@ -193,7 +195,7 @@
Ok(())
})?;
if any == false {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

View file

@ -10,7 +10,8 @@
use values::specified;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let _unused = context;
let mut color = None;
let mut style = None;
@ -47,7 +48,7 @@
outline_width: unwrap_or_initial!(outline_width, width),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -71,7 +72,8 @@
use values::specified::border::BorderRadius;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let radii = try!(BorderRadius::parse(context, input));
Ok(expanded! {
_moz_outline_radius_topleft: radii.top_left,

View file

@ -8,7 +8,8 @@
spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
use properties::longhands::{flex_direction, flex_wrap};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut direction = None;
let mut wrap = None;
loop {
@ -28,7 +29,7 @@
}
if direction.is_none() && wrap.is_none() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
flex_direction: unwrap_or_initial!(flex_direction, direction),
@ -50,14 +51,15 @@
spec="https://drafts.csswg.org/css-flexbox/#flex-property">
use values::specified::Number;
fn parse_flexibility(context: &ParserContext, input: &mut Parser)
-> Result<(Number, Option<Number>),()> {
fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(Number, Option<Number>),ParseError<'i>> {
let grow = try!(Number::parse_non_negative(context, input));
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
Ok((grow, shrink))
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut grow = None;
let mut shrink = None;
let mut basis = None;
@ -87,7 +89,7 @@
}
if grow.is_none() && basis.is_none() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
flex_grow: grow.unwrap_or(Number::new(1.0)),
@ -118,7 +120,8 @@
products="gecko">
use properties::longhands::{grid_row_gap, grid_column_gap};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let row_gap = grid_row_gap::parse(context, input)?;
let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());
@ -152,7 +155,8 @@
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
// the other. This might not be a big deal for now, but we should consider looking into this in the future
// to limit the amount of code generated.
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let start = input.try(|i| GridLine::parse(context, i))?;
let end = if input.try(|i| i.expect_delim('/')).is_ok() {
GridLine::parse(context, input)?
@ -189,7 +193,8 @@
use parser::Parse;
// The code is the same as `grid-{row,column}` except that this can have four values at most.
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
fn line_with_ident_from(other: &GridLine) -> GridLine {
let mut this = GridLine::default();
if other.line_num.is_none() && !other.is_span {
@ -259,8 +264,9 @@
use values::specified::grid::parse_line_names;
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
pub fn parse_grid_template(context: &ParserContext, input: &mut Parser)
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>), ()> {
pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>),
ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_)))
}
@ -295,7 +301,8 @@
line_names.push(vec![]); // should be one longer than track sizes
}
let template_areas = TemplateAreas::from_vec(strings)?;
let template_areas = TemplateAreas::from_vec(strings)
.map_err(|()| StyleParseError::UnspecifiedError)?;
let template_rows = TrackList {
list_type: TrackListType::Normal,
values: values,
@ -306,7 +313,7 @@
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
let track_list = TrackList::parse(context, input)?;
if track_list.list_type != TrackListType::Explicit {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Either::First(track_list)
@ -326,7 +333,8 @@
}
#[inline]
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let (rows, columns, areas) = parse_grid_template(context, input)?;
Ok(expanded! {
grid_template_rows: rows,
@ -410,7 +418,8 @@
use values::{Either, None_};
use values::specified::{LengthOrPercentage, TrackSize};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut temp_rows = Either::Second(None_);
let mut temp_cols = Either::Second(None_);
let mut temp_areas = Either::Second(None_);
@ -418,7 +427,8 @@
let mut auto_cols = TrackSize::default();
let mut flow = grid_auto_flow::get_initial_value();
fn parse_auto_flow(input: &mut Parser, is_row: bool) -> Result<SpecifiedAutoFlow, ()> {
fn parse_auto_flow<'i, 't>(input: &mut Parser<'i, 't>, is_row: bool)
-> Result<SpecifiedAutoFlow, ParseError<'i>> {
let mut auto_flow = None;
let mut dense = false;
for _ in 0..2 {
@ -440,7 +450,7 @@
autoflow: flow,
dense: dense,
}
}).ok_or(())
}).ok_or(StyleParseError::UnspecifiedError.into())
}
if let Ok((rows, cols, areas)) = input.try(|i| super::grid_template::parse_grid_template(context, i)) {
@ -506,15 +516,16 @@
use properties::longhands::align_content;
use properties::longhands::justify_content;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = align_content::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| justify_content::parse(context, input))
.unwrap_or(justify_content::SpecifiedValue::from(align));
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {
@ -541,14 +552,15 @@
use values::specified::align::AlignJustifySelf;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = AlignJustifySelf::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {
@ -582,15 +594,16 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = AlignItems::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| JustifyItems::parse(context, input))
.unwrap_or(JustifyItems::from(align));
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

View file

@ -16,7 +16,8 @@
use properties::longhands::text_decoration_line;
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% if product == "gecko" or data.testing:
let (mut line, mut style, mut color, mut any) = (None, None, None, false);
% else:
@ -47,7 +48,7 @@
}
if !any {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {