use nom::{
branch::alt,
bytes::complete::escaped_transform,
bytes::complete::{tag, tag_no_case},
character::complete::{none_of, one_of},
combinator::map,
IResult,
};
#[derive(Debug, PartialEq)]
pub enum Column {
Identifier(String),
Asterisk,
}
#[derive(Debug, PartialEq)]
pub enum Variable {
Placeholder,
NamedVariable(String),
}
pub fn parse_variable(input: &str) -> IResult<&str, Variable> {
alt((
map(parse_placeholder, |_| Variable::Placeholder),
map(parse_named_variable, |ident| {
Variable::NamedVariable(ident.to_string())
}),
))(input)
}
fn parse_named_variable(input: &str) -> IResult<&str, &str> {
let (input, _) = tag(":")(input)?;
parse_identifier(input)
}
#[derive(Debug, PartialEq)]
pub enum Value {
Variable(Variable),
Literal(String),
}
pub fn parse_value(input: &str) -> IResult<&str, Value> {
alt((
map(parse_variable, Value::Variable),
map(parse_literal, Value::Literal),
))(input)
}
fn parse_literal(input: &str) -> IResult<&str, String> {
let (input, _) = tag("\"")(input)?;
let (input, literal) = escaped_transform(none_of("\""), '\\', one_of("\""))(input)?;
let (input, _) = tag("\"")(input)?;
Ok((input, literal))
}
pub fn parse_identifier(input: &str) -> IResult<&str, &str> {
nom::character::complete::alpha1(input)
}
fn parse_placeholder(input: &str) -> IResult<&str, String> {
let (input, _) = tag("?")(input)?;
Ok((input, "?".to_string()))
}
pub fn parse_limit_clause(input: &str) -> IResult<&str, Value> {
let (input, _) = tag_no_case("limit ")(input)?;
let (input, limit) = parse_value(input)?;
Ok((input, limit))
}