general_parser/
lexer.rs

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	// TODO some of these temp
26	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			&current[..(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 &current[..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		// fix for or with orpington
51		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}