use nom::branch::alt;
use nom::character::complete::multispace0;
use nom::combinator::map;
use nom::multi::separated_list0;
use nom::sequence::{delimited, tuple};
use nom::IResult;
use nom::error::{make_error, ParseError};
use crate::internal_representation::{CommonIoInteractionInterface, InteractionInternalRepresentation, InteractionOperatorRepresentation};
use crate::from_text::util::delimited_lang_parser::DelimitedInteractionLanguageParser;
pub trait ContextAwareInteractionParser<CioII : CommonIoInteractionInterface> : DelimitedInteractionLanguageParser {
fn parse_operator<'a, E: ParseError<&'a str>>(&self, input : &'a str) ->
IResult<
&'a str,
CioII::InteractionOperatorType,
E
>;
fn parse_explicit_pattern<'a, E: ParseError<&'a str>>(&self, input : &'a str) ->
IResult<
&'a str,
CioII::InteractionLeafPatternType,
E
>;
fn parse_interaction_with_operator_at_root<'a, E: ParseError<&'a str>>(&self,input : &'a str) -> IResult<&'a str,InteractionInternalRepresentation<CioII>,E>
{
let mut parser = tuple(
(
|x| self.parse_operator(x),
multispace0,
nom::character::complete::char(self.left_parenthesis_char()),
multispace0,
separated_list0(
delimited(
multispace0,
nom::character::complete::char(self.separator_char()),
multispace0
),
|x| self.parse_interaction_inner(x)
),
multispace0,
nom::character::complete::char(self.right_parenthesis_char())
)
);
match parser(input) {
IResult::Ok((rem, (operator, _, _, _, operands,_,_))) => {
let arity = operator.arity();
let num_operands = operands.len();
if (operator.is_associative() && num_operands >= 2) || (num_operands==arity) {
IResult::Ok((rem, InteractionInternalRepresentation::Operator(operator,operands)))
} else {
IResult::Err(nom::Err::Error(make_error::<&'a str, E>(input, nom::error::ErrorKind::Count)))
}
},
IResult::Err(e) => {
IResult::Err(e)
}
}
}
fn parse_interaction_inner<'a, E: ParseError<&'a str>>(&self,
input : &'a str) ->
IResult<
&'a str,
InteractionInternalRepresentation<CioII>,
E
> {
delimited(
multispace0,
alt(
(
map(|x| self.parse_explicit_pattern(x),|y| InteractionInternalRepresentation::LeafPattern(y)),
|x| self.parse_interaction_with_operator_at_root(x)
)
),
multispace0
)(input)
}
}