1use crate::ast::*;
4use crate::error::{Error, Result, Span};
5use crate::lexer::{Token, TokenKind};
6
7pub struct Parser {
9 tokens: Vec<Token>,
10 pos: usize,
11}
12
13impl Parser {
14 pub fn new(tokens: Vec<Token>) -> Self {
15 Parser { tokens, pos: 0 }
16 }
17
18 pub fn parse(mut self) -> Result<Template> {
19 let nodes = self.parse_nodes()?;
20 self.expect_eof()?;
21 Ok(Template { nodes })
22 }
23
24 fn peek(&self) -> &Token {
25 &self.tokens[self.pos]
26 }
27
28 fn peek_kind(&self) -> &TokenKind {
29 &self.peek().kind
30 }
31
32 fn peek_span(&self) -> Span {
33 self.peek().span.clone()
34 }
35
36 fn advance(&mut self) -> &Token {
37 let tok = &self.tokens[self.pos];
38 if self.pos + 1 < self.tokens.len() {
39 self.pos += 1;
40 }
41 tok
42 }
43
44 fn expect_close(&mut self) -> Result<()> {
45 match self.peek_kind() {
46 TokenKind::Close => {
47 self.advance();
48 Ok(())
49 }
50 other => Err(Error::ParseError {
51 message: format!("Expected '}}', got {}", other),
52 span: self.peek_span(),
53 }),
54 }
55 }
56
57 fn expect_ident(&mut self) -> Result<String> {
58 match self.peek_kind().clone() {
59 TokenKind::Ident(name) => {
60 self.advance();
61 Ok(name)
62 }
63 other => Err(Error::ParseError {
64 message: format!("Expected identifier, got {}", other),
65 span: self.peek_span(),
66 }),
67 }
68 }
69
70 fn expect_string(&mut self) -> Result<String> {
71 match self.peek_kind().clone() {
72 TokenKind::StringLit(s) => {
73 self.advance();
74 Ok(s)
75 }
76 other => Err(Error::ParseError {
77 message: format!("Expected string literal, got {}", other),
78 span: self.peek_span(),
79 }),
80 }
81 }
82
83 fn expect_keyword(&mut self, expected: TokenKind) -> Result<()> {
84 if *self.peek_kind() == expected {
85 self.advance();
86 Ok(())
87 } else {
88 Err(Error::ParseError {
89 message: format!("Expected {}, got {}", expected, self.peek_kind()),
90 span: self.peek_span(),
91 })
92 }
93 }
94
95 fn expect_eof(&mut self) -> Result<()> {
96 match self.peek_kind() {
97 TokenKind::Eof => Ok(()),
98 other => Err(Error::ParseError {
99 message: format!("Expected end of template, got {}", other),
100 span: self.peek_span(),
101 }),
102 }
103 }
104
105 fn parse_nodes(&mut self) -> Result<Vec<Node>> {
108 let mut nodes: Vec<Node> = Vec::new();
109
110 loop {
111 match self.peek_kind() {
112 TokenKind::Eof | TokenKind::ContinueOpen | TokenKind::BlockClose => break,
113
114 TokenKind::RawText(_) => {
115 let TokenKind::RawText(text) = self.advance().kind.clone() else {
116 unreachable!()
117 };
118 nodes.push(Node::RawText(text));
119 }
120
121 TokenKind::CommentOpen => {
122 self.advance(); let body = match self.peek_kind().clone() {
124 TokenKind::CommentBody(b) => {
125 self.advance();
126 b
127 }
128 _ => String::new(),
129 };
130 match self.peek_kind() {
131 TokenKind::CommentClose => {
132 self.advance();
133 }
134 _ => {
135 return Err(Error::ParseError {
136 message: "Expected comment close '!}'".to_string(),
137 span: self.peek_span(),
138 });
139 }
140 }
141 nodes.push(Node::Comment(body));
142 }
143
144 TokenKind::ExprOpen => {
145 self.advance(); let expr = self.parse_expr()?;
147 self.expect_close()?;
148 nodes.push(Node::ExprTag(ExprTag { expr, raw: false }));
149 }
150
151 TokenKind::ExprOpenRaw => {
152 self.advance(); let expr = self.parse_expr()?;
154 self.expect_close()?;
155 nodes.push(Node::ExprTag(ExprTag { expr, raw: true }));
156 }
157
158 TokenKind::BlockOpen => {
159 let node = self.parse_block()?;
160 nodes.push(node);
161 }
162
163 TokenKind::SpecialOpen => {
164 let node = self.parse_special()?;
165 nodes.push(node);
166 }
167
168 other => {
169 return Err(Error::ParseError {
170 message: format!("Unexpected token {}", other),
171 span: self.peek_span(),
172 });
173 }
174 }
175 }
176
177 strip_standalone(&mut nodes);
178 Ok(nodes)
179 }
180
181 fn parse_block(&mut self) -> Result<Node> {
182 self.advance(); match self.peek_kind().clone() {
185 TokenKind::KwIf => {
186 self.advance(); let cond = self.parse_expr()?;
188 self.expect_close()?;
189 self.parse_if_block(cond)
190 }
191 TokenKind::KwEach => {
192 self.advance(); let iterable = self.parse_expr()?;
194 self.expect_keyword(TokenKind::KwAs)?;
195 let pattern = self.parse_pattern()?;
196 let index_binding = if self.peek_kind() == &TokenKind::Comma {
197 self.advance(); Some(self.expect_ident()?)
199 } else {
200 None
201 };
202 let loop_binding = if self.peek_kind() == &TokenKind::Comma {
203 self.advance(); Some(self.expect_ident()?)
205 } else {
206 None
207 };
208 self.expect_close()?;
209 self.parse_each_block(iterable, pattern, index_binding, loop_binding)
210 }
211 TokenKind::KwSnippet => {
212 self.advance(); let name = self.expect_ident()?;
214 self.expect(&TokenKind::LParen)?;
215 let params = self.parse_param_list()?;
216 self.expect(&TokenKind::RParen)?;
217 self.expect_close()?;
218 self.parse_snippet_block(name, params)
219 }
220 TokenKind::KwRaw => {
221 self.advance(); self.expect_close()?;
223 let body = match self.peek_kind().clone() {
224 TokenKind::RawBody(b) => {
225 self.advance();
226 b
227 }
228 _ => String::new(),
229 };
230 self.expect(&TokenKind::BlockClose)?;
231 self.expect_keyword(TokenKind::KwRaw)?;
232 self.expect_close()?;
233 Ok(Node::RawBlock(body))
234 }
235 other => Err(Error::ParseError {
236 message: format!("Unknown block keyword {}", other),
237 span: self.peek_span(),
238 }),
239 }
240 }
241
242 fn parse_if_block(&mut self, first_cond: Expr) -> Result<Node> {
243 let first_body = self.parse_nodes()?;
244 let mut branches = vec![IfBranch {
245 condition: first_cond,
246 body: first_body,
247 }];
248 let mut else_body: Option<Vec<Node>> = None;
249
250 loop {
251 match self.peek_kind() {
252 TokenKind::ContinueOpen => {
253 self.advance(); self.expect_keyword(TokenKind::KwElse)?;
255 if self.peek_kind() == &TokenKind::KwIf {
256 self.advance(); let cond = self.parse_expr()?;
258 self.expect_close()?;
259 let body = self.parse_nodes()?;
260 branches.push(IfBranch {
261 condition: cond,
262 body,
263 });
264 } else {
265 self.expect_close()?;
266 else_body = Some(self.parse_nodes()?);
267 }
268 }
269 TokenKind::BlockClose => {
270 self.advance(); self.expect_keyword(TokenKind::KwIf)?;
272 self.expect_close()?;
273 break;
274 }
275 other => {
276 return Err(Error::ParseError {
277 message: format!(
278 "Expected {{:else}}, {{:else if}}, or {{/if}}, got {}",
279 other
280 ),
281 span: self.peek_span(),
282 });
283 }
284 }
285 }
286
287 Ok(Node::IfBlock(IfBlock {
288 branches,
289 else_body,
290 }))
291 }
292
293 fn parse_each_block(
294 &mut self,
295 iterable: Expr,
296 pattern: Pattern,
297 index_binding: Option<String>,
298 loop_binding: Option<String>,
299 ) -> Result<Node> {
300 let body = self.parse_nodes()?;
301 let mut else_body: Option<Vec<Node>> = None;
302
303 loop {
304 match self.peek_kind() {
305 TokenKind::ContinueOpen => {
306 self.advance(); self.expect_keyword(TokenKind::KwElse)?;
308 self.expect_close()?;
309 else_body = Some(self.parse_nodes()?);
310 }
311 TokenKind::BlockClose => {
312 self.advance(); self.expect_keyword(TokenKind::KwEach)?;
314 self.expect_close()?;
315 break;
316 }
317 other => {
318 return Err(Error::ParseError {
319 message: format!("Expected {{:else}} or {{/each}}, got {}", other),
320 span: self.peek_span(),
321 });
322 }
323 }
324 }
325
326 Ok(Node::EachBlock(EachBlock {
327 iterable,
328 pattern,
329 index_binding,
330 loop_binding,
331 body,
332 else_body,
333 }))
334 }
335
336 fn parse_snippet_block(&mut self, name: String, params: Vec<String>) -> Result<Node> {
337 let body = self.parse_nodes()?;
338 match self.peek_kind() {
339 TokenKind::BlockClose => {
340 self.advance(); self.expect_keyword(TokenKind::KwSnippet)?;
342 self.expect_close()?;
343 }
344 other => {
345 return Err(Error::ParseError {
346 message: format!("Expected {{/snippet}}, got {}", other),
347 span: self.peek_span(),
348 });
349 }
350 }
351 Ok(Node::SnippetBlock(SnippetBlock { name, params, body }))
352 }
353
354 fn parse_special(&mut self) -> Result<Node> {
355 self.advance(); match self.peek_kind().clone() {
358 TokenKind::KwRender => {
359 self.advance(); let name = self.expect_ident()?;
361 self.expect(&TokenKind::LParen)?;
362 let args = self.parse_arg_list()?;
363 self.expect(&TokenKind::RParen)?;
364 self.expect_close()?;
365 Ok(Node::RenderTag(RenderTag { name, args }))
366 }
367 TokenKind::KwConst => {
368 self.advance(); let name = self.expect_ident()?;
370 self.expect(&TokenKind::Assign)?;
371 let expr = self.parse_expr()?;
372 self.expect_close()?;
373 Ok(Node::ConstTag(ConstTag { name, expr }))
374 }
375 TokenKind::KwInclude => {
376 self.advance(); let path = self.expect_string()?;
378 self.expect_close()?;
379 Ok(Node::IncludeTag(IncludeTag { path }))
380 }
381 TokenKind::KwDebug => {
382 self.advance(); let expr = if self.peek_kind() != &TokenKind::Close {
384 Some(self.parse_expr()?)
385 } else {
386 None
387 };
388 self.expect_close()?;
389 Ok(Node::DebugTag(DebugTag { expr }))
390 }
391 other => Err(Error::ParseError {
392 message: format!("Unknown special tag keyword {}", other),
393 span: self.peek_span(),
394 }),
395 }
396 }
397
398 fn parse_pattern(&mut self) -> Result<Pattern> {
399 if self.peek_kind() == &TokenKind::LBraceD {
400 self.advance(); let mut names = Vec::new();
402 loop {
403 if self.peek_kind() == &TokenKind::RBraceD {
404 self.advance(); break;
406 }
407 names.push(self.expect_ident()?);
408 if self.peek_kind() == &TokenKind::Comma {
409 self.advance();
410 if self.peek_kind() == &TokenKind::RBraceD {
411 self.advance();
412 break;
413 }
414 }
415 }
416 Ok(Pattern::Destructure(names))
417 } else {
418 Ok(Pattern::Ident(self.expect_ident()?))
419 }
420 }
421
422 fn parse_param_list(&mut self) -> Result<Vec<String>> {
423 let mut params = Vec::new();
424 if self.peek_kind() == &TokenKind::RParen {
425 return Ok(params);
426 }
427 params.push(self.expect_ident()?);
428 while self.peek_kind() == &TokenKind::Comma {
429 self.advance();
430 if self.peek_kind() == &TokenKind::RParen {
431 break;
432 }
433 params.push(self.expect_ident()?);
434 }
435 Ok(params)
436 }
437
438 fn parse_arg_list(&mut self) -> Result<Vec<Expr>> {
439 let mut args = Vec::new();
440 if self.peek_kind() == &TokenKind::RParen {
441 return Ok(args);
442 }
443 args.push(self.parse_expr()?);
444 while self.peek_kind() == &TokenKind::Comma {
445 self.advance();
446 if self.peek_kind() == &TokenKind::RParen {
447 break;
448 }
449 args.push(self.parse_expr()?);
450 }
451 Ok(args)
452 }
453
454 fn parse_expr(&mut self) -> Result<Expr> {
455 self.parse_filter_expr()
456 }
457
458 fn parse_filter_expr(&mut self) -> Result<Expr> {
459 let expr = self.parse_ternary()?;
460 let mut filters = Vec::new();
461 while self.peek_kind() == &TokenKind::Pipe {
462 self.advance();
463 let name = self.expect_ident()?;
464 let args = if self.peek_kind() == &TokenKind::LParen {
465 self.advance();
466 let a = self.parse_arg_list()?;
467 self.expect(&TokenKind::RParen)?;
468 a
469 } else {
470 Vec::new()
471 };
472 filters.push(FilterApplication { name, args });
473 }
474 if filters.is_empty() {
475 Ok(expr)
476 } else {
477 Ok(Expr::Filter {
478 expr: Box::new(expr),
479 filters,
480 })
481 }
482 }
483
484 fn parse_ternary(&mut self) -> Result<Expr> {
485 let cond = self.parse_nullish()?;
486 if self.peek_kind() == &TokenKind::Question {
487 self.advance();
488 let consequent = self.parse_expr()?;
489 self.expect(&TokenKind::Colon)?;
490 let alternate = self.parse_expr()?;
491 Ok(Expr::Ternary {
492 condition: Box::new(cond),
493 consequent: Box::new(consequent),
494 alternate: Box::new(alternate),
495 })
496 } else {
497 Ok(cond)
498 }
499 }
500
501 fn parse_nullish(&mut self) -> Result<Expr> {
502 let mut left = self.parse_or()?;
503 while self.peek_kind() == &TokenKind::NullCoalesce {
504 self.advance();
505 let right = self.parse_or()?;
506 left = Expr::Binary {
507 op: BinaryOp::NullCoalesce,
508 left: Box::new(left),
509 right: Box::new(right),
510 };
511 }
512 Ok(left)
513 }
514
515 fn parse_or(&mut self) -> Result<Expr> {
516 let mut left = self.parse_and()?;
517 while self.peek_kind() == &TokenKind::Or {
518 self.advance();
519 let right = self.parse_and()?;
520 left = Expr::Binary {
521 op: BinaryOp::Or,
522 left: Box::new(left),
523 right: Box::new(right),
524 };
525 }
526 Ok(left)
527 }
528
529 fn parse_and(&mut self) -> Result<Expr> {
530 let mut left = self.parse_equality()?;
531 while self.peek_kind() == &TokenKind::And {
532 self.advance();
533 let right = self.parse_equality()?;
534 left = Expr::Binary {
535 op: BinaryOp::And,
536 left: Box::new(left),
537 right: Box::new(right),
538 };
539 }
540 Ok(left)
541 }
542
543 fn parse_equality(&mut self) -> Result<Expr> {
544 let mut left = self.parse_comparison()?;
545 loop {
546 let op = match self.peek_kind() {
547 TokenKind::Eq => BinaryOp::Eq,
548 TokenKind::Neq => BinaryOp::Neq,
549 _ => break,
550 };
551 self.advance();
552 let right = self.parse_comparison()?;
553 left = Expr::Binary {
554 op,
555 left: Box::new(left),
556 right: Box::new(right),
557 };
558 }
559 Ok(left)
560 }
561
562 fn parse_comparison(&mut self) -> Result<Expr> {
563 let mut left = self.parse_test()?;
564 loop {
565 let op = match self.peek_kind() {
566 TokenKind::Lt => BinaryOp::Lt,
567 TokenKind::Gt => BinaryOp::Gt,
568 TokenKind::Lte => BinaryOp::Lte,
569 TokenKind::Gte => BinaryOp::Gte,
570 _ => break,
571 };
572 self.advance();
573 let right = self.parse_test()?;
574 left = Expr::Binary {
575 op,
576 left: Box::new(left),
577 right: Box::new(right),
578 };
579 }
580 Ok(left)
581 }
582
583 fn parse_test(&mut self) -> Result<Expr> {
584 let expr = self.parse_membership()?;
585 if self.peek_kind() == &TokenKind::KwIs {
586 self.advance();
587 let negated = if self.peek_kind() == &TokenKind::KwNot {
588 self.advance();
589 true
590 } else {
591 false
592 };
593 let test_name = self.expect_ident()?;
594 Ok(Expr::Test {
595 expr: Box::new(expr),
596 negated,
597 test_name,
598 })
599 } else {
600 Ok(expr)
601 }
602 }
603
604 fn parse_membership(&mut self) -> Result<Expr> {
605 let expr = self.parse_additive()?;
606 match self.peek_kind() {
607 TokenKind::KwIn => {
608 self.advance();
609 let collection = self.parse_additive()?;
610 Ok(Expr::Membership {
611 expr: Box::new(expr),
612 negated: false,
613 collection: Box::new(collection),
614 })
615 }
616 TokenKind::KwNot => {
617 self.advance();
618 self.expect_keyword(TokenKind::KwIn)?;
619 let collection = self.parse_additive()?;
620 Ok(Expr::Membership {
621 expr: Box::new(expr),
622 negated: true,
623 collection: Box::new(collection),
624 })
625 }
626 _ => Ok(expr),
627 }
628 }
629
630 fn parse_additive(&mut self) -> Result<Expr> {
631 let mut left = self.parse_multiplicative()?;
632 loop {
633 let op = match self.peek_kind() {
634 TokenKind::Add => BinaryOp::Add,
635 TokenKind::Sub => BinaryOp::Sub,
636 _ => break,
637 };
638 self.advance();
639 let right = self.parse_multiplicative()?;
640 left = Expr::Binary {
641 op,
642 left: Box::new(left),
643 right: Box::new(right),
644 };
645 }
646 Ok(left)
647 }
648
649 fn parse_multiplicative(&mut self) -> Result<Expr> {
650 let mut left = self.parse_unary()?;
651 loop {
652 let op = match self.peek_kind() {
653 TokenKind::Mul => BinaryOp::Mul,
654 TokenKind::Div => BinaryOp::Div,
655 TokenKind::Mod => BinaryOp::Mod,
656 _ => break,
657 };
658 self.advance();
659 let right = self.parse_unary()?;
660 left = Expr::Binary {
661 op,
662 left: Box::new(left),
663 right: Box::new(right),
664 };
665 }
666 Ok(left)
667 }
668
669 fn parse_unary(&mut self) -> Result<Expr> {
670 match self.peek_kind() {
671 TokenKind::Bang => {
672 self.advance();
673 Ok(Expr::Unary {
674 op: UnaryOp::Not,
675 operand: Box::new(self.parse_unary()?),
676 })
677 }
678 TokenKind::Sub => {
679 self.advance();
680 Ok(Expr::Unary {
681 op: UnaryOp::Neg,
682 operand: Box::new(self.parse_unary()?),
683 })
684 }
685 _ => self.parse_postfix(),
686 }
687 }
688
689 fn parse_postfix(&mut self) -> Result<Expr> {
690 let mut expr = self.parse_primary()?;
691 loop {
692 match self.peek_kind() {
693 TokenKind::Dot => {
694 self.advance();
695 let prop = self.expect_ident()?;
696 expr = Expr::MemberAccess {
697 object: Box::new(expr),
698 property: prop,
699 };
700 }
701 TokenKind::LBracket => {
702 self.advance();
703 let index = self.parse_expr()?;
704 self.expect(&TokenKind::RBracket)?;
705 expr = Expr::IndexAccess {
706 object: Box::new(expr),
707 index: Box::new(index),
708 };
709 }
710 _ => break,
711 }
712 }
713 Ok(expr)
714 }
715
716 fn parse_primary(&mut self) -> Result<Expr> {
717 match self.peek_kind().clone() {
718 TokenKind::Null => {
719 self.advance();
720 Ok(Expr::Null)
721 }
722 TokenKind::True => {
723 self.advance();
724 Ok(Expr::Bool(true))
725 }
726 TokenKind::False => {
727 self.advance();
728 Ok(Expr::Bool(false))
729 }
730 TokenKind::IntLit(i) => {
731 self.advance();
732 Ok(Expr::Int(i))
733 }
734 TokenKind::FloatLit(f) => {
735 self.advance();
736 Ok(Expr::Float(f))
737 }
738 TokenKind::StringLit(s) => {
739 self.advance();
740 Ok(Expr::String(s))
741 }
742 TokenKind::Ident(name) => {
743 self.advance();
744 Ok(Expr::Ident(name))
745 }
746 TokenKind::LParen => {
747 self.advance();
748 let expr = self.parse_expr()?;
749 self.expect(&TokenKind::RParen)?;
750 Ok(expr)
751 }
752 TokenKind::LBracket => {
753 self.advance();
754 let mut elements = Vec::new();
755 if self.peek_kind() != &TokenKind::RBracket {
756 elements.push(self.parse_expr()?);
757 while self.peek_kind() == &TokenKind::Comma {
758 self.advance();
759 if self.peek_kind() == &TokenKind::RBracket {
760 break;
761 }
762 elements.push(self.parse_expr()?);
763 }
764 }
765 self.expect(&TokenKind::RBracket)?;
766 Ok(Expr::Array(elements))
767 }
768 other => Err(Error::ParseError {
769 message: format!("Expected expression, got {}", other),
770 span: self.peek_span(),
771 }),
772 }
773 }
774
775 fn expect(&mut self, kind: &TokenKind) -> Result<&Token> {
776 if std::mem::discriminant(self.peek_kind()) == std::mem::discriminant(kind) {
777 Ok(self.advance())
778 } else {
779 Err(Error::ParseError {
780 message: format!("Expected {}, got {}", kind, self.peek_kind()),
781 span: self.peek_span(),
782 })
783 }
784 }
785}
786
787fn strip_standalone(nodes: &mut Vec<Node>) {
799 let len = nodes.len();
800 for i in 0..len {
801 if !is_standalone_eligible(&nodes[i]) {
802 continue;
803 }
804
805 if has_vec_body(&nodes[i]) {
811 match block_first_body_text(&nodes[i]) {
812 Some(s) if s.starts_with('\n') => {} _ => continue, }
815 }
816
817 let prefix_blank = match i.checked_sub(1) {
819 None => true, Some(prev) => match &nodes[prev] {
821 Node::RawText(s) => after_last_nl(s).chars().all(|c| c == ' ' || c == '\t'),
822 _ => false,
823 },
824 };
825 if !prefix_blank {
826 continue;
827 }
828
829 let suffix_blank = match nodes.get(i + 1) {
831 None => true, Some(Node::RawText(s)) => before_first_nl(s).chars().all(|c| c == ' ' || c == '\t'),
833 Some(_) => false,
834 };
835 if !suffix_blank {
836 continue;
837 }
838
839 if i > 0
841 && let Node::RawText(s) = &mut nodes[i - 1]
842 {
843 trim_line_tail(s);
844 }
845
846 if i + 1 < len
849 && let Node::RawText(s) = &mut nodes[i + 1]
850 {
851 strip_through_first_nl(s);
852 }
853
854 strip_block_body_edges(&mut nodes[i]);
856 }
857
858 nodes.retain(|n| !matches!(n, Node::RawText(s) if s.is_empty()));
860}
861
862fn is_standalone_eligible(node: &Node) -> bool {
864 matches!(
865 node,
866 Node::IfBlock(_)
867 | Node::EachBlock(_)
868 | Node::SnippetBlock(_)
869 | Node::RawBlock(_)
870 | Node::RenderTag(_)
871 | Node::ConstTag(_)
872 | Node::IncludeTag(_)
873 | Node::DebugTag(_)
874 | Node::Comment(_)
875 )
876}
877
878fn has_vec_body(node: &Node) -> bool {
880 matches!(
881 node,
882 Node::IfBlock(_) | Node::EachBlock(_) | Node::SnippetBlock(_)
883 )
884}
885
886fn block_first_body_text(node: &Node) -> Option<&str> {
888 let body = match node {
889 Node::IfBlock(b) => &b.branches[0].body,
890 Node::EachBlock(b) => &b.body,
891 Node::SnippetBlock(b) => &b.body,
892 _ => return None,
893 };
894 match body.first() {
895 Some(Node::RawText(s)) => Some(s.as_str()),
896 _ => None,
897 }
898}
899
900fn strip_block_body_edges(node: &mut Node) {
904 match node {
905 Node::IfBlock(b) => {
906 for branch in &mut b.branches {
910 strip_body_head(&mut branch.body);
911 strip_body_tail(&mut branch.body);
912 }
913 if let Some(eb) = &mut b.else_body {
914 strip_body_head(eb);
915 strip_body_tail(eb);
916 }
917 }
918 Node::EachBlock(b) => {
919 strip_body_head(&mut b.body);
920 if let Some(eb) = &mut b.else_body {
921 strip_body_tail(&mut b.body); strip_body_head(eb); strip_body_tail(eb); } else {
925 strip_body_tail(&mut b.body);
926 }
927 }
928 Node::SnippetBlock(b) => {
929 strip_body_head(&mut b.body);
930 strip_body_tail(&mut b.body);
931 }
932 _ => {}
933 }
934}
935
936fn strip_body_head(body: &mut Vec<Node>) {
937 if let Some(Node::RawText(s)) = body.first_mut() {
938 let should_strip = match s.find('\n') {
941 Some(pos) => s[..pos].chars().all(|c| c == ' ' || c == '\t'),
942 None => false, };
944 if should_strip {
945 strip_through_first_nl(s);
946 if s.is_empty() {
947 body.remove(0);
948 }
949 }
950 }
951}
952
953fn strip_body_tail(body: &mut Vec<Node>) {
954 if let Some(Node::RawText(s)) = body.last_mut() {
955 let blank_tail = match s.rfind('\n') {
958 Some(pos) => s[pos + 1..].chars().all(|c| c == ' ' || c == '\t'),
959 None => false, };
961 if blank_tail {
962 trim_line_tail(s);
963 if s.is_empty() {
964 body.pop();
965 }
966 }
967 }
968}
969
970fn after_last_nl(s: &str) -> &str {
972 match s.rfind('\n') {
973 Some(pos) => &s[pos + 1..],
974 None => s,
975 }
976}
977
978fn before_first_nl(s: &str) -> &str {
980 match s.find('\n') {
981 Some(pos) => &s[..pos],
982 None => s,
983 }
984}
985
986fn trim_line_tail(s: &mut String) {
989 match s.rfind('\n') {
990 Some(pos) => s.truncate(pos + 1),
991 None => s.clear(),
992 }
993}
994
995fn strip_through_first_nl(s: &mut String) {
998 if let Some(pos) = s.find('\n') {
999 *s = s[pos + 1..].to_string();
1000 } else {
1001 s.clear();
1002 }
1003}
1004
1005pub fn parse(tokens: Vec<Token>) -> Result<Template> {
1007 Parser::new(tokens).parse()
1008}