Skip to content

Commit 3e1bd05

Browse files
authored
Auto merge of #333 - servo:nesting, r=tiaanl
[css-nesting] Trivial-ish nesting API changes. The API change is needed regardless (we need a declaration parser that also parses qualified rules). The implementation details are a bit subject to change so make it opt-in.
2 parents 05c4e05 + 2546cfa commit 3e1bd05

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cssparser"
3-
version = "0.30.0"
3+
version = "0.31.0"
44
authors = [ "Simon Sapin <[email protected]>" ]
55

66
description = "Rust implementation of CSS Syntax Level 3"

src/rules_and_declarations.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ 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 qualified rules along with declarations. See
56+
/// <https://github.com/w3c/csswg-drafts/issues/7961> for the current state of the discussion.
57+
/// This is a low effort opt-in to be able to experiment with it, but it's likely to be needed
58+
/// when nesting is less experimental as well (e.g., you probably don't want to allow nesting
59+
/// in a style attribute anyways).
60+
fn enable_nesting(&self) -> bool { false }
5461
}
5562

5663
/// A trait to provide various parsing of at-rules.
@@ -231,7 +238,9 @@ where
231238
/// or `Err(())` for an invalid one.
232239
impl<'i, 't, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P>
233240
where
234-
P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>,
241+
P: DeclarationParser<'i, Declaration = I, Error = E>
242+
+ AtRuleParser<'i, AtRule = I, Error = E>
243+
+ QualifiedRuleParser<'i, QualifiedRule = I, Error = E>,
235244
{
236245
type Item = Result<I, (ParseError<'i, E>, &'i str)>;
237246

@@ -244,24 +253,37 @@ where
244253
}
245254
Ok(&Token::Ident(ref name)) => {
246255
let name = name.clone();
247-
let result = {
256+
let mut result = {
248257
let parser = &mut self.parser;
249258
parse_until_after(self.input, Delimiter::Semicolon, |input| {
250259
input.expect_colon()?;
251260
parser.parse_value(name, input)
252261
})
253262
};
263+
264+
if result.is_err() && self.parser.enable_nesting() {
265+
self.input.reset(&start);
266+
result = parse_qualified_rule(&start, self.input, &mut self.parser);
267+
}
268+
254269
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
255270
}
256271
Ok(&Token::AtKeyword(ref name)) => {
257272
let name = name.clone();
258273
return Some(parse_at_rule(&start, name, self.input, &mut self.parser));
259274
}
260275
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-
});
276+
let result = if self.parser.enable_nesting() {
277+
self.input.reset(&start);
278+
// XXX do we need to, if we fail, consume only until the next semicolon,
279+
// rather than until the next `{`?
280+
parse_qualified_rule(&start, self.input, &mut self.parser)
281+
} else {
282+
let token = token.clone();
283+
self.input.parse_until_after(Delimiter::Semicolon, |_| {
284+
Err(start.source_location().new_unexpected_token_error(token))
285+
})
286+
};
265287
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
266288
}
267289
Err(..) => return None,
@@ -367,7 +389,7 @@ where
367389
}
368390
} else {
369391
self.any_rule_so_far = true;
370-
let result = parse_qualified_rule(self.input, &mut self.parser);
392+
let result = parse_qualified_rule(&start, self.input, &mut self.parser);
371393
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
372394
}
373395
}
@@ -419,7 +441,7 @@ where
419441
if let Some(name) = at_keyword {
420442
parse_at_rule(&start, name, input, parser).map_err(|e| e.0)
421443
} else {
422-
parse_qualified_rule(input, parser)
444+
parse_qualified_rule(&start, input, parser)
423445
}
424446
})
425447
}
@@ -460,13 +482,13 @@ where
460482
}
461483

462484
fn parse_qualified_rule<'i, 't, P, E>(
485+
start: &ParserState,
463486
input: &mut Parser<'i, 't>,
464487
parser: &mut P,
465488
) -> Result<<P as QualifiedRuleParser<'i>>::QualifiedRule, ParseError<'i, E>>
466489
where
467490
P: QualifiedRuleParser<'i, Error = E>,
468491
{
469-
let start = input.state();
470492
let prelude = parse_until_before(input, Delimiter::CurlyBracketBlock, |input| {
471493
parser.parse_prelude(input)
472494
});

0 commit comments

Comments
 (0)