use winnow::{
combinator::alt,
error::{AddContext, FromExternalError, ParserError, StrContext, TreeError},
PResult, Parser,
};
use crate::{
comments::space_or_comment,
constraints::{constraint_item, ConstraintItem},
parameters::declarations as parameter_declarations,
parameters::declarations::ParDeclItem,
predicates::declarations as predicate_declarations,
predicates::declarations::PredicateItem,
solve_items::{solve_item, SolveItem},
variables::declarations as variable_declarations,
variables::declarations::VarDeclItem,
};
#[derive(PartialEq, Clone, Debug)]
pub enum Stmt {
Comment(String),
Predicate(PredicateItem),
Parameter(ParDeclItem),
Variable(VarDeclItem),
Constraint(ConstraintItem),
SolveItem(SolveItem),
}
impl std::str::FromStr for Stmt {
type Err = String;
fn from_str(input: &str) -> Result<Self, Self::Err> {
statement::<TreeError<&str>>()
.context(StrContext::Label("Error while parsing statement"))
.parse(input)
.map_err(|e| e.to_string())
}
}
fn statement<'a, E>() -> impl Parser<&'a str, Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>
+ AddContext<&'a str, StrContext>,
{
alt((
stmt_predicate,
stmt_parameter,
stmt_variable,
stmt_constraint,
stmt_solve_item,
space_or_comment,
))
}
fn stmt_predicate<'a, E>(input: &mut &'a str) -> PResult<Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>
+ AddContext<&'a str, StrContext>,
{
let item = predicate_declarations::predicate_item(input)?;
Ok(Stmt::Predicate(item))
}
fn stmt_parameter<'a, E>(input: &mut &'a str) -> PResult<Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
let item = parameter_declarations::par_decl_item(input)?;
Ok(Stmt::Parameter(item))
}
fn stmt_variable<'a, E>(input: &mut &'a str) -> PResult<Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
let item = variable_declarations::var_decl_item(input)?;
Ok(Stmt::Variable(item))
}
fn stmt_constraint<'a, E>(input: &mut &'a str) -> PResult<Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>
+ AddContext<&'a str, StrContext>,
{
let item = constraint_item(input)?;
Ok(Stmt::Constraint(item))
}
fn stmt_solve_item<'a, E>(input: &mut &'a str) -> PResult<Stmt, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>
+ AddContext<&'a str, StrContext>,
{
let item = solve_item(input)?;
Ok(Stmt::SolveItem(item))
}