1use crate::{ParseResult, Parser, ParserExt, ParserHandle, ParserOutput, ParserRegistry};
2use regex::{Captures, Regex};
3
4pub mod shorthand {
5 use super::*;
6
7 pub fn template(
8 parser: ParserHandle,
9 rule: Option<String>,
10 content: impl ToString,
11 ) -> ParserHandle {
12 TemplateParser::new(parser, rule, content).into_handle()
13 }
14}
15
16pub struct TemplateParser {
17 parser: ParserHandle,
18 rule: Option<String>,
19 content: String,
20}
21
22impl TemplateParser {
23 pub fn new(parser: ParserHandle, rule: Option<String>, content: impl ToString) -> Self {
24 Self {
25 parser,
26 rule,
27 content: content.to_string(),
28 }
29 }
30}
31
32impl Parser for TemplateParser {
33 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
34 let (input, result) = self.parser.parse(registry, input)?;
35 let content = if let Some(value) = result.read::<String>() {
36 self.content.replace("@{}@", &value)
37 } else if let Some(list) = result.read::<Vec<ParserOutput>>() {
38 Regex::new(r"@(>|<)\{([^\}]*)\}\[([^\]@]*)\]\{([^\}]*)\}(\[(\d+)\])?@")
39 .expect("Expected valid regex")
40 .replace_all(&self.content, |caps: &Captures| -> String {
41 let ordering = caps.get(1).unwrap().as_str();
42 let prefix = caps.get(2).unwrap().as_str();
43 let delimiter = caps.get(3).unwrap().as_str();
44 let suffix = caps.get(4).unwrap().as_str();
45 let mut result = String::default();
46 if let Some(index) = caps.get(6) {
47 let index = index.as_str().parse::<usize>().unwrap();
48 result.push_str(prefix);
49 let item = list
50 .get(index)
51 .unwrap_or_else(|| {
52 panic!("Template parsing result list has no item at {index} index!")
53 })
54 .read::<String>()
55 .unwrap_or_else(|| {
56 panic!("Template parsing result list item {index} is not String!")
57 });
58 result.push_str(item.as_str());
59 result.push_str(suffix);
60 } else if ordering == ">" {
61 for (index, item) in list.iter().enumerate() {
62 if index > 0 {
63 result.push_str(delimiter);
64 }
65 result.push_str(prefix);
66 let item = item.read::<String>().unwrap_or_else(|| {
67 panic!("Template parsing result list item {index} is not String!")
68 });
69 result.push_str(item.as_str());
70 result.push_str(suffix);
71 }
72 } else if ordering == "<" {
73 for (index, item) in list.iter().rev().enumerate() {
74 if index > 0 {
75 result.push_str(delimiter);
76 }
77 result.push_str(prefix);
78 let item = item.read::<String>().unwrap_or_else(|| {
79 panic!("Template parsing result list item {index} is not String!")
80 });
81 result.push_str(item.as_str());
82 result.push_str(suffix);
83 }
84 }
85 result
86 })
87 .to_string()
88 } else {
89 return Err("Template parsing result is not String or Vec<ParserOutput>!".into());
90 };
91 if let Some(rule) = self.rule.as_ref() {
92 let (rest, result) = registry.parse(rule, &content)?;
93 if rest.is_empty() {
94 Ok((input, result))
95 } else {
96 Err("Templating content parsing did not consumed all source!".into())
97 }
98 } else {
99 Ok((input, ParserOutput::new(content).ok().unwrap()))
100 }
101 }
102
103 fn extend(&self, parser: ParserHandle) {
104 self.parser.extend(parser);
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::{
111 ParserOutput, ParserRegistry,
112 shorthand::{inject, lit, map, number_int, prefix, seq_del, source, template, ws},
113 template::TemplateParser,
114 };
115
116 fn is_async<T: Send + Sync>() {}
117
118 #[test]
119 fn test_template() {
120 is_async::<TemplateParser>();
121
122 let registry = ParserRegistry::default()
123 .with_parser(
124 "value",
125 map(prefix(number_int(), lit("value:")), |value: String| {
126 value.parse::<i32>().unwrap()
127 }),
128 )
129 .with_parser(
130 "add",
131 map(
132 seq_del(lit("+"), [inject("value"), inject("value")]),
133 |mut values: Vec<ParserOutput>| {
134 let b = values.remove(1).consume::<i32>().ok().unwrap();
135 let a = values.remove(0).consume::<i32>().ok().unwrap();
136 a + b
137 },
138 ),
139 )
140 .with_parser(
141 "sub",
142 map(
143 seq_del(lit("-"), [inject("value"), inject("value")]),
144 |mut values: Vec<ParserOutput>| {
145 let b = values.remove(1).consume::<i32>().ok().unwrap();
146 let a = values.remove(0).consume::<i32>().ok().unwrap();
147 a - b
148 },
149 ),
150 )
151 .with_parser(
152 "mul",
153 map(
154 seq_del(lit("*"), [inject("value"), inject("value")]),
155 |mut values: Vec<ParserOutput>| {
156 let b = values.remove(1).consume::<i32>().ok().unwrap();
157 let a = values.remove(0).consume::<i32>().ok().unwrap();
158 a * b
159 },
160 ),
161 )
162 .with_parser(
163 "template_value",
164 template(source(number_int()), Some("value".to_owned()), "value:@{}@"),
165 )
166 .with_parser(
167 "template_add",
168 template(
169 seq_del(
170 ws(),
171 [
172 source(inject("template_value")),
173 source(inject("template_value")),
174 ],
175 ),
176 Some("add".to_owned()),
177 "@>{value:}[+]{}@",
178 ),
179 )
180 .with_parser(
181 "template_sub",
182 template(
183 seq_del(
184 ws(),
185 [
186 source(inject("template_value")),
187 source(inject("template_value")),
188 ],
189 ),
190 Some("sub".to_owned()),
191 "@<{value:}[-]{}@",
192 ),
193 )
194 .with_parser(
195 "template_mul",
196 template(
197 seq_del(
198 ws(),
199 [
200 source(inject("template_value")),
201 source(inject("template_value")),
202 ],
203 ),
204 Some("mul".to_owned()),
205 "value:@>{}[]{}[0]@*value:@>{}[]{}[1]@",
206 ),
207 )
208 .with_parser(
209 "template_output",
210 template(source(inject("template_value")), None, "#@{}@"),
211 );
212
213 let (rest, result) = registry.parse("value", "value:42").unwrap();
214 assert_eq!(rest, "");
215 assert_eq!(result.consume::<i32>().ok().unwrap(), 42);
216
217 let (rest, result) = registry.parse("add", "value:40+value:2").unwrap();
218 assert_eq!(rest, "");
219 assert_eq!(result.consume::<i32>().ok().unwrap(), 42);
220
221 let (rest, result) = registry.parse("sub", "value:40-value:2").unwrap();
222 assert_eq!(rest, "");
223 assert_eq!(result.consume::<i32>().ok().unwrap(), 38);
224
225 let (rest, result) = registry.parse("mul", "value:6*value:4").unwrap();
226 assert_eq!(rest, "");
227 assert_eq!(result.consume::<i32>().ok().unwrap(), 24);
228
229 let (rest, result) = registry.parse("template_value", "42").unwrap();
230 assert_eq!(rest, "");
231 assert_eq!(result.consume::<i32>().ok().unwrap(), 42);
232
233 let (rest, result) = registry.parse("template_add", "40 2").unwrap();
234 assert_eq!(rest, "");
235 assert_eq!(result.consume::<i32>().ok().unwrap(), 42);
236
237 let (rest, result) = registry.parse("template_sub", "2 40").unwrap();
238 assert_eq!(rest, "");
239 assert_eq!(result.consume::<i32>().ok().unwrap(), 38);
240
241 let (rest, result) = registry.parse("template_mul", "6 4").unwrap();
242 assert_eq!(rest, "");
243 assert_eq!(result.consume::<i32>().ok().unwrap(), 24);
244
245 let (rest, result) = registry.parse("template_output", "42").unwrap();
246 assert_eq!(rest, "");
247 assert_eq!(result.consume::<String>().ok().unwrap(), "#42");
248 }
249}