Propagate errors properly (reduce unwrap()
calls)
This commit is contained in:
parent
02d6a511a5
commit
8076125576
38
src/main.rs
38
src/main.rs
@ -229,7 +229,7 @@ struct StyleSheetParser<'a> {
|
|||||||
|
|
||||||
impl<'a> StyleSheetParser<'a> {
|
impl<'a> StyleSheetParser<'a> {
|
||||||
fn parse_toplevel(mut self) -> SassResult<StyleSheet> {
|
fn parse_toplevel(mut self) -> SassResult<StyleSheet> {
|
||||||
let mut rules = Vec::new();
|
let mut rules: Vec<Stmt> = Vec::new();
|
||||||
while let Some(Token { kind, .. }) = self.lexer.peek() {
|
while let Some(Token { kind, .. }) = self.lexer.peek() {
|
||||||
match kind.clone() {
|
match kind.clone() {
|
||||||
TokenKind::Ident(_)
|
TokenKind::Ident(_)
|
||||||
@ -300,7 +300,9 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
|
|
||||||
fn eat_rules(&mut self, super_selector: &Selector, scope: &mut Scope) -> Vec<Stmt> {
|
fn eat_rules(&mut self, super_selector: &Selector, scope: &mut Scope) -> Vec<Stmt> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
while let Ok(tok) = eat_expr(&mut self.lexer, scope, super_selector) {
|
while let Some(tok) = eat_expr(&mut self.lexer, scope, super_selector)
|
||||||
|
.unwrap_or_else(|error| self.error(error.0, error.1))
|
||||||
|
{
|
||||||
match tok {
|
match tok {
|
||||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||||
Expr::MixinDecl(name, mixin) => {
|
Expr::MixinDecl(name, mixin) => {
|
||||||
@ -383,7 +385,7 @@ fn eat_include<I: Iterator<Item = Token>>(
|
|||||||
};
|
};
|
||||||
let rules = mixin
|
let rules = mixin
|
||||||
.call_with_args(&args)
|
.call_with_args(&args)
|
||||||
.eval(super_selector, &mut scope.clone());
|
.eval(super_selector, &mut scope.clone())?;
|
||||||
Ok(rules)
|
Ok(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,23 +484,25 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
toks: &mut Peekable<I>,
|
toks: &mut Peekable<I>,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
super_selector: &Selector,
|
super_selector: &Selector,
|
||||||
) -> Result<Expr, ()> {
|
) -> Result<Option<Expr>, (Pos, &'static str)> {
|
||||||
let mut values = Vec::with_capacity(5);
|
let mut values = Vec::with_capacity(5);
|
||||||
while let Some(tok) = toks.peek() {
|
while let Some(tok) = toks.peek() {
|
||||||
match &tok.kind {
|
match &tok.kind {
|
||||||
TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseCurlyBrace) => {
|
TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseCurlyBrace) => {
|
||||||
toks.next();
|
toks.next();
|
||||||
devour_whitespace(toks);
|
devour_whitespace(toks);
|
||||||
return Ok(Expr::Style(Style::from_tokens(&values, scope)?));
|
return Ok(Some(Expr::Style(
|
||||||
|
Style::from_tokens(&values, scope).unwrap(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
TokenKind::Symbol(Symbol::OpenCurlyBrace) => {
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => {
|
||||||
toks.next();
|
toks.next();
|
||||||
devour_whitespace(toks);
|
devour_whitespace(toks);
|
||||||
return Ok(Expr::Selector(Selector::from_tokens(
|
return Ok(Some(Expr::Selector(Selector::from_tokens(
|
||||||
&mut values.iter().peekable(),
|
&mut values.iter().peekable(),
|
||||||
super_selector,
|
super_selector,
|
||||||
scope,
|
scope,
|
||||||
)));
|
))));
|
||||||
}
|
}
|
||||||
TokenKind::Variable(_) => {
|
TokenKind::Variable(_) => {
|
||||||
let tok = toks.next().unwrap();
|
let tok = toks.next().unwrap();
|
||||||
@ -512,10 +516,10 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
{
|
{
|
||||||
toks.next();
|
toks.next();
|
||||||
devour_whitespace(toks);
|
devour_whitespace(toks);
|
||||||
return Ok(Expr::VariableDecl(
|
return Ok(Some(Expr::VariableDecl(
|
||||||
name,
|
name,
|
||||||
eat_variable_value(toks, scope).unwrap(), // .unwrap_or_else(|err| self.error(err.0, err.1)),
|
eat_variable_value(toks, scope)?
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
values.push(Token {
|
values.push(Token {
|
||||||
kind: TokenKind::Variable(name),
|
kind: TokenKind::Variable(name),
|
||||||
@ -532,20 +536,20 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
};
|
};
|
||||||
devour_whitespace(toks);
|
devour_whitespace(toks);
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
return Ok(Expr::MultilineComment(s.clone()));
|
return Ok(Some(Expr::MultilineComment(s.clone())));
|
||||||
} else {
|
} else {
|
||||||
values.push(tok.clone())
|
values.push(tok.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(AtRule::Include) => {
|
TokenKind::AtRule(AtRule::Include) => {
|
||||||
return Ok(Expr::Include(
|
return Ok(Some(Expr::Include(
|
||||||
eat_include(toks, scope, super_selector).unwrap(),
|
eat_include(toks, scope, super_selector)?,
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(AtRule::Mixin) => {
|
TokenKind::AtRule(AtRule::Mixin) => {
|
||||||
toks.next();
|
toks.next();
|
||||||
let (name, mixin) = parse_mixin(toks, scope.clone()).unwrap();
|
let (name, mixin) = parse_mixin(toks, scope.clone()).unwrap();
|
||||||
return Ok(Expr::MixinDecl(name, mixin));
|
return Ok(Some(Expr::MixinDecl(name, mixin)));
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(_) => {
|
TokenKind::AtRule(_) => {
|
||||||
if let Some(Token {
|
if let Some(Token {
|
||||||
@ -554,7 +558,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
}) = toks.next()
|
}) = toks.next()
|
||||||
{
|
{
|
||||||
if let Ok(a) = eat_at_rule(rule, pos, toks, scope) {
|
if let Ok(a) = eat_at_rule(rule, pos, toks, scope) {
|
||||||
return Ok(a);
|
return Ok(Some(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,7 +580,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Err(())
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Functions that print to stdout or stderr
|
/// Functions that print to stdout or stderr
|
||||||
|
10
src/mixin.rs
10
src/mixin.rs
@ -1,7 +1,7 @@
|
|||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
use crate::common::Scope;
|
use crate::common::{Pos, Scope};
|
||||||
use crate::function::{CallArgs, FuncArgs};
|
use crate::function::{CallArgs, FuncArgs};
|
||||||
use crate::selector::Selector;
|
use crate::selector::Selector;
|
||||||
use crate::{eat_expr, Expr, RuleSet, Stmt, Token};
|
use crate::{eat_expr, Expr, RuleSet, Stmt, Token};
|
||||||
@ -39,16 +39,16 @@ impl Mixin {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval(&mut self, super_selector: &Selector, scope: &mut Scope) -> Vec<Stmt> {
|
pub fn eval(&mut self, super_selector: &Selector, scope: &mut Scope) -> Result<Vec<Stmt>, (Pos, &'static str)> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
while let Ok(expr) = eat_expr(&mut self.body, scope, super_selector) {
|
while let Some(expr) = eat_expr(&mut self.body, scope, super_selector)? {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||||
Expr::Include(_) => todo!(),
|
Expr::Include(_) => todo!(),
|
||||||
Expr::MixinDecl(_, _) => todo!(),
|
Expr::MixinDecl(_, _) => todo!(),
|
||||||
Expr::Selector(s) => {
|
Expr::Selector(s) => {
|
||||||
self.nesting += 1;
|
self.nesting += 1;
|
||||||
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope);
|
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope)?;
|
||||||
stmts.push(Stmt::RuleSet(RuleSet {
|
stmts.push(Stmt::RuleSet(RuleSet {
|
||||||
super_selector: super_selector.clone(),
|
super_selector: super_selector.clone(),
|
||||||
selector: s,
|
selector: s,
|
||||||
@ -67,6 +67,6 @@ impl Mixin {
|
|||||||
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
|
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stmts
|
Ok(stmts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user