sqruff_lib_core/parser/
parser.rs

1use ahash::AHashMap;
2
3use super::context::ParseContext;
4use super::segments::base::{ErasedSegment, Tables};
5use crate::dialects::base::Dialect;
6use crate::errors::SQLParseError;
7use crate::parser::segments::file::FileSegment;
8
9#[derive(Clone)]
10pub struct Parser<'a> {
11    dialect: &'a Dialect,
12    pub(crate) indentation_config: AHashMap<String, bool>,
13}
14
15impl<'a> From<&'a Dialect> for Parser<'a> {
16    fn from(value: &'a Dialect) -> Self {
17        Self {
18            dialect: value,
19            indentation_config: AHashMap::new(),
20        }
21    }
22}
23
24impl<'a> Parser<'a> {
25    pub fn new(dialect: &'a Dialect, indentation_config: AHashMap<String, bool>) -> Self {
26        Self {
27            dialect,
28            indentation_config,
29        }
30    }
31
32    pub fn dialect(&self) -> &Dialect {
33        self.dialect
34    }
35
36    pub fn indentation_config(&self) -> &AHashMap<String, bool> {
37        &self.indentation_config
38    }
39
40    pub fn parse(
41        &self,
42        tables: &Tables,
43        segments: &[ErasedSegment],
44        filename: Option<String>,
45    ) -> Result<Option<ErasedSegment>, SQLParseError> {
46        if segments.is_empty() {
47            // This should normally never happen because there will usually
48            // be an end_of_file segment. It would probably only happen in
49            // api use cases.
50            return Ok(None);
51        }
52
53        // NOTE: This is the only time we use the parse context not in the
54        // context of a context manager. That's because it's the initial
55        // instantiation.
56        let mut parse_cx: ParseContext = self.into();
57        // Kick off parsing with the root segment. The BaseFileSegment has
58        // a unique entry point to facilitate exaclty this. All other segments
59        // will use the standard .match()/.parse() route.
60        let root = FileSegment.root_parse(
61            tables,
62            parse_cx.dialect().name,
63            segments,
64            &mut parse_cx,
65            filename,
66        )?;
67
68        // Basic Validation, that we haven't dropped anything.
69        super::helpers::check_still_complete(segments, &[root.clone()], &[]);
70
71        Ok(root.into())
72    }
73}