further reduce allocations in @if
This commit is contained in:
parent
11e859705a
commit
fd4073aaca
@ -39,6 +39,7 @@ mod keyframes;
|
|||||||
mod media;
|
mod media;
|
||||||
mod mixin;
|
mod mixin;
|
||||||
mod style;
|
mod style;
|
||||||
|
mod throw_away;
|
||||||
mod value;
|
mod value;
|
||||||
mod variable;
|
mod variable;
|
||||||
|
|
||||||
@ -508,23 +509,6 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
fn throw_away_until_closing_curly_brace(&mut self) {
|
|
||||||
let mut scope = 0;
|
|
||||||
while let Some(tok) = self.toks.next() {
|
|
||||||
match tok.kind {
|
|
||||||
'}' => {
|
|
||||||
if scope == 0 {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
scope -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'{' => scope += 1,
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_if(&mut self) -> SassResult<Vec<Stmt>> {
|
fn parse_if(&mut self) -> SassResult<Vec<Stmt>> {
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
|
|
||||||
@ -536,7 +520,7 @@ impl<'a> Parser<'a> {
|
|||||||
// consume the open curly brace
|
// consume the open curly brace
|
||||||
let span_before = match self.toks.next() {
|
let span_before = match self.toks.next() {
|
||||||
Some(Token { kind: '{', pos }) => pos,
|
Some(Token { kind: '{', pos }) => pos,
|
||||||
Some(..) | None => return Err(("expected \"}\".", self.span_before).into()),
|
Some(..) | None => return Err(("expected \"{\".", self.span_before).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.toks.peek().is_none() {
|
if self.toks.peek().is_none() {
|
||||||
@ -563,7 +547,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
} else {
|
} else {
|
||||||
self.throw_away_until_closing_curly_brace();
|
self.throw_away_until_closing_curly_brace()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
@ -590,10 +574,20 @@ impl<'a> Parser<'a> {
|
|||||||
{
|
{
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
let cond = read_until_open_curly_brace(self.toks)?;
|
let cond = if !found_true {
|
||||||
// todo: ensure there is a `{`
|
let v = self.parse_value()?.node.is_true();
|
||||||
self.toks.next();
|
match self.toks.next() {
|
||||||
if !found_true && self.parse_value_from_vec(cond)?.is_true() {
|
Some(Token { kind: '{', .. }) => {}
|
||||||
|
Some(..) | None => {
|
||||||
|
return Err(("expected \"{\".", self.span_before).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
self.throw_away_until_open_curly_brace()?;
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if cond {
|
||||||
found_true = true;
|
found_true = true;
|
||||||
body = Parser {
|
body = Parser {
|
||||||
toks: self.toks,
|
toks: self.toks,
|
||||||
@ -610,17 +604,15 @@ impl<'a> Parser<'a> {
|
|||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
// todo: ensure there is a `{`
|
|
||||||
self.toks.next();
|
|
||||||
} else {
|
} else {
|
||||||
self.throw_away_until_closing_curly_brace();
|
self.throw_away_until_closing_curly_brace()?;
|
||||||
}
|
}
|
||||||
self.whitespace();
|
self.whitespace();
|
||||||
}
|
}
|
||||||
'{' => {
|
'{' => {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
if found_true {
|
if found_true {
|
||||||
self.throw_away_until_closing_curly_brace();
|
self.throw_away_until_closing_curly_brace()?;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return Parser {
|
return Parser {
|
||||||
|
125
src/parse/throw_away.rs
Normal file
125
src/parse/throw_away.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//! Consume tokens without allocating
|
||||||
|
|
||||||
|
use crate::{error::SassResult, Token};
|
||||||
|
|
||||||
|
use super::Parser;
|
||||||
|
|
||||||
|
impl<'a> Parser<'a> {
|
||||||
|
pub(super) fn throw_away_until_newline(&mut self) {
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
if tok.kind == '\n' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn throw_away_quoted_string(&mut self, q: char) -> SassResult<()> {
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
match tok.kind {
|
||||||
|
'"' if q == '"' => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
'\'' if q == '\'' => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
if self.toks.next().is_none() {
|
||||||
|
return Err((format!("Expected {}.", q), tok.pos).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'#' => {
|
||||||
|
self.toks.next();
|
||||||
|
self.throw_away_until_closing_curly_brace()?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err((format!("Expected {}.", q), self.span_before).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn throw_away_until_open_curly_brace(&mut self) -> SassResult<()> {
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
match tok.kind {
|
||||||
|
'{' => return Ok(()),
|
||||||
|
'/' => {
|
||||||
|
match self.toks.peek() {
|
||||||
|
Some(Token { kind: '/', .. }) => self.throw_away_until_newline(),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
'\\' | '#' => {
|
||||||
|
self.toks.next();
|
||||||
|
}
|
||||||
|
q @ '"' | q @ '\'' => {
|
||||||
|
self.throw_away_quoted_string(q)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(("expected \"{\".", self.span_before).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn throw_away_until_closing_curly_brace(&mut self) -> SassResult<()> {
|
||||||
|
let mut nesting = 0;
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
match tok.kind {
|
||||||
|
q @ '"' | q @ '\'' => {
|
||||||
|
self.throw_away_quoted_string(q)?;
|
||||||
|
}
|
||||||
|
'{' => {
|
||||||
|
nesting += 1;
|
||||||
|
}
|
||||||
|
'}' => {
|
||||||
|
if nesting == 0 {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
nesting -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'/' => match self.toks.peek() {
|
||||||
|
Some(Token { kind: '/', .. }) => {
|
||||||
|
self.throw_away_until_newline();
|
||||||
|
}
|
||||||
|
Some(..) | None => continue,
|
||||||
|
},
|
||||||
|
'(' => {
|
||||||
|
self.throw_away_until_closing_paren()?;
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
self.toks.next();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(("expected \"}\".", self.span_before).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn throw_away_until_closing_paren(&mut self) -> SassResult<()> {
|
||||||
|
let mut scope = 0;
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
match tok.kind {
|
||||||
|
')' => {
|
||||||
|
if scope < 1 {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
scope -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'(' => scope += 1,
|
||||||
|
'"' | '\'' => {
|
||||||
|
self.throw_away_quoted_string(tok.kind)?;
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
match self.toks.next() {
|
||||||
|
Some(tok) => tok,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(("expected \")\".", self.span_before).into())
|
||||||
|
}
|
||||||
|
}
|
@ -224,7 +224,6 @@ pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
t.push(toks.next().unwrap());
|
|
||||||
t.push(match toks.next() {
|
t.push(match toks.next() {
|
||||||
Some(tok) => tok,
|
Some(tok) => tok,
|
||||||
None => continue,
|
None => continue,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user