use std::fmt::Debug;
use crate::proc_macro::{TokenStream, TokenTree};
#[derive(Debug)]
pub struct KTokenStream {
pos: usize,
kstream: Vec<TokenTree>,
size: usize,
}
impl From<TokenStream> for KTokenStream {
fn from(value: TokenStream) -> Self {
KTokenStream::new(&value)
}
}
impl From<&TokenStream> for KTokenStream {
fn from(value: &TokenStream) -> Self {
KTokenStream::new(value)
}
}
impl KTokenStream {
pub fn new(tokens: &TokenStream) -> Self {
KTokenStream::new_with_pos(tokens, 0)
}
pub fn new_with_pos(tokens: &TokenStream, pos: usize) -> Self {
let mut kstream = Vec::new();
tokens
.to_owned()
.into_iter()
.for_each(|token| kstream.push(token));
KTokenStream {
pos,
kstream: kstream.to_vec(),
size: kstream.len(),
}
}
pub fn advance(&mut self) -> TokenTree {
self.next();
if self.is_end() {
return self.kstream.last().unwrap().to_owned();
}
self.prev().to_owned()
}
pub fn lookup(&self, step: usize) -> &TokenTree {
assert!(self.size > self.pos + step);
&self.kstream[self.pos + step]
}
pub fn has(&self, step: usize) -> bool {
self.size > self.pos + step
}
pub fn next(&mut self) {
self.pos += 1;
}
pub fn prev(&self) -> &TokenTree {
assert!(self.pos < self.size, "prev: out of bound");
&self.kstream[self.pos - 1]
}
pub fn peek(&self) -> &TokenTree {
assert!(
self.pos < self.size,
"peek: out of bound requested {} vs tot size {}",
self.pos,
self.size
);
&self.kstream[self.pos]
}
pub fn last(&self) -> &TokenTree {
self.kstream.last().unwrap()
}
pub fn match_tok(&self, tok: &str) -> bool {
self.peek().match_tok(tok)
}
pub fn is_end(&self) -> bool {
self.pos >= self.size
}
pub fn to_ktoken_stream(&self) -> KTokenStream {
match self.peek() {
TokenTree::Group(stream) => KTokenStream::new(&stream.stream()),
_ => panic!("no stream on token {:?}", self.peek()),
}
}
pub fn opt_ktoken_stream(&self) -> Option<KTokenStream> {
match self.peek() {
TokenTree::Group(stream) => Some(KTokenStream::new(&stream.stream())),
_ => None,
}
}
pub fn unwrap_group(&self) -> TokenTree {
match self.peek() {
TokenTree::Group(_) => self.peek().clone(),
_ => panic!("the token {:?} is not a `TokenTree::Group`", self.peek()),
}
}
pub fn unwrap_group_as_stream(&self) -> TokenStream {
match self.peek() {
TokenTree::Group(stream) => stream.stream(),
_ => panic!("the token {:?} is not a `TokenTree::Group`", self.peek()),
}
}
pub fn is_group(&self) -> bool {
match self.peek() {
TokenTree::Group(_) => true,
_ => false,
}
}
pub fn consume_brace(&mut self) {
let tok = self.peek();
match tok.to_string().as_str() {
"{" | "}" => {
self.advance();
}
_ => {}
}
}
}
pub trait MatchTok
where
Self: ToString + Debug,
{
fn match_tok(&self, tok: &str) -> bool {
self.to_string().as_str() == tok
}
fn to_token_stream(&self) -> KTokenStream;
}
impl MatchTok for TokenTree {
fn to_token_stream(&self) -> KTokenStream {
match self {
TokenTree::Group(stream) => KTokenStream::new(&stream.stream()),
_ => panic!("no stream on token {:?}", self),
}
}
}
#[derive(Clone, Debug)]
pub struct OrderedTokenTree {
idx: u64,
token: TokenTree,
}
impl OrderedTokenTree {
pub fn new(idx: u64, token: TokenTree) -> Self {
OrderedTokenTree { idx, token }
}
pub fn token(&self) -> TokenTree {
self.token.clone()
}
pub fn idx(&mut self, idx: u64) {
self.idx = idx;
}
}
impl From<TokenTree> for OrderedTokenTree {
fn from(value: TokenTree) -> Self {
OrderedTokenTree::new(0, value)
}
}
impl PartialOrd for OrderedTokenTree {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.idx.partial_cmp(&other.idx)
}
}
impl Ord for OrderedTokenTree {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.idx.cmp(&other.idx)
}
}
impl PartialEq for OrderedTokenTree {
fn eq(&self, other: &Self) -> bool {
self.idx.eq(&other.idx)
}
}
impl Eq for OrderedTokenTree {}