1use nom::branch::alt;
4use nom::bytes::complete::tag;
5use nom::character::complete::multispace1;
6use nom::combinator::map;
7use nom::sequence::{preceded, terminated, tuple};
8
9use crate::parsers::prefix_expr;
10use crate::parsers::{parse_f_exp, ParseResult, Span};
11use crate::types::FExpT;
12
13pub fn parse_f_exp_t<'a, T: Into<Span<'a>>>(input: T) -> ParseResult<'a, FExpT> {
44 let now = map(tag("#t"), |_| FExpT::new());
45 let scaled = map(
46 prefix_expr(
47 "*",
48 alt((
49 preceded(tuple((tag("#t"), multispace1)), parse_f_exp),
50 terminated(parse_f_exp, tuple((multispace1, tag("#t")))),
51 )),
52 ),
53 FExpT::new_scaled,
54 );
55
56 alt((scaled, now))(input.into())
57}
58
59impl crate::parsers::Parser for FExpT {
60 type Item = FExpT;
61
62 fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
64 parse_f_exp_t(input)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use crate::parsers::UnwrapValue;
71 use crate::{FExp, FExpT, FHead, FunctionSymbol, Parser, Term, Variable};
72
73 #[test]
74 fn test_parse() {
75 assert!(FExpT::parse("#t").is_value(FExpT::Now));
76
77 assert!(
78 FExpT::parse("(* (fuel ?tank) #t)").is_value(FExpT::new_scaled(FExp::new_function(
79 FHead::new_with_terms(
80 FunctionSymbol::from_str("fuel"),
81 [Term::Variable(Variable::from_str("tank"))]
82 )
83 )))
84 );
85
86 assert!(
87 FExpT::parse("(* #t (fuel ?tank))").is_value(FExpT::new_scaled(FExp::new_function(
88 FHead::new_with_terms(
89 FunctionSymbol::from_str("fuel"),
90 [Term::Variable(Variable::from_str("tank"))]
91 )
92 )))
93 );
94 }
95}