]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/parse/token.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / libsyntax / parse / token.rs
CommitLineData
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
11pub use self::BinOpToken::*;
12pub use self::Nonterminal::*;
13pub use self::DelimToken::*;
1a4d82fc
JJ
14pub use self::Lit::*;
15pub use self::Token::*;
16
9e0c209e 17use ast::{self};
1a4d82fc 18use ptr::P;
476ff2be 19use symbol::keywords;
3157f602 20use tokenstream;
223e47cc 21
1a4d82fc 22use std::fmt;
1a4d82fc
JJ
23use std::rc::Rc;
24
85aaf69f 25#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
1a4d82fc
JJ
26pub 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
41pub 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 52impl 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
59pub 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
70impl 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
83fn 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
106pub 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
172impl 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.
340pub 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 361impl 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}