implement @if/@else
This commit is contained in:
parent
1127897bd8
commit
f1238c4d3a
@ -32,6 +32,7 @@ pub(crate) enum AtRule {
|
|||||||
Content,
|
Content,
|
||||||
Unknown(UnknownAtRule),
|
Unknown(UnknownAtRule),
|
||||||
For(Vec<Stmt>),
|
For(Vec<Stmt>),
|
||||||
|
If(Vec<Token>, Vec<Stmt>, Vec<Stmt>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtRule {
|
impl AtRule {
|
||||||
@ -104,7 +105,46 @@ impl AtRule {
|
|||||||
}
|
}
|
||||||
AtRuleKind::Each => todo!("@each not yet implemented"),
|
AtRuleKind::Each => todo!("@each not yet implemented"),
|
||||||
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
||||||
AtRuleKind::If => todo!("@if not yet implemented"),
|
AtRuleKind::If => {
|
||||||
|
let mut cond = Vec::new();
|
||||||
|
let mut n = 0;
|
||||||
|
while let Some(tok) = toks.peek() {
|
||||||
|
match tok.kind {
|
||||||
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => n += 1,
|
||||||
|
TokenKind::Symbol(Symbol::CloseCurlyBrace) => n -= 1,
|
||||||
|
TokenKind::Interpolation => n += 1,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if n == 1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cond.push(toks.next().unwrap());
|
||||||
|
}
|
||||||
|
toks.next();
|
||||||
|
devour_whitespace_or_comment(toks);
|
||||||
|
let mut yes = Vec::new();
|
||||||
|
yes.extend(eat_stmts(toks, scope, super_selector)?);
|
||||||
|
|
||||||
|
devour_whitespace_or_comment(toks);
|
||||||
|
|
||||||
|
let mut no = Vec::new();
|
||||||
|
if let Some(tok) = toks.peek() {
|
||||||
|
if tok.kind == TokenKind::AtRule(AtRuleKind::Else) {
|
||||||
|
toks.next();
|
||||||
|
devour_whitespace_or_comment(toks);
|
||||||
|
if let Some(tok) = toks.next() {
|
||||||
|
if !tok.is_symbol(Symbol::OpenCurlyBrace) {
|
||||||
|
return Err("expected \"{\".".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
devour_whitespace_or_comment(toks);
|
||||||
|
no.extend(eat_stmts(toks, scope, super_selector)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
devour_whitespace_or_comment(toks);
|
||||||
|
|
||||||
|
AtRule::If(cond, yes, no)
|
||||||
|
}
|
||||||
AtRuleKind::Else => todo!("@else not yet implemented"),
|
AtRuleKind::Else => todo!("@else not yet implemented"),
|
||||||
AtRuleKind::For => {
|
AtRuleKind::For => {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
|
@ -153,7 +153,7 @@ impl Css {
|
|||||||
.pretty_print(buf, nesting + 1)?;
|
.pretty_print(buf, nesting + 1)?;
|
||||||
writeln!(buf, "{}}}", padding)?;
|
writeln!(buf, "{}}}", padding)?;
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!("at-rule other than unknown at toplevel"),
|
||||||
},
|
},
|
||||||
Toplevel::Newline => {
|
Toplevel::Newline => {
|
||||||
if has_written {
|
if has_written {
|
||||||
|
25
src/lib.rs
25
src/lib.rs
@ -417,6 +417,17 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
AtRule::For(s) => rules.extend(s),
|
AtRule::For(s) => rules.extend(s),
|
||||||
AtRule::Content => return Err("@content is only allowed within mixin declarations.".into()),
|
AtRule::Content => return Err("@content is only allowed within mixin declarations.".into()),
|
||||||
|
AtRule::If(cond, yes, no) => {
|
||||||
|
if Value::from_tokens(
|
||||||
|
&mut cond.into_iter().peekable(),
|
||||||
|
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
|
||||||
|
&Selector::new(),
|
||||||
|
)?.is_true()? {
|
||||||
|
rules.extend(yes);
|
||||||
|
} else {
|
||||||
|
rules.extend(no);
|
||||||
|
}
|
||||||
|
}
|
||||||
u @ AtRule::Unknown(..) => rules.push(Stmt::AtRule(u)),
|
u @ AtRule::Unknown(..) => rules.push(Stmt::AtRule(u)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,6 +454,19 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||||
Expr::AtRule(a) => match a {
|
Expr::AtRule(a) => match a {
|
||||||
AtRule::For(s) => stmts.extend(s),
|
AtRule::For(s) => stmts.extend(s),
|
||||||
|
AtRule::If(cond, yes, no) => {
|
||||||
|
if Value::from_tokens(
|
||||||
|
&mut cond.into_iter().peekable(),
|
||||||
|
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
|
||||||
|
&Selector::new(),
|
||||||
|
)?
|
||||||
|
.is_true()?
|
||||||
|
{
|
||||||
|
stmts.extend(yes);
|
||||||
|
} else {
|
||||||
|
stmts.extend(no);
|
||||||
|
}
|
||||||
|
}
|
||||||
AtRule::Content => {
|
AtRule::Content => {
|
||||||
return Err("@content is only allowed within mixin declarations.".into())
|
return Err("@content is only allowed within mixin declarations.".into())
|
||||||
}
|
}
|
||||||
@ -620,6 +644,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
AtRule::Content => {
|
AtRule::Content => {
|
||||||
return Err("@content is only allowed within mixin declarations.".into())
|
return Err("@content is only allowed within mixin declarations.".into())
|
||||||
}
|
}
|
||||||
|
f @ AtRule::If(..) => Ok(Some(Expr::AtRule(f))),
|
||||||
f @ AtRule::For(..) => Ok(Some(Expr::AtRule(f))),
|
f @ AtRule::For(..) => Ok(Some(Expr::AtRule(f))),
|
||||||
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user