tex2typst_rs/
tex_parser_utils.rs1use crate::definitions::{TexNode, TexNodeType, TexToken, TexTokenType};
2use std::sync::LazyLock;
3
4pub static EMPTY_NODE: LazyLock<TexNode> =
5 LazyLock::new(|| TexNode::new(TexNodeType::Empty, String::new(), None, None));
6
7pub static LEFT_CURLY_BRACKET: LazyLock<TexToken> =
8 LazyLock::new(|| TexToken::new(TexTokenType::Control, "{".to_string()));
9pub static RIGHT_CURLY_BRACKET: LazyLock<TexToken> =
10 LazyLock::new(|| TexToken::new(TexTokenType::Control, "}".to_string()));
11
12pub static LEFT_SQUARE_BRACKET: LazyLock<TexToken> =
13 LazyLock::new(|| TexToken::new(TexTokenType::Element, "[".to_string()));
14pub static RIGHT_SQUARE_BRACKET: LazyLock<TexToken> =
15 LazyLock::new(|| TexToken::new(TexTokenType::Element, "]".to_string()));
16
17pub fn eat_whitespaces(tokens: &[TexToken], start: usize) -> usize {
18 let mut pos = start;
19 while pos < tokens.len() && matches!(tokens[pos].token_type, TexTokenType::Space | TexTokenType::Newline) {
20 pos += 1;
21 }
22 tokens[start..pos].len()
23}
24
25pub fn eat_parenthesis(tokens: &[TexToken], start: usize) -> Option<&TexToken> {
26 let first_token = &tokens[start];
27 if first_token.token_type == TexTokenType::Element
28 && ["(", ")", "[", "]", "|", "\\{", "\\}", "."].contains(&first_token.value.as_str())
29 {
30 Some(first_token)
31 } else if first_token.token_type == TexTokenType::Command
32 && ["lfloor", "rfloor", "lceil", "rceil", "langle", "rangle"].contains(&&first_token.value[1..])
33 {
34 Some(first_token)
35 } else {
36 None
37 }
38}
39
40pub fn eat_primes(tokens: &[TexToken], start: usize) -> usize {
41 let mut pos = start;
42 while pos < tokens.len() && tokens[pos] == TexToken::new(TexTokenType::Element, "'".to_string()) {
43 pos += 1;
44 }
45 pos - start
46}
47
48pub fn find_closing_match(tokens: &[TexToken], start: usize, left_token: &TexToken, right_token: &TexToken) -> isize {
49 assert!(tokens[start].eq(left_token));
50 let mut count = 1;
51 let mut pos = start + 1;
52
53 while count > 0 {
54 if pos >= tokens.len() {
55 return -1;
56 }
57 if tokens[pos].eq(left_token) {
58 count += 1;
59 } else if tokens[pos].eq(right_token) {
60 count -= 1;
61 }
62 pos += 1;
63 }
64
65 (pos - 1) as isize
66}
67
68pub static LEFT_COMMAND: LazyLock<TexToken> =
69 LazyLock::new(|| TexToken::new(TexTokenType::Command, "\\left".to_string()));
70pub static RIGHT_COMMAND: LazyLock<TexToken> =
71 LazyLock::new(|| TexToken::new(TexTokenType::Command, "\\right".to_string()));
72
73pub fn find_closing_right_command(tokens: &[TexToken], start: usize) -> isize {
74 find_closing_match(tokens, start, &LEFT_COMMAND, &RIGHT_COMMAND)
75}
76
77pub static BEGIN_COMMAND: LazyLock<TexToken> =
78 LazyLock::new(|| TexToken::new(TexTokenType::Command, "\\begin".to_string()));
79pub static END_COMMAND: LazyLock<TexToken> =
80 LazyLock::new(|| TexToken::new(TexTokenType::Command, "\\end".to_string()));
81
82pub fn find_closing_end_command(tokens: &[TexToken], start: usize) -> isize {
83 find_closing_match(tokens, start, &BEGIN_COMMAND, &END_COMMAND)
84}
85
86pub static SUB_SYMBOL: LazyLock<TexToken> = LazyLock::new(|| TexToken::new(TexTokenType::Control, "_".to_string()));
87pub static SUP_SYMBOL: LazyLock<TexToken> = LazyLock::new(|| TexToken::new(TexTokenType::Control, "^".to_string()));