emit proper error on unclosed quote
This commit is contained in:
parent
b653c55ad7
commit
737a6ba90d
@ -262,7 +262,7 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'(' => {
|
||||
default.push(toks.next().unwrap());
|
||||
default.extend(read_until_closing_paren(toks));
|
||||
default.extend(read_until_closing_paren(toks)?);
|
||||
}
|
||||
_ => default.push(toks.next().unwrap()),
|
||||
}
|
||||
@ -380,15 +380,15 @@ pub(crate) fn eat_call_args<I: Iterator<Item = Token>>(
|
||||
',' => break,
|
||||
'[' => {
|
||||
val.push(tok);
|
||||
val.extend(read_until_closing_square_brace(toks));
|
||||
val.extend(read_until_closing_square_brace(toks)?);
|
||||
}
|
||||
'(' => {
|
||||
val.push(tok);
|
||||
val.extend(read_until_closing_paren(toks));
|
||||
val.extend(read_until_closing_paren(toks)?);
|
||||
}
|
||||
'"' | '\'' => {
|
||||
val.push(tok);
|
||||
val.extend(read_until_closing_quote(toks, tok.kind));
|
||||
val.extend(read_until_closing_quote(toks, tok.kind)?);
|
||||
}
|
||||
_ => val.push(tok),
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ pub(crate) fn parse_each<I: Iterator<Item = Token>>(
|
||||
return Err(("Expected \"in\".", i.span).into());
|
||||
}
|
||||
devour_whitespace(toks);
|
||||
let iter_val = Value::from_vec(read_until_open_curly_brace(toks), scope, super_selector)?;
|
||||
let iter_val = Value::from_vec(read_until_open_curly_brace(toks)?, scope, super_selector)?;
|
||||
let iter = match iter_val.node.eval(iter_val.span)?.node {
|
||||
Value::List(v, ..) => v,
|
||||
Value::Map(m) => m
|
||||
@ -130,7 +130,7 @@ pub(crate) fn parse_each<I: Iterator<Item = Token>>(
|
||||
};
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks)?;
|
||||
body.push(toks.next().unwrap());
|
||||
devour_whitespace(toks);
|
||||
|
||||
|
@ -148,7 +148,7 @@ pub(crate) fn parse_for<I: Iterator<Item = Token>>(
|
||||
}
|
||||
};
|
||||
|
||||
let to_toks = read_until_open_curly_brace(toks);
|
||||
let to_toks = read_until_open_curly_brace(toks)?;
|
||||
toks.next();
|
||||
let to_val = Value::from_vec(to_toks, scope, super_selector)?;
|
||||
let to = match to_val.node.eval(to_val.span)?.node {
|
||||
@ -164,7 +164,7 @@ pub(crate) fn parse_for<I: Iterator<Item = Token>>(
|
||||
.into())
|
||||
}
|
||||
};
|
||||
let body = read_until_closing_curly_brace(toks);
|
||||
let body = read_until_closing_curly_brace(toks)?;
|
||||
toks.next();
|
||||
|
||||
devour_whitespace(toks);
|
||||
|
@ -58,7 +58,7 @@ impl Function {
|
||||
|
||||
devour_whitespace(toks);
|
||||
|
||||
let mut body = read_until_closing_curly_brace(toks); //eat_stmts(toks, &mut scope.clone(), super_selector)?;
|
||||
let mut body = read_until_closing_curly_brace(toks)?; //eat_stmts(toks, &mut scope.clone(), super_selector)?;
|
||||
body.push(toks.next().unwrap());
|
||||
devour_whitespace(toks);
|
||||
|
||||
|
@ -41,13 +41,13 @@ impl If {
|
||||
) -> SassResult<If> {
|
||||
devour_whitespace_or_comment(toks)?;
|
||||
let mut branches = Vec::new();
|
||||
let init_toks = read_until_open_curly_brace(toks);
|
||||
if init_toks.is_empty() || toks.next().is_none() {
|
||||
let init_cond_toks = read_until_open_curly_brace(toks)?;
|
||||
if init_cond_toks.is_empty() || toks.next().is_none() {
|
||||
return Err(("Expected expression.", span_before).into());
|
||||
}
|
||||
let init_cond = Value::from_vec(init_toks, scope, super_selector)?;
|
||||
let init_cond = Value::from_vec(init_cond_toks, scope, super_selector)?;
|
||||
devour_whitespace_or_comment(toks)?;
|
||||
let mut init_toks = read_until_closing_curly_brace(toks);
|
||||
let mut init_toks = read_until_closing_curly_brace(toks)?;
|
||||
if let Some(tok) = toks.next() {
|
||||
init_toks.push(tok);
|
||||
} else {
|
||||
@ -80,18 +80,18 @@ impl If {
|
||||
'i' if toks.next().unwrap().kind.to_ascii_lowercase() == 'f' => {
|
||||
toks.next();
|
||||
let cond = Value::from_vec(
|
||||
read_until_open_curly_brace(toks),
|
||||
read_until_open_curly_brace(toks)?,
|
||||
scope,
|
||||
super_selector,
|
||||
)?;
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
branches.push(Branch::new(cond, read_until_closing_curly_brace(toks)));
|
||||
branches.push(Branch::new(cond, read_until_closing_curly_brace(toks)?));
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
}
|
||||
'{' => {
|
||||
else_ = read_until_closing_curly_brace(toks);
|
||||
else_ = read_until_closing_curly_brace(toks)?;
|
||||
toks.next();
|
||||
break;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ impl Mixin {
|
||||
|
||||
devour_whitespace(toks);
|
||||
|
||||
let mut body = read_until_closing_curly_brace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks)?;
|
||||
body.push(toks.next().unwrap());
|
||||
|
||||
Ok(Spanned {
|
||||
|
@ -69,7 +69,7 @@ impl AtRule {
|
||||
node: message,
|
||||
span,
|
||||
} = Value::from_vec(
|
||||
read_until_semicolon_or_closing_curly_brace(toks),
|
||||
read_until_semicolon_or_closing_curly_brace(toks)?,
|
||||
scope,
|
||||
super_selector,
|
||||
)?;
|
||||
@ -81,7 +81,7 @@ impl AtRule {
|
||||
node: message,
|
||||
span,
|
||||
} = Value::from_vec(
|
||||
read_until_semicolon_or_closing_curly_brace(toks),
|
||||
read_until_semicolon_or_closing_curly_brace(toks)?,
|
||||
scope,
|
||||
super_selector,
|
||||
)?;
|
||||
@ -103,7 +103,7 @@ impl AtRule {
|
||||
node: message,
|
||||
span,
|
||||
} = Value::from_vec(
|
||||
read_until_semicolon_or_closing_curly_brace(toks),
|
||||
read_until_semicolon_or_closing_curly_brace(toks)?,
|
||||
scope,
|
||||
super_selector,
|
||||
)?;
|
||||
@ -139,7 +139,7 @@ impl AtRule {
|
||||
}
|
||||
}
|
||||
AtRuleKind::Return => {
|
||||
let v = read_until_semicolon_or_closing_curly_brace(toks);
|
||||
let v = read_until_semicolon_or_closing_curly_brace(toks)?;
|
||||
if toks.peek().unwrap().kind == ';' {
|
||||
toks.next();
|
||||
}
|
||||
@ -153,7 +153,7 @@ impl AtRule {
|
||||
let mut selector = &Selector::replace(
|
||||
super_selector,
|
||||
Selector::from_tokens(
|
||||
&mut read_until_open_curly_brace(toks).into_iter().peekmore(),
|
||||
&mut read_until_open_curly_brace(toks)?.into_iter().peekmore(),
|
||||
scope,
|
||||
super_selector,
|
||||
)?,
|
||||
@ -165,7 +165,7 @@ impl AtRule {
|
||||
}
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks)?;
|
||||
body.push(toks.next().unwrap());
|
||||
devour_whitespace(toks);
|
||||
let mut styles = Vec::new();
|
||||
@ -201,7 +201,7 @@ impl AtRule {
|
||||
}
|
||||
}
|
||||
AtRuleKind::Charset => {
|
||||
read_until_semicolon_or_closing_curly_brace(toks);
|
||||
read_until_semicolon_or_closing_curly_brace(toks)?;
|
||||
if toks.peek().unwrap().kind == ';' {
|
||||
toks.next();
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ pub(crate) fn parse_while<I: Iterator<Item = Token>>(
|
||||
span: Span,
|
||||
) -> SassResult<Spanned<AtRule>> {
|
||||
devour_whitespace(toks);
|
||||
let cond = read_until_open_curly_brace(toks);
|
||||
let cond = read_until_open_curly_brace(toks)?;
|
||||
|
||||
if cond.is_empty() {
|
||||
return Err(("Expected expression.", span).into());
|
||||
@ -58,7 +58,7 @@ pub(crate) fn parse_while<I: Iterator<Item = Token>>(
|
||||
|
||||
toks.next();
|
||||
|
||||
let mut body = read_until_closing_curly_brace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks)?;
|
||||
|
||||
body.push(toks.next().unwrap());
|
||||
|
||||
|
@ -375,7 +375,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
Some(Token { kind: '{', .. }) => {
|
||||
let next = toks.next().unwrap();
|
||||
values.push(next);
|
||||
values.extend(read_until_closing_curly_brace(toks));
|
||||
values.extend(read_until_closing_curly_brace(toks)?);
|
||||
if let Some(tok) = toks.next() {
|
||||
values.push(tok);
|
||||
} else {
|
||||
@ -395,7 +395,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
// it is causing us to emit nothing on malformed input
|
||||
'(' => {
|
||||
values.push(toks.next().unwrap());
|
||||
values.extend(read_until_closing_paren(toks));
|
||||
values.extend(read_until_closing_paren(toks)?);
|
||||
}
|
||||
_ => values.push(toks.next().unwrap()),
|
||||
};
|
||||
|
@ -403,7 +403,12 @@ impl Selector {
|
||||
super_selector: &Selector,
|
||||
span_before: Span,
|
||||
) -> SassResult<SelectorKind> {
|
||||
let is_pseudo_element = if toks.peek().ok_or(("Expected identifier.", span_before))?.kind == ':' {
|
||||
let is_pseudo_element = if toks
|
||||
.peek()
|
||||
.ok_or(("Expected identifier.", span_before))?
|
||||
.kind
|
||||
== ':'
|
||||
{
|
||||
toks.next();
|
||||
true
|
||||
} else {
|
||||
@ -419,7 +424,7 @@ impl Selector {
|
||||
Ok(
|
||||
if toks.peek().is_some() && toks.peek().unwrap().kind == '(' {
|
||||
toks.next();
|
||||
let mut inner_toks = read_until_closing_paren(toks);
|
||||
let mut inner_toks = read_until_closing_paren(toks)?;
|
||||
inner_toks.pop();
|
||||
let inner = Selector::from_tokens(
|
||||
&mut inner_toks.into_iter().peekmore(),
|
||||
|
@ -4,6 +4,7 @@ use peekmore::PeekMoreIterator;
|
||||
|
||||
use super::read_until_closing_quote;
|
||||
|
||||
use crate::error::SassResult;
|
||||
use crate::Token;
|
||||
|
||||
/// Reads until the char is found, consuming the char,
|
||||
@ -11,13 +12,13 @@ use crate::Token;
|
||||
pub(crate) fn read_until_char<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
c: char,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut v = Vec::new();
|
||||
while let Some(tok) = toks.next() {
|
||||
match tok.kind {
|
||||
'"' | '\'' => {
|
||||
v.push(tok);
|
||||
v.extend(read_until_closing_quote(toks, tok.kind));
|
||||
v.extend(read_until_closing_quote(toks, tok.kind)?);
|
||||
continue;
|
||||
}
|
||||
t if t == c => break,
|
||||
@ -25,7 +26,7 @@ pub(crate) fn read_until_char<I: Iterator<Item = Token>>(
|
||||
}
|
||||
v.push(tok)
|
||||
}
|
||||
v
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
pub(crate) fn hex_char_for(number: u32) -> char {
|
||||
|
@ -16,7 +16,7 @@ pub(crate) fn parse_interpolation<I: Iterator<Item = Token>>(
|
||||
scope: &Scope,
|
||||
super_selector: &Selector,
|
||||
) -> SassResult<Spanned<Value>> {
|
||||
let val = Value::from_vec(read_until_closing_curly_brace(toks), scope, super_selector)?;
|
||||
let val = Value::from_vec(read_until_closing_curly_brace(toks)?, scope, super_selector)?;
|
||||
toks.next();
|
||||
Ok(Spanned {
|
||||
node: val.node.eval(val.span)?.node.unquote(),
|
||||
|
@ -2,6 +2,7 @@ use std::iter::Iterator;
|
||||
|
||||
use peekmore::PeekMoreIterator;
|
||||
|
||||
use crate::error::SassResult;
|
||||
use crate::Token;
|
||||
|
||||
use super::{devour_whitespace, read_until_newline};
|
||||
@ -11,7 +12,7 @@ use super::{devour_whitespace, read_until_newline};
|
||||
// Does not consume the open curly brace
|
||||
pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut n = 0;
|
||||
while let Some(tok) = toks.peek() {
|
||||
@ -33,6 +34,11 @@ pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
q @ '"' | q @ '\'' => {
|
||||
t.push(toks.next().unwrap());
|
||||
t.extend(read_until_closing_quote(toks, q)?);
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if n == 1 {
|
||||
@ -41,19 +47,19 @@ pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
||||
|
||||
t.push(toks.next().unwrap());
|
||||
}
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut nesting = 0;
|
||||
while let Some(tok) = toks.peek() {
|
||||
match tok.kind {
|
||||
q @ '"' | q @ '\'' => {
|
||||
t.push(toks.next().unwrap());
|
||||
t.extend(read_until_closing_quote(toks, q));
|
||||
t.extend(read_until_closing_quote(toks, q)?);
|
||||
}
|
||||
'{' => {
|
||||
nesting += 1;
|
||||
@ -80,7 +86,7 @@ pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'(' => {
|
||||
t.push(toks.next().unwrap());
|
||||
t.extend(read_until_closing_paren(toks));
|
||||
t.extend(read_until_closing_paren(toks)?);
|
||||
}
|
||||
'\\' => {
|
||||
t.push(toks.next().unwrap());
|
||||
@ -92,13 +98,16 @@ pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
}
|
||||
devour_whitespace(toks);
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
/// Read tokens into a vector until a matching closing quote is found
|
||||
///
|
||||
/// The closing quote is included in the output
|
||||
pub(crate) fn read_until_closing_quote<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
q: char,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
while let Some(tok) = toks.next() {
|
||||
match tok.kind {
|
||||
@ -121,18 +130,24 @@ pub(crate) fn read_until_closing_quote<I: Iterator<Item = Token>>(
|
||||
let next = toks.peek().unwrap();
|
||||
if next.kind == '{' {
|
||||
t.push(toks.next().unwrap());
|
||||
t.append(&mut read_until_closing_curly_brace(toks));
|
||||
t.append(&mut read_until_closing_curly_brace(toks)?);
|
||||
}
|
||||
}
|
||||
_ => t.push(tok),
|
||||
}
|
||||
}
|
||||
t
|
||||
if let Some(tok) = t.pop() {
|
||||
if tok.kind != q {
|
||||
return Err((format!("Expected {}.", q), tok.pos).into());
|
||||
}
|
||||
t.push(tok);
|
||||
}
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
pub(crate) fn read_until_semicolon_or_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut nesting = 0;
|
||||
while let Some(tok) = toks.peek() {
|
||||
@ -149,7 +164,7 @@ pub(crate) fn read_until_semicolon_or_closing_curly_brace<I: Iterator<Item = Tok
|
||||
'"' | '\'' => {
|
||||
let quote = toks.next().unwrap();
|
||||
t.push(quote);
|
||||
t.extend(read_until_closing_quote(toks, quote.kind));
|
||||
t.extend(read_until_closing_quote(toks, quote.kind)?);
|
||||
}
|
||||
'{' => {
|
||||
nesting += 1;
|
||||
@ -178,12 +193,12 @@ pub(crate) fn read_until_semicolon_or_closing_curly_brace<I: Iterator<Item = Tok
|
||||
}
|
||||
}
|
||||
devour_whitespace(toks);
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut scope = 0;
|
||||
while let Some(tok) = toks.next() {
|
||||
@ -191,7 +206,7 @@ pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||
')' => {
|
||||
if scope < 1 {
|
||||
t.push(tok);
|
||||
return t;
|
||||
return Ok(t);
|
||||
} else {
|
||||
scope -= 1;
|
||||
}
|
||||
@ -199,7 +214,7 @@ pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||
'(' => scope += 1,
|
||||
'"' | '\'' => {
|
||||
t.push(tok);
|
||||
t.extend(read_until_closing_quote(toks, tok.kind));
|
||||
t.extend(read_until_closing_quote(toks, tok.kind)?);
|
||||
continue;
|
||||
}
|
||||
'\\' => {
|
||||
@ -213,12 +228,12 @@ pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||
}
|
||||
t.push(tok)
|
||||
}
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
) -> Vec<Token> {
|
||||
) -> SassResult<Vec<Token>> {
|
||||
let mut t = Vec::new();
|
||||
let mut scope = 0;
|
||||
while let Some(tok) = toks.next() {
|
||||
@ -227,7 +242,7 @@ pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||
']' => {
|
||||
if scope < 1 {
|
||||
t.push(tok);
|
||||
return t;
|
||||
return Ok(t);
|
||||
} else {
|
||||
scope -= 1;
|
||||
}
|
||||
@ -235,7 +250,7 @@ pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||
'[' => scope += 1,
|
||||
'"' | '\'' => {
|
||||
t.push(tok);
|
||||
t.extend(read_until_closing_quote(toks, tok.kind));
|
||||
t.extend(read_until_closing_quote(toks, tok.kind)?);
|
||||
continue;
|
||||
}
|
||||
'\\' => {
|
||||
@ -248,5 +263,5 @@ pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||
}
|
||||
t.push(tok)
|
||||
}
|
||||
t
|
||||
Ok(t)
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ pub(crate) fn eat_variable_value<I: Iterator<Item = Token>>(
|
||||
'"' | '\'' => {
|
||||
let quote = toks.next().unwrap();
|
||||
val_toks.push(quote);
|
||||
val_toks.extend(read_until_closing_quote(toks, quote.kind));
|
||||
val_toks.extend(read_until_closing_quote(toks, quote.kind)?);
|
||||
}
|
||||
'#' => {
|
||||
val_toks.push(toks.next().unwrap());
|
||||
@ -93,7 +93,7 @@ pub(crate) fn eat_variable_value<I: Iterator<Item = Token>>(
|
||||
}
|
||||
'(' => {
|
||||
val_toks.push(toks.next().unwrap());
|
||||
val_toks.extend(read_until_closing_paren(toks));
|
||||
val_toks.extend(read_until_closing_paren(toks)?);
|
||||
}
|
||||
'!' => {
|
||||
let pos = tok.pos();
|
||||
|
@ -189,7 +189,7 @@ fn parse_paren(
|
||||
let paren_toks = &mut t.node.into_iter().peekmore();
|
||||
|
||||
let mut map = SassMap::new();
|
||||
let key = Value::from_vec(read_until_char(paren_toks, ':'), scope, super_selector)?;
|
||||
let key = Value::from_vec(read_until_char(paren_toks, ':')?, scope, super_selector)?;
|
||||
|
||||
if paren_toks.peek().is_none() {
|
||||
return Ok(Spanned {
|
||||
@ -198,7 +198,7 @@ fn parse_paren(
|
||||
});
|
||||
}
|
||||
|
||||
let val = Value::from_vec(read_until_char(paren_toks, ','), scope, super_selector)?;
|
||||
let val = Value::from_vec(read_until_char(paren_toks, ',')?, scope, super_selector)?;
|
||||
|
||||
map.insert(key.node, val.node);
|
||||
|
||||
@ -212,9 +212,9 @@ fn parse_paren(
|
||||
let mut span = key.span;
|
||||
|
||||
loop {
|
||||
let key = Value::from_vec(read_until_char(paren_toks, ':'), scope, super_selector)?;
|
||||
let key = Value::from_vec(read_until_char(paren_toks, ':')?, scope, super_selector)?;
|
||||
devour_whitespace(paren_toks);
|
||||
let val = Value::from_vec(read_until_char(paren_toks, ','), scope, super_selector)?;
|
||||
let val = Value::from_vec(read_until_char(paren_toks, ',')?, scope, super_selector)?;
|
||||
span = span.merge(val.span);
|
||||
devour_whitespace(paren_toks);
|
||||
if map.insert(key.node, val.node) {
|
||||
@ -755,7 +755,10 @@ impl Value {
|
||||
}
|
||||
'(' => {
|
||||
let mut span = toks.next().unwrap().pos();
|
||||
let mut inner = read_until_closing_paren(toks);
|
||||
let mut inner = match read_until_closing_paren(toks) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Some(Err(e.into())),
|
||||
};
|
||||
// todo: the above shouldn't eat the closing paren
|
||||
if let Some(last_tok) = inner.pop() {
|
||||
if last_tok.kind != ')' {
|
||||
@ -794,7 +797,10 @@ impl Value {
|
||||
}
|
||||
'[' => {
|
||||
let mut span = toks.next().unwrap().pos();
|
||||
let mut inner = read_until_closing_square_brace(toks);
|
||||
let mut inner = match read_until_closing_square_brace(toks) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Some(Err(e.into())),
|
||||
};
|
||||
if let Some(last_tok) = inner.pop() {
|
||||
if last_tok.kind != ']' {
|
||||
return Some(Err(("expected \"]\".", span).into()));
|
||||
|
@ -126,3 +126,5 @@ error!(
|
||||
nothing_after_escape,
|
||||
"@if \\", "Error: Expected expression."
|
||||
);
|
||||
error!(unclosed_dbl_quote, "@if true \" {}", "Error: Expected \".");
|
||||
error!(unclosed_sgl_quote, "@if true ' {}", "Error: Expected '.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user