builder.rs (5712B)
1 use crate::{TokenFactory, token::Token}; 2 3 /// This struct represents our final, immutable expression 4 #[derive(Clone)] 5 pub struct Expression<F: TokenFactory> { 6 tokens: Vec<Token<F::Number, F::Operator>>, 7 factory: F, 8 } 9 10 impl<F: TokenFactory> Expression<F> { 11 /// Defining builder on Expression rather than calling ExpressionBuilder::new 12 /// directly follows Rust convention: the type you're building provides the 13 /// entry point to its builder, this makes the API discoverable 14 pub fn builder(factory: F) -> ExpressionBuilder<F> { 15 ExpressionBuilder::new(factory) 16 } 17 18 pub fn evaluate(&self) -> Result<F::Number, String> { 19 todo!() 20 } 21 22 /// Prototype Pattern 23 pub fn quadratic_template(factory: F) -> Result<ExpressionBuilder<F>, String> { 24 Expression::builder(factory) 25 .number("1")? 26 .operator("*")? 27 .variable("x") 28 .operator("^")? 29 .number("2")? 30 .operator("+")? 31 .number("0")? 32 .operator("*")? 33 .variable("x") 34 .operator("+")? 35 .number("0") 36 } 37 38 /// Another Prototype Pattern 39 pub fn set_coefficient(&self, a: i64, b: f64) -> Result<(), String> { 40 todo!() 41 } 42 } 43 44 #[derive(Clone)] 45 pub struct SubExpression<F: TokenFactory> { 46 pub tokens: Vec<Token<F::Number, F::Operator>>, 47 factory: F, 48 } 49 50 impl<F: TokenFactory> SubExpression<F> { 51 pub fn new(tokens: Vec<Token<F::Number, F::Operator>>, factory: F) -> Self { 52 Self { tokens, factory } 53 } 54 55 // Insert this subexpression into a larger expression 56 pub fn insert_into(self, builder: ExpressionBuilder<F>) -> ExpressionBuilder<F> { 57 builder.extend(self.tokens) 58 } 59 } 60 61 /// This struct manages the construction process 62 pub struct ExpressionBuilder<F: TokenFactory> { 63 tokens: Vec<Token<F::Number, F::Operator>>, 64 factory: F, 65 paren_count: i32, 66 } 67 68 /// Implement the builder construction methods 69 /// Each method takes ownership of self and then returns it after modification 70 /// This enables method chaining while preventing accidental reuse of partially 71 /// built expressions 72 impl<F: TokenFactory> ExpressionBuilder<F> { 73 pub fn new(factory: F) -> Self { 74 Self { 75 tokens: Vec::new(), 76 factory, 77 paren_count: 0, 78 } 79 } 80 81 // This is to support inserting subexpression into a larger expression 82 pub fn extend(mut self, tokens: Vec<Token<F::Number, F::Operator>>) -> ExpressionBuilder<F> { 83 todo!() 84 } 85 86 // Add a number to the expression 87 pub fn number(mut self, value: &str) -> Result<Self, String> { 88 let num = self.factory.create_number(value)?; 89 self.tokens.push(Token::Number(num)); 90 Ok(self) 91 } 92 93 // Add an operator 94 pub fn operator(mut self, op: &str) -> Result<Self, String> { 95 let op = self.factory.create_operator(op)?; 96 self.tokens.push(Token::Operator(op)); 97 Ok(self) 98 } 99 100 // Add a variable 101 pub fn variable(mut self, name: &str) -> Self { 102 self.tokens.push(Token::Variable(name.to_string())); 103 self 104 } 105 106 // Open a parenthesis group 107 pub fn open_paren(mut self) -> Self { 108 self.tokens.push(Token::OpenParen); 109 self.paren_count += 1; 110 self 111 } 112 113 // Close a parenthesis group 114 // The guard error prevents invalid expression from being built 115 pub fn close_paren(mut self) -> Result<Self, String> { 116 if self.paren_count <= 0 { 117 return Err("Unmatched closing parenthesis".to_string()); 118 } 119 self.tokens.push(Token::CloseParen); 120 self.paren_count -= 1; 121 Ok(self) 122 } 123 124 /// Specialized Builder Pattern 125 /// Function-application Pattern 126 pub fn function(mut self, func: &str, arg: &str) -> Result<Self, String> { 127 let func_op = self.factory.create_operator(func)?; 128 let arg_num = self.factory.create_number(arg)?; 129 130 self.tokens.push(Token::Operator(func_op)); 131 self.tokens.push(Token::Number(arg_num)); 132 133 Ok(self) 134 } 135 136 /// Specialized Builder Pattern 137 /// Constructs a complete binary expression in one call 138 pub fn binary_op(mut self, left: &str, op: &str, right: &str) -> Result<Self, String> { 139 let left_num = self.factory.create_number(left)?; 140 let op_token = self.factory.create_operator(op)?; 141 let right_num = self.factory.create_number(right)?; 142 143 self.tokens.extend([ 144 Token::Number(left_num), 145 Token::Operator(op_token), 146 Token::Number(right_num), 147 ]); 148 149 Ok(self) 150 } 151 152 // Build the final expression 153 // This method consumes the build, by taking self by value, ensuring no 154 // further modifications can be made after building 155 pub fn build(self) -> Result<Expression<F>, String> { 156 if self.paren_count != 0 { 157 return Err("Unmatched parenthesis".to_string()); 158 } 159 160 if self.tokens.is_empty() { 161 return Err("Empty expression".to_string()); 162 } 163 164 // Validate expression structure 165 self.validate_expression()?; 166 167 Ok(Expression { 168 tokens: self.tokens, 169 factory: self.factory, 170 }) 171 } 172 173 fn validate_expression(&self) -> Result<(), String> { 174 use Token::*; 175 176 // No consecutive operators 177 for window in self.tokens.windows(2) { 178 match (&window[0], &window[1]) { 179 (Operator(_), Operator(_)) => { 180 return Err("Consecutive operators".to_string()); 181 } 182 _ => continue, 183 } 184 } 185 186 // More validation rules... 187 Ok(()) 188 } 189 }