1use std::error::Error;
9use std::fmt::{Display, Formatter};
10use std::iter::FusedIterator;
11
12use crate::cell_stream::frame_recovering;
13use crate::{
14 Adj, CellStream, ExternalCstNode, IdentToken, LexError, LiteralToken, Migrate, MigrateError,
15 Punct, SourceFile, Span, Spanned, Terminal, Token, TokenGroup, TokenStream, TokenTree,
16 TrailingTrivia, lex_str,
17};
18
19pub trait Parser<T = SourceFile> {
24 type Error: Error;
26
27 fn parse_cells(&mut self, cells: CellStream) -> Result<T, Self::Error>;
33}
34
35pub fn parse_with<T, P>(parser: &mut P, cells: CellStream) -> Result<T, P::Error>
41where
42 P: Parser<T>,
43{
44 parser.parse_cells(cells)
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 {
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.into_parser_token_stream()).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,
209 pub(crate) crossed_newline: bool,
211 pub(crate) trailing_trivia: TrailingTrivia,
213}
214
215#[derive(Debug, Clone)]
216#[allow(clippy::large_enum_variant)]
217pub(crate) enum Lookahead {
219 Token(SignificantToken),
221 End(Span),
223}
224
225impl Spanned for Lookahead {
226 fn span(&self) -> Span {
227 match self {
228 Self::Token(token) => token.token.span(),
229 Self::End(span) => span.clone(),
230 }
231 }
232}
233
234#[derive(Clone)]
240pub struct ParseStream {
241 tokens: TokenStream,
243 position: usize,
245 eof_span: Span,
251}
252
253impl ParseStream {
254 pub fn new(tokens: TokenStream) -> Self {
256 let eof_span = tokens
257 .last()
258 .and_then(|token| {
259 let span = token.expect_span();
260 Some(span.at(span.end()?))
261 })
262 .unwrap_or_else(|| Span::for_text(""));
263 Self {
264 tokens,
265 position: 0,
266 eof_span,
267 }
268 }
269
270 pub fn fork(&self) -> Self {
272 self.clone()
273 }
274
275 pub fn advance_to(&mut self, fork: &Self) {
281 assert!(
282 self.tokens.shares_storage(&fork.tokens),
283 "cannot advance to a cursor from another token stream"
284 );
285 self.position = fork.position;
286 }
287
288 pub fn peek(&self) -> Option<&TokenTree> {
290 self.tokens().get(self.position)
291 }
292
293 pub(crate) fn lookahead(&self) -> Lookahead {
295 let Some(mut token) = self.tokens().get(self.position).cloned() else {
296 return Lookahead::End(self.eof_span.clone());
297 };
298 let crossed_newline = self.position.checked_sub(1).is_some_and(|left| {
299 self.tokens()
300 .get(left)
301 .is_some_and(|left| tokens_cross_line_break(left, &token))
302 });
303 let trailing_trivia = std::mem::take(token.trailing_trivia_mut());
304 Lookahead::Token(SignificantToken {
305 token,
306 crossed_newline,
307 trailing_trivia,
308 })
309 }
310
311 pub(crate) fn consume_lookahead(&mut self) -> Lookahead {
313 let lookahead = self.lookahead();
314 if matches!(lookahead, Lookahead::Token(_)) {
315 self.position += 1;
316 }
317 lookahead
318 }
319
320 pub(crate) fn next_significant(&mut self) -> Option<SignificantToken> {
322 match self.consume_lookahead() {
323 Lookahead::Token(token) => Some(token),
324 Lookahead::End(_) => None,
325 }
326 }
327
328 pub(crate) fn skip_trivia(&mut self) {
330 }
332
333 pub(crate) fn eof_span(&self) -> Span {
335 self.eof_span.clone()
336 }
337
338 pub fn next_token(&mut self) -> Option<TokenTree> {
340 self.next_raw_token()
341 }
342
343 pub fn next_raw_token(&mut self) -> Option<TokenTree> {
345 self.next()
346 }
347
348 pub fn parse_token<T: Token>(&mut self) -> Result<T, TokenParseError> {
355 let Some(token) = self.next_significant() else {
356 return Err(TokenParseError::unexpected_end(
357 T::SPELLING,
358 self.eof_span(),
359 ));
360 };
361 let error = TokenParseError::unexpected_token(T::SPELLING, &token.token);
362 T::from_token_tree_with_trivia(token.token, token.trailing_trivia).ok_or(error)
363 }
364
365 pub fn is_eof(&self) -> bool {
367 self.peek().is_none()
368 }
369
370 fn tokens(&self) -> &TokenStream {
372 &self.tokens
373 }
374
375 fn finish(&mut self) -> Result<(), TokenParseError> {
377 if let Some(token) = self.next() {
378 return Err(TokenParseError::TrailingToken {
379 found: token.description(),
380 span: token.expect_span(),
381 });
382 }
383 Ok(())
384 }
385}
386
387fn tokens_cross_line_break(left: &TokenTree, right: &TokenTree) -> bool {
389 let left = left.expect_span();
390 let right = right.expect_span();
391 if !left.shares_source(&right) {
392 return false;
393 }
394 let (Some(end), Some(start)) = (left.end(), right.start()) else {
395 return false;
396 };
397 end <= start && left.source().text()[end..start].contains('\n')
398}
399
400impl Iterator for ParseStream {
401 type Item = TokenTree;
402
403 fn next(&mut self) -> Option<Self::Item> {
404 let token = self.tokens().get(self.position)?.clone();
405 self.position += 1;
406 Some(token)
407 }
408
409 fn size_hint(&self) -> (usize, Option<usize>) {
410 let remaining = self.tokens().len().saturating_sub(self.position);
411 (remaining, Some(remaining))
412 }
413}
414
415impl ExactSizeIterator for ParseStream {}
416impl FusedIterator for ParseStream {}
417
418#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
419pub enum TokenParseError {
421 UnexpectedEnd {
423 expected: &'static str,
425 span: Span,
427 },
428 UnexpectedToken {
430 expected: &'static str,
432 found: String,
434 span: Span,
436 },
437 TrailingToken {
439 found: String,
441 span: Span,
443 },
444 Syntax {
446 message: String,
448 span: Span,
450 },
451}
452
453impl TokenParseError {
454 pub(crate) fn unexpected_end(expected: &'static str, span: Span) -> Self {
456 Self::UnexpectedEnd { expected, span }
457 }
458
459 pub(crate) fn unexpected(expected: &'static str, found: impl Into<String>, span: Span) -> Self {
461 Self::UnexpectedToken {
462 expected,
463 found: found.into(),
464 span,
465 }
466 }
467
468 pub(crate) fn unexpected_token(expected: &'static str, token: &TokenTree) -> Self {
470 Self::unexpected(expected, token.description(), token.expect_span())
471 }
472}
473
474impl Display for TokenParseError {
475 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
476 match self {
477 Self::UnexpectedEnd { expected, .. } => {
478 write!(formatter, "expected `{expected}`, found the end of input")
479 }
480 Self::UnexpectedToken {
481 expected, found, ..
482 } => write!(formatter, "expected `{expected}`, found `{found}`"),
483 Self::TrailingToken { found, .. } => {
484 write!(formatter, "expected the end of input, found `{found}`")
485 }
486 Self::Syntax { message, .. } => formatter.write_str(message),
487 }
488 }
489}
490
491impl Error for TokenParseError {}
492
493pub fn migrate<T, N>(root: N) -> Result<T, MigrateError>
499where
500 N: ExternalCstNode,
501 T: Migrate<N>,
502{
503 T::migrate(root)
504}
505
506#[cfg(test)]
507mod tests {
508 use super::*;
509 use crate::{LiteralKind, quote_m2};
510
511 #[test]
512 fn parse_stream_iteration_excludes_its_eof_token() {
513 let mut input = ParseStream::new(quote_m2!(name + 1));
514 assert_eq!(input.len(), 3);
515 let emitted = input.by_ref().collect::<TokenStream>();
516
517 assert_eq!(emitted.to_string(), "name+1");
518 assert!(input.is_eof());
519 assert_eq!(input.next(), None);
520 assert_eq!(input.next(), None);
521 }
522
523 #[test]
524 fn exact_size_counts_every_remaining_token() {
525 let mut input = ParseStream::new(quote_m2!(name));
526
527 assert_eq!(input.len(), 1);
528 assert!(input.next().is_some());
529 assert_eq!(input.len(), 0);
530 }
531
532 #[test]
533 fn raw_token_categories_implement_parse() {
534 let identifier = parse2::<IdentToken>(quote_m2!(name)).unwrap();
535 let literal = parse2::<LiteralToken>(quote_m2!(1)).unwrap();
536 let punctuation = parse2::<Punct>(quote_m2!(+)).unwrap();
537 let group = parse2::<TokenGroup>(quote_m2!((name))).unwrap();
538
539 assert_eq!(identifier.text(), "name");
540 assert_eq!(literal.kind, LiteralKind::Integer);
541 assert_eq!(punctuation.text(), "+");
542 assert_eq!(crate::Lex::to_token_stream(&group).to_string(), "(name)");
543 }
544
545 #[test]
546 fn lookahead_reports_the_stored_eof_span_through_spanned() {
547 let tokens = lex_str("name").unwrap();
548 let mut input = ParseStream::new(tokens);
549 input.next_token();
550
551 let span = input.lookahead().expect_span();
552 assert_eq!(span.start().unwrap(), "name".len());
553 assert_eq!(span, input.eof_span().span());
554 }
555}