diff --git a/src/atrule.rs b/src/atrule.rs index 19393fd..a9bbd5f 100644 --- a/src/atrule.rs +++ b/src/atrule.rs @@ -2,6 +2,7 @@ use std::fmt::{self, Display}; use std::iter::Peekable; use crate::common::{Pos, Scope, Symbol}; +use crate::error::SassResult; use crate::function::Function; use crate::mixin::Mixin; use crate::utils::devour_whitespace; @@ -38,7 +39,7 @@ impl AtRule { pos: Pos, toks: &mut Peekable, scope: &Scope, - ) -> AtRule { + ) -> SassResult { devour_whitespace(toks); match rule { AtRuleKind::Error => { @@ -46,7 +47,7 @@ impl AtRule { .take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)) .map(|x| x.kind.to_string()) .collect::(); - AtRule::Error(pos, message) + Ok(AtRule::Error(pos, message)) } AtRuleKind::Warn => { let message = toks @@ -54,7 +55,7 @@ impl AtRule { .map(|x| x.kind.to_string()) .collect::(); devour_whitespace(toks); - AtRule::Warn(pos, message) + Ok(AtRule::Warn(pos, message)) } AtRuleKind::Debug => { let message = toks @@ -63,34 +64,28 @@ impl AtRule { .map(|x| x.kind.to_string()) .collect::(); devour_whitespace(toks); - AtRule::Debug(pos, message) + Ok(AtRule::Debug(pos, message)) } AtRuleKind::Mixin => { - let (name, mixin) = match Mixin::decl_from_tokens(toks, scope) { - Ok(m) => m, - Err(e) => return AtRule::Error(e.0, e.1), - }; - AtRule::Mixin(name, Box::new(mixin)) + let (name, mixin) = Mixin::decl_from_tokens(toks, scope)?; + Ok(AtRule::Mixin(name, Box::new(mixin))) } AtRuleKind::Function => { - let (name, func) = match Function::decl_from_tokens(toks, scope) { - Ok(m) => m, - Err(e) => return AtRule::Error(e.0, e.1), - }; - AtRule::Function(name, Box::new(func)) + let (name, func) = Function::decl_from_tokens(toks, scope)?; + Ok(AtRule::Function(name, Box::new(func))) } - AtRuleKind::Return => AtRule::Return( + AtRuleKind::Return => Ok(AtRule::Return( // todo: return may not end in semicolon toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon)) .collect(), - ), + )), AtRuleKind::Use => todo!("@use not yet implemented"), AtRuleKind::Annotation => todo!("@annotation not yet implemented"), AtRuleKind::AtRoot => todo!("@at-root not yet implemented"), - AtRuleKind::Charset => AtRule::Charset( + AtRuleKind::Charset => Ok(AtRule::Charset( toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon)) .collect(), - ), + )), AtRuleKind::Each => todo!("@each not yet implemented"), AtRuleKind::Extend => todo!("@extend not yet implemented"), AtRuleKind::If => todo!("@if not yet implemented"), diff --git a/src/common.rs b/src/common.rs index eeb718e..cd5d4fd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -361,7 +361,7 @@ impl Scope { pub fn get_var(&self, v: &str) -> SassResult<&Value> { match self.vars.get(&v.replace('_', "-")) { Some(v) => Ok(v), - None => Err(format!("Undefined variable: ${}.", v).into()), + None => Err("Undefined variable.".into()), } } @@ -373,10 +373,10 @@ impl Scope { self.vars.contains_key(&v.replace('_', "-")) } - pub fn get_mixin(&self, v: &str) -> Result<&Mixin, String> { + pub fn get_mixin(&self, v: &str) -> SassResult<&Mixin> { match self.mixins.get(&v.replace('_', "-")) { Some(v) => Ok(v), - None => Err(format!("Undefined mixin `{}`.", v)), + None => Err("Undefined mixin.".into()), } } @@ -388,10 +388,10 @@ impl Scope { self.mixins.contains_key(&v.replace('_', "-")) } - pub fn get_fn(&self, v: &str) -> Result<&Function, String> { + pub fn get_fn(&self, v: &str) -> SassResult<&Function> { match self.functions.get(&v.replace('_', "-")) { Some(v) => Ok(v), - None => Err(format!("Undefined function `{}`.", v)), + None => Err("Undefined function.".into()), } } diff --git a/src/function.rs b/src/function.rs index 92b4da7..f0907e3 100644 --- a/src/function.rs +++ b/src/function.rs @@ -2,7 +2,7 @@ use std::iter::Peekable; use crate::args::{CallArgs, eat_func_args, FuncArgs}; use crate::atrule::AtRule; -use crate::common::{Pos, Scope, Symbol}; +use crate::common::{Scope, Symbol}; use crate::error::SassResult; use crate::utils::devour_whitespace; use crate::value::Value; @@ -23,19 +23,14 @@ impl Function { pub fn decl_from_tokens>( toks: &mut Peekable, scope: &Scope, - ) -> Result<(String, Function), (Pos, String)> { - let Token { pos, kind } = toks + ) -> SassResult<(String, Function)> { + let Token { kind, .. } = toks .next() .expect("this must exist because we have already peeked"); devour_whitespace(toks); let name = match kind { TokenKind::Ident(s) => s, - _ => { - return Err(( - pos, - String::from("expected identifier after function declaration"), - )) - } + _ => return Err("Expected identifier.".into()) }; devour_whitespace(toks); let args = match toks.next() { @@ -43,7 +38,7 @@ impl Function { kind: TokenKind::Symbol(Symbol::OpenParen), .. }) => eat_func_args(toks, scope), - _ => return Err((pos, String::from("expected `(` after function declaration"))), + _ => return Err("expected \"(\".".into()), }; let mut nesting = 1; @@ -53,13 +48,13 @@ impl Function { if let Some(tok) = toks.next() { match &tok.kind { TokenKind::AtRule(rule) => { - body.push(AtRule::from_tokens(rule, tok.pos, toks, scope)) + body.push(AtRule::from_tokens(rule, tok.pos, toks, scope)?) } TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1, _ => {} } } else { - return Err((pos, String::from("unexpected EOF"))); + return Err("unexpected EOF (TODO: better error message)".into()); } } diff --git a/src/lib.rs b/src/lib.rs index 564be16..8236d48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -430,7 +430,7 @@ impl<'a> StyleSheetParser<'a> { pos, }) = self.lexer.next() { - match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope) { + match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope)? { AtRule::Mixin(name, mixin) => { self.global_scope.insert_mixin(&name, *mixin); } @@ -609,7 +609,7 @@ pub(crate) fn eat_expr>( pos, }) = toks.next() { - return match AtRule::from_tokens(rule, pos, toks, scope) { + return match AtRule::from_tokens(rule, pos, toks, scope)? { AtRule::Mixin(name, mixin) => Ok(Some(Expr::MixinDecl(name, mixin))), AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, func))), AtRule::Charset(_) => todo!("@charset as expr"), diff --git a/src/mixin.rs b/src/mixin.rs index 385adc4..67f2407 100644 --- a/src/mixin.rs +++ b/src/mixin.rs @@ -2,7 +2,7 @@ use std::iter::Peekable; use std::vec::IntoIter; use crate::args::{eat_call_args, eat_func_args, CallArgs, FuncArgs}; -use crate::common::{Pos, Scope, Symbol}; +use crate::common::{Scope, Symbol}; use crate::error::{SassError, SassResult}; use crate::selector::Selector; use crate::utils::devour_whitespace; @@ -24,19 +24,14 @@ impl Mixin { pub fn decl_from_tokens>( toks: &mut Peekable, scope: &Scope, - ) -> Result<(String, Mixin), (Pos, String)> { - let Token { pos, kind } = toks + ) -> SassResult<(String, Mixin)> { + let Token { kind, .. } = toks .next() .expect("this must exist because we have already peeked"); devour_whitespace(toks); let name = match kind { TokenKind::Ident(s) => s, - _ => { - return Err(( - pos, - String::from("expected identifier after mixin declaration"), - )) - } + _ => return Err("Expected identifier.".into()), }; devour_whitespace(toks); let args = match toks.next() { @@ -48,7 +43,7 @@ impl Mixin { kind: TokenKind::Symbol(Symbol::OpenCurlyBrace), .. }) => FuncArgs::new(), - _ => return Err((pos, String::from("expected `(` or `{`"))), + _ => return Err("expected \"{\"".into()), }; devour_whitespace(toks); @@ -67,7 +62,7 @@ impl Mixin { } body.push(tok) } else { - return Err((pos, String::from("unexpected EOF"))); + return Err("unexpected EOF (TODO: better message)".into()); } } @@ -156,10 +151,7 @@ pub(crate) fn eat_include>( devour_whitespace(toks); - let mixin = match scope.get_mixin(&name) { - Ok(m) => m.clone(), - _ => return Err(SassError::new("Expected identifier.", pos)), - }; + let mixin = scope.get_mixin(&name)?.clone(); let rules = mixin.args(&args).call(super_selector)?; Ok(rules)