44
55// https://drafts.csswg.org/css-syntax/#parsing
66
7- use super :: { BasicParseError , BasicParseErrorKind , Delimiter , Delimiters , ParseError , Parser , Token } ;
7+ use super :: {
8+ BasicParseError , BasicParseErrorKind , Delimiter , Delimiters , ParseError , Parser , Token ,
9+ } ;
810use crate :: cow_rc_str:: CowRcStr ;
911use crate :: parser:: { parse_nested_block, parse_until_after, parse_until_before, ParserState } ;
1012
@@ -239,8 +241,7 @@ impl<'i, 't, 'a, P, I, E> RuleBodyParser<'i, 't, 'a, P, I, E> {
239241 }
240242}
241243
242- /// `DeclarationListParser` is an iterator that yields `Ok(_)` for a valid declaration or at-rule
243- /// or `Err(())` for an invalid one.
244+ /// https://drafts.csswg.org/css-syntax/#consume-a-blocks-contents
244245impl < ' i , ' t , ' a , I , P , E : ' i > Iterator for RuleBodyParser < ' i , ' t , ' a , P , I , E >
245246where
246247 P : RuleBodyItemParser < ' i , I , E > ,
@@ -252,47 +253,51 @@ where
252253 self . input . skip_whitespace ( ) ;
253254 let start = self . input . state ( ) ;
254255 match self . input . next_including_whitespace_and_comments ( ) . ok ( ) ? {
256+ Token :: CloseCurlyBracket |
257+ Token :: WhiteSpace ( ..) |
258+ Token :: Semicolon |
255259 Token :: Comment ( ..) => continue ,
256- Token :: Semicolon if self . parser . parse_declarations ( ) => continue ,
260+ Token :: AtKeyword ( ref name) => {
261+ let name = name. clone ( ) ;
262+ return Some ( parse_at_rule ( & start, name, self . input , & mut * self . parser ) ) ;
263+ }
264+ // https://drafts.csswg.org/css-syntax/#consume-a-declaration bails out just to
265+ // keep parsing as a qualified rule if the token is not an ident, so we implement
266+ // that in a slightly more straight-forward way
257267 Token :: Ident ( ref name) if self . parser . parse_declarations ( ) => {
258268 let name = name. clone ( ) ;
259- let parse_qualified = self . parser . parse_qualified ( ) ;
260- let delimiters = if parse_qualified {
261- Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock
262- } else {
263- Delimiter :: Semicolon
264- } ;
265- let mut result = {
269+ let result = {
266270 let parser = & mut self . parser ;
267- parse_until_after ( self . input , delimiters , |input| {
271+ parse_until_after ( self . input , Delimiter :: Semicolon , |input| {
268272 input. expect_colon ( ) ?;
269273 parser. parse_value ( name, input)
270274 } )
271275 } ;
272-
273- if result. is_err ( ) && parse_qualified {
276+ if result. is_err ( ) && self . parser . parse_qualified ( ) {
274277 self . input . reset ( & start) ;
275- result =
276- parse_qualified_rule ( & start, self . input , & mut * self . parser , delimiters) ;
278+ // We ignore the resulting error here. The property declaration parse error
279+ // is likely to be more relevant.
280+ if let Ok ( qual) = parse_qualified_rule (
281+ & start,
282+ self . input ,
283+ & mut * self . parser ,
284+ Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock ,
285+ ) {
286+ return Some ( Ok ( qual) )
287+ }
277288 }
278289
279290 return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
280291 }
281- Token :: AtKeyword ( ref name) => {
282- let name = name. clone ( ) ;
283- return Some ( parse_at_rule ( & start, name, self . input , & mut * self . parser ) ) ;
284- }
285292 token => {
286293 let result = if self . parser . parse_qualified ( ) {
287294 self . input . reset ( & start) ;
288- // TODO(emilio, nesting): do we need to, if we fail, consume only until the
289- // next semicolon, rather than until the next `{`?
290- parse_qualified_rule (
291- & start,
292- self . input ,
293- & mut * self . parser ,
294- Delimiter :: CurlyBracketBlock ,
295- )
295+ let delimiters = if self . parser . parse_declarations ( ) {
296+ Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock
297+ } else {
298+ Delimiter :: CurlyBracketBlock
299+ } ;
300+ parse_qualified_rule ( & start, self . input , & mut * self . parser , delimiters)
296301 } else {
297302 let token = token. clone ( ) ;
298303 self . input . parse_until_after ( Delimiter :: Semicolon , |_| {
0 commit comments