use crate::prelude::Delimiter;
use crate::prelude::Group;
use crate::prelude::Ident;
use crate::prelude::LexError;
use crate::prelude::Literal;
use crate::prelude::Punct;
use crate::prelude::Result;
use crate::prelude::Spacing;
use crate::prelude::Span;
use crate::prelude::TokenStream;
use crate::prelude::TokenTree;
use std::str::FromStr;
#[must_use]
#[derive(Default)]
pub struct StreamBuilder {
pub(crate) stream: TokenStream,
}
impl StreamBuilder {
pub fn new() -> Self {
Self {
stream: TokenStream::new(),
}
}
pub fn extend(
&mut self,
item: impl IntoIterator<Item = TokenTree>,
) -> &mut Self {
self.stream.extend(item);
self
}
pub fn append(
&mut self,
builder: Self,
) -> &mut Self {
self.stream.extend(builder.stream);
self
}
pub fn push(
&mut self,
item: impl Into<TokenTree>,
) -> &mut Self {
self.stream.extend([item.into()]);
self
}
pub fn push_parsed(
&mut self,
item: impl AsRef<str>,
) -> Result<&mut Self> {
let tokens = TokenStream::from_str(item.as_ref()).map_err(|e| {
PushParseError {
error: e,
code: item.as_ref().to_string(),
}
})?;
self.stream.extend(tokens);
Ok(self)
}
pub fn ident(
&mut self,
ident: Ident,
) -> &mut Self {
self.stream.extend([TokenTree::Ident(ident)]);
self
}
pub fn ident_str(
&mut self,
ident: impl AsRef<str>,
) -> &mut Self {
self.stream.extend([TokenTree::Ident(Ident::new(
ident.as_ref(),
Span::call_site(),
))]);
self
}
pub fn group<FN>(
&mut self,
delim: Delimiter,
inner: FN,
) -> crate::Result<&mut Self>
where
FN: FnOnce(&mut Self) -> crate::Result<()>,
{
let mut stream = Self::new();
inner(&mut stream)?;
self.stream
.extend([TokenTree::Group(Group::new(delim, stream.stream))]);
Ok(self)
}
pub fn punct(
&mut self,
p: char,
) -> &mut Self {
self.stream
.extend([TokenTree::Punct(Punct::new(p, Spacing::Alone))]);
self
}
pub fn puncts(
&mut self,
puncts: &str,
) -> &mut Self {
self.stream.extend(
puncts
.chars()
.map(|char| TokenTree::Punct(Punct::new(char, Spacing::Joint))),
);
self
}
pub fn lifetime(
&mut self,
lt: Ident,
) -> &mut Self {
self.stream.extend([
TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
TokenTree::Ident(lt),
]);
self
}
pub fn lifetime_str(
&mut self,
lt: &str,
) -> &mut Self {
self.stream.extend([
TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
TokenTree::Ident(Ident::new(lt, Span::call_site())),
]);
self
}
pub fn lit_str(
&mut self,
str: impl AsRef<str>,
) -> &mut Self {
self.stream
.extend([TokenTree::Literal(Literal::string(str.as_ref()))]);
self
}
pub fn lit_usize(
&mut self,
val: usize,
) -> &mut Self {
self.stream
.extend([TokenTree::Literal(Literal::usize_unsuffixed(val))]);
self
}
pub fn set_span_on_all_tokens(
&mut self,
span: Span,
) {
self.stream = std::mem::take(&mut self.stream)
.into_iter()
.map(|mut token| {
token.set_span(span);
token
})
.collect();
}
}
#[derive(Debug)]
pub struct PushParseError {
pub error: LexError,
pub code: String,
}