LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-ast-collector.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 59.1 % 2247 1327
Test Date: 2026-04-20 14:57:17 Functions: 69.7 % 370 258
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-ast-collector.h"
      20              : #include "rust-ast.h"
      21              : #include "rust-builtin-ast-nodes.h"
      22              : #include "rust-diagnostics.h"
      23              : #include "rust-expr.h"
      24              : #include "rust-item.h"
      25              : #include "rust-keyword-values.h"
      26              : #include "rust-path.h"
      27              : #include "rust-system.h"
      28              : #include "rust-token.h"
      29              : 
      30              : namespace Rust {
      31              : namespace AST {
      32              : 
      33              : std::vector<TokenPtr>
      34            0 : TokenCollector::collect_tokens () const
      35              : {
      36            0 :   std::vector<TokenPtr> result;
      37            0 :   for (auto item : tokens)
      38              :     {
      39            0 :       if (item.get_kind () == CollectItem::Kind::Token)
      40              :         {
      41            0 :           result.emplace_back (item.get_token ());
      42              :         }
      43            0 :     }
      44            0 :   return result;
      45              : }
      46              : 
      47              : std::vector<CollectItem>
      48         2768 : TokenCollector::collect () const
      49              : {
      50         2768 :   return tokens;
      51              : }
      52              : 
      53              : void
      54            0 : TokenCollector::visit (AST::Crate &crate)
      55              : {
      56            0 :   visit_items_as_lines (crate.inner_attrs);
      57            0 :   visit_items_as_lines (crate.items);
      58            0 : }
      59              : 
      60              : void
      61         2768 : TokenCollector::visit (AST::Item &item)
      62              : {
      63         2768 :   item.accept_vis (*this);
      64         2768 : }
      65              : 
      66              : void
      67          390 : TokenCollector::trailing_comma ()
      68              : {
      69          390 :   if (output_trailing_commas)
      70              :     {
      71            0 :       push (Rust::Token::make (COMMA, UNDEF_LOCATION));
      72              :     }
      73          390 : }
      74              : 
      75              : void
      76        16709 : TokenCollector::newline ()
      77              : {
      78        16709 :   tokens.emplace_back (CollectItem::Kind::Newline);
      79        16709 : }
      80              : 
      81              : void
      82        11059 : TokenCollector::indentation ()
      83              : {
      84        11059 :   tokens.emplace_back (indent_level);
      85        11059 : }
      86              : 
      87              : void
      88         2909 : TokenCollector::increment_indentation ()
      89              : {
      90         2909 :   indent_level++;
      91         2909 : }
      92              : 
      93              : void
      94         2909 : TokenCollector::decrement_indentation ()
      95              : {
      96         2909 :   rust_assert (indent_level != 0);
      97         2909 :   indent_level--;
      98         2909 : }
      99              : 
     100              : void
     101            0 : TokenCollector::comment (std::string comment)
     102              : {
     103            0 :   tokens.emplace_back (CollectItem::make_comment (comment));
     104            0 : }
     105              : 
     106              : void
     107        53115 : TokenCollector::describe_node (const std::string &node_name,
     108              :                                std::function<void ()> visitor)
     109              : {
     110        53115 :   tokens.emplace_back (CollectItem::make_begin_node_description (node_name));
     111              : 
     112        53115 :   visitor ();
     113              : 
     114        53115 :   tokens.push_back (CollectItem::make_end_node_description (node_name));
     115        53115 : }
     116              : 
     117              : void
     118            0 : TokenCollector::visit (Visitable &v)
     119              : {
     120            0 :   v.accept_vis (*this);
     121            0 : }
     122              : 
     123              : void
     124          634 : TokenCollector::visit (FunctionParam &param)
     125              : {
     126          634 :   describe_node (std::string ("FunctionParam"), [this, &param] () {
     127          634 :     visit_items_as_lines (param.get_outer_attrs ());
     128          634 :     if (!param.is_variadic ())
     129              :       {
     130          634 :         visit (param.get_pattern ());
     131          634 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
     132          634 :         visit (param.get_type ());
     133              :       }
     134              :     else
     135              :       {
     136            0 :         if (param.has_name ())
     137              :           {
     138            0 :             visit (param.get_pattern ());
     139            0 :             push (Rust::Token::make (COLON, UNDEF_LOCATION));
     140              :           }
     141            0 :         push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
     142              :       }
     143          634 :   });
     144          634 : }
     145              : 
     146              : void
     147            0 : TokenCollector::visit (VariadicParam &param)
     148              : {
     149            0 :   describe_node (std::string ("VariadicParam"), [this, &param] () {
     150            0 :     if (param.has_pattern ())
     151              :       {
     152            0 :         visit (param.get_pattern ());
     153            0 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
     154              :       }
     155            0 :     push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
     156            0 :   });
     157            0 : }
     158              : 
     159              : void
     160         2226 : TokenCollector::visit (Attribute &attrib)
     161              : {
     162         2226 :   describe_node (std::string ("Attribute"), [this, &attrib] () {
     163         2226 :     push (Rust::Token::make (HASH, attrib.get_locus ()));
     164         2226 :     if (attrib.is_inner_attribute ())
     165            0 :       push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
     166         2226 :     push (Rust::Token::make (LEFT_SQUARE, UNDEF_LOCATION));
     167         2226 :     visit (attrib.get_path ());
     168              : 
     169         2226 :     if (attrib.has_attr_input ())
     170              :       {
     171         2168 :         switch (attrib.get_attr_input ().get_attr_input_type ())
     172              :           {
     173         2072 :           case AST::AttrInput::AttrInputType::LITERAL:
     174         2072 :             {
     175         2072 :               visit (
     176         2072 :                 static_cast<AttrInputLiteral &> (attrib.get_attr_input ()));
     177         2072 :               break;
     178              :             }
     179            0 :           case AST::AttrInput::AttrInputType::EXPR:
     180            0 :             {
     181            0 :               visit (static_cast<AttrInputExpr &> (attrib.get_attr_input ()));
     182            0 :               break;
     183              :             }
     184            2 :           case AST::AttrInput::AttrInputType::META_ITEM:
     185            2 :             {
     186            2 :               visit (static_cast<AttrInputMetaItemContainer &> (
     187            2 :                 attrib.get_attr_input ()));
     188            2 :               break;
     189              :             }
     190           94 :           case AST::AttrInput::AttrInputType::TOKEN_TREE:
     191           94 :             {
     192           94 :               visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ()));
     193           94 :               break;
     194              :             }
     195            0 :           default:
     196            0 :             rust_unreachable ();
     197              :           }
     198              :       }
     199         2226 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
     200         2226 :   });
     201         2226 : }
     202              : 
     203              : void
     204         2228 : TokenCollector::visit (SimplePath &path)
     205              : {
     206         2228 :   describe_node (std::string ("SimplePath"), [this, &path] () {
     207         2228 :     if (path.has_opening_scope_resolution ())
     208              :       {
     209            0 :         push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
     210              :       }
     211         2228 :     visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
     212         2228 :   });
     213         2228 : }
     214              : 
     215              : void
     216         2228 : TokenCollector::visit (SimplePathSegment &segment)
     217              : {
     218         2228 :   describe_node (std::string ("SimplePathSegment"), [this, &segment] () {
     219         2228 :     auto name = segment.get_segment_name ();
     220         2228 :     if (segment.is_crate_path_seg ())
     221              :       {
     222            0 :         push (Rust::Token::make (CRATE, segment.get_locus ()));
     223              :       }
     224         2228 :     else if (segment.is_super_path_seg ())
     225              :       {
     226            0 :         push (Rust::Token::make (SUPER, segment.get_locus ()));
     227              :       }
     228         2228 :     else if (segment.is_lower_self_seg ())
     229              :       {
     230            0 :         push (Rust::Token::make (SELF, segment.get_locus ()));
     231              :       }
     232         2228 :     else if (segment.is_big_self ())
     233              :       {
     234            0 :         push (Rust::Token::make (SELF_ALIAS, segment.get_locus ()));
     235              :       }
     236              :     else
     237              :       {
     238         4456 :         push (Rust::Token::make_identifier (segment.get_locus (),
     239              :                                             std::move (name)));
     240              :       }
     241         2228 :   });
     242         2228 : }
     243              : 
     244              : void
     245         3688 : TokenCollector::visit (Visibility &vis)
     246              : {
     247         3688 :   describe_node (std::string ("Visibility"), [this, &vis] () {
     248         3688 :     switch (vis.get_vis_type ())
     249              :       {
     250         2766 :       case Visibility::PUB:
     251         2766 :         push (Rust::Token::make (PUB, vis.get_locus ()));
     252         2766 :         break;
     253            0 :       case Visibility::PUB_CRATE:
     254            0 :         push (Rust::Token::make (PUB, vis.get_locus ()));
     255            0 :         push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
     256            0 :         push (Rust::Token::make (CRATE, UNDEF_LOCATION));
     257            0 :         push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
     258            0 :         break;
     259            0 :       case Visibility::PUB_SELF:
     260            0 :         push (Rust::Token::make (PUB, vis.get_locus ()));
     261            0 :         push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
     262            0 :         push (Rust::Token::make (SELF, UNDEF_LOCATION));
     263            0 :         push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
     264            0 :         break;
     265            0 :       case Visibility::PUB_SUPER:
     266            0 :         push (Rust::Token::make (PUB, vis.get_locus ()));
     267            0 :         push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
     268            0 :         push (Rust::Token::make (SUPER, UNDEF_LOCATION));
     269            0 :         push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
     270            0 :         break;
     271            0 :       case Visibility::PUB_IN_PATH:
     272            0 :         push (Rust::Token::make (PUB, vis.get_locus ()));
     273            0 :         push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
     274            0 :         push (Rust::Token::make (IN, UNDEF_LOCATION));
     275            0 :         visit (vis.get_path ());
     276            0 :         push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
     277            0 :         break;
     278              :       case Visibility::PRIV:
     279              :         break;
     280              :       }
     281         3688 :   });
     282         3688 : }
     283              : 
     284              : void
     285          388 : TokenCollector::visit (std::vector<std::unique_ptr<GenericParam>> &params)
     286              : {
     287          388 :   describe_node (std::string ("GenericParam"), [this, &params] () {
     288          388 :     push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION));
     289          388 :     visit_items_joined_by_separator (params, COMMA);
     290          388 :     push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION));
     291          388 :   });
     292          388 : }
     293              : 
     294              : void
     295          101 : TokenCollector::visit (TupleField &field)
     296              : {
     297          101 :   describe_node (std::string ("TupleField"), [this, &field] () {
     298          101 :     for (auto attr : field.get_outer_attrs ())
     299              :       {
     300            0 :         visit (attr);
     301            0 :       }
     302          101 :     visit (field.get_visibility ());
     303          101 :     visit (field.get_field_type ());
     304          101 :   });
     305          101 : }
     306              : 
     307              : void
     308           14 : TokenCollector::visit (StructField &field)
     309              : {
     310           14 :   describe_node (std::string ("StructField"), [this, &field] () {
     311           14 :     for (auto attr : field.get_outer_attrs ())
     312              :       {
     313            0 :         visit (attr);
     314            0 :       }
     315           14 :     visit (field.get_visibility ());
     316           28 :     auto name = field.get_field_name ().as_string ();
     317           28 :     push (Rust::Token::make_identifier (field.get_locus (), std::move (name)));
     318           14 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
     319           14 :     visit (field.get_field_type ());
     320           14 :   });
     321           14 : }
     322              : 
     323              : void
     324            0 : TokenCollector::visit (std::vector<LifetimeParam> &for_lifetimes)
     325              : {
     326            0 :   describe_node (std::string ("LifetimeParam"), [this, &for_lifetimes] () {
     327            0 :     push (Rust::Token::make (FOR, UNDEF_LOCATION));
     328            0 :     push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION));
     329            0 :     visit_items_joined_by_separator (for_lifetimes, COMMA);
     330            0 :     push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION));
     331            0 :   });
     332            0 : }
     333              : 
     334              : void
     335         1518 : TokenCollector::visit (FunctionQualifiers &qualifiers)
     336              : {
     337              :   // Syntax:
     338              :   //    `const`? `async`? `unsafe`? (`extern` Abi?)?
     339              :   //    unsafe? (extern Abi?)?
     340         1518 :   describe_node (std::string ("FunctionQualifiers"), [this, &qualifiers] () {
     341         1518 :     if (qualifiers.is_async ())
     342            2 :       push (Rust::Token::make (ASYNC, qualifiers.get_locus ()));
     343         1518 :     if (qualifiers.is_const ())
     344            2 :       push (Rust::Token::make (CONST, qualifiers.get_locus ()));
     345         1518 :     if (qualifiers.is_unsafe ())
     346           86 :       push (Rust::Token::make (UNSAFE, qualifiers.get_locus ()));
     347         1518 :     if (qualifiers.is_extern ())
     348              :       {
     349           58 :         push (Rust::Token::make (EXTERN_KW, qualifiers.get_locus ()));
     350           58 :         if (qualifiers.has_abi ())
     351              :           {
     352          116 :             push (Rust::Token::make_string (UNDEF_LOCATION,
     353          174 :                                             qualifiers.get_extern_abi ()));
     354              :           }
     355              :       }
     356         1518 :   });
     357         1518 : }
     358              : 
     359              : void
     360            0 : TokenCollector::visit (MaybeNamedParam &param)
     361              : {
     362              :   // Syntax:
     363              :   //     OuterAttribute* ( ( IDENTIFIER | _ ) : )? Type
     364              : 
     365            0 :   describe_node (std::string ("MaybeNamedParam"), [this, &param] () {
     366            0 :     for (auto attr : param.get_outer_attrs ())
     367              :       {
     368            0 :         visit (attr);
     369            0 :       }
     370            0 :     auto param_name = param.get_name ().as_string ();
     371            0 :     switch (param.get_param_kind ())
     372              :       {
     373              :       case MaybeNamedParam::UNNAMED:
     374              :         break;
     375            0 :       case MaybeNamedParam::IDENTIFIER:
     376            0 :         push (Rust::Token::make_identifier (UNDEF_LOCATION,
     377              :                                             std::move (param_name)));
     378            0 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
     379            0 :         break;
     380            0 :       case MaybeNamedParam::WILDCARD:
     381            0 :         push (Rust::Token::make (UNDERSCORE, UNDEF_LOCATION));
     382            0 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
     383            0 :         break;
     384              :       }
     385            0 :     visit (param.get_type ());
     386            0 :   });
     387            0 : }
     388              : 
     389              : void
     390          854 : TokenCollector::visit (Token &tok)
     391              : {
     392          854 :   std::string data
     393         1602 :     = tok.get_tok_ptr ()->should_have_str () ? tok.get_str () : "";
     394          854 :   switch (tok.get_id ())
     395              :     {
     396          189 :     case IDENTIFIER:
     397          378 :       push (Rust::Token::make_identifier (tok.get_locus (), std::move (data)));
     398          189 :       break;
     399            1 :     case INT_LITERAL:
     400            2 :       push (Rust::Token::make_int (tok.get_locus (), std::move (data),
     401              :                                    tok.get_type_hint ()));
     402            1 :       break;
     403            0 :     case FLOAT_LITERAL:
     404            0 :       push (Rust::Token::make_float (tok.get_locus (), std::move (data),
     405              :                                      tok.get_type_hint ()));
     406            0 :       break;
     407          184 :     case STRING_LITERAL:
     408          368 :       push (Rust::Token::make_string (tok.get_locus (), std::move (data)));
     409          184 :       break;
     410            0 :     case CHAR_LITERAL:
     411            0 :       push (Rust::Token::make_char (
     412              :         tok.get_locus (),
     413              :         // FIXME: This need to be fixed to properly support UTF-8
     414            0 :         static_cast<uint32_t> (data[0])));
     415            0 :       break;
     416            0 :     case BYTE_CHAR_LITERAL:
     417            0 :       push (Rust::Token::make_byte_char (tok.get_locus (), data[0]));
     418            0 :       break;
     419            0 :     case BYTE_STRING_LITERAL:
     420            0 :       push (Rust::Token::make_byte_string (tok.get_locus (), std::move (data)));
     421            0 :       break;
     422            0 :     case RAW_STRING_LITERAL:
     423            0 :       push (Rust::Token::make_raw_string (tok.get_locus (), std::move (data)));
     424            0 :       break;
     425            0 :     case INNER_DOC_COMMENT:
     426            0 :       push (Rust::Token::make_inner_doc_comment (tok.get_locus (),
     427              :                                                  std::move (data)));
     428            0 :       break;
     429            0 :     case OUTER_DOC_COMMENT:
     430            0 :       push (Rust::Token::make_outer_doc_comment (tok.get_locus (),
     431              :                                                  std::move (data)));
     432            0 :       break;
     433            0 :     case LIFETIME:
     434            0 :       push (Rust::Token::make_lifetime (tok.get_locus (), std::move (data)));
     435            0 :       break;
     436          480 :     default:
     437          960 :       push (Rust::Token::make (tok.get_id (), tok.get_locus ()));
     438              :     }
     439          854 : }
     440              : 
     441              : void
     442           99 : TokenCollector::visit (DelimTokenTree &delim_tok_tree)
     443              : {
     444           99 :   describe_node (std::string ("DelimTokenTree"), [this, &delim_tok_tree] () {
     445          952 :     for (auto &token : delim_tok_tree.to_token_stream ())
     446              :       {
     447          853 :         visit (token);
     448           99 :       }
     449           99 :   });
     450           99 : }
     451              : 
     452              : void
     453            2 : TokenCollector::visit (AttrInputMetaItemContainer &container)
     454              : {
     455            2 :   describe_node (std::string ("AttrInputMetaItemContainer"),
     456            2 :                  [this, &container] () {
     457            4 :                    for (auto &item : container.get_items ())
     458              :                      {
     459            2 :                        visit (item);
     460              :                      }
     461            2 :                  });
     462            2 : }
     463              : 
     464              : void
     465         1956 : TokenCollector::visit (IdentifierExpr &ident_expr)
     466              : {
     467         1956 :   describe_node (std::string ("IdentifierExpr"), [this, &ident_expr] () {
     468         3912 :     auto ident = ident_expr.get_ident ().as_string ();
     469         3912 :     push (Rust::Token::make_identifier (ident_expr.get_locus (),
     470              :                                         std::move (ident)));
     471         1956 :   });
     472         1956 : }
     473              : 
     474              : void
     475         1097 : TokenCollector::visit (Lifetime &lifetime)
     476              : {
     477              :   // Syntax:
     478              :   // Lifetime :
     479              :   //    LIFETIME_OR_LABEL
     480              :   //    | 'static
     481              :   //    | '_
     482              : 
     483         1097 :   describe_node (std::string ("Lifetime"), [this, &lifetime] () {
     484         1097 :     auto name = lifetime.get_lifetime_name ();
     485         1097 :     switch (lifetime.get_lifetime_type ())
     486              :       {
     487           50 :       case Lifetime::LifetimeType::NAMED:
     488           50 :         push (
     489          100 :           Rust::Token::make_lifetime (lifetime.get_locus (), std::move (name)));
     490           50 :         break;
     491            1 :       case Lifetime::LifetimeType::STATIC:
     492            2 :         push (Rust::Token::make_lifetime (lifetime.get_locus (),
     493            1 :                                           Values::Keywords::STATIC_KW));
     494            1 :         break;
     495         1046 :       case Lifetime::LifetimeType::WILDCARD:
     496         2092 :         push (Rust::Token::make_lifetime (lifetime.get_locus (),
     497         1046 :                                           Values::Keywords::UNDERSCORE));
     498         1046 :         break;
     499              :       }
     500         1097 :   });
     501         1097 : }
     502              : 
     503              : void
     504           21 : TokenCollector::visit (LifetimeParam &lifetime_param)
     505              : {
     506              :   // Syntax:
     507              :   //   LIFETIME_OR_LABEL ( : LifetimeBounds )?
     508              :   // LifetimeBounds :
     509              :   //   ( Lifetime + )* Lifetime?
     510              : 
     511              :   // TODO what to do with outer attr? They are not mentioned in the reference.
     512           21 :   describe_node (std::string ("LifetimeParam"), [this, &lifetime_param] () {
     513           21 :     visit_items_as_lines (lifetime_param.get_outer_attrs ());
     514           21 :     auto lifetime = lifetime_param.get_lifetime ();
     515           21 :     visit (lifetime);
     516              : 
     517           21 :     if (lifetime_param.has_lifetime_bounds ())
     518              :       {
     519            0 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
     520            0 :         for (auto &bound : lifetime_param.get_lifetime_bounds ())
     521              :           {
     522            0 :             visit (bound);
     523              :           }
     524              :       }
     525           21 :   });
     526           21 : }
     527              : 
     528              : void
     529            0 : TokenCollector::visit (ConstGenericParam &param)
     530              : {
     531              :   // Syntax:
     532              :   // const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )?
     533            0 :   describe_node (std::string ("ConstGenericParam"), [this, &param] () {
     534            0 :     visit_items_as_lines (param.get_outer_attrs ());
     535            0 :     push (Rust::Token::make (CONST, param.get_locus ()));
     536            0 :     auto id = param.get_name ().as_string ();
     537            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
     538            0 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
     539            0 :     if (param.has_type ())
     540            0 :       visit (param.get_type ());
     541            0 :     if (param.has_default_value ())
     542              :       {
     543            0 :         push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
     544            0 :         visit (param.get_default_value_unchecked ());
     545              :       }
     546            0 :   });
     547            0 : }
     548              : 
     549              : void
     550         1599 : TokenCollector::visit (PathExprSegment &segment)
     551              : {
     552         1599 :   describe_node (std::string ("PathExprSegment"), [this, &segment] () {
     553         1599 :     visit (segment.get_ident_segment ());
     554         1599 :     if (segment.has_generic_args ())
     555              :       {
     556           63 :         auto generics = segment.get_generic_args ();
     557           63 :         push (Rust::Token::make (SCOPE_RESOLUTION, segment.get_locus ()));
     558           63 :         push (Rust::Token::make (LEFT_ANGLE, generics.get_locus ()));
     559              : 
     560           63 :         auto &lifetime_args = generics.get_lifetime_args ();
     561           63 :         auto &generic_args = generics.get_generic_args ();
     562           63 :         auto &binding_args = generics.get_binding_args ();
     563              : 
     564           63 :         visit_items_joined_by_separator (generic_args, COMMA);
     565              : 
     566           63 :         if (!lifetime_args.empty ()
     567           63 :             && (!generic_args.empty () || !binding_args.empty ()))
     568              :           {
     569            0 :             push (Rust::Token::make (COMMA, UNDEF_LOCATION));
     570              :           }
     571              : 
     572           63 :         visit_items_joined_by_separator (binding_args, COMMA);
     573              : 
     574           63 :         if (!generic_args.empty () && !binding_args.empty ())
     575              :           {
     576            0 :             push (Rust::Token::make (COMMA, UNDEF_LOCATION));
     577              :           }
     578              : 
     579           63 :         visit_items_joined_by_separator (lifetime_args, COMMA);
     580              : 
     581           63 :         push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION));
     582           63 :       }
     583         1599 :   });
     584         1599 : }
     585              : 
     586              : void
     587         1180 : TokenCollector::visit (PathInExpression &path)
     588              : {
     589         1180 :   describe_node (std::string ("PathInExpression"), [this, &path] () {
     590         1180 :     if (path.is_lang_item ())
     591              :       {
     592           64 :         push (Rust::Token::make (TokenId::HASH, path.get_locus ()));
     593           64 :         push (Rust::Token::make (TokenId::LEFT_SQUARE, path.get_locus ()));
     594          128 :         push (Rust::Token::make_identifier (path.get_locus (), "lang"));
     595           64 :         push (Rust::Token::make (TokenId::EQUAL, path.get_locus ()));
     596          128 :         push (Rust::Token::make_string (
     597           64 :           path.get_locus (), LangItem::ToString (path.get_lang_item ())));
     598           64 :         push (Rust::Token::make (TokenId::RIGHT_SQUARE, path.get_locus ()));
     599              : 
     600           64 :         return;
     601              :       }
     602              : 
     603         1116 :     if (path.opening_scope_resolution ())
     604            0 :       push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
     605              : 
     606         1116 :     visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
     607              :   });
     608         1180 : }
     609              : 
     610              : void
     611         3899 : TokenCollector::visit (TypePathSegment &segment)
     612              : {
     613              :   // Syntax:
     614              :   //    PathIdentSegment
     615         3899 :   describe_node (std::string ("TypePathSegment"), [this, &segment] () {
     616         3899 :     auto locus = segment.is_lang_item ()
     617         3899 :                    ? segment.get_locus ()
     618         3899 :                    : segment.get_ident_segment ().get_locus ();
     619         3899 :     auto segment_string = segment.is_lang_item ()
     620         3899 :                             ? LangItem::PrettyString (segment.get_lang_item ())
     621         3899 :                             : segment.get_ident_segment ().as_string ();
     622         7798 :     push (Rust::Token::make_identifier (locus, std::move (segment_string)));
     623         3899 :   });
     624         3899 : }
     625              : 
     626              : void
     627          334 : TokenCollector::visit (TypePathSegmentGeneric &segment)
     628              : {
     629              :   // Syntax:
     630              :   //    PathIdentSegment `::`? (GenericArgs)?
     631              :   // GenericArgs :
     632              :   //    `<` `>`
     633              :   //    | `<` ( GenericArg `,` )* GenericArg `,`? `>`
     634          334 :   describe_node (std::string ("TypePathSegmentGeneric"), [this, &segment] () {
     635          334 :     auto ident_segment = segment.get_ident_segment ();
     636          334 :     auto id = ident_segment.as_string ();
     637          668 :     push (Rust::Token::make_identifier (ident_segment.get_locus (),
     638              :                                         std::move (id)));
     639              : 
     640          334 :     auto locus = segment.is_lang_item ()
     641          334 :                    ? segment.get_locus ()
     642          334 :                    : segment.get_ident_segment ().get_locus ();
     643          334 :     auto segment_string = segment.is_lang_item ()
     644          334 :                             ? LangItem::PrettyString (segment.get_lang_item ())
     645          334 :                             : segment.get_ident_segment ().as_string ();
     646          668 :     push (Rust::Token::make_identifier (locus, std::move (segment_string)));
     647              : 
     648          334 :     push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION));
     649              : 
     650          334 :     {
     651          334 :       auto &lifetime_args = segment.get_generic_args ().get_lifetime_args ();
     652          334 :       auto &generic_args = segment.get_generic_args ().get_generic_args ();
     653          334 :       auto &binding_args = segment.get_generic_args ().get_binding_args ();
     654              : 
     655          334 :       visit_items_joined_by_separator (lifetime_args, COMMA);
     656          334 :       if (!lifetime_args.empty ()
     657          334 :           && (!generic_args.empty () || !binding_args.empty ()))
     658            4 :         push (Rust::Token::make (COMMA, UNDEF_LOCATION));
     659          334 :       visit_items_joined_by_separator (generic_args, COMMA);
     660          334 :       if (!generic_args.empty () && !binding_args.empty ())
     661            0 :         push (Rust::Token::make (COMMA, UNDEF_LOCATION));
     662          334 :       visit_items_joined_by_separator (binding_args, COMMA);
     663              :     }
     664              : 
     665          668 :     push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION));
     666          334 :   });
     667          334 : }
     668              : 
     669              : void
     670           32 : TokenCollector::visit (GenericArgsBinding &binding)
     671              : {
     672              :   // Syntax:
     673              :   //    IDENTIFIER `=` Type
     674           32 :   describe_node (std::string ("GenericArgsBinding"), [this, &binding] () {
     675           64 :     auto identifier = binding.get_identifier ().as_string ();
     676           64 :     push (Rust::Token::make_identifier (binding.get_locus (),
     677              :                                         std::move (identifier)));
     678              : 
     679           32 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
     680           32 :     visit (binding.get_type ());
     681           32 :   });
     682           32 : }
     683              : 
     684              : void
     685          409 : TokenCollector::visit (GenericArg &arg)
     686              : {
     687              :   // `GenericArg` implements `accept_vis` but it is not useful for this case
     688              :   // as it ignores unresolved cases (`Kind::Either`).
     689          409 :   describe_node (std::string ("GenericArg"), [this, &arg] () {
     690          409 :     switch (arg.get_kind ())
     691              :       {
     692            0 :       case GenericArg::Kind::Const:
     693            0 :         visit (arg.get_expression ());
     694            0 :         break;
     695          409 :       case GenericArg::Kind::Type:
     696          409 :         visit (arg.get_type ());
     697          409 :         break;
     698            0 :       case GenericArg::Kind::Either:
     699            0 :         {
     700            0 :           auto path = arg.get_path ();
     701            0 :           push (
     702            0 :             Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
     703            0 :         }
     704            0 :         break;
     705              :       }
     706          409 :   });
     707          409 : }
     708              : 
     709              : void
     710            5 : TokenCollector::visit (TypePathSegmentFunction &segment)
     711              : {
     712              :   // Syntax:
     713              :   //   PathIdentSegment `::`? (TypePathFn)?
     714            5 :   describe_node (std::string ("TypePathSegmentFunction"), [this, &segment] () {
     715            5 :     auto ident_segment = segment.get_ident_segment ();
     716            5 :     auto id = ident_segment.as_string ();
     717           10 :     push (Rust::Token::make_identifier (ident_segment.get_locus (),
     718              :                                         std::move (id)));
     719              : 
     720            5 :     if (segment.get_separating_scope_resolution ())
     721            0 :       push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
     722              : 
     723            5 :     if (!segment.is_ident_only ())
     724            5 :       visit (segment.get_type_path_function ());
     725            5 :   });
     726            5 : }
     727              : 
     728              : void
     729            5 : TokenCollector::visit (TypePathFunction &type_path_fn)
     730              : {
     731              :   // Syntax:
     732              :   //   `(` TypePathFnInputs? `)` (`->` Type)?
     733              :   // TypePathFnInputs :
     734              :   //   Type (`,` Type)* `,`?
     735            5 :   describe_node (std::string ("TypePathFunction"), [this, &type_path_fn] () {
     736            5 :     push (Rust::Token::make (LEFT_PAREN, type_path_fn.get_locus ()));
     737            5 :     if (type_path_fn.has_inputs ())
     738            5 :       visit_items_joined_by_separator (type_path_fn.get_params (), COMMA);
     739            5 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
     740              : 
     741            5 :     if (type_path_fn.has_return_type ())
     742              :       {
     743            5 :         push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION));
     744            5 :         visit (type_path_fn.get_return_type ());
     745              :       }
     746            5 :   });
     747            5 : }
     748              : 
     749              : void
     750         3649 : TokenCollector::visit (TypePath &path)
     751              : {
     752              :   // Syntax:
     753              :   //    `::`? TypePathSegment (`::` TypePathSegment)*
     754         3649 :   describe_node (std::string ("TypePath"), [this, &path] () {
     755         3649 :     if (path.has_opening_scope_resolution_op ())
     756            0 :       push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
     757              : 
     758         3649 :     visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
     759         3649 :   });
     760         3649 : }
     761              : 
     762              : void
     763         1599 : TokenCollector::visit (PathIdentSegment &segment)
     764              : {
     765         1599 :   describe_node (std::string ("PathIdentSegment"), [this, &segment] () {
     766         1599 :     if (segment.is_super_path_seg ())
     767              :       {
     768            0 :         push (Rust::Token::make (SUPER, segment.get_locus ()));
     769              :       }
     770         1599 :     else if (segment.is_crate_path_seg ())
     771              :       {
     772           16 :         push (Rust::Token::make (CRATE, segment.get_locus ()));
     773              :       }
     774         1591 :     else if (segment.is_lower_self_seg ())
     775              :       {
     776          184 :         push (Rust::Token::make (SELF, segment.get_locus ()));
     777              :       }
     778         1499 :     else if (segment.is_big_self_seg ())
     779              :       {
     780            0 :         push (Rust::Token::make (SELF_ALIAS, segment.get_locus ()));
     781              :       }
     782              :     else
     783              :       {
     784         1499 :         auto id = segment.as_string ();
     785         1499 :         push (
     786         2998 :           Rust::Token::make_identifier (segment.get_locus (), std::move (id)));
     787         1499 :       }
     788         1599 :   });
     789         1599 : }
     790              : 
     791              : void
     792           23 : TokenCollector::visit (QualifiedPathInExpression &path)
     793              : {
     794           23 :   describe_node (std::string ("QualifiedPathInExpression"), [this, &path] () {
     795           23 :     visit (path.get_qualified_path_type ());
     796           46 :     for (auto &segment : path.get_segments ())
     797              :       {
     798           23 :         push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
     799           23 :         visit (segment);
     800              :       }
     801           23 :   });
     802           23 : }
     803              : 
     804              : void
     805           79 : TokenCollector::visit (QualifiedPathType &path)
     806              : {
     807           79 :   describe_node (std::string ("QualifiedPathType"), [this, &path] () {
     808           79 :     push (Rust::Token::make (LEFT_ANGLE, path.get_locus ()));
     809           79 :     visit (path.get_type ());
     810           79 :     if (path.has_as_clause ())
     811              :       {
     812           71 :         push (Rust::Token::make (AS, UNDEF_LOCATION));
     813           71 :         visit (path.get_as_type_path ());
     814              :       }
     815           79 :     push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION));
     816           79 :   });
     817           79 : }
     818              : 
     819              : void
     820           56 : TokenCollector::visit (QualifiedPathInType &path)
     821              : {
     822           56 :   describe_node (std::string ("QualifiedPathInType"), [this, &path] () {
     823           56 :     visit (path.get_qualified_path_type ());
     824              : 
     825           56 :     push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
     826           56 :     visit (path.get_associated_segment ());
     827           56 :     for (auto &segment : path.get_segments ())
     828              :       {
     829            0 :         push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
     830            0 :         visit (segment);
     831              :       }
     832           56 :   });
     833           56 : }
     834              : 
     835              : void
     836         3858 : TokenCollector::visit (Literal &lit, location_t locus)
     837              : {
     838         3858 :   auto value = lit.as_string ();
     839         3858 :   switch (lit.get_lit_type ())
     840              :     {
     841           49 :     case Literal::LitType::CHAR:
     842           49 :       push (
     843           49 :         Rust::Token::make_char (locus,
     844              :                                 // TODO: Change this to support utf-8 properly
     845           49 :                                 Codepoint (static_cast<uint32_t> (value[0]))));
     846           49 :       break;
     847         2148 :     case Literal::LitType::STRING:
     848         4296 :       push (Rust::Token::make_string (locus, std::move (value)));
     849         2148 :       break;
     850           28 :     case Literal::LitType::BYTE:
     851           28 :       push (Rust::Token::make_byte_char (locus, value[0]));
     852           28 :       break;
     853           14 :     case Literal::LitType::BYTE_STRING:
     854           28 :       push (Rust::Token::make_byte_string (locus, std::move (value)));
     855           14 :       break;
     856            0 :     case Literal::LitType::RAW_STRING:
     857            0 :       push (Rust::Token::make_raw_string (locus, std::move (value)));
     858            0 :       break;
     859         1462 :     case Literal::LitType::INT:
     860         2924 :       push (
     861         2924 :         Rust::Token::make_int (locus, std::move (value), lit.get_type_hint ()));
     862         1462 :       break;
     863           16 :     case Literal::LitType::FLOAT:
     864           32 :       push (Rust::Token::make_float (locus, std::move (value),
     865              :                                      lit.get_type_hint ()));
     866           16 :       break;
     867          141 :     case Literal::LitType::BOOL:
     868          141 :       {
     869          141 :         if (value == Values::Keywords::FALSE_LITERAL)
     870          130 :           push (Rust::Token::make (FALSE_LITERAL, locus));
     871           76 :         else if (value == Values::Keywords::TRUE_LITERAL)
     872          152 :           push (Rust::Token::make (TRUE_LITERAL, locus));
     873              :         else
     874            0 :           rust_unreachable (); // Not a boolean
     875              :         break;
     876              :       }
     877            0 :     case Literal::LitType::ERROR:
     878            0 :       rust_unreachable ();
     879         3858 :       break;
     880              :     }
     881         3858 : }
     882              : 
     883              : void
     884         3828 : TokenCollector::visit (LiteralExpr &expr)
     885              : {
     886         3828 :   describe_node (std::string ("LiteralExpr"), [this, &expr] () {
     887         3828 :     auto lit = expr.get_literal ();
     888         3828 :     visit (lit, expr.get_locus ());
     889         3828 :   });
     890         3828 : }
     891              : 
     892              : void
     893         2072 : TokenCollector::visit (AttrInputLiteral &literal)
     894              : {
     895         2072 :   describe_node (std::string ("AttrInputLiteral"), [this, &literal] () {
     896         2072 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
     897         2072 :     visit (literal.get_literal ());
     898         2072 :   });
     899         2072 : }
     900              : 
     901              : void
     902            0 : TokenCollector::visit (AttrInputExpr &attr)
     903              : {
     904            0 :   describe_node (std::string ("AttrInputExpr"),
     905            0 :                  [this, &attr] () { visit (attr.get_expr ()); });
     906            0 : }
     907              : 
     908              : void
     909            0 : TokenCollector::visit (MetaItemLitExpr &item)
     910              : {
     911            0 :   describe_node (std::string ("MetaItemLitExpr"), [this, &item] () {
     912            0 :     auto lit = item.get_literal ();
     913            0 :     visit (lit);
     914            0 :   });
     915            0 : }
     916              : 
     917              : void
     918            0 : TokenCollector::visit (MetaItemPathExpr &item)
     919              : {
     920            0 :   describe_node (std::string ("MetaItemPathLit"), [this, &item] () {
     921            0 :     auto &path = item.get_path ();
     922            0 :     auto &expr = item.get_expr ();
     923            0 :     visit (path);
     924            0 :     push (Rust::Token::make (EQUAL, item.get_locus ()));
     925            0 :     visit (expr);
     926            0 :   });
     927            0 : }
     928              : 
     929              : void
     930          237 : TokenCollector::visit (BorrowExpr &expr)
     931              : {
     932          237 :   describe_node (std::string ("BorrowExpr"), [this, &expr] () {
     933          237 :     push (Rust::Token::make (AMP, expr.get_locus ()));
     934          237 :     if (expr.get_is_double_borrow ())
     935           32 :       push (Rust::Token::make (AMP, UNDEF_LOCATION));
     936              : 
     937          237 :     if (expr.is_raw_borrow ())
     938              :       {
     939            0 :         push (Rust::Token::make_identifier (expr.get_locus (),
     940            0 :                                             Values::WeakKeywords::RAW));
     941            0 :         if (expr.get_is_mut ())
     942            0 :           push (Rust::Token::make (MUT, UNDEF_LOCATION));
     943              :         else
     944            0 :           push (Rust::Token::make (CONST, UNDEF_LOCATION));
     945              :       }
     946              :     else
     947              :       {
     948          237 :         if (expr.get_is_mut ())
     949          134 :           push (Rust::Token::make (MUT, UNDEF_LOCATION));
     950              :       }
     951              : 
     952          237 :     if (expr.is_raw_borrow ())
     953              :       {
     954            0 :         push (Rust::Token::make_identifier (expr.get_locus (),
     955            0 :                                             Values::WeakKeywords::RAW));
     956            0 :         if (expr.get_is_mut ())
     957            0 :           push (Rust::Token::make (MUT, UNDEF_LOCATION));
     958              :         else
     959            0 :           push (Rust::Token::make (CONST, UNDEF_LOCATION));
     960              :       }
     961              :     else
     962              :       {
     963          237 :         if (expr.get_is_mut ())
     964          134 :           push (Rust::Token::make (MUT, UNDEF_LOCATION));
     965              :       }
     966              : 
     967          237 :     if (expr.has_borrow_expr ())
     968          237 :       visit (expr.get_borrowed_expr ());
     969          237 :   });
     970          237 : }
     971              : 
     972              : void
     973           82 : TokenCollector::visit (DereferenceExpr &expr)
     974              : {
     975           82 :   describe_node (std::string ("DereferenceExpr"), [this, &expr] () {
     976           82 :     push (Rust::Token::make (ASTERISK, expr.get_locus ()));
     977           82 :     visit (expr.get_dereferenced_expr ());
     978           82 :   });
     979           82 : }
     980              : 
     981              : void
     982            0 : TokenCollector::visit (ErrorPropagationExpr &expr)
     983              : {
     984            0 :   describe_node (std::string ("ErrorPropagationExpr"), [this, &expr] () {
     985            0 :     visit (expr.get_propagating_expr ());
     986            0 :     push (Rust::Token::make (QUESTION_MARK, expr.get_locus ()));
     987            0 :   });
     988            0 : }
     989              : 
     990              : void
     991          175 : TokenCollector::visit (NegationExpr &expr)
     992              : {
     993          175 :   describe_node (std::string ("NegationExpr"), [this, &expr] () {
     994          175 :     switch (expr.get_expr_type ())
     995              :       {
     996          102 :       case NegationOperator::NEGATE:
     997          102 :         push (Rust::Token::make (MINUS, expr.get_locus ()));
     998          102 :         break;
     999           73 :       case NegationOperator::NOT:
    1000           73 :         push (Rust::Token::make (EXCLAM, expr.get_locus ()));
    1001           73 :         break;
    1002              :       }
    1003          175 :     visit (expr.get_negated_expr ());
    1004          175 :   });
    1005          175 : }
    1006              : 
    1007              : void
    1008          349 : TokenCollector::visit (ArithmeticOrLogicalExpr &expr)
    1009              : {
    1010          349 :   describe_node (std::string ("ArithmeticOrLogicalExpr"), [this, &expr] () {
    1011          349 :     visit (expr.get_left_expr ());
    1012          349 :     switch (expr.get_expr_type ())
    1013              :       {
    1014          214 :       case ArithmeticOrLogicalOperator::ADD:
    1015          214 :         push (Rust::Token::make (PLUS, expr.get_locus ()));
    1016          214 :         break;
    1017              : 
    1018           85 :       case ArithmeticOrLogicalOperator::SUBTRACT:
    1019           85 :         push (Rust::Token::make (MINUS, expr.get_locus ()));
    1020           85 :         break;
    1021              : 
    1022           22 :       case ArithmeticOrLogicalOperator::MULTIPLY:
    1023           22 :         push (Rust::Token::make (ASTERISK, expr.get_locus ()));
    1024           22 :         break;
    1025              : 
    1026            8 :       case ArithmeticOrLogicalOperator::DIVIDE:
    1027            8 :         push (Rust::Token::make (DIV, expr.get_locus ()));
    1028            8 :         break;
    1029              : 
    1030            7 :       case ArithmeticOrLogicalOperator::MODULUS:
    1031            7 :         push (Rust::Token::make (PERCENT, expr.get_locus ()));
    1032            7 :         break;
    1033              : 
    1034            4 :       case ArithmeticOrLogicalOperator::BITWISE_AND:
    1035            4 :         push (Rust::Token::make (AMP, expr.get_locus ()));
    1036            4 :         break;
    1037              : 
    1038            3 :       case ArithmeticOrLogicalOperator::BITWISE_OR:
    1039            3 :         push (Rust::Token::make (PIPE, expr.get_locus ()));
    1040            3 :         break;
    1041              : 
    1042            0 :       case ArithmeticOrLogicalOperator::BITWISE_XOR:
    1043            0 :         push (Rust::Token::make (CARET, expr.get_locus ()));
    1044            0 :         break;
    1045              : 
    1046            4 :       case ArithmeticOrLogicalOperator::LEFT_SHIFT:
    1047            4 :         push (Rust::Token::make (LEFT_SHIFT, expr.get_locus ()));
    1048            4 :         break;
    1049              : 
    1050            2 :       case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
    1051            2 :         push (Rust::Token::make (RIGHT_SHIFT, expr.get_locus ()));
    1052            2 :         break;
    1053              :       }
    1054              : 
    1055          349 :     visit (expr.get_right_expr ());
    1056          349 :   });
    1057          349 : }
    1058              : 
    1059              : void
    1060          199 : TokenCollector::visit (ComparisonExpr &expr)
    1061              : {
    1062          199 :   describe_node (std::string ("ComparisonExpr"), [this, &expr] () {
    1063          199 :     visit (expr.get_left_expr ());
    1064              : 
    1065          199 :     switch (expr.get_expr_type ())
    1066              :       {
    1067           17 :       case ComparisonOperator::EQUAL:
    1068           17 :         push (Rust::Token::make (EQUAL_EQUAL, expr.get_locus ()));
    1069           17 :         break;
    1070           99 :       case ComparisonOperator::NOT_EQUAL:
    1071           99 :         push (Rust::Token::make (NOT_EQUAL, expr.get_locus ()));
    1072           99 :         break;
    1073           44 :       case ComparisonOperator::GREATER_THAN:
    1074           44 :         push (Rust::Token::make (RIGHT_ANGLE, expr.get_locus ()));
    1075           44 :         break;
    1076            2 :       case ComparisonOperator::LESS_THAN:
    1077            2 :         push (Rust::Token::make (LEFT_ANGLE, expr.get_locus ()));
    1078            2 :         break;
    1079            2 :       case ComparisonOperator::GREATER_OR_EQUAL:
    1080            2 :         push (Rust::Token::make (GREATER_OR_EQUAL, expr.get_locus ()));
    1081            2 :         break;
    1082              : 
    1083           35 :       case ComparisonOperator::LESS_OR_EQUAL:
    1084           35 :         push (Rust::Token::make (LESS_OR_EQUAL, expr.get_locus ()));
    1085           35 :         break;
    1086              :       }
    1087          199 :     visit (expr.get_right_expr ());
    1088          199 :   });
    1089          199 : }
    1090              : 
    1091              : void
    1092           35 : TokenCollector::visit (LazyBooleanExpr &expr)
    1093              : {
    1094           35 :   describe_node (std::string ("LazyBooleanExpr"), [this, &expr] () {
    1095           35 :     visit (expr.get_left_expr ());
    1096              : 
    1097           35 :     switch (expr.get_expr_type ())
    1098              :       {
    1099            7 :       case LazyBooleanOperator::LOGICAL_AND:
    1100            7 :         push (Rust::Token::make (LOGICAL_AND, expr.get_locus ()));
    1101            7 :         break;
    1102           28 :       case LazyBooleanOperator::LOGICAL_OR:
    1103           28 :         push (Rust::Token::make (OR, expr.get_locus ()));
    1104           28 :         break;
    1105              :       }
    1106              : 
    1107           35 :     visit (expr.get_right_expr ());
    1108           35 :   });
    1109           35 : }
    1110              : 
    1111              : void
    1112          223 : TokenCollector::visit (TypeCastExpr &expr)
    1113              : {
    1114          223 :   describe_node (std::string ("TypeCastExpr"), [this, &expr] () {
    1115          223 :     visit (expr.get_casted_expr ());
    1116          223 :     push (Rust::Token::make (AS, expr.get_locus ()));
    1117          223 :     visit (expr.get_type_to_cast_to ());
    1118          223 :   });
    1119          223 : }
    1120              : 
    1121              : void
    1122          228 : TokenCollector::visit (AssignmentExpr &expr)
    1123              : {
    1124          228 :   describe_node (std::string ("AssignementExpr"), [this, &expr] () {
    1125          228 :     expr.visit_lhs (*this);
    1126          228 :     push (Rust::Token::make (EQUAL, expr.get_locus ()));
    1127          228 :     expr.visit_rhs (*this);
    1128          228 :   });
    1129          228 : }
    1130              : 
    1131              : void
    1132            7 : TokenCollector::visit (CompoundAssignmentExpr &expr)
    1133              : {
    1134            7 :   describe_node (std::string ("CompoundAssignmentExpr"), [this, &expr] () {
    1135            7 :     visit (expr.get_left_expr ());
    1136              : 
    1137            7 :     switch (expr.get_expr_type ())
    1138              :       {
    1139            0 :       case CompoundAssignmentOperator::ADD:
    1140            0 :         push (Rust::Token::make (PLUS_EQ, expr.get_locus ()));
    1141            0 :         break;
    1142            7 :       case CompoundAssignmentOperator::SUBTRACT:
    1143            7 :         push (Rust::Token::make (MINUS_EQ, expr.get_locus ()));
    1144            7 :         break;
    1145            0 :       case CompoundAssignmentOperator::MULTIPLY:
    1146            0 :         push (Rust::Token::make (ASTERISK_EQ, expr.get_locus ()));
    1147            0 :         break;
    1148            0 :       case CompoundAssignmentOperator::DIVIDE:
    1149            0 :         push (Rust::Token::make (DIV_EQ, expr.get_locus ()));
    1150            0 :         break;
    1151            0 :       case CompoundAssignmentOperator::MODULUS:
    1152            0 :         push (Rust::Token::make (PERCENT_EQ, expr.get_locus ()));
    1153            0 :         break;
    1154            0 :       case CompoundAssignmentOperator::BITWISE_AND:
    1155            0 :         push (Rust::Token::make (AMP_EQ, expr.get_locus ()));
    1156            0 :         break;
    1157            0 :       case CompoundAssignmentOperator::BITWISE_OR:
    1158            0 :         push (Rust::Token::make (PIPE_EQ, expr.get_locus ()));
    1159            0 :         break;
    1160            0 :       case CompoundAssignmentOperator::BITWISE_XOR:
    1161            0 :         push (Rust::Token::make (CARET_EQ, expr.get_locus ()));
    1162            0 :         break;
    1163            0 :       case CompoundAssignmentOperator::LEFT_SHIFT:
    1164            0 :         push (Rust::Token::make (LEFT_SHIFT_EQ, expr.get_locus ()));
    1165            0 :         break;
    1166            0 :       case CompoundAssignmentOperator::RIGHT_SHIFT:
    1167            0 :         push (Rust::Token::make (RIGHT_SHIFT_EQ, expr.get_locus ()));
    1168            0 :         break;
    1169              :       }
    1170            7 :     visit (expr.get_right_expr ());
    1171            7 :   });
    1172            7 : }
    1173              : 
    1174              : void
    1175           58 : TokenCollector::visit (GroupedExpr &expr)
    1176              : {
    1177           58 :   describe_node (std::string ("GroupedExpr"), [this, &expr] () {
    1178           58 :     push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
    1179           58 :     visit (expr.get_expr_in_parens ());
    1180           58 :     push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
    1181           58 :   });
    1182           58 : }
    1183              : 
    1184              : void
    1185            9 : TokenCollector::visit (ArrayElemsValues &elems)
    1186              : {
    1187            9 :   describe_node (std::string ("ArraysElemValues"), [this, &elems] () {
    1188            9 :     visit_items_joined_by_separator (elems.get_values (), COMMA);
    1189            9 :   });
    1190            9 : }
    1191              : 
    1192              : void
    1193            3 : TokenCollector::visit (ArrayElemsCopied &elems)
    1194              : {
    1195            3 :   describe_node (std::string ("ArrayElemsCopied"), [this, &elems] () {
    1196            3 :     visit (elems.get_elem_to_copy ());
    1197            3 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    1198            3 :     visit (elems.get_num_copies ());
    1199            3 :   });
    1200            3 : }
    1201              : 
    1202              : void
    1203           12 : TokenCollector::visit (ArrayExpr &expr)
    1204              : {
    1205           12 :   describe_node (std::string ("ArrayExpr"), [this, &expr] () {
    1206           12 :     push (Rust::Token::make (LEFT_SQUARE, expr.get_locus ()));
    1207           12 :     visit (expr.get_array_elems ());
    1208           12 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
    1209           12 :   });
    1210           12 : }
    1211              : 
    1212              : void
    1213            3 : TokenCollector::visit (ArrayIndexExpr &expr)
    1214              : {
    1215            3 :   describe_node (std::string ("ArrayIndexExpr"), [this, &expr] () {
    1216            3 :     visit (expr.get_array_expr ());
    1217            3 :     push (Rust::Token::make (LEFT_SQUARE, expr.get_locus ()));
    1218            3 :     visit (expr.get_index_expr ());
    1219            3 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
    1220            3 :   });
    1221            3 : }
    1222              : 
    1223              : void
    1224           50 : TokenCollector::visit (TupleExpr &expr)
    1225              : {
    1226           50 :   describe_node (std::string ("TupleExpr"), [this, &expr] () {
    1227           50 :     visit_items_as_lines (expr.get_outer_attrs ());
    1228           50 :     push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
    1229           50 :     visit_items_joined_by_separator (expr.get_tuple_elems (), COMMA);
    1230           50 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    1231           50 :   });
    1232           50 : }
    1233              : 
    1234              : void
    1235           63 : TokenCollector::visit (TupleIndexExpr &expr)
    1236              : {
    1237           63 :   describe_node (std::string ("TupleIndexExpr"), [this, &expr] () {
    1238           63 :     visit (expr.get_tuple_expr ());
    1239           63 :     push (Rust::Token::make (DOT, expr.get_locus ()));
    1240          126 :     push (Rust::Token::make_int (UNDEF_LOCATION,
    1241           63 :                                  std::to_string (expr.get_tuple_index ())));
    1242           63 :   });
    1243           63 : }
    1244              : 
    1245              : void
    1246            7 : TokenCollector::visit (StructExprStruct &expr)
    1247              : {
    1248            7 :   describe_node (std::string ("StructExprStruct"),
    1249           14 :                  [this, &expr] () { visit (expr.get_struct_name ()); });
    1250            7 : }
    1251              : 
    1252              : void
    1253            1 : TokenCollector::visit (StructExprFieldIdentifier &expr)
    1254              : {
    1255            1 :   describe_node (std::string ("StructExprFieldIdentifier"), [this, &expr] () {
    1256            1 :     visit_items_as_lines (expr.get_outer_attrs ());
    1257            2 :     auto id = expr.get_field_name ().as_string ();
    1258            2 :     push (Rust::Token::make_identifier (expr.get_locus (), std::move (id)));
    1259            1 :   });
    1260            1 : }
    1261              : 
    1262              : void
    1263          323 : TokenCollector::visit (StructExprFieldIdentifierValue &expr)
    1264              : {
    1265          323 :   describe_node (std::string ("StructExprFieldIdentifierValue"), [this,
    1266              :                                                                   &expr] () {
    1267          323 :     visit_items_as_lines (expr.get_outer_attrs ());
    1268          323 :     auto id = expr.get_field_name ();
    1269          646 :     push (Rust::Token::make_identifier (expr.get_locus (), std::move (id)));
    1270          323 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    1271          323 :     visit (expr.get_value ());
    1272          323 :   });
    1273          323 : }
    1274              : 
    1275              : void
    1276            0 : TokenCollector::visit (StructExprFieldIndexValue &expr)
    1277              : {
    1278            0 :   describe_node (std::string ("StructExprFieldIndexValue"), [this, &expr] () {
    1279            0 :     visit_items_as_lines (expr.get_outer_attrs ());
    1280            0 :     push (Rust::Token::make_int (expr.get_locus (),
    1281            0 :                                  std::to_string (expr.get_index ())));
    1282            0 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    1283            0 :     visit (expr.get_value ());
    1284            0 :   });
    1285            0 : }
    1286              : 
    1287              : void
    1288           21 : TokenCollector::visit (StructBase &base)
    1289              : {
    1290           21 :   describe_node (std::string ("StructBase"), [this, &base] () {
    1291           21 :     push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
    1292           21 :     visit (base.get_base_struct ());
    1293           21 :   });
    1294           21 : }
    1295              : 
    1296              : void
    1297          123 : TokenCollector::visit (StructExprStructFields &expr)
    1298              : {
    1299          123 :   describe_node (std::string ("StructExprStructFields"), [this, &expr] () {
    1300          123 :     visit (expr.get_struct_name ());
    1301          123 :     push (Rust::Token::make (LEFT_CURLY, expr.get_locus ()));
    1302          123 :     visit_items_joined_by_separator (expr.get_fields (), COMMA);
    1303          123 :     if (expr.has_struct_base ())
    1304              :       {
    1305           21 :         push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    1306           21 :         visit (expr.get_struct_base ());
    1307              :       }
    1308              :     else
    1309              :       {
    1310          102 :         trailing_comma ();
    1311              :       }
    1312          123 :     push (Rust::Token::make (RIGHT_CURLY, expr.get_locus ()));
    1313          123 :   });
    1314          123 : }
    1315              : 
    1316              : void
    1317            0 : TokenCollector::visit (StructExprStructBase &)
    1318              : {
    1319              :   // FIXME: Implement this node
    1320            0 :   rust_unreachable ();
    1321              : }
    1322              : 
    1323              : void
    1324          712 : TokenCollector::visit (CallExpr &expr)
    1325              : {
    1326          712 :   describe_node (std::string ("CallExpr"), [this, &expr] () {
    1327          712 :     visit (expr.get_function_expr ());
    1328              : 
    1329          712 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    1330              : 
    1331          712 :     visit_items_joined_by_separator (expr.get_params (), COMMA);
    1332              : 
    1333          712 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    1334          712 :   });
    1335          712 : }
    1336              : 
    1337              : void
    1338          288 : TokenCollector::visit (MethodCallExpr &expr)
    1339              : {
    1340          288 :   describe_node (std::string ("MethodCallExpr"), [this, &expr] () {
    1341          288 :     visit (expr.get_receiver_expr ());
    1342          288 :     push (Rust::Token::make (DOT, expr.get_locus ()));
    1343          288 :     visit (expr.get_method_name ());
    1344          288 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    1345          288 :     visit_items_joined_by_separator (expr.get_params (), COMMA);
    1346          288 :     trailing_comma ();
    1347          288 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    1348          288 :   });
    1349          288 : }
    1350              : 
    1351              : void
    1352          124 : TokenCollector::visit (FieldAccessExpr &expr)
    1353              : {
    1354          124 :   describe_node (std::string ("FieldAccessExpr"), [this, &expr] () {
    1355          124 :     visit (expr.get_receiver_expr ());
    1356          124 :     push (Rust::Token::make (DOT, expr.get_locus ()));
    1357          248 :     auto field_name = expr.get_field_name ().as_string ();
    1358          124 :     push (
    1359          248 :       Rust::Token::make_identifier (UNDEF_LOCATION, std::move (field_name)));
    1360          124 :   });
    1361          124 : }
    1362              : 
    1363              : void
    1364           22 : TokenCollector::visit (ClosureParam &param)
    1365              : {
    1366           22 :   describe_node (std::string ("ClosureParam"), [this, &param] () {
    1367           22 :     visit_items_as_lines (param.get_outer_attrs ());
    1368           22 :     visit (param.get_pattern ());
    1369           22 :     if (param.has_type_given ())
    1370              :       {
    1371           22 :         push (Rust::Token::make (COLON, param.get_locus ()));
    1372           22 :         visit (param.get_type ());
    1373              :       }
    1374           22 :   });
    1375           22 : }
    1376              : 
    1377              : void
    1378           29 : TokenCollector::visit_closure_common (ClosureExpr &expr)
    1379              : {
    1380           29 :   describe_node (std::string ("ClosureExpr"), [this, &expr] () {
    1381           29 :     if (expr.get_has_move ())
    1382              :       {
    1383            0 :         push (Rust::Token::make (MOVE, expr.get_locus ()));
    1384              :       }
    1385           29 :     push (Rust::Token::make (PIPE, UNDEF_LOCATION));
    1386           29 :     visit_items_joined_by_separator (expr.get_params (), COMMA);
    1387           29 :     push (Rust::Token::make (PIPE, UNDEF_LOCATION));
    1388           29 :   });
    1389           29 : }
    1390              : 
    1391              : void
    1392           28 : TokenCollector::visit (ClosureExprInner &expr)
    1393              : {
    1394           28 :   describe_node (std::string ("ClosureExprInner"), [this, &expr] () {
    1395           28 :     visit_closure_common (expr);
    1396           28 :     visit (expr.get_definition_expr ());
    1397           28 :   });
    1398           28 : }
    1399              : 
    1400              : void
    1401         1554 : TokenCollector::visit (BlockExpr &expr)
    1402              : {
    1403         1554 :   describe_node (std::string ("BlockExpr"), [this, &expr] () {
    1404         1554 :     visit_items_as_lines (expr.get_outer_attrs ());
    1405         1554 :     push (Rust::Token::make (LEFT_CURLY, expr.get_locus ()));
    1406         1554 :     newline ();
    1407         1554 :     increment_indentation ();
    1408         1554 :     visit_items_as_lines (expr.get_inner_attrs ());
    1409              : 
    1410         1554 :     visit_items_as_lines (expr.get_statements (), {});
    1411              : 
    1412         1554 :     if (expr.has_tail_expr ())
    1413              :       {
    1414          942 :         indentation ();
    1415          942 :         visit (expr.get_tail_expr ());
    1416          942 :         newline ();
    1417              :       }
    1418              : 
    1419         1554 :     decrement_indentation ();
    1420         1554 :     indentation ();
    1421         1554 :     push (Rust::Token::make (RIGHT_CURLY, expr.get_locus ()));
    1422         1554 :     newline ();
    1423         1554 :   });
    1424         1554 : }
    1425              : 
    1426              : void
    1427           26 : TokenCollector::visit (AnonConst &expr)
    1428              : {
    1429           26 :   if (!expr.is_deferred ())
    1430              :     {
    1431           20 :       visit (expr.get_inner_expr ());
    1432           20 :       return;
    1433              :     }
    1434              : 
    1435           12 :   push (Rust::Token::make_string (expr.get_locus (), "_"));
    1436              : }
    1437              : 
    1438              : void
    1439            0 : TokenCollector::visit (ConstBlock &expr)
    1440              : {
    1441            0 :   push (Rust::Token::make (CONST, expr.get_locus ()));
    1442              : 
    1443              :   // The inner expression is already a block expr, so we don't need to add
    1444              :   // curlies
    1445            0 :   visit (expr.get_const_expr ());
    1446            0 : }
    1447              : 
    1448              : void
    1449            1 : TokenCollector::visit (ClosureExprInnerTyped &expr)
    1450              : {
    1451            1 :   describe_node (std::string ("ClosureExprInnerTyped"), [this, &expr] () {
    1452            1 :     visit_closure_common (expr);
    1453            1 :     push (Rust::Token::make (RETURN_TYPE, expr.get_locus ()));
    1454            1 :     visit (expr.get_return_type ());
    1455              : 
    1456            1 :     visit (expr.get_definition_expr ());
    1457            1 :   });
    1458            1 : }
    1459              : 
    1460              : void
    1461            2 : TokenCollector::visit (ContinueExpr &expr)
    1462              : {
    1463            2 :   describe_node (std::string ("ContinueExpr"), [this, &expr] () {
    1464            2 :     push (Rust::Token::make (CONTINUE, expr.get_locus ()));
    1465            2 :     if (expr.has_label ())
    1466            1 :       visit (expr.get_label_unchecked ());
    1467            2 :   });
    1468            2 : }
    1469              : 
    1470              : void
    1471           26 : TokenCollector::visit (BreakExpr &expr)
    1472              : {
    1473           26 :   describe_node (std::string ("BreakExpr"), [this, &expr] () {
    1474           26 :     push (Rust::Token::make (BREAK, expr.get_locus ()));
    1475           26 :     if (expr.has_label ())
    1476            1 :       visit (expr.get_label_unchecked ());
    1477           26 :     if (expr.has_break_expr ())
    1478            0 :       visit (expr.get_break_expr_unchecked ());
    1479           26 :   });
    1480           26 : }
    1481              : 
    1482              : void
    1483           24 : TokenCollector::visit (RangeFromToExpr &expr)
    1484              : {
    1485           24 :   describe_node (std::string ("RangeFromToExpr"), [this, &expr] () {
    1486           24 :     visit (expr.get_from_expr ());
    1487           24 :     push (Rust::Token::make (DOT_DOT, expr.get_locus ()));
    1488           24 :     visit (expr.get_to_expr ());
    1489           24 :   });
    1490           24 : }
    1491              : 
    1492              : void
    1493            0 : TokenCollector::visit (RangeFromExpr &expr)
    1494              : {
    1495            0 :   describe_node (std::string ("RangeFromExpr"), [this, &expr] () {
    1496            0 :     visit (expr.get_from_expr ());
    1497            0 :     push (Rust::Token::make (DOT_DOT, expr.get_locus ()));
    1498            0 :   });
    1499            0 : }
    1500              : 
    1501              : void
    1502            0 : TokenCollector::visit (RangeToExpr &expr)
    1503              : {
    1504            0 :   describe_node (std::string ("RangeToExpr"), [this, &expr] () {
    1505            0 :     push (Rust::Token::make (DOT_DOT, expr.get_locus ()));
    1506            0 :     visit (expr.get_to_expr ());
    1507            0 :   });
    1508            0 : }
    1509              : 
    1510              : void
    1511            0 : TokenCollector::visit (RangeFullExpr &expr)
    1512              : {
    1513            0 :   describe_node (std::string ("RangeFullExpr"), [this, &expr] () {
    1514            0 :     push (Rust::Token::make (DOT_DOT, expr.get_locus ()));
    1515            0 :   });
    1516            0 : }
    1517              : 
    1518              : void
    1519            0 : TokenCollector::visit (RangeFromToInclExpr &expr)
    1520              : {
    1521            0 :   describe_node (std::string ("RangeFromToInclExpr"), [this, &expr] () {
    1522            0 :     visit (expr.get_from_expr ());
    1523            0 :     push (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ()));
    1524            0 :     visit (expr.get_to_expr ());
    1525            0 :   });
    1526            0 : }
    1527              : 
    1528              : void
    1529            0 : TokenCollector::visit (RangeToInclExpr &expr)
    1530              : {
    1531            0 :   describe_node (std::string ("RangeToInclExpr"), [this, &expr] () {
    1532            0 :     push (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ()));
    1533            0 :     visit (expr.get_to_expr ());
    1534            0 :   });
    1535            0 : }
    1536              : 
    1537              : void
    1538            0 : TokenCollector::visit (BoxExpr &expr)
    1539              : {
    1540            0 :   describe_node (std::string ("BoxExpr"), [this, &expr] () {
    1541            0 :     push (Rust::Token::make (BOX, expr.get_locus ()));
    1542            0 :     visit (expr.get_boxed_expr ());
    1543            0 :   });
    1544            0 : }
    1545              : 
    1546              : void
    1547            4 : TokenCollector::visit (ReturnExpr &expr)
    1548              : {
    1549            4 :   describe_node (std::string ("ReturnExpr"), [this, &expr] () {
    1550            4 :     push (Rust::Token::make (RETURN_KW, expr.get_locus ()));
    1551            4 :     if (expr.has_returned_expr ())
    1552            4 :       visit (expr.get_returned_expr ());
    1553            4 :   });
    1554            4 : }
    1555              : 
    1556              : void
    1557            0 : TokenCollector::visit (TryExpr &expr)
    1558              : {
    1559            0 :   push (Rust::Token::make (TRY, expr.get_locus ()));
    1560            0 :   visit (expr.get_block_expr ());
    1561            0 : }
    1562              : 
    1563              : void
    1564          362 : TokenCollector::visit (UnsafeBlockExpr &expr)
    1565              : {
    1566          362 :   describe_node (std::string ("UnsafeBlockExpr"), [this, &expr] () {
    1567          362 :     push (Rust::Token::make (UNSAFE, expr.get_locus ()));
    1568          362 :     visit (expr.get_block_expr ());
    1569          362 :   });
    1570          362 : }
    1571              : 
    1572              : void
    1573            5 : TokenCollector::visit (LoopLabel &label)
    1574              : {
    1575            5 :   describe_node (std::string ("LoopLabel"), [this, &label] () {
    1576            5 :     visit (label.get_lifetime ());
    1577            5 :     push (Rust::Token::make (COLON, label.get_locus ()));
    1578            5 :   });
    1579            5 : }
    1580              : 
    1581              : void
    1582           35 : TokenCollector::visit_loop_common (BaseLoopExpr &expr)
    1583              : {
    1584           35 :   describe_node (std::string ("BaseLoopExpr"), [this, &expr] () {
    1585           35 :     if (expr.has_loop_label ())
    1586            4 :       visit (expr.get_loop_label ());
    1587           35 :   });
    1588           35 : }
    1589              : 
    1590              : void
    1591           28 : TokenCollector::visit (LoopExpr &expr)
    1592              : {
    1593           28 :   describe_node (std::string ("LoopExpr"), [this, &expr] () {
    1594           28 :     visit_loop_common (expr);
    1595           28 :     push (Rust::Token::make (LOOP, expr.get_locus ()));
    1596           28 :     visit (expr.get_loop_block ());
    1597           28 :   });
    1598           28 : }
    1599              : 
    1600              : void
    1601            7 : TokenCollector::visit (WhileLoopExpr &expr)
    1602              : {
    1603            7 :   describe_node (std::string ("WhileLoopExpr"), [this, &expr] () {
    1604            7 :     visit_loop_common (expr);
    1605            7 :     push (Rust::Token::make (WHILE, expr.get_locus ()));
    1606            7 :     visit (expr.get_predicate_expr ());
    1607            7 :     visit (expr.get_loop_block ());
    1608            7 :   });
    1609            7 : }
    1610              : 
    1611              : void
    1612            0 : TokenCollector::visit (WhileLetLoopExpr &expr)
    1613              : {
    1614            0 :   describe_node (std::string ("WhileLetLoopExpr"), [this, &expr] () {
    1615            0 :     visit_loop_common (expr);
    1616            0 :     push (Rust::Token::make (WHILE, expr.get_locus ()));
    1617            0 :     push (Rust::Token::make (LET, UNDEF_LOCATION));
    1618            0 :     visit (expr.get_pattern ());
    1619            0 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    1620            0 :     visit (expr.get_scrutinee_expr ());
    1621            0 :     visit (expr.get_loop_block ());
    1622            0 :   });
    1623            0 : }
    1624              : 
    1625              : void
    1626            0 : TokenCollector::visit (ForLoopExpr &expr)
    1627              : {
    1628            0 :   describe_node (std::string ("ForLoopExpr"), [this, &expr] () {
    1629            0 :     visit_loop_common (expr);
    1630            0 :     push (Rust::Token::make (FOR, expr.get_locus ()));
    1631            0 :     visit (expr.get_pattern ());
    1632            0 :     push (Rust::Token::make (IN, UNDEF_LOCATION));
    1633            0 :     visit (expr.get_iterator_expr ());
    1634            0 :     visit (expr.get_loop_block ());
    1635            0 :   });
    1636            0 : }
    1637              : 
    1638              : void
    1639          207 : TokenCollector::visit (IfExpr &expr)
    1640              : {
    1641          207 :   describe_node (std::string ("IfExpr"), [this, &expr] () {
    1642          207 :     push (Rust::Token::make (IF, expr.get_locus ()));
    1643              : 
    1644          207 :     visit (expr.get_condition_expr ());
    1645          207 :     visit (expr.get_if_block ());
    1646          207 :   });
    1647          207 : }
    1648              : 
    1649              : void
    1650           31 : TokenCollector::visit (IfExprConseqElse &expr)
    1651              : {
    1652           31 :   describe_node (std::string ("IfExprConseqElse"), [this, &expr] () {
    1653           31 :     visit (static_cast<IfExpr &> (expr));
    1654           31 :     indentation ();
    1655           31 :     push (Rust::Token::make (ELSE, expr.get_locus ()));
    1656           31 :     visit (expr.get_else_block ());
    1657           31 :   });
    1658           31 : }
    1659              : 
    1660              : void
    1661            3 : TokenCollector::visit (IfLetExpr &expr)
    1662              : {
    1663            3 :   describe_node (std::string ("IfLetExpr"), [this, &expr] () {
    1664            3 :     push (Rust::Token::make (IF, expr.get_locus ()));
    1665            3 :     push (Rust::Token::make (LET, UNDEF_LOCATION));
    1666            3 :     visit (expr.get_pattern ());
    1667            3 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    1668            3 :     visit (expr.get_value_expr ());
    1669            3 :     visit (expr.get_if_block ());
    1670            3 :   });
    1671            3 : }
    1672              : 
    1673              : void
    1674            2 : TokenCollector::visit (IfLetExprConseqElse &expr)
    1675              : {
    1676            2 :   describe_node (std::string ("IfLetExprConseqElse"), [this, &expr] () {
    1677            2 :     visit (static_cast<IfLetExpr &> (expr));
    1678            2 :     indentation ();
    1679            2 :     push (Rust::Token::make (ELSE, expr.get_locus ()));
    1680            2 :     visit (expr.get_else_block ());
    1681            2 :   });
    1682            2 : }
    1683              : 
    1684              : void
    1685          129 : TokenCollector::visit (MatchArm &arm)
    1686              : {
    1687          129 :   describe_node (std::string ("MatchArm"), [this, &arm] () {
    1688          129 :     visit_items_as_lines (arm.get_outer_attrs ());
    1689          129 :     visit (arm.get_pattern ());
    1690          129 :     if (arm.has_match_arm_guard ())
    1691              :       {
    1692            1 :         push (Rust::Token::make (IF, UNDEF_LOCATION));
    1693            1 :         visit (arm.get_guard_expr ());
    1694              :       }
    1695          129 :   });
    1696          129 : }
    1697              : 
    1698              : void
    1699          129 : TokenCollector::visit (MatchCase &match_case)
    1700              : {
    1701          129 :   describe_node (std::string ("MatchCase"), [this, &match_case] () {
    1702          129 :     indentation ();
    1703          129 :     visit (match_case.get_arm ());
    1704          129 :     push (Rust::Token::make (MATCH_ARROW, UNDEF_LOCATION));
    1705          129 :     visit (match_case.get_expr ());
    1706          129 :     indentation ();
    1707          129 :     push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    1708          129 :     newline ();
    1709          129 :   });
    1710          129 : }
    1711              : 
    1712              : void
    1713           74 : TokenCollector::visit (MatchExpr &expr)
    1714              : {
    1715           74 :   describe_node (std::string ("MatchExpr"), [this, &expr] () {
    1716           74 :     push (Rust::Token::make (MATCH_KW, expr.get_locus ()));
    1717           74 :     visit (expr.get_scrutinee_expr ());
    1718           74 :     push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION));
    1719           74 :     newline ();
    1720           74 :     increment_indentation ();
    1721           74 :     visit_items_as_lines (expr.get_inner_attrs ());
    1722          203 :     for (auto &arm : expr.get_match_cases ())
    1723              :       {
    1724          129 :         visit (arm);
    1725              :       }
    1726           74 :     decrement_indentation ();
    1727           74 :     indentation ();
    1728           74 :     push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION));
    1729           74 :   });
    1730           74 : }
    1731              : 
    1732              : void
    1733            0 : TokenCollector::visit (AwaitExpr &expr)
    1734              : {
    1735            0 :   describe_node (std::string ("AwaitExpr"), [this, &expr] () {
    1736            0 :     visit (expr.get_awaited_expr ());
    1737            0 :     push (Rust::Token::make (DOT, expr.get_locus ()));
    1738              :     // TODO: Check status of await keyword (Context dependant ?)
    1739            0 :     push (
    1740            0 :       Rust::Token::make_identifier (UNDEF_LOCATION, Values::Keywords::AWAIT));
    1741            0 :   });
    1742            0 : }
    1743              : 
    1744              : void
    1745            0 : TokenCollector::visit (AsyncBlockExpr &expr)
    1746              : {
    1747            0 :   describe_node (std::string ("AsyncBlockExpr"), [this, &expr] () {
    1748            0 :     push (Rust::Token::make (ASYNC, expr.get_locus ()));
    1749            0 :     if (expr.get_has_move ())
    1750            0 :       push (Rust::Token::make (MOVE, UNDEF_LOCATION));
    1751            0 :     visit (expr.get_block_expr ());
    1752            0 :   });
    1753            0 : }
    1754              : 
    1755              : void
    1756            0 : TokenCollector::visit (InlineAsm &expr)
    1757              : {
    1758            0 :   push (Rust::Token::make_identifier (expr.get_locus (), "asm"));
    1759            0 :   push (Rust::Token::make (EXCLAM, expr.get_locus ()));
    1760            0 :   push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
    1761              : 
    1762            0 :   for (auto &template_str : expr.get_template_strs ())
    1763            0 :     push (Rust::Token::make_string (template_str.get_locus (),
    1764            0 :                                     std::move (template_str.symbol)));
    1765              : 
    1766            0 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1767              : 
    1768            0 :   for (auto &operand : expr.get_operands ())
    1769              :     {
    1770            0 :       using RegisterType = AST::InlineAsmOperand::RegisterType;
    1771            0 :       switch (operand.get_register_type ())
    1772              :         {
    1773            0 :         case RegisterType::In:
    1774            0 :           {
    1775            0 :             visit (operand.get_in ().expr);
    1776            0 :             break;
    1777              :           }
    1778            0 :         case RegisterType::Out:
    1779            0 :           {
    1780            0 :             visit (operand.get_out ().expr);
    1781            0 :             break;
    1782              :           }
    1783            0 :         case RegisterType::InOut:
    1784            0 :           {
    1785            0 :             visit (operand.get_in_out ().expr);
    1786            0 :             break;
    1787              :           }
    1788            0 :         case RegisterType::SplitInOut:
    1789            0 :           {
    1790            0 :             auto split = operand.get_split_in_out ();
    1791            0 :             visit (split.in_expr);
    1792            0 :             visit (split.out_expr);
    1793            0 :             break;
    1794            0 :           }
    1795            0 :         case RegisterType::Const:
    1796            0 :           {
    1797            0 :             visit (operand.get_const ().anon_const.get_inner_expr ());
    1798            0 :             break;
    1799              :           }
    1800            0 :         case RegisterType::Sym:
    1801            0 :           {
    1802            0 :             visit (operand.get_sym ().expr);
    1803            0 :             break;
    1804              :           }
    1805            0 :         case RegisterType::Label:
    1806            0 :           {
    1807            0 :             visit (operand.get_label ().expr);
    1808            0 :             break;
    1809              :           }
    1810              :         }
    1811            0 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1812            0 :     }
    1813            0 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1814              : 
    1815            0 :   for (auto &clobber : expr.get_clobber_abi ())
    1816              :     {
    1817            0 :       push (Rust::Token::make_string (expr.get_locus (),
    1818            0 :                                       std::move (clobber.symbol)));
    1819            0 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1820            0 :     }
    1821            0 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1822              : 
    1823            0 :   for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it)
    1824              :     {
    1825            0 :       auto &arg = *it;
    1826            0 :       push (
    1827            0 :         Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ()));
    1828            0 :       push (Rust::Token::make (EQUAL, expr.get_locus ()));
    1829            0 :       push (Rust::Token::make_identifier (expr.get_locus (),
    1830            0 :                                           std::to_string (arg.second)));
    1831              : 
    1832            0 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1833              :     }
    1834              : 
    1835            0 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1836              : 
    1837            0 :   for (auto &option : expr.get_options ())
    1838              :     {
    1839            0 :       push (Rust::Token::make_identifier (
    1840            0 :         expr.get_locus (), InlineAsm::option_to_string (option).c_str ()));
    1841            0 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1842            0 :     }
    1843              : 
    1844            0 :   push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
    1845            0 : }
    1846              : 
    1847              : void
    1848            2 : TokenCollector::visit (LlvmInlineAsm &expr)
    1849              : {
    1850            4 :   push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm"));
    1851            2 :   push (Rust::Token::make (EXCLAM, expr.get_locus ()));
    1852            2 :   push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
    1853            4 :   for (auto &template_str : expr.get_templates ())
    1854            4 :     push (Rust::Token::make_string (template_str.get_locus (),
    1855            2 :                                     std::move (template_str.symbol)));
    1856              : 
    1857            2 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1858            2 :   for (auto output : expr.get_outputs ())
    1859              :     {
    1860            0 :       push (Rust::Token::make_string (expr.get_locus (),
    1861              :                                       std::move (output.constraint)));
    1862            0 :       visit (output.expr);
    1863            0 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1864            0 :     }
    1865              : 
    1866            2 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1867            4 :   for (auto input : expr.get_inputs ())
    1868              :     {
    1869            4 :       push (Rust::Token::make_string (expr.get_locus (),
    1870              :                                       std::move (input.constraint)));
    1871            2 :       visit (input.expr);
    1872            4 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1873            2 :     }
    1874              : 
    1875            2 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1876            4 :   for (auto &clobber : expr.get_clobbers ())
    1877              :     {
    1878            4 :       push (Rust::Token::make_string (expr.get_locus (),
    1879            2 :                                       std::move (clobber.symbol)));
    1880            4 :       push (Rust::Token::make (COMMA, expr.get_locus ()));
    1881              :     }
    1882            2 :   push (Rust::Token::make (COLON, expr.get_locus ()));
    1883              :   // Dump options
    1884              : 
    1885            2 :   push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
    1886            2 : }
    1887              : 
    1888              : // rust-item.h
    1889              : 
    1890              : void
    1891          410 : TokenCollector::visit (TypeParam &param)
    1892              : {
    1893              :   // Syntax:
    1894              :   //    IDENTIFIER( : TypeParamBounds? )? ( = Type )?
    1895              :   // TypeParamBounds :
    1896              :   //    TypeParamBound ( + TypeParamBound )* +?
    1897          410 :   describe_node (std::string ("TypeParam"), [this, &param] () {
    1898          410 :     visit_items_as_lines (param.get_outer_attrs ());
    1899          820 :     auto id = param.get_type_representation ().as_string ();
    1900          820 :     push (Rust::Token::make_identifier (param.get_locus (), std::move (id)));
    1901          410 :     if (param.has_type_param_bounds ())
    1902              :       {
    1903           86 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
    1904           86 :         visit_items_joined_by_separator (param.get_type_param_bounds (), PLUS);
    1905              :       }
    1906          410 :     if (param.has_type ())
    1907              :       {
    1908          135 :         push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    1909          135 :         visit (param.get_type ());
    1910              :       }
    1911          410 :   });
    1912          410 : }
    1913              : 
    1914              : void
    1915           20 : TokenCollector::visit (WhereClause &rule)
    1916              : {
    1917              :   // Syntax:
    1918              :   //    where ( WhereClauseItem , )* WhereClauseItem ?
    1919              :   // WhereClauseItem :
    1920              :   //    LifetimeWhereClauseItem
    1921              :   //    | TypeBoundWhereClauseItem
    1922           20 :   describe_node (std::string ("WhereClause"), [this, &rule] () {
    1923           20 :     push (Rust::Token::make (WHERE, UNDEF_LOCATION));
    1924           20 :     newline ();
    1925           20 :     increment_indentation ();
    1926           20 :     visit_items_joined_by_separator (rule.get_items (), COMMA);
    1927           20 :     decrement_indentation ();
    1928           20 :   });
    1929           20 : }
    1930              : 
    1931              : void
    1932            0 : TokenCollector::visit (LifetimeWhereClauseItem &item)
    1933              : {
    1934              :   // Syntax:
    1935              :   //    Lifetime : LifetimeBounds
    1936              :   // LifetimeBounds :
    1937              :   //   ( Lifetime + )* Lifetime?
    1938              : 
    1939            0 :   describe_node (std::string ("LifetimeWhereClauseItem"), [this, &item] () {
    1940            0 :     visit (item.get_lifetime ());
    1941            0 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    1942            0 :     visit_items_joined_by_separator (item.get_lifetime_bounds (), PLUS);
    1943            0 :   });
    1944            0 : }
    1945              : 
    1946              : void
    1947           38 : TokenCollector::visit (TypeBoundWhereClauseItem &item)
    1948              : {
    1949              :   // Syntax:
    1950              :   //    ForLifetimes? Type : TypeParamBounds?
    1951              :   // TypeParamBounds :
    1952              :   //    TypeParamBound ( + TypeParamBound )* +?
    1953              :   // TypeParamBound :
    1954              :   //    Lifetime | TraitBound
    1955              : 
    1956           38 :   describe_node (std::string ("TypeBoundWhereClauseItem"), [this, &item] () {
    1957           38 :     if (item.has_for_lifetimes ())
    1958            0 :       visit (item.get_for_lifetimes ());
    1959              : 
    1960           38 :     visit (item.get_type ());
    1961              : 
    1962           38 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    1963           38 :     visit_items_joined_by_separator (item.get_type_param_bounds (), PLUS);
    1964           38 :   });
    1965           38 : }
    1966              : 
    1967              : void
    1968            0 : TokenCollector::visit (Module &module)
    1969              : {
    1970              :   //  Syntax:
    1971              :   //    mod IDENTIFIER ;
    1972              :   //     | mod IDENTIFIER {
    1973              :   //      InnerAttribute*
    1974              :   //      Item*
    1975              :   //    }
    1976            0 :   describe_node (std::string ("Module"), [this, &module] () {
    1977            0 :     visit_items_as_lines (module.get_outer_attrs ());
    1978            0 :     visit (module.get_visibility ());
    1979            0 :     auto name = module.get_name ().as_string ();
    1980            0 :     push (Rust::Token::make (MOD, module.get_locus ()));
    1981            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name)));
    1982              : 
    1983            0 :     if (module.get_kind () == Module::UNLOADED)
    1984              :       {
    1985            0 :         push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    1986            0 :         newline ();
    1987              :       }
    1988              :     else /* Module::LOADED */
    1989              :       {
    1990            0 :         push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION));
    1991            0 :         newline ();
    1992            0 :         increment_indentation ();
    1993              : 
    1994            0 :         visit_items_as_lines (module.get_inner_attrs ());
    1995            0 :         visit_items_as_lines (module.get_items ());
    1996              : 
    1997            0 :         decrement_indentation ();
    1998              : 
    1999            0 :         push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION));
    2000            0 :         newline ();
    2001              :       }
    2002            0 :   });
    2003            0 : }
    2004              : 
    2005              : void
    2006            0 : TokenCollector::visit (ExternCrate &crate)
    2007              : {
    2008            0 :   describe_node (std::string ("ExternCrate"), [this, &crate] () {
    2009            0 :     visit_items_as_lines (crate.get_outer_attrs ());
    2010            0 :     push (Rust::Token::make (EXTERN_KW, crate.get_locus ()));
    2011            0 :     push (Rust::Token::make (CRATE, UNDEF_LOCATION));
    2012            0 :     auto ref = crate.get_referenced_crate ();
    2013            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (ref)));
    2014            0 :     if (crate.has_as_clause ())
    2015              :       {
    2016            0 :         auto as_clause = crate.get_as_clause ();
    2017            0 :         push (Rust::Token::make (AS, UNDEF_LOCATION));
    2018            0 :         push (
    2019            0 :           Rust::Token::make_identifier (UNDEF_LOCATION, std::move (as_clause)));
    2020            0 :       }
    2021            0 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2022            0 :     newline ();
    2023            0 :   });
    2024            0 : }
    2025              : 
    2026              : void
    2027            0 : TokenCollector::visit (UseTreeGlob &use_tree)
    2028              : {
    2029            0 :   describe_node (std::string ("UseTreeGlob"), [this, &use_tree] () {
    2030            0 :     switch (use_tree.get_glob_type ())
    2031              :       {
    2032            0 :       case UseTreeGlob::PathType::PATH_PREFIXED:
    2033            0 :         {
    2034            0 :           auto path = use_tree.get_path ();
    2035            0 :           visit (path);
    2036            0 :           push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
    2037            0 :         }
    2038            0 :         break;
    2039            0 :       case UseTreeGlob::PathType::NO_PATH:
    2040            0 :         push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
    2041            0 :         break;
    2042              :       case UseTreeGlob::PathType::GLOBAL:
    2043              :         break;
    2044              :       }
    2045            0 :     push (Rust::Token::make (ASTERISK, UNDEF_LOCATION));
    2046            0 :   });
    2047            0 : }
    2048              : 
    2049              : void
    2050            0 : TokenCollector::visit (UseTreeList &use_tree)
    2051              : {
    2052            0 :   describe_node (std::string ("UseTreeList"), [this, &use_tree] () {
    2053            0 :     switch (use_tree.get_path_type ())
    2054              :       {
    2055            0 :       case UseTreeList::PathType::PATH_PREFIXED:
    2056            0 :         {
    2057            0 :           auto path = use_tree.get_path ();
    2058            0 :           visit (path);
    2059              : 
    2060            0 :           push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
    2061            0 :         }
    2062            0 :         break;
    2063            0 :       case UseTreeList::PathType::NO_PATH:
    2064            0 :         push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
    2065            0 :         break;
    2066              :       case UseTreeList::PathType::GLOBAL:
    2067              :         break;
    2068              :       }
    2069              : 
    2070            0 :     push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION));
    2071            0 :     if (use_tree.has_trees ())
    2072              :       {
    2073            0 :         visit_items_joined_by_separator (use_tree.get_trees (), COMMA);
    2074              :       }
    2075            0 :     push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION));
    2076            0 :   });
    2077            0 : }
    2078              : 
    2079              : void
    2080            0 : TokenCollector::visit (UseTreeRebind &use_tree)
    2081              : {
    2082            0 :   describe_node (std::string ("UseTreeRebind"), [this, &use_tree] () {
    2083            0 :     auto path = use_tree.get_path ();
    2084            0 :     visit (path);
    2085            0 :     switch (use_tree.get_new_bind_type ())
    2086              :       {
    2087            0 :       case UseTreeRebind::NewBindType::IDENTIFIER:
    2088            0 :         {
    2089            0 :           push (Rust::Token::make (AS, UNDEF_LOCATION));
    2090            0 :           auto id = use_tree.get_identifier ().as_string ();
    2091            0 :           push (Rust::Token::make_identifier (use_tree.get_locus (),
    2092              :                                               std::move (id)));
    2093            0 :         }
    2094            0 :         break;
    2095            0 :       case UseTreeRebind::NewBindType::WILDCARD:
    2096            0 :         push (Rust::Token::make (AS, UNDEF_LOCATION));
    2097            0 :         push (Rust::Token::make (UNDERSCORE, use_tree.get_locus ()));
    2098            0 :         break;
    2099              :       case UseTreeRebind::NewBindType::NONE:
    2100              :         break;
    2101              :       }
    2102            0 :   });
    2103            0 : }
    2104              : 
    2105              : void
    2106            0 : TokenCollector::visit (UseDeclaration &decl)
    2107              : {
    2108            0 :   describe_node (std::string ("UseDeclaration"), [this, &decl] () {
    2109            0 :     visit_items_as_lines (decl.get_outer_attrs ());
    2110            0 :     push (Rust::Token::make (USE, decl.get_locus ()));
    2111            0 :     visit (*decl.get_tree ());
    2112            0 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2113            0 :     newline ();
    2114            0 :   });
    2115            0 : }
    2116              : 
    2117              : void
    2118         1516 : TokenCollector::visit (Function &function)
    2119              : {
    2120              :   // Syntax:
    2121              :   //   FunctionQualifiers fn IDENTIFIER GenericParams?
    2122              :   //      ( FunctionParameters? )
    2123              :   //      FunctionReturnType? WhereClause?
    2124              :   //      ( BlockExpression | ; )
    2125         1516 :   describe_node (std::string ("Function"), [this, &function] () {
    2126         1516 :     visit_items_as_lines (function.get_outer_attrs ());
    2127              : 
    2128         1516 :     visit (function.get_visibility ());
    2129         1516 :     auto qualifiers = function.get_qualifiers ();
    2130         1516 :     visit (qualifiers);
    2131              : 
    2132         1516 :     push (Rust::Token::make (FN_KW, function.get_locus ()));
    2133         3032 :     auto name = function.get_function_name ().as_string ();
    2134         3032 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name)));
    2135         1516 :     if (function.has_generics ())
    2136           95 :       visit (function.get_generic_params ());
    2137              : 
    2138         1516 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2139              : 
    2140         1516 :     visit_items_joined_by_separator (function.get_function_params ());
    2141         1516 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2142              : 
    2143         1516 :     if (function.has_return_type ())
    2144              :       {
    2145         1098 :         push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION));
    2146         1098 :         visit (function.get_return_type ());
    2147              :       }
    2148              : 
    2149         1516 :     if (function.has_where_clause ())
    2150           20 :       visit (function.get_where_clause ());
    2151              : 
    2152         1516 :     if (function.has_body ())
    2153          823 :       visit (*function.get_definition ());
    2154              :     else
    2155         1386 :       push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2156         1516 :     newline ();
    2157         1516 :   });
    2158         1516 : }
    2159              : 
    2160              : void
    2161            0 : TokenCollector::visit (TypeAlias &type_alias)
    2162              : {
    2163              :   // Syntax:
    2164              :   // Visibility? type IDENTIFIER GenericParams? WhereClause? = Type;
    2165              : 
    2166              :   // Note: Associated types are handled by `AST::TraitItemType`.
    2167            0 :   describe_node (std::string ("TypeAlias"), [this, &type_alias] () {
    2168            0 :     visit_items_as_lines (type_alias.get_outer_attrs ());
    2169            0 :     if (type_alias.has_visibility ())
    2170            0 :       visit (type_alias.get_visibility ());
    2171            0 :     auto alias_name = type_alias.get_new_type_name ().as_string ();
    2172            0 :     push (Rust::Token::make (TYPE, type_alias.get_locus ()));
    2173            0 :     push (
    2174            0 :       Rust::Token::make_identifier (UNDEF_LOCATION, std::move (alias_name)));
    2175              : 
    2176            0 :     if (type_alias.has_generics ())
    2177            0 :       visit (type_alias.get_generic_params ());
    2178              : 
    2179            0 :     if (type_alias.has_where_clause ())
    2180            0 :       visit (type_alias.get_where_clause ());
    2181              : 
    2182            0 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    2183            0 :     visit (type_alias.get_type_aliased ());
    2184            0 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2185            0 :   });
    2186            0 : }
    2187              : 
    2188              : void
    2189            7 : TokenCollector::visit (StructStruct &struct_item)
    2190              : {
    2191            7 :   describe_node (std::string ("StructStruct"), [this, &struct_item] () {
    2192            7 :     visit_items_as_lines (struct_item.get_outer_attrs ());
    2193            7 :     if (struct_item.has_visibility ())
    2194            0 :       visit (struct_item.get_visibility ());
    2195           14 :     auto struct_name = struct_item.get_identifier ().as_string ();
    2196            7 :     push (Rust::Token::make (STRUCT_KW, struct_item.get_locus ()));
    2197            7 :     push (
    2198           14 :       Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name)));
    2199              : 
    2200            7 :     if (struct_item.has_generics ())
    2201            0 :       visit (struct_item.get_generic_params ());
    2202            7 :     if (struct_item.has_where_clause ())
    2203            0 :       visit (struct_item.get_where_clause ());
    2204            7 :     if (struct_item.is_unit_struct ())
    2205              :       {
    2206            0 :         push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2207            0 :         newline ();
    2208              :       }
    2209              :     else
    2210           14 :       visit_items_as_block (struct_item.get_fields (),
    2211              :                             {Rust::Token::make (COMMA, UNDEF_LOCATION)});
    2212            7 :   });
    2213            7 : }
    2214              : 
    2215              : void
    2216           22 : TokenCollector::visit (TupleStruct &tuple_struct)
    2217              : {
    2218           22 :   describe_node (std::string ("TupleStruct"), [this, &tuple_struct] () {
    2219           22 :     visit_items_as_lines (tuple_struct.get_outer_attrs ());
    2220           44 :     auto struct_name = tuple_struct.get_identifier ().as_string ();
    2221           22 :     push (Rust::Token::make (STRUCT_KW, tuple_struct.get_locus ()));
    2222           22 :     push (
    2223           44 :       Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name)));
    2224           22 :     if (tuple_struct.has_generics ())
    2225            0 :       visit (tuple_struct.get_generic_params ());
    2226           22 :     if (tuple_struct.has_where_clause ())
    2227            0 :       visit (tuple_struct.get_where_clause ());
    2228              : 
    2229           22 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2230           22 :     visit_items_joined_by_separator (tuple_struct.get_fields (), COMMA);
    2231           22 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2232           22 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2233           22 :     newline ();
    2234           22 :   });
    2235           22 : }
    2236              : 
    2237              : void
    2238            1 : TokenCollector::visit (EnumItem &item)
    2239              : {
    2240            1 :   describe_node (std::string ("EnumItem"), [this, &item] () {
    2241            1 :     visit_items_as_lines (item.get_outer_attrs ());
    2242            2 :     auto id = item.get_identifier ().as_string ();
    2243            2 :     push (Rust::Token::make_identifier (item.get_locus (), std::move (id)));
    2244            1 :   });
    2245            1 : }
    2246              : 
    2247              : void
    2248            2 : TokenCollector::visit (EnumItemTuple &item)
    2249              : {
    2250            2 :   describe_node (std::string ("EnumItemTuple"), [this, &item] () {
    2251            4 :     auto id = item.get_identifier ().as_string ();
    2252            4 :     push (Rust::Token::make_identifier (item.get_locus (), std::move (id)));
    2253            2 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2254            2 :     visit_items_joined_by_separator (item.get_tuple_fields (), COMMA);
    2255            4 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2256            2 :   });
    2257            2 : }
    2258              : 
    2259              : void
    2260            0 : TokenCollector::visit (EnumItemStruct &item)
    2261              : {
    2262            0 :   describe_node (std::string ("EnumItemStruct"), [this, &item] () {
    2263            0 :     auto id = item.get_identifier ().as_string ();
    2264            0 :     push (Rust::Token::make_identifier (item.get_locus (), std::move (id)));
    2265            0 :     visit_items_as_block (item.get_struct_fields (),
    2266              :                           {Rust::Token::make (COMMA, UNDEF_LOCATION)});
    2267            0 :   });
    2268            0 : }
    2269              : 
    2270              : void
    2271            0 : TokenCollector::visit (EnumItemDiscriminant &item)
    2272              : {
    2273            0 :   describe_node (std::string ("EnumItemDiscriminant"), [this, &item] () {
    2274            0 :     auto id = item.get_identifier ().as_string ();
    2275            0 :     push (Rust::Token::make_identifier (item.get_locus (), std::move (id)));
    2276            0 :     push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    2277            0 :     visit (item.get_expr ());
    2278            0 :   });
    2279            0 : }
    2280              : 
    2281              : void
    2282            2 : TokenCollector::visit (Enum &enumeration)
    2283              : {
    2284            2 :   describe_node (std::string ("Enum"), [this, &enumeration] () {
    2285            2 :     visit_items_as_lines (enumeration.get_outer_attrs ());
    2286            2 :     if (enumeration.has_visibility ())
    2287            0 :       visit (enumeration.get_visibility ());
    2288            2 :     push (Rust::Token::make (ENUM_KW, enumeration.get_locus ()));
    2289            4 :     auto id = enumeration.get_identifier ().as_string ();
    2290            2 :     push (
    2291            4 :       Rust::Token::make_identifier (enumeration.get_locus (), std::move (id)));
    2292            2 :     if (enumeration.has_generics ())
    2293            0 :       visit (enumeration.get_generic_params ());
    2294            2 :     if (enumeration.has_where_clause ())
    2295            0 :       visit (enumeration.get_where_clause ());
    2296              : 
    2297            4 :     visit_items_as_block (enumeration.get_variants (),
    2298              :                           {Rust::Token::make (COMMA, UNDEF_LOCATION)});
    2299            2 :   });
    2300            2 : }
    2301              : 
    2302              : void
    2303            0 : TokenCollector::visit (Union &union_item)
    2304              : {
    2305            0 :   describe_node (std::string ("Union"), [this, &union_item] () {
    2306            0 :     visit_items_as_lines (union_item.get_outer_attrs ());
    2307            0 :     auto id = union_item.get_identifier ().as_string ();
    2308            0 :     push (Rust::Token::make_identifier (union_item.get_locus (),
    2309            0 :                                         Values::WeakKeywords::UNION));
    2310            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2311              : 
    2312            0 :     if (union_item.has_generics ())
    2313            0 :       visit (union_item.get_generic_params ());
    2314              : 
    2315            0 :     if (union_item.has_where_clause ())
    2316            0 :       visit (union_item.get_where_clause ());
    2317              : 
    2318            0 :     visit_items_as_block (union_item.get_variants (),
    2319              :                           {Rust::Token::make (COMMA, UNDEF_LOCATION)});
    2320            0 :   });
    2321            0 : }
    2322              : 
    2323              : void
    2324            1 : TokenCollector::visit (ConstantItem &item)
    2325              : {
    2326            1 :   describe_node (std::string ("ConstantItem"), [this, &item] () {
    2327            1 :     visit_items_as_lines (item.get_outer_attrs ());
    2328            1 :     push (Rust::Token::make (CONST, item.get_locus ()));
    2329            1 :     if (item.is_unnamed ())
    2330              :       {
    2331            0 :         push (Rust::Token::make (UNDERSCORE, UNDEF_LOCATION));
    2332              :       }
    2333              :     else
    2334              :       {
    2335            2 :         push (Rust::Token::make_identifier (item.get_identifier ()));
    2336              :       }
    2337            1 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    2338            1 :     visit (item.get_type ());
    2339            1 :     if (item.has_expr ())
    2340              :       {
    2341            0 :         push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    2342            0 :         visit (item.get_expr ());
    2343              :       }
    2344            1 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2345            1 :   });
    2346            1 : }
    2347              : 
    2348              : void
    2349            1 : TokenCollector::visit (StaticItem &item)
    2350              : {
    2351            1 :   describe_node (std::string ("StaticItem"), [this, &item] () {
    2352            1 :     visit_items_as_lines (item.get_outer_attrs ());
    2353            1 :     push (Rust::Token::make (STATIC_KW, item.get_locus ()));
    2354            1 :     if (item.is_mutable ())
    2355            0 :       push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2356              : 
    2357            2 :     auto id = item.get_identifier ().as_string ();
    2358            2 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2359            1 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    2360              : 
    2361            1 :     visit (item.get_type ());
    2362              : 
    2363            1 :     if (item.has_expr ())
    2364              :       {
    2365            1 :         push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    2366            1 :         visit (item.get_expr ());
    2367              :       }
    2368            2 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2369            1 :   });
    2370            1 : }
    2371              : 
    2372              : void
    2373            0 : TokenCollector::visit_function_common (std::unique_ptr<Type> &return_type,
    2374              :                                        std::unique_ptr<BlockExpr> &block)
    2375              : {
    2376              :   // FIXME: This should format the `<vis> fn <name> ( [args] )` as well
    2377            0 :   if (return_type)
    2378              :     {
    2379            0 :       push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION));
    2380            0 :       visit (return_type);
    2381              :     }
    2382              : 
    2383            0 :   if (block)
    2384              :     {
    2385            0 :       visit (block);
    2386              :     }
    2387              :   else
    2388              :     {
    2389            0 :       push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2390            0 :       newline ();
    2391              :     }
    2392            0 : }
    2393              : 
    2394              : void
    2395          704 : TokenCollector::visit (SelfParam &param)
    2396              : {
    2397          704 :   describe_node (std::string ("SelfParam"), [this, &param] () {
    2398          704 :     if (param.get_has_ref ())
    2399              :       {
    2400          382 :         push (Rust::Token::make (AMP, UNDEF_LOCATION));
    2401          382 :         if (param.has_lifetime ())
    2402              :           {
    2403          382 :             auto lifetime = param.get_lifetime ();
    2404          382 :             visit (lifetime);
    2405          382 :           }
    2406          382 :         if (param.get_is_mut ())
    2407          242 :           push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2408              :       }
    2409          704 :     push (Rust::Token::make (SELF, UNDEF_LOCATION));
    2410          704 :     if (param.has_type ())
    2411              :       {
    2412            0 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
    2413            0 :         visit (param.get_type ());
    2414              :       }
    2415          704 :   });
    2416          704 : }
    2417              : 
    2418              : void
    2419          440 : TokenCollector::visit (TraitItemType &item)
    2420              : {
    2421          440 :   describe_node (std::string ("TraitItemType"), [this, &item] () {
    2422          440 :     visit_items_as_lines (item.get_outer_attrs ());
    2423          880 :     auto id = item.get_identifier ().as_string ();
    2424          440 :     indentation ();
    2425              : 
    2426          440 :     push (Rust::Token::make (TYPE, item.get_locus ()));
    2427          880 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2428          440 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2429          440 :     newline ();
    2430          440 :   });
    2431          440 : }
    2432              : 
    2433              : void
    2434         2057 : TokenCollector::visit (Trait &trait)
    2435              : {
    2436         2057 :   describe_node (std::string ("Trait"), [this, &trait] () {
    2437         3843 :     for (auto &attr : trait.get_outer_attrs ())
    2438              :       {
    2439         1786 :         visit (attr);
    2440         1786 :         newline ();
    2441         1786 :         indentation ();
    2442              :       }
    2443              : 
    2444         2057 :     visit (trait.get_visibility ());
    2445              : 
    2446         4114 :     auto id = trait.get_identifier ().as_string ();
    2447         2057 :     push (Rust::Token::make (TRAIT, trait.get_locus ()));
    2448         4114 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2449              : 
    2450         2057 :     if (trait.has_generics ())
    2451          291 :       visit (trait.get_generic_params ());
    2452         2057 :     if (!trait.get_type_param_bounds ().empty ())
    2453          382 :       push (Rust::Token::make ((COLON), trait.get_locus ()));
    2454         2057 :     visit_items_joined_by_separator (trait.get_type_param_bounds (), PLUS);
    2455              : 
    2456         2057 :     visit_items_as_block (trait.get_trait_items (), {});
    2457         2057 :   });
    2458         2057 : }
    2459              : 
    2460              : void
    2461            0 : TokenCollector::visit (InherentImpl &impl)
    2462              : {
    2463            0 :   describe_node (std::string ("InherentImpl"), [this, &impl] () {
    2464            0 :     visit_items_as_lines (impl.get_outer_attrs ());
    2465            0 :     push (Rust::Token::make (IMPL, impl.get_locus ()));
    2466            0 :     visit (impl.get_generic_params ());
    2467              : 
    2468            0 :     visit (impl.get_type ());
    2469              : 
    2470            0 :     if (impl.has_where_clause ())
    2471            0 :       visit (impl.get_where_clause ());
    2472              : 
    2473              :     // FIXME: Handle inner attributes
    2474              : 
    2475            0 :     visit_items_as_block (impl.get_impl_items (), {});
    2476            0 :   });
    2477            0 : }
    2478              : 
    2479              : void
    2480            2 : TokenCollector::visit (TraitImpl &impl)
    2481              : {
    2482            2 :   describe_node (std::string ("TraitImpl"), [this, &impl] () {
    2483            2 :     visit_items_as_lines (impl.get_outer_attrs ());
    2484            2 :     push (Rust::Token::make (IMPL, impl.get_locus ()));
    2485            2 :     visit (impl.get_generic_params ());
    2486            2 :     if (impl.is_exclam ())
    2487            0 :       push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
    2488            2 :     visit (impl.get_trait_path ());
    2489            2 :     push (Rust::Token::make (FOR, UNDEF_LOCATION));
    2490            2 :     visit (impl.get_type ());
    2491              : 
    2492            2 :     if (impl.has_where_clause ())
    2493            0 :       visit (impl.get_where_clause ());
    2494            2 :   });
    2495            2 :   visit_items_as_block (impl.get_impl_items ());
    2496            2 : }
    2497              : 
    2498              : void
    2499            0 : TokenCollector::visit (ExternalTypeItem &type)
    2500              : {
    2501            0 :   describe_node (std::string ("ExternalTypeItem"), [this, &type] () {
    2502            0 :     visit (type.get_visibility ());
    2503              : 
    2504            0 :     auto id = type.get_identifier ().as_string ();
    2505              : 
    2506            0 :     push (Rust::Token::make (TYPE, UNDEF_LOCATION));
    2507            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2508            0 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2509            0 :   });
    2510            0 : }
    2511              : 
    2512              : void
    2513            0 : TokenCollector::visit (ExternalStaticItem &item)
    2514              : {
    2515            0 :   describe_node (std::string ("ExternalStaticItem"), [this, &item] () {
    2516            0 :     auto id = item.get_identifier ().as_string ();
    2517            0 :     visit_items_as_lines (item.get_outer_attrs ());
    2518            0 :     if (item.has_visibility ())
    2519            0 :       visit (item.get_visibility ());
    2520            0 :     push (Rust::Token::make (STATIC_KW, item.get_locus ()));
    2521            0 :     if (item.is_mut ())
    2522            0 :       push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2523            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2524            0 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    2525            0 :     visit (item.get_type ());
    2526              :     // TODO: No expr ? The "(= Expression)?" part from the reference seems
    2527              :     // missing in the ast.
    2528            0 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2529            0 :   });
    2530            0 : }
    2531              : 
    2532              : void
    2533          627 : TokenCollector::visit (ExternBlock &block)
    2534              : {
    2535          627 :   describe_node (std::string ("ExternBlock"), [this, &block] () {
    2536          627 :     visit_items_as_lines (block.get_outer_attrs ());
    2537          627 :     push (Rust::Token::make (EXTERN_KW, block.get_locus ()));
    2538              : 
    2539          627 :     if (block.has_abi ())
    2540              :       {
    2541          627 :         auto abi = block.get_abi ();
    2542         1254 :         push (Rust::Token::make_string (UNDEF_LOCATION, std::move (abi)));
    2543          627 :       }
    2544              : 
    2545          627 :     visit_items_as_block (block.get_extern_items (), {});
    2546          627 :   });
    2547          627 : }
    2548              : 
    2549              : static std::pair<TokenId, TokenId>
    2550            5 : get_delimiters (DelimType delim)
    2551              : {
    2552            5 :   switch (delim)
    2553              :     {
    2554            5 :     case PARENS:
    2555            5 :       return {LEFT_PAREN, RIGHT_PAREN};
    2556            0 :     case SQUARE:
    2557            0 :       return {LEFT_SQUARE, RIGHT_SQUARE};
    2558            0 :     case CURLY:
    2559            0 :       return {LEFT_CURLY, RIGHT_CURLY};
    2560            0 :     default:
    2561            0 :       rust_unreachable ();
    2562              :     }
    2563              : }
    2564              : 
    2565              : void
    2566            0 : TokenCollector::visit (MacroMatchFragment &match)
    2567              : {
    2568            0 :   describe_node (std::string ("MacroMatchFragment"), [this, &match] () {
    2569            0 :     auto id = match.get_ident ().as_string ();
    2570            0 :     auto frag_spec = match.get_frag_spec ().as_string ();
    2571            0 :     push (Rust::Token::make (DOLLAR_SIGN, UNDEF_LOCATION));
    2572            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2573            0 :     push (Rust::Token::make (COLON, UNDEF_LOCATION));
    2574            0 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (frag_spec)));
    2575            0 :   });
    2576            0 : }
    2577              : 
    2578              : void
    2579            0 : TokenCollector::visit (MacroMatchRepetition &repetition)
    2580              : {
    2581            0 :   describe_node (std::string ("MacroMatchRepetition"), [this, &repetition] () {
    2582            0 :     push (Rust::Token::make (DOLLAR_SIGN, UNDEF_LOCATION));
    2583            0 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2584              : 
    2585            0 :     for (auto &match : repetition.get_matches ())
    2586              :       {
    2587            0 :         visit (match);
    2588              :       }
    2589              : 
    2590            0 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2591              : 
    2592            0 :     if (repetition.has_sep ())
    2593              :       {
    2594            0 :         push (Rust::Token::make (repetition.get_sep ()->get_id (),
    2595            0 :                                  repetition.get_sep ()->get_locus ()));
    2596              :       }
    2597            0 :     switch (repetition.get_op ())
    2598              :       {
    2599            0 :       case MacroMatchRepetition::ANY:
    2600            0 :         push (Rust::Token::make (ASTERISK, UNDEF_LOCATION));
    2601            0 :         break;
    2602            0 :       case MacroMatchRepetition::ONE_OR_MORE:
    2603            0 :         push (Rust::Token::make (PLUS, UNDEF_LOCATION));
    2604            0 :         break;
    2605            0 :       case MacroMatchRepetition::ZERO_OR_ONE:
    2606            0 :         push (Rust::Token::make (QUESTION_MARK, UNDEF_LOCATION));
    2607            0 :         break;
    2608              :       case MacroMatchRepetition::NONE:
    2609              :         break;
    2610              :       }
    2611            0 :   });
    2612            0 : }
    2613              : 
    2614              : void
    2615            5 : TokenCollector::visit (MacroMatcher &matcher)
    2616              : {
    2617            5 :   describe_node (std::string ("MacroMatcher"), [this, &matcher] () {
    2618            5 :     auto delimiters = get_delimiters (matcher.get_delim_type ());
    2619              : 
    2620            5 :     push (Rust::Token::make (delimiters.first, UNDEF_LOCATION));
    2621              : 
    2622            6 :     for (auto &item : matcher.get_matches ())
    2623              :       {
    2624            1 :         visit (item);
    2625              :       }
    2626              : 
    2627            5 :     push (Rust::Token::make (delimiters.second, UNDEF_LOCATION));
    2628            5 :   });
    2629            5 : }
    2630              : 
    2631              : void
    2632            5 : TokenCollector::visit (MacroRule &rule)
    2633              : {
    2634            5 :   describe_node (std::string ("MacroRule"), [this, &rule] () {
    2635            5 :     visit (rule.get_matcher ());
    2636            5 :     push (Rust::Token::make (MATCH_ARROW, rule.get_locus ()));
    2637            5 :     visit (rule.get_transcriber ().get_token_tree ());
    2638            5 :   });
    2639            5 : }
    2640              : 
    2641              : void
    2642            5 : TokenCollector::visit (MacroRulesDefinition &rules_def)
    2643              : {
    2644            5 :   describe_node (std::string ("MacroRulesDefinition"), [this, &rules_def] () {
    2645           10 :     for (auto &outer_attr : rules_def.get_outer_attrs ())
    2646            5 :       visit (outer_attr);
    2647              : 
    2648           10 :     auto rule_name = rules_def.get_rule_name ().as_string ();
    2649              : 
    2650           10 :     push (Rust::Token::make_identifier (rules_def.get_locus (),
    2651            5 :                                         Values::WeakKeywords::MACRO_RULES));
    2652            5 :     push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
    2653              : 
    2654           10 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (rule_name)));
    2655              : 
    2656           10 :     visit_items_as_block (rules_def.get_rules (),
    2657              :                           {Rust::Token::make (SEMICOLON, UNDEF_LOCATION)});
    2658            5 :   });
    2659            5 : }
    2660              : 
    2661              : void
    2662            0 : TokenCollector::visit (MacroInvocation &invocation)
    2663              : {
    2664            0 :   describe_node (std::string ("MacroInvocation"), [this, &invocation] () {
    2665            0 :     auto data = invocation.get_invoc_data ();
    2666            0 :     visit (data.get_path ());
    2667            0 :     push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
    2668            0 :     visit (data.get_delim_tok_tree ());
    2669            0 :     if (invocation.has_semicolon ())
    2670            0 :       push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    2671            0 :   });
    2672            0 : }
    2673              : 
    2674              : void
    2675            0 : TokenCollector::visit (MetaItemPath &item)
    2676              : {
    2677            0 :   describe_node (std::string ("MetaItemPath"), [this, &item] () {
    2678            0 :     auto path = item.to_path_item ();
    2679            0 :     visit (path);
    2680            0 :   });
    2681            0 : }
    2682              : 
    2683              : void
    2684            2 : TokenCollector::visit (MetaItemSeq &item)
    2685              : {
    2686            2 :   describe_node (std::string ("MetaItemSeq"), [this, &item] () {
    2687            2 :     visit (item.get_path ());
    2688              :     // TODO: Double check this, there is probably a mistake.
    2689            2 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2690            2 :     visit_items_joined_by_separator (item.get_seq (), COMMA);
    2691            2 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2692            2 :   });
    2693            2 : }
    2694              : 
    2695              : void
    2696            0 : TokenCollector::visit (MetaWord &word)
    2697              : {
    2698            0 :   describe_node (std::string ("MetaWord"), [this, &word] () {
    2699            0 :     auto id = word.get_ident ().as_string ();
    2700              : 
    2701            0 :     push (Rust::Token::make_identifier (word.get_locus (), std::move (id)));
    2702            0 :   });
    2703            0 : }
    2704              : 
    2705              : void
    2706            5 : TokenCollector::visit (MetaNameValueStr &name)
    2707              : {
    2708            5 :   describe_node (std::string ("MetaNameValueStr"), [this, &name] () {
    2709            5 :     auto pair = name.get_name_value_pair ();
    2710            5 :     auto id = std::get<0> (pair).as_string ();
    2711            5 :     auto value = std::get<1> (pair);
    2712              : 
    2713           10 :     push (Rust::Token::make_identifier (name.get_locus (), std::move (id)));
    2714            5 :     push (Rust::Token::make (EQUAL, name.get_locus ()));
    2715            5 :     push (Rust::Token::make (DOUBLE_QUOTE, UNDEF_LOCATION));
    2716           10 :     push (Rust::Token::make_identifier (name.get_locus (), std::move (value)));
    2717           10 :     push (Rust::Token::make (DOUBLE_QUOTE, UNDEF_LOCATION));
    2718            5 :   });
    2719            5 : }
    2720              : 
    2721              : void
    2722            0 : TokenCollector::visit (MetaListPaths &list)
    2723              : {
    2724            0 :   describe_node (std::string ("MetaListPath"), [this, &list] () {
    2725            0 :     auto id = list.get_ident ().as_string ();
    2726              : 
    2727            0 :     push (Rust::Token::make_identifier (list.get_locus (), std::move (id)));
    2728            0 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2729              : 
    2730            0 :     visit_items_joined_by_separator (list.get_paths (), COMMA);
    2731              : 
    2732            0 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2733            0 :   });
    2734            0 : }
    2735              : 
    2736              : void
    2737            0 : TokenCollector::visit (MetaListNameValueStr &list)
    2738              : {
    2739            0 :   describe_node (std::string ("MetaListNameValueStr"), [this, &list] () {
    2740            0 :     auto id = list.get_ident ().as_string ();
    2741              : 
    2742            0 :     push (Rust::Token::make_identifier (list.get_locus (), std::move (id)));
    2743            0 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    2744              : 
    2745            0 :     visit_items_joined_by_separator (list.get_values (), COMMA);
    2746              : 
    2747            0 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2748            0 :   });
    2749            0 : }
    2750              : 
    2751              : // rust-pattern.h
    2752              : void
    2753           30 : TokenCollector::visit (LiteralPattern &pattern)
    2754              : {
    2755           30 :   describe_node (std::string ("LiteralPattern"), [this, &pattern] () {
    2756           30 :     visit (pattern.get_literal (), pattern.get_locus ());
    2757           30 :   });
    2758           30 : }
    2759              : 
    2760              : void
    2761         2081 : TokenCollector::visit (IdentifierPattern &pattern)
    2762              : {
    2763         2081 :   describe_node (std::string ("IdentifierPattern"), [this, &pattern] () {
    2764         2081 :     if (pattern.get_is_ref ())
    2765              :       {
    2766            0 :         push (Rust::Token::make (REF, pattern.get_locus ()));
    2767              :       }
    2768         2081 :     if (pattern.get_is_mut ())
    2769              :       {
    2770          272 :         push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2771              :       }
    2772              : 
    2773         4162 :     auto id = pattern.get_ident ().as_string ();
    2774         4162 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2775              : 
    2776         2081 :     if (pattern.has_subpattern ())
    2777              :       {
    2778            0 :         push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION));
    2779            0 :         visit (pattern.get_subpattern ());
    2780              :       }
    2781         2081 :   });
    2782         2081 : }
    2783              : 
    2784              : void
    2785          121 : TokenCollector::visit (WildcardPattern &pattern)
    2786              : {
    2787          121 :   describe_node (std::string ("WildcardPattern"), [this, &pattern] () {
    2788          121 :     push (Rust::Token::make (UNDERSCORE, pattern.get_locus ()));
    2789          121 :   });
    2790          121 : }
    2791              : 
    2792              : void
    2793            0 : TokenCollector::visit (RestPattern &pattern)
    2794              : {
    2795            0 :   describe_node (std::string ("RestPattern"), [this, &pattern] () {
    2796            0 :     push (Rust::Token::make (DOT_DOT, pattern.get_locus ()));
    2797            0 :   });
    2798            0 : }
    2799              : 
    2800              : // void TokenCollector::visit(RangePatternBound& ){}
    2801              : 
    2802              : void
    2803            0 : TokenCollector::visit (RangePatternBoundLiteral &pattern)
    2804              : {
    2805            0 :   describe_node (std::string ("RangePatternBoundLiteral"), [this, &pattern] () {
    2806            0 :     if (pattern.get_has_minus ())
    2807              :       {
    2808            0 :         push (Rust::Token::make (MINUS, pattern.get_locus ()));
    2809              :       }
    2810            0 :     auto literal = pattern.get_literal ();
    2811            0 :     visit (literal);
    2812            0 :   });
    2813            0 : }
    2814              : 
    2815              : void
    2816            0 : TokenCollector::visit (RangePatternBoundPath &pattern)
    2817              : {
    2818            0 :   describe_node (std::string ("RangePatternBoundPath"),
    2819            0 :                  [this, &pattern] () { visit (pattern.get_path ()); });
    2820            0 : }
    2821              : 
    2822              : void
    2823            0 : TokenCollector::visit (RangePatternBoundQualPath &pattern)
    2824              : {
    2825            0 :   describe_node (std::string ("RangePatternBoundQualPath"),
    2826            0 :                  [this, &pattern] () {
    2827            0 :                    visit (pattern.get_qualified_path ());
    2828              :                  });
    2829            0 : }
    2830              : 
    2831              : void
    2832            0 : TokenCollector::visit (RangePattern &pattern)
    2833              : {
    2834            0 :   describe_node (std::string ("RangePattern"), [this, &pattern] () {
    2835            0 :     if (pattern.get_has_lower_bound () && pattern.get_has_upper_bound ())
    2836              :       {
    2837            0 :         visit (pattern.get_lower_bound ());
    2838            0 :         if (pattern.get_has_ellipsis_syntax ())
    2839            0 :           push (Rust::Token::make (ELLIPSIS, pattern.get_locus ()));
    2840              :         else
    2841            0 :           push (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ()));
    2842            0 :         visit (pattern.get_upper_bound ());
    2843              :       }
    2844            0 :     else if (pattern.get_has_lower_bound ())
    2845              :       {
    2846            0 :         visit (pattern.get_lower_bound ());
    2847            0 :         push (Rust::Token::make (DOT_DOT, pattern.get_locus ()));
    2848              :       }
    2849              :     else
    2850              :       {
    2851            0 :         push (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ()));
    2852            0 :         visit (pattern.get_upper_bound ());
    2853              :       }
    2854            0 :   });
    2855            0 : }
    2856              : 
    2857              : void
    2858            2 : TokenCollector::visit (ReferencePattern &pattern)
    2859              : 
    2860              : {
    2861            2 :   describe_node (std::string ("ReferencePattern"), [this, &pattern] () {
    2862            2 :     if (pattern.is_double_reference ())
    2863              :       {
    2864            2 :         push (Rust::Token::make (LOGICAL_AND, pattern.get_locus ()));
    2865              :       }
    2866              :     else
    2867              :       {
    2868            2 :         push (Rust::Token::make (AMP, pattern.get_locus ()));
    2869              :       }
    2870              : 
    2871            2 :     if (pattern.get_is_mut ())
    2872              :       {
    2873            0 :         push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2874              :       }
    2875              : 
    2876            2 :     visit (pattern.get_referenced_pattern ());
    2877            2 :   });
    2878            2 : }
    2879              : 
    2880              : // void TokenCollector::visit(StructPatternField& ){}
    2881              : 
    2882              : void
    2883           18 : TokenCollector::visit (StructPatternFieldTuplePat &pattern)
    2884              : {
    2885           18 :   describe_node (std::string ("StructPatternFieldTuplePat"), [this,
    2886              :                                                               &pattern] () {
    2887           18 :     visit_items_as_lines (pattern.get_outer_attrs ());
    2888           36 :     push (Rust::Token::make_int (pattern.get_locus (),
    2889           18 :                                  std::to_string (pattern.get_index ())));
    2890           18 :     push (Rust::Token::make (COLON, pattern.get_locus ()));
    2891           18 :     visit (pattern.get_index_pattern ());
    2892           18 :   });
    2893           18 : }
    2894              : 
    2895              : void
    2896            1 : TokenCollector::visit (StructPatternFieldIdentPat &pattern)
    2897              : {
    2898            1 :   describe_node (std::string ("StructPatternFieldIdentPat"), [this,
    2899              :                                                               &pattern] () {
    2900            1 :     visit_items_as_lines (pattern.get_outer_attrs ());
    2901              : 
    2902            1 :     auto id = pattern.get_identifier ().as_string ();
    2903            2 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2904              : 
    2905            1 :     push (Rust::Token::make (COLON, pattern.get_locus ()));
    2906              : 
    2907            1 :     visit (pattern.get_ident_pattern ());
    2908            1 :   });
    2909            1 : }
    2910              : 
    2911              : void
    2912            2 : TokenCollector::visit (StructPatternFieldIdent &pattern)
    2913              : {
    2914            2 :   describe_node (std::string ("StructPatternFieldIdent"), [this, &pattern] () {
    2915            2 :     visit_items_as_lines (pattern.get_outer_attrs ());
    2916            2 :     if (pattern.is_ref ())
    2917            0 :       push (Rust::Token::make (REF, UNDEF_LOCATION));
    2918            2 :     if (pattern.is_mut ())
    2919            4 :       push (Rust::Token::make (MUT, UNDEF_LOCATION));
    2920              : 
    2921            2 :     auto id = pattern.get_identifier ().as_string ();
    2922            4 :     push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
    2923            2 :   });
    2924            2 : }
    2925              : 
    2926              : void
    2927           12 : TokenCollector::visit (StructPattern &pattern)
    2928              : {
    2929           12 :   describe_node (std::string ("StructPattern"), [this, &pattern] () {
    2930           12 :     visit (pattern.get_path ());
    2931           12 :     push (Rust::Token::make (LEFT_CURLY, pattern.get_locus ()));
    2932           12 :     auto elems = pattern.get_struct_pattern_elems ();
    2933           12 :     if (elems.has_struct_pattern_fields ())
    2934              :       {
    2935           12 :         visit_items_joined_by_separator (elems.get_struct_pattern_fields ());
    2936           12 :         if (elems.has_rest ())
    2937              :           {
    2938            2 :             push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    2939            2 :             visit_items_as_lines (elems.get_etc_outer_attrs ());
    2940              :           }
    2941              :       }
    2942              :     else
    2943              :       {
    2944            0 :         visit_items_as_lines (elems.get_etc_outer_attrs ());
    2945              :       }
    2946              : 
    2947           24 :     push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION));
    2948           12 :   });
    2949           12 : }
    2950              : 
    2951              : // void TokenCollector::visit(TupleStructItems& ){}
    2952              : 
    2953              : void
    2954           27 : TokenCollector::visit (TupleStructItemsNoRest &pattern)
    2955              : {
    2956           27 :   describe_node (std::string ("TupleStructItemsNoRange"), [this, &pattern] () {
    2957           27 :     visit_items_joined_by_separator (pattern.get_patterns ());
    2958           27 :   });
    2959           27 : }
    2960              : 
    2961              : void
    2962            0 : TokenCollector::visit (TupleStructItemsHasRest &pattern)
    2963              : {
    2964            0 :   describe_node (std::string ("TupleStructItemsRange"), [this, &pattern] () {
    2965            0 :     for (auto &lower : pattern.get_lower_patterns ())
    2966              :       {
    2967            0 :         visit (lower);
    2968              :       }
    2969            0 :     push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
    2970            0 :     for (auto &upper : pattern.get_lower_patterns ())
    2971              :       {
    2972            0 :         visit (upper);
    2973              :       }
    2974            0 :   });
    2975            0 : }
    2976              : 
    2977              : void
    2978           27 : TokenCollector::visit (TupleStructPattern &pattern)
    2979              : {
    2980           27 :   describe_node (std::string ("TupleStructPattern"), [this, &pattern] () {
    2981           27 :     visit (pattern.get_path ());
    2982           27 :     push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ()));
    2983           27 :     visit (pattern.get_items ());
    2984           27 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    2985           27 :   });
    2986           27 : }
    2987              : 
    2988              : // void
    2989              : // TokenCollector::visit (TuplePatternItems &)
    2990              : // {}
    2991              : 
    2992              : void
    2993            5 : TokenCollector::visit (TuplePatternItemsNoRest &pattern)
    2994              : {
    2995            5 :   describe_node (std::string ("TuplePatternItemsMultiple"), [this,
    2996              :                                                              &pattern] () {
    2997            5 :     visit_items_joined_by_separator (pattern.get_patterns (), COMMA);
    2998            5 :   });
    2999            5 : }
    3000              : 
    3001              : void
    3002            0 : TokenCollector::visit (TuplePatternItemsHasRest &pattern)
    3003              : {
    3004            0 :   describe_node (std::string ("TuplePatternItemsRanged"), [this, &pattern] () {
    3005            0 :     for (auto &lower : pattern.get_lower_patterns ())
    3006              :       {
    3007            0 :         visit (lower);
    3008              :       }
    3009            0 :     push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
    3010            0 :     for (auto &upper : pattern.get_lower_patterns ())
    3011              :       {
    3012            0 :         visit (upper);
    3013              :       }
    3014            0 :   });
    3015            0 : }
    3016              : 
    3017              : void
    3018            5 : TokenCollector::visit (TuplePattern &pattern)
    3019              : {
    3020            5 :   describe_node (std::string ("TuplePattern"), [this, &pattern] () {
    3021            5 :     push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ()));
    3022            5 :     visit (pattern.get_items ());
    3023            5 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    3024            5 :   });
    3025            5 : }
    3026              : 
    3027              : void
    3028            1 : TokenCollector::visit (GroupedPattern &pattern)
    3029              : {
    3030            1 :   describe_node (std::string ("GroupedPattern"), [this, &pattern] () {
    3031            1 :     push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ()));
    3032            1 :     visit (pattern.get_pattern_in_parens ());
    3033            1 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    3034            1 :   });
    3035            1 : }
    3036              : 
    3037              : void
    3038            0 : TokenCollector::visit (SlicePatternItemsNoRest &items)
    3039              : {
    3040            0 :   visit_items_joined_by_separator (items.get_patterns (), COMMA);
    3041            0 : }
    3042              : 
    3043              : void
    3044            2 : TokenCollector::visit (SlicePatternItemsHasRest &items)
    3045              : {
    3046            2 :   if (!items.get_lower_patterns ().empty ())
    3047              :     {
    3048            1 :       visit_items_joined_by_separator (items.get_lower_patterns (), COMMA);
    3049            2 :       push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    3050              :     }
    3051              : 
    3052            2 :   push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
    3053              : 
    3054            2 :   if (!items.get_upper_patterns ().empty ())
    3055              :     {
    3056            1 :       push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    3057            1 :       visit_items_joined_by_separator (items.get_upper_patterns (), COMMA);
    3058              :     }
    3059            2 : }
    3060              : 
    3061              : void
    3062            2 : TokenCollector::visit (SlicePattern &pattern)
    3063              : {
    3064            2 :   describe_node (std::string ("SlicePattern"), [this, &pattern] () {
    3065            2 :     push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ()));
    3066            2 :     visit (pattern.get_items ());
    3067            2 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
    3068            2 :   });
    3069            2 : }
    3070              : 
    3071              : void
    3072            3 : TokenCollector::visit (AltPattern &pattern)
    3073              : {
    3074            3 :   describe_node (std::string ("AltPattern"), [this, &pattern] () {
    3075            3 :     visit_items_joined_by_separator (pattern.get_alts (), PIPE);
    3076            3 :   });
    3077            3 : }
    3078              : 
    3079              : // rust-stmt.h
    3080              : void
    3081            8 : TokenCollector::visit (EmptyStmt &)
    3082            8 : {}
    3083              : 
    3084              : void
    3085         1462 : TokenCollector::visit (LetStmt &stmt)
    3086              : {
    3087         1462 :   describe_node (std::string ("LetStmt"), [this, &stmt] () {
    3088         1462 :     push (Rust::Token::make (LET, stmt.get_locus ()));
    3089         1462 :     auto &pattern = stmt.get_pattern ();
    3090         1462 :     visit (pattern);
    3091              : 
    3092         1462 :     if (stmt.has_type ())
    3093              :       {
    3094          269 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
    3095          269 :         visit (stmt.get_type ());
    3096              :       }
    3097              : 
    3098         1462 :     if (stmt.has_type ())
    3099              :       {
    3100          269 :         push (Rust::Token::make (COLON, UNDEF_LOCATION));
    3101          269 :         visit (stmt.get_type ());
    3102              :       }
    3103              : 
    3104         1462 :     if (stmt.has_init_expr ())
    3105              :       {
    3106         1359 :         push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
    3107         1359 :         visit (stmt.get_init_expr ());
    3108              :       }
    3109              : 
    3110         1462 :     if (stmt.has_else_expr ())
    3111              :       {
    3112            0 :         push (Rust::Token::make (ELSE, UNDEF_LOCATION));
    3113            0 :         visit (stmt.get_else_expr ());
    3114              :       }
    3115              : 
    3116         1462 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    3117         1462 :   });
    3118         1462 : }
    3119              : 
    3120              : void
    3121          872 : TokenCollector::visit (ExprStmt &stmt)
    3122              : {
    3123          872 :   describe_node (std::string ("ExprStmt"), [this, &stmt] () {
    3124          872 :     visit (stmt.get_expr ());
    3125              : 
    3126          872 :     if (stmt.is_semicolon_followed ())
    3127         1280 :       push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    3128          872 :   });
    3129          872 : }
    3130              : 
    3131              : // rust-type.h
    3132              : void
    3133          426 : TokenCollector::visit (TraitBound &bound)
    3134              : {
    3135              :   // Syntax:
    3136              :   //      ?? ForLifetimes? TypePath
    3137              :   //   | ( ?? ForLifetimes? TypePath )
    3138          426 :   describe_node (std::string ("TraitBound"), [this, &bound] () {
    3139          426 :     if (bound.has_opening_question_mark ())
    3140           78 :       push (Rust::Token::make (QUESTION_MARK, bound.get_locus ()));
    3141              : 
    3142          426 :     if (bound.has_for_lifetimes ())
    3143            0 :       visit (bound.get_for_lifetimes ());
    3144              : 
    3145          426 :     visit (bound.get_type_path ());
    3146          426 :   });
    3147          426 : }
    3148              : 
    3149              : void
    3150            0 : TokenCollector::visit (ImplTraitType &type)
    3151              : {
    3152              :   // Syntax:
    3153              :   //    impl TypeParamBounds
    3154              :   // TypeParamBounds :
    3155              :   //    TypeParamBound ( + TypeParamBound )* +?
    3156            0 :   describe_node (std::string ("ImplTraitType"), [this, &type] () {
    3157            0 :     push (Rust::Token::make (IMPL, type.get_locus ()));
    3158            0 :     visit_items_joined_by_separator (type.get_type_param_bounds (), PLUS);
    3159            0 :   });
    3160            0 : }
    3161              : 
    3162              : void
    3163            0 : TokenCollector::visit (TraitObjectType &type)
    3164              : {
    3165              :   // Syntax:
    3166              :   //   dyn? TypeParamBounds
    3167              :   // TypeParamBounds :
    3168              :   //   TypeParamBound ( + TypeParamBound )* +?
    3169            0 :   describe_node (std::string ("TraiObjectType"), [this, &type] () {
    3170            0 :     if (type.is_dyn ())
    3171            0 :       push (Rust::Token::make (DYN, type.get_locus ()));
    3172            0 :     visit_items_joined_by_separator (type.get_type_param_bounds (), PLUS);
    3173            0 :   });
    3174            0 : }
    3175              : 
    3176              : void
    3177            3 : TokenCollector::visit (ParenthesisedType &type)
    3178              : {
    3179              :   // Syntax:
    3180              :   //    ( Type )
    3181            3 :   describe_node (std::string ("ParenthesisedType"), [this, &type] () {
    3182            3 :     push (Rust::Token::make (LEFT_PAREN, type.get_locus ()));
    3183            3 :     visit (type.get_type_in_parens ());
    3184            3 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    3185            3 :   });
    3186            3 : }
    3187              : 
    3188              : void
    3189            0 : TokenCollector::visit (ImplTraitTypeOneBound &type)
    3190              : {
    3191              :   // Syntax:
    3192              :   //    impl TraitBound
    3193              : 
    3194            0 :   describe_node (std::string ("ImplTraitTypeOneBound"), [this, &type] () {
    3195            0 :     push (Rust::Token::make (IMPL, type.get_locus ()));
    3196            0 :     visit (type.get_trait_bound ());
    3197            0 :   });
    3198            0 : }
    3199              : 
    3200              : void
    3201          110 : TokenCollector::visit (TraitObjectTypeOneBound &type)
    3202              : {
    3203              :   // Syntax:
    3204              :   //    dyn? TraitBound
    3205          110 :   describe_node (std::string ("TraitObjectTypeOneBound"), [this, &type] () {
    3206          110 :     if (type.is_dyn ())
    3207          220 :       push (Rust::Token::make (DYN, type.get_locus ()));
    3208          110 :     visit (type.get_trait_bound ());
    3209          110 :   });
    3210          110 : }
    3211              : 
    3212              : void
    3213           27 : TokenCollector::visit (TupleType &type)
    3214              : {
    3215              :   // Syntax:
    3216              :   //   ( )
    3217              :   //   | ( ( Type , )+ Type? )
    3218              : 
    3219           27 :   describe_node (std::string ("TupleType"), [this, &type] () {
    3220           27 :     push (Rust::Token::make (LEFT_PAREN, type.get_locus ()));
    3221           27 :     visit_items_joined_by_separator (type.get_elems (), COMMA);
    3222           27 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    3223           27 :   });
    3224           27 : }
    3225              : 
    3226              : void
    3227            0 : TokenCollector::visit (NeverType &type)
    3228              : {
    3229              :   // Syntax:
    3230              :   //  !
    3231              : 
    3232            0 :   describe_node (std::string ("NeverType"), [this, &type] () {
    3233            0 :     push (Rust::Token::make (EXCLAM, type.get_locus ()));
    3234            0 :   });
    3235            0 : }
    3236              : 
    3237              : void
    3238          275 : TokenCollector::visit (RawPointerType &type)
    3239              : {
    3240              :   // Syntax:
    3241              :   //    * ( mut | const ) TypeNoBounds
    3242          275 :   describe_node (std::string ("RawPointerType"), [this, &type] () {
    3243          275 :     push (Rust::Token::make (ASTERISK, type.get_locus ()));
    3244          275 :     if (type.get_pointer_type () == RawPointerType::MUT)
    3245           30 :       push (Rust::Token::make (MUT, UNDEF_LOCATION));
    3246              :     else /* RawPointerType::CONST */
    3247          520 :       push (Rust::Token::make (CONST, UNDEF_LOCATION));
    3248              : 
    3249          275 :     visit (type.get_type_pointed_to ());
    3250          275 :   });
    3251          275 : }
    3252              : 
    3253              : void
    3254          686 : TokenCollector::visit (ReferenceType &type)
    3255              : {
    3256              :   // Syntax:
    3257              :   //    & Lifetime? mut? TypeNoBounds
    3258          686 :   describe_node (std::string ("ReferenceType"), [this, &type] () {
    3259          686 :     push (Rust::Token::make (AMP, type.get_locus ()));
    3260              : 
    3261          686 :     if (type.has_lifetime ())
    3262              :       {
    3263          686 :         visit (type.get_lifetime ());
    3264              :       }
    3265              : 
    3266          686 :     if (type.get_has_mut ())
    3267          124 :       push (Rust::Token::make (MUT, UNDEF_LOCATION));
    3268              : 
    3269          686 :     visit (type.get_type_referenced ());
    3270          686 :   });
    3271          686 : }
    3272              : 
    3273              : void
    3274           26 : TokenCollector::visit (ArrayType &type)
    3275              : {
    3276              :   // Syntax:
    3277              :   //    [type Type ; Expression ]
    3278           26 :   describe_node (std::string ("ArrayType"), [this, &type] () {
    3279           26 :     push (Rust::Token::make (LEFT_SQUARE, type.get_locus ()));
    3280           26 :     visit (type.get_elem_type ());
    3281           26 :     push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
    3282           26 :     visit (type.get_size_expr ());
    3283           26 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
    3284           26 :   });
    3285           26 : }
    3286              : 
    3287              : void
    3288            5 : TokenCollector::visit (SliceType &type)
    3289              : {
    3290              :   // Syntax:
    3291              :   //    [type Type ]
    3292              : 
    3293            5 :   describe_node (std::string ("SliceType"), [this, &type] () {
    3294            5 :     push (Rust::Token::make (LEFT_SQUARE, type.get_locus ()));
    3295            5 :     visit (type.get_elem_type ());
    3296            5 :     push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
    3297            5 :   });
    3298            5 : }
    3299              : 
    3300              : void
    3301            9 : TokenCollector::visit (InferredType &type)
    3302              : {
    3303              :   // Syntax:
    3304              :   //    _
    3305            9 :   describe_node (std::string ("InferredType"), [this, &type] () {
    3306            9 :     push (Rust::Token::make (UNDERSCORE, type.get_locus ()));
    3307            9 :   });
    3308            9 : }
    3309              : 
    3310              : void
    3311            2 : TokenCollector::visit (BareFunctionType &type)
    3312              : {
    3313              :   // Syntax:
    3314              :   //    ForLifetimes? FunctionTypeQualifiers fn
    3315              :   //      ( FunctionParametersMaybeNamedVariadic? )
    3316              :   //      BareFunctionReturnType?
    3317              :   //
    3318              :   //    BareFunctionReturnType:
    3319              :   //      -> TypeNoBounds
    3320              :   //
    3321              :   //    FunctionParametersMaybeNamedVariadic :
    3322              :   //      MaybeNamedFunctionParameters |
    3323              :   //      MaybeNamedFunctionParametersVariadic
    3324              :   //
    3325              :   //    MaybeNamedFunctionParameters :
    3326              :   //      MaybeNamedParam ( , MaybeNamedParam )* ,?
    3327              :   //
    3328              :   //    MaybeNamedFunctionParametersVariadic :
    3329              :   //      ( MaybeNamedParam , )* MaybeNamedParam , OuterAttribute* ...
    3330            2 :   describe_node (std::string ("BareFunctionType"), [this, &type] () {
    3331            2 :     if (type.has_for_lifetimes ())
    3332            0 :       visit (type.get_for_lifetimes ());
    3333              : 
    3334            2 :     visit (type.get_function_qualifiers ());
    3335              : 
    3336            2 :     push (Rust::Token::make (FN_KW, type.get_locus ()));
    3337            2 :     push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
    3338              : 
    3339            2 :     visit_items_joined_by_separator (type.get_function_params (), COMMA);
    3340              : 
    3341            2 :     if (type.is_variadic ())
    3342              :       {
    3343            0 :         push (Rust::Token::make (COMMA, UNDEF_LOCATION));
    3344            0 :         for (auto &item : type.get_variadic_attr ())
    3345              :           {
    3346            0 :             visit (item);
    3347              :           }
    3348            0 :         push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
    3349              :       }
    3350              : 
    3351            2 :     push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
    3352              : 
    3353            2 :     if (type.has_return_type ())
    3354              :       {
    3355            0 :         push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION));
    3356            0 :         visit (type.get_return_type ());
    3357              :       }
    3358            2 :   });
    3359            2 : }
    3360              : 
    3361              : void
    3362            0 : TokenCollector::visit (AST::FormatArgs &fmt)
    3363              : {
    3364            0 :   push (Rust::Token::make_identifier (fmt.get_locus (), "format_args"));
    3365            0 :   push (Rust::Token::make (EXCLAM, fmt.get_locus ()));
    3366            0 :   push (Rust::Token::make (LEFT_PAREN, fmt.get_locus ()));
    3367              : 
    3368            0 :   std::string reconstructed_template = "\"";
    3369            0 :   const auto &template_pieces = fmt.get_template ();
    3370              : 
    3371            0 :   for (const auto &piece : template_pieces.get_pieces ())
    3372              :     {
    3373            0 :       if (piece.tag == Fmt::ffi::Piece::Tag::String)
    3374              :         {
    3375            0 :           std::string literal = piece.string._0.to_string ();
    3376            0 :           for (char c : literal)
    3377              :             {
    3378            0 :               if (c == '"' || c == '\\')
    3379              :                 {
    3380            0 :                   reconstructed_template += '\\';
    3381              :                 }
    3382            0 :               else if (c == '\n')
    3383              :                 {
    3384            0 :                   reconstructed_template += "\\n";
    3385            0 :                   continue;
    3386              :                 }
    3387            0 :               else if (c == '\r')
    3388              :                 {
    3389            0 :                   reconstructed_template += "\\r";
    3390            0 :                   continue;
    3391              :                 }
    3392            0 :               else if (c == '\t')
    3393              :                 {
    3394            0 :                   reconstructed_template += "\\t";
    3395            0 :                   continue;
    3396              :                 }
    3397            0 :               reconstructed_template += c;
    3398              :             }
    3399            0 :         }
    3400            0 :       else if (piece.tag == Fmt::ffi::Piece::Tag::NextArgument)
    3401              :         {
    3402            0 :           reconstructed_template += "{";
    3403              : 
    3404            0 :           const auto &argument = piece.next_argument._0;
    3405            0 :           const auto &position = argument.position;
    3406              : 
    3407            0 :           switch (position.tag)
    3408              :             {
    3409              :             case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs:
    3410              :               break;
    3411            0 :             case Fmt::ffi::Position::Tag::ArgumentIs:
    3412            0 :               reconstructed_template
    3413            0 :                 += std::to_string (position.argument_is._0);
    3414            0 :               break;
    3415            0 :             case Fmt::ffi::Position::Tag::ArgumentNamed:
    3416            0 :               reconstructed_template += position.argument_named._0.to_string ();
    3417            0 :               break;
    3418              :             }
    3419              : 
    3420              :           // Add format specifiers if any (like :?, :x, etc.)
    3421            0 :           const auto &format_spec = argument.format;
    3422              : 
    3423            0 :           bool has_format_spec = false;
    3424            0 :           std::string format_part;
    3425              : 
    3426              :           // For now, skipping the complex format specifications that
    3427              :           // use FFIOpt since FFIOpt::get_opt() has a bug.
    3428              : 
    3429              :           // Alignment
    3430            0 :           if (format_spec.align != Fmt::ffi::Alignment::AlignUnknown)
    3431              :             {
    3432            0 :               has_format_spec = true;
    3433            0 :               switch (format_spec.align)
    3434              :                 {
    3435            0 :                 case Fmt::ffi::Alignment::AlignLeft:
    3436            0 :                   format_part += "<";
    3437            0 :                   break;
    3438            0 :                 case Fmt::ffi::Alignment::AlignRight:
    3439            0 :                   format_part += ">";
    3440            0 :                   break;
    3441            0 :                 case Fmt::ffi::Alignment::AlignCenter:
    3442            0 :                   format_part += "^";
    3443            0 :                   break;
    3444              :                 case Fmt::ffi::Alignment::AlignUnknown:
    3445              :                   break;
    3446              :                 }
    3447              :             }
    3448              : 
    3449              :           // Alternate flag
    3450            0 :           if (format_spec.alternate)
    3451              :             {
    3452            0 :               has_format_spec = true;
    3453            0 :               format_part += "#";
    3454              :             }
    3455              : 
    3456              :           // Zero pad flag
    3457            0 :           if (format_spec.zero_pad)
    3458              :             {
    3459            0 :               has_format_spec = true;
    3460            0 :               format_part += "0";
    3461              :             }
    3462              : 
    3463              :           // Width
    3464            0 :           if (format_spec.width.tag != Fmt::ffi::Count::Tag::CountImplied)
    3465              :             {
    3466            0 :               has_format_spec = true;
    3467            0 :               switch (format_spec.width.tag)
    3468              :                 {
    3469            0 :                 case Fmt::ffi::Count::Tag::CountIs:
    3470            0 :                   format_part += std::to_string (format_spec.width.count_is._0);
    3471            0 :                   break;
    3472            0 :                 case Fmt::ffi::Count::Tag::CountIsParam:
    3473            0 :                   format_part
    3474            0 :                     += std::to_string (format_spec.width.count_is_param._0)
    3475            0 :                        + "$";
    3476            0 :                   break;
    3477            0 :                 case Fmt::ffi::Count::Tag::CountIsName:
    3478            0 :                   format_part
    3479            0 :                     += format_spec.width.count_is_name._0.to_string () + "$";
    3480            0 :                   break;
    3481            0 :                 case Fmt::ffi::Count::Tag::CountIsStar:
    3482            0 :                   format_part += "*";
    3483            0 :                   break;
    3484              :                 case Fmt::ffi::Count::Tag::CountImplied:
    3485              :                   break;
    3486              :                 }
    3487              :             }
    3488              : 
    3489              :           // Precision
    3490            0 :           if (format_spec.precision.tag != Fmt::ffi::Count::Tag::CountImplied)
    3491              :             {
    3492            0 :               has_format_spec = true;
    3493            0 :               format_part += ".";
    3494            0 :               switch (format_spec.precision.tag)
    3495              :                 {
    3496            0 :                 case Fmt::ffi::Count::Tag::CountIs:
    3497            0 :                   format_part
    3498            0 :                     += std::to_string (format_spec.precision.count_is._0);
    3499            0 :                   break;
    3500            0 :                 case Fmt::ffi::Count::Tag::CountIsParam:
    3501            0 :                   format_part
    3502            0 :                     += std::to_string (format_spec.precision.count_is_param._0)
    3503            0 :                        + "$";
    3504            0 :                   break;
    3505            0 :                 case Fmt::ffi::Count::Tag::CountIsName:
    3506            0 :                   format_part
    3507            0 :                     += format_spec.precision.count_is_name._0.to_string ()
    3508            0 :                        + "$";
    3509            0 :                   break;
    3510            0 :                 case Fmt::ffi::Count::Tag::CountIsStar:
    3511            0 :                   format_part += "*";
    3512            0 :                   break;
    3513              :                 case Fmt::ffi::Count::Tag::CountImplied:
    3514              :                   break;
    3515              :                 }
    3516              :             }
    3517              : 
    3518              :           // Type/trait (like ?, x, X, etc.)
    3519            0 :           std::string type_str = format_spec.ty.to_string ();
    3520            0 :           if (!type_str.empty ())
    3521              :             {
    3522            0 :               has_format_spec = true;
    3523            0 :               format_part += type_str;
    3524              :             }
    3525              : 
    3526              :           // Add the format specification if any
    3527            0 :           if (has_format_spec)
    3528              :             {
    3529            0 :               reconstructed_template += ":";
    3530            0 :               reconstructed_template += format_part;
    3531              :             }
    3532              : 
    3533            0 :           reconstructed_template += "}";
    3534              :         }
    3535              :     }
    3536            0 :   reconstructed_template += "\"";
    3537              : 
    3538            0 :   push (Rust::Token::make_string (fmt.get_locus (), reconstructed_template));
    3539              : 
    3540              :   // Visit format arguments if any exist
    3541            0 :   auto &arguments = fmt.get_arguments ();
    3542            0 :   if (!arguments.empty ())
    3543              :     {
    3544            0 :       push (Rust::Token::make (COMMA, fmt.get_locus ()));
    3545              : 
    3546            0 :       auto &args = arguments.get_args ();
    3547            0 :       for (size_t i = 0; i < args.size (); ++i)
    3548              :         {
    3549            0 :           if (i > 0)
    3550              :             {
    3551            0 :               push (Rust::Token::make (COMMA, fmt.get_locus ()));
    3552              :             }
    3553              : 
    3554            0 :           auto kind = args[i].get_kind ();
    3555              : 
    3556              :           // Handle named arguments: name = expr
    3557            0 :           if (kind.kind == FormatArgumentKind::Kind::Named)
    3558              :             {
    3559            0 :               auto ident = kind.get_ident ().as_string ();
    3560            0 :               push (Rust::Token::make_identifier (fmt.get_locus (),
    3561              :                                                   std::move (ident)));
    3562            0 :               push (Rust::Token::make (EQUAL, fmt.get_locus ()));
    3563            0 :             }
    3564              :           // Note: Captured arguments are handled implicitly in the
    3565              :           // template reconstruction They don't need explicit "name ="
    3566              :           // syntax in the reconstructed macro call
    3567              : 
    3568            0 :           auto &expr = args[i].get_expr ();
    3569            0 :           expr.accept_vis (*this);
    3570            0 :         }
    3571              :     }
    3572              : 
    3573            0 :   push (Rust::Token::make (RIGHT_PAREN, fmt.get_locus ()));
    3574            0 : }
    3575              : 
    3576              : void
    3577            0 : TokenCollector::visit (AST::OffsetOf &offset_of)
    3578              : {
    3579            0 :   auto loc = offset_of.get_locus ();
    3580              : 
    3581            0 :   push (Rust::Token::make_identifier (loc, "offset_of"));
    3582            0 :   push (Rust::Token::make (EXCLAM, loc));
    3583            0 :   push (Rust::Token::make (LEFT_PAREN, loc));
    3584              : 
    3585            0 :   visit (offset_of.get_type ());
    3586              : 
    3587            0 :   push (Rust::Token::make (COMMA, loc));
    3588              : 
    3589            0 :   push (Rust::Token::make_identifier (offset_of.get_field ()));
    3590              : 
    3591            0 :   push (Rust::Token::make (RIGHT_PAREN, loc));
    3592            0 : }
    3593              : 
    3594              : } // namespace AST
    3595              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.