741 lines
21 KiB
C++

// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "elna/source/result.h"
namespace elna
{
namespace source
{
enum class binary_operator
{
sum,
subtraction,
multiplication,
division,
remainder,
equals,
not_equals,
less,
greater,
less_equal,
greater_equal,
disjunction,
conjunction
};
enum class unary_operator
{
reference,
negation
};
class variable_declaration;
class constant_definition;
class procedure_definition;
class type_definition;
class call_expression;
class assign_statement;
class if_statement;
class while_statement;
class return_statement;
class expression_statement;
class block;
class program;
class binary_expression;
class unary_expression;
class basic_type_expression;
class array_type_expression;
class pointer_type_expression;
class record_type_expression;
class union_type_expression;
class variable_expression;
class array_access_expression;
class field_access_expression;
class dereference_expression;
template<typename T>
class number_literal;
class char_literal;
class string_literal;
/**
* Interface for AST visitors.
*/
struct parser_visitor
{
virtual void visit(variable_declaration *) = 0;
virtual void visit(constant_definition *) = 0;
virtual void visit(procedure_definition *) = 0;
virtual void visit(type_definition *) = 0;
virtual void visit(call_expression *) = 0;
virtual void visit(expression_statement *) = 0;
virtual void visit(assign_statement *) = 0;
virtual void visit(if_statement *) = 0;
virtual void visit(while_statement *) = 0;
virtual void visit(return_statement *) = 0;
virtual void visit(block *) = 0;
virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
virtual void visit(basic_type_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(union_type_expression *) = 0;
virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *is_field_access) = 0;
virtual void visit(dereference_expression *is_dereference) = 0;
virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<std::uint32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0;
virtual void visit(number_literal<bool> *) = 0;
virtual void visit(number_literal<unsigned char> *) = 0;
virtual void visit(string_literal *) = 0;
};
/**
* A visitor which visits all nodes but does nothing.
*/
struct empty_visitor : parser_visitor
{
virtual void visit(variable_declaration *) override;
virtual void visit(constant_definition *definition) override;
virtual void visit(procedure_definition *definition) override;
virtual void visit(type_definition *definition) override;
virtual void visit(call_expression *statement) override;
virtual void visit(expression_statement *statement) override;
virtual void visit(assign_statement *statement) override;
virtual void visit(if_statement *) override;
virtual void visit(while_statement *) override;
virtual void visit(return_statement *) override;
virtual void visit(block *block) override;
virtual void visit(program *program) override;
virtual void visit(binary_expression *expression) override;
virtual void visit(unary_expression *expression) override;
virtual void visit(basic_type_expression *) override;
virtual void visit(array_type_expression *expression) override;
virtual void visit(pointer_type_expression *) override;
virtual void visit(record_type_expression *expression) override;
virtual void visit(union_type_expression *expression) override;
virtual void visit(variable_expression *) override;
virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *expression) override;
virtual void visit(dereference_expression *expression) override;
virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<std::uint32_t> *) override;
virtual void visit(number_literal<double> *) override;
virtual void visit(number_literal<bool> *) override;
virtual void visit(number_literal<unsigned char> *) override;
virtual void visit(string_literal *) override;
};
/**
* Operand representing a subexpression in the 3 address code.
*/
struct operand
{
public:
virtual ~operand() = 0;
};
struct integer_operand final : public operand
{
std::int32_t m_value;
public:
explicit integer_operand(const std::int32_t value);
std::int32_t value() const;
};
class variable_operand final : public operand
{
std::string m_name;
public:
explicit variable_operand(const std::string& name);
const std::string& name() const;
};
struct temporary_variable final : public operand
{
std::size_t m_counter;
public:
explicit temporary_variable(const std::size_t counter);
std::size_t counter() const;
};
struct label_operand final : public operand
{
std::size_t m_counter;
public:
explicit label_operand(const std::size_t counter);
std::size_t counter() const;
};
/**
* AST node.
*/
class node
{
const struct position source_position;
protected:
/**
* \param position Source code position.
*/
explicit node(const position position);
public:
virtual ~node() = default;
virtual void accept(parser_visitor *) = 0;
/**
* \return Node position in the source code.
*/
const struct position& position() const;
};
class statement : public node
{
protected:
/**
* \param position Source code position.
*/
explicit statement(const struct position position);
};
class expression : public node
{
public:
std::shared_ptr<operand> place;
protected:
/**
* \param position Source code position.
*/
explicit expression(const struct position position);
};
/**
* Symbol definition.
*/
class definition : public node
{
std::string m_identifier;
protected:
/**
* Constructs a definition identified by some name.
*
* \param position Source code position.
* \param identifier Definition name.
*/
definition(const struct position position, const std::string& identifier);
public:
/**
* \return Definition name.
*/
std::string& identifier();
};
/**
* Some type expression.
*/
class type_expression : public node
{
public:
virtual basic_type_expression *is_basic();
virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
virtual record_type_expression *is_record();
virtual union_type_expression *is_union();
protected:
type_expression(const struct position position);
};
/**
* Expression defining a basic type.
*/
class basic_type_expression final : public type_expression
{
const std::string m_name;
public:
/**
* \param position Source code position.
* \param name Type name.
*/
basic_type_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
const std::string& base_name();
basic_type_expression *is_basic() override;
};
class array_type_expression final : public type_expression
{
type_expression *m_base;
public:
const std::uint32_t size;
array_type_expression(const struct position position, type_expression *base, const std::uint32_t size);
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
array_type_expression *is_array() override;
virtual ~array_type_expression() override;
};
class pointer_type_expression final : public type_expression
{
type_expression *m_base;
public:
pointer_type_expression(const struct position position, type_expression *base);
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
pointer_type_expression *is_pointer() override;
virtual ~pointer_type_expression() override;
};
using field_t = std::pair<std::string, type_expression *>;
using fields_t = std::vector<field_t>;
class composite_type_expression : public type_expression
{
protected:
composite_type_expression(const struct position position, fields_t&& fields);
public:
fields_t fields;
virtual ~composite_type_expression() override;
};
class record_type_expression final : public composite_type_expression
{
public:
record_type_expression(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
record_type_expression *is_record() override;
};
class union_type_expression final : public composite_type_expression
{
public:
union_type_expression(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
union_type_expression *is_union() override;
};
/**
* Variable declaration.
*/
class variable_declaration : public definition
{
type_expression *m_type;
public:
/**
* Constructs a declaration with a name and a type.
*
* \param position Source code position.
* \param identifier Definition name.
* \param type Declared type.
*/
variable_declaration(const struct position position, const std::string& identifier,
type_expression *type);
virtual void accept(parser_visitor *visitor) override;
type_expression& type();
virtual ~variable_declaration() override;
};
class literal : public expression
{
protected:
explicit literal(const struct position position);
};
/**
* Constant definition.
*/
class constant_definition : public definition
{
literal *m_body;
public:
/**
* \param position Source code position.
* \param identifier Constant name.
* \param body Constant value.
*/
constant_definition(const struct position position, const std::string& identifier,
literal *body);
virtual void accept(parser_visitor *visitor) override;
literal& body();
virtual ~constant_definition() override;
};
/**
* Procedure definition.
*/
class procedure_definition : public definition
{
type_expression *m_return_type{ nullptr };
block *m_body{ nullptr };
public:
std::vector<variable_declaration *> parameters;
/**
* \param position Source code position.
* \param identifier Procedure name.
* \param parameters Procedure formal parameters.
* \param return_type Return type if any.
* \param body Procedure body.
*/
procedure_definition(const struct position position, const std::string& identifier,
std::vector<variable_declaration *>&& parameters,
type_expression *return_type = nullptr, block *body = nullptr);
virtual void accept(parser_visitor *visitor) override;
type_expression *return_type();
block *body();
virtual ~procedure_definition() override;
};
class type_definition : public definition
{
type_expression *m_body;
public:
type_definition(const struct position position, const std::string& identifier,
type_expression *expression);
virtual void accept(parser_visitor *visitor) override;
type_expression& body();
virtual ~type_definition() override;
};
/**
* Call statement.
*/
class call_expression : public expression
{
std::string m_name;
std::vector<expression *> m_arguments;
public:
/**
* \param position Source code position.
* \param name Callable's name.
*/
call_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
std::string& name();
std::vector<expression *>& arguments();
virtual ~call_expression() override;
};
class expression_statement : public statement
{
expression *m_body;
public:
expression_statement(const struct position position, expression *body);
virtual void accept(parser_visitor *visitor) override;
expression& body();
virtual ~expression_statement() override;
};
/**
* List of statements paired with a condition.
*/
class conditional_statements
{
expression *m_prerequisite;
public:
std::vector<statement *> statements;
conditional_statements(expression *prerequisite);
expression& prerequisite();
virtual ~conditional_statements();
};
class return_statement : public statement
{
expression *m_return_expression{ nullptr };
public:
return_statement(const struct position position, expression *return_expression);
virtual void accept(parser_visitor *visitor) override;
expression *return_expression();
virtual ~return_statement() override;
};
class designator_expression : public expression
{
public:
virtual variable_expression *is_variable();
virtual array_access_expression *is_array_access();
virtual field_access_expression *is_field_access();
virtual dereference_expression *is_dereference();
protected:
designator_expression(const struct position position);
};
class variable_expression : public designator_expression
{
std::string m_name;
public:
variable_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
const std::string& name() const;
variable_expression *is_variable() override;
};
class array_access_expression : public designator_expression
{
designator_expression *m_base;
expression *m_index;
public:
array_access_expression(const struct position position, designator_expression *base, expression *index);
virtual void accept(parser_visitor *visitor) override;
designator_expression& base();
expression& index();
array_access_expression *is_array_access() override;
~array_access_expression() override;
};
class field_access_expression : public designator_expression
{
designator_expression *m_base;
std::string m_field;
public:
field_access_expression(const struct position position, designator_expression *base,
const std::string& field);
virtual void accept(parser_visitor *visitor) override;
designator_expression& base();
std::string& field();
field_access_expression *is_field_access() override;
~field_access_expression() override;
};
class dereference_expression : public designator_expression
{
designator_expression *m_base;
public:
dereference_expression(const struct position position, designator_expression *base);
virtual void accept(parser_visitor *visitor) override;
designator_expression& base();
dereference_expression *is_dereference() override;
~dereference_expression() override;
};
class assign_statement : public statement
{
designator_expression *m_lvalue;
expression *m_rvalue;
public:
/**
* \param position Source code position.
* \param lvalue Left-hand side.
* \param rvalue Assigned expression.
*/
assign_statement(const struct position position, designator_expression *lvalue,
expression *rvalue);
virtual void accept(parser_visitor *visitor) override;
designator_expression& lvalue();
expression& rvalue();
virtual ~assign_statement() override;
};
/**
* If-statement.
*/
class if_statement : public statement
{
conditional_statements *m_body;
std::vector<statement *> *m_alternative;
public:
if_statement(const struct position position, conditional_statements *body,
std::vector<statement *> *alternative = nullptr);
virtual void accept(parser_visitor *visitor) override;
conditional_statements& body();
std::vector<statement *> *alternative();
virtual ~if_statement() override;
};
/**
* While-statement.
*/
class while_statement : public statement
{
conditional_statements *m_body;
public:
while_statement(const struct position position, conditional_statements *body);
virtual void accept(parser_visitor *visitor) override;
conditional_statements& body();
virtual ~while_statement() override;
};
class block : public node
{
public:
std::vector<definition *> value_definitions;
std::vector<statement *> body;
block(const struct position position, std::vector<definition *>&& value_definitions,
std::vector<statement *>&& body);
virtual void accept(parser_visitor *visitor) override;
virtual ~block() override;
};
class program : public block
{
public:
std::vector<definition *> type_definitions;
program(const struct position position, std::vector<definition *>&& type_definitions,
std::vector<definition *>&& value_definitions, std::vector<statement *>&& body);
virtual void accept(parser_visitor *visitor) override;
virtual ~program() override;
};
template<typename T>
class number_literal : public literal
{
T m_number;
public:
number_literal(const struct position position, const T value)
: literal(position), m_number(value)
{
}
virtual void accept(parser_visitor *visitor) override
{
visitor->visit(this);
}
T number() const
{
return m_number;
}
};
class string_literal : public literal
{
std::string m_string;
public:
string_literal(const struct position position, const std::string& value);
virtual void accept(parser_visitor *visitor) override;
const std::string& string() const;
};
class binary_expression : public expression
{
expression *m_lhs;
expression *m_rhs;
binary_operator m_operator;
public:
binary_expression(const struct position position, expression *lhs,
expression *rhs, const binary_operator operation);
virtual void accept(parser_visitor *visitor) override;
expression& lhs();
expression& rhs();
binary_operator operation() const;
virtual ~binary_expression() override;
};
class unary_expression : public expression
{
expression *m_operand;
unary_operator m_operator;
public:
unary_expression(const struct position position, expression *operand,
const unary_operator operation);
virtual void accept(parser_visitor *visitor) override;
expression& operand();
unary_operator operation() const;
virtual ~unary_expression() override;
};
const char *print_binary_operator(const binary_operator operation);
}
}