Skip to main content

pddl_ish_parser/parser/
problem_parser.rs

1use nom::bytes::complete::take_until;
2use nom::{
3    bytes::complete::tag,
4    character::complete::{multispace0, multispace1},
5    sequence::{delimited, preceded},
6};
7use regex::Regex;
8
9use super::action::parse_actions;
10use super::error_context::get_error_context;
11use super::object::parse_objects;
12use crate::models::parser_error::ParserError;
13use crate::models::problem::Problem;
14
15// Function to parse a PDDL problem
16pub fn parse_problem(original_input: &str) -> Result<(String, Problem), ParserError> {
17    // Remove comments
18    let re = Regex::new(r";.*").unwrap();
19    let input_no_comments = re.replace_all(original_input, "").to_string();
20    // eprintln!("input_no_comments: {:?}", input_no_comments);
21    let input = input_no_comments.as_str();
22
23    let (input, _) = tag("(define (problem ")(input).map_err(|err: nom::Err<nom::error::Error<&str>>| ParserError {
24        description: format!("{}", err),
25        code: get_error_context(input),
26    })?;
27    let (input, name) = take_until(")")(input).map_err(|err: nom::Err<nom::error::Error<&str>>| ParserError {
28        description: format!("{}", err),
29        code: get_error_context(input),
30    })?;
31    let (input, _) = tag(")")(input).map_err(|err: nom::Err<nom::error::Error<&str>>| ParserError {
32        description: format!("{}", err),
33        code: get_error_context(input),
34    })?;
35    let (_, domain) = parse_problem_domain(input)?;
36    // eprintln!("domain: {:?}", domain);
37    let (_, objects) = parse_objects(&input_no_comments)?;
38    // eprintln!("objects: {:?}", objects);
39    let (_, actions) = parse_actions(&input_no_comments)?;
40    // eprintln!("actions: {:?}", actions);
41
42    Ok((
43        input_no_comments.clone(),
44        Problem {
45            name: name.to_string().trim().to_owned(),
46            domain,
47            objects,
48            init: vec![],
49            goal: vec![],
50            actions,
51        },
52    ))
53}
54
55pub fn parse_problem_domain(input: &str) -> Result<(&str, String), ParserError> {
56    delimited(
57        multispace0::<&str, ParserError>,
58        preceded(
59            tag("(:domain"),
60            delimited(multispace1::<&str, ParserError>, take_until(")"), tag(")")),
61        ),
62        multispace0::<&str, ParserError>,
63    )(input)
64    .map(|(next_input, domain)| (next_input, domain.to_string()))
65    .map_err(|err| ParserError {
66        description: format!("{}", err),
67        code: get_error_context(input),
68    })
69}