From e700445cdeb67526246dd148e4bf429818391c93 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Fri, 14 Jan 2022 17:46:07 +0100 Subject: [PATCH] Added logical and/or operators --- cli/src/repl.rs | 4 ++- kalk/src/interpreter.rs | 2 ++ kalk/src/kalk_value/mod.rs | 18 +++++++++++ kalk/src/lexer.rs | 10 +++++- kalk/src/parser.rs | 57 +++++++++++++++-------------------- web/src/KalkCalculator.svelte | 8 +++-- 6 files changed, 62 insertions(+), 37 deletions(-) diff --git a/cli/src/repl.rs b/cli/src/repl.rs index b81e2bf..3701061 100644 --- a/cli/src/repl.rs +++ b/cli/src/repl.rs @@ -106,7 +106,7 @@ impl Highlighter for LineHighlighter { let reg = Regex::new( r"(?x) - (?P([+\-/*%^!×÷⋅]|if|otherwise|load|exit|clear|help)) | + (?P([+\-/*%^!×÷⋅∧∨]|if|otherwise|\sand|\sor|load|exit|clear|help)) | (?P0[box][a-zA-Z0-9]+) | (?P[^!-@\s_|^⌊⌋⌈⌉\[\]\{\}⟦⟧≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)", ) @@ -158,6 +158,8 @@ lazy_static! { m.insert("!=", "≠"); m.insert(">=", "≥"); m.insert("<=", "≤"); + m.insert(" and", " ∧"); + m.insert(" or", " ∨"); m.insert("*", "×"); m.insert("/", "÷"); m.insert("asin", "sin⁻¹()"); diff --git a/kalk/src/interpreter.rs b/kalk/src/interpreter.rs index e6a6875..fdd1171 100644 --- a/kalk/src/interpreter.rs +++ b/kalk/src/interpreter.rs @@ -169,6 +169,8 @@ fn eval_binary_expr( TokenKind::LessThan => left.less_than(context, right), TokenKind::GreaterOrEquals => left.greater_or_equals(context, right), TokenKind::LessOrEquals => left.less_or_equals(context, right), + TokenKind::And => left.and(&right), + TokenKind::Or => left.or(&right), _ => KalkValue::from(1), }; diff --git a/kalk/src/kalk_value/mod.rs b/kalk/src/kalk_value/mod.rs index e3d8937..5f9e4c9 100644 --- a/kalk/src/kalk_value/mod.rs +++ b/kalk/src/kalk_value/mod.rs @@ -676,6 +676,24 @@ impl KalkValue { } } + pub(crate) fn and(self, rhs: &KalkValue) -> KalkValue { + match (self, rhs) { + (KalkValue::Boolean(boolean), KalkValue::Boolean(boolean_rhs)) => { + KalkValue::Boolean(boolean && *boolean_rhs) + } + _ => KalkValue::nan(), + } + } + + pub(crate) fn or(self, rhs: &KalkValue) -> KalkValue { + match (self, rhs) { + (KalkValue::Boolean(boolean), KalkValue::Boolean(boolean_rhs)) => { + KalkValue::Boolean(boolean || *boolean_rhs) + } + _ => KalkValue::nan(), + } + } + pub(crate) fn add_without_unit(self, rhs: &KalkValue) -> KalkValue { match (self.clone(), rhs) { ( diff --git a/kalk/src/lexer.rs b/kalk/src/lexer.rs index 72e1478..716cd24 100644 --- a/kalk/src/lexer.rs +++ b/kalk/src/lexer.rs @@ -23,6 +23,8 @@ pub enum TokenKind { NotEquals, GreaterOrEquals, LessOrEquals, + And, + Or, UnitKeyword, ToKeyword, @@ -144,6 +146,8 @@ impl<'a> Lexer<'a> { '=' => build(TokenKind::Equals, "", span), '>' => build(TokenKind::GreaterThan, "", span), '<' => build(TokenKind::LessThan, "", span), + '∧' => build(TokenKind::And, "", span), + '∨' => build(TokenKind::Or, "", span), ',' => build(TokenKind::Comma, "", span), ';' => build(TokenKind::Semicolon, "", span), '\n' => build(TokenKind::Newline, "", span), @@ -316,6 +320,8 @@ impl<'a> Lexer<'a> { } let kind = match value.as_ref() { + "and" => TokenKind::And, + "or" => TokenKind::Or, "unit" => TokenKind::UnitKeyword, "to" => TokenKind::ToKeyword, "if" => TokenKind::IfKeyword, @@ -382,7 +388,9 @@ fn is_valid_identifier(c: Option<&char>) -> bool { match c { '+' | '-' | '/' | '*' | '%' | '^' | '!' | '(' | ')' | '=' | '.' | ',' | ';' | '|' | '⌊' | '⌋' | '⌈' | '⌉' | '[' | ']' | '{' | '}' | 'π' | '√' | 'τ' | 'ϕ' | 'Γ' | '<' - | '>' | '≠' | '≥' | '≤' | '×' | '÷' | '⋅' | '⟦' | '⟧' | '\n' => false, + | '>' | '≠' | '≥' | '≤' | '×' | '÷' | '⋅' | '⟦' | '⟧' | '∧' | '∨' | '\n' => { + false + } _ => !c.is_digit(10) || is_superscript(c) || is_subscript(c), } } else { diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 5c1fa94..a86d4b8 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -342,43 +342,36 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result { } fn parse_expr(context: &mut Context) -> Result { - Ok(parse_equality(context)?) + Ok(parse_or(context)?) +} + +fn parse_or(context: &mut Context) -> Result { + let left = parse_and(context)?; + + if match_token(context, TokenKind::Or) { + let op = advance(context).kind; + let right = Box::new(parse_or(context)?); + return Ok(Expr::Binary(Box::new(left), op, right)); + } + + Ok(left) +} + +fn parse_and(context: &mut Context) -> Result { + let left = parse_equality(context)?; + + if match_token(context, TokenKind::And) { + let op = advance(context).kind; + let right = Box::new(parse_and(context)?); + return Ok(Expr::Binary(Box::new(left), op, right)); + } + + Ok(left) } fn parse_equality(context: &mut Context) -> Result { let mut left = parse_to(context)?; - // Equation - /*if match_token(context, TokenKind::Equals) && context.contains_equation_equal_sign { - advance(context); - let right = parse_to(context)?; - let var_name = if let Some(var_name) = &context.equation_variable { - var_name - } else { - return Err(CalcError::UnableToSolveEquation); - }; - - let inverted = - if inverter::contains_var(&mut context.symbol_table.get_mut(), &left, var_name) { - left.invert_to_target(&mut context.symbol_table.get_mut(), right, var_name)? - } else { - right.invert_to_target(&mut context.symbol_table.get_mut(), left, var_name)? - }; - - // If the inverted expression still contains the variable, - // the equation solving failed. - if inverter::contains_var(&mut context.symbol_table.get_mut(), &inverted, var_name) { - return Err(CalcError::UnableToSolveEquation); - } - - context.symbol_table.get_mut().insert(Stmt::VarDecl( - Identifier::from_full_name(var_name), - Box::new(inverted.clone()), - )); - - return Ok(inverted); - }*/ - // Equality check while match_token(context, TokenKind::Equals) || match_token(context, TokenKind::NotEquals) diff --git a/web/src/KalkCalculator.svelte b/web/src/KalkCalculator.svelte index 77423d2..a4971f8 100644 --- a/web/src/KalkCalculator.svelte +++ b/web/src/KalkCalculator.svelte @@ -306,7 +306,7 @@ let result = input; let offset = 0; result = result.replace( - /(?\[\[)|(?0[box][a-zA-Z0-9]+)|(?(!=|[<>]=?))|(?[<>&]|(\n\s*\}?|\s+))|(?([+\-/*%^!≈×÷⋅]|if|otherwise)|(?[^!-@\s_|^⌊⌋⌈⌉≈\[\]\{\}⟦⟧≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)\(?)/g, + /(?\[\[)|(?0[box][a-zA-Z0-9]+)|(?(!=|[<>]=?))|(?[<>&]|(\n\s*\}?|\s+))|(?([+\-/*%^!≈×÷⋅∧∨]|if|otherwise|and|or)|(?[^!-@\s_|^⌊⌋⌈⌉≈\[\]\{\}⟦⟧≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)\(?)/g, ( substring, brackets, @@ -380,8 +380,10 @@ } if (op && highlightType != HighlightType.Output) { - if (substring == "*") return "⋅"; - if (substring == "/") return "÷"; + if (substring == "*") substring = "⋅"; + if (substring == "/") substring = "÷"; + if (substring == "and") substring = "∧"; + if (substring == "or") substring = "∨"; } if (identifier) {