LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-ast-collector.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 58.8 % 2257 1327
Test Date: 2026-03-28 14:25:54 Functions: 69.4 % 372 258
Legend: Lines:     hit not hit

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