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