Skip to content

Commit

Permalink
fix(css/parser): nested rule parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Dec 1, 2022
1 parent 9287709 commit 4555fed
Show file tree
Hide file tree
Showing 8 changed files with 559 additions and 31 deletions.
28 changes: 5 additions & 23 deletions crates/swc_css_parser/src/parser/at_rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,6 @@ where
}
_ => {
let ctx = Ctx {
is_top_level: false,
in_container_at_rule: true,
..self.ctx
};
Expand Down Expand Up @@ -493,11 +492,7 @@ where
style_blocks
}
_ => {
let ctx = Ctx {
is_top_level: false,
..self.ctx
};
let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
let rule_list = self.parse_as::<Vec<Rule>>()?;
let rule_list: Vec<ComponentValue> =
rule_list.into_iter().map(ComponentValue::Rule).collect();

Expand Down Expand Up @@ -565,7 +560,6 @@ where
| js_word!("-ms-keyframes") => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::RuleList,
is_top_level: false,
in_keyframes_at_rule: true,
..self.ctx
};
Expand Down Expand Up @@ -636,11 +630,7 @@ where
rule_list
}
js_word!("layer") => {
let ctx = Ctx {
is_top_level: false,
..self.ctx
};
let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
let rule_list = self.parse_as::<Vec<Rule>>()?;
let rule_list: Vec<ComponentValue> =
rule_list.into_iter().map(ComponentValue::Rule).collect();

Expand All @@ -657,11 +647,7 @@ where
style_blocks
}
_ => {
let ctx = Ctx {
is_top_level: false,
..self.ctx
};
let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
let rule_list = self.parse_as::<Vec<Rule>>()?;
let rule_list: Vec<ComponentValue> =
rule_list.into_iter().map(ComponentValue::Rule).collect();

Expand Down Expand Up @@ -742,11 +728,7 @@ where
style_blocks
}
_ => {
let ctx = Ctx {
is_top_level: false,
..self.ctx
};
let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
let rule_list = self.parse_as::<Vec<Rule>>()?;
let rule_list: Vec<ComponentValue> =
rule_list.into_iter().map(ComponentValue::Rule).collect();

Expand Down Expand Up @@ -934,7 +916,7 @@ where

return Err(Error::new(
span,
ErrorKind::Expected("ident or percentage token"),
ErrorKind::Expected("'from', 'to' or percentage"),
));
}
}
Expand Down
24 changes: 20 additions & 4 deletions crates/swc_css_parser/src/parser/syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ where
let mut rules = vec![];

// Repeatedly consume the next input token:

// Reset the `is_top_level` value
let ctx = Ctx {
is_top_level: false,
..self.ctx
};
loop {
// <EOF-token>
// Return the list of rules.
Expand All @@ -70,21 +76,28 @@ where
// Otherwise, reconsume the current input token. Consume a qualified rule. If
// anything is returned, append it to the list of rules.
else {
rules.push(Rule::QualifiedRule(self.parse()?));
let qualified_rule = self.with_ctx(ctx).parse_as::<Box<QualifiedRule>>()?;

rules.push(Rule::QualifiedRule(qualified_rule));
}
}
// <at-keyword-token>
// Reconsume the current input token. Consume an at-rule, and append the returned
// value to the list of rules.
tok!("@") => {
rules.push(Rule::AtRule(self.parse()?));
let at_rule = self.with_ctx(ctx).parse_as::<Box<AtRule>>()?;

rules.push(Rule::AtRule(at_rule));
}
// anything else
// Reconsume the current input token. Consume a qualified rule. If anything is
// returned, append it to the list of rules.
//
// For better recovery we parse broken code into the list of component values and
// append it to the list of rules.
_ => {
let state = self.input.state();
let qualified_rule = self.parse();
let qualified_rule = self.with_ctx(ctx).parse_as::<Box<QualifiedRule>>();

match qualified_rule {
Ok(i) => rules.push(Rule::QualifiedRule(i)),
Expand All @@ -99,7 +112,8 @@ where
};

while !is_one_of!(self, EOF) {
let component_value = self.parse_as::<ComponentValue>()?;
let component_value =
self.with_ctx(ctx).parse_as::<ComponentValue>()?;

list_of_component_values.children.push(component_value);
}
Expand All @@ -122,6 +136,8 @@ where
I: ParserInput,
{
fn parse(&mut self) -> PResult<AtRule> {
println!("TOP LEVEL {:?}", self.ctx.is_top_level);

// To consume an at-rule:

// Consume the next input token. Create a new at-rule with its name set to the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

x Expected ident or percentage token
x Expected 'from', 'to' or percentage
,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1]
1 | @keyframes foo {
2 | 10 {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

x Expected ident or percentage token
x Expected 'from', 'to' or percentage
,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:1:1]
1 | @keyframes foo {
2 | 10 {
Expand Down
6 changes: 6 additions & 0 deletions crates/swc_css_parser/tests/recovery/cdo-and-cdc/input.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ a {
color: red;
}
}

@keyframes box {
<!-- -->
50% { left: 0; }
90% { left: 300px; }
}

0 comments on commit 4555fed

Please sign in to comment.