From 1e3405d51daa88f9d3e5c2ac362b13056f0f9cd8 Mon Sep 17 00:00:00 2001 From: Lloyd Date: Mon, 1 Sep 2025 00:40:14 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=99=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cell.rs | 18 +++++++++++++++--- src/evaluator.rs | 30 ++++++++++++++++-------------- src/parser.rs | 27 ++++++++++++++++++--------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/cell.rs b/src/cell.rs index 5a196dd..d95b830 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -4,13 +4,13 @@ use crate::evaluator::*; #[derive(Clone)] pub struct Cell { - eval: Option, + eval: Eval, raw: String, deps: HashSet, } impl Cell { - pub fn new(eval: Option, raw: String) -> Self { + pub fn new(eval: Eval, raw: String) -> Self { Self { eval, raw, @@ -22,9 +22,21 @@ impl Cell { self.raw.clone() } - pub fn eval(&self) -> Option { + pub fn eval(&self) -> Eval { self.eval.clone() } + + pub fn add_dep(&mut self, dep: CellRef) { + self.deps.insert(dep); + } + + pub fn clear_deps(&mut self) { + self.deps.clear(); + } + + pub fn set_eval(&mut self, eval: Eval) { + self.eval = eval; + } } #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] diff --git a/src/evaluator.rs b/src/evaluator.rs index 4b9958e..6bc64cf 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -7,14 +7,12 @@ use std::fmt; #[derive(Debug, PartialEq, Clone)] pub enum Eval { Literal(Literal), - Expr(Expr), } impl fmt::Display for Eval { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Eval::Literal(lit) => write!(f, "{lit:?}"), - Eval::Expr(expr) => write!(f, "({expr})"), } } } @@ -35,20 +33,26 @@ impl Evaluator { return Ok(()); } - let mut eval: Option = None; + let eval: Eval; + if let Some(c) = raw_val.chars().nth(0) && c == '=' { - if let Ok(e) = self.evaluate(raw_val[1..].to_owned()) { - eval = Some(e); - }; + eval = self.evaluate(raw_val[1..].to_owned())?; + } else { + match self.evaluate(raw_val.to_owned()) { + Ok(e) => { + eval = e; + } + Err(_) => eval = Eval::Literal(Literal::String(raw_val.to_owned())), + } } self.cells.insert(cell_ref, Cell::new(eval, raw_val)); Ok(()) } - pub fn get_cell(&mut self, cell_ref: CellRef) -> Result<(String, Option), String> { + pub fn get_cell(&mut self, cell_ref: CellRef) -> Result<(String, Eval), String> { if !self.cells.contains_key(&cell_ref) { return Err(format!("Cell at {:?} not found.", cell_ref)); } @@ -58,14 +62,16 @@ impl Evaluator { Ok((cell.raw(), cell.eval())) } - pub fn evaluate(&self, str: String) -> Result { - let mut expr = parse(&str)?; + pub fn evaluate(&mut self, str: String) -> Result { + let (mut expr, mut deps) = parse(&str)?; + self.evaluate_expr(&mut expr) } - fn evaluate_expr(&self, expr: &mut Expr) -> Result { + fn evaluate_expr(&mut self, expr: &mut Expr) -> Result { let res = match expr { Expr::Literal(lit) => Eval::Literal(lit.clone()), + Expr::CellRef(re) => self.get_cell(re.to_owned())?.1, Expr::Infix { op, lhs, rhs } => { let lval = self.evaluate_expr(lhs)?; let rval = self.evaluate_expr(rhs)?; @@ -101,7 +107,6 @@ fn eval_add(lval: &Eval, rval: &Eval) -> Result { Err("Evaluation error: expected string or numeric types for ADD function.".to_string()) } - _ => return Err("Evalutation error: expected literals for ADD function.".to_string()), } } @@ -114,7 +119,6 @@ fn eval_sub(lval: &Eval, rval: &Eval) -> Result { Err("Evaluation error: expected string or numeric types for SUB function.".to_string()) } - _ => return Err("Evalutation error: expected literals for SUB function.".to_string()), } } fn eval_mul(lval: &Eval, rval: &Eval) -> Result { @@ -126,7 +130,6 @@ fn eval_mul(lval: &Eval, rval: &Eval) -> Result { Err("Evaluation error: expected string or numeric types for MUL function.".to_string()) } - _ => return Err("Evalutation error: expected literals for MUL function.".to_string()), } } fn eval_div(lval: &Eval, rval: &Eval) -> Result { @@ -138,7 +141,6 @@ fn eval_div(lval: &Eval, rval: &Eval) -> Result { Err("Evaluation error: expected string or numeric types for DIV function.".to_string()) } - _ => return Err("Evalutation error: expected literals for DIV function.".to_string()), } } diff --git a/src/parser.rs b/src/parser.rs index c546baf..e528f68 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,5 +1,5 @@ use crate::{cell::CellRef, tokenizer::*}; -use std::fmt; +use std::{collections::HashSet, fmt}; #[derive(Debug, PartialEq, Clone)] pub enum PrefixOp { @@ -154,19 +154,24 @@ impl Expr { } } -pub fn parse(input: &str) -> Result { +pub fn parse(input: &str) -> Result<(Expr, HashSet), String> { let mut tokenizer = Tokenizer::new(input)?; // println!("{:?}", tokenizer.tokens); - _parse(&mut tokenizer, 0) + let mut deps = HashSet::new(); + Ok((_parse(&mut tokenizer, 0, &mut deps)?, deps)) } -pub fn _parse(input: &mut Tokenizer, min_prec: u8) -> Result { +pub fn _parse( + input: &mut Tokenizer, + min_prec: u8, + deps: &mut HashSet, +) -> Result { let mut lhs = match input.next() { Token::Literal(it) => Expr::Literal(it), Token::Identifier(id) if id == "true" => Expr::Literal(Literal::Boolean(true)), Token::Identifier(id) if id == "false" => Expr::Literal(Literal::Boolean(false)), Token::Paren('(') => { - let lhs = _parse(input, 0)?; + let lhs = _parse(input, 0, deps)?; if input.next() != Token::Paren(')') { return Err(format!("Parse error: expected closing paren.")); } @@ -180,7 +185,7 @@ pub fn _parse(input: &mut Tokenizer, min_prec: u8) -> Result { it => return Err(format!("Parse error: unknown prefix operator {:?}.", it)), }; - let rhs = _parse(input, prefix_op.prec().1)?; + let rhs = _parse(input, prefix_op.prec().1, deps)?; Expr::Prefix { op: prefix_op, @@ -209,7 +214,7 @@ pub fn _parse(input: &mut Tokenizer, min_prec: u8) -> Result { input.next(); // Skip comma } - let arg = _parse(input, 0)?; + let arg = _parse(input, 0, deps)?; args.push(arg); } @@ -218,7 +223,11 @@ pub fn _parse(input: &mut Tokenizer, min_prec: u8) -> Result { args: args, } } - _ => Expr::CellRef(CellRef::new(id)?), + _ => { + let cell_ref = CellRef::new(id)?; + deps.insert(cell_ref); + Expr::CellRef(cell_ref) + } }, it => return Err(format!("Parse error: did not expect token {:?}.", it)), @@ -246,7 +255,7 @@ pub fn _parse(input: &mut Tokenizer, min_prec: u8) -> Result { } input.next(); - let rhs = _parse(input, r_prec)?; + let rhs = _parse(input, r_prec, deps)?; lhs = Expr::Infix { op: infix_op, lhs: Box::new(lhs),