Refactor style parsing to separate module
This commit is contained in:
parent
3f063709c5
commit
3ba585b40d
@ -84,7 +84,7 @@ impl<W: Write> PrettyPrinter<W> {
|
|||||||
s: &StyleSheet,
|
s: &StyleSheet,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
for rule in &s.rules {
|
for rule in &s.rules {
|
||||||
self.pretty_print_stmt(rule)?;
|
self.pretty_print_stmt_preserve_super_selectors(rule)?;
|
||||||
}
|
}
|
||||||
writeln!(self.buf)?;
|
writeln!(self.buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
126
src/main.rs
126
src/main.rs
@ -37,6 +37,7 @@ use crate::css::Css;
|
|||||||
use crate::format::PrettyPrinter;
|
use crate::format::PrettyPrinter;
|
||||||
use crate::lexer::Lexer;
|
use crate::lexer::Lexer;
|
||||||
use crate::selector::Selector;
|
use crate::selector::Selector;
|
||||||
|
use crate::style::Style;
|
||||||
use crate::units::Unit;
|
use crate::units::Unit;
|
||||||
|
|
||||||
mod color;
|
mod color;
|
||||||
@ -46,6 +47,7 @@ mod error;
|
|||||||
mod format;
|
mod format;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod selector;
|
mod selector;
|
||||||
|
mod style;
|
||||||
mod units;
|
mod units;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
@ -95,130 +97,6 @@ pub struct StyleSheet {
|
|||||||
rules: Vec<Stmt>,
|
rules: Vec<Stmt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub struct Style {
|
|
||||||
property: String,
|
|
||||||
value: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Style {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}:{};", self.property, self.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Style {
|
|
||||||
pub fn from_tokens(tokens: &[Token], vars: &HashMap<String, Vec<Token>>) -> Result<Self, ()> {
|
|
||||||
Ok(StyleParser::new(tokens, vars)?.parse())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StyleParser<'a> {
|
|
||||||
tokens: Peekable<std::slice::Iter<'a, Token>>,
|
|
||||||
vars: &'a HashMap<String, Vec<Token>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> StyleParser<'a> {
|
|
||||||
fn new(tokens: &'a [Token], vars: &'a HashMap<String, Vec<Token>>) -> Result<Self, ()> {
|
|
||||||
if tokens.is_empty() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
let tokens = tokens.iter().peekable();
|
|
||||||
Ok(StyleParser { tokens, vars })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deref_variable(&mut self, variable: &TokenKind) -> String {
|
|
||||||
let mut val = String::with_capacity(25);
|
|
||||||
let mut v = match variable {
|
|
||||||
TokenKind::Variable(ref v) => {
|
|
||||||
self.vars.get(v).expect("todo! expected variable to exist")
|
|
||||||
}
|
|
||||||
_ => panic!("expected variable"),
|
|
||||||
}
|
|
||||||
.iter()
|
|
||||||
.peekable();
|
|
||||||
while let Some(tok) = v.next() {
|
|
||||||
match &tok.kind {
|
|
||||||
TokenKind::Variable(_) => val.push_str(&self.deref_variable(&tok.kind)),
|
|
||||||
TokenKind::Whitespace(_) => {
|
|
||||||
while let Some(w) = v.peek() {
|
|
||||||
if let TokenKind::Whitespace(_) = w.kind {
|
|
||||||
v.next();
|
|
||||||
} else {
|
|
||||||
val.push(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => val.push_str(&tok.kind.to_string()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
val
|
|
||||||
}
|
|
||||||
|
|
||||||
fn devour_whitespace(&mut self) {
|
|
||||||
while let Some(tok) = self.tokens.peek() {
|
|
||||||
if let TokenKind::Whitespace(_) = tok.kind {
|
|
||||||
self.tokens.next();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse(&mut self) -> Style {
|
|
||||||
let mut property = String::new();
|
|
||||||
// read property
|
|
||||||
while let Some(tok) = self.tokens.next() {
|
|
||||||
match tok.kind {
|
|
||||||
TokenKind::Whitespace(_) => continue,
|
|
||||||
TokenKind::Ident(ref s) => {
|
|
||||||
property = s.clone();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// read until `:`
|
|
||||||
while let Some(tok) = self.tokens.next() {
|
|
||||||
match tok.kind {
|
|
||||||
TokenKind::Whitespace(_) => continue,
|
|
||||||
TokenKind::Symbol(Symbol::Colon) => break,
|
|
||||||
_ => todo!("found tokens before style value"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut value = String::new();
|
|
||||||
|
|
||||||
// read styles
|
|
||||||
while let Some(tok) = self.tokens.next() {
|
|
||||||
match &tok.kind {
|
|
||||||
TokenKind::Whitespace(_) => {
|
|
||||||
while let Some(w) = self.tokens.peek() {
|
|
||||||
if let TokenKind::Whitespace(_) = w.kind {
|
|
||||||
self.tokens.next();
|
|
||||||
continue;
|
|
||||||
} else if let TokenKind::Ident(ref s) = w.kind {
|
|
||||||
if s == &String::from("-") {
|
|
||||||
self.tokens.next();
|
|
||||||
value.push('-');
|
|
||||||
self.devour_whitespace();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value.push(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TokenKind::Variable(_) => value.push_str(&self.deref_variable(&tok.kind)),
|
|
||||||
_ => value.push_str(&tok.kind.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Style { property, value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Style(Style),
|
Style(Style),
|
||||||
|
130
src/style.rs
Normal file
130
src/style.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
use crate::{Token, TokenKind};
|
||||||
|
use crate::common::Symbol;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::slice::Iter;
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct Style {
|
||||||
|
property: String,
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Style {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}:{};", self.property, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Style {
|
||||||
|
pub fn from_tokens(tokens: &[Token], vars: &HashMap<String, Vec<Token>>) -> Result<Self, ()> {
|
||||||
|
Ok(StyleParser::new(tokens, vars)?.parse())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StyleParser<'a> {
|
||||||
|
tokens: Peekable<Iter<'a, Token>>,
|
||||||
|
vars: &'a HashMap<String, Vec<Token>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> StyleParser<'a> {
|
||||||
|
fn new(tokens: &'a [Token], vars: &'a HashMap<String, Vec<Token>>) -> Result<Self, ()> {
|
||||||
|
if tokens.is_empty() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let tokens = tokens.iter().peekable();
|
||||||
|
Ok(StyleParser { tokens, vars })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref_variable(&mut self, variable: &TokenKind) -> String {
|
||||||
|
let mut val = String::with_capacity(25);
|
||||||
|
let mut v = match variable {
|
||||||
|
TokenKind::Variable(ref v) => {
|
||||||
|
self.vars.get(v).expect("todo! expected variable to exist")
|
||||||
|
}
|
||||||
|
_ => panic!("expected variable"),
|
||||||
|
}
|
||||||
|
.iter()
|
||||||
|
.peekable();
|
||||||
|
while let Some(tok) = v.next() {
|
||||||
|
match &tok.kind {
|
||||||
|
TokenKind::Variable(_) => val.push_str(&self.deref_variable(&tok.kind)),
|
||||||
|
TokenKind::Whitespace(_) => {
|
||||||
|
while let Some(w) = v.peek() {
|
||||||
|
if let TokenKind::Whitespace(_) = w.kind {
|
||||||
|
v.next();
|
||||||
|
} else {
|
||||||
|
val.push(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => val.push_str(&tok.kind.to_string()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
val
|
||||||
|
}
|
||||||
|
|
||||||
|
fn devour_whitespace(&mut self) {
|
||||||
|
while let Some(tok) = self.tokens.peek() {
|
||||||
|
if let TokenKind::Whitespace(_) = tok.kind {
|
||||||
|
self.tokens.next();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(&mut self) -> Style {
|
||||||
|
let mut property = String::new();
|
||||||
|
// read property
|
||||||
|
while let Some(tok) = self.tokens.next() {
|
||||||
|
match tok.kind {
|
||||||
|
TokenKind::Whitespace(_) => continue,
|
||||||
|
TokenKind::Ident(ref s) => {
|
||||||
|
property = s.clone();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// read until `:`
|
||||||
|
while let Some(tok) = self.tokens.next() {
|
||||||
|
match tok.kind {
|
||||||
|
TokenKind::Whitespace(_) => continue,
|
||||||
|
TokenKind::Symbol(Symbol::Colon) => break,
|
||||||
|
_ => todo!("found tokens before style value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut value = String::new();
|
||||||
|
|
||||||
|
// read styles
|
||||||
|
while let Some(tok) = self.tokens.next() {
|
||||||
|
match &tok.kind {
|
||||||
|
TokenKind::Whitespace(_) => {
|
||||||
|
while let Some(w) = self.tokens.peek() {
|
||||||
|
if let TokenKind::Whitespace(_) = w.kind {
|
||||||
|
self.tokens.next();
|
||||||
|
continue;
|
||||||
|
} else if let TokenKind::Ident(ref s) = w.kind {
|
||||||
|
if s == &String::from("-") {
|
||||||
|
self.tokens.next();
|
||||||
|
value.push('-');
|
||||||
|
self.devour_whitespace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value.push(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenKind::Variable(_) => value.push_str(&self.deref_variable(&tok.kind)),
|
||||||
|
_ => value.push_str(&tok.kind.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style { property, value }
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user