1#![no_std]
2use log::info;
3extern crate alloc;
4use alloc::{boxed::Box, format, string::String, vec::Vec};
5use core::{ops::Rem, result::Result};
6
7pub type ID = String;
8pub type BN = Box<N>;
9pub type VN = Vec<N>;
10
11macro_rules! bx {
12 ($e:expr) => {
13 Box::new($e)
14 };
15}
16
17#[derive(Debug, Clone)]
19pub enum N {
20 FuncCall {
21 func: BN,
22 args: VN,
23 },
24 Block(VN),
25 If {
26 condition: BN,
27 path_true: BN,
28 path_false: BN,
29 },
30 While {
31 condition: BN,
32 body: BN,
33 },
34 Set(ID, BN),
35 Get(ID),
36 Unary(Op, BN),
37 Binary(Op, BN, BN),
38 FuncDef {
40 args_name: Vec<ID>,
41 scope: BN,
42 },
43 FuncNativeDef(Native),
44 Array(VN),
45 Num(f64),
46 Str(String),
47 Unit,
48}
49
50#[derive(Clone)]
52pub struct Native(pub alloc::rc::Rc<dyn Fn(N, N, N, N) -> N>);
53
54impl core::fmt::Debug for Native {
55 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
56 write!(f, "Native")
57 }
58}
59
60#[repr(u8)]
61#[derive(Debug, Clone, PartialEq, Eq, Copy)]
62pub enum Op {
63 Mul = 0,
64 Div = 1,
65 Equals,
66 NotEquals,
67 Lesser,
68 Greater,
69 Modulus,
70 And,
71 Or,
72 Plus,
73 Plus2,
74 Shift,
75 Minus,
76 Assign,
77}
78impl Op {
79 fn term_separate(self) -> bool {
80 self as u8 > 1
81 }
82}
83
84impl N {
85 pub fn as_f64(&self) -> f64 {
86 match self {
87 N::Num(x) => *x,
88 _ => 0.0,
89 }
90 }
91 pub fn to_bool(&self) -> bool {
93 match self {
94 N::Num(x) if *x != 0.0 => true,
95 N::Str(s) => !s.is_empty(),
96 N::Array(vec) => !vec.is_empty(),
97 _ => false,
98 }
99 }
100 pub fn to_str(&self) -> String {
101 match self {
102 N::Num(x) => format!("{}", x),
103 N::Str(s) => s.clone(),
104 e => format!("{:?}", e),
105 }
106 }
107}
108
109#[derive(Debug, Clone)]
113enum Token {
114 BlockStart,
115 BlockEnd,
116 If,
117 Else,
118 Comma,
119 ParStart,
120 ParEnd,
121 While,
122 Quoted(String),
123 Bin(Op),
124 N(N),
125 Let(ID),
126 Err(String),
127 Assoc,
128 ArrayStart,
129 ArrayEnd,
130}
131
132pub struct Ctx {
134 pub values: Vec<N>,
135 pub idents: Vec<String>,
136 pub code: Vec<char>,
137 pub deep: usize,
138}
139
140impl Ctx {
141 pub fn new() -> Ctx {
142 Ctx {
143 values: Vec::new(),
144 idents: Vec::new(),
145 code: Vec::new(),
146 deep: 0,
147 }
148 }
149
150 #[inline(always)]
151 pub fn drain(&mut self, from: usize) {
152 self.values.drain(from..);
153 self.idents.drain(from..);
154 }
155
156 #[inline(always)]
157 pub fn set_val(&mut self, name: &str, n: N) {
158 self.idents.push(String::from(name));
159 self.values.push(n);
160 }
161
162 #[inline(always)]
163 pub fn set_val_absolute(&mut self, i: usize, name: &str, n: N) {
164 self.idents[i] = String::from(name);
165 self.values[i] = n;
166 }
167 pub fn find_var(&mut self, name: &str) -> Option<(usize, &mut N)> {
171 for (i, id) in self.idents.iter().enumerate().rev() {
172 if id == name {
173 return Some((i, &mut self.values[i]));
174 }
175 }
176 info!("Unknown variable {}", name);
177 None
178 }
179
180 pub fn insert_code(&mut self, code: &str) {
181 self.code.extend(code.chars());
182 }
183
184 pub fn parse_next_expr(&mut self) -> Result<N, Error> {
185 let mut i = 0;
186 let res = parse_expr(&mut i, &self.code, 0)?;
187 self.code.drain(0..i);
188 Ok(res)
189 }
190}
191
192impl Default for Ctx {
193 fn default() -> Self {
194 Ctx::new()
195 }
196}
197
198pub fn parse_eval(code: &str) -> N {
199 let mut ctx = Ctx::new();
200 ctx.insert_code(code);
201 let mut res = N::Unit;
202 while let Ok(mut parent) = ctx.parse_next_expr() {
203 res = eval(&mut parent, &mut ctx);
204 }
205 res
206}
207
208fn bool_n(b: bool) -> N {
209 N::Num(if b { 1.0 } else { 0.0 })
210}
211
212pub fn eval(n: &N, ctx: &mut Ctx) -> N {
214 ctx.deep += 1;
215 if log::log_enabled!(log::Level::Info) {
216 info!("\n{}eval {:?}", pa(ctx.deep), n);
217 for i in 0..ctx.idents.len() {
218 info!(
219 "{}{} {:?}:{:?}",
220 pa(ctx.deep),
221 i,
222 ctx.idents[i],
223 ctx.values[i]
224 );
225 }
226 }
227 let res = match n {
228 N::If {
229 condition,
230 path_true,
231 path_false,
232 } => match eval(condition, ctx).to_bool() {
233 true => eval(path_true, ctx),
234 false => eval(path_false, ctx),
235 },
236 N::While { condition, body } => {
237 let mut res = N::Unit;
238 while eval(condition, ctx).to_bool() {
239 res = eval(body, ctx)
240 }
241 res
242 }
243 N::Block(arr) => {
244 let variable_skip_begin = ctx.values.len();
245 let mut res = N::Unit;
246 for a in arr.iter() {
247 res = eval(a, ctx);
248 }
249 if log::log_enabled!(log::Level::Info) {
250 for i in variable_skip_begin..ctx.values.len() {
251 info!(
252 "block forget {} {:?}: {:?}",
253 i, ctx.idents[i], ctx.values[i]
254 );
255 }
256 }
257 ctx.drain(variable_skip_begin);
258 res
259 }
260 N::Set(name, val) => {
261 let val = eval(val, ctx);
262 ctx.set_val(name, val);
263 N::Unit
264 }
265 N::Get(name) => ctx.find_var(name).map(|e| e.1.clone()).unwrap_or(N::Unit),
266 N::FuncCall { func, args } => match eval(func, ctx) {
267 N::FuncNativeDef(native) => native.0(
268 args.first().map(|e| eval(e, ctx)).unwrap_or(N::Unit),
269 args.get(1).map(|e| eval(e, ctx)).unwrap_or(N::Unit),
270 args.get(2).map(|e| eval(e, ctx)).unwrap_or(N::Unit),
271 args.get(3).map(|e| eval(e, ctx)).unwrap_or(N::Unit),
272 ),
273 N::FuncDef {
274 args_name,
275 mut scope,
276 } => {
277 let variable_scope_index = ctx.values.len();
278 for (i, arg_name) in args_name.iter().enumerate() {
279 let val = args.get(i).map(|e| eval(e, ctx)).unwrap_or(N::Unit);
280 ctx.set_val(arg_name, val);
281 }
282 let res = eval(&mut scope, ctx);
283 if log::log_enabled!(log::Level::Info) {
284 for i in variable_scope_index..ctx.values.len() {
285 info!("forget {} {:?}: {:?}", i, ctx.idents[i], ctx.values[i]);
286 }
287 }
288 ctx.drain(variable_scope_index);
289 res
290 }
291 N::Array(mut v) => {
292 if let Some(index) = args.first().map(|e| eval(e, ctx)) {
293 match index {
294 N::Num(i) => {
295 let mut i = i as isize;
296 if i < 0 {
297 i = v.len() as isize + (i as isize);
298 }
299 v.get(i as usize).cloned().unwrap_or(N::Unit)
300 }
301 N::FuncDef { args_name, scope } => {
302 for (index, e) in v.iter_mut().enumerate() {
303 let variable_scope_index = ctx.values.len();
304 if let Some(s) = args_name.first() {
305 ctx.set_val(s, e.clone());
306 }
307 if let Some(s) = args_name.get(1) {
308 ctx.set_val(s, N::Num(index as f64));
309 }
310 *e = eval(&scope, ctx);
311 ctx.drain(variable_scope_index);
312 }
313 N::Array(v)
314 }
315 _ => N::Unit,
316 }
317 } else {
318 N::Num(v.len() as f64)
319 }
320 }
321 _ => N::Unit,
322 },
323 N::Binary(op, l, r) => {
324 if let Op::Assign = op {
325 if let N::Get(name) = l.as_ref() {
326 if let Some((key, _)) = ctx.find_var(name) {
327 let v = eval(r, ctx);
328 ctx.set_val_absolute(key, name, v);
329 }
330 }
331 return N::Unit;
332 }
333 let lt = eval(l, ctx);
334 let rt = eval(r, ctx);
335 match (op.clone(), <, &rt) {
336 (Op::Plus, N::Num(li), N::Num(ri)) => N::Num(li + ri),
337 (Op::Plus, N::Num(li), N::Unit) => N::Num(*li),
338 (Op::Plus, N::Unit, N::Num(ri)) => N::Num(*ri),
339 (Op::Greater, N::Num(li), N::Num(ri)) => bool_n(li > ri),
340 (Op::Lesser, N::Num(li), N::Num(ri)) => bool_n(li < ri),
341 (Op::Equals, N::Num(li), N::Num(ri)) => bool_n(li == ri),
342 (Op::Equals, N::Str(li), N::Str(ri)) => bool_n(li == ri),
343 (Op::NotEquals, N::Num(li), N::Num(ri)) => bool_n(li != ri),
344 (Op::NotEquals, N::Str(li), N::Str(ri)) => bool_n(li != ri),
345 (Op::Minus, N::Num(li), N::Num(ri)) => N::Num(li - ri),
346 (Op::Mul, N::Num(li), N::Num(ri)) => N::Num(li * ri),
347 (Op::Div, N::Num(li), N::Num(ri)) => N::Num(li / ri),
348 (Op::Modulus, N::Num(li), N::Num(ri)) => N::Num(li.rem(ri)),
349 (Op::Plus, N::Str(li), ri) => N::Str(format!("{}{}", li, ri.to_str())),
350 (Op::Plus, li, N::Str(ri)) => N::Str(format!("{}{}", li.to_str(), ri)),
351 (Op::Plus2, N::Array(li), N::Array(ri)) => {
352 N::Array(li.iter().chain(ri).cloned().collect())
353 }
354 (Op::Plus, N::Array(li), ri) => {
355 N::Array(li.iter().chain(core::iter::once(ri)).cloned().collect())
356 }
357 (Op::Plus, li, N::Array(ri)) => {
358 N::Array(core::iter::once(li).chain(ri.iter()).cloned().collect())
359 }
360 (Op::And, N::Array(li), N::FuncDef { args_name, scope }) => {
361 let mut new_arr = Vec::new();
362 for (index, e) in li.iter().enumerate() {
363 let variable_scope_index = ctx.values.len();
364 if let Some(s) = args_name.first() {
365 ctx.set_val(s, e.clone());
366 }
367 if let Some(s) = args_name.get(1) {
368 ctx.set_val(s, N::Num(index as f64));
369 }
370 if eval(&scope, ctx).to_bool() {
371 new_arr.push(e.clone());
372 }
373 ctx.drain(variable_scope_index);
374 }
375 N::Array(new_arr)
376 }
377 (Op::Or, N::Array(li), N::FuncDef { args_name, scope }) => {
378 let mut acc = li.first().cloned().unwrap_or(N::Unit);
379
380 for e in li.iter().skip(1) {
381 let variable_scope_index = ctx.values.len();
382 if let Some(s) = args_name.first() {
383 ctx.set_val(s, acc);
384 }
385 if let Some(s) = args_name.get(1) {
386 ctx.set_val(s, e.clone());
387 }
388 acc = eval(&scope, ctx);
389 ctx.drain(variable_scope_index);
390 }
391 acc
392 }
393 (Op::And, li, ri) => bool_n(li.to_bool() && ri.to_bool()),
394 (Op::Or, li, ri) => bool_n(li.to_bool() || ri.to_bool()),
395 _ => {
396 info!("unknown bin {:?} {:?} {:?}", lt, op, rt);
397 N::Unit
398 }
399 }
400 }
401 N::FuncDef { args_name, scope } => N::FuncDef {
402 args_name: args_name.clone(),
403 scope: bx!(dup(&mut args_name.clone(), &mut scope.clone(), ctx)),
404 },
405 e => {
406 info!("noop");
407 e.clone()
408 }
409 };
410
411 ctx.deep -= 1;
412 res
413}
414
415pub fn dup(excl: &mut Vec<ID>, n: &mut N, ctx: &mut Ctx) -> N {
417 info!("instanciate {:?}", n);
418 match n {
419 N::Block(scope) => N::Block(scope.iter_mut().map(|e| dup(excl, e, ctx)).collect()),
420 N::While { condition, body } => N::While {
421 condition: bx!(dup(excl, condition, ctx)),
422 body: bx!(dup(excl, body, ctx)),
423 },
424 N::FuncCall { func, args } => N::FuncCall {
425 func: bx!(dup(excl, func, ctx)),
426 args: args.iter_mut().map(|e| dup(excl, e, ctx)).collect(),
427 },
428 N::FuncDef { args_name, scope } => N::FuncDef {
429 args_name: args_name.clone(),
430 scope: bx!(dup(excl, scope, ctx)),
431 },
432 N::If {
433 condition,
434 path_true,
435 path_false,
436 } => N::If {
437 condition: bx!(dup(excl, condition, ctx)),
438 path_true: bx!(dup(excl, path_true, ctx)),
439 path_false: bx!(dup(excl, path_false, ctx)),
440 },
441 N::Get(name) => {
442 if excl.contains(name) {
443 return N::Get(name.clone());
444 }
445 match ctx.find_var(name) {
446 Some((_, n)) => n.clone(),
447 _ => N::Get(name.clone()),
448 }
449 }
450 N::Set(name, val) => {
451 if let Some(index) = excl.iter().position(|x| x == name) {
452 excl.remove(index);
453 }
454 N::Set(name.clone(), val.clone())
455 }
456 N::Binary(op, l, r) => N::Binary(*op, bx!(dup(excl, l, ctx)), bx!(dup(excl, r, ctx))),
457 N::Array(v) => N::Array(v.iter_mut().map(|e| dup(excl, e, ctx)).collect()),
458 e => e.clone(),
459 }
460}
461
462fn next_token(i: &mut usize, code: &[char]) -> Token {
463 let skip_whitespaces = |i: &mut usize| {
464 while *i < code.len() && (code[*i] == ' ' || code[*i] == '\n') {
465 *i += 1;
466 }
467 };
468
469 let parse_number = |i: &mut usize| {
470 let backup_i = *i;
471 let mut id = String::from("");
472 while code.len() > *i && (code[*i].is_ascii_digit() || code[*i] == '.') {
473 id = format!("{}{}", id, code[*i]);
474 *i += 1;
475 }
476 if !id.is_empty() {
477 if let Ok(j) = id.parse::<f64>() {
478 Some(j)
479 } else {
480 *i = backup_i;
481 None
482 }
483 } else {
484 *i = backup_i;
485 None
486 }
487 };
488
489 let parse_ident = |i: &mut usize| {
490 let mut id = String::from("");
491 while code.len() > *i && (code[*i].is_alphanumeric() || code[*i] == '_') {
492 id = format!("{}{}", id, code[*i]);
493 *i += 1;
494 }
495 if !id.is_empty() {
496 Some(id)
497 } else {
498 None
499 }
500 };
501
502 let starts_with = |mut i: usize, e: &str| {
503 if i + e.len() > code.len() {
504 return false;
505 }
506 for c in e.chars() {
507 if code[i] != c {
508 return false;
509 }
510 i += 1;
511 }
512 true
513 };
514 loop {
515 skip_whitespaces(i);
516
517 if *i >= code.len() {
518 break Token::Err(String::from("i>code"));
519 }
520
521 if code[*i] == '"' {
522 let mut builder = String::from("");
523 while *i + 1 < code.len() {
524 *i += 1;
525 match code[*i] {
526 '"' => {
527 *i += 1;
528 return Token::Quoted(builder);
529 }
530 c => builder.push(c),
531 }
532 }
533 return Token::Err(String::from("i>code"));
534 }
535
536 for (s, tok) in [
537 ("if", Token::If),
538 ("else", Token::Else),
539 ("while", Token::While),
540 ] {
541 if starts_with(*i, s)
542 && *i + s.len() < code.len()
543 && [' ', '{'].contains(&code[*i + s.len()])
544 {
545 *i += s.len();
546 return tok;
547 }
548 }
549
550 if starts_with(*i, "let ") && *i + 4 < code.len() {
551 *i += 4;
552 skip_whitespaces(i);
553 let id = match parse_ident(i) {
554 Some(id) => id,
555 None => break Token::Err(String::from("no id after let # ")),
556 };
557 skip_whitespaces(i);
558 if *i >= code.len() || code[*i] != '=' {
559 break Token::Err(String::from("no equal after let 'id' # "));
560 }
561 *i += 1;
562 break Token::Let(id);
563 }
564
565 if let Some(num) = parse_number(i) {
566 break Token::N(N::Num(num));
567 }
568
569 if let Some(id) = parse_ident(i) {
570 break Token::N(N::Get(id));
571 }
572
573 for (st, tok) in [
574 ("==", Token::Bin(Op::Equals)),
575 ("!=", Token::Bin(Op::NotEquals)),
576 ("++", Token::Bin(Op::Plus2)),
577 ("<<", Token::Bin(Op::Shift)),
578 ("=>", Token::Assoc),
579 ] {
580 if starts_with(*i, st) {
581 *i += 2;
582 return tok;
583 }
584 }
585
586 for (key, val) in [
587 ('{', Token::BlockStart),
588 ('}', Token::BlockEnd),
589 (',', Token::Comma),
590 ('(', Token::ParStart),
591 (')', Token::ParEnd),
592 ('=', Token::Bin(Op::Assign)),
593 ('+', Token::Bin(Op::Plus)),
594 ('-', Token::Bin(Op::Minus)),
595 ('*', Token::Bin(Op::Mul)),
596 ('/', Token::Bin(Op::Div)),
597 ('>', Token::Bin(Op::Greater)),
598 ('<', Token::Bin(Op::Lesser)),
599 ('%', Token::Bin(Op::Modulus)),
600 ('&', Token::Bin(Op::And)),
601 ('|', Token::Bin(Op::Or)),
602 ('[', Token::ArrayStart),
603 (']', Token::ArrayEnd),
604 ] {
605 if code[*i] == key {
606 *i += 1;
607 return val;
608 }
609 }
610
611 *i += 1;
612 }
613}
614
615fn pa(i: usize) -> String {
616 format!("{:width$}", "", width = i * 5)
617}
618type Error = &'static str;
619
620fn parse_expr(i: &mut usize, code: &[char], pad: usize) -> Result<N, Error> {
621 info!(
622 "{}parse expr {:?}",
623 pa(pad),
624 &code[*i..(*i + 5).min(if code.is_empty() { *i } else { code.len() - 1 })]
625 );
626 let term = parse_term(i, code, pad + 1)?;
627
628 let mut j = *i;
629 let token = next_token(&mut j, code);
630
631 if let Token::Bin(op) = token {
632 {
634 *i = j;
635 let term_right = parse_expr(i, code, pad + 1)?;
636 let n = N::Binary(op, bx!(term), bx!(term_right));
637 return Ok(n);
638 }
639 }
640
641 Ok(term)
642}
643
644fn parse_term(i: &mut usize, code: &[char], pad: usize) -> Result<N, Error> {
645 info!(
646 "{}parse_term {:?}",
647 pa(pad),
648 &code[*i..(*i + 5).min(if code.is_empty() { *i } else { code.len() - 1 })]
649 );
650
651 let factor = parse_factor(i, code, pad + 1)?;
652 let mut j = *i;
653 let token = next_token(&mut j, code);
654 info!("{:?}", token);
655 match token {
656 Token::Bin(Op::Mul) | Token::Bin(Op::Div) | Token::ParStart => {
657 *i = j;
658 match token {
659 Token::Bin(op) if !op.term_separate() => {
660 let factor_right = parse_term(i, code, pad + 1)?;
661 let n = N::Binary(op, bx!(factor), bx!(factor_right));
662 return Ok(n);
663 }
664
665 Token::ParStart => {
666 info!("Function call start");
667 let mut args = Vec::new();
668 loop {
669 info!("args enum");
670 let mut j = *i;
671 let e = parse_expr(&mut j, code, pad + 1);
672 match e {
673 Ok(expr) => {
674 info!("args enum got");
675 *i = j;
676 args.push(expr);
677
678 let mut k = *i;
679 let token = next_token(&mut k, code);
680 if let Token::Comma = token {
681 *i = k
682 }
683 }
684 Err(_) => {
685 info!("args enum end");
686 break;
687 }
688 }
689 }
690 let token = next_token(i, code);
691 if let Token::ParEnd = token {
692 return Ok(N::FuncCall {
693 func: bx!(factor),
694 args,
695 });
696 } else {
697 return Err("No parenthesis close");
698 }
699 }
700 _ => {}
701 }
702 }
703 _ => {}
704 }
705
706 Ok(factor)
707}
708
709fn parse_factor(i: &mut usize, code: &[char], pad: usize) -> Result<N, Error> {
710 if *i >= code.len() {
711 return Err("EOF");
712 }
713
714 info!(
715 "{}parse_factor {:?}",
716 pa(pad),
717 &code[*i..(*i + 5).min(if code.is_empty() { *i } else { code.len() - 1 })]
718 );
719
720 let token = next_token(i, code);
721 info!("{}{:?}", pa(pad), token);
722 if let Token::BlockStart = token {
723 let mut scope = Vec::new();
724
725 loop {
726 let mut j = *i;
727 let e = parse_expr(&mut j, code, pad + 1);
728 match e {
729 Ok(expr) => {
730 *i = j;
731 scope.push(expr);
732 }
733 Err(_) => {
734 break;
735 }
736 }
737 }
738 let token = next_token(i, code);
739 if let Token::BlockEnd = token {
740 return Ok(N::Block(scope));
741 } else {
742 return Err("No block end");
743 }
744 }
745
746 if let Token::ArrayStart = token {
747 let mut es = Vec::new();
748
749 loop {
750 let mut j = *i;
751 let next = parse_expr(&mut j, code, pad);
752 match next {
753 Ok(expr) => {
754 *i = j;
755 es.push(expr)
756 }
757 Err(_) => {
758 let next = next_token(i, code);
759 match next {
760 Token::Comma => continue,
761 Token::ArrayEnd => break,
762 _ => break,
763 }
764 }
765 }
766 }
767
768 return Ok(N::Array(es));
769 }
770
771 if let Token::ParStart = token {
772 info!("Function definition start");
773 let mut args_name = Vec::new();
774
775 loop {
776 let token = next_token(i, code);
777 match token {
778 Token::N(N::Get(name)) => {
779 info!("name {}", name);
780 args_name.push(name);
781 }
782 Token::Comma => {}
783 Token::ParEnd => {
784 break;
785 }
786 _ => {}
787 }
788 }
789
790 let token = next_token(i, code);
791 if let Token::Assoc = token {
792 let scope = parse_expr(i, code, pad + 1)?;
793 let n = N::FuncDef {
794 args_name,
795 scope: bx!(scope),
796 };
797
798 return Ok(n);
799 } else {
800 return Err("No => after func def");
801 }
802 }
803
804 if let Token::Quoted(s) = token {
805 let n = N::Str(s);
806 return Ok(n);
807 }
808
809 if let Token::While = token {
810 let condition = parse_expr(i, code, pad + 1)?;
811 let body = parse_expr(i, code, pad + 1)?;
812 let n = N::While {
813 condition: bx!(condition),
814 body: bx!(body),
815 };
816
817 return Ok(n);
818 }
819
820 if let Token::If = token {
821 let cond_expr = parse_expr(i, code, pad + 1)?;
822 let true_expr = parse_expr(i, code, pad + 1)?;
823 let mut j = *i;
824 let token = next_token(&mut j, code);
825 let else_expr;
826 if let Token::Else = token {
827 *i = j;
828 else_expr = parse_expr(i, code, pad + 1)?;
829 } else {
830 else_expr = N::Unit;
831 }
832 let n = N::If {
833 condition: bx!(cond_expr),
834 path_true: bx!(true_expr),
835 path_false: bx!(else_expr),
836 };
837 return Ok(n);
838 }
839
840 if let Token::Let(name) = token {
841 let val = parse_expr(i, code, pad + 1)?;
842 let n = N::Set(name, bx!(val));
843 return Ok(n);
844 }
845
846 if let Token::N(N::Num(num)) = token {
847 return Ok(N::Num(num));
848 }
849
850 if let Token::N(N::Get(name)) = token {
851 return Ok(N::Get(name));
852 }
853
854 Err("No term found")
855}
856
857#[cfg(test)]
858mod test;