use hashbrown::HashSet;
use super::context::ParseContext;
use super::match_algorithms::skip_start_index_forward_to_code;
use super::match_result::MatchResult;
use super::matchable::{Matchable, MatchableCacheKey, MatchableTrait, next_matchable_cache_key};
use super::segments::ErasedSegment;
use crate::dialects::syntax::SyntaxSet;
use crate::errors::SQLParseError;
#[derive(Debug, Clone, PartialEq)]
pub struct LookaheadExclude {
first_token: &'static str,
lookahead_token: &'static str,
cache_key: MatchableCacheKey,
}
impl LookaheadExclude {
pub fn new(first_token: &'static str, lookahead_token: &'static str) -> Self {
Self {
first_token,
lookahead_token,
cache_key: next_matchable_cache_key(),
}
}
}
impl MatchableTrait for LookaheadExclude {
fn elements(&self) -> &[Matchable] {
&[]
}
fn is_optional(&self) -> bool {
false
}
fn simple(
&self,
_parse_context: &ParseContext,
_crumbs: Option<Vec<&str>>,
) -> Option<(HashSet<String>, SyntaxSet)> {
None
}
fn match_segments(
&self,
segments: &[ErasedSegment],
idx: u32,
_parse_context: &mut ParseContext,
) -> Result<MatchResult, SQLParseError> {
if idx >= segments.len() as u32 {
return Ok(MatchResult::empty_at(idx));
}
let current_raw = segments[idx as usize].raw();
if current_raw.eq_ignore_ascii_case(self.first_token) {
let next_idx =
skip_start_index_forward_to_code(segments, idx + 1, segments.len() as u32);
if next_idx < segments.len() as u32 {
let next_raw = segments[next_idx as usize].raw();
if next_raw.eq_ignore_ascii_case(self.lookahead_token) {
return Ok(MatchResult::from_span(idx, idx + 1));
}
}
}
Ok(MatchResult::empty_at(idx))
}
fn cache_key(&self) -> MatchableCacheKey {
self.cache_key
}
}