use super::super::super::{
comment::shouldbespace,
ending,
error::expected,
literal::{filters, ident, strand, tokenizer::tokenizers},
IResult,
};
use crate::sql::Ident;
use crate::sql::{filter::Filter, statements::DefineAnalyzerStatement, Strand, Tokenizer};
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
use nom::{bytes::complete::tag, combinator::opt, sequence::tuple};
pub fn analyzer(i: &str) -> IResult<&str, DefineAnalyzerStatement> {
let (i, _) = tag_no_case("ANALYZER")(i)?;
let (i, if_not_exists) = opt(tuple((
shouldbespace,
tag_no_case("IF"),
shouldbespace,
tag_no_case("NOT"),
shouldbespace,
cut(tag_no_case("EXISTS")),
)))(i)?;
let (i, _) = shouldbespace(i)?;
let (i, name) = cut(ident)(i)?;
let (i, opts) = many0(analyzer_opts)(i)?;
let (i, _) = expected("one of FUNCTION, FILTERS, TOKENIZERS, or COMMENT", ending::query)(i)?;
let mut res = DefineAnalyzerStatement {
name,
if_not_exists: if_not_exists.is_some(),
..Default::default()
};
for opt in opts {
match opt {
DefineAnalyzerOption::Function(i) => {
res.function = Some(i);
}
DefineAnalyzerOption::Comment(v) => {
res.comment = Some(v);
}
DefineAnalyzerOption::Filters(v) => {
res.filters = Some(v);
}
DefineAnalyzerOption::Tokenizers(v) => {
res.tokenizers = Some(v);
}
}
}
Ok((i, res))
}
enum DefineAnalyzerOption {
Function(Ident),
Comment(Strand),
Filters(Vec<Filter>),
Tokenizers(Vec<Tokenizer>),
}
fn analyzer_opts(i: &str) -> IResult<&str, DefineAnalyzerOption> {
alt((analyzer_function, analyzer_comment, analyzer_filters, analyzer_tokenizers))(i)
}
fn analyzer_function(i: &str) -> IResult<&str, DefineAnalyzerOption> {
let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("FUNCTION")(i)?;
let (i, _) = shouldbespace(i)?;
let (i, _) = tag("fn::")(i)?;
let (i, name) = ident(i)?;
Ok((i, DefineAnalyzerOption::Function(name)))
}
fn analyzer_comment(i: &str) -> IResult<&str, DefineAnalyzerOption> {
let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("COMMENT")(i)?;
let (i, _) = shouldbespace(i)?;
let (i, v) = cut(strand)(i)?;
Ok((i, DefineAnalyzerOption::Comment(v)))
}
fn analyzer_filters(i: &str) -> IResult<&str, DefineAnalyzerOption> {
let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("FILTERS")(i)?;
let (i, _) = shouldbespace(i)?;
let (i, v) = cut(filters)(i)?;
Ok((i, DefineAnalyzerOption::Filters(v)))
}
fn analyzer_tokenizers(i: &str) -> IResult<&str, DefineAnalyzerOption> {
let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("TOKENIZERS")(i)?;
let (i, _) = shouldbespace(i)?;
let (i, v) = cut(tokenizers)(i)?;
Ok((i, DefineAnalyzerOption::Tokenizers(v)))
}