Parse variable declarations

This commit is contained in:
2024-12-21 14:05:27 +01:00
parent 72681e349a
commit f080b75c52
15 changed files with 1151 additions and 62 deletions

View File

@ -0,0 +1,35 @@
#pragma once
#include <list>
#include "elna/source/ast.hpp"
#include "location.hh"
namespace elna::source
{
position make_position(const yy::location& location);
class syntax_error final : public error
{
std::string message;
public:
syntax_error(const std::string& message,
const std::filesystem::path& input_file, const yy::location& location);
virtual std::string what() const override;
};
class driver
{
std::list<std::unique_ptr<struct error>> m_errors;
const std::filesystem::path input_file;
public:
std::unique_ptr<program> tree;
driver(const std::filesystem::path& input_file);
void error(const yy::location& loc, const std::string& message);
const std::list<std::unique_ptr<struct error>>& errors() const noexcept;
};
}

View File

@ -2,6 +2,7 @@
#include <cstddef>
#include <filesystem>
#include "elna/source/types.hpp"
namespace elna::source
{
@ -49,4 +50,53 @@ namespace elna::source
/// Source file name.
const std::filesystem::path& path() const noexcept;
};
class name_collision final : public error
{
position previous;
std::string name;
public:
/**
* \param name Symbol name.
* \param path Source file name.
* \param current Current symbol position.
* \param previous Position of the previously defined symbol.
*/
name_collision(const std::string& name, const std::filesystem::path& path,
const position current, const position previous);
std::string what() const override;
};
struct type_mismatch final : public error
{
/**
* Kind of the operation on the type.
*/
enum class operation
{
dereference,
argument,
arithmetic,
comparison,
condition,
assignment
};
/**
* \param name Given type.
* \param kind Kind of the operation on the type.
* \param path Source file name.
* \param position Operation position.
*/
type_mismatch(std::shared_ptr<const type> got, operation kind, const std::filesystem::path& path,
const struct position position);
std::string what() const override;
private:
std::shared_ptr<const type> got;
operation kind;
};
}

View File

@ -0,0 +1,94 @@
#pragma once
#include <list>
#include "elna/source/ast.hpp"
#include "elna/source/symbol_table.hpp"
namespace elna::source
{
class name_analysis_visitor final : public empty_visitor
{
std::shared_ptr<symbol_table> table;
const std::filesystem::path filename;
std::list<std::unique_ptr<error>> m_errors;
const std::size_t pointer_size;
std::shared_ptr<const type> convert_declaration_type(const type_expression& ast_type) const;
public:
/**
* \param table Symbol table.
* \param path Source filename.
* \param target_pointer_size Pointer size on the target platform.
*/
name_analysis_visitor(std::shared_ptr<symbol_table> table, const std::filesystem::path& filename,
const std::size_t target_pointer_size);
/**
* \return Collected errors.
*/
const std::list<std::unique_ptr<error>>& errors() const noexcept;
void visit(constant_definition *definition) override;
void visit(declaration *declaration) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
};
/**
* Visitor which allocates registers and stack space for variables and
* parameters.
*/
class allocator_visitor final : public empty_visitor
{
std::ptrdiff_t local_offset;
std::ptrdiff_t argument_offset;
std::shared_ptr<symbol_table> table;
public:
allocator_visitor(std::shared_ptr<symbol_table> table);
void visit(declaration *declaration) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
void visit(call_statement *statement) override;
};
/**
* This visitor performs the type checking.
*/
class type_analysis_visitor final : public empty_visitor
{
std::shared_ptr<symbol_table> table;
const std::filesystem::path filename;
const std::size_t pointer_size;
std::list<std::unique_ptr<error>> m_errors;
public:
/**
* \param table Symbol table.
* \param path Source filename.
* \param target_pointer_size Pointer size on the target platform.
*/
type_analysis_visitor(std::shared_ptr<symbol_table> table, const std::filesystem::path& filename,
const std::size_t target_pointer_size);
/**
* \return Collected errors.
*/
const std::list<std::unique_ptr<error>>& errors() const noexcept;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
void visit(integer_literal *literal) override;
void visit(boolean_literal *literal) override;
void visit(variable_expression *expression) override;
void visit(unary_expression *expression) override;
void visit(binary_expression *expression) override;
void visit(call_statement *statement) override;
void visit(constant_definition *definition) override;
void visit(while_statement *statement) override;
void visit(if_statement *statement) override;
void visit(assign_statement *statement) override;
};
}

View File

@ -0,0 +1,161 @@
#pragma once
#include <cstdint>
#include <unordered_map>
#include <string>
#include <memory>
namespace elna::source
{
class symbol_table;
/**
* Generic language entity information.
*/
class info
{
public:
virtual ~info() = 0;
protected:
info();
};
/**
* Type information.
*/
class type_info final : public info
{
std::shared_ptr<class type> m_type;
public:
explicit type_info(const class type& type);
~type_info() override;
std::shared_ptr<const class type> type() const noexcept;
};
/**
* Information for a typed symbol.
*/
class typed_info : public info
{
std::shared_ptr<const class type> m_type;
protected:
typed_info(std::shared_ptr<const class type> type);
public:
~typed_info() override;
std::shared_ptr<const class type> type() const noexcept;
};
/**
* Constant information.
*/
class constant_info final : public typed_info
{
std::int32_t m_value;
public:
constant_info(std::shared_ptr<const class type> type, const std::int32_t value);
std::int32_t value() const noexcept;
};
/**
* Variable information.
*/
class variable_info final : public typed_info
{
public:
std::ptrdiff_t offset{ 0 };
explicit variable_info(std::shared_ptr<const class type> type);
};
/**
* Procedure parameter information.
*/
class parameter_info final : public typed_info
{
public:
std::ptrdiff_t offset{ 0 };
explicit parameter_info(std::shared_ptr<const class type> type);
};
/**
* Intrinsic and external procedure information.
*/
class intrinsic_info : public info
{
std::shared_ptr<const class procedure_type> m_type;
public:
explicit intrinsic_info(const class procedure_type& type);
~intrinsic_info() override;
std::shared_ptr<const class procedure_type> type() const noexcept;
std::size_t parameter_stack_size() const noexcept;
};
/**
* Procedure information.
*/
class procedure_info final : public intrinsic_info
{
std::shared_ptr<symbol_table> local_table;
public:
std::size_t local_stack_size{ 0 };
std::size_t argument_stack_size{ 0 };
procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope);
~procedure_info() override;
std::shared_ptr<symbol_table> scope();
std::size_t stack_size() const noexcept;
};
/**
* Symbol table.
*/
class symbol_table
{
std::unordered_map<std::string, std::shared_ptr<info>> entries;
std::shared_ptr<symbol_table> outer_scope;
public:
/**
* Constructs a new symbol with an optional outer scope.
*
* \param scope Outer scope.
*/
explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr);
/**
* Looks for symbol in the table by name. Returns nullptr if the symbol
* can not be found.
*
* \param name Symbol name.
* \return Symbol from the table if found.
*/
std::shared_ptr<info> lookup(const std::string& name);
/**
* Registers new symbol.
*
* \param name Symbol name.
* \param entry Symbol information.
*/
void enter(const std::string& name, std::shared_ptr<info> entry);
/**
* Returns the outer scope or nullptr if the this is the global scope.
*
* \return Outer scope.
*/
std::shared_ptr<symbol_table> scope();
};
}