1use std::cell::Cell;
4use std::hash::Hash;
5
6pub trait Lexer<'a> {
8 type Token: Copy + Eq;
10 type Position: Copy + Eq + Ord + Hash;
12
13 fn new(input: &'a str) -> Self;
15
16 fn pos(&self) -> Self::Position;
18
19 fn next(&self) -> (Option<Self::Token>, usize);
21
22 fn is_empty(&self) -> bool;
24
25 fn advance_to_pos(&self, pos: Self::Position);
27
28 fn fork(&self) -> Self;
30}
31
32pub struct CharLexer<'a> {
34 pos: Cell<usize>,
35 remaining: Cell<&'a str>,
36}
37
38impl<'a> Lexer<'a> for CharLexer<'a> {
39 type Token = char;
40 type Position = usize;
41
42 fn new(input: &'a str) -> Self {
43 Self {
44 pos: Cell::new(0),
45 remaining: Cell::new(input),
46 }
47 }
48
49 fn pos(&self) -> Self::Position {
50 self.pos.get()
51 }
52
53 fn next(&self) -> (Option<Self::Token>, usize) {
54 let start = self.pos.get();
55 let mut chars = self.remaining.get().chars();
56 if let Some(c) = chars.next() {
57 let advance = c.len_utf8();
58 let remaining = chars.as_str();
59
60 self.pos.set(start + advance);
61 self.remaining.set(remaining);
62
63 (Some(c), advance)
64 } else {
65 (None, 0)
66 }
67 }
68
69 fn is_empty(&self) -> bool {
70 self.remaining.get().is_empty()
71 }
72
73 fn advance_to_pos(&self, pos: Self::Position) {
74 let advance = pos - self.pos.get();
75 self.pos.set(pos);
76 self.remaining.set(&self.remaining.get()[advance..]);
77 }
78
79 fn fork(&self) -> Self {
80 Self {
81 pos: self.pos.clone(),
82 remaining: self.remaining.clone(),
83 }
84 }
85}