#![feature(box_syntax, rustc_private)] #[allow(plugin_as_library)] extern crate herbie_lint; extern crate rustc; use herbie_lint::lisp::{LispExpr, Parser, ParseError}; use herbie_lint::lisp::LispExpr::*; use rustc::hir::BinOp_::*; use rustc::hir::UnOp::*; pub fn parse(s: &str) -> Result { let mut parser = Parser::new(); parser.parse(s) } #[test] fn test_parser() { assert_eq!(parse(""), Err(ParseError::EOE)); assert_eq!(parse("0."), Ok(Lit(0.))); assert_eq!(parse("herbie"), Ok(Ident(0))); assert_eq!(parse("(+ 0. herbie1)"), Ok(Binary(BiAdd, box Lit(0.), box Ident(0)))); let valid = &[ ("0", Lit(0.)), ("herbie0", Ident(0)), ("(+ herbie0 herbie1)", Binary(BiAdd, box Ident(0), box Ident(1))), ("(- herbie0)", Unary(UnNeg, box Ident(0))), ("(- herbie0 herbie1)", Binary(BiSub, box Ident(0), box Ident(1))), ("(cos 1)", Fun("cos".into(), vec![Lit(1.)])), ("(cos herbie0)", Fun("cos".into(), vec![Ident(0)])), ("(log1p (cos herbie0))", Fun("log1p".into(), vec![Fun("cos".into(), vec![Ident(0)])])), ]; for &(s, ref e) in valid { assert_eq!(parse(s).as_ref(), Ok(e)); assert_eq!(s, e.to_lisp("herbie")); } assert_eq!(parse("(+ 0. 0.) foobar"), Err(ParseError::EOE)); assert_eq!(parse("("), Err(ParseError::EOE)); assert_eq!(parse("0.eee"), Err(ParseError::Float)); assert_eq!(parse("+"), Err(ParseError::Unexpected('+'))); assert_eq!(parse("(+)"), Err(ParseError::Unexpected(')'))); assert_eq!(parse("(+ 0.)"), Err(ParseError::Arity)); assert_eq!(parse("(+ 0. 0."), Err(ParseError::Expected(')'))); assert_eq!(parse("(+ 0. 0. 0.)"), Err(ParseError::Expected(')'))); assert_eq!(parse("(+ 0. 0. 0."), Err(ParseError::Expected(')'))); assert_eq!(parse("-"), Err(ParseError::Unexpected('-'))); assert_eq!(parse("(-)"), Err(ParseError::Unexpected(')'))); assert_eq!(parse("(- 0. 0. 0.)"), Err(ParseError::Expected(')'))); assert_eq!(parse("(cos)"), Err(ParseError::Arity)); assert_eq!(parse("(cos"), Err(ParseError::Expected(')'))); assert_eq!(parse("(cos 1. 2.)"), Err(ParseError::Arity)); assert_eq!(parse("(cos 1. 2. 3."), Err(ParseError::Expected(')'))); assert_eq!(parse("(foo 1.)"), Err(ParseError::Ident)); assert_eq!(parse("(foocos 1.)"), Err(ParseError::Ident)); assert_eq!(parse("(cosfoocos 1.)"), Err(ParseError::Ident)); let mut parser = Parser::new(); assert_eq!(parser.parse("(* (+ (/ herbie0 herbie1) herbie2) herbie1)"), Ok( Binary(BiMul, box Binary(BiAdd, box Binary(BiDiv, box Ident(0), box Ident(1)), box Ident(2) ), box Ident(1) ) )); assert_eq!(parser.parse("(+ (* herbie2 herbie1) herbie0)"), Ok( Binary(BiAdd, box Binary(BiMul, box Ident(2), box Ident(1)), box Ident(0) ) )); assert_eq!(parse("(+ (* herbie2 herbie1) herbie0)"), Ok( Binary(BiAdd, box Binary(BiMul, box Ident(0), box Ident(1)), box Ident(2) ) )); }