741 lines
21 KiB
C++
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);
|
|
}
|
|
}
|