rustbasic_core/template/
parser.rs1use super::lexer::Token;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum Expr {
5 Path(Vec<String>),
6 StringLiteral(String),
7 NumberLiteral(f64),
8 BooleanLiteral(bool),
9 Comparison {
10 left: Box<Expr>,
11 op: String,
12 right: Box<Expr>,
13 },
14 Filter {
15 expr: Box<Expr>,
16 filter_name: String,
17 args: Vec<Expr>,
18 },
19}
20
21#[derive(Debug, Clone, PartialEq)]
22pub enum Node {
23 Text(String),
24 Variable(Expr),
25 If {
26 condition: Expr,
27 then_branch: Vec<Node>,
28 else_branch: Option<Vec<Node>>,
29 },
30 For {
31 item: String,
32 iterator: Expr,
33 body: Vec<Node>,
34 },
35}
36
37pub struct Parser {
38 tokens: Vec<Token>,
39 pos: usize,
40}
41
42impl Parser {
43 pub fn new(tokens: Vec<Token>) -> Self {
44 Self { tokens, pos: 0 }
45 }
46
47 fn peek(&self) -> Option<Token> {
48 if self.pos < self.tokens.len() {
49 Some(self.tokens[self.pos].clone())
50 } else {
51 None
52 }
53 }
54
55 fn advance(&mut self) -> Option<Token> {
56 if self.pos < self.tokens.len() {
57 let t = &self.tokens[self.pos];
58 self.pos += 1;
59 Some(t.clone())
60 } else {
61 None
62 }
63 }
64
65 fn expect(&mut self, token: Token) -> Result<(), String> {
66 if let Some(t) = self.peek() {
67 if t == token {
68 self.advance();
69 Ok(())
70 } else {
71 Err(format!("Expected token {:?}, found {:?}", token, t))
72 }
73 } else {
74 Err(format!("Expected token {:?}, reached EOF", token))
75 }
76 }
77
78 pub fn parse(&mut self) -> Result<Vec<Node>, String> {
79 let mut nodes = Vec::new();
80 while self.pos < self.tokens.len() {
81 if let Some(token) = self.peek() {
82 match token {
83 Token::Text(text) => {
84 nodes.push(Node::Text(text));
85 self.advance();
86 }
87 Token::VariableStart => {
88 self.advance(); let expr = self.parse_expr()?;
90 self.expect(Token::VariableEnd)?;
91 nodes.push(Node::Variable(expr));
92 }
93 Token::BlockStart => {
94 self.advance(); let node = self.parse_block()?;
96 nodes.push(node);
97 }
98 _ => {
99 return Err(format!("Unexpected token in template body: {:?}", token));
100 }
101 }
102 }
103 }
104 Ok(nodes)
105 }
106
107 fn parse_block(&mut self) -> Result<Node, String> {
108 if let Some(Token::Identifier(keyword)) = self.peek() {
109 match keyword.as_str() {
110 "if" => {
111 self.advance(); let condition = self.parse_expr()?;
113 self.expect(Token::BlockEnd)?;
114
115 let mut then_branch = Vec::new();
116 let mut else_branch = None;
117
118 while self.pos < self.tokens.len() {
119 if let Some(Token::BlockStart) = self.peek() {
120 if let Some(Token::Identifier(ident)) = self.tokens.get(self.pos + 1) {
121 if ident == "else" {
122 self.advance(); self.advance(); self.expect(Token::BlockEnd)?;
125
126 let mut else_nodes = Vec::new();
127 while self.pos < self.tokens.len() {
128 if let Some(Token::BlockStart) = self.peek() {
129 if let Some(Token::Identifier(inner_ident)) = self.tokens.get(self.pos + 1) {
130 if inner_ident == "endif" {
131 break;
132 }
133 }
134 }
135 if let Some(Token::Text(text)) = self.peek() {
136 else_nodes.push(Node::Text(text));
137 self.advance();
138 } else if let Some(Token::VariableStart) = self.peek() {
139 self.advance();
140 let expr = self.parse_expr()?;
141 self.expect(Token::VariableEnd)?;
142 else_nodes.push(Node::Variable(expr));
143 } else if let Some(Token::BlockStart) = self.peek() {
144 self.advance();
145 else_nodes.push(self.parse_block()?);
146 }
147 }
148 else_branch = Some(else_nodes);
149 continue;
150 } else if ident == "endif" {
151 self.advance(); self.advance(); self.expect(Token::BlockEnd)?;
154 break;
155 }
156 }
157 }
158
159 if let Some(Token::Text(text)) = self.peek() {
160 then_branch.push(Node::Text(text));
161 self.advance();
162 } else if let Some(Token::VariableStart) = self.peek() {
163 self.advance();
164 let expr = self.parse_expr()?;
165 self.expect(Token::VariableEnd)?;
166 then_branch.push(Node::Variable(expr));
167 } else if let Some(Token::BlockStart) = self.peek() {
168 self.advance();
169 then_branch.push(self.parse_block()?);
170 }
171 }
172
173 Ok(Node::If {
174 condition,
175 then_branch,
176 else_branch,
177 })
178 }
179 "for" => {
180 self.advance(); let item = if let Some(Token::Identifier(name)) = self.advance() {
182 name
183 } else {
184 return Err("Expected item identifier in for loop".to_string());
185 };
186
187 if let Some(Token::Identifier(keyword_in)) = self.advance() {
188 if keyword_in != "in" {
189 return Err(format!("Expected 'in', found '{}'", keyword_in));
190 }
191 } else {
192 return Err("Expected 'in' keyword in for loop".to_string());
193 }
194
195 let iterator = self.parse_expr()?;
196 self.expect(Token::BlockEnd)?;
197
198 let mut body = Vec::new();
199 while self.pos < self.tokens.len() {
200 if let Some(Token::BlockStart) = self.peek() {
201 if let Some(Token::Identifier(ident)) = self.tokens.get(self.pos + 1) {
202 if ident == "endfor" {
203 self.advance(); self.advance(); self.expect(Token::BlockEnd)?;
206 break;
207 }
208 }
209 }
210
211 if let Some(Token::Text(text)) = self.peek() {
212 body.push(Node::Text(text));
213 self.advance();
214 } else if let Some(Token::VariableStart) = self.peek() {
215 self.advance();
216 let expr = self.parse_expr()?;
217 self.expect(Token::VariableEnd)?;
218 body.push(Node::Variable(expr));
219 } else if let Some(Token::BlockStart) = self.peek() {
220 self.advance();
221 body.push(self.parse_block()?);
222 }
223 }
224
225 Ok(Node::For {
226 item,
227 iterator,
228 body,
229 })
230 }
231 other => Err(format!("Unknown block keyword: {}", other)),
232 }
233 } else {
234 Err("Expected keyword at start of block statement".to_string())
235 }
236 }
237
238 fn parse_expr(&mut self) -> Result<Expr, String> {
239 let mut left = self.parse_comparison_expr()?;
240
241 while let Some(Token::Operator(op)) = self.peek() {
242 if op == "|" {
243 self.advance(); if let Some(Token::Identifier(filter_name)) = self.advance() {
245 let mut args = Vec::new();
246 if let Some(Token::Operator(paren)) = self.peek() {
247 if paren == "(" {
248 self.advance(); while self.pos < self.tokens.len() {
250 if let Some(Token::Operator(close_paren)) = self.peek() {
251 if close_paren == ")" {
252 self.advance(); break;
254 }
255 }
256 args.push(self.parse_expr()?);
257 if let Some(Token::Comma) = self.peek() {
258 self.advance();
259 }
260 }
261 }
262 }
263 left = Expr::Filter {
264 expr: Box::new(left),
265 filter_name,
266 args,
267 };
268 } else {
269 return Err("Expected filter name after '|'".to_string());
270 }
271 } else {
272 break;
273 }
274 }
275
276 Ok(left)
277 }
278
279 fn parse_comparison_expr(&mut self) -> Result<Expr, String> {
280 let left = self.parse_primary_expr()?;
281
282 if let Some(Token::Operator(op)) = self.peek() {
283 if op == "==" || op == "!=" || op == "<" || op == ">" || op == "<=" || op == ">=" {
284 self.advance(); let right = self.parse_primary_expr()?;
286 return Ok(Expr::Comparison {
287 left: Box::new(left),
288 op,
289 right: Box::new(right),
290 });
291 }
292 }
293
294 Ok(left)
295 }
296
297 fn parse_primary_expr(&mut self) -> Result<Expr, String> {
298 if let Some(token) = self.peek() {
299 match token {
300 Token::StringLiteral(s) => {
301 self.advance();
302 Ok(Expr::StringLiteral(s))
303 }
304 Token::NumberLiteral(n) => {
305 self.advance();
306 Ok(Expr::NumberLiteral(n))
307 }
308 Token::Identifier(s) if s == "true" => {
309 self.advance();
310 Ok(Expr::BooleanLiteral(true))
311 }
312 Token::Identifier(s) if s == "false" => {
313 self.advance();
314 Ok(Expr::BooleanLiteral(false))
315 }
316 Token::Identifier(first_name) => {
317 self.advance();
318 let mut path = vec![first_name];
319 while let Some(Token::Dot) = self.peek() {
320 self.advance(); if let Some(Token::Identifier(field)) = self.advance() {
322 path.push(field);
323 } else {
324 return Err("Expected identifier after '.'".to_string());
325 }
326 }
327 Ok(Expr::Path(path))
328 }
329 other => Err(format!("Expected primary expression, found {:?}", other)),
330 }
331 } else {
332 Err("Expected primary expression, reached EOF".to_string())
333 }
334 }
335}