diff options
author | bnewbold <bnewbold@robocracy.org> | 2017-01-14 19:37:09 -0800 |
---|---|---|
committer | bnewbold <bnewbold@robocracy.org> | 2017-01-14 19:52:56 -0800 |
commit | a71465e935a178478d269e828550b7e3fc475fab (patch) | |
tree | 62e501dea9e40d9cd50dfc35753654b4c1e0e40e /src/transpile_latex.rs | |
parent | 11569fdec123e9c7aeaf38d8a122842c4c758fdf (diff) | |
download | modelthing-a71465e935a178478d269e828550b7e3fc475fab.tar.gz modelthing-a71465e935a178478d269e828550b7e3fc475fab.zip |
basic LaTeX transpiling
Diffstat (limited to 'src/transpile_latex.rs')
-rw-r--r-- | src/transpile_latex.rs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/transpile_latex.rs b/src/transpile_latex.rs new file mode 100644 index 0000000..1c777d2 --- /dev/null +++ b/src/transpile_latex.rs @@ -0,0 +1,99 @@ + +extern crate modelica_parser; + +use self::modelica_parser::*; +use errors::Result; + +pub trait TranspileLaTeX { + fn repr_latex(&self) -> Result<String>; +} + + +impl TranspileLaTeX for ModelicaModel { + fn repr_latex(&self) -> Result<String> { + + 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 TranspileLaTeX for Expr { + fn repr_latex(&self) -> Result<String> { + 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!(), + } + } +} |