#[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", target_os = "unknown")),
feature = "proc-macro"
))]
use proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
use buffer::{Cursor, TokenBuffer};
use error;
use lookahead;
use private;
use punctuated::Punctuated;
use token::Token;
pub use error::{Error, Result};
pub use 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: Rc<Cell<Option<Span>>>,
}
impl<'a> Drop for ParseBuffer<'a> {
fn drop(&mut self) {
if !self.is_empty() && self.unexpected.get().is_none() {
self.unexpected.set(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)
}
}
impl private {
pub 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) }
}
}
fn skip(input: ParseStream) -> bool {
input
.step(|cursor| {
if let Some((_lifetime, rest)) = cursor.lifetime() {
Ok((true, rest))
} else if let Some((_token, rest)) = cursor.token_tree() {
Ok((true, rest))
} else {
Ok((false, *cursor))
}
})
.unwrap()
}
impl private {
pub fn new_parse_buffer(
scope: Span,
cursor: Cursor,
unexpected: Rc<Cell<Option<Span>>>,
) -> ParseBuffer {
ParseBuffer {
scope: scope,
cell: Cell::new(unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) }),
marker: PhantomData,
unexpected: unexpected,
}
}
pub fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Option<Span>>> {
buffer.unexpected.clone()
}
}
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 ahead = self.fork();
skip(&ahead) && ahead.peek(token)
}
pub fn peek3<T: Peek>(&self, token: T) -> bool {
let ahead = self.fork();
skip(&ahead) && skip(&ahead) && ahead.peek(token)
}
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: Rc::new(Cell::new(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 cursor(&self) -> Cursor<'a> {
self.cell.get()
}
fn check_unexpected(&self) -> Result<()> {
match self.unexpected.get() {
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", target_os = "unknown")),
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)
}
}
fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer {
let scope = Span::call_site();
let cursor = tokens.begin();
let unexpected = Rc::new(Cell::new(None));
private::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(None));
let state = private::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"))
}
}
}
impl private {
pub fn parse_scoped<F: Parser>(f: F, scope: Span, tokens: TokenStream) -> Result<F::Output> {
f.__parse_scoped(scope, tokens)
}
}