#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::doc_markdown,
clippy::items_after_statements,
clippy::manual_assert,
clippy::must_use_candidate,
clippy::needless_doctest_main,
clippy::return_self_not_must_use,
clippy::shadow_unrelated,
clippy::trivially_copy_pass_by_ref,
clippy::unnecessary_wraps,
clippy::unused_self,
clippy::used_underscore_binding,
clippy::vec_init_then_push
)]
#![warn(unsafe_code)]
#![feature(doc_auto_cfg, doc_cfg)]
mod fallback;
mod incompatible;
mod parse;
use crate::fallback as imp;
use std::error::Error;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::ops::RangeBounds;
use std::str::FromStr;
use std::{cmp::Ordering, path::PathBuf};
#[derive(Clone)]
pub struct TokenStream {
inner: imp::TokenStream,
}
pub struct LexError {
inner: imp::LexError,
}
impl TokenStream {
fn _new(inner: imp::TokenStream) -> Self {
TokenStream { inner }
}
fn _new_stable(inner: fallback::TokenStream) -> Self {
TokenStream { inner }
}
pub fn new() -> Self {
TokenStream::_new(imp::TokenStream::new())
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl Default for TokenStream {
fn default() -> Self {
TokenStream::new()
}
}
impl FromStr for TokenStream {
type Err = LexError;
fn from_str(src: &str) -> Result<TokenStream, LexError> {
let e = src.parse().map_err(|e| LexError { inner: e })?;
Ok(TokenStream::_new(e))
}
}
impl From<TokenTree> for TokenStream {
fn from(token: TokenTree) -> Self {
TokenStream::_new(imp::TokenStream::from(token))
}
}
impl Extend<TokenTree> for TokenStream {
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
self.inner.extend(streams);
}
}
impl Extend<TokenStream> for TokenStream {
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
self.inner
.extend(streams.into_iter().map(|stream| stream.inner));
}
}
impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
TokenStream::_new(streams.into_iter().collect())
}
}
impl FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
TokenStream::_new(streams.into_iter().map(|i| i.inner).collect())
}
}
impl Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl Debug for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
impl LexError {
pub fn span(&self) -> Span {
Span::_new(self.inner.span())
}
}
impl Debug for LexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
impl Display for LexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl Error for LexError {}
#[derive(Clone, PartialEq, Eq)]
pub struct SourceFile {
inner: imp::SourceFile,
}
impl SourceFile {
fn _new(inner: imp::SourceFile) -> Self {
SourceFile { inner }
}
pub fn path(&self) -> PathBuf {
self.inner.path()
}
pub fn is_real(&self) -> bool {
self.inner.is_real()
}
}
impl Debug for SourceFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LineColumn {
pub line: usize,
pub column: usize,
}
impl Ord for LineColumn {
fn cmp(&self, other: &Self) -> Ordering {
self.line
.cmp(&other.line)
.then(self.column.cmp(&other.column))
}
}
impl PartialOrd for LineColumn {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Span {
inner: imp::Span,
}
impl Span {
fn _new(inner: imp::Span) -> Self {
Span { inner }
}
fn _new_stable(inner: fallback::Span) -> Self {
Span { inner }
}
pub fn call_site() -> Self {
Span::_new(imp::Span::call_site())
}
pub fn mixed_site() -> Self {
Span::_new(imp::Span::mixed_site())
}
pub fn def_site() -> Self {
Span::_new(imp::Span::def_site())
}
pub fn resolved_at(&self, other: Span) -> Span {
Span::_new(self.inner.resolved_at(other.inner))
}
pub fn located_at(&self, other: Span) -> Span {
Span::_new(self.inner.located_at(other.inner))
}
pub fn source_file(&self) -> SourceFile {
SourceFile::_new(self.inner.source_file())
}
pub fn start(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.start();
LineColumn { line, column }
}
pub fn end(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.end();
LineColumn { line, column }
}
pub fn join(&self, other: Span) -> Option<Span> {
self.inner.join(other.inner).map(Span::_new)
}
#[doc(hidden)]
#[allow(clippy::should_implement_trait)]
pub fn eq(&self, other: &Span) -> bool {
self == other
}
}
impl Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
#[derive(Clone)]
pub enum TokenTree {
Group(Group),
Ident(Ident),
Punct(Punct),
Literal(Literal),
}
impl TokenTree {
pub fn span(&self) -> Span {
match self {
TokenTree::Group(t) => t.span(),
TokenTree::Ident(t) => t.span(),
TokenTree::Punct(t) => t.span(),
TokenTree::Literal(t) => t.span(),
}
}
pub fn set_span(&mut self, span: Span) {
match self {
TokenTree::Group(t) => t.set_span(span),
TokenTree::Ident(t) => t.set_span(span),
TokenTree::Punct(t) => t.set_span(span),
TokenTree::Literal(t) => t.set_span(span),
}
}
}
impl From<Group> for TokenTree {
fn from(g: Group) -> TokenTree {
TokenTree::Group(g)
}
}
impl From<Ident> for TokenTree {
fn from(g: Ident) -> TokenTree {
TokenTree::Ident(g)
}
}
impl From<Punct> for TokenTree {
fn from(g: Punct) -> TokenTree {
TokenTree::Punct(g)
}
}
impl From<Literal> for TokenTree {
fn from(g: Literal) -> TokenTree {
TokenTree::Literal(g)
}
}
impl Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenTree::Group(t) => Display::fmt(t, f),
TokenTree::Ident(t) => Display::fmt(t, f),
TokenTree::Punct(t) => Display::fmt(t, f),
TokenTree::Literal(t) => Display::fmt(t, f),
}
}
}
impl Debug for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenTree::Group(t) => Debug::fmt(t, f),
TokenTree::Ident(t) => {
let mut debug = f.debug_struct("Ident");
debug.field("sym", &format_args!("{}", t));
imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner);
debug.finish()
}
TokenTree::Punct(t) => Debug::fmt(t, f),
TokenTree::Literal(t) => Debug::fmt(t, f),
}
}
}
#[derive(Clone)]
pub struct Group {
inner: imp::Group,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Delimiter {
Parenthesis,
Brace,
Bracket,
None,
}
impl Group {
fn _new(inner: imp::Group) -> Self {
Group { inner }
}
fn _new_stable(inner: fallback::Group) -> Self {
Group { inner }
}
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
Group {
inner: imp::Group::new(delimiter, stream.inner),
}
}
pub fn delimiter(&self) -> Delimiter {
self.inner.delimiter()
}
pub fn stream(&self) -> TokenStream {
TokenStream::_new(self.inner.stream())
}
pub fn span(&self) -> Span {
Span::_new(self.inner.span())
}
pub fn span_open(&self) -> Span {
Span::_new(self.inner.span_open())
}
pub fn span_close(&self) -> Span {
Span::_new(self.inner.span_close())
}
pub fn set_span(&mut self, span: Span) {
self.inner.set_span(span.inner);
}
}
impl Display for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, formatter)
}
}
impl Debug for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, formatter)
}
}
#[derive(Clone)]
pub struct Punct {
ch: char,
spacing: Spacing,
span: Span,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Spacing {
Alone,
Joint,
}
impl Punct {
pub fn new(ch: char, spacing: Spacing) -> Self {
Punct {
ch,
spacing,
span: Span::call_site(),
}
}
pub fn as_char(&self) -> char {
self.ch
}
pub fn spacing(&self) -> Spacing {
self.spacing
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
}
impl Display for Punct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.ch, f)
}
}
impl Debug for Punct {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut debug = fmt.debug_struct("Punct");
debug.field("char", &self.ch);
debug.field("spacing", &self.spacing);
imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner);
debug.finish()
}
}
#[derive(Clone)]
pub struct Ident {
inner: imp::Ident,
}
impl Ident {
fn _new(inner: imp::Ident) -> Self {
Ident { inner }
}
pub fn new(string: &str, span: Span) -> Self {
Ident::_new(imp::Ident::new(string, span.inner))
}
pub fn new_raw(string: &str, span: Span) -> Self {
Ident::_new_raw(string, span)
}
fn _new_raw(string: &str, span: Span) -> Self {
Ident::_new(imp::Ident::new_raw(string, span.inner))
}
pub fn span(&self) -> Span {
Span::_new(self.inner.span())
}
pub fn set_span(&mut self, span: Span) {
self.inner.set_span(span.inner);
}
}
impl PartialEq for Ident {
fn eq(&self, other: &Ident) -> bool {
self.inner == other.inner
}
}
impl<T> PartialEq<T> for Ident
where
T: ?Sized + AsRef<str>,
{
fn eq(&self, other: &T) -> bool {
self.inner == other
}
}
impl Eq for Ident {}
impl PartialOrd for Ident {
fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Ident {
fn cmp(&self, other: &Ident) -> Ordering {
self.to_string().cmp(&other.to_string())
}
}
impl Hash for Ident {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.to_string().hash(hasher);
}
}
impl Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
#[derive(Clone)]
pub struct Literal {
inner: imp::Literal,
}
macro_rules! suffixed_int_literals {
($($name:ident => $kind:ident,)*) => ($(
pub fn $name(n: $kind) -> Literal {
Literal::_new(imp::Literal::$name(n))
}
)*)
}
macro_rules! unsuffixed_int_literals {
($($name:ident => $kind:ident,)*) => ($(
pub fn $name(n: $kind) -> Literal {
Literal::_new(imp::Literal::$name(n))
}
)*)
}
impl Literal {
fn _new(inner: imp::Literal) -> Self {
Literal { inner }
}
fn _new_stable(inner: fallback::Literal) -> Self {
Literal { inner }
}
suffixed_int_literals! {
u8_suffixed => u8,
u16_suffixed => u16,
u32_suffixed => u32,
u64_suffixed => u64,
u128_suffixed => u128,
usize_suffixed => usize,
i8_suffixed => i8,
i16_suffixed => i16,
i32_suffixed => i32,
i64_suffixed => i64,
i128_suffixed => i128,
isize_suffixed => isize,
}
unsuffixed_int_literals! {
u8_unsuffixed => u8,
u16_unsuffixed => u16,
u32_unsuffixed => u32,
u64_unsuffixed => u64,
u128_unsuffixed => u128,
usize_unsuffixed => usize,
i8_unsuffixed => i8,
i16_unsuffixed => i16,
i32_unsuffixed => i32,
i64_unsuffixed => i64,
i128_unsuffixed => i128,
isize_unsuffixed => isize,
}
pub fn f64_unsuffixed(f: f64) -> Literal {
assert!(f.is_finite());
Literal::_new(imp::Literal::f64_unsuffixed(f))
}
pub fn f64_suffixed(f: f64) -> Literal {
assert!(f.is_finite());
Literal::_new(imp::Literal::f64_suffixed(f))
}
pub fn f32_unsuffixed(f: f32) -> Literal {
assert!(f.is_finite());
Literal::_new(imp::Literal::f32_unsuffixed(f))
}
pub fn f32_suffixed(f: f32) -> Literal {
assert!(f.is_finite());
Literal::_new(imp::Literal::f32_suffixed(f))
}
pub fn string(string: &str) -> Literal {
Literal::_new(imp::Literal::string(string))
}
pub fn character(ch: char) -> Literal {
Literal::_new(imp::Literal::character(ch))
}
pub fn byte_string(s: &[u8]) -> Literal {
Literal::_new(imp::Literal::byte_string(s))
}
pub fn span(&self) -> Span {
Span::_new(self.inner.span())
}
pub fn set_span(&mut self, span: Span) {
self.inner.set_span(span.inner);
}
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
self.inner.subspan(range).map(Span::_new)
}
}
impl FromStr for Literal {
type Err = LexError;
fn from_str(repr: &str) -> Result<Self, LexError> {
repr.parse()
.map(Literal::_new)
.map_err(|inner| LexError { inner })
}
}
impl Debug for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
impl Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
#[doc(hidden)]
pub mod token_stream {
use crate::{imp, TokenTree};
use std::fmt::{self, Debug};
pub use crate::TokenStream;
#[derive(Clone)]
pub struct IntoIter {
inner: imp::TokenTreeIter,
}
impl Iterator for IntoIter {
type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> {
self.inner.next()
}
}
impl Debug for IntoIter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
impl IntoIterator for TokenStream {
type Item = TokenTree;
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter {
IntoIter {
inner: self.inner.into_iter(),
}
}
}
}