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