1pub struct Lexer<'a> {
2 on: &'a str,
3 idx: usize,
4}
5
6impl<'a> Lexer<'a> {
7 pub fn new(on: &'a str) -> Self {
8 Self { on, idx: 0 }
9 }
10
11 pub(crate) fn current(&self) -> &'a str {
12 &self.on[self.idx..]
13 }
14
15 pub(crate) fn finished(&self) -> bool {
16 self.current().is_empty()
17 }
18
19 pub(crate) fn skip(&mut self) {
20 let current = self.current();
21 let idx = current.find(|chr: char| !chr.is_whitespace()).unwrap_or(current.len());
22 self.advance(idx);
23 }
24
25 pub(crate) fn parse_identifier(&mut self) -> &'a str {
27 self.skip();
28 let current = self.current();
29 if let Some(rest) = current.strip_prefix('"') {
30 let next = rest.find('"').unwrap();
31 self.advance(next + 2);
32 ¤t[..(next + 2)]
33 } else {
34 for (idx, chr) in current.char_indices() {
35 if !(chr.is_alphanumeric() || matches!(chr, '.')) {
36 self.advance(idx);
37 return ¤t[..idx];
38 }
39 }
40 self.advance(current.len());
41 assert!(!current.is_empty(), "empty identifier");
42 current
43 }
44 }
45
46 pub(crate) fn starts_with(&mut self, slice: &str) -> bool {
47 self.skip();
48 let current = self.current();
49 let matches = current.starts_with(slice);
50 let is_not_actually_operator = matches
52 && slice.chars().all(char::is_alphanumeric)
53 && current[slice.len()..].chars().next().is_some_and(char::is_alphanumeric);
54
55 if is_not_actually_operator { false } else { matches }
56 }
57
58 pub(crate) fn starts_with_value(&mut self) -> bool {
59 self.skip();
60 let current = self.current();
61 current
62 .starts_with(|chr: char| chr.is_alphanumeric() || matches!(chr, '"' | '\'' | '(' | '['))
63 }
64
65 pub(crate) fn advance(&mut self, idx: usize) {
66 self.idx += idx;
67 }
68}