% Translate R expression/compound to HTML/MathJax term mathml(R, M, Flags) => ml(R, M0, Flags), denoting(R, Denoting, Flags), ml(with(Denoting), With, Flags), !, M = [math(M0), With]. mathjax(R, M, Flags) => jax(R, M0, Flags), denoting(R, Denoting, Flags), jax(with(Denoting), With, Flags), !, format(string(M), "$~w$~w", [M0, With]). % Translates the compound A to another compound M, checking for Flags % and eventually changing Flags to Flags1 % macro(A, A1, Flags, Flags1) :- math_hook(A, A0, Flags, Flags0), !, Flags1 = Flags0, A1 = A0. macro(A, A1, Flags, Flags1) :- math_hook(A, A0, Flags), !, Flags1 = Flags, A1 = A0. macro(A, A1, Flags, Flags1) :- math_hook(A, A0), !, Flags1 = Flags, A1 = A0. macro(A, M, Flags, Flags1) :- math(A, M, Flags, Flags1), % math/4 macro changing Flags dif(Flags-A, Flags1-M). macro(A, M, Flags, Flags) :- math(A, M, Flags), % math/3 only reading Flags dif(A, M). macro(A, M, Flags, Flags) :- math(A, M), % math/2 ignoring the flags dif(A, M). % Main MathML translation % % R: R expression % M: HTML term % Flags: to control some aspects of the output % % This predicate only checks if a macro can be applied. Add ml/3 predicates for % R expressions with their translation below. % ml(R, M, Flags), macro(R, R1, Flags, Flags1) => ml(R1, M, Flags1). ml(R, M, Flags), mlx(R, R1, Flags) % R hook into ml/3 => M = R1. % Same for MathJax/LaTeX jax(R, M, Flags), macro(R, R1, Flags, Flags1) => jax(R1, M, Flags1). jax(R, M, Flags), jaxx(R, R1, Flags) % R hook => M = R1. % Return precedence of an R expression, to decide if parentheses are % needed. Uses the usual Prolog precendence. prec(R, Prec, Flags), macro(R, R1, Flags, Flags1) => prec(R1, Prec, Flags1). prec(R, Prec, Flags), precx(R, Prec1, Flags) => Prec = Prec1. % Return parentheses counter of an R expression. Needed to decide % which shape is chosen (), [], {}, and restarting again with (). paren(R, Paren, Flags), macro(R, R1, Flags, Flags1) => paren(R1, Paren, Flags1). paren(R, Paren, Flags), parenx(R, Paren1, Flags) => Paren = Paren1. % Return some extra type information as a list. type(R, Type, Flags), macro(R, R1, Flags, Flags1) => type(R1, Type, Flags1). type(R, Type, Flags), typex(R, Type1, Flags) => Type = Type1. % Suppress the names of function arguments from R % % For instance, the R expression dbinom(x=5, size=20, prob=0.6) is % handed over to mathml as dbinom(name(x) = 5, name(size) = ...). This % macro removes the name of the arguments. math(name(_) = R, M) => M = R. % These two predicate are only used for ad hoc testing from within % Prolog. % % Examples % mathml(sin(x)). % mathjax(sin(x)). % % mathml :- % mathml(sin(x)). % mathml(R) :- r2mathml(R, M), atomic_list_concat(M, S), writeln(R-S). mathjax(R) :- r2mathjax(R, M), atomic_list_concat(M, S), writeln(R-S). % Performance can be a bit improved by putting Flags at the end of the % list of arguments and having the R term as the first argument. % However, some rules below use maplist. There it is convenient to have % Flags in the beginning. ml_(Flags, R, M) => ml(R, M, Flags). jax_(Flags, R, M) => jax(R, M, Flags). paren_(Flags, R, Paren) => paren(R, Paren, Flags). denoting_(Flags, R, Den) => denoting(R, Den, Flags).