aboutsummaryrefslogtreecommitdiffstats
path: root/src/transpile_latex.rs
blob: 1c777d21c3e0626b83bc82feac76de26367ccb21 (plain)
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!(),
        }
    }
}