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