1use anyhow::Result;
2use brack_sdk_rs::ast::AST;
3use brack_tokenizer::tokens::Token;
4
5use crate::{
6 ast::new_document,
7 stmt,
8};
9
10pub fn parse(tokens: &Vec<Token>) -> Result<AST> {
11 let mut new_tokens = tokens.clone();
12 let mut result = new_document();
13
14 while new_tokens.len() > 0 {
15 match stmt::parse(&new_tokens) {
16 Ok((ast, tokens)) => {
17 new_tokens = tokens;
18 result.add(ast)?;
19 }
20 Err(e) => return Err(e),
21 }
22 }
23
24 Ok(result)
25}
26
27#[cfg(test)]
28mod test {
29 use anyhow::Result;
30 use brack_tokenizer::tokens::{mock_location, Token};
31
32 use crate::ast::{
33 assert_ast_eq, new_angle_with_children, new_curly_with_children,
34 new_document_with_children, new_expr_with_children, new_ident, new_square_with_children,
35 new_stmt_with_children, new_text,
36 };
37
38 use super::parse;
39
40 #[test]
41 fn test_parse_no_commands() -> Result<()> {
42 let tokens = vec![
43 Token::Text("Hello, World!".to_string(), mock_location()),
44 Token::EOF(mock_location()),
45 ];
46 let parsed = parse(&tokens)?;
47 let expected =
48 new_document_with_children(vec![new_stmt_with_children(vec![new_expr_with_children(
49 vec![new_text("Hello, World!".to_string())],
50 )])]);
51 assert_ast_eq(&parsed, &expected);
52 Ok(())
53 }
54
55 #[test]
56 fn test_parse_commands_with_an_argument_includes_square_brackets() -> Result<()> {
57 let tokens = vec![
58 Token::Text("Hello, ".to_string(), mock_location()),
59 Token::SquareBracketOpen(mock_location()),
60 Token::Module("std".to_string(), mock_location()),
61 Token::Dot(mock_location()),
62 Token::Ident("*".to_string(), mock_location()),
63 Token::Text("World!".to_string(), mock_location()),
64 Token::SquareBracketClose(mock_location()),
65 Token::EOF(mock_location()),
66 ];
67 let parsed = parse(&tokens)?;
68 let expected =
69 new_document_with_children(vec![new_stmt_with_children(vec![new_expr_with_children(
70 vec![
71 new_text("Hello, ".to_string()),
72 new_square_with_children(vec![
73 new_ident(vec![new_text("std".to_string()), new_text("*".to_string())]),
74 new_expr_with_children(vec![new_text("World!".to_string())]),
75 ]),
76 ],
77 )])]);
78 assert_ast_eq(&parsed, &expected);
79 Ok(())
80 }
81
82 #[test]
83 fn test_parse_commands_with_an_argument_includes_curly_brackets() -> Result<()> {
84 let tokens = vec![
85 Token::CurlyBracketOpen(mock_location()),
86 Token::Module("std".to_string(), mock_location()),
87 Token::Dot(mock_location()),
88 Token::Ident("*".to_string(), mock_location()),
89 Token::Text("Heading".to_string(), mock_location()),
90 Token::CurlyBracketClose(mock_location()),
91 Token::NewLine(mock_location()),
92 Token::Text("Hello, World!".to_string(), mock_location()),
93 Token::EOF(mock_location()),
94 ];
95 let parsed = parse(&tokens)?;
96 let expected = new_document_with_children(vec![
97 new_stmt_with_children(vec![new_curly_with_children(vec![
98 new_ident(vec![new_text("std".to_string()), new_text("*".to_string())]),
99 new_expr_with_children(vec![new_text("Heading".to_string())]),
100 ])]),
101 new_stmt_with_children(vec![new_expr_with_children(vec![new_text(
102 "Hello, World!".to_string(),
103 )])]),
104 ]);
105 assert_ast_eq(&parsed, &expected);
106 Ok(())
107 }
108
109 #[test]
110 fn test_parse_commands_with_an_argument_includes_angle_brackets() -> Result<()> {
111 let tokens = vec![
112 Token::Text("Hello, ".to_string(), mock_location()),
113 Token::AngleBracketOpen(mock_location()),
114 Token::Module("std".to_string(), mock_location()),
115 Token::Dot(mock_location()),
116 Token::Ident("*".to_string(), mock_location()),
117 Token::Text("World!".to_string(), mock_location()),
118 Token::AngleBracketClose(mock_location()),
119 Token::EOF(mock_location()),
120 ];
121 let parsed = parse(&tokens)?;
122 let expected =
123 new_document_with_children(vec![new_stmt_with_children(vec![new_expr_with_children(
124 vec![
125 new_text("Hello, ".to_string()),
126 new_angle_with_children(vec![
127 new_ident(vec![new_text("std".to_string()), new_text("*".to_string())]),
128 new_expr_with_children(vec![new_text("World!".to_string())]),
129 ]),
130 ],
131 )])]);
132 assert_ast_eq(&parsed, &expected);
133 Ok(())
134 }
135
136 #[test]
137 fn test_parse_commands_with_two_arguments_includes_square_brackets() -> Result<()> {
138 let tokens = vec![
139 Token::Text("Hello, ".to_string(), mock_location()),
140 Token::SquareBracketOpen(mock_location()),
141 Token::Module("std".to_string(), mock_location()),
142 Token::Dot(mock_location()),
143 Token::Ident("@".to_string(), mock_location()),
144 Token::Text("World!".to_string(), mock_location()),
145 Token::Comma(mock_location()),
146 Token::Text("https://example.com/".to_string(), mock_location()),
147 Token::SquareBracketClose(mock_location()),
148 Token::EOF(mock_location()),
149 ];
150 let parsed = parse(&tokens)?;
151 let expected =
152 new_document_with_children(vec![new_stmt_with_children(vec![new_expr_with_children(
153 vec![
154 new_text("Hello, ".to_string()),
155 new_square_with_children(vec![
156 new_ident(vec![new_text("std".to_string()), new_text("@".to_string())]),
157 new_expr_with_children(vec![new_text("World!".to_string())]),
158 new_expr_with_children(vec![new_text("https://example.com/".to_string())]),
159 ]),
160 ],
161 )])]);
162 assert_ast_eq(&parsed, &expected);
163 Ok(())
164 }
165
166 #[test]
167 fn test_parse_nesting_commands() -> Result<()> {
168 let tokens = vec![
169 Token::Text("Hello, ".to_string(), mock_location()),
170 Token::SquareBracketOpen(mock_location()),
171 Token::Module("std".to_string(), mock_location()),
172 Token::Dot(mock_location()),
173 Token::Ident("*".to_string(), mock_location()),
174 Token::SquareBracketOpen(mock_location()),
175 Token::Module("std".to_string(), mock_location()),
176 Token::Dot(mock_location()),
177 Token::Ident("@".to_string(), mock_location()),
178 Token::Text("World!".to_string(), mock_location()),
179 Token::Comma(mock_location()),
180 Token::Text("https://example.com/".to_string(), mock_location()),
181 Token::SquareBracketClose(mock_location()),
182 Token::SquareBracketClose(mock_location()),
183 Token::EOF(mock_location()),
184 ];
185 let parsed = parse(&tokens)?;
186 let expected =
187 new_document_with_children(vec![new_stmt_with_children(vec![new_expr_with_children(
188 vec![
189 new_text("Hello, ".to_string()),
190 new_square_with_children(vec![
191 new_ident(vec![new_text("std".to_string()), new_text("*".to_string())]),
192 new_expr_with_children(vec![new_square_with_children(vec![
193 new_ident(vec![new_text("std".to_string()), new_text("@".to_string())]),
194 new_expr_with_children(vec![new_text("World!".to_string())]),
195 new_expr_with_children(vec![new_text(
196 "https://example.com/".to_string(),
197 )]),
198 ])]),
199 ]),
200 ],
201 )])]);
202 assert_ast_eq(&parsed, &expected);
203 Ok(())
204 }
205
206 #[test]
207 fn test_parse_newlines() -> Result<()> {
208 let tokens = vec![
209 Token::Text("Hello,".to_string(), mock_location()),
210 Token::NewLine(mock_location()),
211 Token::Text("World,".to_string(), mock_location()),
212 Token::NewLine(mock_location()),
213 Token::CurlyBracketOpen(mock_location()),
214 Token::Module("std".to_string(), mock_location()),
215 Token::Dot(mock_location()),
216 Token::Ident("**".to_string(), mock_location()),
217 Token::Text("Contact".to_string(), mock_location()),
218 Token::CurlyBracketClose(mock_location()),
219 Token::NewLine(mock_location()),
220 Token::SquareBracketOpen(mock_location()),
221 Token::Module("std".to_string(), mock_location()),
222 Token::Dot(mock_location()),
223 Token::Ident("@".to_string(), mock_location()),
224 Token::Text("My website".to_string(), mock_location()),
225 Token::Comma(mock_location()),
226 Token::Text("https://example.com/".to_string(), mock_location()),
227 Token::SquareBracketClose(mock_location()),
228 Token::NewLine(mock_location()),
229 Token::NewLine(mock_location()),
230 Token::Text("2023.12.28".to_string(), mock_location()),
231 Token::NewLine(mock_location()),
232 Token::EOF(mock_location()),
233 ];
234 let parsed = parse(&tokens)?;
235 let expected = new_document_with_children(vec![
236 new_stmt_with_children(vec![
237 new_expr_with_children(vec![new_text("Hello,".to_string())]),
238 new_expr_with_children(vec![new_text("World,".to_string())]),
239 ]),
240 new_stmt_with_children(vec![new_curly_with_children(vec![
241 new_ident(vec![
242 new_text("std".to_string()),
243 new_text("**".to_string()),
244 ]),
245 new_expr_with_children(vec![new_text("Contact".to_string())]),
246 ])]),
247 new_stmt_with_children(vec![new_expr_with_children(vec![
248 new_square_with_children(vec![
249 new_ident(vec![new_text("std".to_string()), new_text("@".to_string())]),
250 new_expr_with_children(vec![new_text("My website".to_string())]),
251 new_expr_with_children(vec![new_text("https://example.com/".to_string())]),
252 ]),
253 ])]),
254 new_stmt_with_children(vec![new_expr_with_children(vec![new_text(
255 "2023.12.28".to_string(),
256 )])]),
257 ]);
258 assert_ast_eq(&parsed, &expected);
259 Ok(())
260 }
261}