macroonz_compiler/token/capture/cursor/
read.rs1use super::{
7 CaptureCursor, CaptureExpectation, CaptureReadIssue, CaptureReadRefusal, CapturedDelimiter,
8 CapturedInput, CapturedSpacing, CapturedTokenTree,
9};
10use crate::bounded::Bounded;
11
12impl CapturedInput {
13 #[must_use]
15 pub fn cursor(&self) -> CaptureCursor<'_> {
16 CaptureCursor::over(self.trees())
17 }
18}
19
20impl<'tokens> super::CapturedFragment<'tokens> {
21 #[must_use]
23 pub fn cursor(self) -> CaptureCursor<'tokens> {
24 let mut cursor = CaptureCursor::over(self.tokens);
25 cursor.end = self.end;
26 cursor
27 }
28}
29
30impl<'tokens> CaptureCursor<'tokens> {
31 pub(super) const fn over(tokens: &'tokens [CapturedTokenTree]) -> Self {
33 Self {
34 tokens,
35 next: 0,
36 end: None,
37 }
38 }
39
40 #[must_use]
42 pub fn is_finished(&self) -> bool {
43 self.next == self.tokens.len()
44 }
45
46 #[must_use]
48 pub(crate) fn next_word(&self) -> Option<&'tokens str> {
49 self.tokens.get(self.next).and_then(CapturedTokenTree::word)
50 }
51
52 #[must_use]
54 pub(crate) fn next_token(&self) -> Option<&'tokens CapturedTokenTree> {
55 self.tokens.get(self.next)
56 }
57
58 pub fn fragment<T>(
67 &mut self,
68 read: impl FnOnce(&mut Self) -> Result<T, CaptureReadRefusal>,
69 ) -> Result<(super::CapturedFragment<'tokens>, T), CaptureReadRefusal> {
70 let start = self.next;
71 let value = read(self)?;
72 let tokens = self
73 .tokens
74 .get(start..self.next)
75 .ok_or(CaptureReadRefusal {
76 issue: CaptureReadIssue::CursorRangeContradiction,
77 at: self.current_span(),
78 })?;
79 Ok((super::CapturedFragment::over(tokens, self.end), value))
80 }
81
82 pub fn token(&mut self) -> Result<&'tokens CapturedTokenTree, CaptureReadRefusal> {
88 self.take(|| CaptureExpectation::Token, |_| true)
89 }
90
91 pub fn word(
100 &mut self,
101 expected: &str,
102 ) -> Result<&'tokens CapturedTokenTree, CaptureReadRefusal> {
103 self.take(
104 || CaptureExpectation::Word(expected.to_owned()),
105 |token| token.word() == Some(expected),
106 )
107 }
108
109 pub fn identifier(
117 &mut self,
118 ) -> Result<(&'tokens CapturedTokenTree, &'tokens str), CaptureReadRefusal> {
119 let token = self.take(
120 || CaptureExpectation::Identifier,
121 |token| token.word().is_some() || token.raw_identifier().is_some(),
122 )?;
123 let ((Some(spelling), None) | (None, Some(spelling))) =
124 (token.word(), token.raw_identifier())
125 else {
126 return Err(CaptureReadRefusal {
127 issue: CaptureReadIssue::Unexpected(CaptureExpectation::Identifier),
128 at: Some(token.span()),
129 });
130 };
131 Ok((token, spelling))
132 }
133
134 pub fn number(
140 &mut self,
141 ) -> Result<(&'tokens CapturedTokenTree, &'tokens str), CaptureReadRefusal> {
142 let token = self.take(
143 || CaptureExpectation::Number,
144 |token| token.number().is_some(),
145 )?;
146 match token.number() {
147 Some(spelling) => Ok((token, spelling)),
148 None => Err(CaptureReadRefusal {
149 issue: CaptureReadIssue::Unexpected(CaptureExpectation::Number),
150 at: Some(token.span()),
151 }),
152 }
153 }
154
155 pub fn punctuation(
161 &mut self,
162 mark: char,
163 spacing: CapturedSpacing,
164 ) -> Result<&'tokens CapturedTokenTree, CaptureReadRefusal> {
165 self.take(
166 || CaptureExpectation::Punctuation { mark, spacing },
167 |token| match spacing {
168 CapturedSpacing::Alone => {
169 token.punct() == Some(mark) && token.joint_punct().is_none()
170 }
171 CapturedSpacing::Joint => token.joint_punct() == Some(mark),
172 },
173 )
174 }
175
176 pub fn thin_arrow(&mut self) -> Result<[&'tokens CapturedTokenTree; 2], CaptureReadRefusal> {
182 let dash = self.punctuation('-', CapturedSpacing::Joint)?;
183 let arrow = self.punctuation('>', CapturedSpacing::Alone)?;
184 Ok([dash, arrow])
185 }
186
187 pub fn fat_arrow(&mut self) -> Result<[&'tokens CapturedTokenTree; 2], CaptureReadRefusal> {
193 let equals = self.punctuation('=', CapturedSpacing::Joint)?;
194 let arrow = self.punctuation('>', CapturedSpacing::Alone)?;
195 Ok([equals, arrow])
196 }
197
198 pub fn group(&mut self, delimiter: CapturedDelimiter) -> Result<Self, CaptureReadRefusal> {
206 let token = self.take(
207 || CaptureExpectation::Group(delimiter),
208 |token| token.group().is_some_and(|(found, _)| found == delimiter),
209 )?;
210 match token.group() {
211 Some((_, members)) => Ok(Self {
212 tokens: members,
213 next: 0,
214 end: Some(token.span()),
215 }),
216 None => Err(CaptureReadRefusal {
217 issue: CaptureReadIssue::Unexpected(CaptureExpectation::Group(delimiter)),
218 at: Some(token.span()),
219 }),
220 }
221 }
222
223 pub fn trailing_separated<T, const LIMIT: usize>(
232 mut self,
233 separator: char,
234 mut read: impl FnMut(&mut Self) -> Result<T, CaptureReadRefusal>,
235 ) -> Result<Bounded<T, LIMIT>, CaptureReadRefusal> {
236 let mut members = Bounded::empty();
237 while !self.is_finished() {
238 let member_at = self.current_span();
239 if members.len() >= LIMIT {
240 return Err(CaptureReadRefusal {
241 issue: CaptureReadIssue::SequenceUnbounded { limit: LIMIT },
242 at: member_at,
243 });
244 }
245 let before = self.next;
246 let member = read(&mut self)?;
247 if self.next == before {
248 return Err(CaptureReadRefusal {
249 issue: CaptureReadIssue::SequenceMemberDidNotAdvance,
250 at: member_at,
251 });
252 }
253 self.punctuation(separator, CapturedSpacing::Alone)?;
254 members.try_push(member).map_err(|_| CaptureReadRefusal {
255 issue: CaptureReadIssue::SequenceUnbounded { limit: LIMIT },
256 at: member_at,
257 })?;
258 }
259 Ok(members)
260 }
261
262 pub fn finish(self) -> Result<(), CaptureReadRefusal> {
268 match self.tokens.get(self.next) {
269 Some(token) => Err(CaptureReadRefusal {
270 issue: CaptureReadIssue::InputRemaining,
271 at: Some(token.span()),
272 }),
273 None => Ok(()),
274 }
275 }
276
277 fn take(
279 &mut self,
280 expected: impl FnOnce() -> CaptureExpectation,
281 accepts: impl FnOnce(&CapturedTokenTree) -> bool,
282 ) -> Result<&'tokens CapturedTokenTree, CaptureReadRefusal> {
283 let Some(token) = self.tokens.get(self.next) else {
284 return Err(CaptureReadRefusal {
285 issue: CaptureReadIssue::Missing(expected()),
286 at: self.end,
287 });
288 };
289 if !accepts(token) {
290 return Err(CaptureReadRefusal {
291 issue: CaptureReadIssue::Unexpected(expected()),
292 at: Some(token.span()),
293 });
294 }
295 self.next = self.next.saturating_add(1);
296 Ok(token)
297 }
298
299 fn current_span(&self) -> Option<super::SpanHandle> {
301 self.tokens
302 .get(self.next)
303 .map(CapturedTokenTree::span)
304 .or(self.end)
305 }
306}
307
308impl CaptureReadRefusal {
309 pub(crate) const fn projected(issue: CaptureReadIssue, at: Option<super::SpanHandle>) -> Self {
311 Self { issue, at }
312 }
313
314 pub const fn issue(&self) -> &CaptureReadIssue {
316 &self.issue
317 }
318
319 #[must_use]
323 pub const fn token(&self) -> Option<super::SpanHandle> {
324 self.at
325 }
326
327 pub(crate) fn into_parts(self) -> (CaptureReadIssue, Option<super::SpanHandle>) {
329 (self.issue, self.at)
330 }
331}