pddl/parsers/
f_head.rs

1//! Provides parsers for f-heads.
2
3use 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
12/// Parses an f-head.
13///
14/// ## Example
15/// ```
16/// # use pddl::parsers::{parse_f_head, preamble::*};
17/// # use pddl::{FunctionTerm, Variable, FunctionSymbol, Term, FHead};
18/// assert!(parse_f_head("fun-sym").is_value(
19///     FHead::new(FunctionSymbol::from_str("fun-sym"))
20/// ));
21///
22/// assert!(parse_f_head("(fun-sym)").is_value(
23///     FHead::new(FunctionSymbol::from_str("fun-sym"))
24/// ));
25///
26/// assert!(parse_f_head("(fun-sym term)").is_value(
27///     FHead::new_with_terms(FunctionSymbol::from_str("fun-sym"), [
28///         Term::Name("term".into())
29///     ])
30/// ));
31///```
32pub 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    /// See [`parse_f_head`].
50    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}