1use std::hash::Hash;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct Span {
8 pub start: usize,
10 pub end: usize,
12}
13
14pub trait Lexer<'a> {
16 type Token: Eq;
18 type Position: Clone + Hash + Eq + PartialOrd;
20
21 fn new(input: &'a str) -> Self;
23
24 fn lexeme(&self) -> &str;
26
27 fn span(&self) -> Span;
29
30 fn pos(&self) -> &Self::Position;
32
33 fn next(&mut self) -> Option<Self::Token>;
35
36 fn is_empty(&self) -> bool;
38
39 fn advance_to_pos(&mut self, pos: &Self::Position);
41
42 fn fork(&self) -> Self;
44}
45
46#[derive(Clone)]
48pub struct CharLexer<'a> {
49 pos: usize,
50 current: char,
51 remaining: &'a str,
52}
53
54impl<'a> Lexer<'a> for CharLexer<'a> {
55 type Token = char;
56 type Position = usize;
57
58 fn new(input: &'a str) -> Self {
59 Self {
60 pos: 0,
61 current: input.chars().next().unwrap_or_default(),
62 remaining: input,
63 }
64 }
65
66 fn lexeme(&self) -> &str {
67 self.remaining
68 }
69
70 fn span(&self) -> Span {
71 Span {
72 start: self.pos,
73 end: self.pos + self.current.len_utf8(),
74 }
75 }
76
77 fn pos(&self) -> &Self::Position {
78 &self.pos
79 }
80
81 fn next(&mut self) -> Option<Self::Token> {
82 let start = self.pos;
83 let mut chars = self.remaining.chars();
84 if let Some(c) = chars.next() {
85 let advance = c.len_utf8();
86 let remaining = chars.as_str();
87
88 self.pos = start + advance;
89 self.current = c;
90 self.remaining = remaining;
91
92 Some(c)
93 } else {
94 None
95 }
96 }
97
98 fn is_empty(&self) -> bool {
99 self.remaining.is_empty()
100 }
101
102 fn advance_to_pos(&mut self, pos: &usize) {
103 self.pos = *pos;
104 self.remaining = &self.remaining[self.pos..];
105 self.current = self.remaining.chars().next().unwrap_or_default();
106 }
107
108 fn fork(&self) -> Self {
109 self.clone()
110 }
111}