use ssexp::{ parse, parsers::{DelimitedListParser, InfixKind}, MacroMap, Token::{self, List, Symbol}, }; use num_traits::{One, Zero}; use std::{fmt::Debug, str::FromStr}; fn sum(nums: &[T]) -> T { nums.iter().fold(T::zero(), |x, y| x + *y) } fn prod(nums: &[T]) -> T { nums.iter().fold(T::one(), |x, y| x * *y) } fn to(tokens: &[Token]) -> Vec where ::Err: Debug, { let mut vec = Vec::new(); for token in tokens { match token { Symbol(string) => vec.push( string .parse() .expect(&format!("Parsing number from \"{}\" failed", string)[..]), ), List(toks) => { if let Symbol(op) = &toks[0] { let nums = &to(&toks[1..])[..]; vec.push(match &op[..] { "add" => sum(nums), "mul" => prod(nums), _ => panic!("Operation `{}` not supported", op), }); } else { panic!("First list element has to be a symbol") } } } } vec } #[test] fn math_test() { use std::io::Read; use std::fs::File; let mut file = File::open("sexp/test.sexp").unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); let map = MacroMap::new() .with_lists('(', ')') .with_comments(';') .with_separating_whitespaces() .with_infix('+', InfixKind::Prefix("add".into()), false) .with_infix('*', InfixKind::Prefix("mul".into()), false); let sexps = parse(contents.chars(), DelimitedListParser(')'), map); let nums = to::(&sexps[..]); assert_eq!(nums[0], 7); assert_eq!(nums[1], 15); assert_eq!(nums[2], 0); assert_eq!(nums[3], -1); assert_eq!(nums[4], 6); assert_eq!(nums[5], 9); }