Skip to content

Commit 00b102e

Browse files
committed
nesting: Introduce an opt-in into nesting.
1 parent 20be7cc commit 00b102e

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

src/rules_and_declarations.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ pub trait DeclarationParser<'i> {
5151
name: CowRcStr<'i>,
5252
input: &mut Parser<'i, 't>,
5353
) -> 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 }
5459
}
5560

5661
/// A trait to provide various parsing of at-rules.
@@ -231,7 +236,9 @@ where
231236
/// or `Err(())` for an invalid one.
232237
impl<'i, 't, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P>
233238
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>,
235242
{
236243
type Item = Result<I, (ParseError<'i, E>, &'i str)>;
237244

@@ -244,24 +251,37 @@ where
244251
}
245252
Ok(&Token::Ident(ref name)) => {
246253
let name = name.clone();
247-
let result = {
254+
let mut result = {
248255
let parser = &mut self.parser;
249256
parse_until_after(self.input, Delimiter::Semicolon, |input| {
250257
input.expect_colon()?;
251258
parser.parse_value(name, input)
252259
})
253260
};
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+
254267
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
255268
}
256269
Ok(&Token::AtKeyword(ref name)) => {
257270
let name = name.clone();
258271
return Some(parse_at_rule(&start, name, self.input, &mut self.parser));
259272
}
260273
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+
};
265285
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
266286
}
267287
Err(..) => return None,
@@ -367,7 +387,7 @@ where
367387
}
368388
} else {
369389
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);
371391
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
372392
}
373393
}
@@ -419,7 +439,7 @@ where
419439
if let Some(name) = at_keyword {
420440
parse_at_rule(&start, name, input, parser).map_err(|e| e.0)
421441
} else {
422-
parse_qualified_rule(input, parser)
442+
parse_qualified_rule(&start, input, parser)
423443
}
424444
})
425445
}
@@ -460,13 +480,13 @@ where
460480
}
461481

462482
fn parse_qualified_rule<'i, 't, P, E>(
483+
start: &ParserState,
463484
input: &mut Parser<'i, 't>,
464485
parser: &mut P,
465486
) -> Result<<P as QualifiedRuleParser<'i>>::QualifiedRule, ParseError<'i, E>>
466487
where
467488
P: QualifiedRuleParser<'i, Error = E>,
468489
{
469-
let start = input.state();
470490
let prelude = parse_until_before(input, Delimiter::CurlyBracketBlock, |input| {
471491
parser.parse_prelude(input)
472492
});

0 commit comments

Comments
 (0)