Handle variables on global scope

This commit is contained in:
ConnorSkees 2020-01-06 19:23:27 -05:00
parent 485bb8b94d
commit 1d80b00c20

View File

@ -186,15 +186,30 @@ impl<'a> StyleSheetParser<'a> {
_ => todo!("unexpected toplevel token"), _ => todo!("unexpected toplevel token"),
}; };
} }
StyleSheet { rules } Ok(StyleSheet { rules })
} }
fn eat_variable_value(&mut self) -> Vec<Token> { fn eat_variable_value(&mut self) -> Vec<Token> {
self.devour_whitespace(); self.devour_whitespace();
self.lexer let iter1 = self
.lexer
.by_ref() .by_ref()
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)) .take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
.collect::<Vec<Token>>() .collect::<Vec<Token>>();
let mut iter2 = Vec::with_capacity(iter1.len());
for tok in iter1 {
if let TokenKind::Variable(name) = tok.kind {
iter2.extend(
self.global_variables
.get(&name)
.expect("expected variable")
.clone(),
);
} else {
iter2.push(tok);
}
}
iter2
} }
fn eat_rules( fn eat_rules(
@ -207,15 +222,22 @@ impl<'a> StyleSheetParser<'a> {
match tok { match tok {
Expr::Style(s) => stmts.push(Stmt::Style(s)), Expr::Style(s) => stmts.push(Stmt::Style(s)),
Expr::Selector(s) => { Expr::Selector(s) => {
self.scope += 1;
let rules = self.eat_rules(&super_selector.clone().zip(s.clone()), vars); let rules = self.eat_rules(&super_selector.clone().zip(s.clone()), vars);
stmts.push(Stmt::RuleSet(RuleSet { stmts.push(Stmt::RuleSet(RuleSet {
super_selector: super_selector.clone(), super_selector: super_selector.clone(),
selector: s, selector: s,
rules, rules,
})); }));
self.scope -= 1;
} }
Expr::VariableDecl(name, val) => { Expr::VariableDecl(name, val) => {
vars.insert(name, val); if self.scope == 0 {
vars.insert(name.clone(), val.clone());
self.global_variables.insert(name, val);
} else {
vars.insert(name, val);
}
} }
} }
} }
@ -237,13 +259,13 @@ impl<'a> StyleSheetParser<'a> {
))); )));
} }
TokenKind::Variable(name) => { TokenKind::Variable(name) => {
if self if let TokenKind::Symbol(Symbol::Colon) = self
.lexer .lexer
.next() .peek()
.expect("expected something after variable") .expect("expected something after variable")
.kind .kind
== TokenKind::Symbol(Symbol::Colon)
{ {
self.lexer.next();
self.devour_whitespace(); self.devour_whitespace();
return Ok(Expr::VariableDecl(name, self.eat_variable_value())); return Ok(Expr::VariableDecl(name, self.eat_variable_value()));
} else { } else {
@ -293,7 +315,8 @@ mod test_css {
#[test] #[test]
fn $func() { fn $func() {
let mut buf = Vec::new(); let mut buf = Vec::new();
StyleSheet::new($input).expect(concat!("failed to parse on ", $input)) StyleSheet::new($input)
.expect(concat!("failed to parse on ", $input))
.print_as_css(&mut buf) .print_as_css(&mut buf)
.expect(concat!("failed to pretty print on ", $input)); .expect(concat!("failed to pretty print on ", $input));
assert_eq!( assert_eq!(
@ -306,7 +329,8 @@ mod test_css {
#[test] #[test]
fn $func() { fn $func() {
let mut buf = Vec::new(); let mut buf = Vec::new();
StyleSheet::new($input).expect(concat!("failed to parse on ", $input)) StyleSheet::new($input)
.expect(concat!("failed to parse on ", $input))
.print_as_css(&mut buf) .print_as_css(&mut buf)
.expect(concat!("failed to pretty print on ", $input)); .expect(concat!("failed to pretty print on ", $input));
assert_eq!( assert_eq!(