1mod utils;
9
10use crate::utils::{IIter, Iter};
11use std::collections::HashMap;
12use std::f64;
13
14macro_rules! cast_opt_ok {
15 ($i:expr) => {
16 match $i {
17 Some(e) => e,
18 None => return Ok(None),
19 }
20 };
21}
22
23macro_rules! try_tokenize {
24 ($self:ident,$start:ident,$i:ident,$j:ident) => {{
25 let result = $i($self.source)?;
26 if result.is_some() {
27 let option = result.unwrap();
28 $self.shift(option.1);
29 return Ok(Some((Token::$j(option.0), $start, $self.index)));
30 }
31 }};
32}
33
34macro_rules! try_one_char {
35 ($self:ident,$start:ident,$ch:ident,$i:expr,$j:ident) => {{
36 if $ch == $i {
37 $self.shift(1);
38 return Ok(Some((Token::$j, $self.index - 1, $self.index)));
39 }
40 }};
41}
42
43type Function = fn(f64) -> f64;
44
45#[derive(Debug)]
46pub struct Program {
47 pub body: Expression,
48}
49
50#[derive(Debug)]
51pub enum Expression {
52 Primitive(Primitive),
53 ExpressionOperation((Box<Expression>, char, Box<Expression>)),
54}
55
56#[derive(Debug)]
57pub enum Primitive {
58 Function((Function, Box<Expression>)),
59 Identifier(String),
60 Number(f64),
61}
62
63impl Program {
64 fn run(&self, x: f64) -> f64 {
65 self.body.perform(x, 0.0)
66 }
67 fn runge_kutta(&self, x0: f64, y0: f64, step: f64) -> (f64, f64) {
68 let a1 = step * self.body.perform(x0, y0);
69 let a2 = step * self.body.perform(x0 + step / 2.0, y0 + a1 / 2.0);
70 let a3 = step * self.body.perform(x0 + step / 2.0, y0 + a2 / 2.0);
71 let a4 = step * self.body.perform(x0, y0 + a3);
72 (y0 + (a1 + 2.0 * a2 + 2.0 * a3 + a4) / 6.0, x0 + step)
73 }
74}
75
76impl Primitive {
77 fn typ(&self) -> &'static str {
78 use Primitive::*;
79 match self {
80 Function(_) => "Function",
81 Identifier(_) => "Identifier",
82 Number(_) => "Number",
83 }
84 }
85 fn perform(&self, x: f64, y: f64) -> f64 {
86 use Primitive::*;
87 match self {
88 Function(func) => {
89 (func.0)(func.1.perform(x, y))
90 }
91 Identifier(ident) => {
92 match ident.as_str() {
93 "x" => x,
94 "y" => y,
95 _ => 0.0
96 }
97 }
98 Number(num) => *num
99 }
100 }
101}
102
103impl Expression {
104 fn perform(&self, x: f64, y: f64) -> f64 {
105 use Expression::*;
106 match self {
107 Primitive(primitive) => {
108 primitive.perform(x, y)
109 }
110 ExpressionOperation(expr) => {
111 match expr.1 {
112 '+' => expr.0.perform(x, y) + expr.2.perform(x, y),
113 '-' => expr.0.perform(x, y) - expr.2.perform(x, y),
114 '*' => expr.0.perform(x, y) * expr.2.perform(x, y),
115 '/' => expr.0.perform(x, y) / expr.2.perform(x, y),
116 '^' => f64::powf(expr.0.perform(x, y), expr.2.perform(x, y)),
117 _ => 0.0
118 }
119 }
120 }
121 }
122}
123
124pub enum Token {
125 Identifier(String),
126 Number(f64),
127 Add,
128 Sub,
129 Mult,
130 Div,
131 Pow,
132 LParent,
133 RParent,
134 Comma,
135}
136
137impl Token {
138 fn typ(&self) -> &'static str {
139 use Token::*;
140 match self {
141 Identifier(_) => "Identifier",
142 Number(_) => "Number",
143 Add | Sub | Mult | Div | Pow => "Operator",
144 LParent => "LParent",
145 RParent => "RParent",
146 Comma => "Comma",
147 }
148 }
149 fn to_string(&self) -> String {
150 use Token::*;
151 match self {
152 Number(num) => num.to_string(),
153 Add => "+".to_string(),
154 Sub => "-".to_string(),
155 Mult => "*".to_string(),
156 Div => "/".to_string(),
157 Pow => "^".to_string(),
158 LParent => "(".to_string(),
159 RParent => ")".to_string(),
160 Comma => "Comma".to_string(),
161 Identifier(ident) => ident.to_string(),
162 }
163 }
164}
165
166struct Tokenizer<'a> {
167 index: usize,
168 source: &'a str,
169}
170
171fn takes(source: &str, f: fn(ch: char) -> bool) -> Result<(&str, usize), &str> {
172 let mut i: usize = 0;
173 for ch in source.chars() {
174 if f(ch) {
175 i += 1;
176 } else {
177 break;
178 }
179 }
180 if i == 0 {
181 Err("No Matches".into())
182 } else {
183 Ok((&source[..i], i))
184 }
185}
186
187fn identifier(source: &str) -> Result<Option<(String, usize)>, &str> {
188 let mut i: usize = 0;
189 let mut chars = source.chars();
190 let ch = cast_opt_ok!(chars.next());
191 if !(ch.is_alphabetic() || ch == '_') {
192 return Ok(None);
193 }
194 i += 1;
195 for ch in chars {
196 if ch.is_alphanumeric() || ch == '_' {
197 i += 1;
198 } else {
199 break;
200 }
201 }
202 if i > 0 {
203 Ok(Some((source[..i].to_string(), i)))
204 } else {
205 Ok(None)
206 }
207}
208
209fn number(source: &str) -> Result<Option<(f64, usize)>, &str> {
210 let mut i: usize = 0;
211 let result = integer(source)?;
212 if result.is_none() {
213 return Ok(None);
214 }
215 let int = result.unwrap();
216 i += int.1;
217 let num_str;
218 if i < source.len() {
219 let mut chars = source.get(i..).unwrap().chars();
220 let ch = chars.next().unwrap();
221 if ch == '.' {
222 i += 1;
223 for ch in chars {
224 if ch == '.' {
225 return Err("Unexpected number");
226 }
227 if ch.is_digit(10) {
228 i += 1;
229 } else {
230 break;
231 }
232 }
233 num_str = &source[..i];
234 } else {
235 num_str = int.0;
236 }
237 } else {
238 num_str = int.0;
239 }
240 return match num_str.replace("_", "").parse::<f64>() {
241 Ok(num) => Ok(Some((num, i))),
242 Err(_) => Err("Cannot to parse number"),
243 };
244}
245
246fn integer(source: &str) -> Result<Option<(&str, usize)>, &str> {
247 let mut i: usize = 0;
248 let mut chars = source.chars();
249 let ch = cast_opt_ok!(chars.next());
250 if ch == '0' {
251 return Ok(Some(("0", 1)));
252 }
253 if ch.is_digit(10) {
254 i += 1;
255 for ch in chars {
256 if ch.is_digit(10) || ch == '_' {
257 i += 1;
258 } else {
259 break;
260 }
261 }
262 return Ok(Some((&source[..i], i)));
263 }
264 return Ok(None);
265}
266
267impl<'a> Tokenizer<'a> {
268 fn new(src: &str) -> Tokenizer {
269 Tokenizer {
270 index: 0,
271 source: src,
272 }
273 }
274 fn next(&mut self) -> Result<Option<(Token, usize, usize)>, &str> {
275 if !self.source.is_empty() {
276 self.skip_whitespace();
277 if let Some(ch) = self.source.chars().next() {
278 let start = self.index;
279 try_tokenize!(self, start, number, Number);
280 try_tokenize!(self, start, identifier, Identifier);
281 try_one_char!(self, start, ch, '^', Pow);
282 try_one_char!(self, start, ch, '+', Add);
283 try_one_char!(self, start, ch, '-', Sub);
284 try_one_char!(self, start, ch, '*', Mult);
285 try_one_char!(self, start, ch, '/', Div);
286 try_one_char!(self, start, ch, '(', LParent);
287 try_one_char!(self, start, ch, ')', RParent);
288 try_one_char!(self, start, ch, ',', Comma);
289 }
290 Ok(None)
291 } else {
292 Ok(None)
293 }
294 }
295 fn skip_whitespace(&mut self) {
296 match takes(self.source, |a| a.is_whitespace()) {
297 Ok(e) => {
298 self.shift(e.1);
299 }
300 Err(_) => {}
301 };
302 }
303 fn shift(&mut self, length: usize) {
304 self.source = &self.source[length..];
305 self.index += length;
306 }
307}
308
309pub struct Moo<'a> {
310 functions: HashMap<&'a str, Function>,
311}
312
313impl<'a> Moo<'a> {
314 pub fn new(add_on: fn(functions: &mut HashMap<&str, Function>)) -> Moo<'a> {
315 let mut functions: HashMap<&str, Function> = HashMap::new();
316 functions.insert("sin", |v| {
317 f64::sin(v)
318 });
319 functions.insert("cos", |v| {
320 f64::cos(v)
321 });
322 functions.insert("abs", |v| {
323 f64::abs(v)
324 });
325 add_on(&mut functions);
326 Moo {
327 functions,
328 }
329 }
330 pub fn parse(&self, source: &str) -> Result<Option<Program>, &str> {
331 let mut tokenizer = Tokenizer::new(source);
332 let mut tokens: Vec<(Token, usize, usize)> = Vec::new();
333 loop {
334 let result = tokenizer.next();
335 if result.is_ok() {
336 match result.unwrap() {
337 Some(token) => {
338 tokens.push(token);
339 }
340 None => break,
341 }
342 } else {
343 break;
344 }
345 }
346 let token_iter = &mut Iter::new(&tokens);
347 Ok(self.ast_program(token_iter)?)
348 }
349 fn ast_program(&self, iter: &mut Iter<(Token, usize, usize)>) -> Result<Option<Program>, &str> {
350 let body = self.ast_additive_expression(iter)?;
351 if body.is_some() {
352 return Ok(Some(Program { body: body.unwrap() }));
353 }
354 return Ok(None);
355 }
356 fn ast_additive_expression(&self, iter: &mut Iter<(Token, usize, usize)>) -> Result<Option<Expression>, &str> {
357 let left = self.ast_multiplicative_expression(iter)?;
358 if left.is_none() {
359 return Ok(None);
360 }
361 if let Some(tnk) = iter.next() {
362 use crate::Token::*;
363 use crate::Expression::*;
364 match tnk.0 {
365 Add => {
366 let right = self.ast_additive_expression(iter)?;
367 if right.is_none() {
368 return Err("ERROR 8");
369 }
370 return Ok(Some(ExpressionOperation((Box::new(left.unwrap()), '+', Box::new(right.unwrap())))));
371 }
372 Sub => {
373 let right = self.ast_additive_expression(iter)?;
374 if right.is_none() {
375 return Err("ERROR 7");
376 }
377 return Ok(Some(ExpressionOperation((Box::new(left.unwrap()), '-', Box::new(right.unwrap())))));
378 }
379 _ => {
380 iter.prev();
381 }
382 };
383 }
384 Ok(left)
385 }
386 fn ast_multiplicative_expression(&self, iter: &mut Iter<(Token, usize, usize)>) -> Result<Option<Expression>, &str> {
387 let left = self.ast_exponential_expression(iter)?;
388 if left.is_none() {
389 return Ok(None);
390 }
391 if let Some(tnk) = iter.next() {
392 use crate::Token::*;
393 use crate::Expression::*;
394 match tnk.0 {
395 Mult => {
396 let right = self.ast_exponential_expression(iter)?;
397 if right.is_none() {
398 return Err("ERROR 6");
399 }
400 return Ok(Some(ExpressionOperation((Box::new(left.unwrap()), '*', Box::new(right.unwrap())))));
401 }
402 Div => {
403 let right = self.ast_exponential_expression(iter)?;
404 if right.is_none() {
405 return Err("ERROR 5");
406 }
407 return Ok(Some(ExpressionOperation((Box::new(left.unwrap()), '/', Box::new(right.unwrap())))));
408 }
409 _ => {
410 iter.prev();
411 }
412 };
413 }
414 Ok(left)
415 }
416
417 fn ast_exponential_expression(&self, iter: &mut Iter<(Token, usize, usize)>) -> Result<Option<Expression>, &str> {
418 use crate::Token::*;
419 use crate::Expression::*;
420 let left = self.ast_primitive(iter)?;
421 if left.is_none() {
422 return Ok(None);
423 }
424 if let Some(tnk) = iter.next() {
425 match tnk.0 {
426 Pow => {
427 let right = self.ast_primitive(iter)?;
428 if right.is_none() {
429 return Err("ERROR 4");
430 }
431 return Ok(Some(ExpressionOperation((Box::new(left.unwrap()), '^', Box::new(right.unwrap())))));
432 }
433 _ => {
434 iter.prev();
435 }
436 };
437 }
438 match left.unwrap() {
439 Primitive(left) => Ok(Some(Primitive(left))),
440 ExpressionOperation(left) => Ok(Some(ExpressionOperation(left)))
441 }
442 }
443
444 fn ast_primitive(&self, iter: &mut Iter<(Token, usize, usize)>) -> Result<Option<Expression>, &str> {
445 use crate::Token::*;
446 return if let Some(tnk) = iter.next() {
447 match &tnk.0 {
448 Identifier(ident) => {
449 if ident.as_str() == "x" {
450 return Ok(Some(Expression::Primitive(Primitive::Identifier(ident.clone()))));
451 }
452 return match self.functions.get(&ident.as_str()) {
453 None => Err("ERROR 3"),
454 Some(func) => {
455 return match iter.next() {
456 Some(token) => {
457 match token.0 {
458 LParent => {}
459 _ => {
460 return Err("ERROR FUNCTION MUST HAVE OPEN BRACKET");
461 }
462 }
463 let w_input = self.ast_additive_expression(iter)?;
464 match w_input {
465 None => Err("Function must have input"),
466 Some(input) => {
467 match iter.next() {
468 Some(token) => {
469 match token.0 {
470 RParent => {}
471 _ => return Err("Function expected ')'")
472 }
473 }
474 None => return Err("Function expected ')'")
475 }
476 Ok(Some(Expression::Primitive(Primitive::Function((func.clone(), Box::new(input))))))
477 }
478 }
479 }
480 None => Err("Function expected '('"),
481 };
482 }
483 };
484 }
485 Number(num) => {
486 return Ok(Some(Expression::Primitive(Primitive::Number(num.clone()))));
487 }
488 LParent => {
489 let expr = self.ast_additive_expression(iter)?;
490 return match expr {
491 Some(expr) => {
492 match iter.next() {
493 Some(token) => {
494 match token.0 {
495 RParent => {}
496 _ => return Err("Parenthesis expected ')'")
497 }
498 }
499 None => return Err("Parenthesis expected ')'")
500 }
501 Ok(Some(expr))
502 }
503 None => {
504 match iter.next() {
505 Some(token) => {
506 match token.0 {
507 RParent => Ok(None),
508 _ => return Err("Parenthesis expected ')'")
509 }
510 }
511 None => return Err("Parenthesis expected ')'")
512 }
513 }
514 };
515 }
516 _ => {
517 return Err("ERROR 1");
518 }
519 }
520 } else {
521 Ok(None)
522 };
523 }
524}
525
526#[cfg(test)]
527mod numeric_tests {
528 use super::*;
529
530 #[test]
531 fn number_integer() {
532 let mut tokenizer = Tokenizer::new(" 10");
533 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
534 }
535
536 #[test]
537 fn number_zero_integer() {
538 let mut tokenizer = Tokenizer::new(" 0");
539 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
540 }
541
542 #[test]
543 fn number_float() {
544 let mut tokenizer = Tokenizer::new(" 10.1");
545 let token = tokenizer.next().unwrap().unwrap().0;
546 println!("{}", token.to_string());
547 assert_eq!(token.typ(), "Number");
548 }
549
550 #[test]
551 fn number_zero_float() {
552 let mut tokenizer = Tokenizer::new(" 0.1");
553 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
554 }
555
556 #[test]
557 fn number_underscore() {
558 let mut tokenizer = Tokenizer::new(" 1_10");
559 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
560 }
561
562 #[test]
563 fn number_unexpected_err() {
564 let mut tokenizer = Tokenizer::new(" 10.1.1");
565 assert_eq!(tokenizer.next().err().unwrap(), "Unexpected number");
566 }
567}
568
569#[cfg(test)]
570mod identifier_tests {
571 use super::*;
572
573 #[test]
574 fn ident_x() {
575 let mut tokenizer = Tokenizer::new("x");
576 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Identifier");
577 }
578
579 #[test]
580 fn ident_cow() {
581 let mut tokenizer = Tokenizer::new("วัว");
582 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Identifier");
583 }
584
585 #[test]
586 fn ident_underscore() {
587 let mut tokenizer = Tokenizer::new("_cow");
588 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Identifier");
589 }
590
591 #[test]
592 fn ident_number() {
593 let mut tokenizer = Tokenizer::new("boon1_");
594 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Identifier");
595 }
596}
597
598#[cfg(test)]
599mod expr_tests {
600 use super::*;
601
602 #[test]
603 fn expr_1() {
604 let mut tokenizer = Tokenizer::new(" 10.6 + x");
605 let a = tokenizer.next().unwrap().unwrap().0;
606 let b = tokenizer.next().unwrap().unwrap().0;
607 let c = tokenizer.next().unwrap().unwrap().0;
608
609 println!("{}", a.to_string());
610 println!("{}", b.to_string());
611 println!("{}", c.to_string());
612
613 assert_eq!(a.typ(), "Number");
614 assert_eq!(b.typ(), "Operator");
615 assert_eq!(c.typ(), "Identifier");
616 }
617
618 #[test]
619 fn expr_2() {
620 let mut tokenizer = Tokenizer::new(" (10 / 5)");
621 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Parenthesis");
622 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
623 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Operator");
624 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Number");
625 assert_eq!(tokenizer.next().unwrap().unwrap().0.typ(), "Parenthesis");
626 }
627}
628
629#[cfg(test)]
630mod parse_tests {
631 use super::*;
632
633 #[test]
634 fn parse_1() {
635 use std::time::{Duration, SystemTime};
636 let moo = Moo::new(|functions| {
637 functions.insert("relu", |v| {
638 f64::max(0.0, v)
639 });
640 });
641 let now = SystemTime::now();
642 let program = moo.parse("1 + 4.9 ^ 0.2 * x").ok().unwrap().unwrap();
643 match now.elapsed() {
644 Ok(elapsed) => {
645 println!("{}ns", elapsed.as_nanos());
646 }
647 Err(e) => {
648 println!("Error: {e:?}");
649 }
650 }
651 println!("{}", program.run(1000.0));
652 }
653}