1use tokio::task::yield_now;
6
7use crate::state::{State, OpenNode};
8use crate::state::OpenNodeType;
9use crate::{Parameter, Warning, WarningMessage, Node};
10
11
12pub async fn parse_parameter_name_end(state: &mut State) {
13 let stack_length = state.stack.len();
14 if stack_length > 0 {
15 if let OpenNode {
16 type_:
17 OpenNodeType::Template {
18 name: Some(_),
19 parameters,
20 },
21 ..
22 } = &mut state.stack[stack_length - 1]
23 {
24 let parameters_length = parameters.len();
25 let name = &mut parameters[parameters_length - 1].name;
26 if name.is_none() {
27 crate::state::flush(
28 &mut state.nodes,
29 state.flushed_position,
30 crate::state::skip_whitespace_backwards(state.wiki_text.clone(), state.scan_position).await,
31 state.wiki_text.clone(),
32 ).await;
33 state.flushed_position =
34 crate::state::skip_whitespace_forwards(state.wiki_text.clone(), state.scan_position + 1).await;
35 state.scan_position = state.flushed_position;
36 *name = Some(std::mem::take(&mut state.nodes));
37 return;
38 }
39 }
40 }
41 state.scan_position += 1;
42 yield_now().await;
43}
44
45pub async fn parse_parameter_separator(state: &mut State) {
46 match state.stack.last_mut() {
47 Some(OpenNode {
48 type_: OpenNodeType::Parameter { default, name },
49 ..
50 }) => {
51 if name.is_none() {
52 let position =
53 crate::state::skip_whitespace_backwards(state.wiki_text.clone(), state.scan_position).await;
54 crate::state::flush(
55 &mut state.nodes,
56 state.flushed_position,
57 position,
58 state.wiki_text.clone(),
59 ).await;
60 *name = Some(std::mem::take(&mut state.nodes));
61 } else {
62 crate::state::flush(
63 &mut state.nodes,
64 state.flushed_position,
65 state.scan_position,
66 state.wiki_text.clone(),
67 ).await;
68 *default = Some(std::mem::take(&mut state.nodes));
69 state.warnings.push(Warning {
70 end: state.scan_position + 1,
71 message: WarningMessage::UselessTextInParameter,
72 start: state.scan_position,
73 });
74 }
75 state.scan_position += 1;
76 state.flushed_position = state.scan_position;
77 }
78 _ => unreachable!(),
79 }
80}
81
82pub async fn parse_template_end(state: &mut State) {
83 match state.stack.pop() {
84 Some(OpenNode {
85 nodes,
86 start,
87 type_: OpenNodeType::Parameter { default, name },
88 }) => if state.get_byte(state.scan_position + 2).await == Some(b'}') {
89 if let Some(name) = name {
90 let start_position = state.scan_position;
91 state.flush(start_position).await;
92 let nodes = std::mem::replace(&mut state.nodes, nodes);
93 state.nodes.push(Node::Parameter {
94 default: Some(default.unwrap_or(nodes)),
95 end: state.scan_position,
96 name,
97 start,
98 });
99 } else {
100 let start_position = state.skip_whitespace_backwards(state.scan_position).await;
101 state.flush(start_position).await;
102 let nodes = std::mem::replace(&mut state.nodes, nodes);
103 state.nodes.push(Node::Parameter {
104 default: None,
105 end: state.scan_position,
106 name: nodes,
107 start,
108 });
109 }
110 state.scan_position += 3;
111 state.flushed_position = state.scan_position;
112 } else {
113 state.warnings.push(Warning {
114 end: state.scan_position + 2,
115 message: WarningMessage::UnexpectedEndTagRewinding,
116 start: state.scan_position,
117 });
118 state.rewind(nodes, start);
119 },
120 Some(OpenNode {
121 nodes,
122 start,
123 type_:
124 OpenNodeType::Template {
125 name,
126 mut parameters,
127 },
128 }) => {
129 let position = state.skip_whitespace_backwards(state.scan_position).await;
130 state.flush(position).await;
131 state.scan_position += 2;
132 state.flushed_position = state.scan_position;
133 let name = match name {
134 None => std::mem::replace(&mut state.nodes, nodes),
135 Some(name) => {
136 let parameters_length = parameters.len();
137 let parameter = &mut parameters[parameters_length - 1];
138 parameter.end = position;
139 parameter.value = std::mem::replace(&mut state.nodes, nodes);
140 name
141 }
142 };
143 state.nodes.push(Node::Template {
144 end: state.scan_position,
145 name,
146 parameters,
147 start,
148 });
149 }
150 Some(OpenNode { nodes, start, .. }) => {
151 state.warnings.push(Warning {
152 end: state.scan_position + 2,
153 message: WarningMessage::UnexpectedEndTagRewinding,
154 start: state.scan_position,
155 });
156 state.rewind(nodes, start);
157 }
158 _ => {
159 state.warnings.push(Warning {
160 end: state.scan_position + 2,
161 message: WarningMessage::UnexpectedEndTag,
162 start: state.scan_position,
163 });
164 state.scan_position += 2;
165 }
166 }
167}
168
169pub async fn parse_template_separator(state: &mut State) {
170 match state.stack.last_mut() {
171 Some(OpenNode {
172 type_: OpenNodeType::Template { name, parameters },
173 ..
174 }) => {
175 let position = crate::state::skip_whitespace_backwards(state.wiki_text.clone(), state.scan_position).await;
176 crate::state::flush(
177 &mut state.nodes,
178 state.flushed_position,
179 position,
180 state.wiki_text.clone(),
181 ).await;
182 state.flushed_position =
183 crate::state::skip_whitespace_forwards(state.wiki_text.clone(), state.scan_position + 1).await;
184 state.scan_position = state.flushed_position;
185 if name.is_none() {
186 *name = Some(std::mem::take(&mut state.nodes));
187 } else {
188 let parameters_length = parameters.len();
189 let parameter = &mut parameters[parameters_length - 1];
190 parameter.end = position;
191 parameter.value = std::mem::take(&mut state.nodes);
192 }
193 parameters.push(Parameter {
194 end: 0,
195 name: None,
196 start: state.scan_position,
197 value: vec![],
198 });
199 }
200 _ => unreachable!(),
201 }
202 yield_now().await;
203}
204
205pub async fn parse_template_start(state: &mut State) {
206 let scan_position = state.scan_position;
207 if state.get_byte(state.scan_position + 2).await == Some(b'{') {
208 let position = state.skip_whitespace_forwards(scan_position + 3).await;
209 state.push_open_node(
210 OpenNodeType::Parameter {
211 default: None,
212 name: None,
213 },
214 position,
215 ).await;
216 } else {
217 let position = state.skip_whitespace_forwards(scan_position + 2).await;
218 state.push_open_node(
219 OpenNodeType::Template {
220 name: None,
221 parameters: vec![],
222 },
223 position,
224 ).await;
225 }
226}