ratex_parser/functions/
left_right.rs1use std::collections::HashMap;
2
3use crate::error::{ParseError, ParseResult};
4use crate::functions::{define_function_full, FunctionContext, FunctionSpec};
5use crate::parse_node::ParseNode;
6
7pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
8 define_function_full(
9 map,
10 &["\\left"],
11 "leftright",
12 1,
13 0,
14 None,
15 false,
16 false,
17 true,
18 false,
19 true, handle_left,
21 );
22
23 define_function_full(
24 map,
25 &["\\right"],
26 "leftright-right",
27 1,
28 0,
29 None,
30 false,
31 false,
32 true,
33 false,
34 true, handle_right,
36 );
37
38 define_function_full(
39 map,
40 &["\\middle"],
41 "middle",
42 1,
43 0,
44 None,
45 false,
46 false,
47 true,
48 false,
49 true,
50 handle_middle,
51 );
52}
53
54fn handle_left(
55 ctx: &mut FunctionContext,
56 args: Vec<ParseNode>,
57 _opt_args: Vec<Option<ParseNode>>,
58) -> ParseResult<ParseNode> {
59 let delim = get_delim_text(&args[0])?;
60
61 ctx.parser.leftright_depth += 1;
62 let body = ctx.parser.parse_expression(false, None)?;
63 ctx.parser.leftright_depth -= 1;
64
65 ctx.parser.expect("\\right", false)?;
67 let right_node = ctx.parser.parse_function(None, None)?;
69
70 let (right, right_color) = match right_node {
71 Some(ParseNode::LeftRightRight { delim, color, .. }) => (delim, color),
72 _ => {
73 return Err(ParseError::msg("Expected \\right after \\left"));
74 }
75 };
76
77 Ok(ParseNode::LeftRight {
78 mode: ctx.parser.mode,
79 body,
80 left: delim,
81 right,
82 right_color,
83 loc: None,
84 })
85}
86
87fn handle_right(
88 ctx: &mut FunctionContext,
89 args: Vec<ParseNode>,
90 _opt_args: Vec<Option<ParseNode>>,
91) -> ParseResult<ParseNode> {
92 let delim = get_delim_text(&args[0])?;
93
94 Ok(ParseNode::LeftRightRight {
95 mode: ctx.parser.mode,
96 delim,
97 color: None,
98 loc: None,
99 })
100}
101
102fn handle_middle(
103 ctx: &mut FunctionContext,
104 args: Vec<ParseNode>,
105 _opt_args: Vec<Option<ParseNode>>,
106) -> ParseResult<ParseNode> {
107 let delim = get_delim_text(&args[0])?;
108
109 if ctx.parser.leftright_depth <= 0 {
110 return Err(ParseError::msg(
111 "\\middle must be within \\left and \\right",
112 ));
113 }
114
115 Ok(ParseNode::Middle {
116 mode: ctx.parser.mode,
117 delim,
118 loc: None,
119 })
120}
121
122fn get_delim_text(node: &ParseNode) -> ParseResult<String> {
123 if let Some(text) = node.symbol_text() {
124 return Ok(text.to_string());
125 }
126 Err(ParseError::msg(format!(
127 "Invalid delimiter type '{}'",
128 node.type_name(),
129 )))
130}