Actually just three programming languages in a trenchcoat
at main 58 lines 2.1 kB view raw
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}