2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								use   tracing ::{ debug ,   error } ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								use   once_cell ::sync ::Lazy ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug) ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								pub   struct  Calculation   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 pub   equation : String , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 pub   result : String , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								pub   fn  calculate ( query : & str )   -> Option < Calculation >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 debug! ( " Got query {} " ,   query ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 let   mut   parser   =   Parser ::new ( Lexer ::new ( query ) ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:58:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 let   tree   =   parser . parse ( ) ? ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 let   res   =   tree . eval ( ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:37:13 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 debug! ( " Calculation: {} " ,   query ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:58:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 debug! ( " Tree: {:?} " ,   tree ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 debug! ( " Result: {} " ,   res ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Some ( Calculation   { equation : query . to_string ( ) ,   result : res . to_string ( ) } ) 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								// TODO: put into own crate with dependency astro-float = "0.9.2" so I can use more than f64
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Token   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Op ( Op ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Atom ( Atom ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								/* 	Number(f64),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Func ( Func ) , * / 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Op   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:14:04 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Add , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Subtract , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Multiply , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Divide , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Exponent , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 LParen , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 RParen , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Func ( Func ) ,   // A function is an Op that takes whatever the next thing is and binds it, either the next number or whatever is in parens
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Op   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  bp_infix ( & self )   -> Option < ( f64 ,   f64 ) >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   self   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 // Op::LParen => Some(0.0),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 // Op::RParen => Some(0.0),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Add   = >   Some ( ( 1.0 ,   1.1 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Subtract   = >   Some ( ( 1.0 ,   1.1 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Multiply   = >   Some ( ( 2.0 ,   2.1 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Divide   = >   Some ( ( 2.0 ,   2.1 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Exponent   = >   Some ( ( 3.1 ,   3.0 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 _   = >   None , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 // Op::Func(_) => 0.0, // TODO: decide if this is a good LBP
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  bp_prefix ( & self )   -> Option < f64 >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   self   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Func ( _ )   = >   Some ( 6.0 ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Subtract   = >   Some ( 5.0 ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Op ::Add   = >   Some ( 5.0 ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 _   = >   None , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:37:13 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  apply_to ( & self ,   args : & Vec < Expr > )   -> f64  { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   args . len ( )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 1   = >   match   self   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Subtract   = >   Some ( 0.0   -   args [ 0 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Add   = >   Some ( args [ 0 ] . eval ( ) . abs ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Func ( f )   = >   match   f   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Sine   = >   Some ( args [ 0 ] . eval ( ) . sin ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Cosine   = >   Some ( args [ 0 ] . eval ( ) . cos ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Tangent   = >   Some ( args [ 0 ] . eval ( ) . tan ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::ArcSine   = >   Some ( args [ 0 ] . eval ( ) . asin ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::ArcCosine   = >   Some ( args [ 0 ] . eval ( ) . acos ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::ArcTangent   = >   Some ( args [ 0 ] . eval ( ) . atan ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Log2   = >   Some ( args [ 0 ] . eval ( ) . log2 ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Log10   = >   Some ( args [ 0 ] . eval ( ) . log10 ( ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::LogN   = >   Some ( args [ 0 ] . eval ( ) . ln ( ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Square   = >   Some ( args [ 0 ] . eval ( ) . powf ( 2.0 ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::SquareRoot   = >   Some ( args [ 0 ] . eval ( ) . sqrt ( ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Abs   = >   Some ( args [ 0 ] . eval ( ) . abs ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Func ::Log   = >   None , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 // _ => todo!("{:?}", self)
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 _   = >   None , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 2   = >   match   self   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::LParen   = >   Some ( args [ 0 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::RParen   = >   Some ( args [ 0 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Add   = >   Some ( args [ 0 ] . eval ( )   +   args [ 1 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Subtract   = >   Some ( args [ 0 ] . eval ( )   -   args [ 1 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Multiply   = >   Some ( args [ 0 ] . eval ( )   *   args [ 1 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Divide   = >   Some ( args [ 0 ] . eval ( )   /   args [ 1 ] . eval ( ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Exponent   = >   Some ( args [ 0 ] . eval ( ) . powf ( args [ 1 ] . eval ( ) ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Op ::Func ( Func ::Log )   = >   Some ( args [ 0 ] . eval ( ) . log ( args [ 1 ] . eval ( ) ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 _   = >   None , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 _   = >   None , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } . unwrap_or_else ( | |   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 error! ( " ERROR when evaluating maths expression, got invalid number of args ({}) for {:?} " ,   args . len ( ) ,   self ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 // None
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 f64 ::NAN 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } ) 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:37:13 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Atom   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Number ( f64 ) ,   // TODO: use the high precision floats library instead
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Const ( Const ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:39:48 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Atom   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  get_val ( & self )   -> f64  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   self   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Atom ::Number ( val )   = >   * val , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Atom ::Const ( c )   = >   match   c   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Const ::Pi   = >   3.141592653589793238462643383279 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Const ::E   = >   2.718281828459045235360287471352 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Func   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Sine , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Cosine , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Tangent , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 // sin-1, cos-1, tan-1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 ArcSine , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 ArcCosine , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 ArcTangent , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Log2 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Log10 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 LogN , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Log , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Square , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 SquareRoot , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Abs , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Func   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  names ( )   -> & 'static  [ ( Func ,   & 'static   [ & 'static   str ] ) ]   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 & [ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Sine ,   & [ " sin " ,   " sine " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Cosine ,   & [ " cos " ,   " cosine " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Tangent ,   & [ " tan " ,   " tangent " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::ArcSine ,   & [ " asin " ,   " asine " ,   " arcsin " ,   " arcsine " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::ArcCosine ,   & [ " acos " ,   " acosine " ,   " arccos " ,   " arccosine " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::ArcTangent ,   & [ " atan " ,   " atangent " ,   " arctan " ,   " arctangent " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Log2 ,   & [ " log2 " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Log10 ,   & [ " log10 " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::LogN ,   & [ " ln " ,   " logn " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Log ,   & [ " log " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Square ,   & [ " square " ,   " squared " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::SquareRoot ,   & [ " sqrt " ,   " squareroot " ,   " √ " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 ( Func ::Abs ,   & [ " abs " ,   " absolute " ] ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Const   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Pi , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 E , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug, Copy, Clone, PartialEq) ] 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  ParseErr   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Eof , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Invalid , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								// this can probably be swapped out with a lexer generator like Logos if needed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								struct  Lexer < ' a >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 data : & ' a  str , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 data_ptr : & ' a  str , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 // idx: usize,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 next_by : usize , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 next_tok : Result < Token ,   ParseErr > , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								// TODO: refactor with iterator that returns Option(Token) where one token option is Eof (or a enum of Token(Token) and Eof, or just Option(Option(Token)))
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Lexer < '_ >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  new ( data : & str )   -> Lexer < '_ >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 let   mut   n : Lexer   =   Lexer   { data ,   data_ptr : data ,   next_by : 0 ,   next_tok : Err ( ParseErr ::Eof ) } ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 n . next ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 debug! ( " New finished! " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 n 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  _next ( & mut   self )   -> Result < Token ,   ParseErr >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 self . data_ptr   =   & self . data_ptr [ self . next_by .. ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   self . data_ptr . chars ( ) . nth ( 0 )   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Some ( val )   = >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 debug! ( " lexing char '{}' at idx {} " ,   val ,   self . data . chars ( ) . count ( )   -   self . data_ptr . chars ( ) . count ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 self . next_by   =   1 ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 match   val   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:14:04 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 '+'   = >   Ok ( Token ::Op ( Op ::Add ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 '-'   = >   Ok ( Token ::Op ( Op ::Subtract ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
										 
									
								 
							
							
													 '×  '   |   '*'   = >   Ok ( Token ::Op ( Op ::Multiply ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 '÷'   |   '/'   = >   Ok ( Token ::Op ( Op ::Divide ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 '^'   = >   Ok ( Token ::Op ( Op ::Exponent ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 '('   = >   Ok ( Token ::Op ( Op ::LParen ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 ')'   = >   Ok ( Token ::Op ( Op ::RParen ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 _   if   val . is_whitespace ( )   = >   self . _next ( ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 _   if   val . is_digit ( 10 )   = >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 let   mut   len : usize  =   0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 self . data_ptr . chars ( ) . take_while ( | c |   c . is_digit ( 10 )   | |   * c   = =   '.' ) . for_each ( | _ |   len   + =   1 ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 self . next_by   =   len ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 match   self . data_ptr [ .. len ] . parse ( )   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
															 Ok ( val )   = >   Ok ( Token ::Atom ( Atom ::Number ( val ) ) ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
															 Err ( e )   = >   Err ( ParseErr ::Invalid ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 } , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 _   = >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 let   len   =   self . data_ptr . chars ( ) . count ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 for   ( f ,   names )   in   Func ::names ( )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
															 for   name   in   * names   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
																 if   self . data_ptr . starts_with ( name )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
																	 self . next_by   =   if   self . data_ptr . len ( )   >   name . len ( )   {   name . chars ( ) . count ( )   +   1 }   else   {   name . chars ( ) . count ( )   } ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
																	 return   Ok ( Token ::Op ( Op ::Func ( * f ) ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
																 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
															 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 debug! ( " got invalid char '{}' " ,   val ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 Err ( ParseErr ::Invalid ) 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 22:26:06 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 None   = >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 self . next_by   =   0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Err ( ParseErr ::Eof ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  next ( & mut   self )   -> Result < Token ,   ParseErr >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 let   val   =   self . next_tok ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 self . next_tok   =   self . _next ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 val 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  peek ( & mut   self )   -> Result < Token ,   ParseErr >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 self . next_tok 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 // TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  lex_all ( & mut   self )   -> Option < Vec < Token > >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 let   mut   tokens : Vec < Token >   =   vec! [ ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 loop   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 match   self . next ( )   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Err ( ParseErr ::Eof )   = >   return   Some ( tokens ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Err ( ParseErr ::Invalid )   = >   return   None , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Ok ( tok )   = >   tokens . push ( tok ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 // debug!("tokens: {:?}", tokens);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								fn  matches ( s : & str ,   check : & str )   -> usize  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 // debug!("s: \"{}\", check: \"{}\"c_len: {}, s_len: {}, s[c_len]: {:?}, s[c_len + 1]: {:?}", s, check, check.chars().count(), s.chars().count(), s.chars().nth(check.chars().count()), s.chars().nth(check.chars().count() + 1));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 match   ( s . chars ( ) . count ( ) ,   check . chars ( ) . count ( ) )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 ( s_len ,   c_len )   if   s_len   <   c_len   = >   0 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 ( s_len ,   c_len )   if   s_len   = =   c_len   & &   s   = =   check   = >   c_len   -   1 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 ( s_len ,   c_len )   if   s_len   >   c_len   & &   s . starts_with ( check )   & &   s . chars ( ) . nth ( c_len ) . unwrap ( ) . is_whitespace ( )   = >   c_len , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 ( _ ,   _ )   = >   0 , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								struct  Parser < ' a >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 lex : Lexer < ' a > , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Parser < '_ >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  new ( lex : Lexer )   -> Parser   {   Parser   { lex }   } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  parse ( & mut   self )   -> Option < Expr >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 self . parse_expr ( 0.0 ) . ok ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  parse_expr ( & mut   self ,   min_bp : f64 )   -> Result < Expr ,   ParseErr >   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 /* while let Ok(val) = self.lex.next() {debug!("token: {:?}", val)}
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:11:11 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 match   self . lex . next ( ) . err ( )   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 _   = >   return   Err ( ParseErr ::Invalid ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } * / 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 let   mut   lhs : Expr   =   match   self . lex . next ( )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Ok ( val )   = >   match   val   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Token ::Atom ( val )   = >   Ok ( Expr ::Atom ( val ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Token ::Op ( op )   = >   match   op   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Op ::LParen   = >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 let   val   =   self . parse_expr ( 0.0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 assert_eq! ( self . lex . next ( ) ,   Ok ( Token ::Op ( Op ::RParen ) ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 val 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 } , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 // Op::Func(f) => Ok(Expr::Node(Op::Func(f), vec![self.parse_expr(op.get_lbp())?])),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 _   = >   match   op . bp_prefix ( )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 Some ( bp )   = >   Ok ( Expr ::Node ( op ,   vec! [ self . parse_expr ( bp ) ? ] ) ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 None   = >   { debug! ( " Got unexpected {:?} as prefix " ,   op ) ;   Err ( ParseErr ::Invalid ) } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 } , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Err ( err )   = >   Err ( err ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } . map_err ( | err |   {   debug! ( " Unexpected error at start of expr: {:?} " ,   err ) ;   err   } ) ? ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 debug! ( " lhs of expression is {:?}, min_bp is {} " ,   lhs ,   min_bp ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 loop   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 debug! ( " loop start " ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 let   op : Op   =   match   self . lex . peek ( )   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Err ( ParseErr ::Eof )   = >   break , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Err ( e )   = >   {   debug! ( " In expr got err {:?} " ,   e ) ;   Err ( e )   } , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 Ok ( tok )   = >   match   tok   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
													 Token ::Op ( op )   = >   match   op   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 Op ::RParen   = >   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
															 debug! ( " got RParen " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
															 break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
														 } , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:14:04 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
														 _   = >   Ok ( op ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
													 v   = >   {   debug! ( " Got unexpected token {:?} " ,   v ) ;   Err ( ParseErr ::Invalid )   } , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
												 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 19:35:18 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } . map_err ( | err |   {   debug! ( " Unexpected error inside expr at {:?} " ,   err ) ;   err   } ) ? ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 debug! ( " op is {:?} " ,   op ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 21:50:22 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
											 if   let   Some ( ( lbp ,   rbp ) )   =   op . bp_infix ( )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 if   ( lbp   <   min_bp )   {   break ;   } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 self . lex . next ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 let   rhs : Expr   =   self . parse_expr ( rbp ) ? ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 lhs   =   Expr ::Node ( op ,   vec! [ lhs ,   rhs ] ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 }   else   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 debug! ( " Got unexpected non-infix operator in expression: {:?} " ,   op ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
												 return   Err ( ParseErr ::Invalid ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 23:32:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 debug! ( " Returning expr {:?} " ,   lhs ) ; 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
										 Ok ( lhs ) 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								#[ derive(Debug) ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								enum  Expr   { 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 16:45:57 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Atom ( Atom ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-04 08:54:21 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
									 Node ( Op ,   Vec < Expr > ) , 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-22 12:09:21 +12:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								} 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-05 20:37:13 +12:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								impl   Expr   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 fn  eval ( & self )   -> f64  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 let   res   =   match   ( self )   { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Expr ::Atom ( at )   = >   at . get_val ( ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
											 Expr ::Node ( op ,   exprs )   = >   op . apply_to ( exprs ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 } ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 // debug!("{:?} evaluated to {}", self, res);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
										 res 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
									 } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
								
									
								 
							
							
								}