Actually just three programming languages in a trenchcoat
1use super::*;
2use crate::{Parser, Spanned, token_pattern::TokenPattern};
3use source_span::Span;
4use trilogy_scanner::{Token, TokenType};
5
6#[derive(Clone, Debug)]
7pub struct FunctionHead {
8 pub func: Token,
9 pub name: Identifier,
10 pub parameters: Vec<Pattern>,
11 pub guard: Option<Guard>,
12 pub span: Span,
13}
14
15impl Spanned for FunctionHead {
16 fn span(&self) -> Span {
17 self.span
18 }
19}
20
21impl FunctionHead {
22 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> {
23 let func = parser.expect(TokenType::KwFunc).unwrap();
24 let name = Identifier::parse(parser)?;
25 let mut parameters = vec![];
26 loop {
27 parameters.push(Pattern::parse(parser)?);
28 if !Pattern::PREFIX.matches(parser.peek()) {
29 break;
30 }
31 }
32 let guard = Guard::parse_optional(parser)?;
33 Ok(Self {
34 span: func.span.union(parameters.last().unwrap().span()),
35 func,
36 name,
37 guard,
38 parameters,
39 })
40 }
41}
42
43#[cfg(test)]
44mod test {
45 use super::*;
46
47 test_parse!(funchead_one_param: "func hello x" => FunctionHead::parse => FunctionHead { parameters: [_], .. });
48 test_parse!(funchead_multi_param: "func hello x y z" => FunctionHead::parse => FunctionHead { parameters: [_, _, _], .. });
49 test_parse!(funchead_pattern_param: "func find f x:xs" => FunctionHead::parse => FunctionHead { parameters: [_, _], .. });
50 test_parse!(funchead_guarded: "func find f x if x" => FunctionHead::parse => FunctionHead { parameters: [_, _], guard: Some(..), .. });
51 test_parse_error!(funchead_invalid_param: "func unadd (x + y)" => FunctionHead::parse);
52}