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