From a71465e935a178478d269e828550b7e3fc475fab Mon Sep 17 00:00:00 2001 From: bnewbold Date: Sat, 14 Jan 2017 19:37:09 -0800 Subject: basic LaTeX transpiling --- src/lib.rs | 1 + src/transpile_js.rs | 2 +- src/transpile_latex.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/transpile_latex.rs diff --git a/src/lib.rs b/src/lib.rs index 4c32d66..cf88d3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub extern crate modelica_parser; pub mod modelica_model; pub mod transpile_scheme; pub mod transpile_js; +pub mod transpile_latex; use std::path::Path; use std::fs; diff --git a/src/transpile_js.rs b/src/transpile_js.rs index 269e900..4150b12 100644 --- a/src/transpile_js.rs +++ b/src/transpile_js.rs @@ -57,7 +57,7 @@ impl TranspileJS for Expr { BinExpr(op, ref l, ref r) => { Ok(format!("({} {:?} {})", try!(l.repr_js()), op, try!(r.repr_js()))) } - Array(_) => bail!("Array unimplemented"), + Array(_) => unimplemented!(), } } } 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; +} + + +impl TranspileLaTeX 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 TranspileLaTeX 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!(), + } + } +} -- cgit v1.2.3