extern crate modelica_parser; use self::modelica_parser::*; use errors::Result; pub trait ReprLaTeX { fn repr_latex(&self) -> Result; } impl ReprLaTeX for ModelicaModel { fn repr_latex(&self) -> Result { let mut result = r#"\begin{array}{rcl}"#.to_string() + "\n"; for eq in &self.equations { result += &format!(" {} & = & {} \\\\\n", try!(eq.lhs.repr_latex()), try!(eq.rhs.repr_latex())); } result += "\n"; result += r#"\end{array}"#; Ok(result) } } fn is_latexy_ident(s: &str) -> bool { let latexy_idents = [ "alpha", "Alpha", "beta", "gamma", "Gamma", "delta", "Delta", "epsilon", "zeta", "eta", "theta", "Theta", "iota", "kappa", "lambda", "Lambda", "mu", "nu", "xi", "Xi", "omicron", "pi", "Pi", "rho", "sigma", "Sigma", "tau", "upsilon", "phi", "Phi", "chi", "psi", "Psi", "omega", "Omega"]; latexy_idents.contains(&s) } impl ReprLaTeX for Expr { fn repr_latex(&self) -> Result { use modelica_parser::Expr::*; use modelica_parser::MathUnaryFunc::*; use modelica_parser::BinOperator::*; match *self { Integer(e) => Ok(format!("{}", e)), Float(e) => Ok(format!("{}", e)), Boolean(true) => Ok(format!("true")), Boolean(false) => Ok(format!("false")), StringLiteral(ref s) => Ok(format!("\\text{{ {} }}", s)), // Tries to do script for simple cases ("M_1") Ident(ref e) => { if e.contains('_') { let split: Vec<&str> = e.splitn(2, '_').collect(); Ok(format!(r"{}{}_{{ {}{} }}", if is_latexy_ident(split[0]) { "\\" } else { "" }, split[0], if is_latexy_ident(split[1]) { "\\" } else { "" }, split[1])) } else { Ok(format!("{}{}", if is_latexy_ident(e) { "\\" } else { "" }, e)) } }, // Treate simple derivatives (common case) differently from complex // (destructuring with 'box' keyword is still unstable) Der(ref e) => if let &Ident(_) = e.as_ref() { Ok(format!("\\frac{{ d {} }}{{ dt }}", try!(e.repr_latex()))) } else { Ok(format!("\\frac{{ d }}{{ dt }} {}", try!(e.repr_latex()))) }, Sign(ref e) => Ok(format!("\\sign{{ {} }}", try!(e.repr_latex()))), // LaTeX depends on the unary MathUnaryExpr(Abs, ref e) => Ok(format!("\\left\\|{}\\right\\|", try!(e.repr_latex()))), MathUnaryExpr(Sqrt, ref e) => Ok(format!("\\sqrt{{ {} }}", try!(e.repr_latex()))), MathUnaryExpr(Log10, ref e) => Ok(format!("\\log_{{10}}{{ {} }} ", try!(e.repr_latex()))), MathUnaryExpr(func, ref e) => Ok(format!("\\{:?}{{ {} }}", func, try!(e.repr_latex()))), // LaTeX depends on binexpr BinExpr(Divide, ref l, ref r) => Ok(format!("\\frac{{ {} }}{{ {} }}", try!(l.repr_latex()), try!(r.repr_latex()))), BinExpr(Multiply, ref l, ref r) => Ok(format!("{} \\cdot {}", try!(l.repr_latex()), try!(r.repr_latex()))), BinExpr(Exponentiate, ref l, ref r) => Ok(format!("{}^{{ {} }}", try!(l.repr_latex()), try!(r.repr_latex()))), BinExpr(op, ref l, ref r) => Ok(format!("\\left({} {:?} {}\\right)", try!(l.repr_latex()), op, try!(r.repr_latex()))), Array(_) => unimplemented!(), } } }