data_query_lexical/
lexer.rs

1use crate::lexer_constants::*;
2use std::collections::LinkedList;
3use std::fmt::Debug;
4use std::num::ParseIntError;
5use std::ops::{Deref, DerefMut};
6
7#[derive(Debug, Eq, PartialEq)]
8pub enum LexerError {
9    EndOfQuery {
10        expected: String,
11        char_pointer: usize,
12        lex: String,
13    },
14    FailedToParseInt(ParseIntError),
15    UnexpectedCharacter {
16        expected: String,
17        found: String,
18        char_pointer: usize,
19        lex: String,
20    },
21}
22
23impl From<ParseIntError> for LexerError {
24    fn from(e: ParseIntError) -> Self {
25        Self::FailedToParseInt(e)
26    }
27}
28
29pub type LexResult<T> = Result<T, LexerError>;
30
31#[derive(Debug, Eq, PartialEq, Clone)]
32pub enum GenericObjectIndex {
33    Wildcard,
34    Slice(LinkedList<Slicer>),
35}
36
37#[derive(Debug, Eq, PartialEq, Clone)]
38pub enum Slicer {
39    Index(usize),
40    Slice(usize, usize),
41    Ident(String),
42}
43
44#[derive(Debug, Eq, PartialEq, Clone)]
45pub enum LexOperator {
46    Identifier(String),
47    Pipe(LinkedList<LexOperator>),
48    Generic(GenericObjectIndex),
49}
50
51#[derive(Debug, Eq, PartialEq, Clone)]
52pub struct LexicalOperations(LinkedList<LexOperator>);
53
54impl From<LinkedList<LexOperator>> for LexicalOperations {
55    fn from(v: LinkedList<LexOperator>) -> Self {
56        Self(v)
57    }
58}
59
60impl Deref for LexicalOperations {
61    type Target = LinkedList<LexOperator>;
62
63    fn deref(&self) -> &Self::Target {
64        &self.0
65    }
66}
67
68impl DerefMut for LexicalOperations {
69    fn deref_mut(&mut self) -> &mut Self::Target {
70        &mut self.0
71    }
72}
73
74impl TryInto<LexicalOperations> for &str {
75    type Error = String;
76
77    fn try_into(self) -> Result<LexicalOperations, String> {
78        compile(self).map_err(|e| format!("{:?}", e))
79    }
80}
81
82pub fn compile(s: &str) -> LexResult<LexicalOperations> {
83    let mut lexer_vec = s.chars().into_iter().collect::<Vec<char>>();
84    lexer_vec.reverse();
85    generic_compiler(
86        &mut lexer_vec,
87        &mut Default::default(),
88        Default::default(),
89        false,
90        Default::default(),
91    )
92    .map(LexicalOperations::from)
93}
94
95pub fn generic_compiler(
96    lexer_vec: &mut Vec<char>,
97    mut operator: &mut LinkedList<LexOperator>,
98    mut collect: String,
99    mut escape: bool,
100    mut char_pointer: usize,
101) -> LexResult<LinkedList<LexOperator>> {
102    let char = lexer_vec.pop();
103    if let Some(c) = char {
104        char_pointer = char_pointer + 1;
105        if !escape {
106            match c {
107                LEX_ESCAPE => {
108                    escape = true;
109                }
110                LEX_IDENTIFIER => {
111                    if !collect.is_empty() {
112                        operator.push_back(LexOperator::Identifier(collect));
113                    }
114                    collect = Default::default();
115                }
116                LEX_GENERIC_START => {
117                    if !collect.is_empty() {
118                        operator.push_back(LexOperator::Identifier(collect));
119                        collect = Default::default();
120                    }
121                    let v = generic_object_index(
122                        lexer_vec,
123                        Default::default(),
124                        LinkedList::new(),
125                        None,
126                        false,
127                        char_pointer,
128                    )?;
129                    operator.push_back(LexOperator::Generic(v));
130                }
131                _ => {
132                    if c != LEX_ROUGE_WIDESPACE {
133                        collect.push(c)
134                    }
135                }
136            }
137        } else {
138            collect.push(c);
139            escape = false;
140        }
141        generic_compiler(lexer_vec, operator, collect, escape, char_pointer)
142    } else {
143        Ok(operator.clone())
144    }
145}
146
147fn generic_object_index(
148    lexer_vec: &mut Vec<char>,
149    mut collect: String,
150    mut slicer: LinkedList<Slicer>,
151    mut tmp_slice: Option<usize>,
152    mut escape: bool,
153    mut char_pointer: usize,
154) -> LexResult<GenericObjectIndex> {
155    let char = lexer_vec.pop();
156    if let Some(c) = char {
157        char_pointer += 1;
158        if !escape {
159            match c {
160                LEX_ESCAPE => {
161                    generic_object_index(lexer_vec, collect, slicer, tmp_slice, true, char_pointer)
162                }
163                LEX_GENERIC_END => {
164                    if collect.is_empty() && slicer.is_empty() {
165                        Ok(GenericObjectIndex::Wildcard)
166                    } else if !collect.is_empty() {
167                        if let Some(from) = tmp_slice {
168                            let to = collect.parse::<usize>().map_err(LexerError::from)?;
169                            slicer.push_back(Slicer::Slice(from, to));
170                            tmp_slice = None;
171                        } else if let Ok(u) = collect.parse::<usize>() {
172                            slicer.push_back(Slicer::Index(u));
173                        } else {
174                            slicer.push_back(Slicer::Ident(collect.clone()));
175                        }
176                        Ok(GenericObjectIndex::Slice(slicer))
177                    } else {
178                        Ok(GenericObjectIndex::Slice(slicer))
179                    }
180                }
181                LEX_GENERIC_SEPARATOR => {
182                    if collect.is_empty() && slicer.is_empty() {
183                        Err(LexerError::UnexpectedCharacter {
184                            expected: "Integer/String".to_string(),
185                            found: LEX_GENERIC_SEPARATOR.to_string(),
186                            char_pointer,
187                            lex: format!("{:?}", lexer_vec),
188                        })
189                    } else {
190                        if let Some(from) = tmp_slice {
191                            let to = collect.parse::<usize>().map_err(LexerError::from)?;
192                            slicer.push_back(Slicer::Slice(from, to));
193                            tmp_slice = None;
194                        } else if let Ok(u) = collect.parse::<usize>() {
195                            slicer.push_back(Slicer::Index(u));
196                        } else {
197                            slicer.push_back(Slicer::Ident(collect.clone()));
198                        }
199                        collect = Default::default();
200                        generic_object_index(
201                            lexer_vec,
202                            collect,
203                            slicer,
204                            tmp_slice,
205                            false,
206                            char_pointer,
207                        )
208                    }
209                }
210                LEX_GENERIC_SLICE => {
211                    if collect.is_empty() && slicer.is_empty() {
212                        return Err(LexerError::UnexpectedCharacter {
213                            expected: "Integer/String".to_string(),
214                            found: LEX_GENERIC_SEPARATOR.to_string(),
215                            char_pointer,
216                            lex: format!("{:?}", lexer_vec),
217                        });
218                    } else if let Ok(u) = collect.parse::<usize>() {
219                        tmp_slice = Some(u);
220                    } else {
221                        return Err(LexerError::UnexpectedCharacter {
222                            expected: "Integer".to_string(),
223                            found: "String".to_string(),
224                            char_pointer,
225                            lex: format!("{:?}", lexer_vec),
226                        });
227                    }
228                    collect = Default::default();
229                    generic_object_index(lexer_vec, collect, slicer, tmp_slice, false, char_pointer)
230                }
231                LEX_ROUGE_WIDESPACE => {
232                    generic_object_index(lexer_vec, collect, slicer, tmp_slice, false, char_pointer)
233                }
234                _ => {
235                    collect.push(c);
236                    generic_object_index(lexer_vec, collect, slicer, tmp_slice, false, char_pointer)
237                }
238            }
239        } else {
240            collect.push(c);
241            generic_object_index(lexer_vec, collect, slicer, tmp_slice, false, char_pointer)
242        }
243    } else {
244        Err(LexerError::EndOfQuery {
245            expected: String::from(LEX_GENERIC_END),
246            char_pointer,
247            lex: format!("{:?}", lexer_vec),
248        })
249    }
250}
251
252#[cfg(test)]
253mod test {
254    use crate::lexer::LexOperator::*;
255    use crate::lexer::Slicer::*;
256    use crate::lexer::{
257        compile, generic_compiler, generic_object_index, GenericObjectIndex, LexOperator,
258        LexResult, Slicer,
259    };
260    use crate::LexicalOperations;
261    use std::collections::LinkedList;
262
263    fn lex_vec(s: &str) -> Vec<char> {
264        s.chars().into_iter().collect::<Vec<char>>()
265    }
266
267    #[test]
268    pub fn test_slicer() {
269        let mut lex_vec = lex_vec("1,2,4-6,hello]");
270        lex_vec.reverse();
271        let slicer = generic_object_index(
272            &mut lex_vec,
273            "".to_string(),
274            LinkedList::new(),
275            None,
276            false,
277            0usize,
278        );
279        let true_generic_object = GenericObjectIndex::Slice(LinkedList::from([
280            Slicer::Index(1),
281            Slicer::Index(2),
282            Slicer::Slice(4, 6),
283            Ident("hello".to_string()),
284        ]));
285
286        assert_eq!(true_generic_object, slicer.unwrap())
287    }
288
289    #[test]
290    pub fn test_generic_compiler() {
291        let mut lex_vec = lex_vec(".metadata[1,2,4-6,hello]");
292        lex_vec.reverse();
293        let mut operator = LinkedList::new();
294        let compiled_lex = generic_compiler(
295            &mut lex_vec,
296            &mut operator,
297            Default::default(),
298            false,
299            Default::default(),
300        );
301        let true_result: LexResult<LinkedList<LexOperator>> = Ok(LinkedList::from([
302            Identifier("metadata".to_string()),
303            Generic(GenericObjectIndex::Slice(LinkedList::from([
304                Index(1),
305                Index(2),
306                Slice(4, 6),
307                Ident("hello".to_string()),
308            ]))),
309        ]));
310        assert_eq!(true_result, compiled_lex);
311    }
312
313    #[test]
314    pub fn test_compiler() {
315        let compiled_lex = compile(".metadata[1,2,4-6,hello]");
316        let true_result: LexResult<LexicalOperations> = Ok(LinkedList::from([
317            Identifier("metadata".to_string()),
318            Generic(GenericObjectIndex::Slice(LinkedList::from([
319                Index(1),
320                Index(2),
321                Slice(4, 6),
322                Ident("hello".to_string()),
323            ]))),
324        ])
325        .into());
326        assert_eq!(true_result, compiled_lex);
327    }
328
329    #[test]
330    pub fn test_lex_escape() {
331        let compiled_lex = compile(".metadata[1,2\\,,4-6,hello]");
332        let true_result: LexResult<LexicalOperations> = Ok(LinkedList::from([
333            Identifier("metadata".to_string()),
334            Generic(GenericObjectIndex::Slice(LinkedList::from([
335                Index(1),
336                Ident("2,".to_string()),
337                Slice(4, 6),
338                Ident("hello".to_string()),
339            ]))),
340        ])
341        .into());
342        assert_eq!(true_result, compiled_lex);
343    }
344
345    #[test]
346    pub fn test_lex_escape_identifier() {
347        let compiled_lex = compile(".meta\\.data[1,2\\,,4-6,hello]");
348        let true_result: LexResult<LexicalOperations> = Ok(LinkedList::from([
349            Identifier("meta.data".to_string()),
350            Generic(GenericObjectIndex::Slice(LinkedList::from([
351                Index(1),
352                Ident("2,".to_string()),
353                Slice(4, 6),
354                Ident("hello".to_string()),
355            ]))),
356        ])
357        .into());
358        assert_eq!(true_result, compiled_lex);
359    }
360}
361
362/*
363
364
365{
366  "default": "Personal",
367  "annotation-field": "annotations",
368  "workspaces": {
369    "Personal": {
370      "HelloWorld": {
371        "annotations": {
372          "my-app.io/group": "HelloWorld"
373        }
374      },
375      "NoWorld": {}
376    }
377  }
378}
379
380
381
382 */