reduce size of parse::Stmt
This commit is contained in:
parent
177cacd9c9
commit
e12d3a581d
69
src/atrule/media.rs
Normal file
69
src/atrule/media.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::{parse::Stmt, selector::Selector};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct MediaRule {
|
||||||
|
pub super_selector: Selector,
|
||||||
|
pub query: String,
|
||||||
|
pub body: Vec<Stmt>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
|
pub(crate) struct MediaQuery {
|
||||||
|
/// The modifier, probably either "not" or "only".
|
||||||
|
///
|
||||||
|
/// This may be `None` if no modifier is in use.
|
||||||
|
pub modifier: Option<String>,
|
||||||
|
|
||||||
|
/// The media type, for example "screen" or "print".
|
||||||
|
///
|
||||||
|
/// This may be `None`. If so, `self.features` will not be empty.
|
||||||
|
pub media_type: Option<String>,
|
||||||
|
|
||||||
|
/// Feature queries, including parentheses.
|
||||||
|
pub features: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl MediaQuery {
|
||||||
|
pub fn is_condition(&self) -> bool {
|
||||||
|
self.modifier.is_none() && self.media_type.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn matches_all_types(&self) -> bool {
|
||||||
|
self.media_type.is_none()
|
||||||
|
|| self
|
||||||
|
.media_type
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |v| v.to_ascii_lowercase() == "all")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn condition(features: Vec<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
modifier: None,
|
||||||
|
media_type: None,
|
||||||
|
features,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code, unused_variables)]
|
||||||
|
pub fn merge(other: &Self) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MediaQuery {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if let Some(modifier) = &self.modifier {
|
||||||
|
f.write_str(modifier)?;
|
||||||
|
}
|
||||||
|
if let Some(media_type) = &self.media_type {
|
||||||
|
f.write_str(media_type)?;
|
||||||
|
if !&self.features.is_empty() {
|
||||||
|
f.write_str(" and ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.write_str(&self.features.join(" and "))
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,12 @@
|
|||||||
pub(crate) use function::Function;
|
pub(crate) use function::Function;
|
||||||
pub(crate) use kind::AtRuleKind;
|
pub(crate) use kind::AtRuleKind;
|
||||||
pub(crate) use mixin::Mixin;
|
pub(crate) use mixin::Mixin;
|
||||||
|
pub(crate) use supports::SupportsRule;
|
||||||
|
pub(crate) use unknown::UnknownAtRule;
|
||||||
|
|
||||||
mod function;
|
mod function;
|
||||||
mod kind;
|
mod kind;
|
||||||
|
pub mod media;
|
||||||
mod mixin;
|
mod mixin;
|
||||||
|
mod supports;
|
||||||
|
mod unknown;
|
||||||
|
7
src/atrule/supports.rs
Normal file
7
src/atrule/supports.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use crate::parse::Stmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct SupportsRule {
|
||||||
|
pub params: String,
|
||||||
|
pub body: Vec<Stmt>,
|
||||||
|
}
|
9
src/atrule/unknown.rs
Normal file
9
src/atrule/unknown.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::{parse::Stmt, selector::Selector};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct UnknownAtRule {
|
||||||
|
pub name: String,
|
||||||
|
pub super_selector: Selector,
|
||||||
|
pub params: String,
|
||||||
|
pub body: Vec<Stmt>,
|
||||||
|
}
|
@ -3,7 +3,14 @@ use std::io::Write;
|
|||||||
|
|
||||||
use codemap::CodeMap;
|
use codemap::CodeMap;
|
||||||
|
|
||||||
use crate::{error::SassResult, parse::Stmt, selector::Extender, selector::Selector, style::Style};
|
use crate::{
|
||||||
|
atrule::{media::MediaRule, SupportsRule, UnknownAtRule},
|
||||||
|
error::SassResult,
|
||||||
|
parse::Stmt,
|
||||||
|
selector::Extender,
|
||||||
|
selector::Selector,
|
||||||
|
style::Style,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Toplevel {
|
enum Toplevel {
|
||||||
@ -23,7 +30,7 @@ enum Toplevel {
|
|||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
Newline,
|
Newline,
|
||||||
Style(Box<Style>),
|
Style(Style),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -92,17 +99,22 @@ impl Css {
|
|||||||
for rule in body {
|
for rule in body {
|
||||||
match rule {
|
match rule {
|
||||||
Stmt::RuleSet { .. } => vals.extend(self.parse_stmt(rule, extender)?),
|
Stmt::RuleSet { .. } => vals.extend(self.parse_stmt(rule, extender)?),
|
||||||
Stmt::Style(s) => vals.get_mut(0).unwrap().push_style(*s)?,
|
Stmt::Style(s) => vals.get_mut(0).unwrap().push_style(s)?,
|
||||||
Stmt::Comment(s) => vals.get_mut(0).unwrap().push_comment(s),
|
Stmt::Comment(s) => vals.get_mut(0).unwrap().push_comment(s),
|
||||||
Stmt::Media { query, body, .. } => {
|
Stmt::Media(m) => {
|
||||||
|
let MediaRule { query, body, .. } = *m;
|
||||||
vals.push(Toplevel::Media { query, body })
|
vals.push(Toplevel::Media { query, body })
|
||||||
}
|
}
|
||||||
Stmt::Supports { params, body, .. } => {
|
Stmt::Supports(s) => {
|
||||||
|
let SupportsRule { params, body, .. } = *s;
|
||||||
vals.push(Toplevel::Supports { params, body })
|
vals.push(Toplevel::Supports { params, body })
|
||||||
}
|
}
|
||||||
Stmt::UnknownAtRule {
|
Stmt::UnknownAtRule(u) => {
|
||||||
params, body, name, ..
|
let UnknownAtRule {
|
||||||
} => vals.push(Toplevel::UnknownAtRule { params, body, name }),
|
params, body, name, ..
|
||||||
|
} = *u;
|
||||||
|
vals.push(Toplevel::UnknownAtRule { params, body, name })
|
||||||
|
}
|
||||||
Stmt::Return(..) => unreachable!(),
|
Stmt::Return(..) => unreachable!(),
|
||||||
Stmt::AtRoot { body } => body
|
Stmt::AtRoot { body } => body
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -114,11 +126,20 @@ impl Css {
|
|||||||
}
|
}
|
||||||
Stmt::Comment(s) => vec![Toplevel::MultilineComment(s)],
|
Stmt::Comment(s) => vec![Toplevel::MultilineComment(s)],
|
||||||
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
||||||
Stmt::Media { query, body, .. } => vec![Toplevel::Media { query, body }],
|
Stmt::Media(m) => {
|
||||||
Stmt::Supports { params, body, .. } => vec![Toplevel::Supports { params, body }],
|
let MediaRule { query, body, .. } = *m;
|
||||||
Stmt::UnknownAtRule {
|
vec![Toplevel::Media { query, body }]
|
||||||
params, name, body, ..
|
}
|
||||||
} => vec![Toplevel::UnknownAtRule { params, name, body }],
|
Stmt::Supports(s) => {
|
||||||
|
let SupportsRule { params, body, .. } = *s;
|
||||||
|
vec![Toplevel::Supports { params, body }]
|
||||||
|
}
|
||||||
|
Stmt::UnknownAtRule(u) => {
|
||||||
|
let UnknownAtRule {
|
||||||
|
params, body, name, ..
|
||||||
|
} = *u;
|
||||||
|
vec![Toplevel::UnknownAtRule { params, name, body }]
|
||||||
|
}
|
||||||
Stmt::Return(..) => unreachable!("@return: {:?}", stmt),
|
Stmt::Return(..) => unreachable!("@return: {:?}", stmt),
|
||||||
Stmt::AtRoot { .. } => unreachable!("@at-root: {:?}", stmt),
|
Stmt::AtRoot { .. } => unreachable!("@at-root: {:?}", stmt),
|
||||||
})
|
})
|
||||||
|
@ -82,13 +82,13 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn parse_return(&mut self) -> SassResult<Value> {
|
pub(super) fn parse_return(&mut self) -> SassResult<Box<Value>> {
|
||||||
let toks = read_until_semicolon_or_closing_curly_brace(self.toks)?;
|
let toks = read_until_semicolon_or_closing_curly_brace(self.toks)?;
|
||||||
let v = self.parse_value_from_vec(toks)?;
|
let v = self.parse_value_from_vec(toks)?;
|
||||||
if let Some(Token { kind: ';', .. }) = self.toks.peek() {
|
if let Some(Token { kind: ';', .. }) = self.toks.peek() {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
}
|
}
|
||||||
Ok(v.node)
|
Ok(Box::new(v.node))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_function(&mut self, mut function: Function, args: CallArgs) -> SassResult<Value> {
|
pub fn eval_function(&mut self, mut function: Function, args: CallArgs) -> SassResult<Value> {
|
||||||
@ -117,7 +117,7 @@ impl<'a> Parser<'a> {
|
|||||||
.pop()
|
.pop()
|
||||||
.ok_or(("Function finished without @return.", self.span_before))?
|
.ok_or(("Function finished without @return.", self.span_before))?
|
||||||
{
|
{
|
||||||
Stmt::Return(v) => Ok(v),
|
Stmt::Return(v) => Ok(*v),
|
||||||
_ => todo!("should be unreachable"),
|
_ => todo!("should be unreachable"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::fmt;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
utils::{is_name_start, peek_ident_no_interpolation, read_until_closing_paren},
|
utils::{is_name_start, peek_ident_no_interpolation, read_until_closing_paren},
|
||||||
@ -8,65 +6,6 @@ use crate::{
|
|||||||
|
|
||||||
use super::Parser;
|
use super::Parser;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
|
||||||
pub(super) struct MediaQuery {
|
|
||||||
/// The modifier, probably either "not" or "only".
|
|
||||||
///
|
|
||||||
/// This may be `None` if no modifier is in use.
|
|
||||||
modifier: Option<String>,
|
|
||||||
|
|
||||||
/// The media type, for example "screen" or "print".
|
|
||||||
///
|
|
||||||
/// This may be `None`. If so, `self.features` will not be empty.
|
|
||||||
media_type: Option<String>,
|
|
||||||
|
|
||||||
/// Feature queries, including parentheses.
|
|
||||||
features: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl MediaQuery {
|
|
||||||
pub fn is_condition(&self) -> bool {
|
|
||||||
self.modifier.is_none() && self.media_type.is_none()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn matches_all_types(&self) -> bool {
|
|
||||||
self.media_type.is_none()
|
|
||||||
|| self
|
|
||||||
.media_type
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |v| v.to_ascii_lowercase() == "all")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn condition(features: Vec<String>) -> Self {
|
|
||||||
Self {
|
|
||||||
modifier: None,
|
|
||||||
media_type: None,
|
|
||||||
features,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code, unused_variables)]
|
|
||||||
pub fn merge(other: &Self) -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for MediaQuery {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
if let Some(modifier) = &self.modifier {
|
|
||||||
f.write_str(modifier)?;
|
|
||||||
}
|
|
||||||
if let Some(media_type) = &self.media_type {
|
|
||||||
f.write_str(media_type)?;
|
|
||||||
if !&self.features.is_empty() {
|
|
||||||
f.write_str(" and ")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.write_str(&self.features.join(" and "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub fn scan_identifier(&mut self, ident: &str) -> SassResult<bool> {
|
pub fn scan_identifier(&mut self, ident: &str) -> SassResult<bool> {
|
||||||
let peeked_identifier =
|
let peeked_identifier =
|
||||||
|
@ -5,7 +5,7 @@ use num_traits::cast::ToPrimitive;
|
|||||||
use peekmore::{PeekMore, PeekMoreIterator};
|
use peekmore::{PeekMore, PeekMoreIterator};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
atrule::AtRuleKind,
|
atrule::{media::MediaRule, AtRuleKind, SupportsRule, UnknownAtRule},
|
||||||
common::{Brackets, ListSeparator},
|
common::{Brackets, ListSeparator},
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
scope::Scope,
|
scope::Scope,
|
||||||
@ -46,27 +46,15 @@ pub(crate) enum Stmt {
|
|||||||
selector: ExtendedSelector,
|
selector: ExtendedSelector,
|
||||||
body: Vec<Self>,
|
body: Vec<Self>,
|
||||||
},
|
},
|
||||||
Style(Box<Style>),
|
Style(Style),
|
||||||
Media {
|
Media(Box<MediaRule>),
|
||||||
super_selector: Selector,
|
UnknownAtRule(Box<UnknownAtRule>),
|
||||||
query: String,
|
Supports(Box<SupportsRule>),
|
||||||
body: Vec<Stmt>,
|
|
||||||
},
|
|
||||||
UnknownAtRule {
|
|
||||||
name: String,
|
|
||||||
super_selector: Selector,
|
|
||||||
params: String,
|
|
||||||
body: Vec<Stmt>,
|
|
||||||
},
|
|
||||||
Supports {
|
|
||||||
params: String,
|
|
||||||
body: Vec<Stmt>,
|
|
||||||
},
|
|
||||||
AtRoot {
|
AtRoot {
|
||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
Comment(String),
|
Comment(String),
|
||||||
Return(Value),
|
Return(Box<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We could use a generic for the toks, but it makes the API
|
/// We could use a generic for the toks, but it makes the API
|
||||||
@ -252,12 +240,12 @@ impl<'a> Parser<'a> {
|
|||||||
let styles = if let Some(value) = value {
|
let styles = if let Some(value) = value {
|
||||||
vec![Style {
|
vec![Style {
|
||||||
property,
|
property,
|
||||||
value: *value,
|
value: value,
|
||||||
}]
|
}]
|
||||||
} else {
|
} else {
|
||||||
self.parse_style_group(property)?
|
self.parse_style_group(property)?
|
||||||
};
|
};
|
||||||
stmts.extend(styles.into_iter().map(Box::new).map(Stmt::Style));
|
stmts.extend(styles.into_iter().map(Stmt::Style));
|
||||||
}
|
}
|
||||||
SelectorOrStyle::Selector(init) => {
|
SelectorOrStyle::Selector(init) => {
|
||||||
let at_root = self.at_root;
|
let at_root = self.at_root;
|
||||||
@ -1003,12 +991,12 @@ impl<'a> Parser<'a> {
|
|||||||
self.whitespace();
|
self.whitespace();
|
||||||
if let Some(Token { kind: ';', .. }) | None = self.toks.peek() {
|
if let Some(Token { kind: ';', .. }) | None = self.toks.peek() {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
return Ok(Stmt::UnknownAtRule {
|
return Ok(Stmt::UnknownAtRule(Box::new(UnknownAtRule {
|
||||||
name,
|
name,
|
||||||
super_selector: Selector::new(self.span_before),
|
super_selector: Selector::new(self.span_before),
|
||||||
params: String::new(),
|
params: String::new(),
|
||||||
body: Vec::new(),
|
body: Vec::new(),
|
||||||
});
|
})));
|
||||||
}
|
}
|
||||||
while let Some(tok) = self.toks.next() {
|
while let Some(tok) = self.toks.next() {
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
@ -1053,12 +1041,12 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
body.append(&mut rules);
|
body.append(&mut rules);
|
||||||
|
|
||||||
Ok(Stmt::UnknownAtRule {
|
Ok(Stmt::UnknownAtRule(Box::new(UnknownAtRule {
|
||||||
name,
|
name,
|
||||||
super_selector: Selector::new(self.span_before),
|
super_selector: Selector::new(self.span_before),
|
||||||
params: params.trim().to_owned(),
|
params: params.trim().to_owned(),
|
||||||
body,
|
body,
|
||||||
})
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_media(&mut self) -> SassResult<Stmt> {
|
fn parse_media(&mut self) -> SassResult<Stmt> {
|
||||||
@ -1107,11 +1095,11 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
body.append(&mut rules);
|
body.append(&mut rules);
|
||||||
|
|
||||||
Ok(Stmt::Media {
|
Ok(Stmt::Media(Box::new(MediaRule {
|
||||||
super_selector: Selector::new(self.span_before),
|
super_selector: Selector::new(self.span_before),
|
||||||
query,
|
query,
|
||||||
body,
|
body,
|
||||||
})
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_at_root(&mut self) -> SassResult<Vec<Stmt>> {
|
fn parse_at_root(&mut self) -> SassResult<Vec<Stmt>> {
|
||||||
@ -1292,10 +1280,10 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
body.append(&mut rules);
|
body.append(&mut rules);
|
||||||
|
|
||||||
Ok(Stmt::Supports {
|
Ok(Stmt::Supports(Box::new(SupportsRule {
|
||||||
params: params.trim().to_owned(),
|
params: params.trim().to_owned(),
|
||||||
body,
|
body,
|
||||||
})
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code, clippy::unused_self)]
|
#[allow(dead_code, clippy::unused_self)]
|
||||||
|
@ -198,7 +198,7 @@ impl<'a> Parser<'a> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let value = self.parse_style_value()?;
|
let value = Box::new(self.parse_style_value()?);
|
||||||
match self.toks.peek() {
|
match self.toks.peek() {
|
||||||
Some(Token { kind: '}', .. }) => {
|
Some(Token { kind: '}', .. }) => {
|
||||||
styles.push(Style { property, value });
|
styles.push(Style { property, value });
|
||||||
@ -246,7 +246,7 @@ impl<'a> Parser<'a> {
|
|||||||
'{' => {
|
'{' => {
|
||||||
let mut v = vec![Style {
|
let mut v = vec![Style {
|
||||||
property: super_property.clone(),
|
property: super_property.clone(),
|
||||||
value,
|
value: Box::new(value),
|
||||||
}];
|
}];
|
||||||
v.append(&mut self.parse_style_group(super_property)?);
|
v.append(&mut self.parse_style_group(super_property)?);
|
||||||
return Ok(v);
|
return Ok(v);
|
||||||
@ -255,7 +255,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
return Ok(vec![Style {
|
return Ok(vec![Style {
|
||||||
property: super_property,
|
property: super_property,
|
||||||
value,
|
value: Box::new(value),
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::{error::SassResult, value::Value};
|
|||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub(crate) struct Style {
|
pub(crate) struct Style {
|
||||||
pub property: String,
|
pub property: String,
|
||||||
pub value: Spanned<Value>,
|
pub value: Box<Spanned<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
@ -21,10 +21,10 @@ impl Style {
|
|||||||
pub(crate) fn eval(self) -> SassResult<Self> {
|
pub(crate) fn eval(self) -> SassResult<Self> {
|
||||||
Ok(Style {
|
Ok(Style {
|
||||||
property: self.property,
|
property: self.property,
|
||||||
value: Spanned {
|
value: Box::new(Spanned {
|
||||||
span: self.value.span,
|
span: self.value.span,
|
||||||
node: self.value.node.eval(self.value.span)?.node,
|
node: self.value.node.eval(self.value.span)?.node,
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user