// 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 #include #include #include #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 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 *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 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 *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) 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 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; using fields_t = std::vector; 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 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&& 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 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& 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 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 *m_alternative; public: if_statement(const struct position position, conditional_statements *body, std::vector *alternative = nullptr); virtual void accept(parser_visitor *visitor) override; conditional_statements& body(); std::vector *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 value_definitions; std::vector body; block(const struct position position, std::vector&& value_definitions, std::vector&& body); virtual void accept(parser_visitor *visitor) override; virtual ~block() override; }; class program : public block { public: std::vector type_definitions; program(const struct position position, std::vector&& type_definitions, std::vector&& value_definitions, std::vector&& body); virtual void accept(parser_visitor *visitor) override; virtual ~program() override; }; template 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); } }