template_compiler/
parse.rs1use std::{sync::Arc, iter::Peekable};
2
3use anyhow::Result;
4use miette::{NamedSource, SourceSpan};
5
6use crate::tokens::{Token, Tokenizer};
7
8#[derive(Debug)]
9pub struct M<T> {
10 pub span: SourceSpan,
11 pub value: T,
12}
13
14impl<T> M<T> {
15 pub fn new(value: T, span: SourceSpan) -> Self {
16 M { span, value }
17 }
18}
19
20#[derive(Debug)]
21pub struct FileData<'source> {
22 pub source: Arc<NamedSource>,
23 pub contents: Vec<Node<'source>>,
24}
25
26#[derive(Debug)]
27pub enum Node<'source> {
28 Text {
29 index: usize,
30 text: M<&'source str>,
31 },
32 Parameter {
33 name: M<&'source str>,
34 },
35 Conditional {
36 if_kwd: SourceSpan,
37 cond_ident: M<&'source str>,
38 contents: Vec<Node<'source>>,
39 endif_kwd: SourceSpan,
40 },
41}
42
43pub fn parse_file<'source>(
44 source: Arc<NamedSource>,
45 text: &'source str,
46) -> Result<FileData<'source>> {
47 let tokens = Tokenizer::new(source.clone(), text).tokenize()?;
48 let mut token_iter = tokens.into_iter().peekable();
49
50 let contents = parse_tokens(source.clone(), &mut token_iter)?;
51
52 Ok(FileData { source, contents })
53}
54
55fn parse_tokens<'source, Iter>(source: Arc<NamedSource>, token_iter: &mut Peekable<Iter>) -> Result<Vec<Node<'source>>>
56where
57 Iter: Iterator<Item = (SourceSpan, Token<'source>)>,
58{
59 let mut contents = Vec::new();
60
61 while let Some((span, token)) = token_iter.next() {
62 match token {
63 Token::CommandStart => {
64 if token_iter.peek().unwrap().1 == Token::EndIf {
65 return Ok(contents);
66 }
67
68 let if_kwd = match_token(token_iter, Token::If)?;
69 let cond_ident = match_ident(token_iter)?;
70 match_token(token_iter, Token::CommandEnd)?;
71
72 let if_contents = parse_tokens(source.clone(), token_iter)?;
73
74 let endif_kwd = match_token(token_iter, Token::EndIf)?;
75 match_token(token_iter, Token::CommandEnd)?;
76
77 contents.push(Node::Conditional {
78 if_kwd,
79 cond_ident,
80 contents: if_contents,
81 endif_kwd,
82 })
83 }
84 Token::ParamStart => {
85 let name = match_ident(token_iter)?;
86 contents.push(Node::Parameter { name });
87 match_token(token_iter, Token::ParamEnd)?;
88 }
89 Token::Text { index, text } => {
90 contents.push(Node::Text {
91 index,
92 text: M::new(text, span),
93 });
94 }
95 _ => todo!(),
96 }
97 }
98
99 Ok(contents)
100}
101
102fn match_token<'source, Iter>(token_iter: &mut Iter, token: Token<'source>) -> Result<SourceSpan>
103where
104 Iter: Iterator<Item = (SourceSpan, Token<'source>)>,
105{
106 match token_iter.next() {
107 Some((span, t)) if t == token => Ok(span),
108 Some(st) => { dbg!(st); todo!() },
109 None => todo!("error"),
110 }
111}
112
113fn match_ident<'source, Iter>(token_iter: &mut Iter) -> Result<M<&'source str>>
114where
115 Iter: Iterator<Item = (SourceSpan, Token<'source>)>,
116{
117 match token_iter.next() {
118 Some((span, Token::Identifier { name })) => Ok(M::new(name, span)),
119 Some(_) => todo!("error"),
120 None => todo!("error"),
121 }
122}