mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 17:40:52 +01:00
Comparison operators and Iverson brackets
This commit is contained in:
parent
2402d444f5
commit
fe50789cbd
@ -156,6 +156,12 @@ fn eval_binary_expr(
|
|||||||
TokenKind::Slash => left.div(context, right),
|
TokenKind::Slash => left.div(context, right),
|
||||||
TokenKind::Percent => left.rem(context, right),
|
TokenKind::Percent => left.rem(context, right),
|
||||||
TokenKind::Power => left.pow(context, right),
|
TokenKind::Power => left.pow(context, right),
|
||||||
|
TokenKind::Equals => left.eq(context, right),
|
||||||
|
TokenKind::NotEquals => left.not_eq(context, right),
|
||||||
|
TokenKind::GreaterThan => left.greater_than(context, right),
|
||||||
|
TokenKind::LessThan => left.less_than(context, right),
|
||||||
|
TokenKind::GreaterOrEquals => left.greater_or_equals(context, right),
|
||||||
|
TokenKind::LessOrEquals => left.less_or_equals(context, right),
|
||||||
_ => KalkNum::from(1),
|
_ => KalkNum::from(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -468,12 +474,54 @@ mod tests {
|
|||||||
let mul = Stmt::Expr(binary(literal(2f64), Star, literal(3f64)));
|
let mul = Stmt::Expr(binary(literal(2f64), Star, literal(3f64)));
|
||||||
let div = Stmt::Expr(binary(literal(2f64), Slash, literal(4f64)));
|
let div = Stmt::Expr(binary(literal(2f64), Slash, literal(4f64)));
|
||||||
let pow = Stmt::Expr(binary(literal(2f64), Power, literal(3f64)));
|
let pow = Stmt::Expr(binary(literal(2f64), Power, literal(3f64)));
|
||||||
|
let equals = Stmt::Expr(binary(literal(2f64), Equals, literal(3f64)));
|
||||||
|
let not_equals = Stmt::Expr(binary(literal(2f64), NotEquals, literal(3f64)));
|
||||||
|
let greater_than = Stmt::Expr(binary(literal(2f64), GreaterThan, literal(3f64)));
|
||||||
|
let less_than = Stmt::Expr(binary(literal(2f64), LessThan, literal(3f64)));
|
||||||
|
let greater_or_equals = Stmt::Expr(binary(literal(2f64), GreaterOrEquals, literal(3f64)));
|
||||||
|
let less_or_equals = Stmt::Expr(binary(literal(2f64), LessOrEquals, literal(3f64)));
|
||||||
|
|
||||||
assert_eq!(interpret(add).unwrap().unwrap().to_f64(), 5f64);
|
assert_eq!(interpret(add).unwrap().unwrap().to_f64(), 5f64);
|
||||||
assert_eq!(interpret(sub).unwrap().unwrap().to_f64(), -1f64);
|
assert_eq!(interpret(sub).unwrap().unwrap().to_f64(), -1f64);
|
||||||
assert_eq!(interpret(mul).unwrap().unwrap().to_f64(), 6f64);
|
assert_eq!(interpret(mul).unwrap().unwrap().to_f64(), 6f64);
|
||||||
assert_eq!(interpret(div).unwrap().unwrap().to_f64(), 0.5f64);
|
assert_eq!(interpret(div).unwrap().unwrap().to_f64(), 0.5f64);
|
||||||
assert_eq!(interpret(pow).unwrap().unwrap().to_f64(), 8f64);
|
assert_eq!(interpret(pow).unwrap().unwrap().to_f64(), 8f64);
|
||||||
|
|
||||||
|
let result = interpret(equals).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = interpret(not_equals).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = interpret(greater_than).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = interpret(less_than).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = interpret(greater_or_equals).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = interpret(less_or_equals).unwrap().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(result.to_f64(), result.boolean_value.unwrap()),
|
||||||
|
(3f64, true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -186,6 +186,10 @@ impl KalkNum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string_pretty(&self) -> String {
|
pub fn to_string_pretty(&self) -> String {
|
||||||
|
if let Some(boolean_value) = self.boolean_value {
|
||||||
|
return boolean_value.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
let real_f64 = self.to_f64();
|
let real_f64 = self.to_f64();
|
||||||
let imaginary_f64 = self.imaginary_to_f64();
|
let imaginary_f64 = self.imaginary_to_f64();
|
||||||
if real_f64.is_nan() || imaginary_f64.is_nan() {
|
if real_f64.is_nan() || imaginary_f64.is_nan() {
|
||||||
@ -314,6 +318,58 @@ impl KalkNum {
|
|||||||
KalkNum::new(self.value % right.value, &right.unit)
|
KalkNum::new(self.value % right.value, &right.unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn eq(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value == right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn not_eq(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value != right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn greater_than(
|
||||||
|
self,
|
||||||
|
context: &mut crate::interpreter::Context,
|
||||||
|
rhs: KalkNum,
|
||||||
|
) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value > right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn less_than(
|
||||||
|
self,
|
||||||
|
context: &mut crate::interpreter::Context,
|
||||||
|
rhs: KalkNum,
|
||||||
|
) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value < right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn greater_or_equals(
|
||||||
|
self,
|
||||||
|
context: &mut crate::interpreter::Context,
|
||||||
|
rhs: KalkNum,
|
||||||
|
) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value >= right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn less_or_equals(
|
||||||
|
self,
|
||||||
|
context: &mut crate::interpreter::Context,
|
||||||
|
rhs: KalkNum,
|
||||||
|
) -> KalkNum {
|
||||||
|
let mut right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
|
right.boolean_value = Some(self.value <= right.value);
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn add_without_unit(self, rhs: KalkNum) -> KalkNum {
|
pub(crate) fn add_without_unit(self, rhs: KalkNum) -> KalkNum {
|
||||||
KalkNum::new_with_imaginary(
|
KalkNum::new_with_imaginary(
|
||||||
self.value + rhs.value,
|
self.value + rhs.value,
|
||||||
|
@ -7,6 +7,7 @@ pub struct KalkNum {
|
|||||||
pub(crate) value: f64,
|
pub(crate) value: f64,
|
||||||
pub(crate) unit: String,
|
pub(crate) unit: String,
|
||||||
pub(crate) imaginary_value: f64,
|
pub(crate) imaginary_value: f64,
|
||||||
|
pub(crate) boolean_value: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@ -16,6 +17,7 @@ impl KalkNum {
|
|||||||
value,
|
value,
|
||||||
unit: unit.to_string(),
|
unit: unit.to_string(),
|
||||||
imaginary_value: 0f64,
|
imaginary_value: 0f64,
|
||||||
|
boolean_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ impl KalkNum {
|
|||||||
} else {
|
} else {
|
||||||
imaginary_value
|
imaginary_value
|
||||||
},
|
},
|
||||||
|
boolean_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +39,16 @@ impl KalkNum {
|
|||||||
value: 0f64,
|
value: 0f64,
|
||||||
unit: String::new(),
|
unit: String::new(),
|
||||||
imaginary_value: value,
|
imaginary_value: value,
|
||||||
|
boolean_value: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bool(value: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
value: 0f64,
|
||||||
|
unit: String::new(),
|
||||||
|
imaginary_value: 0f64,
|
||||||
|
boolean_value: Some(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ pub struct KalkNum {
|
|||||||
pub(crate) value: Float,
|
pub(crate) value: Float,
|
||||||
pub(crate) unit: String,
|
pub(crate) unit: String,
|
||||||
pub(crate) imaginary_value: Float,
|
pub(crate) imaginary_value: Float,
|
||||||
|
pub(crate) boolean_value: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KalkNum {
|
impl KalkNum {
|
||||||
@ -19,6 +20,7 @@ impl KalkNum {
|
|||||||
value,
|
value,
|
||||||
unit: unit.to_string(),
|
unit: unit.to_string(),
|
||||||
imaginary_value: Float::with_val(63, 0),
|
imaginary_value: Float::with_val(63, 0),
|
||||||
|
boolean_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +33,7 @@ impl KalkNum {
|
|||||||
} else {
|
} else {
|
||||||
imaginary_value
|
imaginary_value
|
||||||
},
|
},
|
||||||
|
boolean_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +42,16 @@ impl KalkNum {
|
|||||||
value: Float::with_val(63, 0),
|
value: Float::with_val(63, 0),
|
||||||
unit: String::new(),
|
unit: String::new(),
|
||||||
imaginary_value: value,
|
imaginary_value: value,
|
||||||
|
boolean_value: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bool(value: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
value: Float::with_val(63, 0),
|
||||||
|
unit: String::new(),
|
||||||
|
imaginary_value: Float::with_val(63, 0),
|
||||||
|
boolean_value: Some(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,10 +13,15 @@ pub enum TokenKind {
|
|||||||
Star,
|
Star,
|
||||||
Slash,
|
Slash,
|
||||||
Power,
|
Power,
|
||||||
Equals,
|
|
||||||
Exclamation,
|
Exclamation,
|
||||||
Percent,
|
Percent,
|
||||||
Tick,
|
Tick,
|
||||||
|
GreaterThan,
|
||||||
|
LessThan,
|
||||||
|
Equals,
|
||||||
|
NotEquals,
|
||||||
|
GreaterOrEquals,
|
||||||
|
LessOrEquals,
|
||||||
|
|
||||||
UnitKeyword,
|
UnitKeyword,
|
||||||
ToKeyword,
|
ToKeyword,
|
||||||
@ -28,6 +33,8 @@ pub enum TokenKind {
|
|||||||
ClosedFloor,
|
ClosedFloor,
|
||||||
OpenParenthesis,
|
OpenParenthesis,
|
||||||
ClosedParenthesis,
|
ClosedParenthesis,
|
||||||
|
OpenBracket,
|
||||||
|
ClosedBracket,
|
||||||
Comma,
|
Comma,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
|
|
||||||
@ -110,12 +117,19 @@ impl<'a> Lexer<'a> {
|
|||||||
'⌋' => build(TokenKind::ClosedFloor, "", span),
|
'⌋' => build(TokenKind::ClosedFloor, "", span),
|
||||||
'(' => build(TokenKind::OpenParenthesis, "", span),
|
'(' => build(TokenKind::OpenParenthesis, "", span),
|
||||||
')' => build(TokenKind::ClosedParenthesis, "", span),
|
')' => build(TokenKind::ClosedParenthesis, "", span),
|
||||||
'=' => build(TokenKind::Equals, "", span),
|
'[' => build(TokenKind::OpenBracket, "", span),
|
||||||
|
']' => build(TokenKind::ClosedBracket, "", span),
|
||||||
'!' => build(TokenKind::Exclamation, "", span),
|
'!' => build(TokenKind::Exclamation, "", span),
|
||||||
|
'=' => build(TokenKind::Equals, "", span),
|
||||||
|
'>' => build(TokenKind::GreaterThan, "", span),
|
||||||
|
'<' => build(TokenKind::LessThan, "", span),
|
||||||
',' => build(TokenKind::Comma, "", span),
|
',' => build(TokenKind::Comma, "", span),
|
||||||
';' => build(TokenKind::Semicolon, "", span),
|
';' => build(TokenKind::Semicolon, "", span),
|
||||||
'%' => build(TokenKind::Percent, "", span),
|
'%' => build(TokenKind::Percent, "", span),
|
||||||
'\'' => build(TokenKind::Tick, "", span),
|
'\'' => build(TokenKind::Tick, "", span),
|
||||||
|
'≠' => build(TokenKind::NotEquals, "", span),
|
||||||
|
'≥' => build(TokenKind::GreaterOrEquals, "", span),
|
||||||
|
'≤' => build(TokenKind::LessOrEquals, "", span),
|
||||||
// Some of the special symbols will be lexed here,
|
// Some of the special symbols will be lexed here,
|
||||||
// so that they don't merge with other symbols.
|
// so that they don't merge with other symbols.
|
||||||
'π' => build(TokenKind::Identifier, "π", span),
|
'π' => build(TokenKind::Identifier, "π", span),
|
||||||
@ -128,13 +142,25 @@ impl<'a> Lexer<'a> {
|
|||||||
|
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
||||||
// Handle **
|
// Handle tokens with two characters
|
||||||
if let (TokenKind::Star, Some(c)) = (token.kind, self.peek()) {
|
match (token.kind, self.peek()) {
|
||||||
if *c == '*' {
|
(TokenKind::Star, Some('*')) => {
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
||||||
return build(TokenKind::Power, "", span);
|
return build(TokenKind::Power, "", span);
|
||||||
}
|
}
|
||||||
|
(TokenKind::Exclamation, Some('=')) => {
|
||||||
|
self.advance();
|
||||||
|
return build(TokenKind::NotEquals, "", span);
|
||||||
|
}
|
||||||
|
(TokenKind::GreaterThan, Some('=')) => {
|
||||||
|
self.advance();
|
||||||
|
return build(TokenKind::GreaterOrEquals, "", span);
|
||||||
|
}
|
||||||
|
(TokenKind::LessThan, Some('=')) => {
|
||||||
|
self.advance();
|
||||||
|
return build(TokenKind::LessOrEquals, "", span);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
token
|
token
|
||||||
@ -228,7 +254,8 @@ fn is_valid_identifier(c: Option<&char>) -> bool {
|
|||||||
if let Some(c) = c {
|
if let Some(c) = c {
|
||||||
match c {
|
match c {
|
||||||
'+' | '-' | '/' | '*' | '%' | '^' | '!' | '(' | ')' | '=' | '.' | ',' | ';' | '|'
|
'+' | '-' | '/' | '*' | '%' | '^' | '!' | '(' | ')' | '=' | '.' | ',' | ';' | '|'
|
||||||
| '⌊' | '⌋' | '⌈' | '⌉' | ']' | 'π' | '√' | 'τ' | 'ϕ' | 'Γ' => false,
|
| '⌊' | '⌋' | '⌈' | '⌉' | '[' | ']' | 'π' | '√' | 'τ' | 'ϕ' | 'Γ' | '<' | '>' | '≠'
|
||||||
|
| '≥' | '≤' => false,
|
||||||
_ => !c.is_digit(10),
|
_ => !c.is_digit(10),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -274,6 +301,22 @@ mod tests {
|
|||||||
match_tokens(tokens, expected);
|
match_tokens(tokens, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn test_brackets() {
|
||||||
|
let tokens = Lexer::lex("[1 < 2]");
|
||||||
|
let expected = vec![
|
||||||
|
TokenKind::OpenBracket,
|
||||||
|
TokenKind::Literal,
|
||||||
|
TokenKind::LessThan,
|
||||||
|
TokenKind::Literal,
|
||||||
|
TokenKind::ClosedBracket,
|
||||||
|
TokenKind::EOF,
|
||||||
|
];
|
||||||
|
|
||||||
|
match_tokens(tokens, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_empty() {
|
fn test_empty() {
|
||||||
|
@ -149,7 +149,9 @@ pub fn eval(
|
|||||||
) -> Result<Option<KalkNum>, CalcError> {
|
) -> Result<Option<KalkNum>, CalcError> {
|
||||||
// Variable and function declaration parsers will set this to false
|
// Variable and function declaration parsers will set this to false
|
||||||
// if the equal sign is for one of those instead.
|
// if the equal sign is for one of those instead.
|
||||||
context.contains_equation_equal_sign = input.contains("=");
|
// It also should not contain an iverson bracket, since equal signs in there
|
||||||
|
// mean something else. This is not super reliable, and should probably be improved in the future.
|
||||||
|
context.contains_equation_equal_sign = input.contains("=") && !input.contains("[");
|
||||||
let statements = parse(context, input)?;
|
let statements = parse(context, input)?;
|
||||||
|
|
||||||
let mut interpreter = interpreter::Context::new(
|
let mut interpreter = interpreter::Context::new(
|
||||||
@ -302,13 +304,14 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_expr(context: &mut Context) -> Result<Expr, CalcError> {
|
||||||
Ok(parse_equation(context)?)
|
Ok(parse_equality(context)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_equation(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_equality(context: &mut Context) -> Result<Expr, CalcError> {
|
||||||
let left = parse_to(context)?;
|
let mut left = parse_to(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Equals) {
|
// Equation
|
||||||
|
if match_token(context, TokenKind::Equals) && context.contains_equation_equal_sign {
|
||||||
advance(context);
|
advance(context);
|
||||||
let right = parse_to(context)?;
|
let right = parse_to(context)?;
|
||||||
let var_name = if let Some(var_name) = &context.equation_variable {
|
let var_name = if let Some(var_name) = &context.equation_variable {
|
||||||
@ -333,9 +336,25 @@ fn parse_equation(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
Identifier::from_full_name(var_name),
|
Identifier::from_full_name(var_name),
|
||||||
Box::new(inverted.clone()),
|
Box::new(inverted.clone()),
|
||||||
));
|
));
|
||||||
|
|
||||||
return Ok(inverted);
|
return Ok(inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equality check
|
||||||
|
while match_token(context, TokenKind::Equals)
|
||||||
|
|| match_token(context, TokenKind::NotEquals)
|
||||||
|
|| match_token(context, TokenKind::GreaterThan)
|
||||||
|
|| match_token(context, TokenKind::LessThan)
|
||||||
|
|| match_token(context, TokenKind::GreaterOrEquals)
|
||||||
|
|| match_token(context, TokenKind::LessOrEquals)
|
||||||
|
{
|
||||||
|
let op = peek(context).kind;
|
||||||
|
advance(context);
|
||||||
|
let right = parse_to(context)?;
|
||||||
|
|
||||||
|
left = Expr::Binary(Box::new(left), op, Box::new(right));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +481,9 @@ fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
|
||||||
let expr = match peek(context).kind {
|
let expr = match peek(context).kind {
|
||||||
TokenKind::OpenParenthesis => parse_group(context)?,
|
TokenKind::OpenParenthesis => parse_group(context)?,
|
||||||
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
|
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor | TokenKind::OpenBracket => {
|
||||||
|
parse_group_fn(context)?
|
||||||
|
}
|
||||||
TokenKind::Identifier => parse_identifier(context)?,
|
TokenKind::Identifier => parse_identifier(context)?,
|
||||||
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
|
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
|
||||||
_ => return Err(CalcError::UnableToParseExpression),
|
_ => return Err(CalcError::UnableToParseExpression),
|
||||||
@ -484,6 +505,7 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
TokenKind::Pipe => "abs",
|
TokenKind::Pipe => "abs",
|
||||||
TokenKind::OpenCeil => "ceil",
|
TokenKind::OpenCeil => "ceil",
|
||||||
TokenKind::OpenFloor => "floor",
|
TokenKind::OpenFloor => "floor",
|
||||||
|
TokenKind::OpenBracket => "iverson",
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ lazy_static! {
|
|||||||
m.insert("abs", (UnaryFuncInfo(abs, Other), ""));
|
m.insert("abs", (UnaryFuncInfo(abs, Other), ""));
|
||||||
m.insert("cbrt", (UnaryFuncInfo(cbrt, Other), ""));
|
m.insert("cbrt", (UnaryFuncInfo(cbrt, Other), ""));
|
||||||
m.insert("ceil", (UnaryFuncInfo(ceil, Other), ""));
|
m.insert("ceil", (UnaryFuncInfo(ceil, Other), ""));
|
||||||
|
m.insert("iverson", (UnaryFuncInfo(inverson, Other), ""));
|
||||||
m.insert("exp", (UnaryFuncInfo(exp, Other), ""));
|
m.insert("exp", (UnaryFuncInfo(exp, Other), ""));
|
||||||
m.insert("floor", (UnaryFuncInfo(floor, Other), ""));
|
m.insert("floor", (UnaryFuncInfo(floor, Other), ""));
|
||||||
m.insert("frac", (UnaryFuncInfo(frac, Other), ""));
|
m.insert("frac", (UnaryFuncInfo(frac, Other), ""));
|
||||||
@ -506,6 +507,18 @@ pub mod funcs {
|
|||||||
KalkNum::new_with_imaginary(x.value, "", KalkNum::default().value)
|
KalkNum::new_with_imaginary(x.value, "", KalkNum::default().value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inverson(x: KalkNum) -> KalkNum {
|
||||||
|
KalkNum::from(if let Some(boolean_value) = x.boolean_value {
|
||||||
|
if boolean_value {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn log(x: KalkNum) -> KalkNum {
|
pub fn log(x: KalkNum) -> KalkNum {
|
||||||
if x.has_imaginary() || x.value < 0f64 {
|
if x.has_imaginary() || x.value < 0f64 {
|
||||||
// ln(z) / ln(10)
|
// ln(z) / ln(10)
|
||||||
|
@ -76,7 +76,7 @@ impl Highlighter for LineHighlighter {
|
|||||||
|
|
||||||
let reg = Regex::new(
|
let reg = Regex::new(
|
||||||
r"(?x)
|
r"(?x)
|
||||||
(?P<identifier>[^!-@\s_|^⌊⌋⌈⌉]+(_\d+)?) |
|
(?P<identifier>[^!-@\s_|^⌊⌋⌈⌉\[\]≠≥≤]+(_\d+)?) |
|
||||||
(?P<op>[+\-/*%^!])",
|
(?P<op>[+\-/*%^!])",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -122,6 +122,9 @@ lazy_static! {
|
|||||||
m.insert("sqrt", "√");
|
m.insert("sqrt", "√");
|
||||||
m.insert("tau", "τ");
|
m.insert("tau", "τ");
|
||||||
m.insert("(", "()");
|
m.insert("(", "()");
|
||||||
|
m.insert("!=", "≠");
|
||||||
|
m.insert(">=", "≥");
|
||||||
|
m.insert("<=", "≤");
|
||||||
m
|
m
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user