implement unary ops + and -
This commit is contained in:
parent
51b080e6eb
commit
7d12bc8142
@ -20,6 +20,7 @@ pub(crate) enum Value {
|
||||
Dimension(Number, Unit),
|
||||
List(Vec<Value>, ListSeparator),
|
||||
Color(Color),
|
||||
UnaryOp(Op, Box<Value>),
|
||||
BinaryOp(Box<Value>, Op, Box<Value>),
|
||||
Paren(Box<Value>),
|
||||
Ident(String, QuoteKind),
|
||||
@ -45,7 +46,7 @@ impl Display for Value {
|
||||
.join(sep.as_str())
|
||||
),
|
||||
Self::Color(c) => write!(f, "{}", c),
|
||||
Self::BinaryOp(..) => write!(
|
||||
Self::UnaryOp(..) | Self::BinaryOp(..) => write!(
|
||||
f,
|
||||
"{}",
|
||||
match self.clone().eval() {
|
||||
@ -148,6 +149,13 @@ impl Value {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn unary_op_plus(self) -> SassResult<Self> {
|
||||
Ok(match self.eval()? {
|
||||
v @ Value::Dimension(..) => v,
|
||||
v => Value::Ident(format!("+{}", v), QuoteKind::None),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn eval(self) -> SassResult<Self> {
|
||||
match self {
|
||||
Self::BinaryOp(lhs, op, rhs) => match op {
|
||||
@ -161,6 +169,11 @@ impl Value {
|
||||
_ => Ok(Self::BinaryOp(lhs, op, rhs)),
|
||||
},
|
||||
Self::Paren(v) => v.eval(),
|
||||
Self::UnaryOp(op, val) => match op {
|
||||
Op::Plus => val.unary_op_plus(),
|
||||
Op::Minus => -*val,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => Ok(self),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
||||
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
@ -70,7 +70,7 @@ impl Add for Value {
|
||||
Self::List(..) => Value::Ident(format!("{}{}", c, other), QuoteKind::None),
|
||||
_ => return Err(format!("Undefined operation \"{} + {}\".", c, other).into()),
|
||||
},
|
||||
Self::BinaryOp(..) | Self::Paren(..) => (self.eval()? + other)?,
|
||||
Self::UnaryOp(..) | Self::BinaryOp(..) | Self::Paren(..) => (self.eval()? + other)?,
|
||||
Self::Ident(s1, quotes1) => match other {
|
||||
Self::Ident(s2, quotes2) => {
|
||||
let quotes = match (quotes1, quotes2) {
|
||||
@ -104,7 +104,7 @@ impl Add for Value {
|
||||
Value::Ident(format!("{}{}", s1, c), quotes)
|
||||
}
|
||||
Self::List(..) => Value::Ident(format!("{}{}", s1, other), quotes1),
|
||||
Self::BinaryOp(..) | Self::Paren(..) => todo!(),
|
||||
Self::UnaryOp(..) | Self::BinaryOp(..) | Self::Paren(..) => todo!(),
|
||||
},
|
||||
Self::List(..) => match other {
|
||||
Self::Ident(s, q) => {
|
||||
@ -417,3 +417,14 @@ impl Rem for Value {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Value {
|
||||
type Output = SassResult<Self>;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Ok(match self.eval()? {
|
||||
Value::Dimension(n, u) => Value::Dimension(-n, u),
|
||||
v => Value::Ident(format!("-{}", v), QuoteKind::None),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,17 @@ impl Value {
|
||||
TokenKind::Keyword(Keyword::From(s)) => Ok(Value::Ident(s, QuoteKind::None)),
|
||||
TokenKind::Keyword(Keyword::Through(s)) => Ok(Value::Ident(s, QuoteKind::None)),
|
||||
TokenKind::Keyword(Keyword::To(s)) => Ok(Value::Ident(s, QuoteKind::None)),
|
||||
TokenKind::AtRule(_) => return Err("expected \";\".".into()),
|
||||
TokenKind::AtRule(_) => Err("expected \";\".".into()),
|
||||
TokenKind::Op(Op::Plus) | TokenKind::Symbol(Symbol::Plus) => {
|
||||
devour_whitespace_or_comment(toks);
|
||||
let v = Self::_from_tokens(toks, scope, super_selector)?;
|
||||
Ok(Value::UnaryOp(Op::Plus, Box::new(v)))
|
||||
}
|
||||
TokenKind::Op(Op::Minus) | TokenKind::Symbol(Symbol::Minus) => {
|
||||
devour_whitespace_or_comment(toks);
|
||||
let v = Self::_from_tokens(toks, scope, super_selector)?;
|
||||
Ok(Value::UnaryOp(Op::Minus, Box::new(v)))
|
||||
}
|
||||
v => {
|
||||
dbg!(v);
|
||||
panic!("Unexpected token in value parsing")
|
||||
|
47
tests/unary.rs
Normal file
47
tests/unary.rs
Normal file
@ -0,0 +1,47 @@
|
||||
#![cfg(test)]
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
test!(unary_pos_unquoted_ident, "a {\n color: +foo;\n}\n");
|
||||
test!(
|
||||
unary_pos_whitespace,
|
||||
"a {\n color: + foo;\n}\n",
|
||||
"a {\n color: +foo;\n}\n"
|
||||
);
|
||||
test!(unary_pos_dblquoted_ident, "a {\n color: +\"foo\";\n}\n");
|
||||
test!(
|
||||
unary_pos_sglquoted_ident,
|
||||
"a {\n color: +'foo';\n}\n",
|
||||
"a {\n color: +\"foo\";\n}\n"
|
||||
);
|
||||
test!(unary_pos_color, "a {\n color: +\"foo\";\n}\n");
|
||||
test!(
|
||||
unary_pos_number,
|
||||
"a {\n color: +1px;\n}\n",
|
||||
"a {\n color: 1px;\n}\n"
|
||||
);
|
||||
test!(
|
||||
unary_pos_in_list,
|
||||
"a {\n color: bar,+ \"bar\" - foo;\n}\n",
|
||||
"a {\n color: bar, +\"bar\"-foo;\n}\n"
|
||||
);
|
||||
test!(unary_neg_unquoted_ident, "a {\n color: -foo;\n}\n");
|
||||
test!(unary_neg_dblquoted_ident, "a {\n color: -\"foo\";\n}\n");
|
||||
test!(
|
||||
unary_neg_sglquoted_ident,
|
||||
"a {\n color: -'foo';\n}\n",
|
||||
"a {\n color: -\"foo\";\n}\n"
|
||||
);
|
||||
test!(unary_neg_color, "a {\n color: -\"foo\";\n}\n");
|
||||
test!(unary_neg_number, "a {\n color: -1px;\n}\n");
|
||||
test!(
|
||||
unary_neg_whitespace,
|
||||
"a {\n color: - 1px;\n}\n",
|
||||
"a {\n color: -1px;\n}\n"
|
||||
);
|
||||
test!(
|
||||
unary_neg_number_type,
|
||||
"a {\n color: type-of(- 1px);\n}\n",
|
||||
"a {\n color: number;\n}\n"
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user