refactor keyframes and number parsing logic
This commit is contained in:
parent
91ef5dcfd5
commit
85a5b005cb
@ -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<String> {
|
||||
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<Token> =
|
||||
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<Token> = 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<Stmt> {
|
||||
|
@ -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<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> SassResult<Spanned<ParsedNumber>> {
|
||||
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<I: Iterator<Item = Token>>(
|
||||
});
|
||||
}
|
||||
|
||||
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<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
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<I: Iterator<Item = Token>>(
|
||||
let tok = toks.next().unwrap();
|
||||
buf.push(tok.kind);
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user