1
0
mirror of https://github.com/osmarks/osmarkscalculator.git synced 2025-04-08 03:36:45 +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,
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Operation {
pub commutative: 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.
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,

View File

@ -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<Vec<Token>> {
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) => {

View File

@ -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(_) => {