use assert_eq as eq; use assert_ne as ne; use temp_name::parser::{self as p}; use temp_name::{Expr, Value, Scope}; use std::borrow::Cow; type ParseError = peg::error::ParseError; #[test] fn between() { eq!(p::between("baaaaab", "b", "b"), Ok("aaaaa")); eq!(p::between("baaaaab", "b", "b"), Ok("aaaaa")); eq!(p::between("(parenthesis)", "(", ")"), Ok("parenthesis")); eq!(p::between("[square brackets]", "[", "]"), Ok("square brackets")); eq!(p::between("-> endline\n", "-> ", "\n"), Ok("endline")); } #[test] fn values() { let int = |n| Ok(Value::Int(n)); let float = |n| Ok(Value::Float(n)); let cha = |c| Ok(Value::Char(c)); let string = |s| Ok(Value::Str(std::borrow::Cow::from(s))); eq!(p::number("5"), int(5)); eq!(p::float("62.4"), float(62.4)); eq!(p::number("9999"), int(9999)); eq!(p::float("0.5"), float(0.5)); eq!(p::char("'5'"), cha('5')); eq!(p::char("'B'"), cha('B')); eq!(p::char("'''"), cha('\'')); eq!(p::char("'\n'"), cha('\n')); eq!(p::char("'💜'"), cha('💜')); assert!(p::char("''").is_err()); eq!(p::ident("bonjour"), Ok("bonjour")); eq!(p::ident("bonjour?"), Ok("bonjour?")); assert!(p::ident("bonjour!").is_err()); assert!(p::ident("bon!jour").is_err()); eq!(p::str("\"type Expr<'input> = Expression<'input>;\""), string("type Expr<'input> = Expression<'input>;")); eq!(p::str("\"💜💜💜💜!\""), string("💜💜💜💜!")); eq!(p::str("\"\""), string("")); } #[test] fn comments() { fn comment(txt: &str) -> Result { Ok(Expr::Comment(txt)) } eq!( p::line_comment("// a useful comment"), comment(" a useful comment") ); eq!( p::line_comment("//a useful comment"), comment("a useful comment") ); eq!( p::line_comment("// a useful comment"), comment(" a useful comment") ); eq!( p::block_comment("/* a more useful comment */"), comment(" a more useful comment ") ); eq!( p::block_comment("/*a more useful comment*/"), comment("a more useful comment") ); eq!( p::block_comment("/* a more useful comment */"), comment(" a more useful comment ") ); } #[test] fn nothing() { eq!(p::nothing(" "), Ok(Expr::Nothing)); eq!(p::nothing("\n"), Ok(Expr::Endline)); } #[test] fn r#let() { fn int<'i>(n: i32) -> Box> { Box::new(Expr::Value(Value::Int(n))) } fn float<'i>(n: f32) -> Box> { Box::new(Expr::Value(Value::Float(n))) } fn _char<'i>(c: char) -> Box> { Box::new(Expr::Value(Value::Char(c))) } fn string(s: & str) -> Box { Box::new(Expr::Value(Value::Str(Cow::from(s)))) } fn name(s: &str) -> Box { Box::new(Expr::Value(Value::Name(s))) } fn _let<'i>(name: &'i str, value: Box>) -> Expr<'i> { Expr::Let(name, value) } fn vec_let<'i, const S: usize>( lets: [(&'i str, Box>); S], ) -> Result>, ParseError> { let lets = lets.into_iter().map(|(name, value)| _let(name, value)); Ok(lets.collect()) } let scope = &mut Scope::new(); eq!(p::_let("let a = 5", scope), Ok(_let("a", int(5)))); eq!(p::_let("let a = 5.5", scope), Ok(_let("a", float(5.5)))); eq!(p::parse("let a = 5", scope), vec_let([("a", int(5))])); eq!(p::parse("let a = 5.5", scope), vec_let([("a", float(5.5))])); eq!(p::parse("let a = 5\n", scope), vec_let([("a", int(5))])); eq!(p::parse("let a = 5.5\n", scope), vec_let([("a", float(5.5))])); eq!(p::parse("let\na\n=\n5", scope), vec_let([("a", int(5))])); eq!(p::parse("let\na\n=\n5.5", scope), vec_let([("a", float(5.5))])); eq!( p::parse("let \n a \n = \n5\n\n", scope), vec_let([("a", int(5))]) ); eq!( p::parse("let \n a \n = \n5.5\n\n", scope), vec_let([("a", float(5.5))]) ); eq!(p::parse("let extremelylongname = \"not so long string\"", scope), vec_let([("extremelylongname", string("not so long string"))])); eq!(p::parse("let a = 99\nlet b = 0.5\nlet c = '🌲'\nlet d = \"Stringy\"\nlet e = a", scope), vec_let([("a", int(99)), ("b", float(0.5)), ("c", _char('🌲')), ("d", string("Stringy")), ("e", name("a"))])); }