Skip to main content

pddl_ish_parser/parser/
predicate.rs

1use regex::Regex;
2
3use crate::models::parser_error::ParserError;
4
5use super::{error_context::get_error_context, parameter::Parameter, utils::extract_balanced};
6
7#[derive(Debug, PartialEq, Clone)]
8pub struct Predicate {
9    pub name: String,
10    pub parameters: Vec<Parameter>,
11}
12
13pub fn parse_predicate_line(line: &str) -> Option<Predicate> {
14    // eprintln!("line: {:?}", line);
15    let parts: Vec<&str> = line.split_whitespace().collect();
16
17    let name = parts[0].trim_matches('(').to_string();
18    let mut parameters = Vec::new();
19
20    let mut i = 1;
21    while i < parts.len() {
22        if parts[i] == "-" {
23            if i + 1 < parts.len() {
24                parameters.push(Parameter {
25                    name: parts[i - 1].to_string(),
26                    param_type: parts[i + 1].trim_matches(')').to_string(),
27                });
28                i += 2;
29            } else {
30                return None;
31            }
32        } else {
33            i += 1;
34        }
35    }
36
37    Some(Predicate { name, parameters })
38}
39
40pub fn parse_predicates(input: &str) -> Result<(&str, Vec<Predicate>), ParserError> {
41    // Find the start of the predicates block
42    let start_index = input
43        .find("(:predicates")
44        .ok_or(ParserError::new("Could not find '(:predicates'".to_string(), "PREDICATES_NOT_FOUND".to_string()))?;
45
46    // Extract the predicates block
47    let predicates_block = extract_balanced(&input[start_index..], '(', ')')?;
48
49    let predicates: Vec<Predicate> = predicates_block
50        .lines()
51        .map(|line| line.trim())
52        .filter(|line| !line.is_empty() && line.starts_with("(") && line.ends_with(")"))
53        .filter_map(parse_predicate_line)
54        .collect();
55
56    let next_input = &input[start_index + predicates_block.len()..];
57    Ok((next_input, predicates))
58}