]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/parse/token.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / src / libsyntax / parse / token.rs
CommitLineData
9fa01778
XL
1pub use BinOpToken::*;
2pub use Nonterminal::*;
3pub use DelimToken::*;
dc9dc135
XL
4pub use LitKind::*;
5pub use TokenKind::*;
9fa01778 6
e74abb32 7use crate::ast;
9fa01778 8use crate::ptr::P;
dc9dc135 9use crate::symbol::kw;
e74abb32 10use crate::tokenstream::TokenTree;
9fa01778 11
dc9dc135 12use syntax_pos::symbol::Symbol;
e74abb32 13use syntax_pos::{self, Span, DUMMY_SP};
223e47cc 14
9fa01778 15use std::fmt;
83c7162d 16use std::mem;
9fa01778 17#[cfg(target_arch = "x86_64")]
48663c56 18use rustc_data_structures::static_assert_size;
9fa01778 19use rustc_data_structures::sync::Lrc;
1a4d82fc 20
8faf50e0 21#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
1a4d82fc
JJ
22pub enum BinOpToken {
23 Plus,
24 Minus,
25 Star,
26 Slash,
27 Percent,
28 Caret,
29 And,
30 Or,
31 Shl,
32 Shr,
33}
34
9fa01778 35/// A delimiter token.
e74abb32 36#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
1a4d82fc 37pub enum DelimToken {
9fa01778 38 /// A round parenthesis (i.e., `(` or `)`).
1a4d82fc 39 Paren,
9fa01778 40 /// A square bracket (i.e., `[` or `]`).
1a4d82fc 41 Bracket,
9fa01778 42 /// A curly brace (i.e., `{` or `}`).
1a4d82fc 43 Brace,
9fa01778 44 /// An empty delimiter.
5bcae85e 45 NoDelim,
1a4d82fc
JJ
46}
47
32a655c1 48impl DelimToken {
8bb4bdeb
XL
49 pub fn len(self) -> usize {
50 if self == NoDelim { 0 } else { 1 }
32a655c1 51 }
7cac9316
XL
52
53 pub fn is_empty(self) -> bool {
54 self == NoDelim
55 }
32a655c1
SL
56}
57
dc9dc135
XL
58#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
59pub enum LitKind {
60 Bool, // AST only, must never appear in a `Token`
61 Byte,
62 Char,
63 Integer,
64 Float,
65 Str,
66 StrRaw(u16), // raw string delimited by `n` hash symbols
67 ByteStr,
68 ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
69 Err,
1a4d82fc
JJ
70}
71
dc9dc135
XL
72/// A literal token.
73#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
74pub struct Lit {
75 pub kind: LitKind,
76 pub symbol: Symbol,
77 pub suffix: Option<Symbol>,
78}
48663c56 79
416331ca
XL
80impl fmt::Display for Lit {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let Lit { kind, symbol, suffix } = *self;
83 match kind {
84 Byte => write!(f, "b'{}'", symbol)?,
85 Char => write!(f, "'{}'", symbol)?,
86 Str => write!(f, "\"{}\"", symbol)?,
87 StrRaw(n) => write!(f, "r{delim}\"{string}\"{delim}",
88 delim="#".repeat(n as usize),
89 string=symbol)?,
90 ByteStr => write!(f, "b\"{}\"", symbol)?,
91 ByteStrRaw(n) => write!(f, "br{delim}\"{string}\"{delim}",
92 delim="#".repeat(n as usize),
93 string=symbol)?,
94 Integer |
95 Float |
96 Bool |
97 Err => write!(f, "{}", symbol)?,
98 }
99
100 if let Some(suffix) = suffix {
101 write!(f, "{}", suffix)?;
102 }
103
104 Ok(())
105 }
106}
107
dc9dc135
XL
108impl LitKind {
109 /// An English article for the literal token kind.
110 crate fn article(self) -> &'static str {
111 match self {
112 Integer | Err => "an",
113 _ => "a",
1a4d82fc
JJ
114 }
115 }
83c7162d 116
dc9dc135
XL
117 crate fn descr(self) -> &'static str {
118 match self {
119 Bool => panic!("literal token contains `Lit::Bool`"),
120 Byte => "byte",
121 Char => "char",
122 Integer => "integer",
123 Float => "float",
124 Str | StrRaw(..) => "string",
125 ByteStr | ByteStrRaw(..) => "byte string",
126 Err => "error",
127 }
128 }
129
130 crate fn may_have_suffix(self) -> bool {
131 match self {
132 Integer | Float | Err => true,
48663c56
XL
133 _ => false,
134 }
135 }
dc9dc135 136}
48663c56 137
dc9dc135
XL
138impl Lit {
139 pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
140 Lit { kind, symbol, suffix }
83c7162d 141 }
1a4d82fc
JJ
142}
143
dc9dc135
XL
144pub(crate) fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> bool {
145 let ident_token = Token::new(Ident(name, is_raw), span);
e74abb32
XL
146 token_can_begin_expr(&ident_token)
147}
32a655c1 148
e74abb32 149pub(crate) fn token_can_begin_expr(ident_token: &Token) -> bool {
041b39d2 150 !ident_token.is_reserved_ident() ||
32a655c1 151 ident_token.is_path_segment_keyword() ||
e74abb32
XL
152 match ident_token.kind {
153 TokenKind::Ident(ident, _) => [
154 kw::Async,
155 kw::Do,
156 kw::Box,
157 kw::Break,
158 kw::Continue,
159 kw::False,
160 kw::For,
161 kw::If,
162 kw::Let,
163 kw::Loop,
164 kw::Match,
165 kw::Move,
166 kw::Return,
167 kw::True,
168 kw::Unsafe,
169 kw::While,
170 kw::Yield,
171 kw::Static,
172 ].contains(&ident),
173 _=> false,
174 }
32a655c1
SL
175}
176
dc9dc135
XL
177fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool {
178 let ident_token = Token::new(Ident(name, is_raw), span);
cc61c64b 179
041b39d2 180 !ident_token.is_reserved_ident() ||
cc61c64b
XL
181 ident_token.is_path_segment_keyword() ||
182 [
dc9dc135
XL
183 kw::Underscore,
184 kw::For,
185 kw::Impl,
186 kw::Fn,
187 kw::Unsafe,
188 kw::Extern,
189 kw::Typeof,
190 kw::Dyn,
191 ].contains(&name)
cc61c64b
XL
192}
193
dc9dc135
XL
194#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
195pub enum TokenKind {
223e47cc 196 /* Expression-operator symbols. */
1a4d82fc
JJ
197 Eq,
198 Lt,
199 Le,
200 EqEq,
201 Ne,
202 Ge,
203 Gt,
204 AndAnd,
205 OrOr,
206 Not,
207 Tilde,
208 BinOp(BinOpToken),
209 BinOpEq(BinOpToken),
223e47cc
LB
210
211 /* Structural symbols */
1a4d82fc
JJ
212 At,
213 Dot,
214 DotDot,
215 DotDotDot,
ea8adc8c 216 DotDotEq,
1a4d82fc
JJ
217 Comma,
218 Semi,
219 Colon,
220 ModSep,
221 RArrow,
222 LArrow,
223 FatArrow,
224 Pound,
225 Dollar,
226 Question,
94b46f34
XL
227 /// Used by proc macros for representing lifetimes, not generated by lexer right now.
228 SingleQuote,
9fa01778 229 /// An opening delimiter (e.g., `{`).
1a4d82fc 230 OpenDelim(DelimToken),
9fa01778 231 /// A closing delimiter (e.g., `}`).
1a4d82fc 232 CloseDelim(DelimToken),
223e47cc
LB
233
234 /* Literals */
dc9dc135 235 Literal(Lit),
223e47cc
LB
236
237 /* Name components */
dc9dc135
XL
238 Ident(ast::Name, /* is_raw */ bool),
239 Lifetime(ast::Name),
223e47cc 240
9fa01778
XL
241 Interpolated(Lrc<Nonterminal>),
242
1a4d82fc 243 // Can be expanded into several tokens.
9fa01778 244 /// A doc comment.
1a4d82fc 245 DocComment(ast::Name),
1a4d82fc
JJ
246
247 // Junk. These carry no data because we don't really care about the data
248 // they *would* carry, and don't really want to allocate a new ident for
249 // them. Instead, users could extract that from the associated span.
250
9fa01778 251 /// Whitespace.
1a4d82fc 252 Whitespace,
9fa01778 253 /// A comment.
1a4d82fc
JJ
254 Comment,
255 Shebang(ast::Name),
416331ca
XL
256 /// A completely invalid token which should be skipped.
257 Unknown(ast::Name),
1a4d82fc
JJ
258
259 Eof,
260}
261
dc9dc135 262// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
0731742a 263#[cfg(target_arch = "x86_64")]
dc9dc135
XL
264static_assert_size!(TokenKind, 16);
265
266#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
267pub struct Token {
268 pub kind: TokenKind,
269 pub span: Span,
270}
271
272impl TokenKind {
273 pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
274 Literal(Lit::new(kind, symbol, suffix))
275 }
276
277 /// Returns tokens that are likely to be typed accidentally instead of the current token.
278 /// Enables better error recovery when the wrong token is found.
279 crate fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
280 match *self {
281 Comma => Some(vec![Dot, Lt, Semi]),
282 Semi => Some(vec![Colon, Comma]),
283 _ => None
284 }
285 }
286}
0731742a 287
1a4d82fc 288impl Token {
e74abb32 289 pub fn new(kind: TokenKind, span: Span) -> Self {
dc9dc135
XL
290 Token { kind, span }
291 }
292
293 /// Some token that will be thrown away later.
294 crate fn dummy() -> Self {
295 Token::new(TokenKind::Whitespace, DUMMY_SP)
296 }
297
0531ce1d 298 /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
e74abb32 299 pub fn from_ast_ident(ident: ast::Ident) -> Self {
dc9dc135
XL
300 Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
301 }
302
303 /// Return this token by value and leave a dummy token in its place.
e74abb32 304 pub fn take(&mut self) -> Self {
dc9dc135
XL
305 mem::replace(self, Token::dummy())
306 }
307
308 crate fn is_op(&self) -> bool {
309 match self.kind {
310 OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
311 Ident(..) | Lifetime(..) | Interpolated(..) |
312 Whitespace | Comment | Shebang(..) | Eof => false,
313 _ => true,
314 }
041b39d2
XL
315 }
316
94b46f34 317 crate fn is_like_plus(&self) -> bool {
dc9dc135 318 match self.kind {
94b46f34 319 BinOp(Plus) | BinOpEq(Plus) => true,
bd371182
AL
320 _ => false,
321 }
322 }
323
1a4d82fc 324 /// Returns `true` if the token can appear at the start of an expression.
e74abb32 325 pub fn can_begin_expr(&self) -> bool {
dc9dc135
XL
326 match self.kind {
327 Ident(name, is_raw) =>
328 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
ea8adc8c
XL
329 OpenDelim(..) | // tuple, array or block
330 Literal(..) | // literal
331 Not | // operator not
332 BinOp(Minus) | // unary minus
333 BinOp(Star) | // dereference
334 BinOp(Or) | OrOr | // closure
335 BinOp(And) | // reference
336 AndAnd | // double reference
abe05a73 337 // DotDotDot is no longer supported, but we need some way to display the error
ea8adc8c 338 DotDot | DotDotDot | DotDotEq | // range notation
ea8adc8c
XL
339 Lt | BinOp(Shl) | // associated path
340 ModSep | // global path
83c7162d 341 Lifetime(..) | // labeled loop
ea8adc8c 342 Pound => true, // expression attributes
9fa01778 343 Interpolated(ref nt) => match **nt {
94b46f34
XL
344 NtLiteral(..) |
345 NtIdent(..) |
346 NtExpr(..) |
347 NtBlock(..) |
348 NtPath(..) |
349 NtLifetime(..) => true,
c30ab7b3
SL
350 _ => false,
351 },
352 _ => false,
1a4d82fc
JJ
353 }
354 }
223e47cc 355
32a655c1 356 /// Returns `true` if the token can appear at the start of a type.
e74abb32 357 pub fn can_begin_type(&self) -> bool {
dc9dc135
XL
358 match self.kind {
359 Ident(name, is_raw) =>
360 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
7cac9316
XL
361 OpenDelim(Paren) | // tuple
362 OpenDelim(Bracket) | // array
7cac9316
XL
363 Not | // never
364 BinOp(Star) | // raw pointer
365 BinOp(And) | // reference
366 AndAnd | // double reference
367 Question | // maybe bound in trait object
368 Lifetime(..) | // lifetime bound in trait object
369 Lt | BinOp(Shl) | // associated path
32a655c1 370 ModSep => true, // global path
9fa01778 371 Interpolated(ref nt) => match **nt {
ff7c6d11 372 NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true,
32a655c1
SL
373 _ => false,
374 },
375 _ => false,
376 }
377 }
378
9fa01778 379 /// Returns `true` if the token can appear at the start of a const param.
dc9dc135
XL
380 crate fn can_begin_const_arg(&self) -> bool {
381 match self.kind {
9fa01778
XL
382 OpenDelim(Brace) => true,
383 Interpolated(ref nt) => match **nt {
384 NtExpr(..) => true,
385 NtBlock(..) => true,
386 NtLiteral(..) => true,
387 _ => false,
388 }
389 _ => self.can_begin_literal_or_bool(),
390 }
391 }
392
abe05a73 393 /// Returns `true` if the token can appear at the start of a generic bound.
94b46f34 394 crate fn can_begin_bound(&self) -> bool {
dc9dc135 395 self.is_path_start() || self.is_lifetime() || self.is_keyword(kw::For) ||
abe05a73
XL
396 self == &Question || self == &OpenDelim(Paren)
397 }
398
1a4d82fc 399 /// Returns `true` if the token is any literal
e74abb32 400 pub fn is_lit(&self) -> bool {
dc9dc135 401 match self.kind {
9e0c209e
SL
402 Literal(..) => true,
403 _ => false,
1a4d82fc
JJ
404 }
405 }
223e47cc 406
dc9dc135
XL
407 crate fn expect_lit(&self) -> Lit {
408 match self.kind {
409 Literal(lit) => lit,
e1599b0c 410 _ => panic!("`expect_lit` called on non-literal"),
dc9dc135
XL
411 }
412 }
413
9fa01778 414 /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
94b46f34 415 /// for example a '-42', or one of the boolean idents).
e74abb32 416 pub fn can_begin_literal_or_bool(&self) -> bool {
dc9dc135 417 match self.kind {
e1599b0c
XL
418 Literal(..) | BinOp(Minus) => true,
419 Ident(name, false) if name.is_bool_lit() => true,
9fa01778 420 Interpolated(ref nt) => match **nt {
b7449926
XL
421 NtLiteral(..) => true,
422 _ => false,
423 },
94b46f34
XL
424 _ => false,
425 }
426 }
427
83c7162d
XL
428 /// Returns an identifier if this token is an identifier.
429 pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
dc9dc135
XL
430 match self.kind {
431 Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
9fa01778 432 Interpolated(ref nt) => match **nt {
83c7162d
XL
433 NtIdent(ident, is_raw) => Some((ident, is_raw)),
434 _ => None,
435 },
436 _ => None,
437 }
438 }
dc9dc135 439
83c7162d
XL
440 /// Returns a lifetime identifier if this token is a lifetime.
441 pub fn lifetime(&self) -> Option<ast::Ident> {
dc9dc135
XL
442 match self.kind {
443 Lifetime(name) => Some(ast::Ident::new(name, self.span)),
9fa01778 444 Interpolated(ref nt) => match **nt {
83c7162d 445 NtLifetime(ident) => Some(ident),
cc61c64b
XL
446 _ => None,
447 },
448 _ => None,
223e47cc 449 }
1a4d82fc 450 }
dc9dc135 451
cc61c64b
XL
452 /// Returns `true` if the token is an identifier.
453 pub fn is_ident(&self) -> bool {
454 self.ident().is_some()
455 }
e1599b0c 456
83c7162d 457 /// Returns `true` if the token is a lifetime.
94b46f34 458 crate fn is_lifetime(&self) -> bool {
83c7162d
XL
459 self.lifetime().is_some()
460 }
461
462 /// Returns `true` if the token is a identifier whose name is the given
463 /// string slice.
dc9dc135
XL
464 crate fn is_ident_named(&self, name: Symbol) -> bool {
465 self.ident().map_or(false, |(ident, _)| ident.name == name)
83c7162d 466 }
cc61c64b 467
1a4d82fc 468 /// Returns `true` if the token is an interpolated path.
94b46f34 469 fn is_path(&self) -> bool {
dc9dc135 470 if let Interpolated(ref nt) = self.kind {
9fa01778 471 if let NtPath(..) = **nt {
c30ab7b3
SL
472 return true;
473 }
1a4d82fc 474 }
c30ab7b3 475 false
1a4d82fc
JJ
476 }
477
416331ca
XL
478 /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
479 /// That is, is this a pre-parsed expression dropped into the token stream
480 /// (which happens while parsing the result of macro expansion)?
481 crate fn is_whole_expr(&self) -> bool {
482 if let Interpolated(ref nt) = self.kind {
483 if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt {
484 return true;
485 }
486 }
487
488 false
489 }
490
1a4d82fc 491 /// Returns `true` if the token is either the `mut` or `const` keyword.
94b46f34 492 crate fn is_mutability(&self) -> bool {
dc9dc135
XL
493 self.is_keyword(kw::Mut) ||
494 self.is_keyword(kw::Const)
1a4d82fc
JJ
495 }
496
94b46f34 497 crate fn is_qpath_start(&self) -> bool {
c30ab7b3
SL
498 self == &Lt || self == &BinOp(Shl)
499 }
500
94b46f34 501 crate fn is_path_start(&self) -> bool {
c30ab7b3 502 self == &ModSep || self.is_qpath_start() || self.is_path() ||
041b39d2 503 self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident()
a7813a04
XL
504 }
505
1a4d82fc 506 /// Returns `true` if the token is a given keyword, `kw`.
dc9dc135 507 pub fn is_keyword(&self, kw: Symbol) -> bool {
e1599b0c 508 self.is_non_raw_ident_where(|id| id.name == kw)
1a4d82fc
JJ
509 }
510
dc9dc135 511 crate fn is_path_segment_keyword(&self) -> bool {
e1599b0c 512 self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword)
1a4d82fc
JJ
513 }
514
041b39d2
XL
515 // Returns true for reserved identifiers used internally for elided lifetimes,
516 // unnamed method parameters, crate root module, error recovery etc.
dc9dc135 517 crate fn is_special_ident(&self) -> bool {
e1599b0c 518 self.is_non_raw_ident_where(ast::Ident::is_special)
1a4d82fc
JJ
519 }
520
041b39d2 521 /// Returns `true` if the token is a keyword used in the language.
94b46f34 522 crate fn is_used_keyword(&self) -> bool {
e1599b0c 523 self.is_non_raw_ident_where(ast::Ident::is_used_keyword)
1a4d82fc
JJ
524 }
525
a7813a04 526 /// Returns `true` if the token is a keyword reserved for possible future use.
94b46f34 527 crate fn is_unused_keyword(&self) -> bool {
e1599b0c 528 self.is_non_raw_ident_where(ast::Ident::is_unused_keyword)
1a4d82fc 529 }
041b39d2 530
83c7162d
XL
531 /// Returns `true` if the token is either a special identifier or a keyword.
532 pub fn is_reserved_ident(&self) -> bool {
e1599b0c
XL
533 self.is_non_raw_ident_where(ast::Ident::is_reserved)
534 }
535
536 /// Returns `true` if the token is the identifier `true` or `false`.
537 crate fn is_bool_lit(&self) -> bool {
538 self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
539 }
540
541 /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
542 fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool {
83c7162d 543 match self.ident() {
e1599b0c 544 Some((id, false)) => pred(id),
83c7162d
XL
545 _ => false,
546 }
547 }
548
e1599b0c 549 crate fn glue(&self, joint: &Token) -> Option<Token> {
dc9dc135
XL
550 let kind = match self.kind {
551 Eq => match joint.kind {
041b39d2
XL
552 Eq => EqEq,
553 Gt => FatArrow,
554 _ => return None,
555 },
dc9dc135 556 Lt => match joint.kind {
041b39d2
XL
557 Eq => Le,
558 Lt => BinOp(Shl),
559 Le => BinOpEq(Shl),
560 BinOp(Minus) => LArrow,
561 _ => return None,
562 },
dc9dc135 563 Gt => match joint.kind {
041b39d2
XL
564 Eq => Ge,
565 Gt => BinOp(Shr),
566 Ge => BinOpEq(Shr),
567 _ => return None,
568 },
dc9dc135 569 Not => match joint.kind {
041b39d2
XL
570 Eq => Ne,
571 _ => return None,
572 },
dc9dc135 573 BinOp(op) => match joint.kind {
041b39d2
XL
574 Eq => BinOpEq(op),
575 BinOp(And) if op == And => AndAnd,
576 BinOp(Or) if op == Or => OrOr,
577 Gt if op == Minus => RArrow,
578 _ => return None,
579 },
dc9dc135 580 Dot => match joint.kind {
041b39d2
XL
581 Dot => DotDot,
582 DotDot => DotDotDot,
583 _ => return None,
584 },
dc9dc135 585 DotDot => match joint.kind {
041b39d2 586 Dot => DotDotDot,
ea8adc8c 587 Eq => DotDotEq,
041b39d2
XL
588 _ => return None,
589 },
dc9dc135 590 Colon => match joint.kind {
041b39d2
XL
591 Colon => ModSep,
592 _ => return None,
593 },
dc9dc135
XL
594 SingleQuote => match joint.kind {
595 Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
94b46f34
XL
596 _ => return None,
597 },
041b39d2 598
a1dfa0c6 599 Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
ea8adc8c 600 DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
9fa01778 601 Question | OpenDelim(..) | CloseDelim(..) |
041b39d2 602 Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
416331ca 603 Whitespace | Comment | Shebang(..) | Unknown(..) | Eof => return None,
dc9dc135 604 };
041b39d2 605
dc9dc135 606 Some(Token::new(kind, self.span.to(joint.span)))
abe05a73
XL
607 }
608
9fa01778 609 // See comments in `Nonterminal::to_tokenstream` for why we care about
83c7162d 610 // *probably* equal here rather than actual equality
94b46f34 611 crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
dc9dc135 612 if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
83c7162d
XL
613 return false
614 }
dc9dc135 615 match (&self.kind, &other.kind) {
83c7162d
XL
616 (&Eq, &Eq) |
617 (&Lt, &Lt) |
618 (&Le, &Le) |
619 (&EqEq, &EqEq) |
620 (&Ne, &Ne) |
621 (&Ge, &Ge) |
622 (&Gt, &Gt) |
623 (&AndAnd, &AndAnd) |
624 (&OrOr, &OrOr) |
625 (&Not, &Not) |
626 (&Tilde, &Tilde) |
627 (&At, &At) |
628 (&Dot, &Dot) |
629 (&DotDot, &DotDot) |
630 (&DotDotDot, &DotDotDot) |
631 (&DotDotEq, &DotDotEq) |
83c7162d
XL
632 (&Comma, &Comma) |
633 (&Semi, &Semi) |
634 (&Colon, &Colon) |
635 (&ModSep, &ModSep) |
636 (&RArrow, &RArrow) |
637 (&LArrow, &LArrow) |
638 (&FatArrow, &FatArrow) |
639 (&Pound, &Pound) |
640 (&Dollar, &Dollar) |
641 (&Question, &Question) |
642 (&Whitespace, &Whitespace) |
643 (&Comment, &Comment) |
644 (&Eof, &Eof) => true,
645
646 (&BinOp(a), &BinOp(b)) |
647 (&BinOpEq(a), &BinOpEq(b)) => a == b,
648
649 (&OpenDelim(a), &OpenDelim(b)) |
650 (&CloseDelim(a), &CloseDelim(b)) => a == b,
651
652 (&DocComment(a), &DocComment(b)) |
653 (&Shebang(a), &Shebang(b)) => a == b,
654
dc9dc135 655 (&Literal(a), &Literal(b)) => a == b,
83c7162d 656
dc9dc135
XL
657 (&Lifetime(a), &Lifetime(b)) => a == b,
658 (&Ident(a, b), &Ident(c, d)) => b == d && (a == c ||
659 a == kw::DollarCrate ||
660 c == kw::DollarCrate),
83c7162d
XL
661
662 (&Interpolated(_), &Interpolated(_)) => false,
663
664 _ => panic!("forgot to add a token?"),
665 }
ea8adc8c 666 }
223e47cc
LB
667}
668
dc9dc135
XL
669impl PartialEq<TokenKind> for Token {
670 fn eq(&self, rhs: &TokenKind) -> bool {
671 self.kind == *rhs
672 }
673}
674
8faf50e0 675#[derive(Clone, RustcEncodable, RustcDecodable)]
1a4d82fc
JJ
676/// For interpolation during macro expansion.
677pub enum Nonterminal {
678 NtItem(P<ast::Item>),
679 NtBlock(P<ast::Block>),
c30ab7b3 680 NtStmt(ast::Stmt),
1a4d82fc
JJ
681 NtPat(P<ast::Pat>),
682 NtExpr(P<ast::Expr>),
683 NtTy(P<ast::Ty>),
83c7162d
XL
684 NtIdent(ast::Ident, /* is_raw */ bool),
685 NtLifetime(ast::Ident),
94b46f34 686 NtLiteral(P<ast::Expr>),
1a4d82fc 687 /// Stuff inside brackets for attributes
e74abb32 688 NtMeta(ast::AttrItem),
c30ab7b3 689 NtPath(ast::Path),
cc61c64b
XL
690 NtVis(ast::Visibility),
691 NtTT(TokenTree),
48663c56
XL
692 // Used only for passing items to proc macro attributes (they are not
693 // strictly necessary for that, `Annotatable` can be converted into
694 // tokens directly, but doing that naively regresses pretty-printing).
c30ab7b3 695 NtTraitItem(ast::TraitItem),
48663c56 696 NtImplItem(ast::ImplItem),
83c7162d 697 NtForeignItem(ast::ForeignItem),
83c7162d
XL
698}
699
700impl PartialEq for Nonterminal {
701 fn eq(&self, rhs: &Self) -> bool {
702 match (self, rhs) {
703 (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) =>
704 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs,
705 (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
706 (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
707 // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
708 // correctly based on data from AST. This will prevent them from matching each other
709 // in macros. The comparison will become possible only when each nonterminal has an
710 // attached token stream from which it was parsed.
711 _ => false,
712 }
713 }
1a4d82fc
JJ
714}
715
85aaf69f 716impl fmt::Debug for Nonterminal {
9fa01778 717 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1a4d82fc
JJ
718 match *self {
719 NtItem(..) => f.pad("NtItem(..)"),
720 NtBlock(..) => f.pad("NtBlock(..)"),
721 NtStmt(..) => f.pad("NtStmt(..)"),
722 NtPat(..) => f.pad("NtPat(..)"),
723 NtExpr(..) => f.pad("NtExpr(..)"),
724 NtTy(..) => f.pad("NtTy(..)"),
725 NtIdent(..) => f.pad("NtIdent(..)"),
94b46f34 726 NtLiteral(..) => f.pad("NtLiteral(..)"),
1a4d82fc
JJ
727 NtMeta(..) => f.pad("NtMeta(..)"),
728 NtPath(..) => f.pad("NtPath(..)"),
729 NtTT(..) => f.pad("NtTT(..)"),
d9579d0f
AL
730 NtImplItem(..) => f.pad("NtImplItem(..)"),
731 NtTraitItem(..) => f.pad("NtTraitItem(..)"),
83c7162d 732 NtForeignItem(..) => f.pad("NtForeignItem(..)"),
cc61c64b 733 NtVis(..) => f.pad("NtVis(..)"),
ff7c6d11 734 NtLifetime(..) => f.pad("NtLifetime(..)"),
1a4d82fc 735 }
970d7e83
LB
736 }
737}