1
0
mirror of https://github.com/osmarks/osmarkscalculator.git synced 2025-08-07 14:23:48 +00:00

Allow quoting

This commit is contained in:
osmarks 2024-08-07 19:49:34 +01:00
parent 66a65c6715
commit 97e562e4b2
4 changed files with 48 additions and 18 deletions

View File

@ -17,7 +17,7 @@ pub struct Rule {
pub result: RuleResult, pub result: RuleResult,
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Operation { pub struct Operation {
pub commutative: bool, pub commutative: bool,
pub associative: bool, pub associative: bool,

View File

@ -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. // Also do sorting after flattening, to avoid any weirdness with ordering.
canonical_sort(v, env)?; canonical_sort(v, env)?;
return Ok(()) return Ok(())
@ -420,7 +425,6 @@ x^n/x = x^(n-1)
PushRuleset[factor_postpostprocess] PushRuleset[factor_postpostprocess]
"; ";
pub struct ImperativeCtx { pub struct ImperativeCtx {
bindings: Bindings, bindings: Bindings,
current_ruleset_stage: InlinableString, current_ruleset_stage: InlinableString,

View File

@ -10,7 +10,15 @@ pub enum Token { Number(InlinableString), OpenBracket, CloseBracket, Op(char), E
enum LexState { enum LexState {
Number(InlinableString), Number(InlinableString),
Identifier(InlinableString), Identifier(InlinableString),
None None,
Quote
}
pub fn is_special_character(c: char) -> bool {
match c {
'#' | '+' | '(' | ')' | '-' | '/' | '*' | '^' | '=' | '[' | ']' | ',' => true,
_ => false
}
} }
// lexer // lexer
@ -30,8 +38,16 @@ pub fn lex(input: &str) -> Result<Vec<Token>> {
n.push(char); n.push(char);
LexState::Number(n) LexState::Number(n)
}, },
// Allow quoting special characters
('`', LexState::None) => {
LexState::Quote
},
// if special character seen, commit existing state and push operator/bracket/comma token // if special character seen, commit existing state and push operator/bracket/comma token
('#' | '+' | '(' | ')' | '-' | '/' | '*' | '^' | '=' | '[' | ']' | ',', state) => { (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 { match state {
LexState::Number(s) => toks.push(Token::Number(s)), LexState::Number(s) => toks.push(Token::Number(s)),
LexState::Identifier(s) => toks.push(Token::Identifier(s)), LexState::Identifier(s) => toks.push(Token::Identifier(s)),
@ -44,6 +60,7 @@ pub fn lex(input: &str) -> Result<Vec<Token>> {
a => Token::Op(a) a => Token::Op(a)
}); });
LexState::None LexState::None
}
}, },
// semicolon or newline is break // semicolon or newline is break
(';' | '\n', state) => { (';' | '\n', state) => {

View File

@ -5,7 +5,7 @@ use std::fmt::{self, Write};
use itertools::Itertools; use itertools::Itertools;
use anyhow::{Result, anyhow}; use anyhow::{Result, anyhow};
use crate::parse::{Ast, precedence}; use crate::parse::{Ast, precedence, is_special_character};
use crate::env::{Env, Bindings}; use crate::env::{Env, Bindings};
use crate::util::char_to_string; use crate::util::char_to_string;
use crate::interval_arithmetic::Interval; use crate::interval_arithmetic::Interval;
@ -179,7 +179,16 @@ impl Value {
Value::ExactNum(x) => if *x >= 0 { Value::ExactNum(x) => if *x >= 0 {
write!(f, "{}", x) write!(f, "{}", x)
} else { write!(f, "Negate[{}]", -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) => { Value::Call(head, args) => {
match env.ops.get(head) { match env.ops.get(head) {
Some(_) => { Some(_) => {