use logos::Logos; mod grammar; #[derive(Logos, Debug, PartialEq)] enum LogosToken { #[regex(r"[0-9]+", priority = 2)] Int, #[regex(r"[0-9]+(\\.[0-9]+)?")] Float, #[regex(r"[A-Za-z0-9!$%&*+\-./:<=>?@^_~]+")] Ident, #[error] #[regex(r"[ \t\n\f]+", logos::skip)] Error, #[token(r"(")] Lparen, #[token(r")")] Rparen, } #[derive(Debug)] pub struct LexError; type Spanned = Result<(Loc, Tok, Loc), Error>; struct Lexer<'a>(logos::Lexer<'a, LogosToken>); impl<'a> Lexer<'a> { fn new(src: &'a str) -> Self { Self(LogosToken::lexer(src)) } } #[derive(Clone, Debug)] pub enum Token<'s> { Int(i64), Float(f64), Ident(&'s str), Lparen, Rparen, } impl<'a> Iterator for Lexer<'a> { type Item = Spanned, usize, LexError>; fn next(&mut self) -> Option { let kind = self.0.next()?; let span = self.0.span(); let text = self.0.slice(); let t = match kind { LogosToken::Int => Token::Int(text.parse().unwrap()), LogosToken::Float => Token::Float(text.parse().unwrap()), LogosToken::Ident => Token::Ident(text), LogosToken::Lparen => Token::Lparen, LogosToken::Rparen => Token::Rparen, LogosToken::Error => return Some(Err(LexError)), }; Some(Ok((span.start, t, span.end))) } } #[derive(Clone, Debug)] pub enum Tree<'s> { Leaf(Val<'s>), Branch(Vec>), } #[derive(Clone, Debug)] pub enum Val<'s> { Int(i64), Float(f64), Ident(&'s str), } enum Func {} enum RVal { Func(Func), Num(f64), } enum Op { Push(RVal), Call(u8), Print, } fn comp_to(t: &Tree) fn eval(t: &Tree<'_>) -> f64 { match t { Tree::Leaf(Val::Ident(_)) => panic!("Need number got {:?}", t), Tree::Leaf(Val::Float(f)) => *f, Tree::Leaf(Val::Int(i)) => *i as f64, Tree::Branch(v) => { if let Tree::Leaf(Val::Ident(f)) = v[0] { match f { "min" => v[1..].iter().map(eval).reduce(f64::min).unwrap(), "max" => v[1..].iter().map(eval).reduce(f64::max).unwrap(), "+" => v[1..].iter().map(eval).sum(), "*" => v[1..].iter().map(eval).product(), "/" => eval(&v[1]) / v[2..].iter().map(eval).product::(), "-" => eval(&v[1]) - v[2..].iter().map(eval).sum::(), _ => panic!("Unknown func {:?}", f), } } else { panic!("Not a function") } } } } fn main() { let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(); let tree = grammar::TreesParser::new().parse(Lexer::new(&src)); let t = dbg!(tree).unwrap(); dbg!(eval(&t[0])); } #[cfg(test)] mod tests { use super::*; #[test] fn math_exprs() { fn test(s: &str, v: f64) { let tree = grammar::TreesParser::new().parse(Lexer::new(s)).unwrap(); assert_eq!(tree.len(), 1); assert_eq!(eval(&tree[0]), v); } test("1", 1.0); test("(+ 1 2)", 3.0); test("(+ 1 2 (/ 2 3 4 5))", 3.033333333333333); } }