1use nom::branch::alt;
4use nom::character::complete::multispace1;
5use nom::combinator::map;
6use nom::sequence::{preceded, tuple};
7
8use crate::parsers::{parens, space_separated_list0, ParseResult, Span};
9use crate::parsers::{parse_function_symbol, parse_term};
10use crate::types::FHead;
11
12pub fn parse_f_head<'a, T: Into<Span<'a>>>(input: T) -> ParseResult<'a, FHead> {
33 let simple = map(parse_function_symbol, FHead::new);
34 let simple_parens = map(parens(parse_function_symbol), FHead::new);
35 let with_terms = map(
36 parens(tuple((
37 parse_function_symbol,
38 preceded(multispace1, space_separated_list0(parse_term)),
39 ))),
40 |(symbol, terms)| FHead::new_with_terms(symbol, terms),
41 );
42
43 alt((simple, simple_parens, with_terms))(input.into())
44}
45
46impl crate::parsers::Parser for FHead {
47 type Item = FHead;
48
49 fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
51 parse_f_head(input)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use crate::parsers::UnwrapValue;
58 use crate::{FHead, FunctionSymbol, Parser, Term};
59
60 #[test]
61 fn test_parse() {
62 assert!(FHead::parse("fun-sym").is_value(FHead::new(FunctionSymbol::from_str("fun-sym"))));
63
64 assert!(FHead::parse("(fun-sym)").is_value(FHead::new(FunctionSymbol::from_str("fun-sym"))));
65
66 assert!(
67 FHead::parse("(fun-sym term)").is_value(FHead::new_with_terms(
68 FunctionSymbol::from_str("fun-sym"),
69 [Term::Name("term".into())]
70 ))
71 );
72 }
73}