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