1use std::error::Error;
17use std::str::Chars;
18
19use abortable_parser::iter::SliceIter;
20use abortable_parser::Result as ParseResult;
21
22use crate::ast::*;
23use crate::iter;
24use crate::parse;
25use crate::tokenizer;
26
27pub trait FormatRenderer {
28 fn render(&self, pos: &Position) -> Result<String, Box<dyn Error>>;
29}
30
31pub type TemplateResult = Result<Vec<TemplatePart>, Box<dyn Error>>;
32
33pub trait TemplateParser {
34 fn parse(&self, input: &str) -> TemplateResult;
35}
36
37pub struct SimpleTemplate();
38
39impl SimpleTemplate {
40 pub fn new() -> Self {
41 Self()
42 }
43}
44
45impl TemplateParser for SimpleTemplate {
46 fn parse(&self, input: &str) -> TemplateResult {
47 let mut result = Vec::new();
48 let mut count = 0;
49 let mut should_escape = false;
50 let mut buf: Vec<char> = Vec::new();
51 for c in input.chars() {
52 if c == '@' && !should_escape {
53 result.push(TemplatePart::Str(buf));
54 buf = Vec::new();
55 result.push(TemplatePart::PlaceHolder(count));
57 count += 1;
58 } else if c == '\\' && !should_escape {
59 should_escape = true;
60 continue;
61 } else {
62 buf.push(c);
63 }
64 should_escape = false;
65 }
66 if buf.len() != 0 {
67 result.push(TemplatePart::Str(buf));
68 }
69 Ok(result)
70 }
71}
72
73pub struct ExpressionTemplate();
74
75impl ExpressionTemplate {
76 pub fn new() -> Self {
77 ExpressionTemplate()
78 }
79
80 fn consume_expr(&self, iter: &mut Chars) -> Result<Expression, Box<dyn Error>> {
81 let mut result = String::new();
82 let mut brace_count = 0;
83 loop {
84 let c = match iter.next() {
85 Some(c) => c,
86 None => break,
87 };
88 if c == '{' {
89 brace_count += 1;
90 if brace_count == 1 {
92 continue;
93 }
94 }
95 if c == '}' {
96 brace_count -= 1;
97 }
98 if brace_count == 0 {
100 break;
101 }
102 result.push(c);
103 }
104 let str_iter = iter::OffsetStrIter::new(&result);
105 let toks = match tokenizer::tokenize(str_iter, None) {
106 Ok(toks) => toks,
107 Err(_e) => panic!("TODO(jwall): make this not a thing"),
108 };
109
110 let i = SliceIter::new(&toks);
111 match parse::expression(i) {
112 ParseResult::Complete(_, expr) => Ok(expr),
113 ParseResult::Abort(_e) | ParseResult::Fail(_e) => {
114 panic!("TODO(jwall): make this not a thing")
115 }
116 ParseResult::Incomplete(_ei) => panic!("TODO(jwall): make this not a thing"),
117 }
118 }
119}
120
121impl TemplateParser for ExpressionTemplate {
122 fn parse(&self, input: &str) -> TemplateResult {
123 let mut parts = Vec::new();
124 let mut should_escape = false;
125 let mut iter = input.chars();
126 let mut buf: Vec<char> = Vec::new();
127 loop {
128 let c = match iter.next() {
129 Some(c) => c,
130 None => break,
131 };
132 if c == '@' && !should_escape {
133 parts.push(TemplatePart::Str(buf));
134 buf = Vec::new();
135 parts.push(TemplatePart::Expression(self.consume_expr(&mut iter)?));
137 } else if c == '\\' && !should_escape {
138 should_escape = true;
139 continue;
140 } else {
141 buf.push(c);
142 }
143 should_escape = false;
144 }
145 if buf.len() != 0 {
146 parts.push(TemplatePart::Str(buf));
147 }
148 Ok(parts)
149 }
150}