mod chain;
mod generic;
mod parse_atom;
mod space;
pub(crate) use chain::parse_item;
pub(crate) use generic::split_at_depth0;
pub(crate) use space::*;
use proc_macro2::{Group, Ident, TokenStream, TokenTree};
use crate::ast::fresh::at_ref_name;
use crate::ast::*;
use crate::util::{Cursor, compile_error_str};
pub(crate) fn resolve_at_refs(tokens: &[TokenTree]) -> Result<Vec<TokenTree>, TokenStream> {
let mut out = Vec::with_capacity(tokens.len());
let mut i = 0;
while i < tokens.len() {
match &tokens[i] {
TokenTree::Punct(p) if p.as_char() == '@' => {
let at_span = p.span();
match tokens.get(i + 1) {
Some(TokenTree::Literal(lit)) => {
let name = at_ref_name(&lit.to_string()).ok_or_else(|| {
compile_error_str(
"batch-impl: `@` in a type must be followed by a \
position digit (e.g. `@0` or `@0_1`)",
at_span,
)
})?;
let ident = Ident::new(&name, at_span);
out.push(TokenTree::Ident(ident));
i += 2;
}
_ => {
return Err(compile_error_str(
"batch-impl: `@` in a type must be a position digit (e.g. `@0` or `@0_1`)",
at_span,
));
}
}
}
TokenTree::Group(g) => {
let inner = g.stream().into_iter().collect::<Vec<_>>();
let mut new_g =
Group::new(g.delimiter(), resolve_at_refs(&inner)?.into_iter().collect());
new_g.set_span(g.span());
out.push(TokenTree::Group(new_g));
i += 1;
}
_ => {
out.push(tokens[i].clone());
i += 1;
}
}
}
Ok(out)
}
pub(crate) fn parse_primitive(tokens: &[TokenTree], trait_name: Option<&Ident>) -> Ty {
let mut cursor = Cursor::new(tokens);
parse_block(&mut cursor, trait_name).unwrap_or_else(|| crate::parse::generic::primitive(tokens))
}