refactor ident parsing to separate function

This commit is contained in:
ConnorSkees 2020-04-01 18:42:58 -04:00
parent dd4a48165a
commit 4cfbf1c4c2

View File

@ -348,6 +348,81 @@ impl Value {
}) })
} }
fn ident<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>,
scope: &Scope,
super_selector: &Selector,
) -> SassResult<IntermediateValue> {
let mut s = eat_ident(toks, scope, super_selector)?;
match toks.peek() {
Some(Token { kind: '(', .. }) => {
toks.next();
let func = match scope.get_fn(&s) {
Ok(f) => f,
Err(_) => match GLOBAL_FUNCTIONS.get(&s) {
Some(f) => {
return Ok(IntermediateValue::Value(f(
&mut eat_call_args(toks, scope, super_selector)?,
scope,
)?))
}
None => {
s.push('(');
let mut unclosed_parens = 0;
while let Some(t) = toks.next() {
match &t.kind {
'(' => {
unclosed_parens += 1;
}
'#' if toks.next().unwrap().kind == '{' => s.push_str(
&parse_interpolation(toks, scope, super_selector)?
.to_string(),
),
'$' => s.push_str(
&scope
.get_var(&eat_ident(toks, scope, super_selector)?)?
.to_string(),
),
')' => {
if unclosed_parens <= 1 {
s.push(')');
break;
} else {
unclosed_parens -= 1;
}
}
_ => {}
}
s.push_str(&t.kind.to_string());
}
return Ok(IntermediateValue::Value(Value::Ident(s, QuoteKind::None)));
}
},
};
Ok(IntermediateValue::Value(
func.clone()
.args(&mut eat_call_args(toks, scope, super_selector)?)?
.call(super_selector, func.body())?,
))
}
_ => {
if let Ok(c) = crate::color::ColorName::try_from(s.as_ref()) {
Ok(IntermediateValue::Value(Value::Color(c.into_color(s))))
} else {
match s.to_ascii_lowercase().as_str() {
"true" => Ok(IntermediateValue::Value(Value::True)),
"false" => Ok(IntermediateValue::Value(Value::False)),
"null" => Ok(IntermediateValue::Value(Value::Null)),
"not" => Ok(IntermediateValue::Op(Op::Not)),
"and" => Ok(IntermediateValue::Op(Op::And)),
"or" => Ok(IntermediateValue::Op(Op::Or)),
_ => Ok(IntermediateValue::Value(Value::Ident(s, QuoteKind::None))),
}
}
}
}
}
fn parse_intermediate_value<I: Iterator<Item = Token>>( fn parse_intermediate_value<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>, toks: &mut Peekable<I>,
scope: &Scope, scope: &Scope,
@ -438,81 +513,7 @@ impl Value {
|| kind == '\\' || kind == '\\'
|| (!kind.is_ascii() && !kind.is_control()) => || (!kind.is_ascii() && !kind.is_control()) =>
{ {
let mut s = eat_ident(toks, scope, super_selector)?; Self::ident(toks, scope, super_selector)
match toks.peek() {
Some(Token { kind: '(', .. }) => {
toks.next();
let func = match scope.get_fn(&s) {
Ok(f) => f,
Err(_) => match GLOBAL_FUNCTIONS.get(&s) {
Some(f) => {
return Ok(IntermediateValue::Value(f(
&mut eat_call_args(toks, scope, super_selector)?,
scope,
)?))
}
None => {
s.push('(');
let mut unclosed_parens = 0;
while let Some(t) = toks.next() {
match &t.kind {
'(' => {
unclosed_parens += 1;
}
'#' if toks.next().unwrap().kind == '{' => s.push_str(
&parse_interpolation(toks, scope, super_selector)?
.to_string(),
),
'$' => s.push_str(
&scope
.get_var(&eat_ident(
toks,
scope,
super_selector,
)?)?
.to_string(),
),
')' => {
if unclosed_parens <= 1 {
s.push(')');
break;
} else {
unclosed_parens -= 1;
}
}
_ => {}
}
s.push_str(&t.kind.to_string());
}
return Ok(IntermediateValue::Value(Value::Ident(
s,
QuoteKind::None,
)));
}
},
};
Ok(IntermediateValue::Value(
func.clone()
.args(&mut eat_call_args(toks, scope, super_selector)?)?
.call(super_selector, func.body())?,
))
}
_ => {
if let Ok(c) = crate::color::ColorName::try_from(s.as_ref()) {
Ok(IntermediateValue::Value(Value::Color(c.into_color(s))))
} else {
match s.to_ascii_lowercase().as_str() {
"true" => Ok(IntermediateValue::Value(Value::True)),
"false" => Ok(IntermediateValue::Value(Value::False)),
"null" => Ok(IntermediateValue::Value(Value::Null)),
"not" => Ok(IntermediateValue::Op(Op::Not)),
"and" => Ok(IntermediateValue::Op(Op::And)),
"or" => Ok(IntermediateValue::Op(Op::Or)),
_ => Ok(IntermediateValue::Value(Value::Ident(s, QuoteKind::None))),
}
}
}
}
} }
q @ '"' | q @ '\'' => { q @ '"' | q @ '\'' => {
toks.next(); toks.next();