]>
Commit | Line | Data |
---|---|---|
970d7e83 | 1 | // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
1a4d82fc JJ |
11 | pub use self::BinOpToken::*; |
12 | pub use self::Nonterminal::*; | |
13 | pub use self::DelimToken::*; | |
1a4d82fc JJ |
14 | pub use self::Lit::*; |
15 | pub use self::Token::*; | |
16 | ||
9e0c209e | 17 | use ast::{self}; |
1a4d82fc | 18 | use ptr::P; |
476ff2be | 19 | use symbol::keywords; |
3157f602 | 20 | use tokenstream; |
223e47cc | 21 | |
1a4d82fc | 22 | use std::fmt; |
1a4d82fc JJ |
23 | use std::rc::Rc; |
24 | ||
85aaf69f | 25 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
26 | pub enum BinOpToken { |
27 | Plus, | |
28 | Minus, | |
29 | Star, | |
30 | Slash, | |
31 | Percent, | |
32 | Caret, | |
33 | And, | |
34 | Or, | |
35 | Shl, | |
36 | Shr, | |
37 | } | |
38 | ||
39 | /// A delimiter token | |
85aaf69f | 40 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
41 | pub enum DelimToken { |
42 | /// A round parenthesis: `(` or `)` | |
43 | Paren, | |
44 | /// A square bracket: `[` or `]` | |
45 | Bracket, | |
46 | /// A curly brace: `{` or `}` | |
47 | Brace, | |
5bcae85e SL |
48 | /// An empty delimiter |
49 | NoDelim, | |
1a4d82fc JJ |
50 | } |
51 | ||
32a655c1 | 52 | impl DelimToken { |
8bb4bdeb XL |
53 | pub fn len(self) -> usize { |
54 | if self == NoDelim { 0 } else { 1 } | |
32a655c1 SL |
55 | } |
56 | } | |
57 | ||
85aaf69f | 58 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
59 | pub enum Lit { |
60 | Byte(ast::Name), | |
61 | Char(ast::Name), | |
62 | Integer(ast::Name), | |
63 | Float(ast::Name), | |
64 | Str_(ast::Name), | |
85aaf69f | 65 | StrRaw(ast::Name, usize), /* raw str delimited by n hash symbols */ |
e9174d1e SL |
66 | ByteStr(ast::Name), |
67 | ByteStrRaw(ast::Name, usize), /* raw byte str delimited by n hash symbols */ | |
1a4d82fc JJ |
68 | } |
69 | ||
70 | impl Lit { | |
71 | pub fn short_name(&self) -> &'static str { | |
72 | match *self { | |
73 | Byte(_) => "byte", | |
74 | Char(_) => "char", | |
75 | Integer(_) => "integer", | |
76 | Float(_) => "float", | |
e9174d1e SL |
77 | Str_(_) | StrRaw(..) => "string", |
78 | ByteStr(_) | ByteStrRaw(..) => "byte string" | |
1a4d82fc JJ |
79 | } |
80 | } | |
81 | } | |
82 | ||
32a655c1 SL |
83 | fn ident_can_begin_expr(ident: ast::Ident) -> bool { |
84 | let ident_token: Token = Ident(ident); | |
85 | ||
86 | !ident_token.is_any_keyword() || | |
87 | ident_token.is_path_segment_keyword() || | |
88 | [ | |
89 | keywords::Box.name(), | |
90 | keywords::Break.name(), | |
91 | keywords::Continue.name(), | |
92 | keywords::False.name(), | |
93 | keywords::For.name(), | |
94 | keywords::If.name(), | |
95 | keywords::Loop.name(), | |
96 | keywords::Match.name(), | |
97 | keywords::Move.name(), | |
98 | keywords::Return.name(), | |
99 | keywords::True.name(), | |
100 | keywords::Unsafe.name(), | |
101 | keywords::While.name(), | |
102 | ].contains(&ident.name) | |
103 | } | |
104 | ||
85aaf69f | 105 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)] |
223e47cc LB |
106 | pub enum Token { |
107 | /* Expression-operator symbols. */ | |
1a4d82fc JJ |
108 | Eq, |
109 | Lt, | |
110 | Le, | |
111 | EqEq, | |
112 | Ne, | |
113 | Ge, | |
114 | Gt, | |
115 | AndAnd, | |
116 | OrOr, | |
117 | Not, | |
118 | Tilde, | |
119 | BinOp(BinOpToken), | |
120 | BinOpEq(BinOpToken), | |
223e47cc LB |
121 | |
122 | /* Structural symbols */ | |
1a4d82fc JJ |
123 | At, |
124 | Dot, | |
125 | DotDot, | |
126 | DotDotDot, | |
127 | Comma, | |
128 | Semi, | |
129 | Colon, | |
130 | ModSep, | |
131 | RArrow, | |
132 | LArrow, | |
133 | FatArrow, | |
134 | Pound, | |
135 | Dollar, | |
136 | Question, | |
137 | /// An opening delimiter, eg. `{` | |
138 | OpenDelim(DelimToken), | |
139 | /// A closing delimiter, eg. `}` | |
140 | CloseDelim(DelimToken), | |
223e47cc LB |
141 | |
142 | /* Literals */ | |
1a4d82fc | 143 | Literal(Lit, Option<ast::Name>), |
223e47cc LB |
144 | |
145 | /* Name components */ | |
a7813a04 | 146 | Ident(ast::Ident), |
1a4d82fc JJ |
147 | Underscore, |
148 | Lifetime(ast::Ident), | |
223e47cc LB |
149 | |
150 | /* For interpolation */ | |
c30ab7b3 | 151 | Interpolated(Rc<Nonterminal>), |
1a4d82fc JJ |
152 | // Can be expanded into several tokens. |
153 | /// Doc comment | |
154 | DocComment(ast::Name), | |
1a4d82fc JJ |
155 | // In right-hand-sides of MBE macros: |
156 | /// A syntactic variable that will be filled in by macro expansion. | |
a7813a04 | 157 | SubstNt(ast::Ident), |
1a4d82fc JJ |
158 | |
159 | // Junk. These carry no data because we don't really care about the data | |
160 | // they *would* carry, and don't really want to allocate a new ident for | |
161 | // them. Instead, users could extract that from the associated span. | |
162 | ||
163 | /// Whitespace | |
164 | Whitespace, | |
165 | /// Comment | |
166 | Comment, | |
167 | Shebang(ast::Name), | |
168 | ||
169 | Eof, | |
170 | } | |
171 | ||
172 | impl Token { | |
bd371182 AL |
173 | /// Returns `true` if the token starts with '>'. |
174 | pub fn is_like_gt(&self) -> bool { | |
175 | match *self { | |
176 | BinOp(Shr) | BinOpEq(Shr) | Gt | Ge => true, | |
177 | _ => false, | |
178 | } | |
179 | } | |
180 | ||
1a4d82fc JJ |
181 | /// Returns `true` if the token can appear at the start of an expression. |
182 | pub fn can_begin_expr(&self) -> bool { | |
183 | match *self { | |
c30ab7b3 | 184 | OpenDelim(..) => true, |
32a655c1 | 185 | Ident(ident) => ident_can_begin_expr(ident), |
9e0c209e | 186 | Literal(..) => true, |
1a4d82fc JJ |
187 | Not => true, |
188 | BinOp(Minus) => true, | |
189 | BinOp(Star) => true, | |
190 | BinOp(And) => true, | |
191 | BinOp(Or) => true, // in lambda syntax | |
192 | OrOr => true, // in lambda syntax | |
85aaf69f | 193 | AndAnd => true, // double borrow |
54a0048b | 194 | DotDot | DotDotDot => true, // range notation |
c30ab7b3 | 195 | Lt | BinOp(Shl) => true, // associated path |
1a4d82fc | 196 | ModSep => true, |
92a42be0 | 197 | Pound => true, // for expression attributes |
c30ab7b3 SL |
198 | Interpolated(ref nt) => match **nt { |
199 | NtExpr(..) => true, | |
200 | NtIdent(..) => true, | |
201 | NtBlock(..) => true, | |
202 | NtPath(..) => true, | |
203 | _ => false, | |
204 | }, | |
205 | _ => false, | |
1a4d82fc JJ |
206 | } |
207 | } | |
223e47cc | 208 | |
32a655c1 SL |
209 | /// Returns `true` if the token can appear at the start of a type. |
210 | pub fn can_begin_type(&self) -> bool { | |
211 | match *self { | |
212 | OpenDelim(Paren) => true, // tuple | |
213 | OpenDelim(Bracket) => true, // array | |
214 | Ident(..) => true, // type name or keyword | |
215 | Underscore => true, // placeholder | |
216 | Not => true, // never | |
217 | BinOp(Star) => true, // raw pointer | |
218 | BinOp(And) => true, // reference | |
219 | AndAnd => true, // double reference | |
220 | Lt | BinOp(Shl) => true, // associated path | |
221 | ModSep => true, // global path | |
222 | Interpolated(ref nt) => match **nt { | |
223 | NtTy(..) => true, | |
224 | NtIdent(..) => true, | |
225 | NtPath(..) => true, | |
226 | _ => false, | |
227 | }, | |
228 | _ => false, | |
229 | } | |
230 | } | |
231 | ||
1a4d82fc JJ |
232 | /// Returns `true` if the token is any literal |
233 | pub fn is_lit(&self) -> bool { | |
234 | match *self { | |
9e0c209e SL |
235 | Literal(..) => true, |
236 | _ => false, | |
1a4d82fc JJ |
237 | } |
238 | } | |
223e47cc | 239 | |
1a4d82fc JJ |
240 | /// Returns `true` if the token is an identifier. |
241 | pub fn is_ident(&self) -> bool { | |
242 | match *self { | |
a7813a04 | 243 | Ident(..) => true, |
1a4d82fc | 244 | _ => false, |
223e47cc | 245 | } |
1a4d82fc JJ |
246 | } |
247 | ||
9e0c209e SL |
248 | /// Returns `true` if the token is a documentation comment. |
249 | pub fn is_doc_comment(&self) -> bool { | |
250 | match *self { | |
251 | DocComment(..) => true, | |
252 | _ => false, | |
253 | } | |
254 | } | |
255 | ||
7453a54e SL |
256 | /// Returns `true` if the token is interpolated. |
257 | pub fn is_interpolated(&self) -> bool { | |
258 | match *self { | |
259 | Interpolated(..) => true, | |
260 | _ => false, | |
261 | } | |
262 | } | |
263 | ||
1a4d82fc JJ |
264 | /// Returns `true` if the token is an interpolated path. |
265 | pub fn is_path(&self) -> bool { | |
c30ab7b3 SL |
266 | if let Interpolated(ref nt) = *self { |
267 | if let NtPath(..) = **nt { | |
268 | return true; | |
269 | } | |
1a4d82fc | 270 | } |
c30ab7b3 | 271 | false |
1a4d82fc JJ |
272 | } |
273 | ||
1a4d82fc JJ |
274 | /// Returns `true` if the token is a lifetime. |
275 | pub fn is_lifetime(&self) -> bool { | |
276 | match *self { | |
277 | Lifetime(..) => true, | |
278 | _ => false, | |
223e47cc | 279 | } |
1a4d82fc JJ |
280 | } |
281 | ||
282 | /// Returns `true` if the token is either the `mut` or `const` keyword. | |
283 | pub fn is_mutability(&self) -> bool { | |
284 | self.is_keyword(keywords::Mut) || | |
285 | self.is_keyword(keywords::Const) | |
286 | } | |
287 | ||
c30ab7b3 SL |
288 | pub fn is_qpath_start(&self) -> bool { |
289 | self == &Lt || self == &BinOp(Shl) | |
290 | } | |
291 | ||
a7813a04 | 292 | pub fn is_path_start(&self) -> bool { |
c30ab7b3 | 293 | self == &ModSep || self.is_qpath_start() || self.is_path() || |
a7813a04 XL |
294 | self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword() |
295 | } | |
296 | ||
1a4d82fc | 297 | /// Returns `true` if the token is a given keyword, `kw`. |
1a4d82fc JJ |
298 | pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { |
299 | match *self { | |
a7813a04 XL |
300 | Ident(id) => id.name == kw.name(), |
301 | _ => false, | |
1a4d82fc JJ |
302 | } |
303 | } | |
304 | ||
a7813a04 | 305 | pub fn is_path_segment_keyword(&self) -> bool { |
1a4d82fc | 306 | match *self { |
a7813a04 XL |
307 | Ident(id) => id.name == keywords::Super.name() || |
308 | id.name == keywords::SelfValue.name() || | |
309 | id.name == keywords::SelfType.name(), | |
310 | _ => false, | |
1a4d82fc JJ |
311 | } |
312 | } | |
313 | ||
a7813a04 | 314 | /// Returns `true` if the token is either a strict or reserved keyword. |
1a4d82fc | 315 | pub fn is_any_keyword(&self) -> bool { |
a7813a04 | 316 | self.is_strict_keyword() || self.is_reserved_keyword() |
1a4d82fc JJ |
317 | } |
318 | ||
a7813a04 | 319 | /// Returns `true` if the token is a strict keyword. |
1a4d82fc JJ |
320 | pub fn is_strict_keyword(&self) -> bool { |
321 | match *self { | |
a7813a04 XL |
322 | Ident(id) => id.name >= keywords::As.name() && |
323 | id.name <= keywords::While.name(), | |
1a4d82fc JJ |
324 | _ => false, |
325 | } | |
326 | } | |
327 | ||
a7813a04 | 328 | /// Returns `true` if the token is a keyword reserved for possible future use. |
1a4d82fc JJ |
329 | pub fn is_reserved_keyword(&self) -> bool { |
330 | match *self { | |
a7813a04 XL |
331 | Ident(id) => id.name >= keywords::Abstract.name() && |
332 | id.name <= keywords::Yield.name(), | |
1a4d82fc JJ |
333 | _ => false, |
334 | } | |
335 | } | |
223e47cc LB |
336 | } |
337 | ||
1a4d82fc JJ |
338 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)] |
339 | /// For interpolation during macro expansion. | |
340 | pub enum Nonterminal { | |
341 | NtItem(P<ast::Item>), | |
342 | NtBlock(P<ast::Block>), | |
c30ab7b3 | 343 | NtStmt(ast::Stmt), |
1a4d82fc JJ |
344 | NtPat(P<ast::Pat>), |
345 | NtExpr(P<ast::Expr>), | |
346 | NtTy(P<ast::Ty>), | |
c30ab7b3 | 347 | NtIdent(ast::SpannedIdent), |
1a4d82fc | 348 | /// Stuff inside brackets for attributes |
476ff2be | 349 | NtMeta(ast::MetaItem), |
c30ab7b3 SL |
350 | NtPath(ast::Path), |
351 | NtTT(tokenstream::TokenTree), | |
92a42be0 | 352 | // These are not exposed to macros, but are used by quasiquote. |
d9579d0f | 353 | NtArm(ast::Arm), |
c30ab7b3 SL |
354 | NtImplItem(ast::ImplItem), |
355 | NtTraitItem(ast::TraitItem), | |
d9579d0f AL |
356 | NtGenerics(ast::Generics), |
357 | NtWhereClause(ast::WhereClause), | |
92a42be0 | 358 | NtArg(ast::Arg), |
1a4d82fc JJ |
359 | } |
360 | ||
85aaf69f | 361 | impl fmt::Debug for Nonterminal { |
1a4d82fc JJ |
362 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
363 | match *self { | |
364 | NtItem(..) => f.pad("NtItem(..)"), | |
365 | NtBlock(..) => f.pad("NtBlock(..)"), | |
366 | NtStmt(..) => f.pad("NtStmt(..)"), | |
367 | NtPat(..) => f.pad("NtPat(..)"), | |
368 | NtExpr(..) => f.pad("NtExpr(..)"), | |
369 | NtTy(..) => f.pad("NtTy(..)"), | |
370 | NtIdent(..) => f.pad("NtIdent(..)"), | |
371 | NtMeta(..) => f.pad("NtMeta(..)"), | |
372 | NtPath(..) => f.pad("NtPath(..)"), | |
373 | NtTT(..) => f.pad("NtTT(..)"), | |
d9579d0f AL |
374 | NtArm(..) => f.pad("NtArm(..)"), |
375 | NtImplItem(..) => f.pad("NtImplItem(..)"), | |
376 | NtTraitItem(..) => f.pad("NtTraitItem(..)"), | |
377 | NtGenerics(..) => f.pad("NtGenerics(..)"), | |
378 | NtWhereClause(..) => f.pad("NtWhereClause(..)"), | |
92a42be0 | 379 | NtArg(..) => f.pad("NtArg(..)"), |
1a4d82fc | 380 | } |
970d7e83 LB |
381 | } |
382 | } |