// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "fidl/raw_ast.h" #include "fidl/tree_visitor.h" namespace fidl { namespace raw { void DeclarationOrderTreeVisitor::OnFile(std::unique_ptr const& element) { OnSourceElementStart(*element); OnCompoundIdentifier(element->library_name); for (auto i = element->using_list.begin(); i != element->using_list.end(); ++i) { OnUsing(*i); } auto const_decls_it = element->const_declaration_list.begin(); auto enum_decls_it = element->enum_declaration_list.begin(); auto interface_decls_it = element->interface_declaration_list.begin(); auto struct_decls_it = element->struct_declaration_list.begin(); auto table_decls_it = element->table_declaration_list.begin(); auto union_decls_it = element->union_declaration_list.begin(); enum Next { const_t, enum_t, interface_t, struct_t, table_t, union_t }; std::map m; do { // We want to visit these in declaration order, rather than grouped // by type of declaration. std::map is sorted by key. For each of // these lists of declarations, we make a map where the key is "the // next start location of the earliest element in the list" to a // variable representing the type. We then identify which type was // put earliest in the map. That will be the earliest declaration // in the file. We then visit the declaration accordingly. m.clear(); if (const_decls_it != element->const_declaration_list.end()) { m[(*const_decls_it)->start_.previous_end().data().data()] = const_t; } if (enum_decls_it != element->enum_declaration_list.end()) { m[(*enum_decls_it)->start_.previous_end().data().data()] = enum_t; } if (interface_decls_it != element->interface_declaration_list.end()) { if (*interface_decls_it == nullptr) { // Used to indicate empty, so let's wind it forward. interface_decls_it = element->interface_declaration_list.end(); } else { m[(*interface_decls_it)->start_.previous_end().data().data()] = interface_t; } } if (struct_decls_it != element->struct_declaration_list.end()) { m[(*struct_decls_it)->start_.previous_end().data().data()] = struct_t; } if (table_decls_it != element->table_declaration_list.end()) { m[(*table_decls_it)->start_.previous_end().data().data()] = table_t; } if (union_decls_it != element->union_declaration_list.end()) { m[(*union_decls_it)->start_.previous_end().data().data()] = union_t; } if (m.size() == 0) break; // And the earliest top level declaration is... switch (m.begin()->second) { case const_t: OnConstDeclaration(*const_decls_it); ++const_decls_it; break; case enum_t: OnEnumDeclaration(*enum_decls_it); ++enum_decls_it; break; case interface_t: OnInterfaceDeclaration(*interface_decls_it); ++interface_decls_it; break; case struct_t: OnStructDeclaration(*struct_decls_it); ++struct_decls_it; break; case table_t: OnTableDeclaration(*table_decls_it); ++table_decls_it; break; case union_t: OnUnionDeclaration(*union_decls_it); ++union_decls_it; break; } } while (1); OnSourceElementEnd(*element); } } // namespace raw } // namespace fidl