use crate::ast::{BinaryOp, Expression, UnaryOp};
pub(super) fn precedence(op: BinaryOp) -> u8 {
match op {
BinaryOp::Add | BinaryOp::Sub | BinaryOp::PlusMinus | BinaryOp::MinusPlus => 1,
BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => 2,
BinaryOp::Pow => 3,
}
}
pub(super) fn needs_parens(child: &Expression, parent_op: BinaryOp, is_right: bool) -> bool {
match child {
Expression::Binary { op: child_op, .. } => {
let parent_prec = precedence(parent_op);
let child_prec = precedence(*child_op);
if child_prec < parent_prec {
return true;
}
if child_prec == parent_prec {
match (parent_op, *child_op) {
(BinaryOp::Pow, BinaryOp::Pow) => return true,
(BinaryOp::Sub, BinaryOp::Sub) | (BinaryOp::Div, BinaryOp::Div) => {
return is_right
}
_ => {}
}
}
false
}
Expression::Unary { op, .. } => {
matches!(
(parent_op, op, is_right),
(BinaryOp::Pow, UnaryOp::Neg | UnaryOp::Pos, false)
)
}
_ => false,
}
}
pub(super) fn wrap_if_additive(expr: &Expression) -> String {
match expr {
Expression::Binary {
op: BinaryOp::Add | BinaryOp::Sub | BinaryOp::PlusMinus | BinaryOp::MinusPlus,
..
} => format!(r"\left({}\right)", expr.to_latex()),
_ => expr.to_latex(),
}
}
pub trait ToLatex {
fn to_latex(&self) -> String;
}
pub(super) const KNOWN_FUNCTIONS: &[&str] = &[
"sin", "cos", "tan", "cot", "sec", "csc", "arcsin", "arccos", "arctan", "arccot", "arcsec",
"arccsc", "sinh", "cosh", "tanh", "coth", "sech", "csch", "ln", "log", "exp", "lg", "det",
"dim", "ker", "hom", "arg", "deg", "gcd", "lcm", "max", "min", "sup", "inf", "lim", "limsup",
"liminf",
];