diff --git a/src/main.rs b/src/main.rs index 71e341f..153dc61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ clippy::use_self, clippy::missing_docs_in_private_items, clippy::todo, - clippy::dbg_macro, clippy::unreachable, clippy::wildcard_enum_match_arm, clippy::option_expect_used, @@ -41,7 +40,7 @@ use crate::mixin::{CallArgs, FuncArgs, Mixin}; use crate::selector::{Attribute, Selector}; use crate::style::Style; use crate::units::Unit; -use crate::utils::{devour_whitespace, IsWhitespace}; +use crate::utils::{devour_whitespace, eat_variable_value, IsWhitespace}; mod color; mod common; @@ -254,7 +253,8 @@ impl<'a> StyleSheetParser<'a> { { self.error(pos, "unexpected variable use at toplevel"); } - let val = self.eat_variable_value(); + let val = eat_variable_value(&mut self.lexer, &self.global_scope) + .unwrap_or_else(|err| self.error(err.0, err.1)); self.global_scope.vars.insert(name, val); } TokenKind::MultilineComment(comment) => { @@ -395,34 +395,6 @@ impl<'a> StyleSheetParser<'a> { Expr::Styles(styles) } - fn eat_variable_value(&mut self) -> Vec { - devour_whitespace(&mut self.lexer); - let iter1 = self - .lexer - .by_ref() - .take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)) - .collect::>(); - let mut iter2 = Vec::with_capacity(iter1.len()); - for tok in iter1 { - if let Token { - kind: TokenKind::Variable(ref name), - pos, - } = tok - { - iter2.extend( - self.global_scope - .vars - .get(name) - .unwrap_or_else(|| self.error(pos, "Undefined variable")) - .clone(), - ); - } else { - iter2.push(tok); - } - } - iter2 - } - fn eat_func_call(&mut self) {} fn eat_rules(&mut self, super_selector: &Selector, scope: &mut Scope) -> Vec { @@ -492,7 +464,11 @@ impl<'a> StyleSheetParser<'a> { { self.lexer.next(); devour_whitespace(&mut self.lexer); - return Ok(Expr::VariableDecl(name, self.eat_variable_value())); + return Ok(Expr::VariableDecl( + name, + eat_variable_value(&mut self.lexer, scope) + .unwrap_or_else(|err| self.error(err.0, err.1)), + )); } else { values.push(Token { kind: TokenKind::Variable(name), diff --git a/src/mixin.rs b/src/mixin.rs index e7f98bb..d0b1b0a 100644 --- a/src/mixin.rs +++ b/src/mixin.rs @@ -1,6 +1,6 @@ -use crate::common::Scope; -use crate::common::Symbol; +use crate::common::{Pos, Scope, Symbol}; use crate::style::Style; +use crate::utils::{devour_whitespace, eat_variable_value_ref}; use crate::{Token, TokenKind}; #[derive(Debug, Clone)] @@ -19,37 +19,36 @@ impl Mixin { let mut toks = self.body.iter().peekable(); let mut styles = Vec::new(); let mut value = Vec::new(); - while let Some(tok) = toks.peek() { - match tok.kind { + while let Some(tok) = &toks.peek() { + dbg!(&tok.kind); + match &tok.kind { TokenKind::Symbol(Symbol::SemiColon) => { + toks.next(); if let Ok(s) = Style::from_tokens(&value, &self.scope) { styles.push(s); + value.clear(); } else { return styles; } } - // TokenKind::Variable(_) => { - // let tok = toks.next().unwrap(); - // let name = if let TokenKind::Variable(n) = tok.kind { - // n - // } else { - // unsafe { std::hint::unreachable_unchecked() } - // }; - // if let TokenKind::Symbol(Symbol::Colon) = toks - // .peek() - // .expect("expected something after variable") - // .kind - // { - // toks.next(); - // devour_whitespace(&mut toks); - // return Ok(Expr::VariableDecl(name, self.eat_variable_value())); - // } else { - // values.push(Token { - // kind: TokenKind::Variable(name), - // pos: tok.pos, - // }); - // } - // } + TokenKind::Variable(ref name) => { + toks.next(); + if let TokenKind::Symbol(Symbol::Colon) = + toks.peek().expect("expected something after variable").kind + { + toks.next(); + devour_whitespace(&mut toks); + self.scope.vars.insert( + name.clone(), + eat_variable_value_ref(&mut toks, &self.scope).unwrap(), + ); + } else { + value.push(Token { + kind: TokenKind::Variable(name.clone()), + pos: Pos::new(), + }); + } + } _ => { if let Some(tok) = toks.next() { value.push(tok.clone()) diff --git a/src/utils.rs b/src/utils.rs index 729cc95..4e2ef29 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use crate::common::{Symbol, Whitespace}; +use crate::common::{Pos, Symbol, Whitespace}; use crate::{Scope, Token, TokenKind}; use std::iter::{Iterator, Peekable}; @@ -61,3 +61,35 @@ pub fn eat_interpolation<'a, I: Iterator>( } val } + +pub fn eat_variable_value>( + toks: &mut Peekable, + scope: &Scope, +) -> Result, (Pos, &'static str)> { + devour_whitespace(toks); + let iter1 = toks.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)); + let mut iter2 = Vec::new(); + for tok in iter1 { + match tok.kind { + TokenKind::Variable(ref name) => iter2.extend(deref_variable(name, scope)), + _ => iter2.push(tok), + }; + } + Ok(iter2) +} + +pub fn eat_variable_value_ref<'a, I: Iterator>( + toks: &mut Peekable, + scope: &Scope, +) -> Result, (Pos, &'static str)> { + devour_whitespace(toks); + let iter1 = toks.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)); + let mut iter2 = Vec::new(); + for tok in iter1 { + match tok.kind { + TokenKind::Variable(ref name) => iter2.extend(deref_variable(name, scope)), + _ => iter2.push(tok.clone()), + }; + } + Ok(iter2) +}