1use crate::ast::{Ast, AstNode, BinOp, SrcLoc};
2use crate::lexer::lex::Token;
3use crate::parser::parse::{self, parse_expr, parse_params};
4use crate::parser::patterns::parse::parse_pattern;
5use crate::parser::util;
6use util::expect_and_consume;
7
8use super::parse::parse_identifier;
9use super::types::parse::parse_type;
10use super::util::{ast_op_to_token_op, consume_if_present};
11
12pub trait PrefixParselet {
13 fn parse(
14 &self,
15 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
16 current_token: (Token, std::ops::Range<usize>),
17 is_top_level: bool,
18 ) -> Result<Ast, util::ParseError>;
19}
20pub trait InfixParselet {
21 fn parse(
22 &self,
23 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
24 left_node: Ast,
25 current_token: (Token, std::ops::Range<usize>),
26 ) -> Result<Ast, util::ParseError>;
27}
28
29pub trait PostfixParselet {
30 fn parse(
31 &self,
32 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
33 left_node: Ast,
34 current_token: (Token, std::ops::Range<usize>),
35 ) -> Result<Ast, util::ParseError>;
36}
37
38pub struct NumberParselet {}
39impl PrefixParselet for NumberParselet {
40 fn parse(
41 &self,
42 _tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
43 current_token: (Token, std::ops::Range<usize>),
44 _is_top_level: bool,
45 ) -> Result<Ast, util::ParseError> {
46 match current_token {
47 (Token::Number(n), span) => Ok(Ast::new(AstNode::NumberNode(n), SrcLoc { span })),
48 _ => panic!("Tried to use number parselet with non-number token"),
49 }
50 }
51}
52
53pub struct BoolParselet {}
54impl PrefixParselet for BoolParselet {
55 fn parse(
56 &self,
57 _tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
58 current_token: (Token, std::ops::Range<usize>),
59 _is_top_level: bool,
60 ) -> Result<Ast, util::ParseError> {
61 match current_token {
62 (Token::Bool(v), span) => Ok(Ast::new(AstNode::BoolNode(v), SrcLoc { span })),
63 _ => panic!("Tried to use bool parselet with non-bool token"),
64 }
65 }
66}
67
68pub struct FunctionParselet {}
69impl PrefixParselet for FunctionParselet {
70 fn parse(
71 &self,
72 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
73 current_token: (Token, std::ops::Range<usize>),
74 is_top_level: bool,
75 ) -> Result<Ast, util::ParseError> {
76 if !is_top_level {
77 return Err(util::ParseError(
78 "Function definitions are only allowed at the top level".to_string(),
79 Some(current_token.1),
80 ));
81 }
82
83 let span_start = current_token.1.start;
84
85 let func_name = match tokens.pop() {
86 Some((Token::Identifier(name), _)) => Ok(name),
87 Some((_, span)) => Err(util::ParseError(
88 "Found non-identifier in function name".to_string(),
89 Some(span.clone()),
90 )),
91 None => Err(util::ParseError(
92 "Ran out of tokens while parsing function name".to_string(),
93 None,
94 )),
95 }?;
96
97 expect_and_consume(tokens, Token::LParen)?;
98
99 let params = parse::parse_params(tokens)?;
100
101 let mut return_type = None;
103 match tokens.last() {
104 Some((Token::ThinArrow, _)) => {
105 tokens.pop();
106 return_type = Some(parse_type(tokens)?);
107 }
108 None => {
109 return Err(util::ParseError(
110 "Ran out of tokens while parsing function name".to_string(),
111 None,
112 ))
113 }
114 _ => {}
115 };
116
117 expect_and_consume(tokens, Token::Colon)?;
118
119 let body = parse::parse_expr(tokens, 0, false)?;
120
121 let span_end = expect_and_consume(tokens, Token::End)?.end;
122
123 return Ok(Ast::new(
124 AstNode::FunctionNode(
125 func_name,
126 params,
127 return_type.map_or(None, |v| Some(v.0)),
128 Box::new(body),
129 ),
130 SrcLoc {
131 span: span_start..span_end,
132 },
133 ));
134 }
135}
136
137pub struct LambdaParselet {}
138impl PrefixParselet for LambdaParselet {
139 fn parse(
140 &self,
141 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
142 current_token: (Token, std::ops::Range<usize>),
143 _is_top_level: bool,
144 ) -> Result<Ast, util::ParseError> {
145 let span_start = current_token.1.start;
146
147 expect_and_consume(tokens, Token::LParen)?;
148
149 let params = parse::parse_params(tokens)?;
150
151 expect_and_consume(tokens, Token::Colon)?;
152
153 let body = parse::parse_expr(tokens, 0, false)?;
154
155 let span_end = expect_and_consume(tokens, Token::End)?.end;
156
157 return Ok(Ast::new(
158 AstNode::LambdaNode(params, Box::new(body)),
159 SrcLoc {
160 span: span_start..span_end,
161 },
162 ));
163 }
164}
165
166pub struct IfParselet {}
167impl PrefixParselet for IfParselet {
168 fn parse(
169 &self,
170 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
171 current_token: (Token, std::ops::Range<usize>),
172 _is_top_level: bool,
173 ) -> Result<Ast, util::ParseError> {
174 let span_start = current_token.1.start;
175
176 let mut conditions = vec![];
177 let mut bodies = vec![];
178 conditions.push(parse::parse_expr(tokens, 0, false)?);
179 expect_and_consume(tokens, Token::Colon)?;
180 bodies.push(parse::parse_expr(tokens, 0, false)?);
181
182 let altern = loop {
183 match tokens.pop() {
184 Some((Token::Elif, _)) => {
185 conditions.push(parse::parse_expr(tokens, 0, false)?);
186 expect_and_consume(tokens, Token::Colon)?;
187 bodies.push(parse::parse_expr(tokens, 0, false)?);
188 }
189 Some((Token::Else, _)) => {
190 expect_and_consume(tokens, Token::Colon)?;
191 break parse::parse_expr(tokens, 0, false)?;
192 }
193 Some((_, span)) => {
194 return Err(util::ParseError(
195 "Expected `else` or `elif`".to_string(),
196 Some(span),
197 ))
198 }
199 None => {
200 return Err(util::ParseError(
201 "Ran out of tokens while parsing conditional".to_string(),
202 None,
203 ))
204 }
205 }
206 };
207
208 let span_end = expect_and_consume(tokens, Token::End)?.end;
209
210 return Ok(Ast::new(
211 AstNode::IfNode(
212 conditions
213 .into_iter()
214 .zip(bodies.into_iter())
215 .collect::<Vec<(Ast, Ast)>>(),
216 Box::new(altern),
217 ),
218 SrcLoc {
219 span: span_start..span_end,
220 },
221 ));
222 }
223}
224
225pub struct LetParselet {}
226impl PrefixParselet for LetParselet {
227 fn parse(
228 &self,
229 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
230 current_token: (Token, std::ops::Range<usize>),
231 is_top_level: bool,
232 ) -> Result<Ast, util::ParseError> {
233 let span_start = current_token.1.start;
234
235 let (id, _) = parse_identifier(None, tokens)?;
236
237 let span_end = expect_and_consume(tokens, Token::Eq)?.end;
239
240 let binding = parse::parse_expr(tokens, 0, false)?;
241 if is_top_level {
242 return Ok(Ast::new(
243 AstNode::LetNodeTopLevel(id, Box::new(binding)),
244 SrcLoc {
245 span: span_start..span_end,
246 },
247 ));
248 } else {
249 let body = parse::parse_expr(tokens, 0, false)?;
250 return Ok(Ast::new(
251 AstNode::LetNode(id, Box::new(binding), Box::new(body)),
252 SrcLoc {
253 span: span_start..span_end,
254 },
255 ));
256 }
257 }
258}
259
260pub struct IdentifierParselet {}
261impl PrefixParselet for IdentifierParselet {
262 fn parse(
263 &self,
264 _tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
265 current_token: (Token, std::ops::Range<usize>),
266 _is_top_level: bool,
267 ) -> Result<Ast, util::ParseError> {
268 match current_token {
269 (Token::Identifier(id), span) => Ok(Ast::new(AstNode::VarNode(id), SrcLoc { span })),
270 _ => panic!("Tried to use identifier parselet with non-id token"),
271 }
272 }
273}
274
275pub struct ParenthesisParselet {}
276impl PrefixParselet for ParenthesisParselet {
277 fn parse(
278 &self,
279 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
280 _current_token: (Token, std::ops::Range<usize>),
281 _is_top_level: bool,
282 ) -> Result<Ast, util::ParseError> {
283 let expr = parse::parse_expr(tokens, 0, false)?;
284
285 expect_and_consume(tokens, Token::RParen)?;
286
287 return Ok(expr);
288 }
289}
290
291pub struct DataParselet {}
292impl PrefixParselet for DataParselet {
293 fn parse(
294 &self,
295 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
296 current_token: (Token, std::ops::Range<usize>),
297 is_top_level: bool,
298 ) -> Result<Ast, util::ParseError> {
299 if !is_top_level {
300 return Err(util::ParseError(
301 "Data declarations can only exist at the top level".to_string(),
302 Some(current_token.1),
303 ));
304 }
305
306 let (data_name, span_start) = match tokens.pop() {
307 Some((Token::Identifier(id), span)) => Ok((id, span.start)),
308 Some((_, span)) => Err(util::ParseError(
309 "Found non-identifier as data declaration name".to_string(),
310 Some(span),
311 )),
312 None => Err(util::ParseError(
313 "Ran out of tokens while parsing data declaration".to_string(),
314 None,
315 )),
316 }?;
317
318 expect_and_consume(tokens, Token::Colon)?;
319 consume_if_present(tokens, Token::Pipe)?;
321
322 let mut variants = vec![];
323
324 let span_end = loop {
325 let variant_name = match tokens.pop() {
326 Some((Token::Identifier(id), _)) => Ok(id),
327 Some((_, span)) => Err(util::ParseError(
328 "Found non-identifier as data variant name".to_string(),
329 Some(span),
330 )),
331 None => Err(util::ParseError(
332 "Ran out of tokens while parsing data variant".to_string(),
333 None,
334 )),
335 }?;
336
337 expect_and_consume(tokens, Token::LParen)?;
339 let field_names = parse_params(tokens)?;
340
341 variants.push((variant_name, field_names));
342
343 match tokens.pop() {
345 Some((Token::Pipe, _)) => continue,
346 Some((Token::End, span)) => break span.end,
347 Some((_, span)) => {
348 return Err(util::ParseError(
349 "Found bad token while parsing data variants".to_string(),
350 Some(span),
351 ))
352 }
353 None => {
354 return Err(util::ParseError(
355 "Ran out of tokens while parsing data variant".to_string(),
356 None,
357 ))
358 }
359 }
360 };
361
362 return Ok(Ast::new(
363 AstNode::DataDeclarationNode(data_name, variants),
364 SrcLoc {
365 span: span_start..span_end,
366 },
367 ));
368 }
369}
370
371pub struct MatchParselet {}
372impl PrefixParselet for MatchParselet {
373 fn parse(
374 &self,
375 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
376 current_token: (Token, std::ops::Range<usize>),
377 _is_top_level: bool,
378 ) -> Result<Ast, util::ParseError> {
379 let span_start = current_token.1.end;
380 let expression_to_match = parse_expr(tokens, 0, false)?;
381
382 expect_and_consume(tokens, Token::Colon)?;
383 expect_and_consume(tokens, Token::Pipe)?;
385
386 let mut branches = vec![];
387
388 let span_end = loop {
389 let branch_pattern = parse_pattern(tokens, 0)?;
390
391 expect_and_consume(tokens, Token::FatArrow)?;
393 let branch_body = parse_expr(tokens, 0, false)?;
394
395 branches.push((branch_pattern, branch_body));
396
397 match tokens.pop() {
399 Some((Token::Pipe, _)) => continue,
400 Some((Token::End, span)) => break span.end,
401 Some((token, span)) => {
402 return Err(util::ParseError(
403 format!(
404 "Found bad token while parsing match expression: {:?}",
405 token
406 )
407 .to_string(),
408 Some(span),
409 ))
410 }
411 None => {
412 return Err(util::ParseError(
413 "Ran out of tokens while parsing match expression".to_string(),
414 None,
415 ))
416 }
417 }
418 };
419
420 return Ok(Ast::new(
421 AstNode::MatchNode(Box::new(expression_to_match), branches),
422 SrcLoc {
423 span: span_start..span_end,
424 },
425 ));
426 }
427}
428
429pub struct OperatorParselet {
430 operator: BinOp,
431 is_left_associative: bool,
432}
433impl OperatorParselet {
434 pub fn new(op: BinOp, is_left_associative: bool) -> OperatorParselet {
435 OperatorParselet {
436 operator: op,
437 is_left_associative: is_left_associative,
438 }
439 }
440}
441impl InfixParselet for OperatorParselet {
442 fn parse(
443 &self,
444 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
445 left_node: Ast,
446 current_token: (Token, std::ops::Range<usize>),
447 ) -> Result<Ast, util::ParseError> {
448 let my_binding_power = parse::get_binding_power(&ast_op_to_token_op(&self.operator));
449 let right_node = parse::parse_expr(
450 tokens,
451 if self.is_left_associative {
452 my_binding_power
453 } else {
454 my_binding_power - 1
455 },
456 false,
457 )?;
458
459 return Ok(Ast::new(
460 AstNode::BinOpNode(self.operator, Box::new(left_node), Box::new(right_node)),
461 SrcLoc {
462 span: current_token.1,
463 },
464 ));
465 }
466}
467
468pub struct FunCallParselet {}
469impl PostfixParselet for FunCallParselet {
470 fn parse(
471 &self,
472 tokens: &mut Vec<(Token, std::ops::Range<usize>)>,
473 left_node: Ast,
474 _current_token: (Token, std::ops::Range<usize>),
475 ) -> Result<Ast, util::ParseError> {
476 let (args, span_end) = parse::parse_args(tokens)?;
477 let span_start = left_node.src_loc.span.start;
478 return Ok(Ast::new(
479 AstNode::FunCallNode(Box::new(left_node), args),
480 SrcLoc {
481 span: span_start..span_end,
482 },
483 ));
484 }
485}