pddl_ish_parser/parser/
predicate.rs1use 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 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 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 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}