refactor paren parsing (still susceptible to stack overflow)
This commit is contained in:
parent
bf8cb594da
commit
b2451b45c6
@ -141,6 +141,72 @@ impl IsWhitespace for IntermediateValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_paren(
|
||||||
|
t: Vec<Token>,
|
||||||
|
scope: &Scope,
|
||||||
|
super_selector: &Selector,
|
||||||
|
space_separated: &mut Vec<Value>,
|
||||||
|
) -> SassResult<()> {
|
||||||
|
if t.is_empty() {
|
||||||
|
space_separated.push(Value::List(
|
||||||
|
Vec::new(),
|
||||||
|
ListSeparator::Space,
|
||||||
|
Brackets::None,
|
||||||
|
));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let paren_toks = &mut t.into_iter().peekable();
|
||||||
|
|
||||||
|
let mut map = SassMap::new();
|
||||||
|
let key = Value::from_tokens(
|
||||||
|
&mut read_until_char(paren_toks, ':').into_iter().peekable(),
|
||||||
|
scope,
|
||||||
|
super_selector,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if paren_toks.peek().is_none() {
|
||||||
|
space_separated.push(Value::Paren(Box::new(key)));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = Value::from_tokens(
|
||||||
|
&mut read_until_char(paren_toks, ',').into_iter().peekable(),
|
||||||
|
scope,
|
||||||
|
super_selector,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
map.insert(key, val);
|
||||||
|
|
||||||
|
if paren_toks.peek().is_none() {
|
||||||
|
space_separated.push(Value::Map(map));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let key = Value::from_tokens(
|
||||||
|
&mut read_until_char(paren_toks, ':').into_iter().peekable(),
|
||||||
|
scope,
|
||||||
|
super_selector,
|
||||||
|
)?;
|
||||||
|
devour_whitespace(paren_toks);
|
||||||
|
let val = Value::from_tokens(
|
||||||
|
&mut read_until_char(paren_toks, ',').into_iter().peekable(),
|
||||||
|
scope,
|
||||||
|
super_selector,
|
||||||
|
)?;
|
||||||
|
devour_whitespace(paren_toks);
|
||||||
|
if map.insert(key, val) {
|
||||||
|
return Err("Duplicate key.".into());
|
||||||
|
}
|
||||||
|
if paren_toks.peek().is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
space_separated.push(Value::Map(map));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn eat_op<I: Iterator<Item = IntermediateValue>>(
|
fn eat_op<I: Iterator<Item = IntermediateValue>>(
|
||||||
iter: &mut Peekable<I>,
|
iter: &mut Peekable<I>,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
@ -229,10 +295,11 @@ fn single_value<I: Iterator<Item = IntermediateValue>>(
|
|||||||
v => Value::List(vec![v], ListSeparator::Space, Brackets::Bracketed),
|
v => Value::List(vec![v], ListSeparator::Space, Brackets::Bracketed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IntermediateValue::Paren(t) => {
|
IntermediateValue::Paren(t) => Value::Paren(Box::new(Value::from_tokens(
|
||||||
let inner = Value::from_tokens(&mut t.into_iter().peekable(), scope, super_selector)?;
|
&mut t.into_iter().peekable(),
|
||||||
Value::Paren(Box::new(inner))
|
scope,
|
||||||
}
|
super_selector,
|
||||||
|
)?)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,63 +343,7 @@ impl Value {
|
|||||||
v => Value::List(vec![v], ListSeparator::Space, Brackets::Bracketed),
|
v => Value::List(vec![v], ListSeparator::Space, Brackets::Bracketed),
|
||||||
}),
|
}),
|
||||||
IntermediateValue::Paren(t) => {
|
IntermediateValue::Paren(t) => {
|
||||||
if t.is_empty() {
|
parse_paren(t, scope, super_selector, &mut space_separated)?;
|
||||||
space_separated.push(Value::List(
|
|
||||||
Vec::new(),
|
|
||||||
ListSeparator::Space,
|
|
||||||
Brackets::None,
|
|
||||||
));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let paren_toks = &mut t.into_iter().peekable();
|
|
||||||
|
|
||||||
let mut map = SassMap::new();
|
|
||||||
let key = Value::from_tokens(
|
|
||||||
&mut read_until_char(paren_toks, ':').into_iter().peekable(),
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if paren_toks.peek().is_none() {
|
|
||||||
space_separated.push(Value::Paren(Box::new(key)));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let val = Self::from_tokens(
|
|
||||||
&mut read_until_char(paren_toks, ',').into_iter().peekable(),
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
map.insert(key, val);
|
|
||||||
|
|
||||||
if paren_toks.peek().is_none() {
|
|
||||||
space_separated.push(Value::Map(map));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let key = Value::from_tokens(
|
|
||||||
&mut read_until_char(paren_toks, ':').into_iter().peekable(),
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
)?;
|
|
||||||
devour_whitespace(paren_toks);
|
|
||||||
let val = Self::from_tokens(
|
|
||||||
&mut read_until_char(paren_toks, ',').into_iter().peekable(),
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
)?;
|
|
||||||
devour_whitespace(paren_toks);
|
|
||||||
if map.insert(key, val) {
|
|
||||||
return Err("Duplicate key.".into());
|
|
||||||
}
|
|
||||||
if paren_toks.peek().is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
space_separated.push(Value::Map(map))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user