Refactor various devour_whitespace methods into single util function
This commit is contained in:
parent
2439579d20
commit
33843dd2ac
78
src/main.rs
78
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<Token> {
|
||||
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
|
||||
|
@ -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<SelectorKind>);
|
||||
|
||||
fn devour_whitespace(i: &mut Peekable<Iter<SelectorKind>>) -> 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<Iter<Token>>) -> 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<SelectorKind>),
|
||||
}
|
||||
|
||||
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<Iter<'_, Token>>,
|
||||
) -> Option<SelectorKind> {
|
||||
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<SelectorKind> {
|
||||
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 {
|
||||
|
@ -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()),
|
||||
}
|
||||
|
18
src/utils.rs
Normal file
18
src/utils.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use std::iter::Iterator;
|
||||
use std::iter::Peekable;
|
||||
|
||||
pub trait IsWhitespace {
|
||||
fn is_whitespace(&self) -> bool;
|
||||
}
|
||||
|
||||
pub fn devour_whitespace<I: Iterator<Item = W>, W: IsWhitespace>(s: &mut Peekable<I>) -> bool {
|
||||
let mut found_whitespace = false;
|
||||
while let Some(w) = s.peek() {
|
||||
if !w.is_whitespace() {
|
||||
break;
|
||||
}
|
||||
found_whitespace = true;
|
||||
s.next();
|
||||
}
|
||||
found_whitespace
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user