From 82387cd8a0e70c9ab791ebccf26290907cf0d217 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 2 May 2023 16:02:55 +0200 Subject: gccrs: ast: Rename rust-ast-tokenstream file The file does not contain any TokenStream declaration anymore and thus should be named more appropriately. gcc/rust/ChangeLog: * Make-lang.in: Change file name. * ast/rust-ast-tokenstream.cc: Moved to... * ast/rust-ast-collector.cc: ...here. * ast/rust-ast-tokenstream.h: Moved to... * ast/rust-ast-collector.h: ...here. * rust-session-manager.cc: Change header name. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/Make-lang.in | 2 +- gcc/rust/ast/rust-ast-collector.cc | 3188 ++++++++++++++++++++++++++++++++++ gcc/rust/ast/rust-ast-collector.h | 317 ++++ gcc/rust/ast/rust-ast-tokenstream.cc | 3188 ---------------------------------- gcc/rust/ast/rust-ast-tokenstream.h | 317 ---- gcc/rust/rust-session-manager.cc | 2 +- 6 files changed, 3507 insertions(+), 3507 deletions(-) create mode 100644 gcc/rust/ast/rust-ast-collector.cc create mode 100644 gcc/rust/ast/rust-ast-collector.h delete mode 100644 gcc/rust/ast/rust-ast-tokenstream.cc delete mode 100644 gcc/rust/ast/rust-ast-tokenstream.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 8ef50b2..fdfc484 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -78,7 +78,7 @@ GRS_OBJS = \ rust/rust-pattern.o \ rust/rust-ast-fragment.o \ rust/rust-ast-dump.o \ - rust/rust-ast-tokenstream.o \ + rust/rust-ast-collector.o \ rust/rust-hir-dump.o \ rust/rust-session-manager.o \ rust/rust-compile.o \ diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc new file mode 100644 index 0000000..908d151 --- /dev/null +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -0,0 +1,3188 @@ +// Copyright (C) 2020-2023 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 +// . +#include "rust-ast-collector.h" +#include "libproc_macro/proc_macro.h" + +namespace Rust { +namespace AST { + +TokenCollector::TokenCollector (std::vector &container) + : tokens (container) +{} + +std::vector +TokenCollector::collect_tokens () const +{ + return tokens; +} + +static void +pop_group (std::vector &streams, + ProcMacro::Delimiter delim) +{ + auto g = ProcMacro::Group::make_group (streams.back (), delim); + streams.pop_back (); + auto tt = ProcMacro::TokenTree::make_tokentree (g); + + streams.back ().push (tt); +} + +static void +dispatch_float_literals (ProcMacro::TokenStream &ts, TokenPtr &token) +{ + std::string::size_type sz; + auto str = token->as_string (); + switch (token->get_type_hint ()) + { + case CORETYPE_F32: { + auto value = std::stof (str, &sz); + bool suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_f32 (value, suffixed))); + } + break; + case CORETYPE_F64: { + auto value = std::stod (str, &sz); + bool suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_f64 (value, suffixed))); + } + break; + default: + gcc_unreachable (); + } +} + +static void +dispatch_integer_literals (ProcMacro::TokenStream &ts, TokenPtr &token) +{ + std::string::size_type sz; + auto str = token->as_string (); + unsigned long long uvalue; + long long svalue; + bool suffixed = false; + + switch (token->get_type_hint ()) + { + case CORETYPE_U8: + uvalue = std::stoull (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_u8 (uvalue, suffixed))); + break; + case CORETYPE_U16: + uvalue = std::stoull (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_u16 (uvalue, suffixed))); + break; + case CORETYPE_U32: + uvalue = std::stoull (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_u32 (uvalue, suffixed))); + break; + case CORETYPE_U64: + uvalue = std::stoull (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_u32 (uvalue, suffixed))); + break; + case CORETYPE_I8: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_i8 (svalue, suffixed))); + break; + case CORETYPE_I16: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_i16 (svalue, suffixed))); + break; + case CORETYPE_I32: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_i32 (svalue, suffixed))); + break; + case CORETYPE_I64: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_i32 (svalue, suffixed))); + break; + case CORETYPE_INT: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_isize (svalue, suffixed))); + break; + case CORETYPE_UINT: + uvalue = std::stoull (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_usize (uvalue, suffixed))); + break; + case CORETYPE_UNKNOWN: + svalue = std::stoll (str, &sz); + suffixed = sz == str.length (); + ts.push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_i32 (svalue, false))); + break; + default: + gcc_unreachable (); + break; + } +} + +ProcMacro::TokenStream +TokenCollector::collect () const +{ + std::vector trees; + trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); + for (auto &token : collect_tokens ()) + { + switch (token->get_id ()) + { + // Literals + case FLOAT_LITERAL: + dispatch_float_literals (trees.back (), token); + break; + case INT_LITERAL: + dispatch_integer_literals (trees.back (), token); + break; + // FIXME: Why does BYTE_CHAR_LITERAL is not handled by rustc ? + case CHAR_LITERAL: // TODO: UTF-8 handling + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_char (token->as_string ()[0]))); + break; + case STRING_LITERAL: + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_string (token->as_string ()))); + break; + case BYTE_STRING_LITERAL: { + auto str = token->as_string (); + std::vector data (str.begin (), str.end ()); + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Literal::make_byte_string (data))); + } + break; + // Ident + case IDENTIFIER: + case ABSTRACT: + case AS: + case ASYNC: + case AUTO: + case BECOME: + case BOX: + case BREAK: + case CONST: + case CONTINUE: + case CRATE: + case DO: + case DYN: + case ELSE: + case ENUM_TOK: + case EXTERN_TOK: + case FINAL_TOK: + case FN_TOK: + case FOR: + case IF: + case IMPL: + case IN: + case LET: + case LOOP: + case MACRO: + case MATCH_TOK: + case MOD: + case MOVE: + case MUT: + case OVERRIDE_TOK: + case PRIV: + case PUB: + case REF: + case RETURN_TOK: + case SELF_ALIAS: + case SELF: + case STATIC_TOK: + case STRUCT_TOK: + case SUPER: + case TRAIT: + case TRY: + case TYPE: + case TYPEOF: + case UNSAFE: + case UNSIZED: + case USE: + case VIRTUAL: + case WHERE: + case WHILE: + case YIELD: + // Underscore is not a Punct, considered as an Ident + case UNDERSCORE: + // True and false are idents, not literals + // (https://doc.rust-lang.org/proc_macro/struct.Literal.html) + case FALSE_LITERAL: + case TRUE_LITERAL: + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Ident::make_ident (token->as_string ()))); + break; + // Joint punct + case OR: + case PIPE_EQ: + case CARET_EQ: + case RIGHT_SHIFT_EQ: + case RIGHT_SHIFT: + case GREATER_OR_EQUAL: + case MATCH_ARROW: + case LESS_OR_EQUAL: + case LEFT_SHIFT_EQ: + case LEFT_SHIFT: + case DIV_EQ: + case ELLIPSIS: + case DOT_DOT_EQ: + case DOT_DOT: + case RETURN_TYPE: + case MINUS_EQ: + case PLUS_EQ: + case ASTERISK_EQ: + case LOGICAL_AND: + case AMP_EQ: + case PERCENT_EQ: + case SCOPE_RESOLUTION: + case NOT_EQUAL: + case EQUAL_EQUAL: { + auto str = token->as_string (); + auto it = str.cbegin (); + for (; it != str.cend () - 1; it++) + { + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Punct::make_punct (*it, ProcMacro::JOINT))); + } + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Punct::make_punct (*it, ProcMacro::ALONE))); + } + break; + // Alone punct tokens + case EQUAL: + case RIGHT_ANGLE: + case LEFT_ANGLE: + case EXCLAM: + case TILDE: + case PLUS: + case MINUS: + case ASTERISK: + case DIV: + case PERCENT: + case CARET: + case AMP: + case PIPE: + case PATTERN_BIND: + case DOT: + case COMMA: + case SEMICOLON: + case COLON: + case HASH: + case DOLLAR_SIGN: + case QUESTION_MARK: + case SINGLE_QUOTE: + trees.back ().push (ProcMacro::TokenTree::make_tokentree ( + ProcMacro::Punct::make_punct (token->as_string ()[0], + ProcMacro::ALONE))); + break; + case RIGHT_PAREN: + pop_group (trees, ProcMacro::PARENTHESIS); + break; + case RIGHT_CURLY: + pop_group (trees, ProcMacro::BRACE); + break; + case RIGHT_SQUARE: + pop_group (trees, ProcMacro::BRACKET); + break; + case LEFT_SQUARE: + case LEFT_CURLY: + case LEFT_PAREN: + trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); + break; + default: + gcc_unreachable (); + } + } + return trees.back (); +} + +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); +} + +template +void +TokenCollector::visit (std::unique_ptr &node) +{ + node->accept_vis (*this); +} + +template +void +TokenCollector::visit (T &node) +{ + node.accept_vis (*this); +} + +template +void +TokenCollector::visit_items_joined_by_separator (T &collection, + TokenId separator, + size_t start_offset, + size_t end_offset) +{ + if (collection.size () > start_offset) + { + visit (collection.at (start_offset)); + auto size = collection.size () - end_offset; + for (size_t i = start_offset + 1; i < size; i++) + { + tokens.push_back (Rust::Token::make (separator, Location ())); + visit (collection.at (i)); + } + } +} + +template +void +TokenCollector::visit_as_line (T &item, std::vector trailing) +{ + indentation (); + visit (item); + for (auto &token : trailing) + tokens.push_back (token); + newline (); +} + +template +void +TokenCollector::visit_items_as_lines (T &collection, + std::vector trailing) +{ + for (auto &item : collection) + visit_as_line (item, trailing); +} + +template +void +TokenCollector::visit_items_as_block (T &collection, + std::vector trailing, + TokenId left_brace, TokenId right_brace) +{ + tokens.push_back (Rust::Token::make (left_brace, Location ())); + if (collection.empty ()) + { + tokens.push_back (Rust::Token::make (right_brace, Location ())); + newline (); + } + else + { + newline (); + increment_indentation (); + visit_items_as_lines (collection, trailing); + decrement_indentation (); + indentation (); + tokens.push_back (Rust::Token::make (right_brace, Location ())); + newline (); + } +} + +void +TokenCollector::trailing_comma () +{ + if (output_trailing_commas) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + } +} + +void +TokenCollector::newline () +{} + +void +TokenCollector::indentation () +{} + +void +TokenCollector::increment_indentation () +{} + +void +TokenCollector::decrement_indentation () +{} + +void +TokenCollector::visit (FunctionParam ¶m) +{ + visit (param.get_pattern ()); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (param.get_type ()); +} + +void +TokenCollector::visit (Attribute &attrib) +{ + tokens.push_back (Rust::Token::make (HASH, attrib.get_locus ())); + if (attrib.is_inner_attribute ()) + tokens.push_back (Rust::Token::make (EXCLAM, Location ())); + tokens.push_back (Rust::Token::make (LEFT_SQUARE, 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 (attrib.get_attr_input ())); + break; + } + case AST::AttrInput::AttrInputType::META_ITEM: { + visit (static_cast ( + attrib.get_attr_input ())); + break; + } + case AST::AttrInput::AttrInputType::TOKEN_TREE: { + visit (static_cast (attrib.get_attr_input ())); + break; + } + default: + gcc_unreachable (); + } + } + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); +} + +void +TokenCollector::visit (SimplePath &path) +{ + if (path.has_opening_scope_resolution ()) + { + tokens.push_back ( + 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 ()) + { + tokens.push_back (Rust::Token::make (CRATE, segment.get_locus ())); + } + else if (segment.is_super_path_seg ()) + { + tokens.push_back (Rust::Token::make (SUPER, segment.get_locus ())); + } + else if (segment.is_lower_self ()) + { + tokens.push_back (Rust::Token::make (SELF, segment.get_locus ())); + } + else if (segment.is_big_self ()) + { + tokens.push_back (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); + } + else + { + tokens.push_back ( + Rust::Token::make_identifier (segment.get_locus (), std::move (name))); + } +} + +void +TokenCollector::visit (Visibility &vis) +{ + switch (vis.get_vis_type ()) + { + case Visibility::PUB: + tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); + break; + case Visibility::PUB_CRATE: + tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + tokens.push_back (Rust::Token::make (CRATE, Location ())); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + break; + case Visibility::PUB_SELF: + tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + tokens.push_back (Rust::Token::make (SELF, Location ())); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + break; + case Visibility::PUB_SUPER: + tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + tokens.push_back (Rust::Token::make (SUPER, Location ())); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + break; + case Visibility::PUB_IN_PATH: + tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + tokens.push_back (Rust::Token::make (IN, Location ())); + visit (vis.get_path ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + break; + case Visibility::PRIV: + break; + } +} + +void +TokenCollector::visit (NamedFunctionParam ¶m) +{ + auto name = param.get_name (); + tokens.push_back ( + Rust::Token::make_identifier (param.get_locus (), std::move (name))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (param.get_type ()); +} + +void +TokenCollector::visit (std::vector> ¶ms) +{ + tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); + visit_items_joined_by_separator (params, COMMA); + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, 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 (); + tokens.push_back ( + Rust::Token::make_identifier (field.get_locus (), std::move (name))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (field.get_field_type ()); +} + +void +TokenCollector::visit (std::vector &for_lifetimes) +{ + tokens.push_back (Rust::Token::make (FOR, Location ())); + tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); + visit_items_joined_by_separator (for_lifetimes, COMMA); + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); +} + +void +TokenCollector::visit (FunctionQualifiers &qualifiers) +{ + // Syntax: + // `const`? `async`? `unsafe`? (`extern` Abi?)? + // unsafe? (extern Abi?)? + + switch (qualifiers.get_const_status ()) + { + case NONE: + break; + case CONST_FN: + tokens.push_back (Rust::Token::make (CONST, qualifiers.get_locus ())); + break; + case ASYNC_FN: + tokens.push_back (Rust::Token::make (ASYNC, qualifiers.get_locus ())); + break; + } + + if (qualifiers.is_unsafe ()) + tokens.push_back (Rust::Token::make (UNSAFE, qualifiers.get_locus ())); + if (qualifiers.is_extern ()) + { + tokens.push_back ( + Rust::Token::make (EXTERN_TOK, qualifiers.get_locus ())); + if (qualifiers.has_abi ()) + { + tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); + auto abi = qualifiers.get_extern_abi (); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (abi))); + tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); + } + } +} + +void +TokenCollector::visit (MaybeNamedParam ¶m) +{ + // Syntax: + // OuterAttribute* ( ( IDENTIFIER | _ ) : )? Type + + for (auto attr : param.get_outer_attrs ()) + { + visit (attr); + } + auto param_name = param.get_name (); + switch (param.get_param_kind ()) + { + case MaybeNamedParam::UNNAMED: + break; + case MaybeNamedParam::IDENTIFIER: + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (param_name))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + break; + case MaybeNamedParam::WILDCARD: + tokens.push_back (Rust::Token::make (UNDERSCORE, Location ())); + tokens.push_back (Rust::Token::make (COLON, 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: + tokens.push_back ( + Rust::Token::make_identifier (tok.get_locus (), std::move (data))); + break; + case INT_LITERAL: + tokens.push_back (Rust::Token::make_int (tok.get_locus (), + std::move (data), + tok.get_type_hint ())); + break; + case FLOAT_LITERAL: + tokens.push_back (Rust::Token::make_float (tok.get_locus (), + std::move (data), + tok.get_type_hint ())); + break; + case STRING_LITERAL: + tokens.push_back ( + Rust::Token::make_string (tok.get_locus (), std::move (data))); + break; + case CHAR_LITERAL: + tokens.push_back (Rust::Token::make_char ( + tok.get_locus (), + // FIXME: This need to be fixed to properly support UTF-8 + static_cast (data[0]))); + break; + case BYTE_CHAR_LITERAL: + tokens.push_back ( + Rust::Token::make_byte_char (tok.get_locus (), data[0])); + break; + case BYTE_STRING_LITERAL: + tokens.push_back ( + Rust::Token::make_byte_string (tok.get_locus (), std::move (data))); + break; + case INNER_DOC_COMMENT: + tokens.push_back (Rust::Token::make_inner_doc_comment (tok.get_locus (), + std::move (data))); + break; + case OUTER_DOC_COMMENT: + tokens.push_back (Rust::Token::make_outer_doc_comment (tok.get_locus (), + std::move (data))); + break; + case LIFETIME: + tokens.push_back ( + Rust::Token::make_lifetime (tok.get_locus (), std::move (data))); + break; + default: + tokens.push_back (Rust::Token::make (tok.get_id (), tok.get_locus ())); + } +} + +void +TokenCollector::visit (DelimTokenTree &delim_tok_tree) +{ + increment_indentation (); + newline (); + indentation (); + for (auto &token : delim_tok_tree.to_token_stream ()) + { + visit (token); + } + decrement_indentation (); + newline (); + indentation (); +} + +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 (); + tokens.push_back ( + 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: + tokens.push_back ( + Rust::Token::make_lifetime (lifetime.get_locus (), std::move (name))); + break; + case Lifetime::LifetimeType::STATIC: + tokens.push_back (Rust::Token::make_lifetime (lifetime.get_locus (), + std::move ("static"))); + break; + case Lifetime::LifetimeType::WILDCARD: + tokens.push_back ( + Rust::Token::make_lifetime (lifetime.get_locus (), std::move ("_"))); + 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. + + auto lifetime = lifetime_param.get_lifetime (); + visit (lifetime); + + if (lifetime_param.has_lifetime_bounds ()) + { + tokens.push_back (Rust::Token::make (COLON, Location ())); + for (auto &bound : lifetime_param.get_lifetime_bounds ()) + { + visit (bound); + } + } +} + +void +TokenCollector::visit (ConstGenericParam ¶m) +{ + // Syntax: + // const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )? + + tokens.push_back (Rust::Token::make (CONST, param.get_locus ())); + auto id = param.get_name (); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (param.get_type ()); + if (param.has_default_value ()) + { + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (param.get_type ()); + } +} + +void +TokenCollector::visit (PathExprSegment &segment) +{ + visit (segment.get_ident_segment ()); + if (segment.has_generic_args ()) + { + auto generics = segment.get_generic_args (); + tokens.push_back ( + Rust::Token::make (SCOPE_RESOLUTION, segment.get_locus ())); + tokens.push_back (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 ())) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + } + + visit_items_joined_by_separator (binding_args, COMMA); + + if (!generic_args.empty () && !binding_args.empty ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + } + + visit_items_joined_by_separator (lifetime_args, COMMA); + + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); + } +} + +void +TokenCollector::visit (PathInExpression &path) +{ + if (path.opening_scope_resolution ()) + { + tokens.push_back ( + 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 (); + tokens.push_back ( + 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 (); + tokens.push_back ( + Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + + if (segment.get_separating_scope_resolution ()) + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + + tokens.push_back (Rust::Token::make (LEFT_ANGLE, 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 ())) + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit_items_joined_by_separator (generic_args, COMMA); + if (!generic_args.empty () && !binding_args.empty ()) + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit_items_joined_by_separator (generic_args, COMMA); + } + + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); +} + +void +TokenCollector::visit (GenericArgsBinding &binding) +{ + // Syntax: + // IDENTIFIER `=` Type + auto identifier = binding.get_identifier (); + tokens.push_back (Rust::Token::make_identifier (binding.get_locus (), + std::move (identifier))); + + tokens.push_back (Rust::Token::make (EQUAL, 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 (); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (path))); + } + break; + case GenericArg::Kind::Error: + gcc_unreachable (); + } +} + +void +TokenCollector::visit (TypePathSegmentFunction &segment) +{ + // Syntax: + // PathIdentSegment `::`? (TypePathFn)? + + auto ident_segment = segment.get_ident_segment (); + auto id = ident_segment.as_string (); + tokens.push_back ( + Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + + if (segment.get_separating_scope_resolution ()) + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, 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)* `,`? + + tokens.push_back (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); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + if (type_path_fn.has_return_type ()) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (type_path_fn.get_return_type ()); + } +} + +void +TokenCollector::visit (TypePath &path) +{ + // Syntax: + // `::`? TypePathSegment (`::` TypePathSegment)* + + if (path.has_opening_scope_resolution_op ()) + tokens.push_back (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 ()) + { + tokens.push_back (Rust::Token::make (SUPER, segment.get_locus ())); + } + else if (segment.is_crate_segment ()) + { + tokens.push_back (Rust::Token::make (CRATE, segment.get_locus ())); + } + else if (segment.is_lower_self ()) + { + tokens.push_back (Rust::Token::make (SELF, segment.get_locus ())); + } + else if (segment.is_big_self ()) + { + tokens.push_back (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); + } + else + { + auto id = segment.as_string (); + tokens.push_back ( + 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 ()) + { + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + visit (segment); + } +} + +void +TokenCollector::visit (QualifiedPathType &path) +{ + tokens.push_back (Rust::Token::make (LEFT_ANGLE, path.get_locus ())); + visit (path.get_type ()); + if (path.has_as_clause ()) + { + tokens.push_back (Rust::Token::make (AS, Location ())); + visit (path.get_as_type_path ()); + } + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); +} + +void +TokenCollector::visit (QualifiedPathInType &path) +{ + visit (path.get_qualified_path_type ()); + + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + visit (path.get_associated_segment ()); + for (auto &segment : path.get_segments ()) + { + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + visit (segment); + } +} + +void +TokenCollector::visit (Literal &lit, Location locus) +{ + auto value = lit.as_string (); + switch (lit.get_lit_type ()) + { + case Literal::LitType::CHAR: + tokens.push_back ( + Rust::Token::make_char (locus, + // TODO: Change this to support utf-8 properly + Codepoint (static_cast (value[0])))); + break; + case Literal::LitType::STRING: + tokens.push_back (Rust::Token::make_string (locus, std::move (value))); + break; + case Literal::LitType::BYTE: + tokens.push_back (Rust::Token::make_byte_char (locus, value[0])); + break; + case Literal::LitType::BYTE_STRING: + tokens.push_back ( + Rust::Token::make_byte_string (locus, std::move (value))); + break; + case Literal::LitType::INT: + tokens.push_back (Rust::Token::make_int (locus, std::move (value))); + break; + case Literal::LitType::FLOAT: + tokens.push_back (Rust::Token::make_float (locus, std::move (value))); + break; + case Literal::LitType::BOOL: { + if (value == "false") + tokens.push_back (Rust::Token::make (FALSE_LITERAL, locus)); + else if (value == "true") + tokens.push_back (Rust::Token::make (TRUE_LITERAL, locus)); + else + gcc_unreachable (); // Not a boolean + break; + } + case Literal::LitType::ERROR: + gcc_unreachable (); + break; + } +} + +void +TokenCollector::visit (LiteralExpr &expr) +{ + auto lit = expr.get_literal (); + visit (lit, expr.get_locus ()); +} + +void +TokenCollector::visit (AttrInputLiteral &literal) +{ + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (literal.get_literal ()); +} + +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); + tokens.push_back (Rust::Token::make (COLON, item.get_locus ())); + visit (lit); +} + +void +TokenCollector::visit (BorrowExpr &expr) +{ + tokens.push_back (Rust::Token::make (AMP, expr.get_locus ())); + if (expr.get_is_double_borrow ()) + tokens.push_back (Rust::Token::make (AMP, Location ())); + if (expr.get_is_mut ()) + tokens.push_back (Rust::Token::make (MUT, Location ())); + + visit (expr.get_borrowed_expr ()); +} + +void +TokenCollector::visit (DereferenceExpr &expr) +{ + tokens.push_back (Rust::Token::make (ASTERISK, expr.get_locus ())); + visit (expr.get_dereferenced_expr ()); +} + +void +TokenCollector::visit (ErrorPropagationExpr &expr) +{ + visit (expr.get_propagating_expr ()); + tokens.push_back (Rust::Token::make (QUESTION_MARK, expr.get_locus ())); +} + +void +TokenCollector::visit (NegationExpr &expr) +{ + switch (expr.get_expr_type ()) + { + case NegationOperator::NEGATE: + tokens.push_back (Rust::Token::make (MINUS, expr.get_locus ())); + break; + case NegationOperator::NOT: + tokens.push_back (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: + tokens.push_back (Rust::Token::make (PLUS, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::SUBTRACT: + tokens.push_back (Rust::Token::make (MINUS, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::MULTIPLY: + tokens.push_back (Rust::Token::make (ASTERISK, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::DIVIDE: + tokens.push_back (Rust::Token::make (DIV, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::MODULUS: + tokens.push_back (Rust::Token::make (PERCENT, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::BITWISE_AND: + tokens.push_back (Rust::Token::make (AMP, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::BITWISE_OR: + tokens.push_back (Rust::Token::make (PIPE, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::BITWISE_XOR: + tokens.push_back (Rust::Token::make (CARET, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + tokens.push_back (Rust::Token::make (LEFT_SHIFT, expr.get_locus ())); + break; + + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + tokens.push_back (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: + tokens.push_back (Rust::Token::make (EQUAL_EQUAL, expr.get_locus ())); + break; + case ComparisonOperator::NOT_EQUAL: + tokens.push_back (Rust::Token::make (NOT_EQUAL, expr.get_locus ())); + break; + case ComparisonOperator::GREATER_THAN: + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, expr.get_locus ())); + break; + case ComparisonOperator::LESS_THAN: + tokens.push_back (Rust::Token::make (LEFT_ANGLE, expr.get_locus ())); + break; + case ComparisonOperator::GREATER_OR_EQUAL: + tokens.push_back ( + Rust::Token::make (GREATER_OR_EQUAL, expr.get_locus ())); + break; + + case ComparisonOperator::LESS_OR_EQUAL: + tokens.push_back (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: + tokens.push_back (Rust::Token::make (LOGICAL_AND, expr.get_locus ())); + break; + case LazyBooleanOperator::LOGICAL_OR: + tokens.push_back (Rust::Token::make (OR, expr.get_locus ())); + break; + } + + visit (expr.get_right_expr ()); +} + +void +TokenCollector::visit (TypeCastExpr &expr) +{ + visit (expr.get_casted_expr ()); + tokens.push_back (Rust::Token::make (AS, expr.get_locus ())); + visit (expr.get_type_to_cast_to ()); +} + +void +TokenCollector::visit (AssignmentExpr &expr) +{ + expr.visit_lhs (*this); + tokens.push_back (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: + tokens.push_back (Rust::Token::make (PLUS_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::SUBTRACT: + tokens.push_back (Rust::Token::make (MINUS_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::MULTIPLY: + tokens.push_back (Rust::Token::make (ASTERISK_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::DIVIDE: + tokens.push_back (Rust::Token::make (DIV_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::MODULUS: + tokens.push_back (Rust::Token::make (PERCENT_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::BITWISE_AND: + tokens.push_back (Rust::Token::make (AMP_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::BITWISE_OR: + tokens.push_back (Rust::Token::make (PIPE_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::BITWISE_XOR: + tokens.push_back (Rust::Token::make (CARET_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::LEFT_SHIFT: + tokens.push_back (Rust::Token::make (LEFT_SHIFT_EQ, expr.get_locus ())); + break; + case CompoundAssignmentOperator::RIGHT_SHIFT: + tokens.push_back (Rust::Token::make (RIGHT_SHIFT_EQ, expr.get_locus ())); + break; + } + visit (expr.get_right_expr ()); +} + +void +TokenCollector::visit (GroupedExpr &expr) +{ + tokens.push_back (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + visit (expr.get_expr_in_parens ()); + tokens.push_back (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 ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + visit (elems.get_num_copies ()); +} + +void +TokenCollector::visit (ArrayExpr &expr) +{ + tokens.push_back (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); + visit (expr.get_array_elems ()); + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); +} + +void +TokenCollector::visit (ArrayIndexExpr &expr) +{ + visit (expr.get_array_expr ()); + tokens.push_back (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); + visit (expr.get_index_expr ()); + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); +} + +void +TokenCollector::visit (TupleExpr &expr) +{ + visit_items_as_lines (expr.get_outer_attrs ()); + tokens.push_back (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + visit_items_joined_by_separator (expr.get_tuple_elems (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (TupleIndexExpr &expr) +{ + visit (expr.get_tuple_expr ()); + tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); + tokens.push_back ( + Rust::Token::make_int (Location (), + std::to_string (expr.get_tuple_index ()))); +} + +void +TokenCollector::visit (StructExprStruct &expr) +{ + visit (expr.get_struct_name ()); +} + +void +TokenCollector::visit (StructExprFieldIdentifier &expr) +{ + // TODO: Add attributes + // visit_items_as_lines (expr.get_attrs ()); + auto id = expr.get_field_name (); + tokens.push_back ( + Rust::Token::make_identifier (expr.get_locus (), std::move (id))); +} + +void +TokenCollector::visit (StructExprFieldIdentifierValue &expr) +{ + // TODO: Add attributes + // visit_items_as_lines (expr.get_attrs ()); + auto id = expr.get_field_name (); + tokens.push_back ( + Rust::Token::make_identifier (expr.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (expr.get_value ()); +} + +void +TokenCollector::visit (StructExprFieldIndexValue &expr) +{ + // TODO: Add attributes + // visit_items_as_lines (expr.get_attrs ()); + tokens.push_back (Rust::Token::make_int (expr.get_locus (), + std::to_string (expr.get_index ()))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (expr.get_value ()); +} + +void +TokenCollector::visit (StructBase &base) +{ + tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); + visit (base.get_base_struct ()); +} + +void +TokenCollector::visit (StructExprStructFields &expr) +{ + visit (expr.get_struct_name ()); + tokens.push_back (Rust::Token::make (LEFT_CURLY, expr.get_locus ())); + visit_items_joined_by_separator (expr.get_fields (), COMMA); + if (expr.has_struct_base ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit (expr.get_struct_base ()); + } + else + { + trailing_comma (); + } + tokens.push_back (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); +} + +void +TokenCollector::visit (StructExprStructBase &) +{ + // FIXME: Implement this node + gcc_unreachable (); +} + +void +TokenCollector::visit (CallExpr &expr) +{ + visit (expr.get_function_expr ()); + + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit_items_joined_by_separator (expr.get_params (), COMMA); + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (MethodCallExpr &expr) +{ + visit (expr.get_receiver_expr ()); + tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); + visit (expr.get_method_name ()); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (expr.get_params (), COMMA); + trailing_comma (); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (FieldAccessExpr &expr) +{ + visit (expr.get_receiver_expr ()); + tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); + auto field_name = expr.get_field_name (); + tokens.push_back ( + Rust::Token::make_identifier (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 ()) + { + tokens.push_back (Rust::Token::make (COLON, param.get_locus ())); + visit (param.get_type ()); + } +} + +void +TokenCollector::visit_closure_common (ClosureExpr &expr) +{ + if (expr.get_has_move ()) + { + tokens.push_back (Rust::Token::make (MOVE, expr.get_locus ())); + } + tokens.push_back (Rust::Token::make (PIPE, Location ())); + visit_items_joined_by_separator (expr.get_params (), COMMA); + tokens.push_back (Rust::Token::make (PIPE, Location ())); +} + +void +TokenCollector::visit (ClosureExprInner &expr) +{ + visit_closure_common (expr); + visit (expr.get_definition_expr ()); +} + +void +TokenCollector::visit (BlockExpr &expr) +{ + tokens.push_back (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 (), + {Rust::Token::make (SEMICOLON, Location ())}); + + if (expr.has_tail_expr ()) + { + visit (expr.get_tail_expr ()); + newline (); + } + + decrement_indentation (); + tokens.push_back (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); + newline (); +} + +void +TokenCollector::visit (ClosureExprInnerTyped &expr) +{ + visit_closure_common (expr); + tokens.push_back (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); + visit (expr.get_return_type ()); + visit (expr.get_definition_block ()); +} + +void +TokenCollector::visit (ContinueExpr &expr) +{ + tokens.push_back (Rust::Token::make (CONTINUE, expr.get_locus ())); + if (expr.has_label ()) + visit (expr.get_label ()); +} + +void +TokenCollector::visit (BreakExpr &expr) +{ + tokens.push_back (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 ()); + tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); + visit (expr.get_to_expr ()); +} + +void +TokenCollector::visit (RangeFromExpr &expr) +{ + visit (expr.get_from_expr ()); + tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); +} + +void +TokenCollector::visit (RangeToExpr &expr) +{ + tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); + visit (expr.get_to_expr ()); +} + +void +TokenCollector::visit (RangeFullExpr &expr) +{ + tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); +} + +void +TokenCollector::visit (RangeFromToInclExpr &expr) +{ + visit (expr.get_from_expr ()); + tokens.push_back (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); + visit (expr.get_to_expr ()); +} + +void +TokenCollector::visit (RangeToInclExpr &expr) +{ + tokens.push_back (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); + visit (expr.get_to_expr ()); +} + +void +TokenCollector::visit (ReturnExpr &expr) +{ + tokens.push_back (Rust::Token::make (RETURN_TOK, expr.get_locus ())); + if (expr.has_returned_expr ()) + visit (expr.get_returned_expr ()); +} + +void +TokenCollector::visit (UnsafeBlockExpr &expr) +{ + tokens.push_back (Rust::Token::make (UNSAFE, expr.get_locus ())); + visit (expr.get_block_expr ()); +} + +void +TokenCollector::visit (LoopLabel &label) +{ + visit (label.get_lifetime ()); + tokens.push_back (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); + tokens.push_back (Rust::Token::make (LOOP, expr.get_locus ())); + visit (expr.get_loop_block ()); +} + +void +TokenCollector::visit (WhileLoopExpr &expr) +{ + visit_loop_common (expr); + tokens.push_back (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); + tokens.push_back (Rust::Token::make (WHILE, expr.get_locus ())); + tokens.push_back (Rust::Token::make (LET, Location ())); + // TODO: The reference mention only one Pattern + for (auto &item : expr.get_patterns ()) + { + visit (item); + } + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (expr.get_scrutinee_expr ()); + visit (expr.get_loop_block ()); +} + +void +TokenCollector::visit (ForLoopExpr &expr) +{ + visit_loop_common (expr); + tokens.push_back (Rust::Token::make (FOR, expr.get_locus ())); + visit (expr.get_pattern ()); + tokens.push_back (Rust::Token::make (IN, Location ())); + visit (expr.get_iterator_expr ()); + visit (expr.get_loop_block ()); +} + +void +TokenCollector::visit (IfExpr &expr) +{ + tokens.push_back (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 (expr)); + indentation (); + tokens.push_back (Rust::Token::make (ELSE, expr.get_locus ())); + visit (expr.get_else_block ()); +} + +void +TokenCollector::visit (IfLetExpr &expr) +{ + tokens.push_back (Rust::Token::make (IF, expr.get_locus ())); + tokens.push_back (Rust::Token::make (LET, Location ())); + for (auto &pattern : expr.get_patterns ()) + { + visit (pattern); + } + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (expr.get_value_expr ()); + visit (expr.get_if_block ()); +} + +void +TokenCollector::visit (IfLetExprConseqElse &expr) +{ + visit (static_cast (expr)); + indentation (); + tokens.push_back (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 ()) + { + tokens.push_back (Rust::Token::make (IF, Location ())); + visit (arm.get_guard_expr ()); + } +} + +void +TokenCollector::visit (MatchCase &match_case) +{ + visit (match_case.get_arm ()); + tokens.push_back (Rust::Token::make (MATCH_ARROW, Location ())); + visit (match_case.get_expr ()); + tokens.push_back (Rust::Token::make (COMMA, Location ())); +} + +void +TokenCollector::visit (MatchExpr &expr) +{ + tokens.push_back (Rust::Token::make (MATCH_TOK, expr.get_locus ())); + visit (expr.get_scrutinee_expr ()); + tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); + visit_items_as_lines (expr.get_inner_attrs ()); + for (auto &arm : expr.get_match_cases ()) + { + visit (arm); + } + tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); +} + +void +TokenCollector::visit (AwaitExpr &expr) +{ + visit (expr.get_awaited_expr ()); + tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); + // TODO: Check status of await keyword (Context dependant ?) + tokens.push_back (Rust::Token::make_identifier (Location (), "await")); +} + +void +TokenCollector::visit (AsyncBlockExpr &expr) +{ + tokens.push_back (Rust::Token::make (ASYNC, expr.get_locus ())); + if (expr.get_has_move ()) + tokens.push_back (Rust::Token::make (MOVE, Location ())); + visit (expr.get_block_expr ()); +} + +// rust-item.h + +void +TokenCollector::visit (TypeParam ¶m) +{ + // Syntax: + // IDENTIFIER( : TypeParamBounds? )? ( = Type )? + // TypeParamBounds : + // TypeParamBound ( + TypeParamBound )* +? + + auto id = param.get_type_representation (); + tokens.push_back ( + Rust::Token::make_identifier (param.get_locus (), std::move (id))); + if (param.has_type_param_bounds ()) + { + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit_items_joined_by_separator (param.get_type_param_bounds (), PLUS); + } + if (param.has_type ()) + { + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (param.get_type ()); + } +} + +void +TokenCollector::visit (WhereClause &rule) +{ + // Syntax: + // where ( WhereClauseItem , )* WhereClauseItem ? + // WhereClauseItem : + // LifetimeWhereClauseItem + // | TypeBoundWhereClauseItem + + tokens.push_back (Rust::Token::make (WHERE, 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 ()); + tokens.push_back (Rust::Token::make (COLON, 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 ()); + + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit_items_joined_by_separator (item.get_type_param_bounds (), PLUS); +} + +void +TokenCollector::visit (Method &method) +{ + visit (method.get_visibility ()); + auto method_name = method.get_method_name (); + tokens.push_back (Rust::Token::make (FN_TOK, method.get_locus ())); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (method_name))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + tokens.push_back (Rust::Token::make (SELF, Location ())); + if (!method.get_function_params ().empty ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit_items_joined_by_separator (method.get_function_params (), COMMA); + } + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + if (method.has_return_type ()) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (method.get_return_type ()); + } + + auto &block = method.get_definition (); + if (!block) + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + else + visit (block); + newline (); +} + +void +TokenCollector::visit (Module &module) +{ + // Syntax: + // mod IDENTIFIER ; + // | mod IDENTIFIER { + // InnerAttribute* + // Item* + // } + + visit (module.get_visibility ()); + auto name = module.get_name (); + tokens.push_back (Rust::Token::make (MOD, module.get_locus ())); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (name))); + + if (module.get_kind () == Module::UNLOADED) + { + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); + } + else /* Module::LOADED */ + { + tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); + newline (); + increment_indentation (); + + visit_items_as_lines (module.get_inner_attrs ()); + visit_items_as_lines (module.get_items ()); + + decrement_indentation (); + + tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); + newline (); + } +} + +void +TokenCollector::visit (ExternCrate &crate) +{ + tokens.push_back (Rust::Token::make (EXTERN_TOK, crate.get_locus ())); + tokens.push_back (Rust::Token::make (CRATE, Location ())); + auto ref = crate.get_referenced_crate (); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (ref))); + if (crate.has_as_clause ()) + { + auto as_clause = crate.get_as_clause (); + tokens.push_back (Rust::Token::make (AS, Location ())); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (as_clause))); + } + tokens.push_back (Rust::Token::make (SEMICOLON, 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); + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + } + break; + case UseTreeGlob::PathType::NO_PATH: + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + break; + case UseTreeGlob::PathType::GLOBAL: + break; + } + tokens.push_back (Rust::Token::make (ASTERISK, 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); + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + } + break; + case UseTreeList::PathType::NO_PATH: + tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); + break; + case UseTreeList::PathType::GLOBAL: + break; + } + + tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); + if (use_tree.has_trees ()) + { + visit_items_joined_by_separator (use_tree.get_trees (), COMMA); + } + tokens.push_back (Rust::Token::make (RIGHT_CURLY, 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: { + tokens.push_back (Rust::Token::make (AS, Location ())); + auto id = use_tree.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (use_tree.get_locus (), std::move (id))); + } + break; + case UseTreeRebind::NewBindType::WILDCARD: + tokens.push_back (Rust::Token::make (AS, Location ())); + tokens.push_back (Rust::Token::make (UNDERSCORE, use_tree.get_locus ())); + break; + case UseTreeRebind::NewBindType::NONE: + break; + } +} + +void +TokenCollector::visit (UseDeclaration &decl) +{ + tokens.push_back (Rust::Token::make (USE, decl.get_locus ())); + visit (*decl.get_tree ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); +} + +void +TokenCollector::visit (Function &function) +{ + // Syntax: + // FunctionQualifiers fn IDENTIFIER GenericParams? + // ( FunctionParameters? ) + // FunctionReturnType? WhereClause? + // ( BlockExpression | ; ) + + visit (function.get_visibility ()); + + tokens.push_back (Rust::Token::make (FN_TOK, function.get_locus ())); + auto name = function.get_function_name (); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (name))); + if (function.has_generics ()) + visit (function.get_generic_params ()); + + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (function.get_function_params ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + if (function.has_return_type ()) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (function.get_return_type ()); + } + + if (function.has_where_clause ()) + visit (function.get_where_clause ()); + + auto &block = function.get_definition (); + if (!block) + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + else + visit (block); + newline (); +} + +void +TokenCollector::visit (TypeAlias &type_alias) +{ + // Syntax: + // Visibility? type IDENTIFIER GenericParams? WhereClause? = Type; + + // Note: Associated types are handled by `AST::TraitItemType`. + + if (type_alias.has_visibility ()) + visit (type_alias.get_visibility ()); + auto alias_name = type_alias.get_new_type_name (); + tokens.push_back (Rust::Token::make (TYPE, type_alias.get_locus ())); + tokens.push_back ( + Rust::Token::make_identifier (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 ()); + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (type_alias.get_type_aliased ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +void +TokenCollector::visit (StructStruct &struct_item) +{ + if (struct_item.has_visibility ()) + visit (struct_item.get_visibility ()); + auto struct_name = struct_item.get_identifier (); + tokens.push_back (Rust::Token::make (STRUCT_TOK, struct_item.get_locus ())); + tokens.push_back ( + Rust::Token::make_identifier (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 ()) + { + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); + } + else + visit_items_as_block (struct_item.get_fields (), + {Rust::Token::make (COMMA, Location ())}); +} + +void +TokenCollector::visit (TupleStruct &tuple_struct) +{ + auto struct_name = tuple_struct.get_identifier (); + tokens.push_back (Rust::Token::make (STRUCT_TOK, tuple_struct.get_locus ())); + tokens.push_back ( + Rust::Token::make_identifier (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 ()); + + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (tuple_struct.get_fields (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); +} + +void +TokenCollector::visit (EnumItem &item) +{ + auto id = item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (item.get_locus (), std::move (id))); +} + +void +TokenCollector::visit (EnumItemTuple &item) +{ + auto id = item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (item.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (item.get_tuple_fields (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (EnumItemStruct &item) +{ + auto id = item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (item.get_locus (), std::move (id))); + visit_items_as_block (item.get_struct_fields (), + {Rust::Token::make (COMMA, Location ())}); +} + +void +TokenCollector::visit (EnumItemDiscriminant &item) +{ + auto id = item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (item.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (item.get_expr ()); +} + +void +TokenCollector::visit (Enum &enumeration) +{ + if (enumeration.has_visibility ()) + visit (enumeration.get_visibility ()); + tokens.push_back (Rust::Token::make (ENUM_TOK, enumeration.get_locus ())); + auto id = enumeration.get_identifier (); + tokens.push_back ( + 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, Location ())}); +} + +void +TokenCollector::visit (Union &union_item) +{ + visit_items_as_lines (union_item.get_outer_attrs ()); + auto id = union_item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (union_item.get_locus (), "union")); + tokens.push_back (Rust::Token::make_identifier (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, Location ())}); +} + +void +TokenCollector::visit (ConstantItem &item) +{ + tokens.push_back (Rust::Token::make (CONST, item.get_locus ())); + if (item.is_unnamed ()) + { + tokens.push_back (Rust::Token::make (UNDERSCORE, Location ())); + } + else + { + auto id = item.get_identifier (); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (id))); + } + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (item.get_type ()); + if (item.has_expr ()) + { + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (item.get_expr ()); + } + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +void +TokenCollector::visit (StaticItem &item) +{ + tokens.push_back (Rust::Token::make (STATIC_TOK, item.get_locus ())); + if (item.is_mutable ()) + tokens.push_back (Rust::Token::make (MUT, Location ())); + auto id = item.get_identifier (); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (item.get_type ()); + if (item.has_expr ()) + { + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (item.get_expr ()); + } + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +void +TokenCollector::visit_function_common (std::unique_ptr &return_type, + std::unique_ptr &block) +{ + // FIXME: This should format the ` fn ( [args] )` as well + if (return_type) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (return_type); + } + + if (block) + { + visit (block); + } + else + { + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); + } +} + +void +TokenCollector::visit (TraitItemFunc &item) +{ + auto func = item.get_trait_function_decl (); + auto id = func.get_identifier (); + tokens.push_back (Rust::Token::make (FN_TOK, item.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit_items_joined_by_separator (func.get_function_params ()); + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + visit_function_common (func.get_return_type (), item.get_definition ()); +} + +void +TokenCollector::visit (SelfParam ¶m) +{ + if (param.get_has_ref ()) + { + tokens.push_back (Rust::Token::make (AMP, param.get_locus ())); + if (param.has_lifetime ()) + { + auto lifetime = param.get_lifetime (); + visit (lifetime); + } + } + + if (param.get_is_mut ()) + { + tokens.push_back (Rust::Token::make (MUT, Location ())); + } + + tokens.push_back (Rust::Token::make (SELF, Location ())); +} + +void +TokenCollector::visit (TraitItemMethod &item) +{ + auto method = item.get_trait_method_decl (); + auto id = method.get_identifier (); + + tokens.push_back (Rust::Token::make (FN_TOK, item.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit (method.get_self_param ()); + + if (!method.get_function_params ().empty ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit_items_joined_by_separator (method.get_function_params (), COMMA); + } + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + visit_function_common (method.get_return_type (), item.get_definition ()); +} + +void +TokenCollector::visit (TraitItemConst &item) +{ + auto id = item.get_identifier (); + indentation (); + tokens.push_back (Rust::Token::make (CONST, item.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (item.get_type ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + newline (); +} + +void +TokenCollector::visit (TraitItemType &item) +{ + auto id = item.get_identifier (); + indentation (); + tokens.push_back (Rust::Token::make (TYPE, item.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (SEMICOLON, 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 (); + tokens.push_back (Rust::Token::make (TRAIT, trait.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + + // Traits actually have an implicit Self thrown at the start, so we must + // expect the number of generic params to be > 1 + if (trait.get_generic_params ().size () > 1) + { + tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); + visit_items_joined_by_separator (trait.get_generic_params (), COMMA, 1); + tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); + } + + visit_items_as_block (trait.get_trait_items (), {}); +} + +void +TokenCollector::visit (InherentImpl &impl) +{ + tokens.push_back (Rust::Token::make (IMPL, impl.get_locus ())); + // FIXME: Handle generics + + 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) +{ + tokens.push_back (Rust::Token::make (IMPL, impl.get_locus ())); + visit (impl.get_trait_path ()); + tokens.push_back (Rust::Token::make (FOR, Location ())); + visit (impl.get_type ()); + tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); + newline (); + + increment_indentation (); + + for (auto &item : impl.get_impl_items ()) + { + indentation (); + visit (item); + } + + decrement_indentation (); + newline (); + + tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); + newline (); +} + +void +TokenCollector::visit (ExternalTypeItem &type) +{ + visit (type.get_visibility ()); + + auto id = type.get_identifier (); + tokens.push_back (Rust::Token::make (TYPE, Location ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +void +TokenCollector::visit (ExternalStaticItem &item) +{ + auto id = item.get_identifier (); + visit_items_as_lines (item.get_outer_attrs ()); + if (item.has_visibility ()) + visit (item.get_visibility ()); + tokens.push_back (Rust::Token::make (STATIC_TOK, item.get_locus ())); + if (item.is_mut ()) + tokens.push_back (Rust::Token::make (MUT, Location ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (item.get_type ()); + // TODO: No expr ? The "(= Expression)?" part from the reference seems missing + // in the ast. + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +void +TokenCollector::visit (ExternalFunctionItem &function) +{ + visit (function.get_visibility ()); + + auto id = function.get_identifier (); + tokens.push_back (Rust::Token::make (FN_TOK, function.get_locus ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit_items_joined_by_separator (function.get_function_params ()); + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + if (function.has_return_type ()) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (function.get_return_type ()); + } +} + +void +TokenCollector::visit (ExternBlock &block) +{ + tokens.push_back (Rust::Token::make (EXTERN_TOK, block.get_locus ())); + + if (block.has_abi ()) + { + auto abi = block.get_abi (); + tokens.push_back ( + Rust::Token::make_string (Location (), std::move (abi))); + } + + visit_items_as_block (block.get_extern_items ()); +} + +static std::pair +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: + gcc_unreachable (); + } +} + +void +TokenCollector::visit (MacroMatchFragment &match) +{ + auto id = match.get_ident (); + auto frag_spec = match.get_frag_spec ().as_string (); + tokens.push_back (Rust::Token::make (DOLLAR_SIGN, Location ())); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (Rust::Token::make (COLON, Location ())); + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (frag_spec))); +} + +void +TokenCollector::visit (MacroMatchRepetition &repetition) +{ + tokens.push_back (Rust::Token::make (DOLLAR_SIGN, Location ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit_items_joined_by_separator (repetition.get_matches (), {}); + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + if (repetition.has_sep ()) + { + tokens.push_back ( + Rust::Token::make (repetition.get_sep ()->get_id (), + repetition.get_sep ()->get_locus ())); + } + switch (repetition.get_op ()) + { + case MacroMatchRepetition::ANY: + tokens.push_back (Rust::Token::make (ASTERISK, Location ())); + break; + case MacroMatchRepetition::ONE_OR_MORE: + tokens.push_back (Rust::Token::make (PLUS, Location ())); + break; + case MacroMatchRepetition::ZERO_OR_ONE: + tokens.push_back (Rust::Token::make (QUESTION_MARK, Location ())); + break; + case MacroMatchRepetition::NONE: + break; + } +} + +void +TokenCollector::visit (MacroMatcher &matcher) +{ + auto delimiters = get_delimiters (matcher.get_delim_type ()); + + tokens.push_back (Rust::Token::make (delimiters.first, Location ())); + + for (auto &item : matcher.get_matches ()) + { + visit (item); + } + + tokens.push_back (Rust::Token::make (delimiters.second, Location ())); +} + +void +TokenCollector::visit (MacroRule &rule) +{ + visit (rule.get_matcher ()); + tokens.push_back (Rust::Token::make (MATCH_ARROW, rule.get_locus ())); + visit (rule.get_transcriber ().get_token_tree ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); +} + +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 (); + tokens.push_back ( + Rust::Token::make_identifier (rules_def.get_locus (), "macro_rules")); + tokens.push_back (Rust::Token::make (EXCLAM, Location ())); + + tokens.push_back ( + Rust::Token::make_identifier (Location (), std::move (rule_name))); + + visit_items_as_block (rules_def.get_rules (), + {Rust::Token::make (SEMICOLON, Location ())}); +} + +void +TokenCollector::visit (MacroInvocation &invocation) +{ + auto data = invocation.get_invoc_data (); + visit (data.get_path ()); + tokens.push_back (Rust::Token::make (EXCLAM, Location ())); + visit (data.get_delim_tok_tree ()); + if (invocation.has_semicolon ()) + tokens.push_back (Rust::Token::make (SEMICOLON, 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. + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (item.get_seq (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (MetaWord &word) +{ + auto id = word.get_ident (); + tokens.push_back ( + 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); + auto value = std::get<1> (pair); + tokens.push_back ( + Rust::Token::make_identifier (name.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (EQUAL, name.get_locus ())); + tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); + tokens.push_back ( + Rust::Token::make_identifier (name.get_locus (), std::move (value))); + tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); +} + +void +TokenCollector::visit (MetaListPaths &list) +{ + auto id = list.get_ident (); + tokens.push_back ( + Rust::Token::make_identifier (list.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (list.get_paths (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (MetaListNameValueStr &list) +{ + auto id = list.get_ident (); + tokens.push_back ( + Rust::Token::make_identifier (list.get_locus (), std::move (id))); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + visit_items_joined_by_separator (list.get_values (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, 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 ()) + { + tokens.push_back (Rust::Token::make (REF, pattern.get_locus ())); + } + if (pattern.get_is_mut ()) + { + tokens.push_back (Rust::Token::make (MUT, Location ())); + } + auto id = pattern.get_ident (); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + if (pattern.has_pattern_to_bind ()) + { + tokens.push_back (Rust::Token::make (PATTERN_BIND, Location ())); + visit (pattern.get_pattern_to_bind ()); + } +} + +void +TokenCollector::visit (WildcardPattern &pattern) +{ + tokens.push_back (Rust::Token::make (UNDERSCORE, pattern.get_locus ())); +} + +void +TokenCollector::visit (RestPattern &pattern) +{ + tokens.push_back (Rust::Token::make (DOT_DOT, pattern.get_locus ())); +} + +// void TokenCollector::visit(RangePatternBound& ){} + +void +TokenCollector::visit (RangePatternBoundLiteral &pattern) +{ + if (pattern.get_has_minus ()) + { + tokens.push_back (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 ()) + tokens.push_back (Rust::Token::make (ELLIPSIS, pattern.get_locus ())); + else + tokens.push_back (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 ()); + tokens.push_back (Rust::Token::make (DOT_DOT, pattern.get_locus ())); + } + else + { + tokens.push_back (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ())); + visit (pattern.get_upper_bound ()); + } +} + +void +TokenCollector::visit (ReferencePattern &pattern) +{ + if (pattern.is_double_reference ()) + { + tokens.push_back (Rust::Token::make (LOGICAL_AND, pattern.get_locus ())); + } + else + { + tokens.push_back (Rust::Token::make (AMP, pattern.get_locus ())); + } + + if (pattern.get_is_mut ()) + { + tokens.push_back (Rust::Token::make (MUT, Location ())); + } + + visit (pattern.get_referenced_pattern ()); +} + +// void TokenCollector::visit(StructPatternField& ){} + +void +TokenCollector::visit (StructPatternFieldTuplePat &pattern) +{ + visit_items_as_lines (pattern.get_outer_attrs ()); + tokens.push_back ( + Rust::Token::make_int (pattern.get_locus (), + std::to_string (pattern.get_index ()))); + tokens.push_back (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 (); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); + tokens.push_back (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 ()) + tokens.push_back (Rust::Token::make (REF, Location ())); + if (pattern.is_mut ()) + tokens.push_back (Rust::Token::make (MUT, Location ())); + + auto id = pattern.get_identifier (); + tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); +} + +void +TokenCollector::visit (StructPattern &pattern) +{ + visit (pattern.get_path ()); + tokens.push_back (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 ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + visit_items_as_lines (elems.get_etc_outer_attrs ()); + } + } + else + { + visit_items_as_lines (elems.get_etc_outer_attrs ()); + } + + tokens.push_back (Rust::Token::make (RIGHT_CURLY, 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); + } + tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); + for (auto &upper : pattern.get_lower_patterns ()) + { + visit (upper); + } +} + +void +TokenCollector::visit (TupleStructPattern &pattern) +{ + visit (pattern.get_path ()); + tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); + if (pattern.has_items ()) + visit (pattern.get_items ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, 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); + } + tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); + for (auto &upper : pattern.get_lower_patterns ()) + { + visit (upper); + } +} + +void +TokenCollector::visit (TuplePattern &pattern) +{ + tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); + visit (pattern.get_items ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (GroupedPattern &pattern) +{ + tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); + visit (pattern.get_pattern_in_parens ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (SlicePattern &pattern) +{ + tokens.push_back (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); + visit_items_joined_by_separator (pattern.get_items (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, 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) +{ + tokens.push_back (Rust::Token::make (LET, stmt.get_locus ())); + auto &pattern = stmt.get_pattern (); + if (pattern) + visit (pattern); + + if (stmt.has_type ()) + { + tokens.push_back (Rust::Token::make (COLON, Location ())); + visit (stmt.get_type ()); + } + + if (stmt.has_init_expr ()) + { + tokens.push_back (Rust::Token::make (EQUAL, Location ())); + visit (stmt.get_init_expr ()); + } +} + +void +TokenCollector::visit (ExprStmtWithoutBlock &stmt) +{ + visit (stmt.get_expr ()); +} + +void +TokenCollector::visit (ExprStmtWithBlock &stmt) +{ + visit (stmt.get_expr ()); +} + +// rust-type.h +void +TokenCollector::visit (TraitBound &bound) +{ + // Syntax: + // ?? ForLifetimes? TypePath + // | ( ?? ForLifetimes? TypePath ) + + if (bound.has_opening_question_mark ()) + tokens.push_back (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 )* +? + + tokens.push_back (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 ()) + tokens.push_back (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 ) + + tokens.push_back (Rust::Token::make (LEFT_PAREN, type.get_locus ())); + visit (type.get_type_in_parens ()); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (ImplTraitTypeOneBound &type) +{ + // Syntax: + // impl TraitBound + + tokens.push_back (Rust::Token::make (IMPL, type.get_locus ())); + visit (type.get_trait_bound ()); +} + +void +TokenCollector::visit (TraitObjectTypeOneBound &type) +{ + // Syntax: + // dyn? TraitBound + + if (type.is_dyn ()) + tokens.push_back (Rust::Token::make (DYN, type.get_locus ())); + visit (type.get_trait_bound ()); +} + +void +TokenCollector::visit (TupleType &type) +{ + // Syntax: + // ( ) + // | ( ( Type , )+ Type? ) + + tokens.push_back (Rust::Token::make (LEFT_PAREN, type.get_locus ())); + visit_items_joined_by_separator (type.get_elems (), COMMA); + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); +} + +void +TokenCollector::visit (NeverType &type) +{ + // Syntax: + // ! + + tokens.push_back (Rust::Token::make (EXCLAM, type.get_locus ())); +} + +void +TokenCollector::visit (RawPointerType &type) +{ + // Syntax: + // * ( mut | const ) TypeNoBounds + + tokens.push_back (Rust::Token::make (ASTERISK, type.get_locus ())); + if (type.get_pointer_type () == RawPointerType::MUT) + tokens.push_back (Rust::Token::make (MUT, Location ())); + else /* RawPointerType::CONST */ + tokens.push_back (Rust::Token::make (CONST, Location ())); + + visit (type.get_type_pointed_to ()); +} + +void +TokenCollector::visit (ReferenceType &type) +{ + // Syntax: + // & Lifetime? mut? TypeNoBounds + + tokens.push_back (Rust::Token::make (AMP, type.get_locus ())); + + if (type.has_lifetime ()) + { + visit (type.get_lifetime ()); + } + + if (type.get_has_mut ()) + tokens.push_back (Rust::Token::make (MUT, Location ())); + + visit (type.get_type_referenced ()); +} + +void +TokenCollector::visit (ArrayType &type) +{ + // Syntax: + // [ Type ; Expression ] + + tokens.push_back (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); + visit (type.get_elem_type ()); + tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); + visit (type.get_size_expr ()); + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); +} + +void +TokenCollector::visit (SliceType &type) +{ + // Syntax: + // [ Type ] + + tokens.push_back (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); + visit (type.get_elem_type ()); + tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); +} + +void +TokenCollector::visit (InferredType &type) +{ + // Syntax: + // _ + + tokens.push_back (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 ()); + + tokens.push_back (Rust::Token::make (FN_TOK, type.get_locus ())); + tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); + + visit_items_joined_by_separator (type.get_function_params (), COMMA); + + if (type.is_variadic ()) + { + tokens.push_back (Rust::Token::make (COMMA, Location ())); + for (auto &item : type.get_variadic_attr ()) + { + visit (item); + } + tokens.push_back (Rust::Token::make (ELLIPSIS, Location ())); + } + + tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); + + if (type.has_return_type ()) + { + tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); + visit (type.get_return_type ()); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h new file mode 100644 index 0000000..01c7e7c --- /dev/null +++ b/gcc/rust/ast/rust-ast-collector.h @@ -0,0 +1,317 @@ +// Copyright (C) 2020-2023 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 +// . + +#ifndef RUST_AST_TOKENSTREAM_H +#define RUST_AST_TOKENSTREAM_H + +#include "rust-token.h" +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-ast-full.h" + +#include "libproc_macro/tokenstream.h" + +namespace Rust { +namespace AST { + +class TokenCollector : public ASTVisitor +{ +public: + TokenCollector (std::vector &container); + bool output_trailing_commas = false; + + void visit (AST::Crate &crate); + void visit (AST::Item &item); + + std::vector collect_tokens () const; + + ProcMacro::TokenStream collect () const; + +private: + std::vector &tokens; + + /** + * Compatibility layer for using the visitor pattern on polymorphic classes + * with a unified overload syntax. This allows us to call `visit` both on + * types implementing `accept_vis` method and for classes for which the + * `visit` method is directly implemented. + */ + template void visit (std::unique_ptr &node); + + /** + * @see visit> + */ + template void visit (T &node); + + /** + * Visit all items in given @collection, placing the separator in between but + * not at the end. + */ + template + void visit_items_joined_by_separator (T &collection, + TokenId separator = COMMA, + size_t start_offset = 0, + size_t end_offset = 0); + + /** + * Visit item placing end of line after. + */ + template + void visit_as_line (T &item, std::vector trailing = {}); + + /** + * Visit each item in @collection "as line". + * + * @see visit_as_line + */ + template + void visit_items_as_lines (T &collection, + std::vector trailing = {}); + + /** + * Visit each item in @collection as lines inside a block delimited by braces + * with increased indentation. Also includes special handling for empty + * collection to print only the delimiters with no new line inside. + */ + template + void visit_items_as_block (T &collection, std::vector trailing = {}, + TokenId left_brace = LEFT_CURLY, + TokenId right_brace = RIGHT_CURLY); + + void trailing_comma (); + void newline (); + void indentation (); + void increment_indentation (); + void decrement_indentation (); + /** + * Visit common items of functions: Parameters, return type, block + */ + void visit_function_common (std::unique_ptr &return_type, + std::unique_ptr &block); + + void visit_closure_common (ClosureExpr &expr); + + void visit_loop_common (BaseLoopExpr &expr); + void visit (LoopLabel &label); + + void visit (Literal &lit, Location locus = {}); + + void visit (FunctionParam ¶m); + void visit (Attribute &attrib); + void visit (Visibility &vis); + void visit (std::vector> ¶ms); + void visit (TupleField &field); + void visit (StructField &field); + void visit (SimplePathSegment &segment); + void visit (NamedFunctionParam ¶m); + void visit (MacroRule &rule); + void visit (WhereClause &rule); + void visit (std::vector &for_lifetimes); + void visit (FunctionQualifiers &qualifiers); + void visit (MaybeNamedParam ¶m); + void visit (TypePathFunction &type_path_fn); + void visit (GenericArgsBinding &binding); + void visit (GenericArg &arg); + + // rust-ast.h + void visit (Token &tok); + void visit (DelimTokenTree &delim_tok_tree); + void visit (AttrInputMetaItemContainer &input); + void visit (IdentifierExpr &ident_expr); + void visit (Lifetime &lifetime); + void visit (LifetimeParam &lifetime_param); + void visit (ConstGenericParam &const_param); + + // rust-path.h + void visit (SimplePath &path); + void visit (PathExprSegment &segment); + void visit (PathIdentSegment &segment); + void visit (PathInExpression &path); + void visit (TypePathSegment &segment); + void visit (TypePathSegmentGeneric &segment); + void visit (TypePathSegmentFunction &segment); + void visit (TypePath &path); + void visit (QualifiedPathType &path); + void visit (QualifiedPathInExpression &path); + void visit (QualifiedPathInType &path); + + // rust-expr.h + void visit (LiteralExpr &expr); + void visit (AttrInputLiteral &attr_input); + void visit (MetaItemLitExpr &meta_item); + void visit (MetaItemPathLit &meta_item); + void visit (BorrowExpr &expr); + void visit (DereferenceExpr &expr); + void visit (ErrorPropagationExpr &expr); + void visit (NegationExpr &expr); + void visit (ArithmeticOrLogicalExpr &expr); + void visit (ComparisonExpr &expr); + void visit (LazyBooleanExpr &expr); + void visit (TypeCastExpr &expr); + void visit (AssignmentExpr &expr); + void visit (CompoundAssignmentExpr &expr); + void visit (GroupedExpr &expr); + void visit (ArrayElemsValues &elems); + void visit (ArrayElemsCopied &elems); + void visit (ArrayExpr &expr); + void visit (ArrayIndexExpr &expr); + void visit (TupleExpr &expr); + void visit (TupleIndexExpr &expr); + void visit (StructExprStruct &expr); + void visit (StructExprFieldIdentifier &field); + void visit (StructExprFieldIdentifierValue &field); + void visit (StructExprFieldIndexValue &field); + void visit (StructBase &base); + void visit (StructExprStructFields &expr); + void visit (StructExprStructBase &expr); + void visit (CallExpr &expr); + void visit (MethodCallExpr &expr); + void visit (FieldAccessExpr &expr); + void visit (ClosureParam ¶m); + void visit (ClosureExprInner &expr); + void visit (BlockExpr &expr); + void visit (ClosureExprInnerTyped &expr); + void visit (ContinueExpr &expr); + void visit (BreakExpr &expr); + void visit (RangeFromToExpr &expr); + void visit (RangeFromExpr &expr); + void visit (RangeToExpr &expr); + void visit (RangeFullExpr &expr); + void visit (RangeFromToInclExpr &expr); + void visit (RangeToInclExpr &expr); + void visit (ReturnExpr &expr); + void visit (UnsafeBlockExpr &expr); + void visit (LoopExpr &expr); + void visit (WhileLoopExpr &expr); + void visit (WhileLetLoopExpr &expr); + void visit (ForLoopExpr &expr); + void visit (IfExpr &expr); + void visit (IfExprConseqElse &expr); + void visit (IfLetExpr &expr); + void visit (IfLetExprConseqElse &expr); + void visit (MatchArm &arm); + void visit (MatchCase &arm); + void visit (MatchExpr &expr); + void visit (AwaitExpr &expr); + void visit (AsyncBlockExpr &expr); + + // rust-item.h + void visit (TypeParam ¶m); + void visit (LifetimeWhereClauseItem &item); + void visit (TypeBoundWhereClauseItem &item); + void visit (Method &method); + void visit (Module &module); + void visit (ExternCrate &crate); + void visit (UseTreeGlob &use_tree); + void visit (UseTreeList &use_tree); + void visit (UseTreeRebind &use_tree); + void visit (UseDeclaration &use_decl); + void visit (Function &function); + void visit (TypeAlias &type_alias); + void visit (StructStruct &struct_item); + void visit (TupleStruct &tuple_struct); + void visit (EnumItem &item); + void visit (EnumItemTuple &item); + void visit (EnumItemStruct &item); + void visit (EnumItemDiscriminant &item); + void visit (Enum &enum_item); + void visit (Union &union_item); + void visit (ConstantItem &const_item); + void visit (StaticItem &static_item); + void visit (TraitItemFunc &item); + void visit (SelfParam ¶m); + void visit (TraitItemMethod &item); + void visit (TraitItemConst &item); + void visit (TraitItemType &item); + void visit (Trait &trait); + void visit (InherentImpl &impl); + void visit (TraitImpl &impl); + void visit (ExternalTypeItem &item); + void visit (ExternalStaticItem &item); + void visit (ExternalFunctionItem &item); + void visit (ExternBlock &block); + + // rust-macro.h + void visit (MacroMatchFragment &match); + void visit (MacroMatchRepetition &match); + void visit (MacroMatcher &matcher); + void visit (MacroRulesDefinition &rules_def); + void visit (MacroInvocData &invoc_data); + void visit (MacroInvocation ¯o_invoc); + void visit (MetaItemPath &meta_item); + void visit (MetaItemSeq &meta_item); + void visit (MetaWord &meta_item); + void visit (MetaNameValueStr &meta_item); + void visit (MetaListPaths &meta_item); + void visit (MetaListNameValueStr &meta_item); + + // rust-pattern.h + void visit (LiteralPattern &pattern); + void visit (IdentifierPattern &pattern); + void visit (WildcardPattern &pattern); + void visit (RestPattern &pattern); + // void visit(RangePatternBound& bound); + void visit (RangePatternBoundLiteral &bound); + void visit (RangePatternBoundPath &bound); + void visit (RangePatternBoundQualPath &bound); + void visit (RangePattern &pattern); + void visit (ReferencePattern &pattern); + // void visit(StructPatternField& field); + void visit (StructPatternFieldTuplePat &field); + void visit (StructPatternFieldIdentPat &field); + void visit (StructPatternFieldIdent &field); + void visit (StructPattern &pattern); + // void visit(TupleStructItems& tuple_items); + void visit (TupleStructItemsNoRange &tuple_items); + void visit (TupleStructItemsRange &tuple_items); + void visit (TupleStructPattern &pattern); + // void visit(TuplePatternItems& tuple_items); + void visit (TuplePatternItemsMultiple &tuple_items); + void visit (TuplePatternItemsRanged &tuple_items); + void visit (TuplePattern &pattern); + void visit (GroupedPattern &pattern); + void visit (SlicePattern &pattern); + void visit (AltPattern &pattern); + + // rust-stmt.h + void visit (EmptyStmt &stmt); + void visit (LetStmt &stmt); + void visit (ExprStmtWithoutBlock &stmt); + void visit (ExprStmtWithBlock &stmt); + + // rust-type.h + void visit (TraitBound &bound); + void visit (ImplTraitType &type); + void visit (TraitObjectType &type); + void visit (ParenthesisedType &type); + void visit (ImplTraitTypeOneBound &type); + void visit (TraitObjectTypeOneBound &type); + void visit (TupleType &type); + void visit (NeverType &type); + void visit (RawPointerType &type); + void visit (ReferenceType &type); + void visit (ArrayType &type); + void visit (SliceType &type); + void visit (InferredType &type); + void visit (BareFunctionType &type); +}; +} // namespace AST + +} // namespace Rust + +#endif // !RUST_AST_TOKENSTREAM_H diff --git a/gcc/rust/ast/rust-ast-tokenstream.cc b/gcc/rust/ast/rust-ast-tokenstream.cc deleted file mode 100644 index 41db77b..0000000 --- a/gcc/rust/ast/rust-ast-tokenstream.cc +++ /dev/null @@ -1,3188 +0,0 @@ -// Copyright (C) 2020-2023 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 -// . -#include "rust-ast-tokenstream.h" -#include "libproc_macro/proc_macro.h" - -namespace Rust { -namespace AST { - -TokenCollector::TokenCollector (std::vector &container) - : tokens (container) -{} - -std::vector -TokenCollector::collect_tokens () const -{ - return tokens; -} - -static void -pop_group (std::vector &streams, - ProcMacro::Delimiter delim) -{ - auto g = ProcMacro::Group::make_group (streams.back (), delim); - streams.pop_back (); - auto tt = ProcMacro::TokenTree::make_tokentree (g); - - streams.back ().push (tt); -} - -static void -dispatch_float_literals (ProcMacro::TokenStream &ts, TokenPtr &token) -{ - std::string::size_type sz; - auto str = token->as_string (); - switch (token->get_type_hint ()) - { - case CORETYPE_F32: { - auto value = std::stof (str, &sz); - bool suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_f32 (value, suffixed))); - } - break; - case CORETYPE_F64: { - auto value = std::stod (str, &sz); - bool suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_f64 (value, suffixed))); - } - break; - default: - gcc_unreachable (); - } -} - -static void -dispatch_integer_literals (ProcMacro::TokenStream &ts, TokenPtr &token) -{ - std::string::size_type sz; - auto str = token->as_string (); - unsigned long long uvalue; - long long svalue; - bool suffixed = false; - - switch (token->get_type_hint ()) - { - case CORETYPE_U8: - uvalue = std::stoull (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_u8 (uvalue, suffixed))); - break; - case CORETYPE_U16: - uvalue = std::stoull (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_u16 (uvalue, suffixed))); - break; - case CORETYPE_U32: - uvalue = std::stoull (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_u32 (uvalue, suffixed))); - break; - case CORETYPE_U64: - uvalue = std::stoull (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_u32 (uvalue, suffixed))); - break; - case CORETYPE_I8: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_i8 (svalue, suffixed))); - break; - case CORETYPE_I16: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_i16 (svalue, suffixed))); - break; - case CORETYPE_I32: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_i32 (svalue, suffixed))); - break; - case CORETYPE_I64: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_i32 (svalue, suffixed))); - break; - case CORETYPE_INT: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_isize (svalue, suffixed))); - break; - case CORETYPE_UINT: - uvalue = std::stoull (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_usize (uvalue, suffixed))); - break; - case CORETYPE_UNKNOWN: - svalue = std::stoll (str, &sz); - suffixed = sz == str.length (); - ts.push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_i32 (svalue, false))); - break; - default: - gcc_unreachable (); - break; - } -} - -ProcMacro::TokenStream -TokenCollector::collect () const -{ - std::vector trees; - trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); - for (auto &token : collect_tokens ()) - { - switch (token->get_id ()) - { - // Literals - case FLOAT_LITERAL: - dispatch_float_literals (trees.back (), token); - break; - case INT_LITERAL: - dispatch_integer_literals (trees.back (), token); - break; - // FIXME: Why does BYTE_CHAR_LITERAL is not handled by rustc ? - case CHAR_LITERAL: // TODO: UTF-8 handling - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_char (token->as_string ()[0]))); - break; - case STRING_LITERAL: - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_string (token->as_string ()))); - break; - case BYTE_STRING_LITERAL: { - auto str = token->as_string (); - std::vector data (str.begin (), str.end ()); - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Literal::make_byte_string (data))); - } - break; - // Ident - case IDENTIFIER: - case ABSTRACT: - case AS: - case ASYNC: - case AUTO: - case BECOME: - case BOX: - case BREAK: - case CONST: - case CONTINUE: - case CRATE: - case DO: - case DYN: - case ELSE: - case ENUM_TOK: - case EXTERN_TOK: - case FINAL_TOK: - case FN_TOK: - case FOR: - case IF: - case IMPL: - case IN: - case LET: - case LOOP: - case MACRO: - case MATCH_TOK: - case MOD: - case MOVE: - case MUT: - case OVERRIDE_TOK: - case PRIV: - case PUB: - case REF: - case RETURN_TOK: - case SELF_ALIAS: - case SELF: - case STATIC_TOK: - case STRUCT_TOK: - case SUPER: - case TRAIT: - case TRY: - case TYPE: - case TYPEOF: - case UNSAFE: - case UNSIZED: - case USE: - case VIRTUAL: - case WHERE: - case WHILE: - case YIELD: - // Underscore is not a Punct, considered as an Ident - case UNDERSCORE: - // True and false are idents, not literals - // (https://doc.rust-lang.org/proc_macro/struct.Literal.html) - case FALSE_LITERAL: - case TRUE_LITERAL: - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Ident::make_ident (token->as_string ()))); - break; - // Joint punct - case OR: - case PIPE_EQ: - case CARET_EQ: - case RIGHT_SHIFT_EQ: - case RIGHT_SHIFT: - case GREATER_OR_EQUAL: - case MATCH_ARROW: - case LESS_OR_EQUAL: - case LEFT_SHIFT_EQ: - case LEFT_SHIFT: - case DIV_EQ: - case ELLIPSIS: - case DOT_DOT_EQ: - case DOT_DOT: - case RETURN_TYPE: - case MINUS_EQ: - case PLUS_EQ: - case ASTERISK_EQ: - case LOGICAL_AND: - case AMP_EQ: - case PERCENT_EQ: - case SCOPE_RESOLUTION: - case NOT_EQUAL: - case EQUAL_EQUAL: { - auto str = token->as_string (); - auto it = str.cbegin (); - for (; it != str.cend () - 1; it++) - { - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Punct::make_punct (*it, ProcMacro::JOINT))); - } - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Punct::make_punct (*it, ProcMacro::ALONE))); - } - break; - // Alone punct tokens - case EQUAL: - case RIGHT_ANGLE: - case LEFT_ANGLE: - case EXCLAM: - case TILDE: - case PLUS: - case MINUS: - case ASTERISK: - case DIV: - case PERCENT: - case CARET: - case AMP: - case PIPE: - case PATTERN_BIND: - case DOT: - case COMMA: - case SEMICOLON: - case COLON: - case HASH: - case DOLLAR_SIGN: - case QUESTION_MARK: - case SINGLE_QUOTE: - trees.back ().push (ProcMacro::TokenTree::make_tokentree ( - ProcMacro::Punct::make_punct (token->as_string ()[0], - ProcMacro::ALONE))); - break; - case RIGHT_PAREN: - pop_group (trees, ProcMacro::PARENTHESIS); - break; - case RIGHT_CURLY: - pop_group (trees, ProcMacro::BRACE); - break; - case RIGHT_SQUARE: - pop_group (trees, ProcMacro::BRACKET); - break; - case LEFT_SQUARE: - case LEFT_CURLY: - case LEFT_PAREN: - trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); - break; - default: - gcc_unreachable (); - } - } - return trees.back (); -} - -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); -} - -template -void -TokenCollector::visit (std::unique_ptr &node) -{ - node->accept_vis (*this); -} - -template -void -TokenCollector::visit (T &node) -{ - node.accept_vis (*this); -} - -template -void -TokenCollector::visit_items_joined_by_separator (T &collection, - TokenId separator, - size_t start_offset, - size_t end_offset) -{ - if (collection.size () > start_offset) - { - visit (collection.at (start_offset)); - auto size = collection.size () - end_offset; - for (size_t i = start_offset + 1; i < size; i++) - { - tokens.push_back (Rust::Token::make (separator, Location ())); - visit (collection.at (i)); - } - } -} - -template -void -TokenCollector::visit_as_line (T &item, std::vector trailing) -{ - indentation (); - visit (item); - for (auto &token : trailing) - tokens.push_back (token); - newline (); -} - -template -void -TokenCollector::visit_items_as_lines (T &collection, - std::vector trailing) -{ - for (auto &item : collection) - visit_as_line (item, trailing); -} - -template -void -TokenCollector::visit_items_as_block (T &collection, - std::vector trailing, - TokenId left_brace, TokenId right_brace) -{ - tokens.push_back (Rust::Token::make (left_brace, Location ())); - if (collection.empty ()) - { - tokens.push_back (Rust::Token::make (right_brace, Location ())); - newline (); - } - else - { - newline (); - increment_indentation (); - visit_items_as_lines (collection, trailing); - decrement_indentation (); - indentation (); - tokens.push_back (Rust::Token::make (right_brace, Location ())); - newline (); - } -} - -void -TokenCollector::trailing_comma () -{ - if (output_trailing_commas) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - } -} - -void -TokenCollector::newline () -{} - -void -TokenCollector::indentation () -{} - -void -TokenCollector::increment_indentation () -{} - -void -TokenCollector::decrement_indentation () -{} - -void -TokenCollector::visit (FunctionParam ¶m) -{ - visit (param.get_pattern ()); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (param.get_type ()); -} - -void -TokenCollector::visit (Attribute &attrib) -{ - tokens.push_back (Rust::Token::make (HASH, attrib.get_locus ())); - if (attrib.is_inner_attribute ()) - tokens.push_back (Rust::Token::make (EXCLAM, Location ())); - tokens.push_back (Rust::Token::make (LEFT_SQUARE, 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 (attrib.get_attr_input ())); - break; - } - case AST::AttrInput::AttrInputType::META_ITEM: { - visit (static_cast ( - attrib.get_attr_input ())); - break; - } - case AST::AttrInput::AttrInputType::TOKEN_TREE: { - visit (static_cast (attrib.get_attr_input ())); - break; - } - default: - gcc_unreachable (); - } - } - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); -} - -void -TokenCollector::visit (SimplePath &path) -{ - if (path.has_opening_scope_resolution ()) - { - tokens.push_back ( - 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 ()) - { - tokens.push_back (Rust::Token::make (CRATE, segment.get_locus ())); - } - else if (segment.is_super_path_seg ()) - { - tokens.push_back (Rust::Token::make (SUPER, segment.get_locus ())); - } - else if (segment.is_lower_self ()) - { - tokens.push_back (Rust::Token::make (SELF, segment.get_locus ())); - } - else if (segment.is_big_self ()) - { - tokens.push_back (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); - } - else - { - tokens.push_back ( - Rust::Token::make_identifier (segment.get_locus (), std::move (name))); - } -} - -void -TokenCollector::visit (Visibility &vis) -{ - switch (vis.get_vis_type ()) - { - case Visibility::PUB: - tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); - break; - case Visibility::PUB_CRATE: - tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - tokens.push_back (Rust::Token::make (CRATE, Location ())); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - break; - case Visibility::PUB_SELF: - tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - tokens.push_back (Rust::Token::make (SELF, Location ())); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - break; - case Visibility::PUB_SUPER: - tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - tokens.push_back (Rust::Token::make (SUPER, Location ())); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - break; - case Visibility::PUB_IN_PATH: - tokens.push_back (Rust::Token::make (PUB, vis.get_locus ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - tokens.push_back (Rust::Token::make (IN, Location ())); - visit (vis.get_path ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - break; - case Visibility::PRIV: - break; - } -} - -void -TokenCollector::visit (NamedFunctionParam ¶m) -{ - auto name = param.get_name (); - tokens.push_back ( - Rust::Token::make_identifier (param.get_locus (), std::move (name))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (param.get_type ()); -} - -void -TokenCollector::visit (std::vector> ¶ms) -{ - tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); - visit_items_joined_by_separator (params, COMMA); - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, 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 (); - tokens.push_back ( - Rust::Token::make_identifier (field.get_locus (), std::move (name))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (field.get_field_type ()); -} - -void -TokenCollector::visit (std::vector &for_lifetimes) -{ - tokens.push_back (Rust::Token::make (FOR, Location ())); - tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); - visit_items_joined_by_separator (for_lifetimes, COMMA); - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); -} - -void -TokenCollector::visit (FunctionQualifiers &qualifiers) -{ - // Syntax: - // `const`? `async`? `unsafe`? (`extern` Abi?)? - // unsafe? (extern Abi?)? - - switch (qualifiers.get_const_status ()) - { - case NONE: - break; - case CONST_FN: - tokens.push_back (Rust::Token::make (CONST, qualifiers.get_locus ())); - break; - case ASYNC_FN: - tokens.push_back (Rust::Token::make (ASYNC, qualifiers.get_locus ())); - break; - } - - if (qualifiers.is_unsafe ()) - tokens.push_back (Rust::Token::make (UNSAFE, qualifiers.get_locus ())); - if (qualifiers.is_extern ()) - { - tokens.push_back ( - Rust::Token::make (EXTERN_TOK, qualifiers.get_locus ())); - if (qualifiers.has_abi ()) - { - tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); - auto abi = qualifiers.get_extern_abi (); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (abi))); - tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); - } - } -} - -void -TokenCollector::visit (MaybeNamedParam ¶m) -{ - // Syntax: - // OuterAttribute* ( ( IDENTIFIER | _ ) : )? Type - - for (auto attr : param.get_outer_attrs ()) - { - visit (attr); - } - auto param_name = param.get_name (); - switch (param.get_param_kind ()) - { - case MaybeNamedParam::UNNAMED: - break; - case MaybeNamedParam::IDENTIFIER: - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (param_name))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - break; - case MaybeNamedParam::WILDCARD: - tokens.push_back (Rust::Token::make (UNDERSCORE, Location ())); - tokens.push_back (Rust::Token::make (COLON, 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: - tokens.push_back ( - Rust::Token::make_identifier (tok.get_locus (), std::move (data))); - break; - case INT_LITERAL: - tokens.push_back (Rust::Token::make_int (tok.get_locus (), - std::move (data), - tok.get_type_hint ())); - break; - case FLOAT_LITERAL: - tokens.push_back (Rust::Token::make_float (tok.get_locus (), - std::move (data), - tok.get_type_hint ())); - break; - case STRING_LITERAL: - tokens.push_back ( - Rust::Token::make_string (tok.get_locus (), std::move (data))); - break; - case CHAR_LITERAL: - tokens.push_back (Rust::Token::make_char ( - tok.get_locus (), - // FIXME: This need to be fixed to properly support UTF-8 - static_cast (data[0]))); - break; - case BYTE_CHAR_LITERAL: - tokens.push_back ( - Rust::Token::make_byte_char (tok.get_locus (), data[0])); - break; - case BYTE_STRING_LITERAL: - tokens.push_back ( - Rust::Token::make_byte_string (tok.get_locus (), std::move (data))); - break; - case INNER_DOC_COMMENT: - tokens.push_back (Rust::Token::make_inner_doc_comment (tok.get_locus (), - std::move (data))); - break; - case OUTER_DOC_COMMENT: - tokens.push_back (Rust::Token::make_outer_doc_comment (tok.get_locus (), - std::move (data))); - break; - case LIFETIME: - tokens.push_back ( - Rust::Token::make_lifetime (tok.get_locus (), std::move (data))); - break; - default: - tokens.push_back (Rust::Token::make (tok.get_id (), tok.get_locus ())); - } -} - -void -TokenCollector::visit (DelimTokenTree &delim_tok_tree) -{ - increment_indentation (); - newline (); - indentation (); - for (auto &token : delim_tok_tree.to_token_stream ()) - { - visit (token); - } - decrement_indentation (); - newline (); - indentation (); -} - -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 (); - tokens.push_back ( - 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: - tokens.push_back ( - Rust::Token::make_lifetime (lifetime.get_locus (), std::move (name))); - break; - case Lifetime::LifetimeType::STATIC: - tokens.push_back (Rust::Token::make_lifetime (lifetime.get_locus (), - std::move ("static"))); - break; - case Lifetime::LifetimeType::WILDCARD: - tokens.push_back ( - Rust::Token::make_lifetime (lifetime.get_locus (), std::move ("_"))); - 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. - - auto lifetime = lifetime_param.get_lifetime (); - visit (lifetime); - - if (lifetime_param.has_lifetime_bounds ()) - { - tokens.push_back (Rust::Token::make (COLON, Location ())); - for (auto &bound : lifetime_param.get_lifetime_bounds ()) - { - visit (bound); - } - } -} - -void -TokenCollector::visit (ConstGenericParam ¶m) -{ - // Syntax: - // const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )? - - tokens.push_back (Rust::Token::make (CONST, param.get_locus ())); - auto id = param.get_name (); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (param.get_type ()); - if (param.has_default_value ()) - { - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (param.get_type ()); - } -} - -void -TokenCollector::visit (PathExprSegment &segment) -{ - visit (segment.get_ident_segment ()); - if (segment.has_generic_args ()) - { - auto generics = segment.get_generic_args (); - tokens.push_back ( - Rust::Token::make (SCOPE_RESOLUTION, segment.get_locus ())); - tokens.push_back (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 ())) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - } - - visit_items_joined_by_separator (binding_args, COMMA); - - if (!generic_args.empty () && !binding_args.empty ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - } - - visit_items_joined_by_separator (lifetime_args, COMMA); - - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); - } -} - -void -TokenCollector::visit (PathInExpression &path) -{ - if (path.opening_scope_resolution ()) - { - tokens.push_back ( - 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 (); - tokens.push_back ( - 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 (); - tokens.push_back ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); - - if (segment.get_separating_scope_resolution ()) - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - - tokens.push_back (Rust::Token::make (LEFT_ANGLE, 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 ())) - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit_items_joined_by_separator (generic_args, COMMA); - if (!generic_args.empty () && !binding_args.empty ()) - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit_items_joined_by_separator (generic_args, COMMA); - } - - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); -} - -void -TokenCollector::visit (GenericArgsBinding &binding) -{ - // Syntax: - // IDENTIFIER `=` Type - auto identifier = binding.get_identifier (); - tokens.push_back (Rust::Token::make_identifier (binding.get_locus (), - std::move (identifier))); - - tokens.push_back (Rust::Token::make (EQUAL, 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 (); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (path))); - } - break; - case GenericArg::Kind::Error: - gcc_unreachable (); - } -} - -void -TokenCollector::visit (TypePathSegmentFunction &segment) -{ - // Syntax: - // PathIdentSegment `::`? (TypePathFn)? - - auto ident_segment = segment.get_ident_segment (); - auto id = ident_segment.as_string (); - tokens.push_back ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); - - if (segment.get_separating_scope_resolution ()) - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, 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)* `,`? - - tokens.push_back (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); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - if (type_path_fn.has_return_type ()) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (type_path_fn.get_return_type ()); - } -} - -void -TokenCollector::visit (TypePath &path) -{ - // Syntax: - // `::`? TypePathSegment (`::` TypePathSegment)* - - if (path.has_opening_scope_resolution_op ()) - tokens.push_back (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 ()) - { - tokens.push_back (Rust::Token::make (SUPER, segment.get_locus ())); - } - else if (segment.is_crate_segment ()) - { - tokens.push_back (Rust::Token::make (CRATE, segment.get_locus ())); - } - else if (segment.is_lower_self ()) - { - tokens.push_back (Rust::Token::make (SELF, segment.get_locus ())); - } - else if (segment.is_big_self ()) - { - tokens.push_back (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); - } - else - { - auto id = segment.as_string (); - tokens.push_back ( - 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 ()) - { - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - visit (segment); - } -} - -void -TokenCollector::visit (QualifiedPathType &path) -{ - tokens.push_back (Rust::Token::make (LEFT_ANGLE, path.get_locus ())); - visit (path.get_type ()); - if (path.has_as_clause ()) - { - tokens.push_back (Rust::Token::make (AS, Location ())); - visit (path.get_as_type_path ()); - } - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); -} - -void -TokenCollector::visit (QualifiedPathInType &path) -{ - visit (path.get_qualified_path_type ()); - - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - visit (path.get_associated_segment ()); - for (auto &segment : path.get_segments ()) - { - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - visit (segment); - } -} - -void -TokenCollector::visit (Literal &lit, Location locus) -{ - auto value = lit.as_string (); - switch (lit.get_lit_type ()) - { - case Literal::LitType::CHAR: - tokens.push_back ( - Rust::Token::make_char (locus, - // TODO: Change this to support utf-8 properly - Codepoint (static_cast (value[0])))); - break; - case Literal::LitType::STRING: - tokens.push_back (Rust::Token::make_string (locus, std::move (value))); - break; - case Literal::LitType::BYTE: - tokens.push_back (Rust::Token::make_byte_char (locus, value[0])); - break; - case Literal::LitType::BYTE_STRING: - tokens.push_back ( - Rust::Token::make_byte_string (locus, std::move (value))); - break; - case Literal::LitType::INT: - tokens.push_back (Rust::Token::make_int (locus, std::move (value))); - break; - case Literal::LitType::FLOAT: - tokens.push_back (Rust::Token::make_float (locus, std::move (value))); - break; - case Literal::LitType::BOOL: { - if (value == "false") - tokens.push_back (Rust::Token::make (FALSE_LITERAL, locus)); - else if (value == "true") - tokens.push_back (Rust::Token::make (TRUE_LITERAL, locus)); - else - gcc_unreachable (); // Not a boolean - break; - } - case Literal::LitType::ERROR: - gcc_unreachable (); - break; - } -} - -void -TokenCollector::visit (LiteralExpr &expr) -{ - auto lit = expr.get_literal (); - visit (lit, expr.get_locus ()); -} - -void -TokenCollector::visit (AttrInputLiteral &literal) -{ - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (literal.get_literal ()); -} - -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); - tokens.push_back (Rust::Token::make (COLON, item.get_locus ())); - visit (lit); -} - -void -TokenCollector::visit (BorrowExpr &expr) -{ - tokens.push_back (Rust::Token::make (AMP, expr.get_locus ())); - if (expr.get_is_double_borrow ()) - tokens.push_back (Rust::Token::make (AMP, Location ())); - if (expr.get_is_mut ()) - tokens.push_back (Rust::Token::make (MUT, Location ())); - - visit (expr.get_borrowed_expr ()); -} - -void -TokenCollector::visit (DereferenceExpr &expr) -{ - tokens.push_back (Rust::Token::make (ASTERISK, expr.get_locus ())); - visit (expr.get_dereferenced_expr ()); -} - -void -TokenCollector::visit (ErrorPropagationExpr &expr) -{ - visit (expr.get_propagating_expr ()); - tokens.push_back (Rust::Token::make (QUESTION_MARK, expr.get_locus ())); -} - -void -TokenCollector::visit (NegationExpr &expr) -{ - switch (expr.get_expr_type ()) - { - case NegationOperator::NEGATE: - tokens.push_back (Rust::Token::make (MINUS, expr.get_locus ())); - break; - case NegationOperator::NOT: - tokens.push_back (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: - tokens.push_back (Rust::Token::make (PLUS, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::SUBTRACT: - tokens.push_back (Rust::Token::make (MINUS, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::MULTIPLY: - tokens.push_back (Rust::Token::make (ASTERISK, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::DIVIDE: - tokens.push_back (Rust::Token::make (DIV, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::MODULUS: - tokens.push_back (Rust::Token::make (PERCENT, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::BITWISE_AND: - tokens.push_back (Rust::Token::make (AMP, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::BITWISE_OR: - tokens.push_back (Rust::Token::make (PIPE, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::BITWISE_XOR: - tokens.push_back (Rust::Token::make (CARET, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::LEFT_SHIFT: - tokens.push_back (Rust::Token::make (LEFT_SHIFT, expr.get_locus ())); - break; - - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: - tokens.push_back (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: - tokens.push_back (Rust::Token::make (EQUAL_EQUAL, expr.get_locus ())); - break; - case ComparisonOperator::NOT_EQUAL: - tokens.push_back (Rust::Token::make (NOT_EQUAL, expr.get_locus ())); - break; - case ComparisonOperator::GREATER_THAN: - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, expr.get_locus ())); - break; - case ComparisonOperator::LESS_THAN: - tokens.push_back (Rust::Token::make (LEFT_ANGLE, expr.get_locus ())); - break; - case ComparisonOperator::GREATER_OR_EQUAL: - tokens.push_back ( - Rust::Token::make (GREATER_OR_EQUAL, expr.get_locus ())); - break; - - case ComparisonOperator::LESS_OR_EQUAL: - tokens.push_back (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: - tokens.push_back (Rust::Token::make (LOGICAL_AND, expr.get_locus ())); - break; - case LazyBooleanOperator::LOGICAL_OR: - tokens.push_back (Rust::Token::make (OR, expr.get_locus ())); - break; - } - - visit (expr.get_right_expr ()); -} - -void -TokenCollector::visit (TypeCastExpr &expr) -{ - visit (expr.get_casted_expr ()); - tokens.push_back (Rust::Token::make (AS, expr.get_locus ())); - visit (expr.get_type_to_cast_to ()); -} - -void -TokenCollector::visit (AssignmentExpr &expr) -{ - expr.visit_lhs (*this); - tokens.push_back (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: - tokens.push_back (Rust::Token::make (PLUS_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::SUBTRACT: - tokens.push_back (Rust::Token::make (MINUS_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::MULTIPLY: - tokens.push_back (Rust::Token::make (ASTERISK_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::DIVIDE: - tokens.push_back (Rust::Token::make (DIV_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::MODULUS: - tokens.push_back (Rust::Token::make (PERCENT_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::BITWISE_AND: - tokens.push_back (Rust::Token::make (AMP_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::BITWISE_OR: - tokens.push_back (Rust::Token::make (PIPE_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::BITWISE_XOR: - tokens.push_back (Rust::Token::make (CARET_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::LEFT_SHIFT: - tokens.push_back (Rust::Token::make (LEFT_SHIFT_EQ, expr.get_locus ())); - break; - case CompoundAssignmentOperator::RIGHT_SHIFT: - tokens.push_back (Rust::Token::make (RIGHT_SHIFT_EQ, expr.get_locus ())); - break; - } - visit (expr.get_right_expr ()); -} - -void -TokenCollector::visit (GroupedExpr &expr) -{ - tokens.push_back (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); - visit (expr.get_expr_in_parens ()); - tokens.push_back (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 ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - visit (elems.get_num_copies ()); -} - -void -TokenCollector::visit (ArrayExpr &expr) -{ - tokens.push_back (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); - visit (expr.get_array_elems ()); - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); -} - -void -TokenCollector::visit (ArrayIndexExpr &expr) -{ - visit (expr.get_array_expr ()); - tokens.push_back (Rust::Token::make (LEFT_SQUARE, expr.get_locus ())); - visit (expr.get_index_expr ()); - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); -} - -void -TokenCollector::visit (TupleExpr &expr) -{ - visit_items_as_lines (expr.get_outer_attrs ()); - tokens.push_back (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); - visit_items_joined_by_separator (expr.get_tuple_elems (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (TupleIndexExpr &expr) -{ - visit (expr.get_tuple_expr ()); - tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); - tokens.push_back ( - Rust::Token::make_int (Location (), - std::to_string (expr.get_tuple_index ()))); -} - -void -TokenCollector::visit (StructExprStruct &expr) -{ - visit (expr.get_struct_name ()); -} - -void -TokenCollector::visit (StructExprFieldIdentifier &expr) -{ - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); - auto id = expr.get_field_name (); - tokens.push_back ( - Rust::Token::make_identifier (expr.get_locus (), std::move (id))); -} - -void -TokenCollector::visit (StructExprFieldIdentifierValue &expr) -{ - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); - auto id = expr.get_field_name (); - tokens.push_back ( - Rust::Token::make_identifier (expr.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (expr.get_value ()); -} - -void -TokenCollector::visit (StructExprFieldIndexValue &expr) -{ - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); - tokens.push_back (Rust::Token::make_int (expr.get_locus (), - std::to_string (expr.get_index ()))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (expr.get_value ()); -} - -void -TokenCollector::visit (StructBase &base) -{ - tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); - visit (base.get_base_struct ()); -} - -void -TokenCollector::visit (StructExprStructFields &expr) -{ - visit (expr.get_struct_name ()); - tokens.push_back (Rust::Token::make (LEFT_CURLY, expr.get_locus ())); - visit_items_joined_by_separator (expr.get_fields (), COMMA); - if (expr.has_struct_base ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit (expr.get_struct_base ()); - } - else - { - trailing_comma (); - } - tokens.push_back (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); -} - -void -TokenCollector::visit (StructExprStructBase &) -{ - // FIXME: Implement this node - gcc_unreachable (); -} - -void -TokenCollector::visit (CallExpr &expr) -{ - visit (expr.get_function_expr ()); - - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit_items_joined_by_separator (expr.get_params (), COMMA); - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (MethodCallExpr &expr) -{ - visit (expr.get_receiver_expr ()); - tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); - visit (expr.get_method_name ()); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (expr.get_params (), COMMA); - trailing_comma (); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (FieldAccessExpr &expr) -{ - visit (expr.get_receiver_expr ()); - tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); - auto field_name = expr.get_field_name (); - tokens.push_back ( - Rust::Token::make_identifier (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 ()) - { - tokens.push_back (Rust::Token::make (COLON, param.get_locus ())); - visit (param.get_type ()); - } -} - -void -TokenCollector::visit_closure_common (ClosureExpr &expr) -{ - if (expr.get_has_move ()) - { - tokens.push_back (Rust::Token::make (MOVE, expr.get_locus ())); - } - tokens.push_back (Rust::Token::make (PIPE, Location ())); - visit_items_joined_by_separator (expr.get_params (), COMMA); - tokens.push_back (Rust::Token::make (PIPE, Location ())); -} - -void -TokenCollector::visit (ClosureExprInner &expr) -{ - visit_closure_common (expr); - visit (expr.get_definition_expr ()); -} - -void -TokenCollector::visit (BlockExpr &expr) -{ - tokens.push_back (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 (), - {Rust::Token::make (SEMICOLON, Location ())}); - - if (expr.has_tail_expr ()) - { - visit (expr.get_tail_expr ()); - newline (); - } - - decrement_indentation (); - tokens.push_back (Rust::Token::make (RIGHT_CURLY, expr.get_locus ())); - newline (); -} - -void -TokenCollector::visit (ClosureExprInnerTyped &expr) -{ - visit_closure_common (expr); - tokens.push_back (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); - visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); -} - -void -TokenCollector::visit (ContinueExpr &expr) -{ - tokens.push_back (Rust::Token::make (CONTINUE, expr.get_locus ())); - if (expr.has_label ()) - visit (expr.get_label ()); -} - -void -TokenCollector::visit (BreakExpr &expr) -{ - tokens.push_back (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 ()); - tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); - visit (expr.get_to_expr ()); -} - -void -TokenCollector::visit (RangeFromExpr &expr) -{ - visit (expr.get_from_expr ()); - tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); -} - -void -TokenCollector::visit (RangeToExpr &expr) -{ - tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); - visit (expr.get_to_expr ()); -} - -void -TokenCollector::visit (RangeFullExpr &expr) -{ - tokens.push_back (Rust::Token::make (DOT_DOT, expr.get_locus ())); -} - -void -TokenCollector::visit (RangeFromToInclExpr &expr) -{ - visit (expr.get_from_expr ()); - tokens.push_back (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); - visit (expr.get_to_expr ()); -} - -void -TokenCollector::visit (RangeToInclExpr &expr) -{ - tokens.push_back (Rust::Token::make (DOT_DOT_EQ, expr.get_locus ())); - visit (expr.get_to_expr ()); -} - -void -TokenCollector::visit (ReturnExpr &expr) -{ - tokens.push_back (Rust::Token::make (RETURN_TOK, expr.get_locus ())); - if (expr.has_returned_expr ()) - visit (expr.get_returned_expr ()); -} - -void -TokenCollector::visit (UnsafeBlockExpr &expr) -{ - tokens.push_back (Rust::Token::make (UNSAFE, expr.get_locus ())); - visit (expr.get_block_expr ()); -} - -void -TokenCollector::visit (LoopLabel &label) -{ - visit (label.get_lifetime ()); - tokens.push_back (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); - tokens.push_back (Rust::Token::make (LOOP, expr.get_locus ())); - visit (expr.get_loop_block ()); -} - -void -TokenCollector::visit (WhileLoopExpr &expr) -{ - visit_loop_common (expr); - tokens.push_back (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); - tokens.push_back (Rust::Token::make (WHILE, expr.get_locus ())); - tokens.push_back (Rust::Token::make (LET, Location ())); - // TODO: The reference mention only one Pattern - for (auto &item : expr.get_patterns ()) - { - visit (item); - } - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (expr.get_scrutinee_expr ()); - visit (expr.get_loop_block ()); -} - -void -TokenCollector::visit (ForLoopExpr &expr) -{ - visit_loop_common (expr); - tokens.push_back (Rust::Token::make (FOR, expr.get_locus ())); - visit (expr.get_pattern ()); - tokens.push_back (Rust::Token::make (IN, Location ())); - visit (expr.get_iterator_expr ()); - visit (expr.get_loop_block ()); -} - -void -TokenCollector::visit (IfExpr &expr) -{ - tokens.push_back (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 (expr)); - indentation (); - tokens.push_back (Rust::Token::make (ELSE, expr.get_locus ())); - visit (expr.get_else_block ()); -} - -void -TokenCollector::visit (IfLetExpr &expr) -{ - tokens.push_back (Rust::Token::make (IF, expr.get_locus ())); - tokens.push_back (Rust::Token::make (LET, Location ())); - for (auto &pattern : expr.get_patterns ()) - { - visit (pattern); - } - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (expr.get_value_expr ()); - visit (expr.get_if_block ()); -} - -void -TokenCollector::visit (IfLetExprConseqElse &expr) -{ - visit (static_cast (expr)); - indentation (); - tokens.push_back (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 ()) - { - tokens.push_back (Rust::Token::make (IF, Location ())); - visit (arm.get_guard_expr ()); - } -} - -void -TokenCollector::visit (MatchCase &match_case) -{ - visit (match_case.get_arm ()); - tokens.push_back (Rust::Token::make (MATCH_ARROW, Location ())); - visit (match_case.get_expr ()); - tokens.push_back (Rust::Token::make (COMMA, Location ())); -} - -void -TokenCollector::visit (MatchExpr &expr) -{ - tokens.push_back (Rust::Token::make (MATCH_TOK, expr.get_locus ())); - visit (expr.get_scrutinee_expr ()); - tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); - visit_items_as_lines (expr.get_inner_attrs ()); - for (auto &arm : expr.get_match_cases ()) - { - visit (arm); - } - tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); -} - -void -TokenCollector::visit (AwaitExpr &expr) -{ - visit (expr.get_awaited_expr ()); - tokens.push_back (Rust::Token::make (DOT, expr.get_locus ())); - // TODO: Check status of await keyword (Context dependant ?) - tokens.push_back (Rust::Token::make_identifier (Location (), "await")); -} - -void -TokenCollector::visit (AsyncBlockExpr &expr) -{ - tokens.push_back (Rust::Token::make (ASYNC, expr.get_locus ())); - if (expr.get_has_move ()) - tokens.push_back (Rust::Token::make (MOVE, Location ())); - visit (expr.get_block_expr ()); -} - -// rust-item.h - -void -TokenCollector::visit (TypeParam ¶m) -{ - // Syntax: - // IDENTIFIER( : TypeParamBounds? )? ( = Type )? - // TypeParamBounds : - // TypeParamBound ( + TypeParamBound )* +? - - auto id = param.get_type_representation (); - tokens.push_back ( - Rust::Token::make_identifier (param.get_locus (), std::move (id))); - if (param.has_type_param_bounds ()) - { - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit_items_joined_by_separator (param.get_type_param_bounds (), PLUS); - } - if (param.has_type ()) - { - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (param.get_type ()); - } -} - -void -TokenCollector::visit (WhereClause &rule) -{ - // Syntax: - // where ( WhereClauseItem , )* WhereClauseItem ? - // WhereClauseItem : - // LifetimeWhereClauseItem - // | TypeBoundWhereClauseItem - - tokens.push_back (Rust::Token::make (WHERE, 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 ()); - tokens.push_back (Rust::Token::make (COLON, 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 ()); - - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit_items_joined_by_separator (item.get_type_param_bounds (), PLUS); -} - -void -TokenCollector::visit (Method &method) -{ - visit (method.get_visibility ()); - auto method_name = method.get_method_name (); - tokens.push_back (Rust::Token::make (FN_TOK, method.get_locus ())); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (method_name))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - tokens.push_back (Rust::Token::make (SELF, Location ())); - if (!method.get_function_params ().empty ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit_items_joined_by_separator (method.get_function_params (), COMMA); - } - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - if (method.has_return_type ()) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (method.get_return_type ()); - } - - auto &block = method.get_definition (); - if (!block) - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - else - visit (block); - newline (); -} - -void -TokenCollector::visit (Module &module) -{ - // Syntax: - // mod IDENTIFIER ; - // | mod IDENTIFIER { - // InnerAttribute* - // Item* - // } - - visit (module.get_visibility ()); - auto name = module.get_name (); - tokens.push_back (Rust::Token::make (MOD, module.get_locus ())); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (name))); - - if (module.get_kind () == Module::UNLOADED) - { - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); - } - else /* Module::LOADED */ - { - tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); - newline (); - increment_indentation (); - - visit_items_as_lines (module.get_inner_attrs ()); - visit_items_as_lines (module.get_items ()); - - decrement_indentation (); - - tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); - newline (); - } -} - -void -TokenCollector::visit (ExternCrate &crate) -{ - tokens.push_back (Rust::Token::make (EXTERN_TOK, crate.get_locus ())); - tokens.push_back (Rust::Token::make (CRATE, Location ())); - auto ref = crate.get_referenced_crate (); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (ref))); - if (crate.has_as_clause ()) - { - auto as_clause = crate.get_as_clause (); - tokens.push_back (Rust::Token::make (AS, Location ())); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (as_clause))); - } - tokens.push_back (Rust::Token::make (SEMICOLON, 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); - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - } - break; - case UseTreeGlob::PathType::NO_PATH: - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - break; - case UseTreeGlob::PathType::GLOBAL: - break; - } - tokens.push_back (Rust::Token::make (ASTERISK, 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); - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - } - break; - case UseTreeList::PathType::NO_PATH: - tokens.push_back (Rust::Token::make (SCOPE_RESOLUTION, Location ())); - break; - case UseTreeList::PathType::GLOBAL: - break; - } - - tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); - if (use_tree.has_trees ()) - { - visit_items_joined_by_separator (use_tree.get_trees (), COMMA); - } - tokens.push_back (Rust::Token::make (RIGHT_CURLY, 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: { - tokens.push_back (Rust::Token::make (AS, Location ())); - auto id = use_tree.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (use_tree.get_locus (), std::move (id))); - } - break; - case UseTreeRebind::NewBindType::WILDCARD: - tokens.push_back (Rust::Token::make (AS, Location ())); - tokens.push_back (Rust::Token::make (UNDERSCORE, use_tree.get_locus ())); - break; - case UseTreeRebind::NewBindType::NONE: - break; - } -} - -void -TokenCollector::visit (UseDeclaration &decl) -{ - tokens.push_back (Rust::Token::make (USE, decl.get_locus ())); - visit (*decl.get_tree ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); -} - -void -TokenCollector::visit (Function &function) -{ - // Syntax: - // FunctionQualifiers fn IDENTIFIER GenericParams? - // ( FunctionParameters? ) - // FunctionReturnType? WhereClause? - // ( BlockExpression | ; ) - - visit (function.get_visibility ()); - - tokens.push_back (Rust::Token::make (FN_TOK, function.get_locus ())); - auto name = function.get_function_name (); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (name))); - if (function.has_generics ()) - visit (function.get_generic_params ()); - - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (function.get_function_params ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - if (function.has_return_type ()) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (function.get_return_type ()); - } - - if (function.has_where_clause ()) - visit (function.get_where_clause ()); - - auto &block = function.get_definition (); - if (!block) - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - else - visit (block); - newline (); -} - -void -TokenCollector::visit (TypeAlias &type_alias) -{ - // Syntax: - // Visibility? type IDENTIFIER GenericParams? WhereClause? = Type; - - // Note: Associated types are handled by `AST::TraitItemType`. - - if (type_alias.has_visibility ()) - visit (type_alias.get_visibility ()); - auto alias_name = type_alias.get_new_type_name (); - tokens.push_back (Rust::Token::make (TYPE, type_alias.get_locus ())); - tokens.push_back ( - Rust::Token::make_identifier (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 ()); - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (type_alias.get_type_aliased ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -void -TokenCollector::visit (StructStruct &struct_item) -{ - if (struct_item.has_visibility ()) - visit (struct_item.get_visibility ()); - auto struct_name = struct_item.get_identifier (); - tokens.push_back (Rust::Token::make (STRUCT_TOK, struct_item.get_locus ())); - tokens.push_back ( - Rust::Token::make_identifier (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 ()) - { - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); - } - else - visit_items_as_block (struct_item.get_fields (), - {Rust::Token::make (COMMA, Location ())}); -} - -void -TokenCollector::visit (TupleStruct &tuple_struct) -{ - auto struct_name = tuple_struct.get_identifier (); - tokens.push_back (Rust::Token::make (STRUCT_TOK, tuple_struct.get_locus ())); - tokens.push_back ( - Rust::Token::make_identifier (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 ()); - - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (tuple_struct.get_fields (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); -} - -void -TokenCollector::visit (EnumItem &item) -{ - auto id = item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (item.get_locus (), std::move (id))); -} - -void -TokenCollector::visit (EnumItemTuple &item) -{ - auto id = item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (item.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (item.get_tuple_fields (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (EnumItemStruct &item) -{ - auto id = item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (item.get_locus (), std::move (id))); - visit_items_as_block (item.get_struct_fields (), - {Rust::Token::make (COMMA, Location ())}); -} - -void -TokenCollector::visit (EnumItemDiscriminant &item) -{ - auto id = item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (item.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (item.get_expr ()); -} - -void -TokenCollector::visit (Enum &enumeration) -{ - if (enumeration.has_visibility ()) - visit (enumeration.get_visibility ()); - tokens.push_back (Rust::Token::make (ENUM_TOK, enumeration.get_locus ())); - auto id = enumeration.get_identifier (); - tokens.push_back ( - 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, Location ())}); -} - -void -TokenCollector::visit (Union &union_item) -{ - visit_items_as_lines (union_item.get_outer_attrs ()); - auto id = union_item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (union_item.get_locus (), "union")); - tokens.push_back (Rust::Token::make_identifier (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, Location ())}); -} - -void -TokenCollector::visit (ConstantItem &item) -{ - tokens.push_back (Rust::Token::make (CONST, item.get_locus ())); - if (item.is_unnamed ()) - { - tokens.push_back (Rust::Token::make (UNDERSCORE, Location ())); - } - else - { - auto id = item.get_identifier (); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (id))); - } - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (item.get_type ()); - if (item.has_expr ()) - { - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (item.get_expr ()); - } - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -void -TokenCollector::visit (StaticItem &item) -{ - tokens.push_back (Rust::Token::make (STATIC_TOK, item.get_locus ())); - if (item.is_mutable ()) - tokens.push_back (Rust::Token::make (MUT, Location ())); - auto id = item.get_identifier (); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (item.get_type ()); - if (item.has_expr ()) - { - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (item.get_expr ()); - } - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -void -TokenCollector::visit_function_common (std::unique_ptr &return_type, - std::unique_ptr &block) -{ - // FIXME: This should format the ` fn ( [args] )` as well - if (return_type) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (return_type); - } - - if (block) - { - visit (block); - } - else - { - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); - } -} - -void -TokenCollector::visit (TraitItemFunc &item) -{ - auto func = item.get_trait_function_decl (); - auto id = func.get_identifier (); - tokens.push_back (Rust::Token::make (FN_TOK, item.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit_items_joined_by_separator (func.get_function_params ()); - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - visit_function_common (func.get_return_type (), item.get_definition ()); -} - -void -TokenCollector::visit (SelfParam ¶m) -{ - if (param.get_has_ref ()) - { - tokens.push_back (Rust::Token::make (AMP, param.get_locus ())); - if (param.has_lifetime ()) - { - auto lifetime = param.get_lifetime (); - visit (lifetime); - } - } - - if (param.get_is_mut ()) - { - tokens.push_back (Rust::Token::make (MUT, Location ())); - } - - tokens.push_back (Rust::Token::make (SELF, Location ())); -} - -void -TokenCollector::visit (TraitItemMethod &item) -{ - auto method = item.get_trait_method_decl (); - auto id = method.get_identifier (); - - tokens.push_back (Rust::Token::make (FN_TOK, item.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit (method.get_self_param ()); - - if (!method.get_function_params ().empty ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit_items_joined_by_separator (method.get_function_params (), COMMA); - } - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - visit_function_common (method.get_return_type (), item.get_definition ()); -} - -void -TokenCollector::visit (TraitItemConst &item) -{ - auto id = item.get_identifier (); - indentation (); - tokens.push_back (Rust::Token::make (CONST, item.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (item.get_type ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - newline (); -} - -void -TokenCollector::visit (TraitItemType &item) -{ - auto id = item.get_identifier (); - indentation (); - tokens.push_back (Rust::Token::make (TYPE, item.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (SEMICOLON, 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 (); - tokens.push_back (Rust::Token::make (TRAIT, trait.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - - // Traits actually have an implicit Self thrown at the start, so we must - // expect the number of generic params to be > 1 - if (trait.get_generic_params ().size () > 1) - { - tokens.push_back (Rust::Token::make (LEFT_ANGLE, Location ())); - visit_items_joined_by_separator (trait.get_generic_params (), COMMA, 1); - tokens.push_back (Rust::Token::make (RIGHT_ANGLE, Location ())); - } - - visit_items_as_block (trait.get_trait_items (), {}); -} - -void -TokenCollector::visit (InherentImpl &impl) -{ - tokens.push_back (Rust::Token::make (IMPL, impl.get_locus ())); - // FIXME: Handle generics - - 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) -{ - tokens.push_back (Rust::Token::make (IMPL, impl.get_locus ())); - visit (impl.get_trait_path ()); - tokens.push_back (Rust::Token::make (FOR, Location ())); - visit (impl.get_type ()); - tokens.push_back (Rust::Token::make (LEFT_CURLY, Location ())); - newline (); - - increment_indentation (); - - for (auto &item : impl.get_impl_items ()) - { - indentation (); - visit (item); - } - - decrement_indentation (); - newline (); - - tokens.push_back (Rust::Token::make (RIGHT_CURLY, Location ())); - newline (); -} - -void -TokenCollector::visit (ExternalTypeItem &type) -{ - visit (type.get_visibility ()); - - auto id = type.get_identifier (); - tokens.push_back (Rust::Token::make (TYPE, Location ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -void -TokenCollector::visit (ExternalStaticItem &item) -{ - auto id = item.get_identifier (); - visit_items_as_lines (item.get_outer_attrs ()); - if (item.has_visibility ()) - visit (item.get_visibility ()); - tokens.push_back (Rust::Token::make (STATIC_TOK, item.get_locus ())); - if (item.is_mut ()) - tokens.push_back (Rust::Token::make (MUT, Location ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (item.get_type ()); - // TODO: No expr ? The "(= Expression)?" part from the reference seems missing - // in the ast. - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -void -TokenCollector::visit (ExternalFunctionItem &function) -{ - visit (function.get_visibility ()); - - auto id = function.get_identifier (); - tokens.push_back (Rust::Token::make (FN_TOK, function.get_locus ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit_items_joined_by_separator (function.get_function_params ()); - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - if (function.has_return_type ()) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (function.get_return_type ()); - } -} - -void -TokenCollector::visit (ExternBlock &block) -{ - tokens.push_back (Rust::Token::make (EXTERN_TOK, block.get_locus ())); - - if (block.has_abi ()) - { - auto abi = block.get_abi (); - tokens.push_back ( - Rust::Token::make_string (Location (), std::move (abi))); - } - - visit_items_as_block (block.get_extern_items ()); -} - -static std::pair -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: - gcc_unreachable (); - } -} - -void -TokenCollector::visit (MacroMatchFragment &match) -{ - auto id = match.get_ident (); - auto frag_spec = match.get_frag_spec ().as_string (); - tokens.push_back (Rust::Token::make (DOLLAR_SIGN, Location ())); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (Rust::Token::make (COLON, Location ())); - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (frag_spec))); -} - -void -TokenCollector::visit (MacroMatchRepetition &repetition) -{ - tokens.push_back (Rust::Token::make (DOLLAR_SIGN, Location ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit_items_joined_by_separator (repetition.get_matches (), {}); - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - if (repetition.has_sep ()) - { - tokens.push_back ( - Rust::Token::make (repetition.get_sep ()->get_id (), - repetition.get_sep ()->get_locus ())); - } - switch (repetition.get_op ()) - { - case MacroMatchRepetition::ANY: - tokens.push_back (Rust::Token::make (ASTERISK, Location ())); - break; - case MacroMatchRepetition::ONE_OR_MORE: - tokens.push_back (Rust::Token::make (PLUS, Location ())); - break; - case MacroMatchRepetition::ZERO_OR_ONE: - tokens.push_back (Rust::Token::make (QUESTION_MARK, Location ())); - break; - case MacroMatchRepetition::NONE: - break; - } -} - -void -TokenCollector::visit (MacroMatcher &matcher) -{ - auto delimiters = get_delimiters (matcher.get_delim_type ()); - - tokens.push_back (Rust::Token::make (delimiters.first, Location ())); - - for (auto &item : matcher.get_matches ()) - { - visit (item); - } - - tokens.push_back (Rust::Token::make (delimiters.second, Location ())); -} - -void -TokenCollector::visit (MacroRule &rule) -{ - visit (rule.get_matcher ()); - tokens.push_back (Rust::Token::make (MATCH_ARROW, rule.get_locus ())); - visit (rule.get_transcriber ().get_token_tree ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); -} - -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 (); - tokens.push_back ( - Rust::Token::make_identifier (rules_def.get_locus (), "macro_rules")); - tokens.push_back (Rust::Token::make (EXCLAM, Location ())); - - tokens.push_back ( - Rust::Token::make_identifier (Location (), std::move (rule_name))); - - visit_items_as_block (rules_def.get_rules (), - {Rust::Token::make (SEMICOLON, Location ())}); -} - -void -TokenCollector::visit (MacroInvocation &invocation) -{ - auto data = invocation.get_invoc_data (); - visit (data.get_path ()); - tokens.push_back (Rust::Token::make (EXCLAM, Location ())); - visit (data.get_delim_tok_tree ()); - if (invocation.has_semicolon ()) - tokens.push_back (Rust::Token::make (SEMICOLON, 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. - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (item.get_seq (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (MetaWord &word) -{ - auto id = word.get_ident (); - tokens.push_back ( - 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); - auto value = std::get<1> (pair); - tokens.push_back ( - Rust::Token::make_identifier (name.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (EQUAL, name.get_locus ())); - tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); - tokens.push_back ( - Rust::Token::make_identifier (name.get_locus (), std::move (value))); - tokens.push_back (Rust::Token::make (DOUBLE_QUOTE, Location ())); -} - -void -TokenCollector::visit (MetaListPaths &list) -{ - auto id = list.get_ident (); - tokens.push_back ( - Rust::Token::make_identifier (list.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (list.get_paths (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (MetaListNameValueStr &list) -{ - auto id = list.get_ident (); - tokens.push_back ( - Rust::Token::make_identifier (list.get_locus (), std::move (id))); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - visit_items_joined_by_separator (list.get_values (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, 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 ()) - { - tokens.push_back (Rust::Token::make (REF, pattern.get_locus ())); - } - if (pattern.get_is_mut ()) - { - tokens.push_back (Rust::Token::make (MUT, Location ())); - } - auto id = pattern.get_ident (); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - if (pattern.has_pattern_to_bind ()) - { - tokens.push_back (Rust::Token::make (PATTERN_BIND, Location ())); - visit (pattern.get_pattern_to_bind ()); - } -} - -void -TokenCollector::visit (WildcardPattern &pattern) -{ - tokens.push_back (Rust::Token::make (UNDERSCORE, pattern.get_locus ())); -} - -void -TokenCollector::visit (RestPattern &pattern) -{ - tokens.push_back (Rust::Token::make (DOT_DOT, pattern.get_locus ())); -} - -// void TokenCollector::visit(RangePatternBound& ){} - -void -TokenCollector::visit (RangePatternBoundLiteral &pattern) -{ - if (pattern.get_has_minus ()) - { - tokens.push_back (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 ()) - tokens.push_back (Rust::Token::make (ELLIPSIS, pattern.get_locus ())); - else - tokens.push_back (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 ()); - tokens.push_back (Rust::Token::make (DOT_DOT, pattern.get_locus ())); - } - else - { - tokens.push_back (Rust::Token::make (DOT_DOT_EQ, pattern.get_locus ())); - visit (pattern.get_upper_bound ()); - } -} - -void -TokenCollector::visit (ReferencePattern &pattern) -{ - if (pattern.is_double_reference ()) - { - tokens.push_back (Rust::Token::make (LOGICAL_AND, pattern.get_locus ())); - } - else - { - tokens.push_back (Rust::Token::make (AMP, pattern.get_locus ())); - } - - if (pattern.get_is_mut ()) - { - tokens.push_back (Rust::Token::make (MUT, Location ())); - } - - visit (pattern.get_referenced_pattern ()); -} - -// void TokenCollector::visit(StructPatternField& ){} - -void -TokenCollector::visit (StructPatternFieldTuplePat &pattern) -{ - visit_items_as_lines (pattern.get_outer_attrs ()); - tokens.push_back ( - Rust::Token::make_int (pattern.get_locus (), - std::to_string (pattern.get_index ()))); - tokens.push_back (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 (); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); - tokens.push_back (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 ()) - tokens.push_back (Rust::Token::make (REF, Location ())); - if (pattern.is_mut ()) - tokens.push_back (Rust::Token::make (MUT, Location ())); - - auto id = pattern.get_identifier (); - tokens.push_back (Rust::Token::make_identifier (Location (), std::move (id))); -} - -void -TokenCollector::visit (StructPattern &pattern) -{ - visit (pattern.get_path ()); - tokens.push_back (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 ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - visit_items_as_lines (elems.get_etc_outer_attrs ()); - } - } - else - { - visit_items_as_lines (elems.get_etc_outer_attrs ()); - } - - tokens.push_back (Rust::Token::make (RIGHT_CURLY, 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); - } - tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); - for (auto &upper : pattern.get_lower_patterns ()) - { - visit (upper); - } -} - -void -TokenCollector::visit (TupleStructPattern &pattern) -{ - visit (pattern.get_path ()); - tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); - if (pattern.has_items ()) - visit (pattern.get_items ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, 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); - } - tokens.push_back (Rust::Token::make (DOT_DOT, Location ())); - for (auto &upper : pattern.get_lower_patterns ()) - { - visit (upper); - } -} - -void -TokenCollector::visit (TuplePattern &pattern) -{ - tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); - visit (pattern.get_items ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (GroupedPattern &pattern) -{ - tokens.push_back (Rust::Token::make (LEFT_PAREN, pattern.get_locus ())); - visit (pattern.get_pattern_in_parens ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (SlicePattern &pattern) -{ - tokens.push_back (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); - visit_items_joined_by_separator (pattern.get_items (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, 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) -{ - tokens.push_back (Rust::Token::make (LET, stmt.get_locus ())); - auto &pattern = stmt.get_pattern (); - if (pattern) - visit (pattern); - - if (stmt.has_type ()) - { - tokens.push_back (Rust::Token::make (COLON, Location ())); - visit (stmt.get_type ()); - } - - if (stmt.has_init_expr ()) - { - tokens.push_back (Rust::Token::make (EQUAL, Location ())); - visit (stmt.get_init_expr ()); - } -} - -void -TokenCollector::visit (ExprStmtWithoutBlock &stmt) -{ - visit (stmt.get_expr ()); -} - -void -TokenCollector::visit (ExprStmtWithBlock &stmt) -{ - visit (stmt.get_expr ()); -} - -// rust-type.h -void -TokenCollector::visit (TraitBound &bound) -{ - // Syntax: - // ?? ForLifetimes? TypePath - // | ( ?? ForLifetimes? TypePath ) - - if (bound.has_opening_question_mark ()) - tokens.push_back (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 )* +? - - tokens.push_back (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 ()) - tokens.push_back (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 ) - - tokens.push_back (Rust::Token::make (LEFT_PAREN, type.get_locus ())); - visit (type.get_type_in_parens ()); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (ImplTraitTypeOneBound &type) -{ - // Syntax: - // impl TraitBound - - tokens.push_back (Rust::Token::make (IMPL, type.get_locus ())); - visit (type.get_trait_bound ()); -} - -void -TokenCollector::visit (TraitObjectTypeOneBound &type) -{ - // Syntax: - // dyn? TraitBound - - if (type.is_dyn ()) - tokens.push_back (Rust::Token::make (DYN, type.get_locus ())); - visit (type.get_trait_bound ()); -} - -void -TokenCollector::visit (TupleType &type) -{ - // Syntax: - // ( ) - // | ( ( Type , )+ Type? ) - - tokens.push_back (Rust::Token::make (LEFT_PAREN, type.get_locus ())); - visit_items_joined_by_separator (type.get_elems (), COMMA); - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); -} - -void -TokenCollector::visit (NeverType &type) -{ - // Syntax: - // ! - - tokens.push_back (Rust::Token::make (EXCLAM, type.get_locus ())); -} - -void -TokenCollector::visit (RawPointerType &type) -{ - // Syntax: - // * ( mut | const ) TypeNoBounds - - tokens.push_back (Rust::Token::make (ASTERISK, type.get_locus ())); - if (type.get_pointer_type () == RawPointerType::MUT) - tokens.push_back (Rust::Token::make (MUT, Location ())); - else /* RawPointerType::CONST */ - tokens.push_back (Rust::Token::make (CONST, Location ())); - - visit (type.get_type_pointed_to ()); -} - -void -TokenCollector::visit (ReferenceType &type) -{ - // Syntax: - // & Lifetime? mut? TypeNoBounds - - tokens.push_back (Rust::Token::make (AMP, type.get_locus ())); - - if (type.has_lifetime ()) - { - visit (type.get_lifetime ()); - } - - if (type.get_has_mut ()) - tokens.push_back (Rust::Token::make (MUT, Location ())); - - visit (type.get_type_referenced ()); -} - -void -TokenCollector::visit (ArrayType &type) -{ - // Syntax: - // [ Type ; Expression ] - - tokens.push_back (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); - visit (type.get_elem_type ()); - tokens.push_back (Rust::Token::make (SEMICOLON, Location ())); - visit (type.get_size_expr ()); - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); -} - -void -TokenCollector::visit (SliceType &type) -{ - // Syntax: - // [ Type ] - - tokens.push_back (Rust::Token::make (LEFT_SQUARE, type.get_locus ())); - visit (type.get_elem_type ()); - tokens.push_back (Rust::Token::make (RIGHT_SQUARE, Location ())); -} - -void -TokenCollector::visit (InferredType &type) -{ - // Syntax: - // _ - - tokens.push_back (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 ()); - - tokens.push_back (Rust::Token::make (FN_TOK, type.get_locus ())); - tokens.push_back (Rust::Token::make (LEFT_PAREN, Location ())); - - visit_items_joined_by_separator (type.get_function_params (), COMMA); - - if (type.is_variadic ()) - { - tokens.push_back (Rust::Token::make (COMMA, Location ())); - for (auto &item : type.get_variadic_attr ()) - { - visit (item); - } - tokens.push_back (Rust::Token::make (ELLIPSIS, Location ())); - } - - tokens.push_back (Rust::Token::make (RIGHT_PAREN, Location ())); - - if (type.has_return_type ()) - { - tokens.push_back (Rust::Token::make (RETURN_TYPE, Location ())); - visit (type.get_return_type ()); - } -} - -} // namespace AST -} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-tokenstream.h b/gcc/rust/ast/rust-ast-tokenstream.h deleted file mode 100644 index 01c7e7c..0000000 --- a/gcc/rust/ast/rust-ast-tokenstream.h +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (C) 2020-2023 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 -// . - -#ifndef RUST_AST_TOKENSTREAM_H -#define RUST_AST_TOKENSTREAM_H - -#include "rust-token.h" -#include "rust-ast-visitor.h" -#include "rust-ast.h" -#include "rust-ast-full.h" - -#include "libproc_macro/tokenstream.h" - -namespace Rust { -namespace AST { - -class TokenCollector : public ASTVisitor -{ -public: - TokenCollector (std::vector &container); - bool output_trailing_commas = false; - - void visit (AST::Crate &crate); - void visit (AST::Item &item); - - std::vector collect_tokens () const; - - ProcMacro::TokenStream collect () const; - -private: - std::vector &tokens; - - /** - * Compatibility layer for using the visitor pattern on polymorphic classes - * with a unified overload syntax. This allows us to call `visit` both on - * types implementing `accept_vis` method and for classes for which the - * `visit` method is directly implemented. - */ - template void visit (std::unique_ptr &node); - - /** - * @see visit> - */ - template void visit (T &node); - - /** - * Visit all items in given @collection, placing the separator in between but - * not at the end. - */ - template - void visit_items_joined_by_separator (T &collection, - TokenId separator = COMMA, - size_t start_offset = 0, - size_t end_offset = 0); - - /** - * Visit item placing end of line after. - */ - template - void visit_as_line (T &item, std::vector trailing = {}); - - /** - * Visit each item in @collection "as line". - * - * @see visit_as_line - */ - template - void visit_items_as_lines (T &collection, - std::vector trailing = {}); - - /** - * Visit each item in @collection as lines inside a block delimited by braces - * with increased indentation. Also includes special handling for empty - * collection to print only the delimiters with no new line inside. - */ - template - void visit_items_as_block (T &collection, std::vector trailing = {}, - TokenId left_brace = LEFT_CURLY, - TokenId right_brace = RIGHT_CURLY); - - void trailing_comma (); - void newline (); - void indentation (); - void increment_indentation (); - void decrement_indentation (); - /** - * Visit common items of functions: Parameters, return type, block - */ - void visit_function_common (std::unique_ptr &return_type, - std::unique_ptr &block); - - void visit_closure_common (ClosureExpr &expr); - - void visit_loop_common (BaseLoopExpr &expr); - void visit (LoopLabel &label); - - void visit (Literal &lit, Location locus = {}); - - void visit (FunctionParam ¶m); - void visit (Attribute &attrib); - void visit (Visibility &vis); - void visit (std::vector> ¶ms); - void visit (TupleField &field); - void visit (StructField &field); - void visit (SimplePathSegment &segment); - void visit (NamedFunctionParam ¶m); - void visit (MacroRule &rule); - void visit (WhereClause &rule); - void visit (std::vector &for_lifetimes); - void visit (FunctionQualifiers &qualifiers); - void visit (MaybeNamedParam ¶m); - void visit (TypePathFunction &type_path_fn); - void visit (GenericArgsBinding &binding); - void visit (GenericArg &arg); - - // rust-ast.h - void visit (Token &tok); - void visit (DelimTokenTree &delim_tok_tree); - void visit (AttrInputMetaItemContainer &input); - void visit (IdentifierExpr &ident_expr); - void visit (Lifetime &lifetime); - void visit (LifetimeParam &lifetime_param); - void visit (ConstGenericParam &const_param); - - // rust-path.h - void visit (SimplePath &path); - void visit (PathExprSegment &segment); - void visit (PathIdentSegment &segment); - void visit (PathInExpression &path); - void visit (TypePathSegment &segment); - void visit (TypePathSegmentGeneric &segment); - void visit (TypePathSegmentFunction &segment); - void visit (TypePath &path); - void visit (QualifiedPathType &path); - void visit (QualifiedPathInExpression &path); - void visit (QualifiedPathInType &path); - - // rust-expr.h - void visit (LiteralExpr &expr); - void visit (AttrInputLiteral &attr_input); - void visit (MetaItemLitExpr &meta_item); - void visit (MetaItemPathLit &meta_item); - void visit (BorrowExpr &expr); - void visit (DereferenceExpr &expr); - void visit (ErrorPropagationExpr &expr); - void visit (NegationExpr &expr); - void visit (ArithmeticOrLogicalExpr &expr); - void visit (ComparisonExpr &expr); - void visit (LazyBooleanExpr &expr); - void visit (TypeCastExpr &expr); - void visit (AssignmentExpr &expr); - void visit (CompoundAssignmentExpr &expr); - void visit (GroupedExpr &expr); - void visit (ArrayElemsValues &elems); - void visit (ArrayElemsCopied &elems); - void visit (ArrayExpr &expr); - void visit (ArrayIndexExpr &expr); - void visit (TupleExpr &expr); - void visit (TupleIndexExpr &expr); - void visit (StructExprStruct &expr); - void visit (StructExprFieldIdentifier &field); - void visit (StructExprFieldIdentifierValue &field); - void visit (StructExprFieldIndexValue &field); - void visit (StructBase &base); - void visit (StructExprStructFields &expr); - void visit (StructExprStructBase &expr); - void visit (CallExpr &expr); - void visit (MethodCallExpr &expr); - void visit (FieldAccessExpr &expr); - void visit (ClosureParam ¶m); - void visit (ClosureExprInner &expr); - void visit (BlockExpr &expr); - void visit (ClosureExprInnerTyped &expr); - void visit (ContinueExpr &expr); - void visit (BreakExpr &expr); - void visit (RangeFromToExpr &expr); - void visit (RangeFromExpr &expr); - void visit (RangeToExpr &expr); - void visit (RangeFullExpr &expr); - void visit (RangeFromToInclExpr &expr); - void visit (RangeToInclExpr &expr); - void visit (ReturnExpr &expr); - void visit (UnsafeBlockExpr &expr); - void visit (LoopExpr &expr); - void visit (WhileLoopExpr &expr); - void visit (WhileLetLoopExpr &expr); - void visit (ForLoopExpr &expr); - void visit (IfExpr &expr); - void visit (IfExprConseqElse &expr); - void visit (IfLetExpr &expr); - void visit (IfLetExprConseqElse &expr); - void visit (MatchArm &arm); - void visit (MatchCase &arm); - void visit (MatchExpr &expr); - void visit (AwaitExpr &expr); - void visit (AsyncBlockExpr &expr); - - // rust-item.h - void visit (TypeParam ¶m); - void visit (LifetimeWhereClauseItem &item); - void visit (TypeBoundWhereClauseItem &item); - void visit (Method &method); - void visit (Module &module); - void visit (ExternCrate &crate); - void visit (UseTreeGlob &use_tree); - void visit (UseTreeList &use_tree); - void visit (UseTreeRebind &use_tree); - void visit (UseDeclaration &use_decl); - void visit (Function &function); - void visit (TypeAlias &type_alias); - void visit (StructStruct &struct_item); - void visit (TupleStruct &tuple_struct); - void visit (EnumItem &item); - void visit (EnumItemTuple &item); - void visit (EnumItemStruct &item); - void visit (EnumItemDiscriminant &item); - void visit (Enum &enum_item); - void visit (Union &union_item); - void visit (ConstantItem &const_item); - void visit (StaticItem &static_item); - void visit (TraitItemFunc &item); - void visit (SelfParam ¶m); - void visit (TraitItemMethod &item); - void visit (TraitItemConst &item); - void visit (TraitItemType &item); - void visit (Trait &trait); - void visit (InherentImpl &impl); - void visit (TraitImpl &impl); - void visit (ExternalTypeItem &item); - void visit (ExternalStaticItem &item); - void visit (ExternalFunctionItem &item); - void visit (ExternBlock &block); - - // rust-macro.h - void visit (MacroMatchFragment &match); - void visit (MacroMatchRepetition &match); - void visit (MacroMatcher &matcher); - void visit (MacroRulesDefinition &rules_def); - void visit (MacroInvocData &invoc_data); - void visit (MacroInvocation ¯o_invoc); - void visit (MetaItemPath &meta_item); - void visit (MetaItemSeq &meta_item); - void visit (MetaWord &meta_item); - void visit (MetaNameValueStr &meta_item); - void visit (MetaListPaths &meta_item); - void visit (MetaListNameValueStr &meta_item); - - // rust-pattern.h - void visit (LiteralPattern &pattern); - void visit (IdentifierPattern &pattern); - void visit (WildcardPattern &pattern); - void visit (RestPattern &pattern); - // void visit(RangePatternBound& bound); - void visit (RangePatternBoundLiteral &bound); - void visit (RangePatternBoundPath &bound); - void visit (RangePatternBoundQualPath &bound); - void visit (RangePattern &pattern); - void visit (ReferencePattern &pattern); - // void visit(StructPatternField& field); - void visit (StructPatternFieldTuplePat &field); - void visit (StructPatternFieldIdentPat &field); - void visit (StructPatternFieldIdent &field); - void visit (StructPattern &pattern); - // void visit(TupleStructItems& tuple_items); - void visit (TupleStructItemsNoRange &tuple_items); - void visit (TupleStructItemsRange &tuple_items); - void visit (TupleStructPattern &pattern); - // void visit(TuplePatternItems& tuple_items); - void visit (TuplePatternItemsMultiple &tuple_items); - void visit (TuplePatternItemsRanged &tuple_items); - void visit (TuplePattern &pattern); - void visit (GroupedPattern &pattern); - void visit (SlicePattern &pattern); - void visit (AltPattern &pattern); - - // rust-stmt.h - void visit (EmptyStmt &stmt); - void visit (LetStmt &stmt); - void visit (ExprStmtWithoutBlock &stmt); - void visit (ExprStmtWithBlock &stmt); - - // rust-type.h - void visit (TraitBound &bound); - void visit (ImplTraitType &type); - void visit (TraitObjectType &type); - void visit (ParenthesisedType &type); - void visit (ImplTraitTypeOneBound &type); - void visit (TraitObjectTypeOneBound &type); - void visit (TupleType &type); - void visit (NeverType &type); - void visit (RawPointerType &type); - void visit (ReferenceType &type); - void visit (ArrayType &type); - void visit (SliceType &type); - void visit (InferredType &type); - void visit (BareFunctionType &type); -}; -} // namespace AST - -} // namespace Rust - -#endif // !RUST_AST_TOKENSTREAM_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index e85527e..860abab 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -35,7 +35,7 @@ #include "rust-lint-unused-var.h" #include "rust-hir-dump.h" #include "rust-ast-dump.h" -#include "rust-ast-tokenstream.h" +#include "rust-ast-collector.h" #include "rust-export-metadata.h" #include "rust-imports.h" #include "rust-extern-crate.h" -- cgit v1.1