1use std::error::Error;
9use std::fmt::{Display, Formatter};
10use std::iter::FusedIterator;
11use std::rc::Rc;
12
13use crate::cell_stream::frame_recovering;
14use crate::{
15 Adj, CellStream, ExternalCstNode, IdentToken, LexError, LiteralToken, Migrate, MigrateError,
16 Punct, SourceFile, Span, Spanned, Terminal, Token, TokenGroup, TokenStream, TokenTree,
17 TrailingTrivia, lex_str,
18};
19
20pub trait Parser<T = SourceFile> {
25 type Error: Error;
27
28 fn parse_cells(&mut self, cells: CellStream) -> Result<T, Self::Error>;
34}
35
36pub fn parse_with<T, P>(parser: &mut P, cells: CellStream) -> Result<T, P::Error>
42where
43 P: Parser<T>,
44{
45 parser.parse_cells(cells)
46}
47
48pub trait Parse: Sized {
50 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError>;
56}
57
58impl<T: Parse> Parse for Box<T> {
59 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
60 T::parse(input).map(Self::new)
61 }
62}
63
64impl Parse for TokenTree {
65 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
66 input
67 .next_raw_token()
68 .ok_or_else(|| TokenParseError::unexpected_end("a token tree", input.eof_span()))
69 }
70}
71
72macro_rules! parse_raw_variant {
73 ($ty:ty, $variant:ident, $expected:literal) => {
74 impl Parse for $ty {
75 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
76 let token = TokenTree::parse(input)?;
77 match token {
78 TokenTree::$variant(value) => Ok(value),
79 token => Err(TokenParseError::unexpected_token($expected, &token)),
80 }
81 }
82 }
83 };
84}
85
86parse_raw_variant!(TokenGroup, Group, "a delimited group");
87parse_raw_variant!(LiteralToken, Literal, "a literal");
88parse_raw_variant!(Punct, Punct, "punctuation");
89parse_raw_variant!(IdentToken, Ident, "an identifier");
90
91impl Parse for Adj {
92 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
93 let Some(token) = input.next_significant() else {
94 return Err(TokenParseError::unexpected_end(
95 "adjacency",
96 input.eof_span(),
97 ));
98 };
99 match token.token {
100 TokenTree::Punct(punctuation) if punctuation.text().is_empty() => {
101 let mut adjacency = Self::new("", punctuation.expect_span());
102 *adjacency.trailing_trivia_mut() = token.trailing_trivia;
103 Ok(adjacency)
104 }
105 token => Err(TokenParseError::unexpected_token("adjacency", &token)),
106 }
107 }
108}
109
110impl Parse for TokenStream {
111 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
112 Ok(input.by_ref().collect())
113 }
114}
115
116pub fn parse2<T: Parse>(tokens: TokenStream) -> Result<T, TokenParseError> {
123 let mut input = ParseStream::new(tokens);
124 let value = T::parse(&mut input)?;
125 input.finish()?;
126 Ok(value)
127}
128
129pub fn parse_fragment_str<T: Parse>(source: &str) -> Result<T, FragmentParseError> {
143 let framed = frame_recovering(lex_str(source)?);
144 let mut cells = framed.cells;
145 cells.extend(framed.incomplete);
146 if cells.len() > 1 {
147 return Err(FragmentParseError::MultipleCells { count: cells.len() });
148 }
149 let tokens = cells.pop().unwrap_or_default();
150 parse2(tokens).map_err(Into::into)
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
155pub enum FragmentParseError {
156 Lex(LexError),
158 Parse(TokenParseError),
160 MultipleCells {
163 count: usize,
165 },
166}
167
168impl Display for FragmentParseError {
169 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
170 match self {
171 Self::Lex(error) => error.fmt(formatter),
172 Self::Parse(error) => error.fmt(formatter),
173 Self::MultipleCells { count } => {
174 write!(formatter, "expected one source cell, found {count}")
175 }
176 }
177 }
178}
179
180impl Error for FragmentParseError {
181 fn source(&self) -> Option<&(dyn Error + 'static)> {
182 match self {
183 Self::Lex(error) => Some(error),
184 Self::Parse(error) => Some(error),
185 Self::MultipleCells { .. } => None,
186 }
187 }
188}
189
190impl From<LexError> for FragmentParseError {
191 fn from(error: LexError) -> Self {
192 Self::Lex(error)
193 }
194}
195
196impl From<TokenParseError> for FragmentParseError {
197 fn from(error: TokenParseError) -> Self {
198 Self::Parse(error)
199 }
200}
201
202#[derive(Debug, Clone)]
206pub(crate) struct SignificantToken {
207 pub(crate) token: TokenTree,
208 pub(crate) crossed_newline: bool,
209 pub(crate) trailing_trivia: TrailingTrivia,
210}
211
212#[derive(Debug, Clone)]
213#[allow(clippy::large_enum_variant)]
214pub(crate) enum Lookahead {
215 Token(SignificantToken),
216 End(Span),
217}
218
219impl Spanned for Lookahead {
220 fn span(&self) -> Span {
221 match self {
222 Self::Token(token) => token.token.span(),
223 Self::End(span) => span.clone(),
224 }
225 }
226}
227
228#[derive(Clone)]
233pub struct ParseStream {
234 tokens: Rc<TokenStream>,
235 position: usize,
236 eof_span: Span,
242}
243
244impl ParseStream {
245 pub fn new(tokens: TokenStream) -> Self {
247 let eof_span = tokens
248 .last()
249 .and_then(|token| {
250 let span = token.expect_span();
251 Some(span.at(span.end()?))
252 })
253 .unwrap_or_else(|| Span::for_text(""));
254 Self {
255 tokens: Rc::new(tokens),
256 position: 0,
257 eof_span,
258 }
259 }
260
261 pub fn fork(&self) -> Self {
263 self.clone()
264 }
265
266 pub fn advance_to(&mut self, fork: &Self) {
272 assert!(
273 Rc::ptr_eq(&self.tokens, &fork.tokens),
274 "cannot advance to a cursor from another token stream"
275 );
276 self.position = fork.position;
277 }
278
279 pub fn peek(&self) -> Option<&TokenTree> {
281 self.tokens().get(self.position)
282 }
283
284 pub(crate) fn lookahead(&self) -> Lookahead {
285 let Some(mut token) = self.tokens().get(self.position).cloned() else {
286 return Lookahead::End(self.eof_span.clone());
287 };
288 let crossed_newline = self.position.checked_sub(1).is_some_and(|left| {
289 self.tokens()
290 .get(left)
291 .is_some_and(|left| tokens_cross_line_break(left, &token))
292 });
293 let trailing_trivia = std::mem::take(token.trailing_trivia_mut());
294 Lookahead::Token(SignificantToken {
295 token,
296 crossed_newline,
297 trailing_trivia,
298 })
299 }
300
301 pub(crate) fn consume_lookahead(&mut self) -> Lookahead {
302 let lookahead = self.lookahead();
303 if matches!(lookahead, Lookahead::Token(_)) {
304 self.position += 1;
305 }
306 lookahead
307 }
308
309 pub(crate) fn next_significant(&mut self) -> Option<SignificantToken> {
310 match self.consume_lookahead() {
311 Lookahead::Token(token) => Some(token),
312 Lookahead::End(_) => None,
313 }
314 }
315
316 pub(crate) fn skip_trivia(&mut self) {
317 }
319
320 pub(crate) fn eof_span(&self) -> Span {
321 self.eof_span.clone()
322 }
323
324 pub fn next_token(&mut self) -> Option<TokenTree> {
326 self.next_raw_token()
327 }
328
329 pub fn next_raw_token(&mut self) -> Option<TokenTree> {
331 self.next()
332 }
333
334 pub fn parse_token<T: Token>(&mut self) -> Result<T, TokenParseError> {
341 let Some(token) = self.next_significant() else {
342 return Err(TokenParseError::unexpected_end(
343 T::SPELLING,
344 self.eof_span(),
345 ));
346 };
347 let error = TokenParseError::unexpected_token(T::SPELLING, &token.token);
348 T::from_token_tree_with_trivia(token.token, token.trailing_trivia).ok_or(error)
349 }
350
351 pub fn is_eof(&self) -> bool {
353 self.peek().is_none()
354 }
355
356 fn tokens(&self) -> &TokenStream {
357 &self.tokens
358 }
359
360 fn finish(&mut self) -> Result<(), TokenParseError> {
361 if let Some(token) = self.next() {
362 return Err(TokenParseError::TrailingToken {
363 found: token.description(),
364 span: token.expect_span(),
365 });
366 }
367 Ok(())
368 }
369}
370
371fn tokens_cross_line_break(left: &TokenTree, right: &TokenTree) -> bool {
372 let left = left.expect_span();
373 let right = right.expect_span();
374 if !left.shares_source(&right) {
375 return false;
376 }
377 let (Some(end), Some(start)) = (left.end(), right.start()) else {
378 return false;
379 };
380 end <= start && left.source().text()[end..start].contains('\n')
381}
382
383impl Iterator for ParseStream {
384 type Item = TokenTree;
385
386 fn next(&mut self) -> Option<Self::Item> {
387 let token = self.tokens().get(self.position)?.clone();
388 self.position += 1;
389 Some(token)
390 }
391
392 fn size_hint(&self) -> (usize, Option<usize>) {
393 let remaining = self.tokens().len().saturating_sub(self.position);
394 (remaining, Some(remaining))
395 }
396}
397
398impl ExactSizeIterator for ParseStream {}
399impl FusedIterator for ParseStream {}
400
401#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
402pub enum TokenParseError {
404 UnexpectedEnd {
406 expected: &'static str,
408 span: Span,
410 },
411 UnexpectedToken {
413 expected: &'static str,
415 found: String,
417 span: Span,
419 },
420 TrailingToken {
422 found: String,
424 span: Span,
426 },
427 Syntax {
429 message: String,
431 span: Span,
433 },
434}
435
436impl TokenParseError {
437 pub(crate) fn unexpected_end(expected: &'static str, span: Span) -> Self {
438 Self::UnexpectedEnd { expected, span }
439 }
440
441 pub(crate) fn unexpected(expected: &'static str, found: impl Into<String>, span: Span) -> Self {
442 Self::UnexpectedToken {
443 expected,
444 found: found.into(),
445 span,
446 }
447 }
448
449 pub(crate) fn unexpected_token(expected: &'static str, token: &TokenTree) -> Self {
450 Self::unexpected(expected, token.description(), token.expect_span())
451 }
452}
453
454impl Display for TokenParseError {
455 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
456 match self {
457 Self::UnexpectedEnd { expected, .. } => {
458 write!(formatter, "expected `{expected}`, found the end of input")
459 }
460 Self::UnexpectedToken {
461 expected, found, ..
462 } => write!(formatter, "expected `{expected}`, found `{found}`"),
463 Self::TrailingToken { found, .. } => {
464 write!(formatter, "expected the end of input, found `{found}`")
465 }
466 Self::Syntax { message, .. } => formatter.write_str(message),
467 }
468 }
469}
470
471impl Error for TokenParseError {}
472
473pub fn migrate<T, N>(root: N) -> Result<T, MigrateError>
479where
480 N: ExternalCstNode,
481 T: Migrate<N>,
482{
483 T::migrate(root)
484}
485
486#[cfg(test)]
487mod tests {
488 use super::*;
489 use crate::{LiteralKind, quote_m2};
490
491 #[test]
492 fn parse_stream_iteration_excludes_its_eof_token() {
493 let mut input = ParseStream::new(quote_m2!(name + 1));
494 assert_eq!(input.len(), 3);
495 let emitted = input.by_ref().collect::<TokenStream>();
496
497 assert_eq!(emitted.to_string(), "name+1");
498 assert!(input.is_eof());
499 assert_eq!(input.next(), None);
500 assert_eq!(input.next(), None);
501 }
502
503 #[test]
504 fn exact_size_counts_every_remaining_token() {
505 let mut input = ParseStream::new(quote_m2!(name));
506
507 assert_eq!(input.len(), 1);
508 assert!(input.next().is_some());
509 assert_eq!(input.len(), 0);
510 }
511
512 #[test]
513 fn raw_token_categories_implement_parse() {
514 let identifier = parse2::<IdentToken>(quote_m2!(name)).unwrap();
515 let literal = parse2::<LiteralToken>(quote_m2!(1)).unwrap();
516 let punctuation = parse2::<Punct>(quote_m2!(+)).unwrap();
517 let group = parse2::<TokenGroup>(quote_m2!((name))).unwrap();
518
519 assert_eq!(identifier.text(), "name");
520 assert_eq!(literal.kind, LiteralKind::Integer);
521 assert_eq!(punctuation.text(), "+");
522 assert_eq!(crate::Lex::to_token_stream(&group).to_string(), "(name)");
523 }
524
525 #[test]
526 fn lookahead_reports_the_stored_eof_span_through_spanned() {
527 let tokens = lex_str("name").unwrap();
528 let mut input = ParseStream::new(tokens);
529 input.next_token();
530
531 let span = input.lookahead().expect_span();
532 assert_eq!(span.start().unwrap(), "name".len());
533 assert_eq!(span, input.eof_span().span());
534 }
535}