1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::any::Any;
use std::fmt::Debug;
use std::sync::Arc;

use ahash::AHashSet;
use dyn_clone::DynClone;
use dyn_ord::DynEq;

use super::context::ParseContext;
use super::grammar::base::Ref;
use super::match_result::MatchResult;
use super::segments::base::{ErasedSegment, Segment};
use crate::core::errors::SQLParseError;

// Define a trait to represent the Matchable interface.
// This trait is similar to the abstract base class in Python.
pub trait Matchable: Any + Segment + DynClone + Debug + DynEq {
    fn mk_from_segments(&self, segments: Vec<ErasedSegment>) -> ErasedSegment {
        let _ = segments;
        unimplemented!("{}", std::any::type_name::<Self>())
    }

    fn hack_eq(&self, rhs: &Arc<dyn Matchable>) -> bool {
        let lhs = self.as_any().downcast_ref::<Ref>();
        let rhs = rhs.as_any().downcast_ref::<Ref>();

        lhs.zip(rhs).map_or(false, |(lhs, rhs)| lhs.reference == rhs.reference)
    }

    // Return whether this element is optional.
    fn is_optional(&self) -> bool {
        false
    }

    // Try to obtain a simple response from the matcher.
    // Returns a tuple of two sets of strings if simple.
    // The first is a set of uppercase raw strings which would match.
    // The second is a set of segment types that would match.
    // Returns None if not simple.
    // Note: the crumbs argument is used to detect recursion.

    fn simple(
        &self,
        parse_context: &ParseContext,
        crumbs: Option<Vec<&str>>,
    ) -> Option<(AHashSet<String>, AHashSet<String>)> {
        let match_grammar = self.match_grammar()?;

        match_grammar.simple(parse_context, crumbs)
    }

    // Match against this matcher.

    fn match_segments(
        &self,
        segments: &[ErasedSegment],
        parse_context: &mut ParseContext,
    ) -> Result<MatchResult, SQLParseError> {
        let Some(match_grammar) = self.match_grammar() else {
            unimplemented!("{} has no match function implemented", std::any::type_name::<Self>())
        };

        if segments.len() == 1 && segments[0].get_type() == self.get_type() {
            return Ok(MatchResult::from_matched(segments.to_vec()));
        } else if segments.len() > 1 && segments[0].get_type() == self.get_type() {
            let (first_segment, remaining_segments) =
                segments.split_first().expect("segments should not be empty");
            return Ok(MatchResult {
                matched_segments: vec![first_segment.clone()],
                unmatched_segments: remaining_segments.to_vec(),
            });
        }

        let match_result = match_grammar.match_segments(segments, parse_context)?;

        if match_result.has_match() {
            Ok(MatchResult {
                matched_segments: vec![self.mk_from_segments(match_result.matched_segments)],
                unmatched_segments: match_result.unmatched_segments,
            })
        } else {
            Ok(MatchResult::from_unmatched(segments.to_vec()))
        }
    }

    // A method to generate a unique cache key for the matchable object.
    //
    // Returns none for no caching key
    fn cache_key(&self) -> Option<uuid::Uuid> {
        unimplemented!("{}", std::any::type_name::<Self>())
    }

    fn copy(
        &self,
        _insert: Option<Vec<Arc<dyn Matchable>>>,
        _at: Option<usize>,
        _before: Option<Arc<dyn Matchable>>,
        _remove: Option<Vec<Arc<dyn Matchable>>>,
        _terminators: Vec<Arc<dyn Matchable>>,
        _replace_terminators: bool,
    ) -> Arc<dyn Matchable> {
        unimplemented!()
    }
}

dyn_clone::clone_trait_object!(Matchable);
dyn_hash::hash_trait_object!(Matchable);