blob: a4835e52e23ed3a0e739e72f4332a888f6b9a9b8 [file] [log] [blame]
// 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_