// Copyright (C) 2020-2025 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. #include "rust-ast-collector.h" #include "rust-ast.h" #include "rust-diagnostics.h" #include "rust-item.h" #include "rust-keyword-values.h" #include "rust-token.h" namespace Rust { namespace AST { std::vector<TokenPtr> TokenCollector::collect_tokens () const { std::vector<TokenPtr> result; for (auto item : tokens) { if (item.get_kind () == CollectItem::Kind::Token) { result.emplace_back (item.get_token ()); } } return result; } std::vector<CollectItem> TokenCollector::collect () const { return tokens; } void TokenCollector::visit (AST::Crate &crate) { visit_items_as_lines (crate.inner_attrs); visit_items_as_lines (crate.items); } void TokenCollector::visit (AST::Item &item) { item.accept_vis (*this); } void TokenCollector::trailing_comma () { if (output_trailing_commas) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); } } void TokenCollector::newline () { tokens.push_back ({CollectItem::Kind::Newline}); } void TokenCollector::indentation () { tokens.push_back ({indent_level}); } void TokenCollector::increment_indentation () { indent_level++; } void TokenCollector::decrement_indentation () { rust_assert (indent_level != 0); indent_level--; } void TokenCollector::comment (std::string comment) { tokens.push_back ({comment}); } void TokenCollector::visit (Visitable &v) { v.accept_vis (*this); } void TokenCollector::visit (FunctionParam ¶m) { visit_items_as_lines (param.get_outer_attrs ()); if (!param.is_variadic ()) { visit (param.get_pattern ()); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (param.get_type ()); } else { if (param.has_name ()) { visit (param.get_pattern ()); push (Rust::Token::make (COLON, UNDEF_LOCATION)); } push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); } } void TokenCollector::visit (VariadicParam ¶m) { if (param.has_pattern ()) { visit (param.get_pattern ()); push (Rust::Token::make (COLON, UNDEF_LOCATION)); } push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); } void TokenCollector::visit (Attribute &attrib) { push (Rust::Token::make (HASH, attrib.get_locus ())); if (attrib.is_inner_attribute ()) push (Rust::Token::make (EXCLAM, UNDEF_LOCATION)); push (Rust::Token::make (LEFT_SQUARE, UNDEF_LOCATION)); visit (attrib.get_path ()); if (attrib.has_attr_input ()) { switch (attrib.get_attr_input ().get_attr_input_type ()) { case AST::AttrInput::AttrInputType::LITERAL: { visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ())); break; } case AST::AttrInput::AttrInputType::MACRO: { visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ())); break; } case AST::AttrInput::AttrInputType::META_ITEM: { visit (static_cast<AttrInputMetaItemContainer &> ( attrib.get_attr_input ())); break; } case AST::AttrInput::AttrInputType::TOKEN_TREE: { visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ())); break; } default: rust_unreachable (); } } push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (SimplePath &path) { if (path.has_opening_scope_resolution ()) { push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); } visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } void TokenCollector::visit (SimplePathSegment &segment) { auto name = segment.get_segment_name (); if (segment.is_crate_path_seg ()) { push (Rust::Token::make (CRATE, segment.get_locus ())); } else if (segment.is_super_path_seg ()) { push (Rust::Token::make (SUPER, segment.get_locus ())); } else if (segment.is_lower_self_seg ()) { push (Rust::Token::make (SELF, segment.get_locus ())); } else if (segment.is_big_self ()) { push (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); } else { push ( Rust::Token::make_identifier (segment.get_locus (), std::move (name))); } } void TokenCollector::visit (Visibility &vis) { switch (vis.get_vis_type ()) { case Visibility::PUB: push (Rust::Token::make (PUB, vis.get_locus ())); break; case Visibility::PUB_CRATE: push (Rust::Token::make (PUB, vis.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (CRATE, UNDEF_LOCATION)); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); break; case Visibility::PUB_SELF: push (Rust::Token::make (PUB, vis.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (SELF, UNDEF_LOCATION)); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); break; case Visibility::PUB_SUPER: push (Rust::Token::make (PUB, vis.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (SUPER, UNDEF_LOCATION)); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); break; case Visibility::PUB_IN_PATH: push (Rust::Token::make (PUB, vis.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (IN, UNDEF_LOCATION)); visit (vis.get_path ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); break; case Visibility::PRIV: break; } } void TokenCollector::visit (NamedFunctionParam ¶m) { auto name = param.get_name (); if (!param.is_variadic ()) { push ( Rust::Token::make_identifier (param.get_locus (), std::move (name))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (param.get_type ()); } else { if (name != "") { push (Rust::Token::make_identifier (param.get_locus (), std::move (name))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); } push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); } } void TokenCollector::visit (std::vector<std::unique_ptr<GenericParam>> ¶ms) { push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION)); visit_items_joined_by_separator (params, COMMA); push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION)); } void TokenCollector::visit (TupleField &field) { for (auto attr : field.get_outer_attrs ()) { visit (attr); } visit (field.get_visibility ()); visit (field.get_field_type ()); } void TokenCollector::visit (StructField &field) { for (auto attr : field.get_outer_attrs ()) { visit (attr); } visit (field.get_visibility ()); auto name = field.get_field_name ().as_string (); push (Rust::Token::make_identifier (field.get_locus (), std::move (name))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (field.get_field_type ()); } void TokenCollector::visit (std::vector<LifetimeParam> &for_lifetimes) { push (Rust::Token::make (FOR, UNDEF_LOCATION)); push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION)); visit_items_joined_by_separator (for_lifetimes, COMMA); push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION)); } void TokenCollector::visit (FunctionQualifiers &qualifiers) { // Syntax: // `const`? `async`? `unsafe`? (`extern` Abi?)? // unsafe? (extern Abi?)? if (qualifiers.is_async ()) push (Rust::Token::make (ASYNC, qualifiers.get_locus ())); if (qualifiers.is_const ()) push (Rust::Token::make (CONST, qualifiers.get_locus ())); if (qualifiers.is_unsafe ()) push (Rust::Token::make (UNSAFE, qualifiers.get_locus ())); if (qualifiers.is_extern ()) { push (Rust::Token::make (EXTERN_KW, qualifiers.get_locus ())); if (qualifiers.has_abi ()) { push (Rust::Token::make_string (UNDEF_LOCATION, qualifiers.get_extern_abi ())); } } } void TokenCollector::visit (MaybeNamedParam ¶m) { // Syntax: // OuterAttribute* ( ( IDENTIFIER | _ ) : )? Type for (auto attr : param.get_outer_attrs ()) { visit (attr); } auto param_name = param.get_name ().as_string (); switch (param.get_param_kind ()) { case MaybeNamedParam::UNNAMED: break; case MaybeNamedParam::IDENTIFIER: push ( Rust::Token::make_identifier (UNDEF_LOCATION, std::move (param_name))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); break; case MaybeNamedParam::WILDCARD: push (Rust::Token::make (UNDERSCORE, UNDEF_LOCATION)); push (Rust::Token::make (COLON, UNDEF_LOCATION)); break; } visit (param.get_type ()); } void TokenCollector::visit (Token &tok) { std::string data = tok.get_tok_ptr ()->has_str () ? tok.get_str () : ""; switch (tok.get_id ()) { case IDENTIFIER: push (Rust::Token::make_identifier (tok.get_locus (), std::move (data))); break; case INT_LITERAL: push (Rust::Token::make_int (tok.get_locus (), std::move (data), tok.get_type_hint ())); break; case FLOAT_LITERAL: push (Rust::Token::make_float (tok.get_locus (), std::move (data), tok.get_type_hint ())); break; case STRING_LITERAL: push (Rust::Token::make_string (tok.get_locus (), std::move (data))); break; case CHAR_LITERAL: push (Rust::Token::make_char ( tok.get_locus (), // FIXME: This need to be fixed to properly support UTF-8 static_cast<uint32_t> (data[0]))); break; case BYTE_CHAR_LITERAL: push (Rust::Token::make_byte_char (tok.get_locus (), data[0])); break; case BYTE_STRING_LITERAL: push (Rust::Token::make_byte_string (tok.get_locus (), std::move (data))); break; case INNER_DOC_COMMENT: push (Rust::Token::make_inner_doc_comment (tok.get_locus (), std::move (data))); break; case OUTER_DOC_COMMENT: push (Rust::Token::make_outer_doc_comment (tok.get_locus (), std::move (data))); break; case LIFETIME: push (Rust::Token::make_lifetime (tok.get_locus (), std::move (data))); break; default: push (Rust::Token::make (tok.get_id (), tok.get_locus ())); } } void TokenCollector::visit (DelimTokenTree &delim_tok_tree) { for (auto &token : delim_tok_tree.to_token_stream ()) { visit (token); } } void TokenCollector::visit (AttrInputMetaItemContainer &container) { for (auto &item : container.get_items ()) { visit (item); } } void TokenCollector::visit (IdentifierExpr &ident_expr) { auto ident = ident_expr.get_ident ().as_string (); push ( Rust::Token::make_identifier (ident_expr.get_locus (), std::move (ident))); } void TokenCollector::visit (Lifetime &lifetime) { // Syntax: // Lifetime : // LIFETIME_OR_LABEL // | 'static // | '_ auto name = lifetime.get_lifetime_name (); switch (lifetime.get_lifetime_type ()) { case Lifetime::LifetimeType::NAMED: push ( Rust::Token::make_lifetime (lifetime.get_locus (), std::move (name))); break; case Lifetime::LifetimeType::STATIC: push (Rust::Token::make_lifetime (lifetime.get_locus (), Values::Keywords::STATIC_KW)); break; case Lifetime::LifetimeType::WILDCARD: push (Rust::Token::make_lifetime (lifetime.get_locus (), Values::Keywords::UNDERSCORE)); break; } } void TokenCollector::visit (LifetimeParam &lifetime_param) { // Syntax: // LIFETIME_OR_LABEL ( : LifetimeBounds )? // LifetimeBounds : // ( Lifetime + )* Lifetime? // TODO what to do with outer attr? They are not mentioned in the reference. visit_items_as_lines (lifetime_param.get_outer_attrs ()); auto lifetime = lifetime_param.get_lifetime (); visit (lifetime); if (lifetime_param.has_lifetime_bounds ()) { push (Rust::Token::make (COLON, UNDEF_LOCATION)); for (auto &bound : lifetime_param.get_lifetime_bounds ()) { visit (bound); } } } void TokenCollector::visit (ConstGenericParam ¶m) { // Syntax: // const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )? visit_items_as_lines (param.get_outer_attrs ()); push (Rust::Token::make (CONST, param.get_locus ())); auto id = param.get_name ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); if (param.has_type ()) visit (param.get_type ()); if (param.has_default_value ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (param.get_default_value ()); } } void TokenCollector::visit (PathExprSegment &segment) { visit (segment.get_ident_segment ()); if (segment.has_generic_args ()) { auto generics = segment.get_generic_args (); push (Rust::Token::make (SCOPE_RESOLUTION, segment.get_locus ())); push (Rust::Token::make (LEFT_ANGLE, generics.get_locus ())); auto &lifetime_args = generics.get_lifetime_args (); auto &generic_args = generics.get_generic_args (); auto &binding_args = generics.get_binding_args (); visit_items_joined_by_separator (generic_args, COMMA); if (!lifetime_args.empty () && (!generic_args.empty () || !binding_args.empty ())) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); } visit_items_joined_by_separator (binding_args, COMMA); if (!generic_args.empty () && !binding_args.empty ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); } visit_items_joined_by_separator (lifetime_args, COMMA); push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION)); } } void TokenCollector::visit (PathInExpression &path) { if (path.opening_scope_resolution ()) { push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); } visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } void TokenCollector::visit (TypePathSegment &segment) { // Syntax: // PathIdentSegment auto ident_segment = segment.get_ident_segment (); auto id = ident_segment.as_string (); push ( Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); } void TokenCollector::visit (TypePathSegmentGeneric &segment) { // Syntax: // PathIdentSegment `::`? (GenericArgs)? // GenericArgs : // `<` `>` // | `<` ( GenericArg `,` )* GenericArg `,`? `>` auto ident_segment = segment.get_ident_segment (); auto id = ident_segment.as_string (); push ( Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); if (segment.get_separating_scope_resolution ()) push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION)); { auto &lifetime_args = segment.get_generic_args ().get_lifetime_args (); auto &generic_args = segment.get_generic_args ().get_generic_args (); auto &binding_args = segment.get_generic_args ().get_binding_args (); visit_items_joined_by_separator (lifetime_args, COMMA); if (!lifetime_args.empty () && (!generic_args.empty () || !binding_args.empty ())) push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit_items_joined_by_separator (generic_args, COMMA); if (!generic_args.empty () && !binding_args.empty ()) push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit_items_joined_by_separator (binding_args, COMMA); } push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION)); } void TokenCollector::visit (GenericArgsBinding &binding) { // Syntax: // IDENTIFIER `=` Type auto identifier = binding.get_identifier ().as_string (); push (Rust::Token::make_identifier (binding.get_locus (), std::move (identifier))); push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (binding.get_type ()); } void TokenCollector::visit (GenericArg &arg) { // `GenericArg` implements `accept_vis` but it is not useful for this case as // it ignores unresolved cases (`Kind::Either`). switch (arg.get_kind ()) { case GenericArg::Kind::Const: visit (arg.get_expression ()); break; case GenericArg::Kind::Type: visit (arg.get_type ()); break; case GenericArg::Kind::Either: { auto path = arg.get_path (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } break; case GenericArg::Kind::Error: rust_unreachable (); } } void TokenCollector::visit (TypePathSegmentFunction &segment) { // Syntax: // PathIdentSegment `::`? (TypePathFn)? auto ident_segment = segment.get_ident_segment (); auto id = ident_segment.as_string (); push ( Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); if (segment.get_separating_scope_resolution ()) push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); if (!segment.is_ident_only ()) visit (segment.get_type_path_function ()); } void TokenCollector::visit (TypePathFunction &type_path_fn) { // Syntax: // `(` TypePathFnInputs? `)` (`->` Type)? // TypePathFnInputs : // Type (`,` Type)* `,`? push (Rust::Token::make (LEFT_PAREN, type_path_fn.get_locus ())); if (type_path_fn.has_inputs ()) visit_items_joined_by_separator (type_path_fn.get_params (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); if (type_path_fn.has_return_type ()) { push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION)); visit (type_path_fn.get_return_type ()); } } void TokenCollector::visit (TypePath &path) { // Syntax: // `::`? TypePathSegment (`::` TypePathSegment)* if (path.has_opening_scope_resolution_op ()) push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } void TokenCollector::visit (PathIdentSegment &segment) { if (segment.is_super_segment ()) { push (Rust::Token::make (SUPER, segment.get_locus ())); } else if (segment.is_crate_segment ()) { push (Rust::Token::make (CRATE, segment.get_locus ())); } else if (segment.is_lower_self ()) { push (Rust::Token::make (SELF, segment.get_locus ())); } else if (segment.is_big_self ()) { push (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); } else { auto id = segment.as_string (); push ( Rust::Token::make_identifier (segment.get_locus (), std::move (id))); } } void TokenCollector::visit (QualifiedPathInExpression &path) { visit (path.get_qualified_path_type ()); for (auto &segment : path.get_segments ()) { push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); visit (segment); } } void TokenCollector::visit (QualifiedPathType &path) { push (Rust::Token::make (LEFT_ANGLE, path.get_locus ())); visit (path.get_type ()); if (path.has_as_clause ()) { push (Rust::Token::make (AS, UNDEF_LOCATION)); visit (path.get_as_type_path ()); } push (Rust::Token::make (RIGHT_ANGLE, UNDEF_LOCATION)); } void TokenCollector::visit (QualifiedPathInType &path) { visit (path.get_qualified_path_type ()); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); visit (path.get_associated_segment ()); for (auto &segment : path.get_segments ()) { push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); visit (segment); } } void TokenCollector::visit (Literal &lit, location_t locus) { auto value = lit.as_string (); switch (lit.get_lit_type ()) { case Literal::LitType::CHAR: push ( Rust::Token::make_char (locus, // TODO: Change this to support utf-8 properly Codepoint (static_cast<uint32_t> (value[0])))); break; case Literal::LitType::STRING: push (Rust::Token::make_string (locus, std::move (value))); break; case Literal::LitType::BYTE: push (Rust::Token::make_byte_char (locus, value[0])); break; case Literal::LitType::BYTE_STRING: push (Rust::Token::make_byte_string (locus, std::move (value))); break; case Literal::LitType::INT: push ( Rust::Token::make_int (locus, std::move (value), lit.get_type_hint ())); break; case Literal::LitType::FLOAT: push (Rust::Token::make_float (locus, std::move (value), lit.get_type_hint ())); break; case Literal::LitType::BOOL: { if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); else if (value == Values::Keywords::TRUE_LITERAL) push (Rust::Token::make (TRUE_LITERAL, locus)); else rust_unreachable (); // Not a boolean break; } case Literal::LitType::ERROR: rust_unreachable (); break; } } void TokenCollector::visit (LiteralExpr &expr) { auto lit = expr.get_literal (); visit (lit, expr.get_locus ()); } void TokenCollector::visit (AttrInputLiteral &literal) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (literal.get_literal ()); } void TokenCollector::visit (AttrInputMacro ¯o) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (macro.get_macro ()); } void TokenCollector::visit (MetaItemLitExpr &item) { auto lit = item.get_literal (); visit (lit); } void TokenCollector::visit (MetaItemPathLit &item) { auto path = item.get_path (); auto lit = item.get_literal (); visit (path); push (Rust::Token::make (COLON, item.get_locus ())); visit (lit); } void TokenCollector::visit (BorrowExpr &expr) { push (Rust::Token::make (AMP, expr.get_locus ())); if (expr.get_is_double_borrow ()) push (Rust::Token::make (AMP, UNDEF_LOCATION)); if (expr.is_raw_borrow ()) { push (Rust::Token::make_identifier (expr.get_locus (), Values::WeakKeywords::RAW)); if (expr.get_is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); else push (Rust::Token::make (CONST, UNDEF_LOCATION)); } else { if (expr.get_is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); } visit (expr.get_borrowed_expr ()); } void TokenCollector::visit (DereferenceExpr &expr) { push (Rust::Token::make (ASTERISK, expr.get_locus ())); visit (expr.get_dereferenced_expr ()); } void TokenCollector::visit (ErrorPropagationExpr &expr) { visit (expr.get_propagating_expr ()); push (Rust::Token::make (QUESTION_MARK, expr.get_locus ())); } void TokenCollector::visit (NegationExpr &expr) { switch (expr.get_expr_type ()) { case NegationOperator::NEGATE: push (Rust::Token::make (MINUS, expr.get_locus ())); break; case NegationOperator::NOT: push (Rust::Token::make (EXCLAM, expr.get_locus ())); break; } visit (expr.get_negated_expr ()); } void TokenCollector::visit (ArithmeticOrLogicalExpr &expr) { visit (expr.get_left_expr ()); switch (expr.get_expr_type ()) { case ArithmeticOrLogicalOperator::ADD: push (Rust::Token::make (PLUS, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::SUBTRACT: push (Rust::Token::make (MINUS, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::MULTIPLY: push (Rust::Token::make (ASTERISK, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::DIVIDE: push (Rust::Token::make (DIV, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::MODULUS: push (Rust::Token::make (PERCENT, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::BITWISE_AND: push (Rust::Token::make (AMP, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::BITWISE_OR: push (Rust::Token::make (PIPE, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::BITWISE_XOR: push (Rust::Token::make (CARET, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::LEFT_SHIFT: push (Rust::Token::make (LEFT_SHIFT, expr.get_locus ())); break; case ArithmeticOrLogicalOperator::RIGHT_SHIFT: push (Rust::Token::make (RIGHT_SHIFT, expr.get_locus ())); break; } visit (expr.get_right_expr ()); } void TokenCollector::visit (ComparisonExpr &expr) { visit (expr.get_left_expr ()); switch (expr.get_expr_type ()) { case ComparisonOperator::EQUAL: push (Rust::Token::make (EQUAL_EQUAL, expr.get_locus ())); break; case ComparisonOperator::NOT_EQUAL: push (Rust::Token::make (NOT_EQUAL, expr.get_locus ())); break; case ComparisonOperator::GREATER_THAN: push (Rust::Token::make (RIGHT_ANGLE, expr.get_locus ())); break; case ComparisonOperator::LESS_THAN: push (Rust::Token::make (LEFT_ANGLE, expr.get_locus ())); break; case ComparisonOperator::GREATER_OR_EQUAL: push (Rust::Token::make (GREATER_OR_EQUAL, expr.get_locus ())); break; case ComparisonOperator::LESS_OR_EQUAL: push (Rust::Token::make (LESS_OR_EQUAL, expr.get_locus ())); break; } visit (expr.get_right_expr ()); } void TokenCollector::visit (LazyBooleanExpr &expr) { visit (expr.get_left_expr ()); switch (expr.get_expr_type ()) { case LazyBooleanOperator::LOGICAL_AND: push (Rust::Token::make (LOGICAL_AND, expr.get_locus ())); break; case LazyBooleanOperator::LOGICAL_OR: push (Rust::Token::make (OR, expr.get_locus ())); break; } visit (expr.get_right_expr ()); } void TokenCollector::visit (TypeCastExpr &expr) { visit (expr.get_casted_expr ()); push (Rust::Token::make (AS, expr.get_locus ())); visit (expr.get_type_to_cast_to ()); } void TokenCollector::visit (AssignmentExpr &expr) { expr.visit_lhs (*this); push (Rust::Token::make (EQUAL, expr.get_locus ())); expr.visit_rhs (*this); } void TokenCollector::visit (CompoundAssignmentExpr &expr) { visit (expr.get_left_expr ()); switch (expr.get_expr_type ()) { case CompoundAssignmentOperator::ADD: push (Rust::Token::make (PLUS_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::SUBTRACT: push (Rust::Token::make (MINUS_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::MULTIPLY: push (Rust::Token::make (ASTERISK_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::DIVIDE: push (Rust::Token::make (DIV_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::MODULUS: push (Rust::Token::make (PERCENT_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::BITWISE_AND: push (Rust::Token::make (AMP_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::BITWISE_OR: push (Rust::Token::make (PIPE_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::BITWISE_XOR: push (Rust::Token::make (CARET_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::LEFT_SHIFT: push (Rust::Token::make (LEFT_SHIFT_EQ, expr.get_locus ())); break; case CompoundAssignmentOperator::RIGHT_SHIFT: push (Rust::Token::make (RIGHT_SHIFT_EQ, expr.get_locus ())); break; } visit (expr.get_right_expr ()); } void TokenCollector::visit (GroupedExpr &expr) { push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); visit (expr.get_expr_in_parens ()); push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); } void TokenCollector::visit (ArrayElemsValues &elems) { visit_items_joined_by_separator (elems.get_values (), COMMA); } void TokenCollector::visit (ArrayElemsCopied &elems) { visit (elems.get_elem_to_copy ()); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); visit (elems.get_num_copies ()); } void TokenCollector::visit (ArrayExpr &expr) { push (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); visit (expr.get_array_elems ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (ArrayIndexExpr &expr) { visit (expr.get_array_expr ()); push (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); visit (expr.get_index_expr ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (TupleExpr &expr) { visit_items_as_lines (expr.get_outer_attrs ()); push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); visit_items_joined_by_separator (expr.get_tuple_elems (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (TupleIndexExpr &expr) { visit (expr.get_tuple_expr ()); push (Rust::Token::make (DOT, expr.get_locus ())); push (Rust::Token::make_int (UNDEF_LOCATION, std::to_string (expr.get_tuple_index ()))); } void TokenCollector::visit (StructExprStruct &expr) { visit (expr.get_struct_name ()); } void TokenCollector::visit (StructExprFieldIdentifier &expr) { visit_items_as_lines (expr.get_outer_attrs ()); auto id = expr.get_field_name ().as_string (); push (Rust::Token::make_identifier (expr.get_locus (), std::move (id))); } void TokenCollector::visit (StructExprFieldIdentifierValue &expr) { visit_items_as_lines (expr.get_outer_attrs ()); auto id = expr.get_field_name (); push (Rust::Token::make_identifier (expr.get_locus (), std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (expr.get_value ()); } void TokenCollector::visit (StructExprFieldIndexValue &expr) { visit_items_as_lines (expr.get_outer_attrs ()); push (Rust::Token::make_int (expr.get_locus (), std::to_string (expr.get_index ()))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (expr.get_value ()); } void TokenCollector::visit (StructBase &base) { push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); visit (base.get_base_struct ()); } void TokenCollector::visit (StructExprStructFields &expr) { visit (expr.get_struct_name ()); push (Rust::Token::make (LEFT_CURLY, expr.get_locus ())); visit_items_joined_by_separator (expr.get_fields (), COMMA); if (expr.has_struct_base ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit (expr.get_struct_base ()); } else { trailing_comma (); } push (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); } void TokenCollector::visit (StructExprStructBase &) { // FIXME: Implement this node rust_unreachable (); } void TokenCollector::visit (CallExpr &expr) { visit (expr.get_function_expr ()); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (expr.get_params (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (MethodCallExpr &expr) { visit (expr.get_receiver_expr ()); push (Rust::Token::make (DOT, expr.get_locus ())); visit (expr.get_method_name ()); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (expr.get_params (), COMMA); trailing_comma (); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (FieldAccessExpr &expr) { visit (expr.get_receiver_expr ()); push (Rust::Token::make (DOT, expr.get_locus ())); auto field_name = expr.get_field_name ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (field_name))); } void TokenCollector::visit (ClosureParam ¶m) { visit_items_as_lines (param.get_outer_attrs ()); visit (param.get_pattern ()); if (param.has_type_given ()) { push (Rust::Token::make (COLON, param.get_locus ())); visit (param.get_type ()); } } void TokenCollector::visit_closure_common (ClosureExpr &expr) { if (expr.get_has_move ()) { push (Rust::Token::make (MOVE, expr.get_locus ())); } push (Rust::Token::make (PIPE, UNDEF_LOCATION)); visit_items_joined_by_separator (expr.get_params (), COMMA); push (Rust::Token::make (PIPE, UNDEF_LOCATION)); } void TokenCollector::visit (ClosureExprInner &expr) { visit_closure_common (expr); visit (expr.get_definition_expr ()); } void TokenCollector::visit (BlockExpr &expr) { visit_items_as_lines (expr.get_outer_attrs ()); push (Rust::Token::make (LEFT_CURLY, expr.get_locus ())); newline (); increment_indentation (); visit_items_as_lines (expr.get_inner_attrs ()); visit_items_as_lines (expr.get_statements (), {}); if (expr.has_tail_expr ()) { indentation (); visit (expr.get_tail_expr ()); comment ("tail expr"); newline (); } decrement_indentation (); indentation (); push (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); newline (); } void TokenCollector::visit (ClosureExprInnerTyped &expr) { visit_closure_common (expr); push (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); visit (expr.get_return_type ()); visit (expr.get_definition_block ()); } void TokenCollector::visit (ContinueExpr &expr) { push (Rust::Token::make (CONTINUE, expr.get_locus ())); if (expr.has_label ()) visit (expr.get_label ()); } void TokenCollector::visit (BreakExpr &expr) { push (Rust::Token::make (BREAK, expr.get_locus ())); if (expr.has_label ()) visit (expr.get_label ()); if (expr.has_break_expr ()) visit (expr.get_break_expr ()); } void TokenCollector::visit (RangeFromToExpr &expr) { visit (expr.get_from_expr ()); push (Rust::Token::make (DOT_DOT, expr.get_locus ())); visit (expr.get_to_expr ()); } void TokenCollector::visit (RangeFromExpr &expr) { visit (expr.get_from_expr ()); push (Rust::Token::make (DOT_DOT, expr.get_locus ())); } void TokenCollector::visit (RangeToExpr &expr) { push (Rust::Token::make (DOT_DOT, expr.get_locus ())); visit (expr.get_to_expr ()); } void TokenCollector::visit (RangeFullExpr &expr) { push (Rust::Token::make (DOT_DOT, expr.get_locus ())); } void TokenCollector::visit (RangeFromToInclExpr &expr) { visit (expr.get_from_expr ()); push (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); visit (expr.get_to_expr ()); } void TokenCollector::visit (RangeToInclExpr &expr) { push (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); visit (expr.get_to_expr ()); } void TokenCollector::visit (BoxExpr &expr) { push (Rust::Token::make (BOX, expr.get_locus ())); visit (expr.get_boxed_expr ()); } void TokenCollector::visit (ReturnExpr &expr) { push (Rust::Token::make (RETURN_KW, expr.get_locus ())); if (expr.has_returned_expr ()) visit (expr.get_returned_expr ()); } void TokenCollector::visit (UnsafeBlockExpr &expr) { push (Rust::Token::make (UNSAFE, expr.get_locus ())); visit (expr.get_block_expr ()); } void TokenCollector::visit (LoopLabel &label) { visit (label.get_lifetime ()); push (Rust::Token::make (COLON, label.get_locus ())); } void TokenCollector::visit_loop_common (BaseLoopExpr &expr) { if (expr.has_loop_label ()) visit (expr.get_loop_label ()); } void TokenCollector::visit (LoopExpr &expr) { visit_loop_common (expr); push (Rust::Token::make (LOOP, expr.get_locus ())); visit (expr.get_loop_block ()); } void TokenCollector::visit (WhileLoopExpr &expr) { visit_loop_common (expr); push (Rust::Token::make (WHILE, expr.get_locus ())); visit (expr.get_predicate_expr ()); visit (expr.get_loop_block ()); } void TokenCollector::visit (WhileLetLoopExpr &expr) { visit_loop_common (expr); push (Rust::Token::make (WHILE, expr.get_locus ())); push (Rust::Token::make (LET, UNDEF_LOCATION)); // TODO: The reference mention only one Pattern for (auto &item : expr.get_patterns ()) { visit (item); } push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_block ()); } void TokenCollector::visit (ForLoopExpr &expr) { visit_loop_common (expr); push (Rust::Token::make (FOR, expr.get_locus ())); visit (expr.get_pattern ()); push (Rust::Token::make (IN, UNDEF_LOCATION)); visit (expr.get_iterator_expr ()); visit (expr.get_loop_block ()); } void TokenCollector::visit (IfExpr &expr) { push (Rust::Token::make (IF, expr.get_locus ())); visit (expr.get_condition_expr ()); visit (expr.get_if_block ()); } void TokenCollector::visit (IfExprConseqElse &expr) { visit (static_cast<IfExpr &> (expr)); indentation (); push (Rust::Token::make (ELSE, expr.get_locus ())); visit (expr.get_else_block ()); } void TokenCollector::visit (IfLetExpr &expr) { push (Rust::Token::make (IF, expr.get_locus ())); push (Rust::Token::make (LET, UNDEF_LOCATION)); for (auto &pattern : expr.get_patterns ()) { visit (pattern); } push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (expr.get_value_expr ()); visit (expr.get_if_block ()); } void TokenCollector::visit (IfLetExprConseqElse &expr) { visit (static_cast<IfLetExpr &> (expr)); indentation (); push (Rust::Token::make (ELSE, expr.get_locus ())); visit (expr.get_else_block ()); } void TokenCollector::visit (MatchArm &arm) { visit_items_as_lines (arm.get_outer_attrs ()); for (auto &pattern : arm.get_patterns ()) { visit (pattern); } if (arm.has_match_arm_guard ()) { push (Rust::Token::make (IF, UNDEF_LOCATION)); visit (arm.get_guard_expr ()); } } void TokenCollector::visit (MatchCase &match_case) { indentation (); visit (match_case.get_arm ()); push (Rust::Token::make (MATCH_ARROW, UNDEF_LOCATION)); visit (match_case.get_expr ()); indentation (); push (Rust::Token::make (COMMA, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (MatchExpr &expr) { push (Rust::Token::make (MATCH_KW, expr.get_locus ())); visit (expr.get_scrutinee_expr ()); push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION)); newline (); increment_indentation (); visit_items_as_lines (expr.get_inner_attrs ()); for (auto &arm : expr.get_match_cases ()) { visit (arm); } decrement_indentation (); indentation (); push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION)); } void TokenCollector::visit (AwaitExpr &expr) { visit (expr.get_awaited_expr ()); push (Rust::Token::make (DOT, expr.get_locus ())); // TODO: Check status of await keyword (Context dependant ?) push (Rust::Token::make_identifier (UNDEF_LOCATION, Values::Keywords::AWAIT)); } void TokenCollector::visit (AsyncBlockExpr &expr) { push (Rust::Token::make (ASYNC, expr.get_locus ())); if (expr.get_has_move ()) push (Rust::Token::make (MOVE, UNDEF_LOCATION)); visit (expr.get_block_expr ()); } // rust-item.h void TokenCollector::visit (TypeParam ¶m) { // Syntax: // IDENTIFIER( : TypeParamBounds? )? ( = Type )? // TypeParamBounds : // TypeParamBound ( + TypeParamBound )* +? visit_items_as_lines (param.get_outer_attrs ()); auto id = param.get_type_representation ().as_string (); push (Rust::Token::make_identifier (param.get_locus (), std::move (id))); if (param.has_type_param_bounds ()) { push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit_items_joined_by_separator (param.get_type_param_bounds (), PLUS); } if (param.has_type ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (param.get_type ()); } } void TokenCollector::visit (WhereClause &rule) { // Syntax: // where ( WhereClauseItem , )* WhereClauseItem ? // WhereClauseItem : // LifetimeWhereClauseItem // | TypeBoundWhereClauseItem push (Rust::Token::make (WHERE, UNDEF_LOCATION)); newline (); increment_indentation (); visit_items_joined_by_separator (rule.get_items (), COMMA); decrement_indentation (); } void TokenCollector::visit (LifetimeWhereClauseItem &item) { // Syntax: // Lifetime : LifetimeBounds // LifetimeBounds : // ( Lifetime + )* Lifetime? visit (item.get_lifetime ()); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit_items_joined_by_separator (item.get_lifetime_bounds (), PLUS); } void TokenCollector::visit (TypeBoundWhereClauseItem &item) { // Syntax: // ForLifetimes? Type : TypeParamBounds? // TypeParamBounds : // TypeParamBound ( + TypeParamBound )* +? // TypeParamBound : // Lifetime | TraitBound if (item.has_for_lifetimes ()) visit (item.get_for_lifetimes ()); visit (item.get_type ()); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit_items_joined_by_separator (item.get_type_param_bounds (), PLUS); } void TokenCollector::visit (Module &module) { // Syntax: // mod IDENTIFIER ; // | mod IDENTIFIER { // InnerAttribute* // Item* // } visit_items_as_lines (module.get_outer_attrs ()); visit (module.get_visibility ()); auto name = module.get_name ().as_string (); push (Rust::Token::make (MOD, module.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name))); if (module.get_kind () == Module::UNLOADED) { push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } else /* Module::LOADED */ { push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION)); newline (); increment_indentation (); visit_items_as_lines (module.get_inner_attrs ()); visit_items_as_lines (module.get_items ()); decrement_indentation (); push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION)); newline (); } } void TokenCollector::visit (ExternCrate &crate) { visit_items_as_lines (crate.get_outer_attrs ()); push (Rust::Token::make (EXTERN_KW, crate.get_locus ())); push (Rust::Token::make (CRATE, UNDEF_LOCATION)); auto ref = crate.get_referenced_crate (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (ref))); if (crate.has_as_clause ()) { auto as_clause = crate.get_as_clause (); push (Rust::Token::make (AS, UNDEF_LOCATION)); push ( Rust::Token::make_identifier (UNDEF_LOCATION, std::move (as_clause))); } push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (UseTreeGlob &use_tree) { switch (use_tree.get_glob_type ()) { case UseTreeGlob::PathType::PATH_PREFIXED: { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); } break; case UseTreeGlob::PathType::NO_PATH: push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); break; case UseTreeGlob::PathType::GLOBAL: break; } push (Rust::Token::make (ASTERISK, UNDEF_LOCATION)); } void TokenCollector::visit (UseTreeList &use_tree) { switch (use_tree.get_path_type ()) { case UseTreeList::PathType::PATH_PREFIXED: { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); } break; case UseTreeList::PathType::NO_PATH: push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); break; case UseTreeList::PathType::GLOBAL: break; } push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION)); if (use_tree.has_trees ()) { visit_items_joined_by_separator (use_tree.get_trees (), COMMA); } push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION)); } void TokenCollector::visit (UseTreeRebind &use_tree) { auto path = use_tree.get_path (); visit (path); switch (use_tree.get_new_bind_type ()) { case UseTreeRebind::NewBindType::IDENTIFIER: { push (Rust::Token::make (AS, UNDEF_LOCATION)); auto id = use_tree.get_identifier ().as_string (); push ( Rust::Token::make_identifier (use_tree.get_locus (), std::move (id))); } break; case UseTreeRebind::NewBindType::WILDCARD: push (Rust::Token::make (AS, UNDEF_LOCATION)); push (Rust::Token::make (UNDERSCORE, use_tree.get_locus ())); break; case UseTreeRebind::NewBindType::NONE: break; } } void TokenCollector::visit (UseDeclaration &decl) { visit_items_as_lines (decl.get_outer_attrs ()); push (Rust::Token::make (USE, decl.get_locus ())); visit (*decl.get_tree ()); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (Function &function) { // Syntax: // FunctionQualifiers fn IDENTIFIER GenericParams? // ( FunctionParameters? ) // FunctionReturnType? WhereClause? // ( BlockExpression | ; ) visit_items_as_lines (function.get_outer_attrs ()); visit (function.get_visibility ()); auto qualifiers = function.get_qualifiers (); visit (qualifiers); push (Rust::Token::make (FN_KW, function.get_locus ())); auto name = function.get_function_name ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name))); if (function.has_generics ()) visit (function.get_generic_params ()); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (function.get_function_params ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); if (function.has_return_type ()) { push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION)); visit (function.get_return_type ()); } if (function.has_where_clause ()) visit (function.get_where_clause ()); if (function.has_body ()) visit (*function.get_definition ()); else push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (TypeAlias &type_alias) { // Syntax: // Visibility? type IDENTIFIER GenericParams? WhereClause? = Type; // Note: Associated types are handled by `AST::TraitItemType`. visit_items_as_lines (type_alias.get_outer_attrs ()); if (type_alias.has_visibility ()) visit (type_alias.get_visibility ()); auto alias_name = type_alias.get_new_type_name ().as_string (); push (Rust::Token::make (TYPE, type_alias.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (alias_name))); if (type_alias.has_generics ()) visit (type_alias.get_generic_params ()); if (type_alias.has_where_clause ()) visit (type_alias.get_where_clause ()); push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (type_alias.get_type_aliased ()); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (StructStruct &struct_item) { visit_items_as_lines (struct_item.get_outer_attrs ()); if (struct_item.has_visibility ()) visit (struct_item.get_visibility ()); auto struct_name = struct_item.get_identifier ().as_string (); push (Rust::Token::make (STRUCT_KW, struct_item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name))); if (struct_item.has_generics ()) visit (struct_item.get_generic_params ()); if (struct_item.has_where_clause ()) visit (struct_item.get_where_clause ()); if (struct_item.is_unit_struct ()) { push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } else visit_items_as_block (struct_item.get_fields (), {Rust::Token::make (COMMA, UNDEF_LOCATION)}); } void TokenCollector::visit (TupleStruct &tuple_struct) { visit_items_as_lines (tuple_struct.get_outer_attrs ()); auto struct_name = tuple_struct.get_identifier ().as_string (); push (Rust::Token::make (STRUCT_KW, tuple_struct.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name))); if (tuple_struct.has_generics ()) visit (tuple_struct.get_generic_params ()); if (tuple_struct.has_where_clause ()) visit (tuple_struct.get_where_clause ()); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (tuple_struct.get_fields (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (EnumItem &item) { visit_items_as_lines (item.get_outer_attrs ()); auto id = item.get_identifier ().as_string (); push (Rust::Token::make_identifier (item.get_locus (), std::move (id))); } void TokenCollector::visit (EnumItemTuple &item) { auto id = item.get_identifier ().as_string (); push (Rust::Token::make_identifier (item.get_locus (), std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (item.get_tuple_fields (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (EnumItemStruct &item) { auto id = item.get_identifier ().as_string (); push (Rust::Token::make_identifier (item.get_locus (), std::move (id))); visit_items_as_block (item.get_struct_fields (), {Rust::Token::make (COMMA, UNDEF_LOCATION)}); } void TokenCollector::visit (EnumItemDiscriminant &item) { auto id = item.get_identifier ().as_string (); push (Rust::Token::make_identifier (item.get_locus (), std::move (id))); push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (item.get_expr ()); } void TokenCollector::visit (Enum &enumeration) { visit_items_as_lines (enumeration.get_outer_attrs ()); if (enumeration.has_visibility ()) visit (enumeration.get_visibility ()); push (Rust::Token::make (ENUM_KW, enumeration.get_locus ())); auto id = enumeration.get_identifier ().as_string (); push ( Rust::Token::make_identifier (enumeration.get_locus (), std::move (id))); if (enumeration.has_generics ()) visit (enumeration.get_generic_params ()); if (enumeration.has_where_clause ()) visit (enumeration.get_where_clause ()); visit_items_as_block (enumeration.get_variants (), {Rust::Token::make (COMMA, UNDEF_LOCATION)}); } void TokenCollector::visit (Union &union_item) { visit_items_as_lines (union_item.get_outer_attrs ()); auto id = union_item.get_identifier ().as_string (); push (Rust::Token::make_identifier (union_item.get_locus (), Values::WeakKeywords::UNION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); if (union_item.has_generics ()) visit (union_item.get_generic_params ()); if (union_item.has_where_clause ()) visit (union_item.get_where_clause ()); visit_items_as_block (union_item.get_variants (), {Rust::Token::make (COMMA, UNDEF_LOCATION)}); } void TokenCollector::visit (ConstantItem &item) { visit_items_as_lines (item.get_outer_attrs ()); push (Rust::Token::make (CONST, item.get_locus ())); if (item.is_unnamed ()) { push (Rust::Token::make (UNDERSCORE, UNDEF_LOCATION)); } else { auto id = item.get_identifier (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); } push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); if (item.has_expr ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (item.get_expr ()); } push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (StaticItem &item) { visit_items_as_lines (item.get_outer_attrs ()); push (Rust::Token::make (STATIC_KW, item.get_locus ())); if (item.is_mutable ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); auto id = item.get_identifier ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); if (item.has_expr ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (item.get_expr ()); } push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit_function_common (std::unique_ptr<Type> &return_type, std::unique_ptr<BlockExpr> &block) { // FIXME: This should format the `<vis> fn <name> ( [args] )` as well if (return_type) { push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION)); visit (return_type); } if (block) { visit (block); } else { push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } } void TokenCollector::visit (SelfParam ¶m) { if (param.get_has_ref ()) { push (Rust::Token::make (AMP, UNDEF_LOCATION)); if (param.has_lifetime ()) { auto lifetime = param.get_lifetime (); visit (lifetime); } if (param.get_is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); } push (Rust::Token::make (SELF, UNDEF_LOCATION)); if (param.has_type ()) { push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (param.get_type ()); } } void TokenCollector::visit (TraitItemConst &item) { auto id = item.get_identifier ().as_string (); indentation (); push (Rust::Token::make (CONST, item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (TraitItemType &item) { visit_items_as_lines (item.get_outer_attrs ()); auto id = item.get_identifier ().as_string (); indentation (); push (Rust::Token::make (TYPE, item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } void TokenCollector::visit (Trait &trait) { for (auto &attr : trait.get_outer_attrs ()) { visit (attr); newline (); indentation (); } visit (trait.get_visibility ()); auto id = trait.get_identifier ().as_string (); push (Rust::Token::make (TRAIT, trait.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); visit (trait.get_generic_params ()); visit_items_as_block (trait.get_trait_items (), {}); } void TokenCollector::visit (InherentImpl &impl) { visit_items_as_lines (impl.get_outer_attrs ()); push (Rust::Token::make (IMPL, impl.get_locus ())); visit (impl.get_generic_params ()); visit (impl.get_type ()); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); // FIXME: Handle inner attributes visit_items_as_block (impl.get_impl_items (), {}); } void TokenCollector::visit (TraitImpl &impl) { visit_items_as_lines (impl.get_outer_attrs ()); push (Rust::Token::make (IMPL, impl.get_locus ())); visit (impl.get_generic_params ()); if (impl.is_exclam ()) push (Rust::Token::make (EXCLAM, UNDEF_LOCATION)); visit (impl.get_trait_path ()); push (Rust::Token::make (FOR, UNDEF_LOCATION)); visit (impl.get_type ()); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); visit_items_as_block (impl.get_impl_items ()); } void TokenCollector::visit (ExternalTypeItem &type) { visit (type.get_visibility ()); auto id = type.get_identifier ().as_string (); push (Rust::Token::make (TYPE, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (ExternalStaticItem &item) { auto id = item.get_identifier ().as_string (); visit_items_as_lines (item.get_outer_attrs ()); if (item.has_visibility ()) visit (item.get_visibility ()); push (Rust::Token::make (STATIC_KW, item.get_locus ())); if (item.is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); // TODO: No expr ? The "(= Expression)?" part from the reference seems missing // in the ast. push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (ExternBlock &block) { visit_items_as_lines (block.get_outer_attrs ()); push (Rust::Token::make (EXTERN_KW, block.get_locus ())); if (block.has_abi ()) { auto abi = block.get_abi (); push (Rust::Token::make_string (UNDEF_LOCATION, std::move (abi))); } visit_items_as_block (block.get_extern_items (), {}); } static std::pair<TokenId, TokenId> get_delimiters (DelimType delim) { switch (delim) { case PARENS: return {LEFT_PAREN, RIGHT_PAREN}; case SQUARE: return {LEFT_SQUARE, RIGHT_SQUARE}; case CURLY: return {LEFT_CURLY, RIGHT_CURLY}; default: rust_unreachable (); } } void TokenCollector::visit (MacroMatchFragment &match) { auto id = match.get_ident ().as_string (); auto frag_spec = match.get_frag_spec ().as_string (); push (Rust::Token::make (DOLLAR_SIGN, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (frag_spec))); } void TokenCollector::visit (MacroMatchRepetition &repetition) { push (Rust::Token::make (DOLLAR_SIGN, UNDEF_LOCATION)); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); for (auto &match : repetition.get_matches ()) { visit (match); } push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); if (repetition.has_sep ()) { push (Rust::Token::make (repetition.get_sep ()->get_id (), repetition.get_sep ()->get_locus ())); } switch (repetition.get_op ()) { case MacroMatchRepetition::ANY: push (Rust::Token::make (ASTERISK, UNDEF_LOCATION)); break; case MacroMatchRepetition::ONE_OR_MORE: push (Rust::Token::make (PLUS, UNDEF_LOCATION)); break; case MacroMatchRepetition::ZERO_OR_ONE: push (Rust::Token::make (QUESTION_MARK, UNDEF_LOCATION)); break; case MacroMatchRepetition::NONE: break; } } void TokenCollector::visit (MacroMatcher &matcher) { auto delimiters = get_delimiters (matcher.get_delim_type ()); push (Rust::Token::make (delimiters.first, UNDEF_LOCATION)); for (auto &item : matcher.get_matches ()) { visit (item); } push (Rust::Token::make (delimiters.second, UNDEF_LOCATION)); } void TokenCollector::visit (MacroRule &rule) { visit (rule.get_matcher ()); push (Rust::Token::make (MATCH_ARROW, rule.get_locus ())); visit (rule.get_transcriber ().get_token_tree ()); } void TokenCollector::visit (MacroRulesDefinition &rules_def) { for (auto &outer_attr : rules_def.get_outer_attrs ()) visit (outer_attr); auto rule_name = rules_def.get_rule_name ().as_string (); push (Rust::Token::make_identifier (rules_def.get_locus (), Values::WeakKeywords::MACRO_RULES)); push (Rust::Token::make (EXCLAM, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (rule_name))); visit_items_as_block (rules_def.get_rules (), {Rust::Token::make (SEMICOLON, UNDEF_LOCATION)}); } void TokenCollector::visit (MacroInvocation &invocation) { auto data = invocation.get_invoc_data (); visit (data.get_path ()); push (Rust::Token::make (EXCLAM, UNDEF_LOCATION)); visit (data.get_delim_tok_tree ()); if (invocation.has_semicolon ()) push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (MetaItemPath &item) { auto path = item.to_path_item (); visit (path); } void TokenCollector::visit (MetaItemSeq &item) { visit (item.get_path ()); // TODO: Double check this, there is probably a mistake. push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (item.get_seq (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (MetaWord &word) { auto id = word.get_ident ().as_string (); push (Rust::Token::make_identifier (word.get_locus (), std::move (id))); } void TokenCollector::visit (MetaNameValueStr &name) { auto pair = name.get_name_value_pair (); auto id = std::get<0> (pair).as_string (); auto value = std::get<1> (pair); push (Rust::Token::make_identifier (name.get_locus (), std::move (id))); push (Rust::Token::make (EQUAL, name.get_locus ())); push (Rust::Token::make (DOUBLE_QUOTE, UNDEF_LOCATION)); push (Rust::Token::make_identifier (name.get_locus (), std::move (value))); push (Rust::Token::make (DOUBLE_QUOTE, UNDEF_LOCATION)); } void TokenCollector::visit (MetaListPaths &list) { auto id = list.get_ident ().as_string (); push (Rust::Token::make_identifier (list.get_locus (), std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (list.get_paths (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (MetaListNameValueStr &list) { auto id = list.get_ident ().as_string (); push (Rust::Token::make_identifier (list.get_locus (), std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (list.get_values (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } // rust-pattern.h void TokenCollector::visit (LiteralPattern &pattern) { visit (pattern.get_literal (), pattern.get_locus ()); } void TokenCollector::visit (IdentifierPattern &pattern) { if (pattern.get_is_ref ()) { push (Rust::Token::make (REF, pattern.get_locus ())); } if (pattern.get_is_mut ()) { push (Rust::Token::make (MUT, UNDEF_LOCATION)); } auto id = pattern.get_ident ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); if (pattern.has_pattern_to_bind ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); visit (pattern.get_pattern_to_bind ()); } } void TokenCollector::visit (WildcardPattern &pattern) { push (Rust::Token::make (UNDERSCORE, pattern.get_locus ())); } void TokenCollector::visit (RestPattern &pattern) { push (Rust::Token::make (DOT_DOT, pattern.get_locus ())); } // void TokenCollector::visit(RangePatternBound& ){} void TokenCollector::visit (RangePatternBoundLiteral &pattern) { if (pattern.get_has_minus ()) { push (Rust::Token::make (MINUS, pattern.get_locus ())); } auto literal = pattern.get_literal (); visit (literal); } void TokenCollector::visit (RangePatternBoundPath &pattern) { visit (pattern.get_path ()); } void TokenCollector::visit (RangePatternBoundQualPath &pattern) { visit (pattern.get_qualified_path ()); } void TokenCollector::visit (RangePattern &pattern) { if (pattern.get_has_lower_bound () && pattern.get_has_upper_bound ()) { visit (pattern.get_lower_bound ()); if (pattern.get_has_ellipsis_syntax ()) push (Rust::Token::make (ELLIPSIS, pattern.get_locus ())); else push (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ())); visit (pattern.get_upper_bound ()); } else if (pattern.get_has_lower_bound ()) { visit (pattern.get_lower_bound ()); push (Rust::Token::make (DOT_DOT, pattern.get_locus ())); } else { push (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ())); visit (pattern.get_upper_bound ()); } } void TokenCollector::visit (ReferencePattern &pattern) { if (pattern.is_double_reference ()) { push (Rust::Token::make (LOGICAL_AND, pattern.get_locus ())); } else { push (Rust::Token::make (AMP, pattern.get_locus ())); } if (pattern.get_is_mut ()) { push (Rust::Token::make (MUT, UNDEF_LOCATION)); } visit (pattern.get_referenced_pattern ()); } // void TokenCollector::visit(StructPatternField& ){} void TokenCollector::visit (StructPatternFieldTuplePat &pattern) { visit_items_as_lines (pattern.get_outer_attrs ()); push (Rust::Token::make_int (pattern.get_locus (), std::to_string (pattern.get_index ()))); push (Rust::Token::make (COLON, pattern.get_locus ())); visit (pattern.get_index_pattern ()); } void TokenCollector::visit (StructPatternFieldIdentPat &pattern) { visit_items_as_lines (pattern.get_outer_attrs ()); auto id = pattern.get_identifier ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (COLON, pattern.get_locus ())); visit (pattern.get_ident_pattern ()); } void TokenCollector::visit (StructPatternFieldIdent &pattern) { visit_items_as_lines (pattern.get_outer_attrs ()); if (pattern.is_ref ()) push (Rust::Token::make (REF, UNDEF_LOCATION)); if (pattern.is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); auto id = pattern.get_identifier ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); } void TokenCollector::visit (StructPattern &pattern) { visit (pattern.get_path ()); push (Rust::Token::make (LEFT_CURLY, pattern.get_locus ())); auto elems = pattern.get_struct_pattern_elems (); if (elems.has_struct_pattern_fields ()) { visit_items_joined_by_separator (elems.get_struct_pattern_fields ()); if (elems.has_etc ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit_items_as_lines (elems.get_etc_outer_attrs ()); } } else { visit_items_as_lines (elems.get_etc_outer_attrs ()); } push (Rust::Token::make (RIGHT_CURLY, UNDEF_LOCATION)); } // void TokenCollector::visit(TupleStructItems& ){} void TokenCollector::visit (TupleStructItemsNoRange &pattern) { for (auto &pat : pattern.get_patterns ()) { visit (pat); } } void TokenCollector::visit (TupleStructItemsRange &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { visit (lower); } push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); for (auto &upper : pattern.get_lower_patterns ()) { visit (upper); } } void TokenCollector::visit (TupleStructPattern &pattern) { visit (pattern.get_path ()); push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); visit (pattern.get_items ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } // void // TokenCollector::visit (TuplePatternItems &) // {} void TokenCollector::visit (TuplePatternItemsMultiple &pattern) { visit_items_joined_by_separator (pattern.get_patterns (), COMMA); } void TokenCollector::visit (TuplePatternItemsRanged &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { visit (lower); } push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); for (auto &upper : pattern.get_lower_patterns ()) { visit (upper); } } void TokenCollector::visit (TuplePattern &pattern) { push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); visit (pattern.get_items ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (GroupedPattern &pattern) { push (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); visit (pattern.get_pattern_in_parens ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (SlicePattern &pattern) { push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); visit_items_joined_by_separator (pattern.get_items (), COMMA); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (AltPattern &pattern) { visit_items_joined_by_separator (pattern.get_alts (), PIPE); } // rust-stmt.h void TokenCollector::visit (EmptyStmt &) {} void TokenCollector::visit (LetStmt &stmt) { push (Rust::Token::make (LET, stmt.get_locus ())); auto &pattern = stmt.get_pattern (); visit (pattern); if (stmt.has_type ()) { push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (stmt.get_type ()); } if (stmt.has_init_expr ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (stmt.get_init_expr ()); } push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } void TokenCollector::visit (ExprStmt &stmt) { visit (stmt.get_expr ()); if (stmt.is_semicolon_followed ()) push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } // rust-type.h void TokenCollector::visit (TraitBound &bound) { // Syntax: // ?? ForLifetimes? TypePath // | ( ?? ForLifetimes? TypePath ) if (bound.has_opening_question_mark ()) push (Rust::Token::make (QUESTION_MARK, bound.get_locus ())); if (bound.has_for_lifetimes ()) visit (bound.get_for_lifetimes ()); visit (bound.get_type_path ()); } void TokenCollector::visit (ImplTraitType &type) { // Syntax: // impl TypeParamBounds // TypeParamBounds : // TypeParamBound ( + TypeParamBound )* +? push (Rust::Token::make (IMPL, type.get_locus ())); visit_items_joined_by_separator (type.get_type_param_bounds (), PLUS); } void TokenCollector::visit (TraitObjectType &type) { // Syntax: // dyn? TypeParamBounds // TypeParamBounds : // TypeParamBound ( + TypeParamBound )* +? if (type.is_dyn ()) push (Rust::Token::make (DYN, type.get_locus ())); visit_items_joined_by_separator (type.get_type_param_bounds (), PLUS); } void TokenCollector::visit (ParenthesisedType &type) { // Syntax: // ( Type ) push (Rust::Token::make (LEFT_PAREN, type.get_locus ())); visit (type.get_type_in_parens ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (ImplTraitTypeOneBound &type) { // Syntax: // impl TraitBound push (Rust::Token::make (IMPL, type.get_locus ())); visit (type.get_trait_bound ()); } void TokenCollector::visit (TraitObjectTypeOneBound &type) { // Syntax: // dyn? TraitBound if (type.is_dyn ()) push (Rust::Token::make (DYN, type.get_locus ())); visit (type.get_trait_bound ()); } void TokenCollector::visit (TupleType &type) { // Syntax: // ( ) // | ( ( Type , )+ Type? ) push (Rust::Token::make (LEFT_PAREN, type.get_locus ())); visit_items_joined_by_separator (type.get_elems (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } void TokenCollector::visit (NeverType &type) { // Syntax: // ! push (Rust::Token::make (EXCLAM, type.get_locus ())); } void TokenCollector::visit (RawPointerType &type) { // Syntax: // * ( mut | const ) TypeNoBounds push (Rust::Token::make (ASTERISK, type.get_locus ())); if (type.get_pointer_type () == RawPointerType::MUT) push (Rust::Token::make (MUT, UNDEF_LOCATION)); else /* RawPointerType::CONST */ push (Rust::Token::make (CONST, UNDEF_LOCATION)); visit (type.get_type_pointed_to ()); } void TokenCollector::visit (ReferenceType &type) { // Syntax: // & Lifetime? mut? TypeNoBounds push (Rust::Token::make (AMP, type.get_locus ())); if (type.has_lifetime ()) { visit (type.get_lifetime ()); } if (type.get_has_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); visit (type.get_type_referenced ()); } void TokenCollector::visit (ArrayType &type) { // Syntax: // [ Type ; Expression ] push (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); visit (type.get_elem_type ()); push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); visit (type.get_size_expr ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (SliceType &type) { // Syntax: // [ Type ] push (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); visit (type.get_elem_type ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } void TokenCollector::visit (InferredType &type) { // Syntax: // _ push (Rust::Token::make (UNDERSCORE, type.get_locus ())); } void TokenCollector::visit (BareFunctionType &type) { // Syntax: // ForLifetimes? FunctionTypeQualifiers fn // ( FunctionParametersMaybeNamedVariadic? ) BareFunctionReturnType? // // BareFunctionReturnType: // -> TypeNoBounds // // FunctionParametersMaybeNamedVariadic : // MaybeNamedFunctionParameters | MaybeNamedFunctionParametersVariadic // // MaybeNamedFunctionParameters : // MaybeNamedParam ( , MaybeNamedParam )* ,? // // MaybeNamedFunctionParametersVariadic : // ( MaybeNamedParam , )* MaybeNamedParam , OuterAttribute* ... if (type.has_for_lifetimes ()) visit (type.get_for_lifetimes ()); visit (type.get_function_qualifiers ()); push (Rust::Token::make (FN_KW, type.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (type.get_function_params (), COMMA); if (type.is_variadic ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); for (auto &item : type.get_variadic_attr ()) { visit (item); } push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); } push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); if (type.has_return_type ()) { push (Rust::Token::make (RETURN_TYPE, UNDEF_LOCATION)); visit (type.get_return_type ()); } } void TokenCollector::visit (AST::FormatArgs &fmt) { rust_sorry_at (fmt.get_locus (), "%s:%u: unimplemented FormatArgs visitor", __FILE__, __LINE__); } } // namespace AST } // namespace Rust