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, 0, None,
13 false, false, true, false,
14 true, handle_left,
16 );
17
18 define_function_full(
19 map,
20 &["\\right"],
21 "leftright-right",
22 1, 0, None,
23 false, false, true, false,
24 true, handle_right,
26 );
27
28 define_function_full(
29 map,
30 &["\\middle"],
31 "middle",
32 1, 0, None,
33 false, false, true, false,
34 true,
35 handle_middle,
36 );
37}
38
39fn handle_left(
40 ctx: &mut FunctionContext,
41 args: Vec<ParseNode>,
42 _opt_args: Vec<Option<ParseNode>>,
43) -> ParseResult<ParseNode> {
44 let delim = get_delim_text(&args[0])?;
45
46 ctx.parser.leftright_depth += 1;
47 let body = ctx.parser.parse_expression(false, None)?;
48 ctx.parser.leftright_depth -= 1;
49
50 ctx.parser.expect("\\right", false)?;
52 let right_node = ctx.parser.parse_function(None, None)?;
54
55 let (right, right_color) = match right_node {
56 Some(ParseNode::LeftRightRight { delim, color, .. }) => (delim, color),
57 _ => {
58 return Err(ParseError::msg("Expected \\right after \\left"));
59 }
60 };
61
62 Ok(ParseNode::LeftRight {
63 mode: ctx.parser.mode,
64 body,
65 left: delim,
66 right,
67 right_color,
68 loc: None,
69 })
70}
71
72fn handle_right(
73 ctx: &mut FunctionContext,
74 args: Vec<ParseNode>,
75 _opt_args: Vec<Option<ParseNode>>,
76) -> ParseResult<ParseNode> {
77 let delim = get_delim_text(&args[0])?;
78
79 Ok(ParseNode::LeftRightRight {
80 mode: ctx.parser.mode,
81 delim,
82 color: None,
83 loc: None,
84 })
85}
86
87fn handle_middle(
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 if ctx.parser.leftright_depth <= 0 {
95 return Err(ParseError::msg(
96 "\\middle must be within \\left and \\right",
97 ));
98 }
99
100 Ok(ParseNode::Middle {
101 mode: ctx.parser.mode,
102 delim,
103 loc: None,
104 })
105}
106
107fn get_delim_text(node: &ParseNode) -> ParseResult<String> {
108 if let Some(text) = node.symbol_text() {
109 return Ok(text.to_string());
110 }
111 Err(ParseError::msg(format!(
112 "Invalid delimiter type '{}'",
113 node.type_name(),
114 )))
115}