Use SassError in more places
This commit is contained in:
parent
64fbc96d9d
commit
eab0049566
@ -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"),
|
||||||
|
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"),
|
||||||
|
22
src/mixin.rs
22
src/mixin.rs
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user