Create a generic type for types with an error list
This commit is contained in:
parent
f739194e06
commit
c9a8ecdc0a
@ -42,20 +42,10 @@ namespace boot
|
||||
}
|
||||
|
||||
driver::driver(const char *input_file)
|
||||
: input_file(input_file)
|
||||
: error_container(input_file)
|
||||
{
|
||||
}
|
||||
|
||||
void driver::error(const yy::location& loc, const std::string& message)
|
||||
{
|
||||
m_errors.emplace_back(new boot::syntax_error(message, input_file, loc));
|
||||
}
|
||||
|
||||
const std::list<std::unique_ptr<struct error>>& driver::errors() const noexcept
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
char escape_char(char escape)
|
||||
{
|
||||
switch (escape)
|
||||
|
@ -290,6 +290,6 @@ defer {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
|
||||
driver.error(this->location, ss.str());
|
||||
driver.add_error<elna::boot::syntax_error>(ss.str(), driver.input_file, this->location);
|
||||
}
|
||||
%%
|
||||
|
@ -578,5 +578,5 @@ actual_parameter_list:
|
||||
|
||||
void yy::parser::error(const location_type& loc, const std::string& message)
|
||||
{
|
||||
driver.error(loc, message);
|
||||
driver.add_error<elna::boot::syntax_error>(message, driver.input_file, loc);
|
||||
}
|
||||
|
@ -35,5 +35,15 @@ namespace boot
|
||||
{
|
||||
return this->position.column;
|
||||
}
|
||||
|
||||
error_container::error_container(const char *input_file)
|
||||
: input_file(input_file)
|
||||
{
|
||||
}
|
||||
|
||||
std::deque<std::unique_ptr<error>>& error_container::errors()
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace boot
|
||||
}
|
||||
|
||||
declaration_visitor::declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols)
|
||||
: path(path), symbols(symbols)
|
||||
: error_container(path), symbols(symbols)
|
||||
{
|
||||
}
|
||||
|
||||
@ -66,10 +66,8 @@ namespace boot
|
||||
}
|
||||
else
|
||||
{
|
||||
auto new_error = std::make_unique<declaration_error>(type_expression->name,
|
||||
path, type_expression->position());
|
||||
this->errors.emplace_back(std::move(new_error));
|
||||
// TODO: Delete the next line.
|
||||
// TODO:
|
||||
// add_error<declaration_error>(type_expression->name, this->input_file, type_expression->position());
|
||||
this->current_type = type(std::make_shared<primitive_type>(type_expression->name));
|
||||
}
|
||||
}
|
||||
|
@ -133,5 +133,15 @@ namespace gcc
|
||||
}
|
||||
gcc_unreachable();
|
||||
}
|
||||
|
||||
void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors)
|
||||
{
|
||||
for (const auto& error : errors)
|
||||
{
|
||||
auto gcc_location = elna::gcc::get_location(&error->position);
|
||||
|
||||
error_at(gcc_location, error->what().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,19 +63,24 @@ namespace gcc
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
void do_semantic_analysis(const char *path, std::unique_ptr<boot::program>& ast,
|
||||
std::shared_ptr<symbol_table> symbols)
|
||||
std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
|
||||
std::unique_ptr<boot::program>& ast, std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
auto info_table = boot::builtin_symbol_table();
|
||||
boot::declaration_visitor declaration_visitor(path, info_table);
|
||||
|
||||
declaration_visitor.visit(ast.get());
|
||||
|
||||
if (declaration_visitor.errors().empty())
|
||||
{
|
||||
for (auto unresolved : declaration_visitor.unresolved)
|
||||
{
|
||||
auto inner_alias = get_inner_alias(symbols, boot::type(unresolved.second));
|
||||
symbols->enter(unresolved.first, inner_alias);
|
||||
}
|
||||
}
|
||||
return std::move(declaration_visitor.errors());
|
||||
}
|
||||
|
||||
generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)
|
||||
{
|
||||
|
18
gcc/elna1.cc
18
gcc/elna1.cc
@ -79,12 +79,7 @@ static void elna_parse_file(const char *filename)
|
||||
linemap_add(line_table, LC_ENTER, 0, filename, 1);
|
||||
if (parser())
|
||||
{
|
||||
for (const auto& error : driver.errors())
|
||||
{
|
||||
auto gcc_location = elna::gcc::get_location(&error->position);
|
||||
|
||||
error_at(gcc_location, error->what().c_str());
|
||||
}
|
||||
elna::gcc::report_errors(driver.errors());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -98,11 +93,18 @@ static void elna_parse_file(const char *filename)
|
||||
symbol_table->enter("Float", elna_float_type_node);
|
||||
symbol_table->enter("String", elna_string_type_node);
|
||||
|
||||
elna::gcc::do_semantic_analysis(filename, driver.tree, symbol_table);
|
||||
elna::gcc::generic_visitor generic_visitor{ symbol_table };
|
||||
auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, symbol_table);
|
||||
|
||||
if (semantic_errors.empty())
|
||||
{
|
||||
elna::gcc::generic_visitor generic_visitor{ symbol_table };
|
||||
generic_visitor.visit(driver.tree.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
elna::gcc::report_errors(semantic_errors);
|
||||
}
|
||||
}
|
||||
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include "elna/boot/ast.h"
|
||||
#include "location.hh"
|
||||
@ -39,18 +38,12 @@ namespace boot
|
||||
virtual std::string what() const override;
|
||||
};
|
||||
|
||||
class driver
|
||||
class driver : public error_container
|
||||
{
|
||||
std::list<std::unique_ptr<struct error>> m_errors;
|
||||
const char *input_file;
|
||||
|
||||
public:
|
||||
std::unique_ptr<program> tree;
|
||||
|
||||
driver(const char *input_file);
|
||||
|
||||
void error(const yy::location& loc, const std::string& message);
|
||||
const std::list<std::unique_ptr<struct error>>& errors() const noexcept;
|
||||
};
|
||||
|
||||
constexpr char escape_invalid_char = '\xff';
|
||||
|
@ -19,6 +19,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
@ -59,5 +61,25 @@ namespace boot
|
||||
/// Error column in the source text.
|
||||
std::size_t column() const;
|
||||
};
|
||||
|
||||
class error_container
|
||||
{
|
||||
protected:
|
||||
std::deque<std::unique_ptr<error>> m_errors;
|
||||
|
||||
error_container(const char *input_file);
|
||||
|
||||
public:
|
||||
const char *input_file;
|
||||
|
||||
std::deque<std::unique_ptr<error>>& errors();
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void add_error(Args... arguments)
|
||||
{
|
||||
auto new_error = std::make_unique<T>(arguments...);
|
||||
m_errors.emplace_back(std::move(new_error));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
|
||||
#include "elna/boot/ast.h"
|
||||
#include "elna/boot/result.h"
|
||||
@ -37,12 +38,10 @@ namespace boot
|
||||
virtual std::string what() const override;
|
||||
};
|
||||
|
||||
class declaration_visitor final : public empty_visitor
|
||||
class declaration_visitor final : public empty_visitor, public error_container
|
||||
{
|
||||
type current_type;
|
||||
const char *path;
|
||||
symbol_table symbols;
|
||||
std::vector<std::unique_ptr<error>> errors;
|
||||
|
||||
public:
|
||||
std::unordered_map<std::string, std::shared_ptr<alias_type>> unresolved;
|
||||
|
@ -22,6 +22,10 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "coretypes.h"
|
||||
#include "input.h"
|
||||
#include "tree.h"
|
||||
#include "diagnostic.h"
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
#include "elna/boot/result.h"
|
||||
|
||||
@ -30,7 +34,7 @@ namespace elna
|
||||
namespace gcc
|
||||
{
|
||||
location_t get_location(const boot::position *position);
|
||||
|
||||
std::string print_type(tree type);
|
||||
void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors);
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ namespace elna
|
||||
{
|
||||
namespace gcc
|
||||
{
|
||||
void do_semantic_analysis(const char *path, std::unique_ptr<boot::program>& ast,
|
||||
std::shared_ptr<symbol_table> symbols);
|
||||
std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
|
||||
std::unique_ptr<boot::program>& ast, std::shared_ptr<symbol_table> symbols);
|
||||
|
||||
class generic_visitor final : public boot::empty_visitor
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user