use nom::{
Parser,
branch::alt,
character::complete::{char, multispace0},
multi::many0,
sequence::delimited,
};
use super::parse_pipe_chain;
use super::primitives::{identifier, parse_string_literal};
use crate::filter::ast::{Filter, ObjectKey};
pub fn parse_array_construction(input: &str) -> nom::IResult<&str, Filter> {
let (input, _) = char('[').parse(input)?;
let (input, _) = multispace0(input)?;
if let Ok((input, _)) = char::<_, nom::error::Error<&str>>(']').parse(input) {
return Ok((input, Filter::Array(vec![])));
}
let (input, first) = parse_pipe_chain(input)?;
let (input, rest) = many0(|i| {
let (i, _) = multispace0(i)?;
let (i, _) = char(',').parse(i)?;
let (i, _) = multispace0(i)?;
parse_pipe_chain(i)
})
.parse(input)?;
let (input, _) = multispace0(input)?;
let (input, _) = char(']').parse(input)?;
let mut elements = vec![first];
elements.extend(rest);
Ok((input, Filter::Array(elements)))
}
pub fn parse_object_construction(input: &str) -> nom::IResult<&str, Filter> {
let (input, _) = char('{').parse(input)?;
let (input, _) = multispace0(input)?;
if let Ok((input, _)) = char::<_, nom::error::Error<&str>>('}').parse(input) {
return Ok((input, Filter::Object(vec![])));
}
let (input, first) = parse_object_pair(input)?;
let (input, rest) = many0(|i| {
let (i, _) = delimited(multispace0, char(','), multispace0).parse(i)?;
parse_object_pair(i)
})
.parse(input)?;
let (input, _) = multispace0(input)?;
let (input, _) = char('}').parse(input)?;
let mut pairs = vec![first];
pairs.extend(rest);
Ok((input, Filter::Object(pairs)))
}
fn parse_object_pair(input: &str) -> nom::IResult<&str, (ObjectKey, Filter)> {
let (input, key) = alt((parse_dynamic_key, parse_static_key)).parse(input)?;
let (input, _) = multispace0(input)?;
let (input, _) = char(':').parse(input)?;
let (input, _) = multispace0(input)?;
let (input, value) = parse_pipe_chain(input)?;
Ok((input, (key, value)))
}
fn parse_dynamic_key(input: &str) -> nom::IResult<&str, ObjectKey> {
let (input, _) = char('(').parse(input)?;
let (input, _) = multispace0(input)?;
let (input, filter) = parse_pipe_chain(input)?;
let (input, _) = multispace0(input)?;
let (input, _) = char(')').parse(input)?;
Ok((input, ObjectKey::Dynamic(Box::new(filter))))
}
fn parse_static_key(input: &str) -> nom::IResult<&str, ObjectKey> {
let (input, key) = alt((parse_string_literal, identifier)).parse(input)?;
Ok((input, ObjectKey::Static(key)))
}