1use std::fmt::Display;
3
4use nom::{
5 branch::alt,
6 bytes::complete::{tag, tag_no_case},
7 character::complete::{alpha1, alphanumeric1, digit1},
8 combinator::{map, recognize},
9 error::{ErrorKind, ParseError},
10 multi::many0_count,
11 sequence::{delimited, pair},
12 IResult, InputLength,
13};
14
15use crate::reserved::parse_cql_keyword;
16
17#[derive(Debug, PartialEq)]
19pub enum Column {
20 Identifier(String),
23 Asterisk,
25}
26
27#[derive(Debug, PartialEq)]
29pub enum Variable {
30 Placeholder,
32 NamedVariable(String),
34}
35
36impl Display for Variable {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 Variable::Placeholder => write!(f, "?"),
40 Variable::NamedVariable(ident) => write!(f, ":{}", ident),
41 }
42 }
43}
44
45pub fn parse_variable(input: &str) -> IResult<&str, Variable> {
47 alt((
48 map(parse_placeholder, |_| Variable::Placeholder),
49 map(parse_named_variable, |ident| {
50 if parse_cql_keyword(ident).is_ok() {
52 panic!("variable `{ident}` is a reserved keyword");
53 }
54
55 Variable::NamedVariable(ident.to_string())
56 }),
57 ))(input)
58}
59
60fn parse_named_variable(input: &str) -> IResult<&str, &str> {
62 let (input, _) = tag(":")(input)?;
63 parse_identifier(input)
64}
65
66#[derive(Debug, PartialEq)]
68pub enum Value {
69 Variable(Variable),
71 Literal(String),
73 Number(usize),
75 Boolean(bool),
77}
78
79pub fn parse_value(input: &str) -> IResult<&str, Value> {
81 alt((
82 map(parse_boolean, Value::Boolean),
83 map(parse_variable, Value::Variable),
84 map(parse_number, Value::Number),
85 map(parse_string, Value::Literal), ))(input)
87}
88
89fn parse_string(input: &str) -> IResult<&str, String> {
94 let (input, alpha) = alt((
95 map(parse_escaped, |x| format!("\"{x}\"")),
97 map(alpha1, |x: &str| x.to_string()),
98 ))(input)?;
99
100 Ok((input, alpha.clone()))
101}
102
103pub fn parse_escaped(input: &str) -> IResult<&str, String> {
105 let (input, alpha) = delimited(tag("\""), alpha1, tag("\""))(input)?;
106 Ok((input, alpha.to_string()))
107}
108
109fn parse_number(input: &str) -> IResult<&str, usize> {
111 let (input, number) = digit1(input)?;
112 Ok((input, number.parse().unwrap()))
113}
114
115fn parse_boolean(input: &str) -> IResult<&str, bool> {
117 let (input, boolean) = alt((
118 map(tag_no_case("true"), |_| true),
119 map(tag_no_case("false"), |_| false),
120 ))(input)?;
121
122 Ok((input, boolean))
123}
124
125pub fn parse_string_escaped_rust_flavored_variable(input: &str) -> IResult<&str, String> {
127 let (input, alpha) = delimited(tag("\""), parse_rust_flavored_variable, tag("\""))(input)?;
128 Ok((input, alpha.to_string()))
129}
130
131pub fn parse_rust_flavored_variable(input: &str) -> IResult<&str, &str> {
133 recognize(pair(
134 alt((alpha1, tag("_"))),
135 many0_count(alt((alphanumeric1, tag("_")))),
136 ))(input)
137}
138
139pub fn parse_identifier(input: &str) -> IResult<&str, &str> {
141 parse_rust_flavored_variable(input)
142}
143
144fn parse_placeholder(input: &str) -> IResult<&str, String> {
146 let (input, _) = tag("?")(input)?;
147 Ok((input, "?".to_string()))
148}
149
150pub fn parse_limit_clause(input: &str) -> IResult<&str, Value> {
152 let (input, _) = tag_no_case("limit ")(input)?;
153 let (input, limit) = parse_value(input)?;
154
155 Ok((input, limit))
156}
157
158pub(crate) fn eof<I: Copy + InputLength, E: ParseError<I>>(input: I) -> IResult<I, I, E> {
160 if input.input_len() == 0 {
161 Ok((input, input))
162 } else {
163 Err(nom::Err::Error(E::from_error_kind(input, ErrorKind::Eof)))
164 }
165}
166
167#[cfg(test)]
168mod test {
169 #[test]
170 fn test_regular_literal() {
171 assert_eq!(super::parse_string("foo"), Ok(("", "foo".to_string())));
172 }
173
174 #[test]
176 fn test_escaped_literal() {
177 assert_eq!(
178 super::parse_string(r#""foo""#),
179 Ok(("", r#""foo""#.to_string()))
180 );
181 }
182}