From 97e562e4b2e6f03f776950ee7b17a5c6c7d42be0 Mon Sep 17 00:00:00 2001 From: osmarks Date: Wed, 7 Aug 2024 19:49:34 +0100 Subject: [PATCH] Allow quoting --- src/env.rs | 2 +- src/lib.rs | 6 +++++- src/parse.rs | 45 +++++++++++++++++++++++++++++++-------------- src/value.rs | 13 +++++++++++-- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/env.rs b/src/env.rs index c44dbc7..823f053 100644 --- a/src/env.rs +++ b/src/env.rs @@ -17,7 +17,7 @@ pub struct Rule { pub result: RuleResult, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Operation { pub commutative: bool, pub associative: bool, diff --git a/src/lib.rs b/src/lib.rs index 3a901a1..0afa99a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -230,6 +230,11 @@ fn flatten_tree(v: &mut Value, env: &Env) -> Result<()> { } } } + /* + for child in args.iter_mut() { + flatten_tree(child, env)?; + } + */ // Also do sorting after flattening, to avoid any weirdness with ordering. canonical_sort(v, env)?; return Ok(()) @@ -420,7 +425,6 @@ x^n/x = x^(n-1) PushRuleset[factor_postpostprocess] "; - pub struct ImperativeCtx { bindings: Bindings, current_ruleset_stage: InlinableString, diff --git a/src/parse.rs b/src/parse.rs index 66e2484..c284b49 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -10,7 +10,15 @@ pub enum Token { Number(InlinableString), OpenBracket, CloseBracket, Op(char), E enum LexState { Number(InlinableString), Identifier(InlinableString), - None + None, + Quote +} + +pub fn is_special_character(c: char) -> bool { + match c { + '#' | '+' | '(' | ')' | '-' | '/' | '*' | '^' | '=' | '[' | ']' | ',' => true, + _ => false + } } // lexer @@ -30,20 +38,29 @@ pub fn lex(input: &str) -> Result> { n.push(char); LexState::Number(n) }, + // Allow quoting special characters + ('`', LexState::None) => { + LexState::Quote + }, // if special character seen, commit existing state and push operator/bracket/comma token - ('#' | '+' | '(' | ')' | '-' | '/' | '*' | '^' | '=' | '[' | ']' | ',', state) => { - match state { - LexState::Number(s) => toks.push(Token::Number(s)), - LexState::Identifier(s) => toks.push(Token::Identifier(s)), - _ => () - }; - toks.push(match char { - '(' => Token::OpenBracket, ')' => Token::CloseBracket, - '[' => Token::OpenSqBracket, ']' => Token::CloseSqBracket, - ',' => Token::Comma, - a => Token::Op(a) - }); - LexState::None + (c, state) if is_special_character(c) => { + if let LexState::Quote = state { + toks.push(Token::Identifier(char_to_string(char))); + LexState::None + } else { + match state { + LexState::Number(s) => toks.push(Token::Number(s)), + LexState::Identifier(s) => toks.push(Token::Identifier(s)), + _ => () + }; + toks.push(match char { + '(' => Token::OpenBracket, ')' => Token::CloseBracket, + '[' => Token::OpenSqBracket, ']' => Token::CloseSqBracket, + ',' => Token::Comma, + a => Token::Op(a) + }); + LexState::None + } }, // semicolon or newline is break (';' | '\n', state) => { diff --git a/src/value.rs b/src/value.rs index ebc5336..845b0ff 100644 --- a/src/value.rs +++ b/src/value.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Write}; use itertools::Itertools; use anyhow::{Result, anyhow}; -use crate::parse::{Ast, precedence}; +use crate::parse::{Ast, precedence, is_special_character}; use crate::env::{Env, Bindings}; use crate::util::char_to_string; use crate::interval_arithmetic::Interval; @@ -179,7 +179,16 @@ impl Value { Value::ExactNum(x) => if *x >= 0 { write!(f, "{}", x) } else { write!(f, "Negate[{}]", -x) }, - Value::Identifier(i) => write!(f, "{}", i), + Value::Identifier(i) => { + for c in i.chars() { + if is_special_character(c) { + write!(f, "`{}", c)?; + } else { + write!(f, "{}", c)?; + } + } + Ok(()) + }, Value::Call(head, args) => { match env.ops.get(head) { Some(_) => {