use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::{alpha1, alphanumeric1, char as nom_char, multispace0};
use nom::combinator::recognize;
use nom::error::ParseError as NomParseError;
use nom::multi::many0_count;
use nom::number::complete::double;
use nom::sequence::{pair, preceded};
use nom::{IResult, Parser};
pub fn ws<'a, F, O, E>(mut inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
where
F: FnMut(&'a str) -> IResult<&'a str, O, E>,
E: NomParseError<&'a str>,
{
move |input| preceded(multispace0, &mut inner).parse(input)
}
pub fn parse_constant(input: &str) -> IResult<&str, f64, nom::error::Error<&str>> {
double.parse(input)
}
pub fn parse_char(c: char) -> impl Fn(&str) -> IResult<&str, char, nom::error::Error<&str>> {
move |input| nom_char(c).parse(input)
}
pub fn parse_identifier(input: &str) -> IResult<&str, &str, nom::error::Error<&str>> {
recognize(pair(
alt((alpha1, tag("_"))),
many0_count(alt((alphanumeric1, tag("_")))),
))
.parse(input)
}
pub fn parse_variable(input: &str) -> IResult<&str, &str, nom::error::Error<&str>> {
parse_identifier(input)
}