1use std::error::Error;
9use std::fmt::{Display, Formatter};
10use std::iter::FusedIterator;
11use std::rc::Rc;
12
13use crate::lexer::split_cells;
14use crate::{
15 ExternalCstNode, IdentToken, LexError, LiteralToken, Punct, Reconstruct, ReconstructError,
16 SourceFile, Span, Spanned, Token, TokenGroup, TokenStream, TokenTree, Trivia, lex_str,
17};
18
19pub trait Parser<T = SourceFile> {
24 type Error: Error;
26
27 fn parse_stream(&mut self, tokens: TokenStream) -> Result<T, Self::Error>;
33}
34
35pub fn parse_with<T, P>(parser: &mut P, tokens: TokenStream) -> Result<T, P::Error>
41where
42 P: Parser<T>,
43{
44 parser.parse_stream(tokens)
45}
46
47pub trait Parse: Sized {
49 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError>;
55}
56
57impl<T: Parse> Parse for Box<T> {
58 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
59 T::parse(input).map(Self::new)
60 }
61}
62
63impl Parse for TokenTree {
64 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
65 input
66 .next_raw_token()
67 .ok_or_else(|| TokenParseError::unexpected_end("a token tree", input.eof_span()))
68 }
69}
70
71macro_rules! parse_raw_variant {
72 ($ty:ty, $variant:ident, $expected:literal) => {
73 impl Parse for $ty {
74 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
75 let token = TokenTree::parse(input)?;
76 match token {
77 TokenTree::$variant(value) => Ok(value),
78 token => Err(TokenParseError::unexpected_token($expected, &token)),
79 }
80 }
81 }
82 };
83}
84
85parse_raw_variant!(TokenGroup, Group, "a delimited group");
86parse_raw_variant!(LiteralToken, Literal, "a literal");
87parse_raw_variant!(Punct, Punct, "punctuation");
88parse_raw_variant!(IdentToken, Ident, "an identifier");
89parse_raw_variant!(Trivia, Trivia, "trivia");
90
91impl Parse for TokenStream {
92 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
93 Ok(input.by_ref().collect())
94 }
95}
96
97pub fn parse2<T: Parse>(tokens: TokenStream) -> Result<T, TokenParseError> {
104 let mut input = ParseStream::new(tokens);
105 let value = T::parse(&mut input)?;
106 input.finish()?;
107 Ok(value)
108}
109
110pub fn parse_fragment_str<T: Parse>(source: &str) -> Result<T, FragmentParseError> {
123 let mut cells = split_cells(lex_str(source)?);
124 if cells.len() > 1 {
125 return Err(FragmentParseError::MultipleCells { count: cells.len() });
126 }
127 let tokens = cells
128 .pop()
129 .map_or_else(TokenStream::new, |cell| cell.stream);
130 parse2(tokens).map_err(Into::into)
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
135pub enum FragmentParseError {
136 Lex(LexError),
138 Parse(TokenParseError),
140 MultipleCells {
143 count: usize,
145 },
146}
147
148impl Display for FragmentParseError {
149 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
150 match self {
151 Self::Lex(error) => error.fmt(formatter),
152 Self::Parse(error) => error.fmt(formatter),
153 Self::MultipleCells { count } => {
154 write!(formatter, "expected one source cell, found {count}")
155 }
156 }
157 }
158}
159
160impl Error for FragmentParseError {
161 fn source(&self) -> Option<&(dyn Error + 'static)> {
162 match self {
163 Self::Lex(error) => Some(error),
164 Self::Parse(error) => Some(error),
165 Self::MultipleCells { .. } => None,
166 }
167 }
168}
169
170impl From<LexError> for FragmentParseError {
171 fn from(error: LexError) -> Self {
172 Self::Lex(error)
173 }
174}
175
176impl From<TokenParseError> for FragmentParseError {
177 fn from(error: TokenParseError) -> Self {
178 Self::Parse(error)
179 }
180}
181
182#[derive(Debug, Clone)]
186pub(crate) struct SignificantToken {
187 pub(crate) token: TokenTree,
188 pub(crate) crossed_newline: bool,
189}
190
191#[derive(Debug, Clone)]
192pub(crate) enum Lookahead {
193 Token(SignificantToken),
194 End(Span),
195}
196
197impl Spanned for Lookahead {
198 fn span(&self) -> Span {
199 match self {
200 Self::Token(token) => token.token.span(),
201 Self::End(span) => span.clone(),
202 }
203 }
204}
205
206#[derive(Clone)]
211pub struct ParseStream {
212 tokens: Rc<TokenStream>,
213 position: usize,
214 eof_span: Span,
220}
221
222impl ParseStream {
223 pub fn new(tokens: TokenStream) -> Self {
225 let eof_span = tokens
226 .last()
227 .and_then(|token| {
228 let end = token.span().end()?;
229 Some(Span::from_offset(end))
230 })
231 .unwrap_or_else(Span::detached);
232 Self {
233 tokens: Rc::new(tokens),
234 position: 0,
235 eof_span,
236 }
237 }
238
239 pub fn fork(&self) -> Self {
241 self.clone()
242 }
243
244 pub fn advance_to(&mut self, fork: &Self) {
250 assert!(
251 Rc::ptr_eq(&self.tokens, &fork.tokens),
252 "cannot advance to a cursor from another token stream"
253 );
254 self.position = fork.position;
255 }
256
257 pub fn peek(&self) -> Option<&TokenTree> {
259 self.tokens().get(self.significant_position())
260 }
261
262 pub(crate) fn lookahead(&self) -> Lookahead {
263 let mut position = self.position;
264 let mut crossed_newline = false;
265 while let Some(TokenTree::Trivia(trivia)) = self.tokens().get(position) {
266 crossed_newline |= trivia.contains_line_break();
267 position += 1;
268 }
269 let Some(token) = self.tokens().get(position).cloned() else {
270 return Lookahead::End(self.eof_span.clone());
271 };
272 Lookahead::Token(SignificantToken {
273 token,
274 crossed_newline,
275 })
276 }
277
278 pub(crate) fn consume_lookahead(&mut self) -> Lookahead {
279 let lookahead = self.lookahead();
280 if matches!(lookahead, Lookahead::Token(_)) {
281 self.set_position(self.significant_position() + 1);
282 }
283 lookahead
284 }
285
286 pub(crate) fn skip_trivia(&mut self) {
287 self.set_position(self.significant_position());
288 }
289
290 pub(crate) fn eof_span(&self) -> Span {
291 self.eof_span.clone()
292 }
293
294 pub fn next_token(&mut self) -> Option<TokenTree> {
296 self.set_position(self.significant_position());
297 self.next_raw_token()
298 }
299
300 pub fn next_raw_token(&mut self) -> Option<TokenTree> {
302 self.next()
303 }
304
305 pub fn parse_token<T: Token>(&mut self) -> Result<T, TokenParseError> {
312 let token = self.next_token();
313 let Some(token) = token else {
314 return Err(TokenParseError::unexpected_end(
315 T::SPELLING,
316 self.eof_span(),
317 ));
318 };
319 let error = TokenParseError::unexpected_token(T::SPELLING, &token);
320 T::from_token_tree(token).ok_or(error)
321 }
322
323 pub fn is_eof(&self) -> bool {
325 self.peek().is_none()
326 }
327
328 fn significant_position(&self) -> usize {
329 let mut position = self.position;
330 while matches!(self.tokens().get(position), Some(TokenTree::Trivia(_))) {
331 position += 1;
332 }
333 position
334 }
335
336 fn tokens(&self) -> &TokenStream {
337 &self.tokens
338 }
339
340 fn set_position(&mut self, position: usize) {
341 self.position = position;
342 }
343
344 fn finish(&mut self) -> Result<(), TokenParseError> {
345 for token in self.by_ref() {
346 if matches!(token, TokenTree::Trivia(_) | TokenTree::Eoc(_)) {
347 continue;
348 }
349 return Err(TokenParseError::TrailingToken {
350 found: token.description(),
351 span: token.span(),
352 });
353 }
354 Ok(())
355 }
356}
357
358impl Iterator for ParseStream {
359 type Item = TokenTree;
360
361 fn next(&mut self) -> Option<Self::Item> {
362 let token = self.tokens().get(self.position)?.clone();
363 self.position += 1;
364 Some(token)
365 }
366
367 fn size_hint(&self) -> (usize, Option<usize>) {
368 let remaining = self.tokens().len().saturating_sub(self.position);
369 (remaining, Some(remaining))
370 }
371}
372
373impl ExactSizeIterator for ParseStream {}
374impl FusedIterator for ParseStream {}
375
376#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
377pub enum TokenParseError {
379 UnexpectedEnd {
381 expected: &'static str,
383 span: Span,
385 },
386 UnexpectedToken {
388 expected: &'static str,
390 found: String,
392 span: Span,
394 },
395 TrailingToken {
397 found: String,
399 span: Span,
401 },
402 Syntax {
404 message: String,
406 span: Span,
408 },
409}
410
411impl TokenParseError {
412 pub(crate) fn unexpected_end(expected: &'static str, span: Span) -> Self {
413 Self::UnexpectedEnd { expected, span }
414 }
415
416 pub(crate) fn unexpected(expected: &'static str, found: impl Into<String>, span: Span) -> Self {
417 Self::UnexpectedToken {
418 expected,
419 found: found.into(),
420 span,
421 }
422 }
423
424 pub(crate) fn unexpected_token(expected: &'static str, token: &TokenTree) -> Self {
425 Self::unexpected(expected, token.description(), token.span())
426 }
427}
428
429impl Display for TokenParseError {
430 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
431 match self {
432 Self::UnexpectedEnd { expected, .. } => {
433 write!(formatter, "expected `{expected}`, found the end of input")
434 }
435 Self::UnexpectedToken {
436 expected, found, ..
437 } => write!(formatter, "expected `{expected}`, found `{found}`"),
438 Self::TrailingToken { found, .. } => {
439 write!(formatter, "expected the end of input, found `{found}`")
440 }
441 Self::Syntax { message, .. } => formatter.write_str(message),
442 }
443 }
444}
445
446impl Error for TokenParseError {}
447
448pub fn reconstruct<T, N>(root: N) -> Result<T, ReconstructError>
454where
455 N: ExternalCstNode,
456 T: Reconstruct<N>,
457{
458 T::reconstruct(root)
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464 use crate::{LiteralKind, quote_m2};
465
466 #[test]
467 fn parse_stream_iteration_excludes_its_eof_token() {
468 let mut input = ParseStream::new(quote_m2!(name + 1));
469 assert_eq!(input.len(), 3);
470 let emitted = input.by_ref().collect::<TokenStream>();
471
472 assert_eq!(emitted.to_string(), "name+1");
473 assert!(input.is_eof());
474 assert_eq!(input.next(), None);
475 assert_eq!(input.next(), None);
476 }
477
478 #[test]
479 fn exact_size_counts_every_remaining_token() {
480 let mut input = ParseStream::new(quote_m2!(name));
481
482 assert_eq!(input.len(), 1);
483 assert!(input.next().is_some());
484 assert_eq!(input.len(), 0);
485 }
486
487 #[test]
488 fn raw_token_categories_implement_parse() {
489 let identifier = parse2::<IdentToken>(quote_m2!(name)).unwrap();
490 let literal = parse2::<LiteralToken>(quote_m2!(1)).unwrap();
491 let punctuation = parse2::<Punct>(quote_m2!(+)).unwrap();
492 let group = parse2::<TokenGroup>(quote_m2!((name))).unwrap();
493
494 assert_eq!(identifier.text(), "name");
495 assert_eq!(literal.kind, LiteralKind::Integer);
496 assert_eq!(punctuation.text(), "+");
497 assert_eq!(group.to_string(), "(name)");
498 }
499
500 #[test]
501 fn lookahead_reports_the_stored_eof_span_through_spanned() {
502 let tokens = lex_str("name").unwrap();
503 let mut input = ParseStream::new(tokens);
504 input.next_token();
505
506 let span = input.lookahead().span();
507 assert_eq!(span.start().unwrap(), "name".len());
508 assert_eq!(span, input.eof_span());
509 }
510}