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