1use std::str::FromStr;
2
3use super::ToTokens;
4use crate::lex::{Cursor, LexError, Scan};
5use crate::span::DelimSpan;
6use crate::{Span, Spanner, Token, TokenTree};
7
8#[derive(Debug, Default, Clone, PartialEq, Eq)]
10pub struct TokenStream(Vec<TokenTree>);
11
12impl TokenStream {
13 #[inline]
14 pub fn new() -> Self {
15 Self(vec![])
16 }
17
18 #[inline]
19 pub fn with_capacity(capacity: usize) -> Self {
20 Self(Vec::with_capacity(capacity))
21 }
22
23 #[inline]
24 pub fn is_empty(&self) -> bool {
25 self.0.is_empty()
26 }
27
28 #[inline]
29 pub fn iter(&self) -> impl Iterator<Item = &TokenTree> {
30 self.0.iter()
31 }
32
33 #[inline]
34 pub fn first(&self) -> Span {
35 self.0.first().map(|v| v.span()).unwrap_or_default()
36 }
37
38 #[inline]
39 pub fn last(&self) -> Span {
40 self.0.last().map(|v| v.span()).unwrap_or_default()
41 }
42
43 #[inline]
44 pub fn span(&self) -> Span {
45 self.first().join(self.last())
46 }
47
48 #[inline]
49 pub fn delim(&self) -> DelimSpan {
50 DelimSpan::new(self.first(), self.last())
51 }
52
53 #[inline]
54 pub fn extend_one(&mut self, token: TokenTree) {
55 self.0.push(token);
56 }
57
58 #[inline]
59 pub fn into_inner(self) -> Vec<TokenTree> {
60 self.0
61 }
62
63 #[inline]
64 pub fn to_vec(self) -> Vec<TokenTree> {
65 self.0
66 }
67}
68
69impl std::ops::Deref for TokenStream {
70 type Target = [TokenTree];
71
72 fn deref(&self) -> &[TokenTree] {
73 self.0.as_slice()
74 }
75}
76
77impl Extend<TokenTree> for TokenStream {
78 fn extend<T: IntoIterator<Item = TokenTree>>(&mut self, iter: T) {
79 self.0.extend(iter);
80 }
81}
82
83impl FromIterator<TokenTree> for TokenStream {
84 fn from_iter<T: IntoIterator<Item = TokenTree>>(iter: T) -> Self {
85 Self(iter.into_iter().collect())
86 }
87}
88
89impl FromIterator<Self> for TokenStream {
90 fn from_iter<T: IntoIterator<Item = Self>>(iter: T) -> Self {
91 Self(iter.into_iter().flat_map(|s| s.into_iter()).collect())
92 }
93}
94
95impl IntoIterator for TokenStream {
96 type Item = TokenTree;
97 type IntoIter = std::vec::IntoIter<TokenTree>;
98
99 fn into_iter(self) -> Self::IntoIter {
100 self.0.into_iter()
101 }
102}
103
104impl From<Vec<TokenTree>> for TokenStream {
105 #[inline]
106 fn from(value: Vec<TokenTree>) -> Self {
107 Self(value)
108 }
109}
110
111impl From<&[TokenTree]> for TokenStream {
112 #[inline]
113 fn from(value: &[TokenTree]) -> Self {
114 Self(value.to_vec())
115 }
116}
117
118impl From<TokenStream> for Vec<TokenTree> {
119 #[inline]
120 fn from(value: TokenStream) -> Self {
121 value.0
122 }
123}
124
125impl Spanner for TokenStream {
126 fn span(&self) -> Span {
127 self.first().join(self.last())
128 }
129}
130
131impl Scan for TokenStream {
132 fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
133 let mut tokens = Vec::with_capacity(8);
134 let mut c = cursor;
135
136 loop {
137 c = c.skip_whitespace();
138
139 if c.is_empty() {
140 break;
141 }
142
143 if let Some((next, inner, text)) = c.doc_comment() {
145 push_doc_attr(&mut tokens, inner, &text, c.span_to(&next));
146 c = next;
147 continue;
148 }
149
150 if let Some(')' | ']' | '}') = c.first() {
152 break;
153 }
154
155 if let Ok((next, group)) = crate::Group::scan(c) {
157 tokens.push(TokenTree::Group(group));
158 c = next;
159 continue;
160 }
161
162 if let Ok((next, lit)) = crate::Lit::scan(c) {
163 tokens.push(TokenTree::Literal(lit));
164 c = next;
165 continue;
166 }
167
168 if let Ok((next, keyword)) = crate::Keyword::scan(c) {
169 tokens.push(TokenTree::Keyword(keyword));
170 c = next;
171 continue;
172 }
173
174 if let Ok((next, ident)) = crate::Ident::scan(c) {
175 tokens.push(TokenTree::Ident(ident));
176 c = next;
177 continue;
178 }
179
180 if let Ok((next, punct)) = crate::Punct::scan(c) {
181 tokens.push(TokenTree::Punct(punct));
182 c = next;
183 continue;
184 }
185
186 return Err(c
187 .error()
188 .message(format!("unexpected character '{}'", c.first().unwrap_or('\0'))));
189 }
190
191 Ok((c, Self(tokens)))
192 }
193}
194
195impl FromStr for TokenStream {
196 type Err = LexError;
197
198 fn from_str(s: &str) -> Result<Self, Self::Err> {
199 Self::from_string(s.to_owned())
200 }
201}
202
203impl TokenStream {
204 pub fn from_string(s: String) -> Result<Self, LexError> {
207 use crate::source::SourceMap;
208
209 SourceMap::with_mut(|sm| {
210 let span = sm.push(s);
211 let source = sm.find(span).expect("new source missing from source map");
212 let cursor = Cursor::new(source.text(), span.byte_range().start as u32);
213 let (rest, stream) = Self::scan(cursor)?;
214 let rest = rest.skip_whitespace();
215
216 if !rest.is_empty() {
217 return rest.error().message("unexpected trailing input").into();
218 }
219
220 Ok(stream)
221 })
222 }
223}
224
225impl std::fmt::Display for TokenStream {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 let mut first = true;
228 let mut prev_was_joint = false;
229
230 for tt in self.0.iter() {
231 if !first && !prev_was_joint {
232 write!(f, " ")?;
233 }
234
235 write!(f, "{}", tt)?;
236 first = false;
237 prev_was_joint = matches!(tt, TokenTree::Punct(punct) if punct.spacing().is_joint());
238 }
239
240 Ok(())
241 }
242}
243
244impl ToTokens for TokenStream {
245 fn to_tokens(&self, tokens: &mut Self) {
246 tokens.extend(self.clone());
247 }
248}
249
250#[cfg(feature = "serde")]
251impl serde::Serialize for TokenStream {
252 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
253 where
254 S: serde::Serializer,
255 {
256 self.0.serialize(s)
257 }
258}
259
260fn push_doc_attr(tokens: &mut Vec<TokenTree>, inner: bool, text: &str, span: Span) {
261 use crate::{Delim, Group, Ident, Punct};
262
263 tokens.push(TokenTree::Punct(Punct::Pound(<Token![#]>::new(span))));
264
265 if inner {
266 tokens.push(TokenTree::Punct(Punct::Not(<Token![!]>::new(span))));
267 }
268
269 let mut body = TokenStream::with_capacity(3);
270 body.extend_one(TokenTree::Ident(Ident::new("doc").with_span(span)));
271 body.extend_one(TokenTree::Punct(Punct::Eq(<Token![=]>::new(span))));
272 body.extend_one(TokenTree::Literal(crate::Lit::Str(crate::LitStr::new(text, span))));
273
274 tokens.push(TokenTree::Group(Group::new(Delim::Bracket, body)));
275}