From 2cf8f41124b8173753055f38f06a90a6e27e2ee5 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Wed, 5 Jan 2022 23:30:54 +0100 Subject: [PATCH] =?UTF-8?q?Indexing=20vectors=20by=20=E2=9F=A6=E2=9F=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cli/src/repl.rs | 5 +++-- kalk/src/lexer.rs | 14 +++++++++++++- kalk/src/parser.rs | 15 ++++++++++++++- web/src/KalkCalculator.svelte | 17 +++++++++++++---- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/cli/src/repl.rs b/cli/src/repl.rs index 522df5e..b81e2bf 100644 --- a/cli/src/repl.rs +++ b/cli/src/repl.rs @@ -108,7 +108,7 @@ impl Highlighter for LineHighlighter { r"(?x) (?P([+\-/*%^!×÷⋅]|if|otherwise|load|exit|clear|help)) | (?P0[box][a-zA-Z0-9]+) | - (?P[^!-@\s_|^⌊⌋⌈⌉\[\]\{\}≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)", + (?P[^!-@\s_|^⌊⌋⌈⌉\[\]\{\}⟦⟧≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)", ) .unwrap(); @@ -154,6 +154,7 @@ lazy_static! { m.insert("sqrt", "√"); m.insert("tau", "τ"); m.insert("(", "()"); + m.insert("[[", "⟦⟧"); m.insert("!=", "≠"); m.insert(">=", "≥"); m.insert("<=", "≤"); @@ -212,7 +213,7 @@ impl Completer for RLHelper { fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) { line.backspace(line.pos() - start); line.insert_str(line.pos(), elected); - line.move_forward(if elected.ends_with(")") { + line.move_forward(if elected.ends_with(")") || elected.ends_with("⟧") { elected.chars().count() - 1 } else { elected.chars().count() diff --git a/kalk/src/lexer.rs b/kalk/src/lexer.rs index 04c916f..72e1478 100644 --- a/kalk/src/lexer.rs +++ b/kalk/src/lexer.rs @@ -37,7 +37,9 @@ pub enum TokenKind { OpenParenthesis, ClosedParenthesis, OpenBracket, + OpenDoubleBracket, ClosedBracket, + ClosedDoubleBracket, OpenBrace, ClosedBrace, Comma, @@ -134,6 +136,8 @@ impl<'a> Lexer<'a> { ')' => build(TokenKind::ClosedParenthesis, "", span), '[' => build(TokenKind::OpenBracket, "", span), ']' => build(TokenKind::ClosedBracket, "", span), + '⟦' => build(TokenKind::OpenDoubleBracket, "", span), + '⟧' => build(TokenKind::ClosedDoubleBracket, "", span), '{' => build(TokenKind::OpenBrace, "", span), '}' => build(TokenKind::ClosedBrace, "", span), '!' => build(TokenKind::Exclamation, "", span), @@ -167,6 +171,14 @@ impl<'a> Lexer<'a> { self.advance(); return build(TokenKind::Power, "", span); } + (TokenKind::OpenBracket, Some('[')) => { + self.advance(); + return build(TokenKind::OpenDoubleBracket, "", span); + } + (TokenKind::ClosedBracket, Some(']')) => { + self.advance(); + return build(TokenKind::ClosedDoubleBracket, "", span); + } (TokenKind::Exclamation, Some('=')) => { self.advance(); return build(TokenKind::NotEquals, "", span); @@ -370,7 +382,7 @@ 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 c61313a..6c21cdd 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -549,7 +549,7 @@ fn parse_unary(context: &mut Context) -> Result { } fn parse_exponent(context: &mut Context) -> Result { - let left = parse_factorial(context)?; + let left = parse_indexer(context)?; if match_token(context, TokenKind::Power) { let op = advance(context).kind; @@ -560,6 +560,19 @@ fn parse_exponent(context: &mut Context) -> Result { Ok(left) } +fn parse_indexer(context: &mut Context) -> Result { + let left = parse_factorial(context)?; + + if match_token(context, TokenKind::OpenDoubleBracket) { + advance(context); + let right = Box::new(parse_expr(context)?); + consume(context, TokenKind::ClosedDoubleBracket)?; + return Ok(Expr::Indexer(Box::new(left), right)); + } + + Ok(left) +} + fn parse_factorial(context: &mut Context) -> Result { let expr = parse_primary(context)?; diff --git a/web/src/KalkCalculator.svelte b/web/src/KalkCalculator.svelte index 9ecff1a..70aa363 100644 --- a/web/src/KalkCalculator.svelte +++ b/web/src/KalkCalculator.svelte @@ -282,18 +282,27 @@ 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)|(?[^!-@\s_|^⌊⌋⌈⌉≈\[\]\{\}⟦⟧≠≥≤⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎]+(_\d+)?)\(?)/g, ( substring, + brackets, _radix, - _, - comparison, _2, - html, + comparison, _3, + html, + _4, op, identifier ) => { + if (brackets) { + if (substring == "[[") { + offset -= 1; + + return "⟦⟧"; + } + } + if (comparison) { if (substring == "<=") return "≤"; if (substring == ">=") return "≥";