exercises

Log | Files | Refs | README

builder.rs (5742B)


      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 }
    190 
    191 pub struct ExpressionParser;