subscript_compiler/frontend/pass/
math.rs1use lazy_static::lazy_static;
7use std::iter::FromIterator;
8use std::collections::HashSet;
9use std::rc::Rc;
10use std::borrow::Cow;
11use crate::frontend::data::{
12 Atom,
13 Text,
14 Enclosure,
15 EnclosureKind,
16 INLINE_MATH_TAG,
17};
18use crate::frontend::ast::{Ann, Node, NodeEnvironment, Tag};
19
20pub static LATEX_ENVIRONMENT_NAME_LIST: &'static [&'static str] = &[
21 "equation",
22 "split",
23];
24
25lazy_static! {
26 pub static ref LATEX_ENV_NAMES: HashSet<&'static str> = {
27 HashSet::from_iter(
28 LATEX_ENVIRONMENT_NAME_LIST.to_vec()
29 )
30 };
31}
32
33
34fn to_valid_latex_math<'a>(node: Node<'a>) -> Node<'a> {
36 fn init_env<'a>(env_name: &'a str, children: Vec<Node<'a>>) -> Node<'a> {
38 Node::new_fragment(vec![
39 Node::unannotated_tag_(
40 "begin",
41 Node::Enclosure(Ann::unannotated(
42 Enclosure::new_curly_brace_(Node::unannotated_str(env_name))
43 ))
44 ),
45 Node::new_fragment(children),
46 Node::unannotated_tag_(
47 "end",
48 Node::Enclosure(Ann::unannotated(
49 Enclosure::new_curly_brace_(Node::unannotated_str(env_name))
50 ))
51 ),
52 ])
53 }
54 fn f<'a>(env: NodeEnvironment, x: Node<'a>) -> Node<'a> {
56 match x {
57 Node::Tag(tag) if LATEX_ENV_NAMES.contains(tag.name()) => {
58 let env_name = *LATEX_ENV_NAMES.get(tag.name()).unwrap();
59 init_env(
60 env_name,
61 tag.children
62 )
63 }
64 Node::Tag(mut tag) => {
65 tag.children = tag.children
66 .into_iter()
67 .collect();
69 Node::Tag(tag)
70 }
71 x => x,
72 }
73 }
74 node.transform(NodeEnvironment::default(), Rc::new(f))
76}
77
78
79pub fn latex_pass<'a>(node: Node<'a>) -> Node<'a> {
81 match node {
82 Node::Tag(tag) if tag.has_name("equation") => {
83 let node = tag.children
84 .into_iter()
85 .flat_map(Node::unblock)
86 .map(to_valid_latex_math)
87 .map(|x| x.to_string())
88 .collect::<Vec<_>>()
89 .join("");
90 let start = "\\begin{equation}\\begin{split}";
91 let end = "\\end{split}\\end{equation}";
92 Node::String(Ann::unannotated(Cow::Owned(format!(
93 "\\[{}{}{}\\]",
94 start,
95 node,
96 end,
97 ))))
98 }
99 Node::Tag(tag) if tag.has_name(INLINE_MATH_TAG) => {
100 let node = tag.children
101 .into_iter()
102 .flat_map(Node::unblock)
103 .map(to_valid_latex_math)
104 .map(|x| x.to_string())
105 .collect::<Vec<_>>()
106 .join("");
107 Node::String(Ann::unannotated(Cow::Owned(format!(
108 "\\({}\\)",
109 node,
110 ))))
111 }
112 Node::Tag(mut tag) => {
113 tag.children = tag.children
114 .into_iter()
115 .map(latex_pass)
116 .collect();
117 Node::Tag(tag)
118 }
119 Node::Enclosure(mut block) => {
120 block.data.children = block.data.children
121 .into_iter()
122 .map(latex_pass)
123 .collect();
124 Node::Enclosure(block)
125 }
126 node @ Node::Ident(_) => node,
127 node @ Node::String(_) => node,
128 node @ Node::InvalidToken(_) => node,
129 }
130}
131