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 for (idx, chr) in self.current().char_indices() {
21 if !chr.is_whitespace() {
22 self.advance(idx);
23 break;
24 }
25 }
26 }
27
28 pub(crate) fn parse_identifier(&mut self) -> &'a str {
30 self.skip();
31 let current = self.current();
32 if let Some(rest) = current.strip_prefix('"') {
33 let next = rest.find('"').unwrap();
34 self.advance(next + 2);
35 ¤t[..(next + 2)]
36 } else {
37 for (idx, chr) in current.char_indices() {
38 if !(chr.is_alphanumeric() || matches!(chr, '.')) {
39 self.advance(idx);
40 return ¤t[..idx];
41 }
42 }
43 self.advance(current.len());
44 assert!(!current.is_empty(), "empty identifier");
45 current
46 }
47 }
48
49 pub(crate) fn starts_with(&mut self, slice: &str) -> bool {
50 self.skip();
51 let current = self.current();
52 let matches = current.starts_with(slice);
53 let is_not_actually_operator = matches
54 && slice.chars().all(char::is_alphanumeric)
55 && current[slice.len()..].chars().next().is_some_and(char::is_alphanumeric);
56
57 if is_not_actually_operator { false } else { matches }
58 }
59
60 pub(crate) fn starts_with_value(&mut self) -> bool {
61 self.skip();
62 let current = self.current();
63 current.starts_with(|chr: char| chr.is_alphanumeric() || matches!(chr, '"' | '(' | '['))
64 }
65
66 pub(crate) fn advance(&mut self, idx: usize) {
67 self.idx += idx;
68 }
69}