diff --git a/src/error.rs b/src/error.rs index 9b813b9..ac7794e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,7 +7,7 @@ use crate::common::Pos; pub type SassResult = Result; -#[derive(Debug)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct SassError { message: String, pos: Pos, diff --git a/src/lexer.rs b/src/lexer.rs index 2d9f5c1..e118d15 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -285,8 +285,7 @@ impl<'a> Lexer<'a> { if c == &'=' { return TokenKind::Symbol(Symbol::Dollar); } else if !c.is_alphabetic() && c != &'-' && c != &'_' { - eprintln!("Error: Expected identifier."); - std::process::exit(1) + return TokenKind::Error("Expected identifier.".into()); } else { self.pos.next_char(); name.push(*c); diff --git a/src/lib.rs b/src/lib.rs index 8ea2249..d1f92b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -121,10 +121,6 @@ mod unit; mod utils; mod value; -pub(crate) fn error>(msg: E) -> ! { - eprintln!("Error: {}", msg.into()); - std::process::exit(1); -} /// Represents a parsed SASS stylesheet with nesting #[derive(Debug, Clone)] pub struct StyleSheet(Vec); @@ -325,11 +321,13 @@ impl<'a> StyleSheetParser<'a> { GLOBAL_SCOPE.with(|s| { if !default || s.borrow().get_var(&name).is_err() { match s.borrow_mut().insert_var(&name, val) { - Ok(..) => {}, - Err(e) => error(e), + Ok(..) => Ok(()), + Err(e) => Err(e), } + } else { + Ok(()) } - }) + })? } TokenKind::MultilineComment(_) => { let comment = match self diff --git a/src/token.rs b/src/token.rs index 9ca24fb..2b5725c 100644 --- a/src/token.rs +++ b/src/token.rs @@ -2,6 +2,7 @@ use std::fmt; use crate::atrule::AtRuleKind; use crate::common::{Keyword, Op, Pos, Symbol, Whitespace}; +use crate::error::SassError; use crate::utils::{IsComment, IsWhitespace}; #[derive(Clone, Debug, Eq, PartialEq)] @@ -82,6 +83,7 @@ pub(crate) enum TokenKind { Op(Op), MultilineComment(String), Interpolation, + Error(SassError), } impl TokenKind { @@ -102,7 +104,7 @@ impl fmt::Display for TokenKind { TokenKind::Keyword(kw) => write!(f, "{}", kw), TokenKind::MultilineComment(s) => write!(f, "/*{}*/", s), TokenKind::Variable(s) => write!(f, "{}", s), - TokenKind::Interpolation => { + TokenKind::Interpolation | TokenKind::Error(..) => { panic!("we don't want to format TokenKind::Interpolation using Display") } } diff --git a/src/value/parse.rs b/src/value/parse.rs index 78f2f6f..6abef4c 100644 --- a/src/value/parse.rs +++ b/src/value/parse.rs @@ -293,6 +293,7 @@ impl Value { TokenKind::Keyword(Keyword::Through(s)) => Ok(Value::Ident(s, QuoteKind::None)), TokenKind::Keyword(Keyword::To(s)) => Ok(Value::Ident(s, QuoteKind::None)), TokenKind::AtRule(_) => Err("expected \";\".".into()), + TokenKind::Error(e) => return Err(e), TokenKind::Op(Op::Plus) | TokenKind::Symbol(Symbol::Plus) => { devour_whitespace_or_comment(toks); let v = Self::_from_tokens(toks, scope, super_selector)?;