flams_utils/parsing/
string.rs1use crate::{
2 CharExt,
3 parsing::SourceParser,
4 sourcerefs::{PositionKind, StringPosition},
5};
6
7pub struct StrParser<'a, P: StringPosition> {
8 input: &'a str,
9 pub pos: P,
10}
11
12impl<'a, P: StringPosition> StrParser<'a, P> {
13 #[must_use]
14 pub fn new(input: &'a str) -> Self {
15 Self {
16 input,
17 pos: P::default(),
18 }
19 }
20 #[inline]
21 pub const fn rest(&self) -> &'a str {
22 self.input
23 }
24
25 pub fn read_until_is(&mut self, mut pred: impl FnMut(&'a str) -> bool) -> &'a str {
26 let mut curr = self.input;
27 while !curr.is_empty() {
28 if pred(curr) {
29 let ret = &self.input[..self.input.len() - curr.len()];
30 self.input = curr;
31 self.pos += P::len(ret);
32 return ret;
33 }
34 if let Some(next) = curr.chars().next() {
35 curr = &curr[next.len_utf8()..];
36 }
37 }
38 self.pos += P::len(self.input);
39 std::mem::take(&mut self.input)
40 }
41
42 pub fn preview_until_with_brackets(
43 &self,
44 open: char,
45 close: char,
46 mut pred: impl FnMut(char) -> bool,
47 ) -> &'a str {
48 let mut depth = 0;
49 let i = self
50 .input
51 .find(|c| {
52 if c == open {
53 depth += 1;
54 false
55 } else if c == close && depth > 0 {
56 depth -= 1;
57 false
58 } else {
59 depth == 0 && pred(c)
60 }
61 })
62 .unwrap_or(self.input.len());
63 let (l, _r) = self.input.split_at(i);
64 l
65 }
66
67 pub fn read_until_escaped(&mut self, find: char, escape: char) -> &'a str {
68 let mut chars = self.input.chars();
69 let mut i: usize = 0;
70 while let Some(c) = chars.next() {
71 if c == escape {
72 if let Some(c) = chars.next() {
73 i += c.len_utf8();
74 }
75 } else if c == find {
76 let (l, r) = self.input.split_at(i);
77 self.input = r;
78 self.pos += P::len(l);
79 return l;
80 }
81 i += c.len_utf8();
82 }
83 let ret = self.input;
84 self.input = "";
85 self.pos += P::len(ret);
86 ret
87 }
88}
89
90impl<'a, P: StringPosition> SourceParser<'a> for StrParser<'a, P> {
91 type Pos = P;
92 type Str = &'a str;
93 type Source = &'a str;
94
95 #[inline]
96 fn curr_pos(&self) -> P {
97 self.pos
98 }
99
100 #[inline]
101 fn starts_with_str(&mut self, s: &str) -> bool {
102 self.input.starts_with(s)
103 }
104 fn drop_prefix(&mut self, s: &str) -> bool {
105 self.input.starts_with(s) && {
106 self.input = &self.input[s.len()..];
107 self.pos += P::len(s);
108 true
109 }
110 }
111
112 fn next_char(&mut self) -> Option<char> {
113 if self.input.starts_with(['\r', '\n']) {
114 if self.input.starts_with("\r\n") {
115 self.input = &self.input[2..];
116 self.pos.inc_newline(true);
117 } else {
118 self.input = &self.input[1..];
119 self.pos.inc_newline(false);
120 }
121 return Some('\n');
122 }
123 self.input.chars().next().inspect(|c| {
124 self.pos.inc_by(*c);
125 self.input = &self.input[c.len_utf8()..];
126 })
127 }
128
129 fn read_until_line_end(&mut self) -> (&'a str, P) {
130 if let Some(i) = memchr::memchr2(b'\r', b'\n', self.input.as_bytes()) {
131 if self.input.as_bytes()[i] == b'\r'
132 && self.input.as_bytes().get(i + 1).copied() == Some(b'\n')
133 {
134 let (l, r) = self.input.split_at(i);
135 self.input = &r[2..];
136 self.pos.inc_offset_by(l);
137 let pos = self.pos;
138 self.pos.inc_newline(true);
139 return (l, pos);
140 }
141 let (l, r) = self.input.split_at(i);
142 self.input = &r[1..];
143 self.pos.inc_offset_by(l);
144 let pos = self.pos;
145 self.pos.inc_newline(false);
146 (l, pos)
147 } else {
148 let ret = self.input;
149 self.pos.inc_offset_by(ret);
150 self.input = "";
151 (ret, self.pos)
152 }
153 }
154
155 fn read_until_byte(&mut self, b: u8) -> Self::Str {
156 if let Some(i) = memchr::memchr(b, self.input.as_bytes()) {
157 let (l, r) = self.input.split_at(i);
158 self.input = r;
159 self.pos += P::len(l);
160 l
161 } else {
162 let ret = self.input;
163 self.pos += P::len(ret);
164 self.input = "";
165 ret
166 }
167 }
168 fn read_until_char(&mut self, c: char) -> Self::Str {
169 let bytes = c.into_bytes();
170 let del = bytes[0];
171 for i in memchr::memchr_iter(del, self.input.as_bytes()) {
172 if self.input.as_bytes()[i..].starts_with(&bytes) {
173 let (l, r) = self.input.split_at(i);
174 self.input = r;
175 self.pos += P::len(l);
176 return l;
177 }
178 }
179 let ret = self.input;
180 self.pos += P::len(ret);
181 self.input = "";
182 ret
183 }
184
185 fn read_until_byte_with_brackets(&mut self, needle: u8, open: u8, close: u8) -> Self::Str {
186 let mut in_brackets = 0;
187 let mut curroff = 0;
188 let bytes = self.input.as_bytes();
189 loop {
190 if in_brackets == 0 {
191 if let Some(i) = memchr::memchr2(needle, open, &bytes[curroff..]) {
192 curroff += i;
193 let b = bytes[curroff];
194 if b == needle {
195 let (l, r) = self.input.split_at(curroff);
196 self.input = r;
197 self.pos += P::len(l);
198 return l;
199 }
200 curroff += 1;
201 in_brackets += 1;
202 } else {
203 let ret = self.input;
204 self.input = "";
205 self.pos += P::len(ret);
206 return ret;
207 }
208 } else if let Some(i) = memchr::memchr2(open, close, &bytes[curroff..]) {
209 curroff += i;
210 let b = bytes[curroff];
211 curroff += 1;
212 if b == open {
213 in_brackets += 1;
214 } else {
215 in_brackets -= 1;
216 }
217 } else {
218 let ret = self.input;
219 self.input = "";
220 self.pos += P::len(ret);
221 return ret;
222 }
223 }
224 }
225
226 fn read_until_inclusive(&mut self, pred: impl FnMut(char) -> bool) -> &'a str {
227 let i = self.input.find(pred).unwrap_or(self.input.len());
228 let (l, r) = self.input.split_at(i + 1);
229 self.input = r;
230 self.pos += P::len(l);
231 l
232 }
233
234 fn trim_start(&mut self) {
235 if P::KIND == PositionKind::None {
236 self.input = self.input.trim_start();
237 return;
238 }
239 if P::KIND == PositionKind::Byte {
240 let old = self.input;
241 self.input = self.input.trim_start();
242 let trimmed = &old[..old.len() - self.input.len()];
243 self.pos += P::len(trimmed);
244 return;
245 }
246 while let Some(c) = self.input.chars().next() {
247 if c == '\n' {
248 self.input = &self.input[1..];
249 self.pos.inc_newline(false);
250 } else if c == '\r' {
251 self.input = &self.input[1..];
252 if self.input.starts_with('\n') {
253 self.input = &self.input[1..];
254 self.pos.inc_newline(true);
255 } else {
256 self.pos.inc_newline(false);
257 }
258 } else if c.is_whitespace() {
259 self.input = &self.input[c.len_utf8()..];
260 self.pos.inc_by(c);
261 } else {
262 break;
263 }
264 }
265 }
266 fn starts_with(&mut self, c: char) -> bool {
267 self.input.starts_with(c)
268 }
269 fn read_while(&mut self, mut pred: impl FnMut(char) -> bool) -> Self::Str {
270 let i = self.input.find(|c| !pred(c)).unwrap_or(self.input.len());
271 let (l, r) = self.input.split_at(i);
272 self.input = r;
273 self.pos += P::len(l);
274 l
275 }
276 fn read_until_with_brackets(
277 &mut self,
278 open: char,
279 close: char,
280 mut pred: impl FnMut(char) -> bool,
281 ) -> Self::Str {
282 let mut depth = 0;
283 let i = self
284 .input
285 .find(|c| {
286 if c == close && depth > 0 {
287 depth -= 1;
288 false
289 } else if c == open {
290 depth += 1;
291 false
292 } else {
293 depth == 0 && pred(c)
294 }
295 })
296 .unwrap_or(self.input.len());
297 let (l, r) = self.input.split_at(i);
298 self.input = r;
299 self.pos += P::len(l);
300 l
301 }
302 fn peek_head(&mut self) -> Option<char> {
303 self.input.chars().next()
304 }
305 fn read_n(&mut self, i: usize) -> Self::Str {
306 let (l, mut r) = self.input.split_at(i);
307 if l.ends_with('\r') && r.starts_with('\n') {
308 r = &r[1..];
309 }
310 self.input = r;
311 self.pos += P::len(l);
312 l
313 }
314
315 fn read_until_str(&mut self, s: &str) -> Self::Str {
316 if let Some(i) = self.input.find(s) {
317 let (l, r) = self.input.split_at(i);
318 self.input = r;
319 self.pos += P::len(l);
320 l
321 } else {
322 let ret = self.input;
323 self.input = "";
324 self.pos += P::len(ret);
325 ret
326 }
327 }
328
329 fn read_until_needle(&mut self, s: &super::Needle) -> Self::Str {
330 if let Some(i) = s.find_in(self.input) {
331 let (l, r) = self.input.split_at(i);
332 self.input = r;
333 self.pos += P::len(l);
334 l
335 } else {
336 let ret = self.input;
337 self.input = "";
338 self.pos += P::len(ret);
339 ret
340 }
341 }
342
343 fn skip(&mut self, i: usize) {
344 let (a, b) = self.input.split_at(i);
345 self.input = b;
346 self.pos += P::len(a);
347 }
348}