Use SassError in more places

This commit is contained in:
ConnorSkees 2020-02-17 09:22:41 -05:00
parent 64fbc96d9d
commit eab0049566
5 changed files with 34 additions and 52 deletions

View File

@ -2,6 +2,7 @@ use std::fmt::{self, Display};
use std::iter::Peekable; use std::iter::Peekable;
use crate::common::{Pos, Scope, Symbol}; use crate::common::{Pos, Scope, Symbol};
use crate::error::SassResult;
use crate::function::Function; use crate::function::Function;
use crate::mixin::Mixin; use crate::mixin::Mixin;
use crate::utils::devour_whitespace; use crate::utils::devour_whitespace;
@ -38,7 +39,7 @@ impl AtRule {
pos: Pos, pos: Pos,
toks: &mut Peekable<I>, toks: &mut Peekable<I>,
scope: &Scope, scope: &Scope,
) -> AtRule { ) -> SassResult<AtRule> {
devour_whitespace(toks); devour_whitespace(toks);
match rule { match rule {
AtRuleKind::Error => { AtRuleKind::Error => {
@ -46,7 +47,7 @@ impl AtRule {
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)) .take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
.map(|x| x.kind.to_string()) .map(|x| x.kind.to_string())
.collect::<String>(); .collect::<String>();
AtRule::Error(pos, message) Ok(AtRule::Error(pos, message))
} }
AtRuleKind::Warn => { AtRuleKind::Warn => {
let message = toks let message = toks
@ -54,7 +55,7 @@ impl AtRule {
.map(|x| x.kind.to_string()) .map(|x| x.kind.to_string())
.collect::<String>(); .collect::<String>();
devour_whitespace(toks); devour_whitespace(toks);
AtRule::Warn(pos, message) Ok(AtRule::Warn(pos, message))
} }
AtRuleKind::Debug => { AtRuleKind::Debug => {
let message = toks let message = toks
@ -63,34 +64,28 @@ impl AtRule {
.map(|x| x.kind.to_string()) .map(|x| x.kind.to_string())
.collect::<String>(); .collect::<String>();
devour_whitespace(toks); devour_whitespace(toks);
AtRule::Debug(pos, message) Ok(AtRule::Debug(pos, message))
} }
AtRuleKind::Mixin => { AtRuleKind::Mixin => {
let (name, mixin) = match Mixin::decl_from_tokens(toks, scope) { let (name, mixin) = Mixin::decl_from_tokens(toks, scope)?;
Ok(m) => m, Ok(AtRule::Mixin(name, Box::new(mixin)))
Err(e) => return AtRule::Error(e.0, e.1),
};
AtRule::Mixin(name, Box::new(mixin))
} }
AtRuleKind::Function => { AtRuleKind::Function => {
let (name, func) = match Function::decl_from_tokens(toks, scope) { let (name, func) = Function::decl_from_tokens(toks, scope)?;
Ok(m) => m, Ok(AtRule::Function(name, Box::new(func)))
Err(e) => return AtRule::Error(e.0, e.1),
};
AtRule::Function(name, Box::new(func))
} }
AtRuleKind::Return => AtRule::Return( AtRuleKind::Return => Ok(AtRule::Return(
// todo: return may not end in semicolon // todo: return may not end in semicolon
toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon)) toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon))
.collect(), .collect(),
), )),
AtRuleKind::Use => todo!("@use not yet implemented"), AtRuleKind::Use => todo!("@use not yet implemented"),
AtRuleKind::Annotation => todo!("@annotation not yet implemented"), AtRuleKind::Annotation => todo!("@annotation not yet implemented"),
AtRuleKind::AtRoot => todo!("@at-root 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)) toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon))
.collect(), .collect(),
), )),
AtRuleKind::Each => todo!("@each not yet implemented"), AtRuleKind::Each => todo!("@each not yet implemented"),
AtRuleKind::Extend => todo!("@extend not yet implemented"), AtRuleKind::Extend => todo!("@extend not yet implemented"),
AtRuleKind::If => todo!("@if not yet implemented"), AtRuleKind::If => todo!("@if not yet implemented"),

View File

@ -361,7 +361,7 @@ impl Scope {
pub fn get_var(&self, v: &str) -> SassResult<&Value> { pub fn get_var(&self, v: &str) -> SassResult<&Value> {
match self.vars.get(&v.replace('_', "-")) { match self.vars.get(&v.replace('_', "-")) {
Some(v) => Ok(v), 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('_', "-")) 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('_', "-")) { match self.mixins.get(&v.replace('_', "-")) {
Some(v) => Ok(v), 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('_', "-")) 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('_', "-")) { match self.functions.get(&v.replace('_', "-")) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(format!("Undefined function `{}`.", v)), None => Err("Undefined function.".into()),
} }
} }

View File

@ -2,7 +2,7 @@ use std::iter::Peekable;
use crate::args::{CallArgs, eat_func_args, FuncArgs}; use crate::args::{CallArgs, eat_func_args, FuncArgs};
use crate::atrule::AtRule; use crate::atrule::AtRule;
use crate::common::{Pos, Scope, Symbol}; use crate::common::{Scope, Symbol};
use crate::error::SassResult; use crate::error::SassResult;
use crate::utils::devour_whitespace; use crate::utils::devour_whitespace;
use crate::value::Value; use crate::value::Value;
@ -23,19 +23,14 @@ impl Function {
pub fn decl_from_tokens<I: Iterator<Item = Token>>( pub fn decl_from_tokens<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>, toks: &mut Peekable<I>,
scope: &Scope, scope: &Scope,
) -> Result<(String, Function), (Pos, String)> { ) -> SassResult<(String, Function)> {
let Token { pos, kind } = toks let Token { kind, .. } = toks
.next() .next()
.expect("this must exist because we have already peeked"); .expect("this must exist because we have already peeked");
devour_whitespace(toks); devour_whitespace(toks);
let name = match kind { let name = match kind {
TokenKind::Ident(s) => s, TokenKind::Ident(s) => s,
_ => { _ => return Err("Expected identifier.".into())
return Err((
pos,
String::from("expected identifier after function declaration"),
))
}
}; };
devour_whitespace(toks); devour_whitespace(toks);
let args = match toks.next() { let args = match toks.next() {
@ -43,7 +38,7 @@ impl Function {
kind: TokenKind::Symbol(Symbol::OpenParen), kind: TokenKind::Symbol(Symbol::OpenParen),
.. ..
}) => eat_func_args(toks, scope), }) => eat_func_args(toks, scope),
_ => return Err((pos, String::from("expected `(` after function declaration"))), _ => return Err("expected \"(\".".into()),
}; };
let mut nesting = 1; let mut nesting = 1;
@ -53,13 +48,13 @@ impl Function {
if let Some(tok) = toks.next() { if let Some(tok) = toks.next() {
match &tok.kind { match &tok.kind {
TokenKind::AtRule(rule) => { 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, TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1,
_ => {} _ => {}
} }
} else { } else {
return Err((pos, String::from("unexpected EOF"))); return Err("unexpected EOF (TODO: better error message)".into());
} }
} }

View File

@ -430,7 +430,7 @@ impl<'a> StyleSheetParser<'a> {
pos, pos,
}) = self.lexer.next() }) = 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) => { AtRule::Mixin(name, mixin) => {
self.global_scope.insert_mixin(&name, *mixin); self.global_scope.insert_mixin(&name, *mixin);
} }
@ -609,7 +609,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
pos, pos,
}) = toks.next() }) = 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::Mixin(name, mixin) => Ok(Some(Expr::MixinDecl(name, mixin))),
AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, func))), AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, func))),
AtRule::Charset(_) => todo!("@charset as expr"), AtRule::Charset(_) => todo!("@charset as expr"),

View File

@ -2,7 +2,7 @@ use std::iter::Peekable;
use std::vec::IntoIter; use std::vec::IntoIter;
use crate::args::{eat_call_args, eat_func_args, CallArgs, FuncArgs}; 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::error::{SassError, SassResult};
use crate::selector::Selector; use crate::selector::Selector;
use crate::utils::devour_whitespace; use crate::utils::devour_whitespace;
@ -24,19 +24,14 @@ impl Mixin {
pub fn decl_from_tokens<I: Iterator<Item = Token>>( pub fn decl_from_tokens<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>, toks: &mut Peekable<I>,
scope: &Scope, scope: &Scope,
) -> Result<(String, Mixin), (Pos, String)> { ) -> SassResult<(String, Mixin)> {
let Token { pos, kind } = toks let Token { kind, .. } = toks
.next() .next()
.expect("this must exist because we have already peeked"); .expect("this must exist because we have already peeked");
devour_whitespace(toks); devour_whitespace(toks);
let name = match kind { let name = match kind {
TokenKind::Ident(s) => s, TokenKind::Ident(s) => s,
_ => { _ => return Err("Expected identifier.".into()),
return Err((
pos,
String::from("expected identifier after mixin declaration"),
))
}
}; };
devour_whitespace(toks); devour_whitespace(toks);
let args = match toks.next() { let args = match toks.next() {
@ -48,7 +43,7 @@ impl Mixin {
kind: TokenKind::Symbol(Symbol::OpenCurlyBrace), kind: TokenKind::Symbol(Symbol::OpenCurlyBrace),
.. ..
}) => FuncArgs::new(), }) => FuncArgs::new(),
_ => return Err((pos, String::from("expected `(` or `{`"))), _ => return Err("expected \"{\"".into()),
}; };
devour_whitespace(toks); devour_whitespace(toks);
@ -67,7 +62,7 @@ impl Mixin {
} }
body.push(tok) body.push(tok)
} else { } 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<I: Iterator<Item = Token>>(
devour_whitespace(toks); devour_whitespace(toks);
let mixin = match scope.get_mixin(&name) { let mixin = scope.get_mixin(&name)?.clone();
Ok(m) => m.clone(),
_ => return Err(SassError::new("Expected identifier.", pos)),
};
let rules = mixin.args(&args).call(super_selector)?; let rules = mixin.args(&args).call(super_selector)?;
Ok(rules) Ok(rules)