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