From 33843dd2ac2f17ed5bb93c40073cab107cdbb60c Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Sun, 12 Jan 2020 20:15:27 -0500 Subject: [PATCH] Refactor various devour_whitespace methods into single util function --- src/main.rs | 78 +++++++++++++++++++++++++++++-------------------- src/selector.rs | 53 ++++++++++----------------------- src/style.rs | 4 ++- src/utils.rs | 18 ++++++++++++ 4 files changed, 83 insertions(+), 70 deletions(-) create mode 100644 src/utils.rs diff --git a/src/main.rs b/src/main.rs index b147491..283a3d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ use crate::mixin::{CallArgs, FuncArgs, Mixin}; use crate::selector::{Attribute, Selector}; use crate::style::Style; use crate::units::Unit; -use crate::utils::{IsWhitespace, devour_whitespace}; +use crate::utils::{devour_whitespace, IsWhitespace}; mod color; mod common; @@ -64,6 +64,24 @@ pub struct Token { pub kind: TokenKind, } +impl IsWhitespace for Token { + fn is_whitespace(&self) -> bool { + if let TokenKind::Whitespace(_) = self.kind { + return true; + } + false + } +} + +impl IsWhitespace for &Token { + fn is_whitespace(&self) -> bool { + if let TokenKind::Whitespace(_) = self.kind { + return true; + } + false + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum TokenKind { Ident(String), @@ -226,7 +244,7 @@ impl<'a> StyleSheetParser<'a> { .lexer .next() .expect("this cannot occur as we have already peeked"); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); if self .lexer .next() @@ -243,7 +261,9 @@ impl<'a> StyleSheetParser<'a> { self.lexer.next(); rules.push(Stmt::MultilineComment(comment)); } - TokenKind::AtRule(_) => {self.eat_at_rule();}, + TokenKind::AtRule(_) => { + self.eat_at_rule(); + } _ => { if let Some(Token { pos, .. }) = self.lexer.next() { self.error(pos.clone(), "unexpected toplevel token") @@ -258,7 +278,7 @@ impl<'a> StyleSheetParser<'a> { fn eat_mixin(&mut self) { let Token { pos, .. } = self.lexer.next().unwrap(); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let name = if let Some(Token { kind: TokenKind::Ident(s), .. @@ -268,7 +288,7 @@ impl<'a> StyleSheetParser<'a> { } else { self.error(pos, "expected identifier after mixin declaration") }; - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let args = match self.lexer.next() { Some(Token { kind: TokenKind::Symbol(Symbol::OpenParen), @@ -304,7 +324,7 @@ impl<'a> StyleSheetParser<'a> { { match rule { AtRule::Error => { - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let message = self .lexer .by_ref() @@ -314,7 +334,7 @@ impl<'a> StyleSheetParser<'a> { self.error(pos, &message); } AtRule::Warn => { - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let message = self .lexer .by_ref() @@ -324,7 +344,7 @@ impl<'a> StyleSheetParser<'a> { self.warn(pos, &message); } AtRule::Debug => { - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let message = self .lexer .by_ref() @@ -342,7 +362,7 @@ impl<'a> StyleSheetParser<'a> { } fn eat_include(&mut self) -> Expr { - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let Token { kind, pos } = self.lexer.next().unwrap(); let name = if let TokenKind::Ident(s) = kind { s @@ -350,11 +370,17 @@ impl<'a> StyleSheetParser<'a> { self.error(pos, "expected identifier") }; - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); match self.lexer.next() { - Some(Token { kind: TokenKind::Symbol(Symbol::SemiColon), .. }) => {}, - Some(Token { kind: TokenKind::Symbol(Symbol::OpenParen), .. }) => {}, + Some(Token { + kind: TokenKind::Symbol(Symbol::SemiColon), + .. + }) => {} + Some(Token { + kind: TokenKind::Symbol(Symbol::OpenParen), + .. + }) => {} Some(Token { pos, .. }) => self.error(pos, "expected `(` or `;`"), None => self.error(pos, "unexpected EOF"), } @@ -365,12 +391,12 @@ impl<'a> StyleSheetParser<'a> { self.error(pos, "expected identifier") }; let styles = mixin.eval(); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); Expr::Styles(styles) } fn eat_variable_value(&mut self) -> Vec { - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); let iter1 = self .lexer .by_ref() @@ -436,14 +462,15 @@ impl<'a> StyleSheetParser<'a> { let mut values = Vec::with_capacity(5); while let Some(tok) = self.lexer.peek() { match &tok.kind { - TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseCurlyBrace) => { + TokenKind::Symbol(Symbol::SemiColon) + | TokenKind::Symbol(Symbol::CloseCurlyBrace) => { self.lexer.next(); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); return Ok(Expr::Style(Style::from_tokens(&values, scope)?)); } TokenKind::Symbol(Symbol::OpenCurlyBrace) => { self.lexer.next(); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); return Ok(Expr::Selector(Selector::from_tokens( values.iter().peekable(), super_selector, @@ -464,7 +491,7 @@ impl<'a> StyleSheetParser<'a> { .kind { self.lexer.next(); - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); return Ok(Expr::VariableDecl(name, self.eat_variable_value())); } else { values.push(Token { @@ -480,7 +507,7 @@ impl<'a> StyleSheetParser<'a> { } else { unsafe { std::hint::unreachable_unchecked() } }; - self.devour_whitespace(); + devour_whitespace(&mut self.lexer); if values.is_empty() { return Ok(Expr::MultilineComment(s.clone())); } else { @@ -491,7 +518,7 @@ impl<'a> StyleSheetParser<'a> { if let Some(a) = self.eat_at_rule() { return Ok(a); } - }, + } TokenKind::Interpolation => { while let Some(tok) = self.lexer.next() { if tok.kind == TokenKind::Symbol(Symbol::CloseCurlyBrace) { @@ -512,17 +539,6 @@ impl<'a> StyleSheetParser<'a> { } Err(()) } - - fn devour_whitespace(&mut self) { - while let Some(tok) = self.lexer.peek() { - match tok.kind { - TokenKind::Whitespace(_) => { - self.lexer.next(); - } - _ => break, - } - } - } } /// Functions that print to stdout or stderr diff --git a/src/selector.rs b/src/selector.rs index ec3fe49..b8aeb7a 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -1,4 +1,5 @@ use crate::common::{Scope, Symbol}; +use crate::utils::{devour_whitespace, IsWhitespace}; use crate::{Token, TokenKind}; use std::fmt::{self, Display}; use std::iter::Peekable; @@ -8,28 +9,6 @@ use std::string::ToString; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Selector(pub Vec); -fn devour_whitespace(i: &mut Peekable>) -> bool { - let mut found_whitespace = false; - while let Some(SelectorKind::Whitespace) = i.peek() { - i.next(); - found_whitespace = true; - } - found_whitespace -} - -fn devour_whitespace_from_tokens(i: &mut Peekable>) -> bool { - let mut found_whitespace = false; - while let Some(Token { - kind: TokenKind::Whitespace(_), - .. - }) = i.peek() - { - i.next(); - found_whitespace = true; - } - found_whitespace -} - impl Display for Selector { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut iter = self.0.iter().peekable(); @@ -100,6 +79,18 @@ pub enum SelectorKind { Several(Vec), } +impl IsWhitespace for SelectorKind { + fn is_whitespace(&self) -> bool { + self == &Self::Whitespace + } +} + +impl IsWhitespace for &SelectorKind { + fn is_whitespace(&self) -> bool { + self == &&SelectorKind::Whitespace + } +} + impl Display for SelectorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -214,7 +205,7 @@ impl<'a> SelectorParser<'a> { &mut self, toks: &mut Peekable>, ) -> Option { - if devour_whitespace_from_tokens(toks) { + if devour_whitespace(toks) { if let Some(&&Token { kind: TokenKind::Symbol(Symbol::Comma), .. @@ -329,7 +320,7 @@ impl<'a> SelectorParser<'a> { } fn consume_selector(&mut self) -> Option { - if self.devour_whitespace() { + if devour_whitespace(&mut self.tokens) { if let Some(&&Token { kind: TokenKind::Symbol(Symbol::Comma), .. @@ -359,20 +350,6 @@ impl<'a> SelectorParser<'a> { } None } - - fn devour_whitespace(&mut self) -> bool { - let mut found_whitespace = false; - while let Some(tok) = self.tokens.peek() { - match tok.kind { - TokenKind::Whitespace(_) => { - self.tokens.next(); - found_whitespace = true; - } - _ => break, - } - } - found_whitespace - } } impl Selector { diff --git a/src/style.rs b/src/style.rs index 331d89d..082de57 100644 --- a/src/style.rs +++ b/src/style.rs @@ -82,7 +82,9 @@ impl<'a> StyleParser<'a> { while let Some(Token { kind, .. }) = self.tokens.next() { match &kind { TokenKind::Symbol(Symbol::CloseCurlyBrace) => break, - TokenKind::Symbol(Symbol::OpenCurlyBrace) => todo!("invalid character in interpolation"), + TokenKind::Symbol(Symbol::OpenCurlyBrace) => { + todo!("invalid character in interpolation") + } TokenKind::Variable(_) => val.push_str(&self.deref_variable(kind)), _ => val.push_str(&kind.to_string()), } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..5d29e71 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,18 @@ +use std::iter::Iterator; +use std::iter::Peekable; + +pub trait IsWhitespace { + fn is_whitespace(&self) -> bool; +} + +pub fn devour_whitespace, W: IsWhitespace>(s: &mut Peekable) -> bool { + let mut found_whitespace = false; + while let Some(w) = s.peek() { + if !w.is_whitespace() { + break; + } + found_whitespace = true; + s.next(); + } + found_whitespace +}