@@ -51,6 +51,11 @@ pub trait DeclarationParser<'i> {
51
51
name : CowRcStr < ' i > ,
52
52
input : & mut Parser < ' i , ' t > ,
53
53
) -> Result < Self :: Declaration , ParseError < ' i , Self :: Error > > ;
54
+
55
+ /// Whether to try to parse a qualified rule after a declaration fails to parse. This is useful
56
+ /// for CSS nesting. See <https://github.com/w3c/csswg-drafts/issues/7961> for the current
57
+ /// state of the discussion. This is a low effort opt-in to be able to experiment with it.
58
+ fn enable_nesting ( & self ) -> bool { false }
54
59
}
55
60
56
61
/// A trait to provide various parsing of at-rules.
@@ -231,7 +236,9 @@ where
231
236
/// or `Err(())` for an invalid one.
232
237
impl < ' i , ' t , ' a , I , P , E : ' i > Iterator for DeclarationListParser < ' i , ' t , ' a , P >
233
238
where
234
- P : DeclarationParser < ' i , Declaration = I , Error = E > + AtRuleParser < ' i , AtRule = I , Error = E > ,
239
+ P : DeclarationParser < ' i , Declaration = I , Error = E >
240
+ + AtRuleParser < ' i , AtRule = I , Error = E >
241
+ + QualifiedRuleParser < ' i , QualifiedRule = I , Error = E > ,
235
242
{
236
243
type Item = Result < I , ( ParseError < ' i , E > , & ' i str ) > ;
237
244
@@ -244,24 +251,37 @@ where
244
251
}
245
252
Ok ( & Token :: Ident ( ref name) ) => {
246
253
let name = name. clone ( ) ;
247
- let result = {
254
+ let mut result = {
248
255
let parser = & mut self . parser ;
249
256
parse_until_after ( self . input , Delimiter :: Semicolon , |input| {
250
257
input. expect_colon ( ) ?;
251
258
parser. parse_value ( name, input)
252
259
} )
253
260
} ;
261
+
262
+ if result. is_err ( ) && self . parser . enable_nesting ( ) {
263
+ self . input . reset ( & start) ;
264
+ result = parse_qualified_rule ( & start, self . input , & mut self . parser ) ;
265
+ }
266
+
254
267
return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
255
268
}
256
269
Ok ( & Token :: AtKeyword ( ref name) ) => {
257
270
let name = name. clone ( ) ;
258
271
return Some ( parse_at_rule ( & start, name, self . input , & mut self . parser ) ) ;
259
272
}
260
273
Ok ( token) => {
261
- let token = token. clone ( ) ;
262
- let result = self . input . parse_until_after ( Delimiter :: Semicolon , |_| {
263
- Err ( start. source_location ( ) . new_unexpected_token_error ( token) )
264
- } ) ;
274
+ let result = if self . parser . enable_nesting ( ) {
275
+ self . input . reset ( & start) ;
276
+ // XXX do we need to, if we fail, consume only until the next semicolon,
277
+ // rather than until the next `{`?
278
+ parse_qualified_rule ( & start, self . input , & mut self . parser )
279
+ } else {
280
+ let token = token. clone ( ) ;
281
+ self . input . parse_until_after ( Delimiter :: Semicolon , |_| {
282
+ Err ( start. source_location ( ) . new_unexpected_token_error ( token) )
283
+ } )
284
+ } ;
265
285
return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
266
286
}
267
287
Err ( ..) => return None ,
@@ -367,7 +387,7 @@ where
367
387
}
368
388
} else {
369
389
self . any_rule_so_far = true ;
370
- let result = parse_qualified_rule ( self . input , & mut self . parser ) ;
390
+ let result = parse_qualified_rule ( & start , self . input , & mut self . parser ) ;
371
391
return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
372
392
}
373
393
}
@@ -419,7 +439,7 @@ where
419
439
if let Some ( name) = at_keyword {
420
440
parse_at_rule ( & start, name, input, parser) . map_err ( |e| e. 0 )
421
441
} else {
422
- parse_qualified_rule ( input, parser)
442
+ parse_qualified_rule ( & start , input, parser)
423
443
}
424
444
} )
425
445
}
@@ -460,13 +480,13 @@ where
460
480
}
461
481
462
482
fn parse_qualified_rule < ' i , ' t , P , E > (
483
+ start : & ParserState ,
463
484
input : & mut Parser < ' i , ' t > ,
464
485
parser : & mut P ,
465
486
) -> Result < <P as QualifiedRuleParser < ' i > >:: QualifiedRule , ParseError < ' i , E > >
466
487
where
467
488
P : QualifiedRuleParser < ' i , Error = E > ,
468
489
{
469
- let start = input. state ( ) ;
470
490
let prelude = parse_until_before ( input, Delimiter :: CurlyBracketBlock , |input| {
471
491
parser. parse_prelude ( input)
472
492
} ) ;
0 commit comments