1use std::{unreachable, vec};
2
3use crate::{lex::Token, Error, ParenKind, Sexpr, Sexprs};
4
5pub(crate) struct Parser<'src> {
6 iter: vec::IntoIter<Token<'src>>,
7 curr_tok: Option<Token<'src>>,
8 errors: Vec<Error>,
9}
10
11impl<'src> Parser<'src> {
12 pub fn parse(tokens: Vec<Token<'src>>) -> (Sexprs<'src>, Vec<Error>) {
13 let mut iter = tokens.into_iter();
14 let mut parser = Self {
15 curr_tok: iter.next(),
16 iter,
17 errors: vec![],
18 };
19
20 let mut sexprs = Sexprs::new();
21 while let Some(sexpr) = parser.sexpr() {
22 sexprs.push(sexpr);
23 }
24
25 if let Some(tok) = parser.curr_tok {
26 let paren_kind = match tok {
27 Token::RParen => ParenKind::Round,
28 Token::RBrack => ParenKind::Square,
29 _ => unreachable!("`sexpr` function only returns `None` for above token types"),
30 };
31 parser.errors.push(Error::ExtraClosingParen(paren_kind));
32 }
33
34 (sexprs, parser.errors)
35 }
36
37 fn next(&mut self) {
38 self.curr_tok = self.iter.next();
39 }
40
41 fn expect_closing(&mut self, expected: ParenKind) {
42 match &self.curr_tok {
43 Some(tok) if tok == &Token::from(&expected) => self.next(),
44 Some(_) | None => self.errors.push(Error::MissingClosingParen(expected)),
45 }
46 }
47
48 fn sexpr(&mut self) -> Option<Sexpr<'src>> {
49 match self.curr_tok.take()? {
50 Token::LParen => Some(self.list()),
51 Token::LBrack => Some(self.group()),
52 Token::String(string) => {
53 self.next();
54 Some(Sexpr::String(string))
55 }
56 Token::Atom(atom) => {
57 self.next();
58 Some(Sexpr::Atom(atom))
59 }
60 #[cfg(feature = "comments")]
61 Token::Comment(comment) => {
62 self.next();
63 Some(Sexpr::Comment(comment))
64 }
65 tok @ (Token::RParen | Token::RBrack) => {
66 self.curr_tok = Some(tok);
67 None
68 }
69 }
70 }
71
72 fn list(&mut self) -> Sexpr<'src> {
73 self.next(); let mut children = Sexprs::new();
76 while let Some(child) = self.sexpr() {
77 children.push(child);
78 }
79
80 self.expect_closing(ParenKind::Round);
81
82 Sexpr::List(children)
83 }
84
85 fn group(&mut self) -> Sexpr<'src> {
86 self.next(); let mut children = Sexprs::new();
89 while let Some(child) = self.sexpr() {
90 children.push(child);
91 }
92
93 self.expect_closing(ParenKind::Square);
94
95 Sexpr::Group(children)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn nesting() {
105 assert_eq!(
106 Parser::parse(vec![
107 Token::LParen,
108 Token::LParen,
109 Token::LBrack,
110 Token::LParen,
111 Token::RParen,
112 Token::RBrack,
113 Token::RParen,
114 Token::RParen
115 ])
116 .0,
117 vec![Sexpr::List(
118 vec![Sexpr::List(
119 vec![Sexpr::Group(vec![Sexpr::List(vec![].into())].into())].into()
120 )]
121 .into()
122 )]
123 .into(),
124 );
125 }
126
127 #[test]
128 #[cfg(feature = "comments")]
129 fn comments() {
130 assert_eq!(
131 Parser::parse(vec![Token::Comment(b"; comment")]).0,
132 vec![Sexpr::Comment(b"; comment")].into(),
133 );
134 assert_eq!(
135 Parser::parse(vec![
136 Token::LParen,
137 Token::Comment(b"; comment"),
138 Token::Atom(b"atom"),
139 Token::RParen,
140 ])
141 .0,
142 vec![Sexpr::List(
143 vec![Sexpr::Comment(b"; comment"), Sexpr::Atom(b"atom"),].into()
144 )]
145 .into(),
146 );
147 }
148}