Actually just three programming languages in a trenchcoat
1use super::{expression::Precedence, *};
2use crate::{Parser, Spanned, TokenPattern};
3use source_span::Span;
4
5#[derive(Clone, Debug)]
6pub struct FunctionAssignment {
7 pub lhs: Expression,
8 pub function: Identifier,
9 pub arguments: Vec<Expression>,
10 pub span: Span,
11}
12
13impl Spanned for FunctionAssignment {
14 fn span(&self) -> Span {
15 self.span
16 }
17}
18
19impl FunctionAssignment {
20 pub(crate) fn parse(parser: &mut Parser, lhs: Expression) -> SyntaxResult<Self> {
21 let function = Identifier::parse_eq(parser)?;
22 let mut arguments = vec![];
23 loop {
24 // NOTE: This has potential to be a pretty unintuitive parse. Sugar
25 // was never that healthy I suppose.
26 arguments.push(Expression::parse_precedence(
27 parser,
28 Precedence::Application,
29 )?);
30 parser.chomp(); // to ensure any line ending is detected
31 if parser.is_line_start || !Expression::PREFIX.matches(parser.peek()) {
32 break;
33 }
34 }
35
36 let span = lhs.span().union(arguments.last().unwrap().span());
37
38 Ok(Self {
39 lhs,
40 function,
41 arguments,
42 span,
43 })
44 }
45}
46
47#[cfg(test)]
48mod test {
49 use super::*;
50
51 test_parse!(fn_assignment_single_arg: "xs push= x" => Statement::parse => Statement::FunctionAssignment(FunctionAssignment { arguments: [_], .. }));
52 test_parse!(fn_assignment_multi_arg: "xs fold= x f" => Statement::parse => Statement::FunctionAssignment(FunctionAssignment { arguments: [_, _], .. }));
53 test_parse!(fn_assignment_operators_paren: "xs push= (x + y)" => Statement::parse => Statement::FunctionAssignment(FunctionAssignment { arguments: [_], .. }));
54 test_parse_error!(fn_assignment_no_arg: "xs reverse=" => Statement::parse);
55 test_parse_error!(fn_assignment_lhs_not_lvalue: "xs ys push= x y" => Statement::parse);
56 test_parse_error!(fn_assignment_spaced: "xs push = x" => Statement::parse);
57 test_parse_error!(fn_assignment_operators: "xs push= x + y" => Statement::parse);
58}