use std::collections::HashMap;
use crate::error::ParseResult;
use crate::functions::{define_function_full, FunctionContext, FunctionSpec};
use crate::parse_node::ParseNode;
pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
define_function_full(
map,
&[
"\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
"\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
"\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint",
"\u{220F}", "\u{2210}", "\u{2211}", "\u{22C0}", "\u{22C1}",
"\u{22C2}", "\u{22C3}", "\u{2A00}", "\u{2A01}", "\u{2A02}",
"\u{2A04}", "\u{2A06}",
],
"op",
0, 0, None,
false, false, true, false, false,
handle_op_symbol_limits,
);
define_function_full(
map,
&[
"\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg",
"\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg",
"\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp",
"\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin",
"\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th",
],
"op",
0, 0, None,
false, false, true, false, false,
handle_op_text_nolimits,
);
define_function_full(
map,
&[
"\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup",
],
"op",
0, 0, None,
false, false, true, false, false,
handle_op_text_limits,
);
define_function_full(
map,
&[
"\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint",
],
"op",
0, 0, None,
true, false, true, false, false,
handle_op_symbol_nolimits,
);
define_function_full(
map,
&["\\mathop"],
"op",
1, 0, None,
false, false, true, false,
true, handle_mathop,
);
}
fn single_char_big_op(c: &str) -> Option<&'static str> {
match c {
"\u{220F}" => Some("\\prod"),
"\u{2210}" => Some("\\coprod"),
"\u{2211}" => Some("\\sum"),
"\u{22C0}" => Some("\\bigwedge"),
"\u{22C1}" => Some("\\bigvee"),
"\u{22C2}" => Some("\\bigcap"),
"\u{22C3}" => Some("\\bigcup"),
"\u{2A00}" => Some("\\bigodot"),
"\u{2A01}" => Some("\\bigoplus"),
"\u{2A02}" => Some("\\bigotimes"),
"\u{2A04}" => Some("\\biguplus"),
"\u{2A06}" => Some("\\bigsqcup"),
_ => None,
}
}
fn handle_op_symbol_limits(
ctx: &mut FunctionContext,
_args: Vec<ParseNode>,
_opt_args: Vec<Option<ParseNode>>,
) -> ParseResult<ParseNode> {
let name = single_char_big_op(&ctx.func_name)
.map(|s| s.to_string())
.unwrap_or_else(|| ctx.func_name.clone());
Ok(ParseNode::Op {
mode: ctx.parser.mode,
limits: true,
always_handle_sup_sub: None,
suppress_base_shift: None,
parent_is_sup_sub: false,
symbol: true,
name: Some(name),
body: None,
loc: None,
})
}
fn handle_op_text_nolimits(
ctx: &mut FunctionContext,
_args: Vec<ParseNode>,
_opt_args: Vec<Option<ParseNode>>,
) -> ParseResult<ParseNode> {
Ok(ParseNode::Op {
mode: ctx.parser.mode,
limits: false,
always_handle_sup_sub: None,
suppress_base_shift: None,
parent_is_sup_sub: false,
symbol: false,
name: Some(ctx.func_name.clone()),
body: None,
loc: None,
})
}
fn handle_op_text_limits(
ctx: &mut FunctionContext,
_args: Vec<ParseNode>,
_opt_args: Vec<Option<ParseNode>>,
) -> ParseResult<ParseNode> {
Ok(ParseNode::Op {
mode: ctx.parser.mode,
limits: true,
always_handle_sup_sub: None,
suppress_base_shift: None,
parent_is_sup_sub: false,
symbol: false,
name: Some(ctx.func_name.clone()),
body: None,
loc: None,
})
}
fn handle_op_symbol_nolimits(
ctx: &mut FunctionContext,
_args: Vec<ParseNode>,
_opt_args: Vec<Option<ParseNode>>,
) -> ParseResult<ParseNode> {
Ok(ParseNode::Op {
mode: ctx.parser.mode,
limits: false,
always_handle_sup_sub: None,
suppress_base_shift: None,
parent_is_sup_sub: false,
symbol: true,
name: Some(ctx.func_name.clone()),
body: None,
loc: None,
})
}
fn handle_mathop(
ctx: &mut FunctionContext,
args: Vec<ParseNode>,
_opt_args: Vec<Option<ParseNode>>,
) -> ParseResult<ParseNode> {
let body = ParseNode::ord_argument(args.into_iter().next().unwrap());
Ok(ParseNode::Op {
mode: ctx.parser.mode,
limits: false,
always_handle_sup_sub: None,
suppress_base_shift: None,
parent_is_sup_sub: false,
symbol: false,
name: None,
body: Some(body),
loc: None,
})
}