1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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!(),
}
}
}
|