From 85a5b005cbabfb65f203dffd7ce8bd6aedd080ed Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 5 Jul 2020 17:59:48 +0800 Subject: [PATCH 1/2] refactor keyframes and number parsing logic --- src/parse/keyframes.rs | 74 +++++++++++++++++------------------------- src/utils/number.rs | 74 ++++++++++++++++++++---------------------- 2 files changed, 64 insertions(+), 84 deletions(-) diff --git a/src/parse/keyframes.rs b/src/parse/keyframes.rs index fad7f22..232ecc7 100644 --- a/src/parse/keyframes.rs +++ b/src/parse/keyframes.rs @@ -55,8 +55,7 @@ impl<'a, 'b> KeyframesSelectorParser<'a, 'b> { } } '0'..='9' => { - let mut num = String::new(); - eat_whole_number(self.parser.toks, &mut num); + let num = eat_whole_number(self.parser.toks); if !matches!(self.parser.toks.next(), Some(Token { kind: '%', .. })) { return Err(("expected \"%\".", tok.pos).into()); } @@ -81,7 +80,6 @@ impl<'a, 'b> KeyframesSelectorParser<'a, 'b> { impl<'a> Parser<'a> { fn parse_keyframes_name(&mut self) -> SassResult { let mut name = String::new(); - let mut found_open_brace = false; self.whitespace_or_comment(); while let Some(tok) = self.toks.next() { match tok.kind { @@ -98,19 +96,14 @@ impl<'a> Parser<'a> { name.push(' '); } '{' => { - found_open_brace = true; - break; + // todo: we can avoid the reallocation by trimming before emitting + // (in `output.rs`) + return Ok(name.trim().to_string()); } _ => name.push(tok.kind), } } - - if !found_open_brace { - return Err(("expected \"{\".", self.span_before).into()); - } - - // todo: we can avoid the reallocation by trimming before emitting (in `output.rs`) - Ok(name.trim().to_string()) + Err(("expected \"{\".", self.span_before).into()) } pub(super) fn parse_keyframes_selector( @@ -125,8 +118,6 @@ impl<'a> Parser<'a> { self.span_before = span; - let mut found_curly = false; - while let Some(tok) = self.toks.next() { span = span.merge(tok.pos()); match tok.kind { @@ -157,41 +148,34 @@ impl<'a> Parser<'a> { string.push(' '); } '{' => { - found_curly = true; - break; + let sel_toks: Vec = + string.chars().map(|x| Token::new(span, x)).collect(); + + let selector = KeyframesSelectorParser::new(&mut Parser { + toks: &mut sel_toks.into_iter().peekmore(), + map: self.map, + path: self.path, + scopes: self.scopes, + global_scope: self.global_scope, + super_selectors: self.super_selectors, + span_before: self.span_before, + content: self.content, + in_mixin: self.in_mixin, + in_function: self.in_function, + in_control_flow: self.in_control_flow, + at_root: self.at_root, + at_root_has_selector: self.at_root_has_selector, + extender: self.extender, + in_keyframes: self.in_keyframes, + }) + .parse_keyframes_selector()?; + + return Ok(selector); } c => string.push(c), } } - - if !found_curly { - return Err(("expected \"{\".", span).into()); - } - - let sel_toks: Vec = string.chars().map(|x| Token::new(span, x)).collect(); - - let mut iter = sel_toks.into_iter().peekmore(); - - let selector = KeyframesSelectorParser::new(&mut Parser { - toks: &mut iter, - map: self.map, - path: self.path, - scopes: self.scopes, - global_scope: self.global_scope, - super_selectors: self.super_selectors, - span_before: self.span_before, - content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, - at_root: self.at_root, - at_root_has_selector: self.at_root_has_selector, - extender: self.extender, - in_keyframes: self.in_keyframes, - }) - .parse_keyframes_selector()?; - - Ok(selector) + Err(("expected \"{\".", span).into()) } pub(super) fn parse_keyframes(&mut self) -> SassResult { diff --git a/src/utils/number.rs b/src/utils/number.rs index c84ac4f..7102607 100644 --- a/src/utils/number.rs +++ b/src/utils/number.rs @@ -1,5 +1,4 @@ use codemap::Spanned; - use peekmore::PeekMoreIterator; use crate::{error::SassResult, Token}; @@ -49,10 +48,8 @@ impl ParsedNumber { pub(crate) fn eat_number>( toks: &mut PeekMoreIterator, ) -> SassResult> { - let mut whole = String::with_capacity(1); - // TODO: merge this span with chars - let span = toks.peek().unwrap().pos; - eat_whole_number(toks, &mut whole); + let mut span = toks.peek().unwrap().pos; + let mut whole = eat_whole_number(toks); if toks.peek().is_none() { return Ok(Spanned { @@ -61,66 +58,64 @@ pub(crate) fn eat_number>( }); } - let mut dec = String::new(); - let next_tok = *toks.peek().unwrap(); - if next_tok.kind == '.' { + let dec_len = if next_tok.kind == '.' { toks.next(); - eat_whole_number(toks, &mut dec); + let dec = eat_whole_number(toks); if dec.is_empty() { return Err(("Expected digit.", next_tok.pos()).into()); } - } + + whole.push_str(&dec); + + dec.len() + } else { + 0 + }; let mut times_ten = String::new(); let mut times_ten_is_postive = true; - #[allow(clippy::never_loop)] - loop { - if let Some(Token { kind: 'e', .. }) | Some(Token { kind: 'E', .. }) = toks.peek() { - let t = if let Some(tok) = toks.peek_forward(1) { - *tok - } else { - break; - }; + if let Some(Token { kind: 'e', .. }) | Some(Token { kind: 'E', .. }) = toks.peek() { + if let Some(&tok) = toks.peek_next() { + if tok.kind == '-' { + toks.next(); + times_ten_is_postive = false; - match t.kind { - '-' => { - toks.next(); - times_ten_is_postive = false; + toks.next(); + times_ten = eat_whole_number(toks); + + if times_ten.is_empty() { + return Err(("Expected digit.", toks.peek().unwrap_or(&tok).pos).into()); } - '0'..='9' => {} - _ => break, - } + } else if matches!(tok.kind, '0'..='9') { + toks.next(); + times_ten = eat_whole_number(toks); - toks.next(); - - eat_whole_number(toks, &mut times_ten); - - if times_ten.is_empty() && !times_ten_is_postive { - return Err(("Expected digit.", toks.peek().unwrap_or(&t).pos).into()); - } else if times_ten.len() > 2 { - return Err(("Exponent too large.", toks.peek().unwrap_or(&t).pos).into()); + if times_ten.len() > 2 { + return Err(("Exponent too large.", toks.peek().unwrap_or(&tok).pos).into()); + } } } - break; + } + + if let Ok(Some(Token { pos, .. })) = toks.peek_previous() { + span = span.merge(*pos); } toks.reset_cursor(); - whole.push_str(&dec); - Ok(Spanned { - node: ParsedNumber::new(whole, dec.len(), times_ten, times_ten_is_postive), + node: ParsedNumber::new(whole, dec_len, times_ten, times_ten_is_postive), span, }) } pub(crate) fn eat_whole_number>( toks: &mut PeekMoreIterator, - buf: &mut String, -) { +) -> String { + let mut buf = String::new(); while let Some(c) = toks.peek() { if !c.kind.is_ascii_digit() { break; @@ -128,4 +123,5 @@ pub(crate) fn eat_whole_number>( let tok = toks.next().unwrap(); buf.push(tok.kind); } + buf } From 85ec26001a87482de3e9e49d3fda5187edccbe65 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 5 Jul 2020 19:16:44 +0800 Subject: [PATCH 2/2] Keep parser context with bitflags --- Cargo.toml | 1 + src/builtin/meta.rs | 4 +- src/lib.rs | 17 ++----- src/parse/function.rs | 11 ++--- src/parse/import.rs | 5 +- src/parse/keyframes.rs | 12 ++--- src/parse/mixin.rs | 14 ++---- src/parse/mod.rs | 98 ++++++++++++++-------------------------- src/parse/value/parse.rs | 5 +- src/parse/variable.rs | 6 +-- src/value/mod.rs | 5 +- 11 files changed, 57 insertions(+), 121 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 80fe9d4..5fc5e54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ codemap = "0.1.3" peekmore = "0.5.2" wasm-bindgen = { version = "0.2.63", optional = true } beef = "0.4.4" +bitflags = "1.2.1" # criterion is not a dev-dependency because it makes tests take too # long to compile, and you cannot make dev-dependencies optional criterion = { version = "0.3.2", optional = true } diff --git a/src/builtin/meta.rs b/src/builtin/meta.rs index 725c798..c809781 100644 --- a/src/builtin/meta.rs +++ b/src/builtin/meta.rs @@ -6,7 +6,7 @@ use crate::{ args::CallArgs, common::QuoteKind, error::SassResult, - parse::Parser, + parse::{Flags, Parser}, unit::Unit, value::{SassFunction, Value}, }; @@ -232,7 +232,7 @@ fn call(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult { #[allow(clippy::needless_pass_by_value)] fn content_exists(args: CallArgs, parser: &mut Parser<'_>) -> SassResult { args.max_args(0)?; - if !parser.in_mixin { + if !parser.flags.contains(Flags::IN_MIXIN) { return Err(( "content-exists() may only be called within a mixin.", parser.span_before, diff --git a/src/lib.rs b/src/lib.rs index 4a7916d..8b6ea86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ pub(crate) use crate::token::Token; use crate::{ lexer::Lexer, output::Css, - parse::{common::NeverEmptyVec, Parser}, + parse::{common::NeverEmptyVec, Flags, Parser}, scope::Scope, selector::{Extender, Selector}, }; @@ -149,13 +149,10 @@ pub fn from_path(p: &str) -> Result { super_selectors: &mut NeverEmptyVec::new(Selector::new(empty_span)), span_before: empty_span, content: &mut Vec::new(), - in_mixin: false, - in_function: false, - in_control_flow: false, + flags: Flags::empty(), at_root: true, at_root_has_selector: false, extender: &mut Extender::new(empty_span), - in_keyframes: false, } .parse() .map_err(|e| raw_to_parse_error(&map, *e))?; @@ -194,13 +191,10 @@ pub fn from_string(p: String) -> Result { super_selectors: &mut NeverEmptyVec::new(Selector::new(empty_span)), span_before: empty_span, content: &mut Vec::new(), - in_mixin: false, - in_function: false, - in_control_flow: false, + flags: Flags::empty(), at_root: true, at_root_has_selector: false, extender: &mut Extender::new(empty_span), - in_keyframes: false, } .parse() .map_err(|e| raw_to_parse_error(&map, *e))?; @@ -230,13 +224,10 @@ pub fn from_string(p: String) -> std::result::Result { super_selectors: &mut NeverEmptyVec::new(Selector::new(empty_span)), span_before: empty_span, content: &mut Vec::new(), - in_mixin: false, - in_function: false, - in_control_flow: false, + flags: Flags::empty(), at_root: true, at_root_has_selector: false, extender: &mut Extender::new(empty_span), - in_keyframes: false, } .parse() .map_err(|e| raw_to_parse_error(&map, *e).to_string())?; diff --git a/src/parse/function.rs b/src/parse/function.rs index 01fdccd..5a280c8 100644 --- a/src/parse/function.rs +++ b/src/parse/function.rs @@ -11,7 +11,7 @@ use crate::{ Token, }; -use super::{NeverEmptyVec, Parser, Stmt}; +use super::{Flags, NeverEmptyVec, Parser, Stmt}; /// Names that functions are not allowed to have const FORBIDDEN_IDENTIFIERS: [&str; 7] = @@ -22,11 +22,11 @@ impl<'a> Parser<'a> { self.whitespace_or_comment(); let Spanned { node: name, span } = self.parse_identifier()?; - if self.in_mixin { + if self.flags.contains(Flags::IN_MIXIN) { return Err(("Mixins may not contain function declarations.", span).into()); } - if self.in_control_flow { + if self.flags.contains(Flags::IN_CONTROL_FLOW) { return Err(("Functions may not be declared in control directives.", span).into()); } @@ -88,13 +88,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: true, - in_control_flow: self.in_control_flow, + flags: self.flags | Flags::IN_FUNCTION, at_root: false, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; diff --git a/src/parse/import.rs b/src/parse/import.rs index cd6a509..24e37bf 100644 --- a/src/parse/import.rs +++ b/src/parse/import.rs @@ -83,13 +83,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: file.span.subspan(0, 0), content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse(); } diff --git a/src/parse/keyframes.rs b/src/parse/keyframes.rs index 232ecc7..a083b71 100644 --- a/src/parse/keyframes.rs +++ b/src/parse/keyframes.rs @@ -10,7 +10,7 @@ use crate::{ Token, }; -use super::Parser; +use super::{Flags, Parser}; impl fmt::Display for KeyframesSelector { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -160,13 +160,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, }) .parse_keyframes_selector()?; @@ -192,11 +189,8 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags | Flags::IN_KEYFRAMES, at_root: false, - in_keyframes: true, at_root_has_selector: self.at_root_has_selector, extender: self.extender, } diff --git a/src/parse/mixin.rs b/src/parse/mixin.rs index 16df87a..5083d68 100644 --- a/src/parse/mixin.rs +++ b/src/parse/mixin.rs @@ -10,7 +10,7 @@ use crate::{ Token, }; -use super::{NeverEmptyVec, Parser, Stmt}; +use super::{Flags, NeverEmptyVec, Parser, Stmt}; impl<'a> Parser<'a> { pub(super) fn parse_mixin(&mut self) -> SassResult<()> { @@ -127,14 +127,11 @@ impl<'a> Parser<'a> { global_scope: self.global_scope, super_selectors: self.super_selectors, span_before: self.span_before, - in_mixin: true, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags | Flags::IN_MIXIN, content: self.content, at_root: false, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; @@ -144,7 +141,7 @@ impl<'a> Parser<'a> { } pub(super) fn parse_content_rule(&mut self) -> SassResult> { - if self.in_mixin { + if self.flags.contains(Flags::IN_MIXIN) { let mut scope = self .content .last() @@ -175,14 +172,11 @@ impl<'a> Parser<'a> { global_scope: self.global_scope, super_selectors: self.super_selectors, span_before: self.span_before, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, content: self.content, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()? } else { diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 32cfb8f..5811165 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -66,11 +66,21 @@ pub(crate) enum Stmt { KeyframesRuleSet(Box), } +bitflags::bitflags! { + // todo: try to remove the flag IN_CONTROL_FLOW + /// Flags to indicate the context during parsing. + pub struct Flags: u8 { + const IN_MIXIN = 1; + const IN_FUNCTION = 1 << 1; + const IN_CONTROL_FLOW = 1 << 2; + const IN_KEYFRAMES = 1 << 3; + } +} + /// We could use a generic for the toks, but it makes the API /// much simpler to work with if it isn't generic. The performance /// hit (if there is one) is not important for now. -// todo: refactor `in_mixin`, in_function`, and `at_root` into state machine enum -#[allow(clippy::struct_excessive_bools)] +// todo: merge at_root and at_root_has_selector into an enum pub(crate) struct Parser<'a> { pub toks: &'a mut PeekMoreIterator>, pub map: &'a mut CodeMap, @@ -80,10 +90,7 @@ pub(crate) struct Parser<'a> { pub super_selectors: &'a mut NeverEmptyVec, pub span_before: Span, pub content: &'a mut Vec, - pub in_mixin: bool, - pub in_function: bool, - pub in_control_flow: bool, - pub in_keyframes: bool, + pub flags: Flags, /// Whether this parser is at the root of the document /// E.g. not inside a style, mixin, or function pub at_root: bool, @@ -98,7 +105,7 @@ impl<'a> Parser<'a> { let mut stmts = Vec::new(); while self.toks.peek().is_some() { stmts.append(&mut self.parse_stmt()?); - if self.in_function && !stmts.is_empty() { + if self.flags.contains(Flags::IN_FUNCTION) && !stmts.is_empty() { return Ok(stmts); } self.at_root = true; @@ -109,7 +116,7 @@ impl<'a> Parser<'a> { fn parse_stmt(&mut self) -> SassResult> { let mut stmts = Vec::new(); while let Some(Token { kind, pos }) = self.toks.peek() { - if self.in_function && !stmts.is_empty() { + if self.flags.contains(Flags::IN_FUNCTION) && !stmts.is_empty() { return Ok(stmts); } self.span_before = *pos; @@ -125,7 +132,7 @@ impl<'a> Parser<'a> { AtRuleKind::Include => stmts.append(&mut self.parse_include()?), AtRuleKind::Function => self.parse_function()?, AtRuleKind::Return => { - if self.in_function { + if self.flags.contains(Flags::IN_FUNCTION) { return Ok(vec![Stmt::Return(self.parse_return()?)]); } else { return Err(( @@ -235,7 +242,7 @@ impl<'a> Parser<'a> { // dart-sass seems to special-case the error message here? '!' | '{' => return Err(("expected \"}\".", *pos).into()), _ => { - if self.in_keyframes { + if self.flags.contains(Flags::IN_KEYFRAMES) { match self.is_selector_or_style()? { SelectorOrStyle::Style(property, value) => { if let Some(value) = value { @@ -375,13 +382,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, }, allows_parent, true, @@ -607,13 +611,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse(); } @@ -630,13 +631,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse() } @@ -764,7 +762,7 @@ impl<'a> Parser<'a> { span: var.span, }, ); - if self.in_function { + if self.flags.contains(Flags::IN_FUNCTION) { let these_stmts = Parser { toks: &mut body.clone().into_iter().peekmore(), map: self.map, @@ -774,13 +772,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; if !these_stmts.is_empty() { @@ -797,13 +792,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?, ); @@ -838,7 +830,7 @@ impl<'a> Parser<'a> { let mut val = self.parse_value_from_vec(cond.clone())?; self.scopes.push(self.scopes.last().clone()); while val.node.is_true() { - if self.in_function { + if self.flags.contains(Flags::IN_FUNCTION) { let these_stmts = Parser { toks: &mut body.clone().into_iter().peekmore(), map: self.map, @@ -848,13 +840,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; if !these_stmts.is_empty() { @@ -871,13 +860,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?, ); @@ -972,7 +958,7 @@ impl<'a> Parser<'a> { } } - if self.in_function { + if self.flags.contains(Flags::IN_FUNCTION) { let these_stmts = Parser { toks: &mut body.clone().into_iter().peekmore(), map: self.map, @@ -982,13 +968,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; if !these_stmts.is_empty() { @@ -1005,13 +988,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: true, + flags: self.flags | Flags::IN_CONTROL_FLOW, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?, ); @@ -1102,13 +1082,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: false, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse_stmt()?; @@ -1171,13 +1148,10 @@ impl<'a> Parser<'a> { super_selectors: &mut NeverEmptyVec::new(at_rule_selector.clone()), span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: true, at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()? .into_iter() @@ -1213,13 +1187,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse_selector(false, true, String::new())?; @@ -1292,13 +1263,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: false, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse()?; diff --git a/src/parse/value/parse.rs b/src/parse/value/parse.rs index 7f84229..4983b06 100644 --- a/src/parse/value/parse.rs +++ b/src/parse/value/parse.rs @@ -188,13 +188,10 @@ impl<'a> Parser<'a> { super_selectors: self.super_selectors, span_before: self.span_before, content: self.content, - in_mixin: self.in_mixin, - in_function: self.in_function, - in_control_flow: self.in_control_flow, + flags: self.flags, at_root: self.at_root, at_root_has_selector: self.at_root_has_selector, extender: self.extender, - in_keyframes: self.in_keyframes, } .parse_value() } diff --git a/src/parse/variable.rs b/src/parse/variable.rs index 4bd9791..146d074 100644 --- a/src/parse/variable.rs +++ b/src/parse/variable.rs @@ -11,7 +11,7 @@ use crate::{ Token, }; -use super::Parser; +use super::{Flags, Parser}; #[derive(Debug)] struct VariableValue { @@ -46,7 +46,7 @@ impl<'a> Parser<'a> { } if value.default { - if self.at_root && !self.in_control_flow { + if self.at_root && !self.flags.contains(Flags::IN_CONTROL_FLOW) { if !self.global_scope.var_exists_no_global(&ident) { self.global_scope.insert_var(ident, value.value); } @@ -60,7 +60,7 @@ impl<'a> Parser<'a> { } } } else if self.at_root { - if self.in_control_flow { + if self.flags.contains(Flags::IN_CONTROL_FLOW) { if self.global_scope.var_exists_no_global(&ident) { self.global_scope.insert_var(ident, value.value); } else { diff --git a/src/value/mod.rs b/src/value/mod.rs index bc2ce1a..9f4716b 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -335,13 +335,10 @@ impl Value { super_selectors: parser.super_selectors, span_before: parser.span_before, content: parser.content, - in_mixin: parser.in_mixin, - in_function: parser.in_function, - in_control_flow: parser.in_control_flow, + flags: parser.flags, at_root: parser.at_root, at_root_has_selector: parser.at_root_has_selector, extender: parser.extender, - in_keyframes: parser.in_keyframes, } .parse_selector(allows_parent, true, String::new()) }