refactor errors using Parser::expect_char
This commit is contained in:
parent
074d679cbd
commit
0254517095
@ -72,19 +72,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
'.' => {
|
||||
let next = self.toks.next().ok_or(("expected \".\".", span))?;
|
||||
if next.kind != '.' {
|
||||
return Err(("expected \".\".", next.pos()).into());
|
||||
}
|
||||
let next = self.toks.next().ok_or(("expected \".\".", next.pos()))?;
|
||||
if next.kind != '.' {
|
||||
return Err(("expected \".\".", next.pos()).into());
|
||||
}
|
||||
self.expect_char('.')?;
|
||||
self.expect_char('.')?;
|
||||
|
||||
self.whitespace_or_comment();
|
||||
let next = self.toks.next().ok_or(("expected \")\".", next.pos()))?;
|
||||
if next.kind != ')' {
|
||||
return Err(("expected \")\".", next.pos()).into());
|
||||
}
|
||||
|
||||
self.expect_char(')')?;
|
||||
|
||||
is_variadic = true;
|
||||
|
||||
@ -119,6 +112,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.whitespace_or_comment();
|
||||
// TODO: this should NOT eat the opening curly brace
|
||||
// todo: self.expect_char('{')?;
|
||||
match self.toks.next() {
|
||||
Some(v) if v.kind == '{' => {}
|
||||
Some(..) | None => return Err(("expected \"{\".", close_paren_span).into()),
|
||||
@ -225,11 +219,7 @@ impl<'a> Parser<'a> {
|
||||
return Err(("expected \")\".", pos).into());
|
||||
}
|
||||
self.toks.next();
|
||||
if let Some(Token { kind: '.', .. }) = self.toks.peek() {
|
||||
self.toks.next();
|
||||
} else {
|
||||
return Err(("expected \".\".", pos).into());
|
||||
}
|
||||
self.expect_char('.')?;
|
||||
} else {
|
||||
return Err(("expected \")\".", pos).into());
|
||||
}
|
||||
@ -323,23 +313,16 @@ impl<'a> Parser<'a> {
|
||||
self.whitespace_or_comment();
|
||||
continue;
|
||||
}
|
||||
Some(Token { kind: '.', pos }) => {
|
||||
let pos = *pos;
|
||||
Some(Token { kind: '.', .. }) => {
|
||||
self.toks.next();
|
||||
|
||||
if let Some(Token { kind: '.', pos }) = self.toks.peek().cloned() {
|
||||
if !name.is_empty() {
|
||||
return Err(("expected \")\".", pos).into());
|
||||
}
|
||||
self.toks.next();
|
||||
if let Some(Token { kind: '.', .. }) = self.toks.peek() {
|
||||
self.toks.next();
|
||||
} else {
|
||||
return Err(("expected \".\".", pos).into());
|
||||
}
|
||||
} else {
|
||||
return Err(("expected \")\".", pos).into());
|
||||
self.expect_char('.')?;
|
||||
|
||||
if !name.is_empty() {
|
||||
return Err(("expected \")\".", self.span_before).into());
|
||||
}
|
||||
|
||||
self.expect_char('.')?;
|
||||
}
|
||||
Some(Token { pos, .. }) => {
|
||||
return Err(("expected \")\".", *pos).into());
|
||||
|
@ -24,14 +24,10 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let init_cond = self.parse_value(true, &|_| false)?.node;
|
||||
|
||||
// consume the open curly brace
|
||||
let span_before = match self.toks.next() {
|
||||
Some(Token { kind: '{', pos }) => pos,
|
||||
Some(..) | None => return Err(("expected \"{\".", self.span_before).into()),
|
||||
};
|
||||
self.expect_char('{')?;
|
||||
|
||||
if self.toks.peek().is_none() {
|
||||
return Err(("expected \"}\".", span_before).into());
|
||||
return Err(("expected \"}\".", self.span_before).into());
|
||||
}
|
||||
|
||||
self.whitespace_or_comment();
|
||||
@ -89,12 +85,7 @@ impl<'a> Parser<'a> {
|
||||
false
|
||||
} else {
|
||||
let v = self.parse_value(true, &|_| false)?.node.is_true();
|
||||
match self.toks.next() {
|
||||
Some(Token { kind: '{', .. }) => {}
|
||||
Some(..) | None => {
|
||||
return Err(("expected \"{\".", self.span_before).into())
|
||||
}
|
||||
}
|
||||
self.expect_char('{')?;
|
||||
v
|
||||
};
|
||||
if cond {
|
||||
@ -164,17 +155,15 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub(super) fn parse_for(&mut self) -> SassResult<Vec<Stmt>> {
|
||||
// todo: whitespace or comment
|
||||
self.whitespace();
|
||||
let next = self
|
||||
.toks
|
||||
.next()
|
||||
.ok_or(("expected \"$\".", self.span_before))?;
|
||||
let var: Spanned<Identifier> = match next.kind {
|
||||
'$' => self
|
||||
.parse_identifier_no_interpolation(false)?
|
||||
.map_node(|i| i.into()),
|
||||
_ => return Err(("expected \"$\".", self.span_before).into()),
|
||||
};
|
||||
// todo: test for error here
|
||||
self.expect_char('$')?;
|
||||
|
||||
let var = self
|
||||
.parse_identifier_no_interpolation(false)?
|
||||
.map_node(|n| n.into());
|
||||
|
||||
self.whitespace();
|
||||
self.span_before = match self.toks.peek() {
|
||||
Some(tok) => tok.pos,
|
||||
@ -278,11 +267,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
// consume the open curly brace
|
||||
match self.toks.next() {
|
||||
Some(Token { kind: '{', pos }) => pos,
|
||||
Some(..) | None => return Err(("expected \"{\".", to_val.span).into()),
|
||||
};
|
||||
self.expect_char('{')?;
|
||||
|
||||
let body = read_until_closing_curly_brace(self.toks)?;
|
||||
self.toks.next();
|
||||
@ -443,15 +428,11 @@ impl<'a> Parser<'a> {
|
||||
let mut vars: Vec<Spanned<Identifier>> = Vec::new();
|
||||
|
||||
loop {
|
||||
let next = self
|
||||
.toks
|
||||
.next()
|
||||
.ok_or(("expected \"$\".", self.span_before))?;
|
||||
self.expect_char('$')?;
|
||||
|
||||
match next.kind {
|
||||
'$' => vars.push(self.parse_identifier()?.map_node(|i| i.into())),
|
||||
_ => return Err(("expected \"$\".", next.pos()).into()),
|
||||
}
|
||||
vars.push(self.parse_identifier()?.map_node(|i| i.into()));
|
||||
|
||||
// todo: whitespace or comment
|
||||
self.whitespace();
|
||||
if self
|
||||
.toks
|
||||
|
@ -40,11 +40,9 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
self.whitespace_or_comment();
|
||||
let args = match self.toks.next() {
|
||||
Some(Token { kind: '(', .. }) => self.parse_func_args()?,
|
||||
Some(Token { pos, .. }) => return Err(("expected \"(\".", pos).into()),
|
||||
None => return Err(("expected \"(\".", span).into()),
|
||||
};
|
||||
self.expect_char('(')?;
|
||||
|
||||
let args = self.parse_func_args()?;
|
||||
|
||||
self.whitespace();
|
||||
|
||||
|
@ -63,9 +63,8 @@ impl<'a, 'b> KeyframesSelectorParser<'a, 'b> {
|
||||
num.push_str(&eat_whole_number(self.parser.toks));
|
||||
}
|
||||
|
||||
if !matches!(self.parser.toks.next(), Some(Token { kind: '%', .. })) {
|
||||
return Err(("expected \"%\".", tok.pos).into());
|
||||
}
|
||||
self.parser.expect_char('%')?;
|
||||
|
||||
selectors.push(KeyframesSelector::Percent(num.into_boxed_str()));
|
||||
}
|
||||
'{' => break,
|
||||
|
@ -104,9 +104,7 @@ impl<'a> Parser<'a> {
|
||||
ident.node.make_ascii_lowercase();
|
||||
if ident.node == "using" {
|
||||
self.whitespace_or_comment();
|
||||
if !matches!(self.toks.next(), Some(Token { kind: '(', .. })) {
|
||||
return Err(("expected \"(\".", ident.span).into());
|
||||
}
|
||||
self.expect_char('(')?;
|
||||
|
||||
Some(self.parse_func_args()?)
|
||||
} else {
|
||||
|
@ -903,9 +903,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
self.whitespace();
|
||||
|
||||
if !matches!(self.toks.next(), Some(Token { kind: '{', .. })) {
|
||||
return Err(("expected \"{\".", self.span_before).into());
|
||||
}
|
||||
self.expect_char('{')?;
|
||||
|
||||
let raw_body = self.parse_stmt()?;
|
||||
|
||||
|
@ -598,6 +598,7 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
// todo: the above shouldn't eat the closing paren
|
||||
if let Some(last_tok) = inner.pop() {
|
||||
// todo: we should remove this like we did for square braces
|
||||
if last_tok.kind != ')' {
|
||||
return Some(Err(("expected \")\".", span).into()));
|
||||
}
|
||||
|
@ -29,9 +29,9 @@ impl<'a> Parser<'a> {
|
||||
assert!(matches!(self.toks.next(), Some(Token { kind: '$', .. })));
|
||||
let ident: Identifier = self.parse_identifier_no_interpolation(false)?.node.into();
|
||||
self.whitespace();
|
||||
if !matches!(self.toks.next(), Some(Token { kind: ':', .. })) {
|
||||
return Err(("expected \":\".", self.span_before).into());
|
||||
}
|
||||
|
||||
self.expect_char(':')?;
|
||||
|
||||
let VariableValue {
|
||||
val_toks,
|
||||
global,
|
||||
|
@ -5,7 +5,9 @@ use std::{
|
||||
|
||||
use codemap::Span;
|
||||
|
||||
use crate::{common::QuoteKind, error::SassResult, parse::Parser, utils::is_ident, value::Value};
|
||||
use crate::{
|
||||
common::QuoteKind, error::SassResult, parse::Parser, utils::is_ident, value::Value, Token,
|
||||
};
|
||||
|
||||
use super::{Namespace, QualifiedName};
|
||||
|
||||
@ -41,13 +43,8 @@ impl Hash for Attribute {
|
||||
fn attribute_name(parser: &mut Parser<'_>, start: Span) -> SassResult<QualifiedName> {
|
||||
let next = parser.toks.peek().ok_or(("Expected identifier.", start))?;
|
||||
if next.kind == '*' {
|
||||
let pos = next.pos;
|
||||
parser.toks.next();
|
||||
if parser.toks.peek().ok_or(("expected \"|\".", pos))?.kind != '|' {
|
||||
return Err(("expected \"|\".", pos).into());
|
||||
}
|
||||
|
||||
parser.span_before = parser.toks.next().unwrap().pos();
|
||||
parser.expect_char('|')?;
|
||||
|
||||
let ident = parser.parse_identifier()?.node;
|
||||
return Ok(QualifiedName {
|
||||
@ -89,19 +86,18 @@ fn attribute_name(parser: &mut Parser<'_>, start: Span) -> SassResult<QualifiedN
|
||||
}
|
||||
|
||||
fn attribute_operator(parser: &mut Parser<'_>) -> SassResult<AttributeOp> {
|
||||
let start = parser.span_before;
|
||||
let op = match parser.toks.next().ok_or(("Expected \"]\".", start))?.kind {
|
||||
'=' => return Ok(AttributeOp::Equals),
|
||||
'~' => AttributeOp::Include,
|
||||
'|' => AttributeOp::Dash,
|
||||
'^' => AttributeOp::Prefix,
|
||||
'$' => AttributeOp::Suffix,
|
||||
'*' => AttributeOp::Contains,
|
||||
_ => return Err(("Expected \"]\".", start).into()),
|
||||
let op = match parser.toks.next() {
|
||||
Some(Token { kind: '=', .. }) => return Ok(AttributeOp::Equals),
|
||||
Some(Token { kind: '~', .. }) => AttributeOp::Include,
|
||||
Some(Token { kind: '|', .. }) => AttributeOp::Dash,
|
||||
Some(Token { kind: '^', .. }) => AttributeOp::Prefix,
|
||||
Some(Token { kind: '$', .. }) => AttributeOp::Suffix,
|
||||
Some(Token { kind: '*', .. }) => AttributeOp::Contains,
|
||||
Some(..) | None => return Err(("Expected \"]\".", parser.span_before).into()),
|
||||
};
|
||||
if parser.toks.next().ok_or(("expected \"=\".", start))?.kind != '=' {
|
||||
return Err(("expected \"=\".", start).into());
|
||||
}
|
||||
|
||||
parser.expect_char('=')?;
|
||||
|
||||
Ok(op)
|
||||
}
|
||||
impl Attribute {
|
||||
@ -145,25 +141,23 @@ impl Attribute {
|
||||
};
|
||||
parser.whitespace();
|
||||
|
||||
let peek = parser.toks.peek().ok_or(("expected more input.", start))?;
|
||||
|
||||
let modifier = match peek.kind {
|
||||
c if c.is_alphabetic() => Some(c),
|
||||
let modifier = match parser.toks.peek().cloned() {
|
||||
Some(Token {
|
||||
kind: c @ 'a'..='z',
|
||||
..
|
||||
})
|
||||
| Some(Token {
|
||||
kind: c @ 'A'..='Z',
|
||||
..
|
||||
}) => {
|
||||
parser.toks.next();
|
||||
parser.whitespace();
|
||||
Some(c)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let pos = peek.pos();
|
||||
|
||||
if modifier.is_some() {
|
||||
parser.toks.next();
|
||||
parser.whitespace();
|
||||
}
|
||||
|
||||
if parser.toks.peek().ok_or(("expected \"]\".", pos))?.kind != ']' {
|
||||
return Err(("expected \"]\".", pos).into());
|
||||
}
|
||||
|
||||
parser.toks.next();
|
||||
parser.expect_char(']')?;
|
||||
|
||||
Ok(Attribute {
|
||||
op,
|
||||
|
@ -317,14 +317,14 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
|
||||
if SELECTOR_PSEUDO_ELEMENTS.contains(&unvendored) {
|
||||
selector = Some(Box::new(self.parse_selector_list()?));
|
||||
self.parser.whitespace();
|
||||
self.expect_closing_paren()?;
|
||||
self.parser.expect_char(')')?;
|
||||
} else {
|
||||
argument = Some(self.declaration_value()?.into_boxed_str());
|
||||
}
|
||||
} else if SELECTOR_PSEUDO_CLASSES.contains(&unvendored) {
|
||||
selector = Some(Box::new(self.parse_selector_list()?));
|
||||
self.parser.whitespace();
|
||||
self.expect_closing_paren()?;
|
||||
self.parser.expect_char(')')?;
|
||||
} else if unvendored == "nth-child" || unvendored == "nth-last-child" {
|
||||
let mut this_arg = self.parse_a_n_plus_b()?;
|
||||
let found_whitespace = self.parser.whitespace();
|
||||
@ -339,7 +339,7 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.expect_closing_paren()?;
|
||||
self.parser.expect_char(')')?;
|
||||
argument = Some(this_arg.into_boxed_str());
|
||||
} else {
|
||||
argument = Some(
|
||||
@ -541,14 +541,6 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
|
||||
Err((format!("Expected \"{}\".", s), self.span).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn expect_closing_paren(&mut self) -> SassResult<()> {
|
||||
if let Some(Token { kind: ')', .. }) = self.parser.toks.next() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(("expected \")\".", self.span).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether `c` can start a simple selector other than a type
|
||||
|
Loading…
x
Reference in New Issue
Block a user