Skip to content

Commit

Permalink
Support peeking End
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jun 22, 2024
1 parent b088d5c commit 773627a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
10 changes: 10 additions & 0 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,16 @@ impl<'a> Cursor<'a> {

Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
}

pub(crate) fn scope_delimiter(self) -> Delimiter {
match unsafe { &*self.scope } {
Entry::End(_, offset) => match unsafe { &*self.scope.offset(*offset) } {
Entry::Group(group, _) => group.delimiter(),
_ => Delimiter::None,
},
_ => unreachable!(),
}
}
}

impl<'a> Copy for Cursor<'a> {}
Expand Down
44 changes: 41 additions & 3 deletions src/lookahead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::buffer::Cursor;
use crate::error::{self, Error};
use crate::sealed::lookahead::Sealed;
use crate::span::IntoSpans;
use crate::token::Token;
use proc_macro2::Span;
use crate::token::{CustomToken, Token};
use proc_macro2::{Delimiter, Span};
use std::cell::RefCell;

/// Support for checking the next token in a stream to decide how to parse.
Expand Down Expand Up @@ -110,7 +110,18 @@ impl<'a> Lookahead1<'a> {
/// The error message will identify all of the expected token types that
/// have been peeked against this lookahead instance.
pub fn error(self) -> Error {
let comparisons = self.comparisons.into_inner();
let mut comparisons = self.comparisons.into_inner();
comparisons.retain_mut(|display| {
if *display == "`)`" {
*display = match self.cursor.scope_delimiter() {
Delimiter::Parenthesis => "`)`",
Delimiter::Brace => "`}`",
Delimiter::Bracket => "`]`",
Delimiter::None => return false,
}
}
true
});
match comparisons.len() {
0 => {
if self.cursor.eof() {
Expand Down Expand Up @@ -150,6 +161,31 @@ pub trait Peek: Sealed {
type Token: Token;
}

/// Pseudo-token used for peeking the end of parse stream.
pub struct End;

impl Copy for End {}

impl Clone for End {
fn clone(&self) -> Self {
*self
}
}

impl Peek for End {
type Token = Self;
}

impl CustomToken for End {
fn peek(cursor: Cursor) -> bool {
cursor.eof()
}

fn display() -> &'static str {
"`)`" // Lookahead1 error message will fill in the expected close delimiter
}
}

impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Peek for F {
type Token = T;
}
Expand All @@ -163,3 +199,5 @@ impl<S> IntoSpans<S> for TokenMarker {
}

impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}

impl Sealed for End {}
7 changes: 6 additions & 1 deletion src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ use std::rc::Rc;
use std::str::FromStr;

pub use crate::error::{Error, Result};
pub use crate::lookahead::{Lookahead1, Peek};
pub use crate::lookahead::{End, Lookahead1, Peek};

/// Parsing interface implemented by all types that can be parsed in a default
/// way from a token stream.
Expand Down Expand Up @@ -750,6 +750,11 @@ impl<'a> ParseBuffer<'a> {
/// set of delimiters, as well as at the end of the tokens provided to the
/// outermost parsing entry point.
///
/// This is equivalent to
/// <code>.<a href="#method.peek">peek</a>(<a href="struct.End.html">syn::parse::End</a>)</code>.
/// Use `.peek2(End)` or `.peek3(End)` to look for the end of a parse stream
/// further ahead than the current position.
///
/// # Example
///
/// ```
Expand Down

0 comments on commit 773627a

Please sign in to comment.