1use std::error::Error;
9use std::fmt::{Display, Formatter};
10use std::io::Cursor;
11use std::iter::FusedIterator;
12use std::rc::Rc;
13
14use crate::cst::Token;
15use crate::{
16 CellStream, ExternalCstNode, Group, IdentToken, LexError, Literal, Punct, Reconstruct,
17 ReconstructError, SourceFile, SourceId, Span, Spanned, TextRange, TokenStream, TokenTree,
18 Trivia, TriviaKind, lex_str,
19};
20
21pub trait Parser<T = SourceFile> {
26 type Error: Error;
27
28 fn parse_cells(&mut self, tokens: CellStream) -> Result<T, Self::Error>;
29}
30
31pub fn parse_with<T, P>(parser: &mut P, tokens: CellStream) -> Result<T, P::Error>
33where
34 P: Parser<T>,
35{
36 parser.parse_cells(tokens)
37}
38
39pub trait Parse: Sized {
41 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError>;
42}
43
44impl<T: Parse> Parse for Box<T> {
45 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
46 T::parse(input).map(Self::new)
47 }
48}
49
50impl Parse for TokenTree {
51 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
52 input
53 .next_raw_token()
54 .ok_or(TokenParseError::UnexpectedEnd {
55 expected: "a token tree",
56 span: input.eof_span(),
57 })
58 }
59}
60
61macro_rules! parse_raw_variant {
62 ($ty:ty, $variant:ident, $expected:literal) => {
63 impl Parse for $ty {
64 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
65 let token = TokenTree::parse(input)?;
66 let span = token.span();
67 let found = token_description(&token);
68 match token {
69 TokenTree::$variant(value) => Ok(value),
70 _ => Err(TokenParseError::UnexpectedToken {
71 expected: $expected,
72 found,
73 span,
74 }),
75 }
76 }
77 }
78 };
79}
80
81parse_raw_variant!(Group, Group, "a delimited group");
82parse_raw_variant!(Literal, Literal, "a literal");
83parse_raw_variant!(Punct, Punct, "punctuation");
84parse_raw_variant!(IdentToken, Ident, "an identifier");
85parse_raw_variant!(Trivia, Trivia, "trivia");
86
87impl Parse for TokenStream {
88 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
89 Ok(input.by_ref().collect())
90 }
91}
92
93pub fn parse1<T: Parse>(tokens: TokenStream) -> Result<T, TokenParseError> {
95 let mut input = ParseStream::new(tokens);
96 let value = T::parse(&mut input)?;
97 input.finish()?;
98 Ok(value)
99}
100
101pub fn parse_fragment_str<T: Parse>(
109 source: &str,
110 source_id: SourceId,
111) -> Result<T, FragmentParseError> {
112 let cells = lex_str(source, source_id)?.into_cells();
113 let tokens = match cells.len() {
114 0 => TokenStream::new(),
115 1 => cells.into_iter().next().unwrap().into_stream(),
116 count => return Err(FragmentParseError::MultipleCells { count }),
117 };
118 parse1(tokens).map_err(Into::into)
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum FragmentParseError {
124 Lex(LexError),
126 Parse(TokenParseError),
128 MultipleCells {
131 count: usize,
133 },
134}
135
136impl Display for FragmentParseError {
137 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
138 match self {
139 Self::Lex(error) => error.fmt(formatter),
140 Self::Parse(error) => error.fmt(formatter),
141 Self::MultipleCells { count } => {
142 write!(formatter, "expected one source cell, found {count}")
143 }
144 }
145 }
146}
147
148impl Error for FragmentParseError {
149 fn source(&self) -> Option<&(dyn Error + 'static)> {
150 match self {
151 Self::Lex(error) => Some(error),
152 Self::Parse(error) => Some(error),
153 Self::MultipleCells { .. } => None,
154 }
155 }
156}
157
158impl From<LexError> for FragmentParseError {
159 fn from(error: LexError) -> Self {
160 Self::Lex(error)
161 }
162}
163
164impl From<TokenParseError> for FragmentParseError {
165 fn from(error: TokenParseError) -> Self {
166 Self::Parse(error)
167 }
168}
169
170#[derive(Debug, Clone)]
174pub(crate) struct SignificantToken {
175 pub(crate) token: TokenTree,
176 pub(crate) crossed_newline: bool,
177 pub(crate) leading_span: Span,
178}
179
180#[derive(Debug, Clone)]
181pub(crate) enum Lookahead {
182 Token(SignificantToken),
183 End(Span),
184}
185
186impl Spanned for Lookahead {
187 fn span(&self) -> Span {
188 match self {
189 Self::Token(token) => token.token.span(),
190 Self::End(span) => *span,
191 }
192 }
193}
194
195#[derive(Clone)]
200pub struct ParseStream {
201 cursor: Cursor<Rc<TokenStream>>,
202}
203
204impl ParseStream {
205 pub fn new(mut tokens: TokenStream) -> Self {
207 let eof_span = tokens
208 .last()
209 .and_then(|token| {
210 let source = token.span().source().ok()?;
211 let end = token.span().end_point().ok()?;
212 Some(Span::new(source, TextRange::from_point(end)))
213 })
214 .unwrap_or_else(Span::detached);
215 tokens.push_eof(eof_span);
216 Self {
217 cursor: Cursor::new(Rc::new(tokens)),
218 }
219 }
220
221 pub fn fork(&self) -> Self {
223 self.clone()
224 }
225
226 pub fn advance_to(&mut self, fork: &Self) {
230 assert!(
231 Rc::ptr_eq(self.cursor.get_ref(), fork.cursor.get_ref()),
232 "cannot advance to a cursor from another token stream"
233 );
234 self.cursor.set_position(fork.cursor.position());
235 }
236
237 pub fn peek(&self) -> Option<&TokenTree> {
239 match self.tokens().get(self.significant_position()) {
240 Some(TokenTree::Eof(_)) | None => None,
241 token => token,
242 }
243 }
244
245 pub(crate) fn lookahead(&self) -> Lookahead {
246 let mut position = self.position();
247 let mut crossed_newline = false;
248 let mut leading_span = Span::detached();
249 while let Some(TokenTree::Trivia(trivia)) = self.tokens().get(position) {
250 crossed_newline |= trivia.contains_line_break();
251 leading_span = leading_span.join(trivia.span());
252 position += 1;
253 }
254 let Some(token) = self.tokens().get(position).cloned() else {
255 unreachable!("ParseStream always stores a final EOF token")
256 };
257 if let TokenTree::Eof(span) = token {
258 return Lookahead::End(span);
259 }
260 if leading_span == Span::detached() {
261 leading_span = token
262 .span()
263 .source()
264 .ok()
265 .zip(token.span().start_point().ok())
266 .map(|(source, point)| Span::new(source, TextRange::from_point(point)))
267 .unwrap_or_else(Span::detached);
268 }
269 Lookahead::Token(SignificantToken {
270 token,
271 crossed_newline,
272 leading_span,
273 })
274 }
275
276 pub(crate) fn consume_lookahead(&mut self) -> Lookahead {
277 let lookahead = self.lookahead();
278 if matches!(lookahead, Lookahead::Token(_)) {
279 self.set_position(self.significant_position() + 1);
280 }
281 lookahead
282 }
283
284 pub(crate) fn skip_trivia(&mut self) {
285 self.set_position(self.significant_position());
286 }
287
288 pub(crate) fn eof_span(&self) -> Span {
289 match self.tokens().last() {
290 Some(TokenTree::Eof(span)) => *span,
291 _ => unreachable!("ParseStream always stores a final EOF token"),
292 }
293 }
294
295 pub fn next_token(&mut self) -> Option<TokenTree> {
297 self.set_position(self.significant_position());
298 self.next_raw_token()
299 }
300
301 pub fn next_raw_token(&mut self) -> Option<TokenTree> {
303 self.next()
304 }
305
306 pub fn parse_token<T: Token>(&mut self) -> Result<T, TokenParseError> {
308 let token = self.next_raw_token();
309 let Some(token) = token else {
310 return Err(TokenParseError::UnexpectedEnd {
311 expected: T::SPELLING,
312 span: self.eof_span(),
313 });
314 };
315 let span = token.span();
316 let found = token_description(&token);
317 T::from_token_tree(token).ok_or(TokenParseError::UnexpectedToken {
318 expected: T::SPELLING,
319 found,
320 span,
321 })
322 }
323
324 pub fn is_eof(&self) -> bool {
326 self.peek().is_none()
327 }
328
329 fn significant_position(&self) -> usize {
330 let mut position = self.position();
331 while matches!(self.tokens().get(position), Some(TokenTree::Trivia(_))) {
332 position += 1;
333 }
334 position
335 }
336
337 fn tokens(&self) -> &TokenStream {
338 self.cursor.get_ref()
339 }
340
341 fn position(&self) -> usize {
342 self.cursor.position() as usize
343 }
344
345 fn set_position(&mut self, position: usize) {
346 self.cursor.set_position(position as u64);
347 }
348
349 fn finish(&mut self) -> Result<(), TokenParseError> {
350 let Some(token) = self.next_token() else {
351 return Ok(());
352 };
353 Err(TokenParseError::TrailingToken {
354 found: token_description(&token),
355 span: token.span(),
356 })
357 }
358}
359
360impl Iterator for ParseStream {
361 type Item = TokenTree;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 let token = self.tokens().get(ParseStream::position(self))?.clone();
365 match token {
366 TokenTree::Eof(_) => None,
367 token => {
368 self.cursor.set_position(self.cursor.position() + 1);
369 Some(token)
370 }
371 }
372 }
373
374 fn size_hint(&self) -> (usize, Option<usize>) {
375 let remaining = self
376 .tokens()
377 .len()
378 .saturating_sub(ParseStream::position(self) + 1);
379 (remaining, Some(remaining))
380 }
381}
382
383impl ExactSizeIterator for ParseStream {}
384impl FusedIterator for ParseStream {}
385
386#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
387pub enum TokenParseError {
388 UnexpectedEnd {
389 expected: &'static str,
390 span: Span,
391 },
392 UnexpectedToken {
393 expected: &'static str,
394 found: String,
395 span: Span,
396 },
397 TrailingToken {
398 found: String,
399 span: Span,
400 },
401 Syntax {
402 message: String,
403 span: Span,
404 },
405}
406
407impl Display for TokenParseError {
408 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
409 match self {
410 Self::UnexpectedEnd { expected, .. } => {
411 write!(formatter, "expected `{expected}`, found the end of input")
412 }
413 Self::UnexpectedToken {
414 expected, found, ..
415 } => write!(formatter, "expected `{expected}`, found `{found}`"),
416 Self::TrailingToken { found, .. } => {
417 write!(formatter, "expected the end of input, found `{found}`")
418 }
419 Self::Syntax { message, .. } => formatter.write_str(message),
420 }
421 }
422}
423
424impl Error for TokenParseError {}
425
426fn token_description(token: &TokenTree) -> String {
427 match token {
428 TokenTree::Group(group) => group.delim_kind().to_string(),
429 TokenTree::Trivia(trivia) => match trivia.kind() {
430 TriviaKind::Whitespace => "whitespace".into(),
431 TriviaKind::CarriageReturn => "carriage return".into(),
432 TriviaKind::LineBreak => "line break".into(),
433 TriviaKind::LineComment => "line comment".into(),
434 TriviaKind::BlockComment => "block comment".into(),
435 },
436 token => token.spelling().unwrap_or("").to_owned(),
437 }
438}
439
440pub fn reconstruct<T, N>(root: N) -> Result<T, ReconstructError>
442where
443 N: ExternalCstNode,
444 T: Reconstruct<N>,
445{
446 T::reconstruct(root)
447}
448
449#[cfg(test)]
450mod tests {
451 use super::*;
452 use crate::{LiteralKind, quote_m2};
453
454 #[test]
455 fn parse_stream_iteration_excludes_its_eof_token() {
456 let mut input = ParseStream::new(quote_m2!(name + 1));
457 let emitted = input.by_ref().collect::<TokenStream>();
458
459 assert_eq!(emitted.to_string(), "name+1");
460 assert!(input.is_eof());
461 assert_eq!(input.next(), None);
462 assert_eq!(input.next(), None);
463 }
464
465 #[test]
466 fn raw_token_categories_implement_parse() {
467 let identifier = parse1::<IdentToken>(quote_m2!(name)).unwrap();
468 let literal = parse1::<Literal>(quote_m2!(1)).unwrap();
469 let punctuation = parse1::<Punct>(quote_m2!(+)).unwrap();
470 let group = parse1::<Group>(quote_m2!((name))).unwrap();
471
472 assert_eq!(identifier.text(), "name");
473 assert_eq!(literal.kind, LiteralKind::Integer);
474 assert_eq!(punctuation.text(), "+");
475 assert_eq!(group.to_string(), "(name)");
476 }
477
478 #[test]
479 fn lookahead_reports_the_stored_eof_span_through_spanned() {
480 let source = SourceId(91);
481 let tokens = lex_str("name", source)
482 .unwrap()
483 .into_cells()
484 .pop()
485 .unwrap()
486 .into_stream();
487 let mut input = ParseStream::new(tokens);
488 input.next_token();
489
490 let span = input.lookahead().span();
491 assert_eq!(span.source(), Ok(source));
492 assert_eq!(span.start_point().unwrap().byte, "name".len());
493 assert_eq!(span, input.eof_span());
494 }
495}