| // 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. |
| |
| #ifndef ZIRCON_SYSTEM_UTEST_BANJO_COMPILER_TEST_LIBRARY_H_ |
| #define ZIRCON_SYSTEM_UTEST_BANJO_COMPILER_TEST_LIBRARY_H_ |
| |
| #include <banjo/flat_ast.h> |
| #include <banjo/json_generator.h> |
| #include <banjo/lexer.h> |
| #include <banjo/parser.h> |
| #include <banjo/source_file.h> |
| |
| static banjo::SourceFile MakeSourceFile(const std::string& filename, const std::string& raw_source_code) { |
| std::string source_code(raw_source_code); |
| // NUL terminate the string. |
| source_code.resize(source_code.size() + 1); |
| return banjo::SourceFile(filename, source_code); |
| } |
| |
| class TestLibrary { |
| public: |
| TestLibrary(const std::string& raw_source_code) |
| : TestLibrary("example.banjo", raw_source_code) {} |
| |
| TestLibrary(const std::string& filename, const std::string& raw_source_code) |
| : source_file_(MakeSourceFile(filename, raw_source_code)), |
| lexer_(source_file_, &identifier_table_), |
| parser_(&lexer_, &error_reporter_), |
| library_(std::make_unique<banjo::flat::Library>(&all_libraries_, &error_reporter_)) { |
| } |
| |
| bool AddDependentLibrary(TestLibrary& dependent_library) { |
| // For testing, we have conveniences to construct compiled test |
| // libraries, which we usurp here to move it into the current library |
| // under test. This would be made clearer with a helper object which |
| // owned all libraries under test. |
| if (!all_libraries_.Insert(std::unique_ptr<banjo::flat::Library>(dependent_library.library_.get()))) { |
| return false; |
| } |
| dependent_library.library_.release(); |
| return true; |
| } |
| |
| bool Parse(std::unique_ptr<banjo::raw::File>& ast_ptr) { |
| ast_ptr.reset(parser_.Parse().release()); |
| return parser_.Ok(); |
| } |
| |
| bool Compile() { |
| auto ast = parser_.Parse(); |
| return parser_.Ok() && |
| library_->ConsumeFile(std::move(ast)) && |
| library_->Compile(); |
| } |
| |
| std::string GenerateJSON() { |
| auto json_generator = banjo::JSONGenerator(library_.get()); |
| auto out = json_generator.Produce(); |
| return out.str(); |
| } |
| |
| bool AddSourceFile(const std::string& filename, const std::string& raw_source_code) { |
| auto source_file = MakeSourceFile(filename, raw_source_code); |
| banjo::IdentifierTable identifier_table; |
| banjo::Lexer lexer(source_file, &identifier_table); |
| banjo::Parser parser(&lexer, &error_reporter_); |
| auto ast = parser.Parse(); |
| return parser.Ok() && |
| library_->ConsumeFile(std::move(ast)) && |
| library_->Compile(); |
| } |
| |
| const banjo::flat::Struct* LookupStruct(const std::string& name) { |
| for (const auto& struct_decl : library_->struct_declarations_) { |
| if (struct_decl->GetName() == name) { |
| return struct_decl.get(); |
| } |
| } |
| return nullptr; |
| } |
| |
| const banjo::flat::Union* LookupUnion(const std::string& name) { |
| for (const auto& union_decl : library_->union_declarations_) { |
| if (union_decl->GetName() == name) { |
| return union_decl.get(); |
| } |
| } |
| return nullptr; |
| } |
| |
| const banjo::flat::Interface* LookupInterface(const std::string& name) { |
| for (const auto& interface_decl : library_->interface_declarations_) { |
| if (interface_decl->GetName() == name) { |
| return interface_decl.get(); |
| } |
| } |
| return nullptr; |
| } |
| |
| banjo::SourceFile source_file() { |
| return source_file_; |
| } |
| |
| const std::vector<std::string>& errors() const { |
| return error_reporter_.errors(); |
| } |
| |
| private: |
| banjo::SourceFile source_file_; |
| banjo::IdentifierTable identifier_table_; |
| banjo::ErrorReporter error_reporter_; |
| banjo::Lexer lexer_; |
| banjo::Parser parser_; |
| banjo::flat::Libraries all_libraries_; |
| std::unique_ptr<banjo::flat::Library> library_; |
| }; |
| |
| #endif // ZIRCON_SYSTEM_UTEST_BANJO_COMPILER_TEST_LIBRARY_H_ |