kproc_parser/
kproc_macros.rs

1//! core module that implement the basic concept
2//! used inside the parser.
3use std::fmt::Debug;
4
5use crate::proc_macro::{TokenStream, TokenTree};
6
7/// Convinient way to manage any kind of tokens stream
8/// by exposing basic function to advance and consume
9/// the stream.
10///
11/// Heavenly inspired to `albert_stream` <https://github.com/vincenzopalazzo/albert/tree/main/stream>
12#[derive(Debug)]
13pub struct KTokenStream {
14    pos: usize,
15    kstream: Vec<TokenTree>,
16    size: usize,
17}
18
19impl From<TokenStream> for KTokenStream {
20    fn from(value: TokenStream) -> Self {
21        KTokenStream::new(&value)
22    }
23}
24
25impl From<&TokenStream> for KTokenStream {
26    fn from(value: &TokenStream) -> Self {
27        KTokenStream::new(value)
28    }
29}
30
31impl KTokenStream {
32    /// create a new instance from a TokenStream
33    pub fn new(tokens: &TokenStream) -> Self {
34        KTokenStream::new_with_pos(tokens, 0)
35    }
36
37    /// create the a new instance from a TokenStream and the
38    /// initial position
39    pub fn new_with_pos(tokens: &TokenStream, pos: usize) -> Self {
40        let mut kstream = Vec::new();
41        tokens
42            .to_owned()
43            .into_iter()
44            .for_each(|token| kstream.push(token));
45        KTokenStream {
46            pos,
47            kstream: kstream.to_vec(),
48            size: kstream.len(),
49        }
50    }
51
52    /// advance the position and return the previous element
53    /// in position - 1
54    pub fn advance(&mut self) -> TokenTree {
55        self.next();
56        if self.is_end() {
57            return self.kstream.last().unwrap().to_owned();
58        }
59        self.prev().to_owned()
60    }
61
62    /// perform a search operation inside the stream by a number
63    /// of specified steps.
64    pub fn lookup(&self, step: usize) -> &TokenTree {
65        assert!(self.size > self.pos + step);
66        &self.kstream[self.pos + step]
67    }
68
69    /// perform a search operation inside the stream by a number
70    /// of specified steps.
71    pub fn has(&self, step: usize) -> bool {
72        self.size > self.pos + step
73    }
74
75    /// advance the position of the stream.
76    pub fn next(&mut self) {
77        self.pos += 1;
78    }
79
80    /// take the previous element of the stream from the
81    /// current position.
82    pub fn prev(&self) -> &TokenTree {
83        assert!(self.pos < self.size, "prev: out of bound");
84        &self.kstream[self.pos - 1]
85    }
86
87    /// return he token at the current position.
88    pub fn peek(&self) -> &TokenTree {
89        assert!(
90            self.pos < self.size,
91            "peek: out of bound requested {} vs tot size {}",
92            self.pos,
93            self.size
94        );
95        &self.kstream[self.pos]
96    }
97
98    /// return the last token of the stream.
99    pub fn last(&self) -> &TokenTree {
100        self.kstream.last().unwrap()
101    }
102
103    /// match the current token with the one specified.
104    pub fn match_tok(&self, tok: &str) -> bool {
105        self.peek().match_tok(tok)
106    }
107
108    /// check if it is reach the end of the stream
109    pub fn is_end(&self) -> bool {
110        self.pos >= self.size
111    }
112
113    /// unwrap the `TokenTree::Group` and the return the
114    /// token stream that contains. If the current token
115    /// it is not a `TokenTree::Group` the function will panic
116    pub fn to_ktoken_stream(&self) -> KTokenStream {
117        match self.peek() {
118            TokenTree::Group(stream) => KTokenStream::new(&stream.stream()),
119            _ => panic!("no stream on token {:?}", self.peek()),
120        }
121    }
122
123    /// unwrap the `TokenTree::Group` and the return the
124    /// token stream that contains. If the current token
125    /// it is not a `TokenTree::Group` the function will panic
126    pub fn opt_ktoken_stream(&self) -> Option<KTokenStream> {
127        match self.peek() {
128            TokenTree::Group(stream) => Some(KTokenStream::new(&stream.stream())),
129            _ => None,
130        }
131    }
132
133    pub fn unwrap_group(&self) -> TokenTree {
134        match self.peek() {
135            TokenTree::Group(_) => self.peek().clone(),
136            _ => panic!("the token {:?} is not a `TokenTree::Group`", self.peek()),
137        }
138    }
139
140    pub fn unwrap_group_as_stream(&self) -> TokenStream {
141        match self.peek() {
142            TokenTree::Group(stream) => stream.stream(),
143            _ => panic!("the token {:?} is not a `TokenTree::Group`", self.peek()),
144        }
145    }
146
147    /// check if the current token is a `TokenTree::Group`
148    pub fn is_group(&self) -> bool {
149        match self.peek() {
150            TokenTree::Group(_) => true,
151            _ => false,
152        }
153    }
154
155    // FIXME: this can be removed?
156    pub fn consume_brace(&mut self) {
157        let tok = self.peek();
158        match tok.to_string().as_str() {
159            "{" | "}" => {
160                self.advance();
161            }
162            _ => {}
163        }
164    }
165}
166
167pub trait MatchTok
168where
169    Self: ToString + Debug,
170{
171    fn match_tok(&self, tok: &str) -> bool {
172        self.to_string().as_str() == tok
173    }
174
175    fn to_token_stream(&self) -> KTokenStream;
176}
177
178impl MatchTok for TokenTree {
179    fn to_token_stream(&self) -> KTokenStream {
180        match self {
181            TokenTree::Group(stream) => KTokenStream::new(&stream.stream()),
182            _ => panic!("no stream on token {:?}", self),
183        }
184    }
185}
186
187#[derive(Clone, Debug)]
188pub struct OrderedTokenTree {
189    idx: u64,
190    token: TokenTree,
191}
192
193impl OrderedTokenTree {
194    pub fn new(idx: u64, token: TokenTree) -> Self {
195        OrderedTokenTree { idx, token }
196    }
197
198    pub fn token(&self) -> TokenTree {
199        self.token.clone()
200    }
201
202    pub fn idx(&mut self, idx: u64) {
203        self.idx = idx;
204    }
205}
206
207impl From<TokenTree> for OrderedTokenTree {
208    fn from(value: TokenTree) -> Self {
209        OrderedTokenTree::new(0, value)
210    }
211}
212
213impl PartialOrd for OrderedTokenTree {
214    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
215        self.idx.partial_cmp(&other.idx)
216    }
217}
218
219impl Ord for OrderedTokenTree {
220    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
221        self.idx.cmp(&other.idx)
222    }
223}
224
225impl PartialEq for OrderedTokenTree {
226    fn eq(&self, other: &Self) -> bool {
227        self.idx.eq(&other.idx)
228    }
229}
230
231impl Eq for OrderedTokenTree {}