Refactor out variable eating

This commit is contained in:
ConnorSkees 2020-01-14 19:34:13 -05:00
parent 2389abaeed
commit e3968ac047
3 changed files with 66 additions and 59 deletions

View File

@ -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<Token> {
devour_whitespace(&mut self.lexer);
let iter1 = self
.lexer
.by_ref()
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
.collect::<Vec<Token>>();
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<Stmt> {
@ -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),

View File

@ -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())

View File

@ -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<Item = &'a Token>>(
}
val
}
pub fn eat_variable_value<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>,
scope: &Scope,
) -> Result<Vec<Token>, (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<Item = &'a Token>>(
toks: &mut Peekable<I>,
scope: &Scope,
) -> Result<Vec<Token>, (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)
}