#[path = "discouraged.rs"]
pub mod discouraged;
use std::cell::Cell;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::rc::Rc;
use std::str::FromStr;
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
use crate::proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
use crate::buffer::{Cursor, TokenBuffer};
use crate::error;
use crate::lookahead;
use crate::punctuated::Punctuated;
use crate::token::Token;
pub use crate::error::{Error, Result};
pub use crate::lookahead::{Lookahead1, Peek};
pub trait Parse: Sized {
fn parse(input: ParseStream) -> Result<Self>;
}
pub type ParseStream<'a> = &'a ParseBuffer<'a>;
pub struct ParseBuffer<'a> {
scope: Span,
cell: Cell<Cursor<'static>>,
marker: PhantomData<Cursor<'a>>,
unexpected: Cell<Option<Rc<Cell<Unexpected>>>>,
}
impl<'a> Drop for ParseBuffer<'a> {
fn drop(&mut self) {
if !self.is_empty() {
let (inner, old_span) = inner_unexpected(self);
if old_span.is_none() {
inner.set(Unexpected::Some(self.cursor().span()));
}
}
}
}
impl<'a> Display for ParseBuffer<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.cursor().token_stream(), f)
}
}
impl<'a> Debug for ParseBuffer<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.cursor().token_stream(), f)
}
}
#[derive(Copy, Clone)]
pub struct StepCursor<'c, 'a> {
scope: Span,
cursor: Cursor<'c>,
marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
}
impl<'c, 'a> Deref for StepCursor<'c, 'a> {
type Target = Cursor<'c>;
fn deref(&self) -> &Self::Target {
&self.cursor
}
}
impl<'c, 'a> StepCursor<'c, 'a> {
pub fn error<T: Display>(self, message: T) -> Error {
error::new_at(self.scope, self.cursor, message)
}
}
pub(crate) fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> {
let _ = proof;
unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) }
}
pub(crate) fn new_parse_buffer(
scope: Span,
cursor: Cursor,
unexpected: Rc<Cell<Unexpected>>,
) -> ParseBuffer {
ParseBuffer {
scope,
cell: Cell::new(unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) }),
marker: PhantomData,
unexpected: Cell::new(Some(unexpected)),
}
}
#[derive(Clone)]
pub(crate) enum Unexpected {
None,
Some(Span),
Chain(Rc<Cell<Unexpected>>),
}
impl Default for Unexpected {
fn default() -> Self {
Unexpected::None
}
}
fn cell_clone<T: Default + Clone>(cell: &Cell<T>) -> T {
let prev = cell.take();
let ret = prev.clone();
cell.set(prev);
ret
}
fn inner_unexpected(buffer: &ParseBuffer) -> (Rc<Cell<Unexpected>>, Option<Span>) {
let mut unexpected = get_unexpected(buffer);
loop {
match cell_clone(&unexpected) {
Unexpected::None => return (unexpected, None),
Unexpected::Some(span) => return (unexpected, Some(span)),
Unexpected::Chain(next) => unexpected = next,
}
}
}
pub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Unexpected>> {
cell_clone(&buffer.unexpected).unwrap()
}
impl<'a> ParseBuffer<'a> {
pub fn parse<T: Parse>(&self) -> Result<T> {
T::parse(self)
}
pub fn call<T>(&self, function: fn(ParseStream) -> Result<T>) -> Result<T> {
function(self)
}
pub fn peek<T: Peek>(&self, token: T) -> bool {
let _ = token;
T::Token::peek(self.cursor())
}
pub fn peek2<T: Peek>(&self, token: T) -> bool {
let _ = token;
self.cursor().skip().map_or(false, T::Token::peek)
}
pub fn peek3<T: Peek>(&self, token: T) -> bool {
let _ = token;
self.cursor()
.skip()
.and_then(Cursor::skip)
.map_or(false, T::Token::peek)
}
pub fn parse_terminated<T, P: Parse>(
&self,
parser: fn(ParseStream) -> Result<T>,
) -> Result<Punctuated<T, P>> {
Punctuated::parse_terminated_with(self, parser)
}
pub fn is_empty(&self) -> bool {
self.cursor().eof()
}
pub fn lookahead1(&self) -> Lookahead1<'a> {
lookahead::new(self.scope, self.cursor())
}
pub fn fork(&self) -> Self {
ParseBuffer {
scope: self.scope,
cell: self.cell.clone(),
marker: PhantomData,
unexpected: Cell::new(Some(Rc::new(Cell::new(Unexpected::None)))),
}
}
pub fn error<T: Display>(&self, message: T) -> Error {
error::new_at(self.scope, self.cursor(), message)
}
pub fn step<F, R>(&self, function: F) -> Result<R>
where
F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>,
{
let (node, rest) = function(StepCursor {
scope: self.scope,
cursor: self.cell.get(),
marker: PhantomData,
})?;
self.cell.set(rest);
Ok(node)
}
pub fn span(&self) -> Span {
let cursor = self.cursor();
if cursor.eof() {
self.scope
} else {
crate::buffer::open_span_of_group(cursor)
}
}
pub fn cursor(&self) -> Cursor<'a> {
self.cell.get()
}
fn check_unexpected(&self) -> Result<()> {
match inner_unexpected(self).1 {
Some(span) => Err(Error::new(span, "unexpected token")),
None => Ok(()),
}
}
}
impl<T: Parse> Parse for Box<T> {
fn parse(input: ParseStream) -> Result<Self> {
input.parse().map(Box::new)
}
}
impl<T: Parse + Token> Parse for Option<T> {
fn parse(input: ParseStream) -> Result<Self> {
if T::peek(input.cursor()) {
Ok(Some(input.parse()?))
} else {
Ok(None)
}
}
}
impl Parse for TokenStream {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
}
}
impl Parse for TokenTree {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| match cursor.token_tree() {
Some((tt, rest)) => Ok((tt, rest)),
None => Err(cursor.error("expected token tree")),
})
}
}
impl Parse for Group {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| {
for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
if let Some((inside, span, rest)) = cursor.group(*delim) {
let mut group = Group::new(*delim, inside.token_stream());
group.set_span(span);
return Ok((group, rest));
}
}
Err(cursor.error("expected group token"))
})
}
}
impl Parse for Punct {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| match cursor.punct() {
Some((punct, rest)) => Ok((punct, rest)),
None => Err(cursor.error("expected punctuation token")),
})
}
}
impl Parse for Literal {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| match cursor.literal() {
Some((literal, rest)) => Ok((literal, rest)),
None => Err(cursor.error("expected literal token")),
})
}
}
pub trait Parser: Sized {
type Output;
fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
self.parse2(proc_macro2::TokenStream::from(tokens))
}
fn parse_str(self, s: &str) -> Result<Self::Output> {
self.parse2(proc_macro2::TokenStream::from_str(s)?)
}
#[doc(hidden)]
fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> {
let _ = scope;
self.parse2(tokens)
}
#[doc(hidden)]
fn __parse_stream(self, input: ParseStream) -> Result<Self::Output> {
input.parse().and_then(|tokens| self.parse2(tokens))
}
}
fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer {
let scope = Span::call_site();
let cursor = tokens.begin();
let unexpected = Rc::new(Cell::new(Unexpected::None));
new_parse_buffer(scope, cursor, unexpected)
}
impl<F, T> Parser for F
where
F: FnOnce(ParseStream) -> Result<T>,
{
type Output = T;
fn parse2(self, tokens: TokenStream) -> Result<T> {
let buf = TokenBuffer::new2(tokens);
let state = tokens_to_parse_buffer(&buf);
let node = self(&state)?;
state.check_unexpected()?;
if state.is_empty() {
Ok(node)
} else {
Err(state.error("unexpected token"))
}
}
#[doc(hidden)]
fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> {
let buf = TokenBuffer::new2(tokens);
let cursor = buf.begin();
let unexpected = Rc::new(Cell::new(Unexpected::None));
let state = new_parse_buffer(scope, cursor, unexpected);
let node = self(&state)?;
state.check_unexpected()?;
if state.is_empty() {
Ok(node)
} else {
Err(state.error("unexpected token"))
}
}
#[doc(hidden)]
fn __parse_stream(self, input: ParseStream) -> Result<Self::Output> {
self(input)
}
}
pub(crate) fn parse_scoped<F: Parser>(f: F, scope: Span, tokens: TokenStream) -> Result<F::Output> {
f.__parse_scoped(scope, tokens)
}
pub(crate) fn parse_stream<F: Parser>(f: F, input: ParseStream) -> Result<F::Output> {
f.__parse_stream(input)
}
pub struct Nothing;
impl Parse for Nothing {
fn parse(_input: ParseStream) -> Result<Self> {
Ok(Nothing)
}
}