/* Abstract syntax tree representation. Copyright (C) 2025 Free Software Foundation, Inc. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #pragma once #include #include #include #include #include "elna/boot/result.h" namespace elna { namespace boot { enum class binary_operator { sum, subtraction, multiplication, division, remainder, equals, not_equals, less, greater, less_equal, greater_equal, disjunction, conjunction, exclusive_disjunction, shift_left, shift_right }; enum class unary_operator { reference, negation, minus }; class variable_declaration; class constant_definition; class procedure_definition; class type_definition; class procedure_call; class cast_expression; class assign_statement; class if_statement; class while_statement; class return_statement; class traits_expression; class block; class program; class binary_expression; class unary_expression; class primitive_type_expression; class array_type_expression; class pointer_type_expression; class record_type_expression; class union_type_expression; class procedure_type_expression; class variable_expression; class array_access_expression; class field_access_expression; class dereference_expression; class designator_expression; class literal; template class number_literal; class defer_statement; /** * 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(procedure_call *) = 0; virtual void visit(cast_expression *) = 0; virtual void visit(traits_expression *) = 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(defer_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(primitive_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(procedure_type_expression *) = 0; virtual void visit(variable_expression *) = 0; virtual void visit(array_access_expression *) = 0; virtual void visit(field_access_expression *) = 0; virtual void visit(dereference_expression *) = 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(number_literal *) = 0; virtual void visit(number_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 *) override; virtual void visit(procedure_definition *) override; virtual void visit(type_definition *) override; virtual void visit(procedure_call *) override; virtual void visit(cast_expression *) override; virtual void visit(traits_expression *) override; virtual void visit(assign_statement *) override; virtual void visit(if_statement *) override; virtual void visit(while_statement *) override; virtual void visit(return_statement *) override; virtual void visit(defer_statement *) override; virtual void visit(block *) override; virtual void visit(program *) override; virtual void visit(binary_expression *) override; virtual void visit(unary_expression *) override; virtual void visit(primitive_type_expression *) override; virtual void visit(array_type_expression *) override; virtual void visit(pointer_type_expression *) override; virtual void visit(record_type_expression *) override; virtual void visit(union_type_expression *) override; virtual void visit(procedure_type_expression *) override; virtual void visit(variable_expression *) override; virtual void visit(array_access_expression *) override; virtual void visit(field_access_expression *) override; virtual void visit(dereference_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(number_literal *) override; virtual void visit(number_literal *) override; }; /** * AST node. */ class node { const struct position source_position; protected: /** * \param position Source code position. */ explicit node(const position position); public: virtual ~node() = 0; /** * \return Node position in the source code. */ const struct position& position() const; }; class statement : public virtual node { public: virtual assign_statement *is_assign(); virtual if_statement *is_if(); virtual while_statement *is_while(); virtual return_statement *is_return(); virtual defer_statement *is_defer(); virtual procedure_call *is_call_statement(); void accept(parser_visitor *visitor); ~statement() = 0; protected: statement(); }; class expression : public virtual node { public: virtual cast_expression *is_cast(); virtual traits_expression *is_traits(); virtual binary_expression *is_binary(); virtual unary_expression *is_unary(); virtual designator_expression *is_designator(); virtual procedure_call *is_call_expression(); virtual literal *is_literal(); void accept(parser_visitor *visitor); ~expression() = 0; protected: expression(); }; /** * Symbol definition. */ class definition : public node { protected: definition(const struct position position, const std::string& identifier, const bool exported); public: const std::string identifier; const bool exported; }; /** * Some type expression. */ class type_expression : public node, public std::enable_shared_from_this { public: virtual std::shared_ptr is_primitive(); virtual std::shared_ptr is_array(); virtual std::shared_ptr is_pointer(); virtual std::shared_ptr is_record(); virtual std::shared_ptr is_union(); virtual std::shared_ptr is_procedure(); void accept(parser_visitor *visitor); protected: type_expression(const struct position position); }; /** * Expression defining a basic type. */ class primitive_type_expression : public type_expression { public: const std::string name; primitive_type_expression(const struct position position, const std::string& name); void accept(parser_visitor *visitor); std::shared_ptr is_primitive() override; }; class array_type_expression : public type_expression { std::shared_ptr m_base; public: const std::uint32_t size; array_type_expression(const struct position position, std::shared_ptr base, const std::uint32_t size); void accept(parser_visitor *visitor); std::shared_ptr is_array() override; type_expression& base(); }; class pointer_type_expression : public type_expression { std::shared_ptr m_base; public: pointer_type_expression(const struct position position, std::shared_ptr base); void accept(parser_visitor *visitor); std::shared_ptr is_pointer() override; type_expression& base(); }; using field_declaration = std::pair>; class record_type_expression : public type_expression { public: const std::vector fields; record_type_expression(const struct position position, std::vector&& fields); void accept(parser_visitor *visitor); std::shared_ptr is_record() override; }; class union_type_expression : public type_expression { public: std::vector fields; union_type_expression(const struct position position, std::vector&& fields); void accept(parser_visitor *visitor); std::shared_ptr is_union() override; }; /** * Variable declaration. */ class variable_declaration : public definition { std::shared_ptr m_type; public: variable_declaration(const struct position position, const std::string& identifier, std::shared_ptr type, const bool exported = false); void accept(parser_visitor *visitor); type_expression& variable_type(); }; /** * Literal expression. */ class literal : public expression { public: virtual number_literal *is_int() = 0; virtual number_literal *is_word() = 0; virtual number_literal *is_float() = 0; virtual number_literal *is_bool() = 0; virtual number_literal *is_char() = 0; virtual number_literal *is_nil() = 0; virtual number_literal *is_string() = 0; literal *is_literal() override; void accept(parser_visitor *visitor); protected: literal(); }; /** * 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, const bool exported, literal *body); void accept(parser_visitor *visitor); literal& body(); virtual ~constant_definition() override; }; /** * Tags a procedure type as never returning. */ struct no_return_t { }; constexpr no_return_t no_return{}; /** * Procedure type. */ class procedure_type_expression : public type_expression { public: const std::shared_ptr return_type; const bool no_return; std::vector parameters; procedure_type_expression(const struct position position, std::shared_ptr return_type = nullptr); procedure_type_expression(const struct position position, no_return_t); void accept(parser_visitor *visitor); std::shared_ptr is_procedure() override; virtual ~procedure_type_expression() override; }; /** * Procedure definition. */ class procedure_definition : public definition { std::shared_ptr m_heading; public: block *const body; procedure_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr heading, block *body = nullptr); void accept(parser_visitor *visitor); procedure_type_expression& heading(); virtual ~procedure_definition() override; }; /** * Type definition. */ class type_definition : public definition { std::shared_ptr m_body; public: type_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr expression); void accept(parser_visitor *visitor); type_expression& body(); }; /** * Cast expression. */ class cast_expression : public expression { std::shared_ptr m_target; expression *m_value; public: cast_expression(const struct position position, std::shared_ptr target, expression *value); void accept(parser_visitor *visitor); cast_expression *is_cast() override; type_expression& target(); expression& value(); virtual ~cast_expression() override; }; class traits_expression : public expression { std::shared_ptr m_type; public: const std::string name; traits_expression(const struct position position, const std::string& name, std::shared_ptr type); void accept(parser_visitor *visitor); traits_expression *is_traits() override; type_expression& type(); }; /** * 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); void accept(parser_visitor *visitor); virtual return_statement *is_return() 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(); designator_expression *is_designator() override; void accept(parser_visitor *visitor); ~designator_expression() = 0; protected: designator_expression(); }; class variable_expression : public designator_expression { public: const std::string name; variable_expression(const struct position position, const std::string& name); void accept(parser_visitor *visitor); variable_expression *is_variable() override; }; class array_access_expression : public designator_expression { expression *m_base; expression *m_index; public: array_access_expression(const struct position position, expression *base, expression *index); void accept(parser_visitor *visitor); expression& base(); expression& index(); array_access_expression *is_array_access() override; ~array_access_expression() override; }; class field_access_expression : public designator_expression { expression *m_base; std::string m_field; public: field_access_expression(const struct position position, expression *base, const std::string& field); void accept(parser_visitor *visitor); expression& base(); std::string& field(); field_access_expression *is_field_access() override; ~field_access_expression() override; }; class dereference_expression : public designator_expression { expression *m_base; public: dereference_expression(const struct position position, expression *base); void accept(parser_visitor *visitor); expression& base(); dereference_expression *is_dereference() override; ~dereference_expression() override; }; /** * Procedure call expression. */ class procedure_call : public expression, public statement { designator_expression *m_callable; public: std::vector arguments; procedure_call(const struct position position, designator_expression *callable); void accept(parser_visitor *visitor); virtual procedure_call *is_call_statement() override; virtual procedure_call *is_call_expression() override; designator_expression& callable(); virtual ~procedure_call() 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); void accept(parser_visitor *visitor); designator_expression& lvalue(); expression& rvalue(); virtual ~assign_statement() override; assign_statement *is_assign() override; }; /** * If-statement. */ class if_statement : public statement { conditional_statements *m_body; std::vector *m_alternative; public: std::vector branches; if_statement(const struct position position, conditional_statements *body, std::vector *alternative = nullptr); void accept(parser_visitor *visitor); virtual if_statement *is_if() override; conditional_statements& body(); std::vector *alternative(); virtual ~if_statement() override; }; /** * While-statement. */ class while_statement : public statement { conditional_statements *m_body; public: std::vector branches; while_statement(const struct position position, conditional_statements *body); void accept(parser_visitor *visitor); while_statement *is_while() override; conditional_statements& body(); virtual ~while_statement() override; }; class block : public node { public: std::vector variables; std::vector constants; std::vector body; block(const struct position position); void accept(parser_visitor *visitor); virtual ~block() override; }; class program : public block { public: std::vector types; std::vector procedures; program(const struct position position); void accept(parser_visitor *visitor); virtual ~program() override; }; template class number_literal : public literal { public: T value; number_literal(const struct position position, const T& value) : node(position), value(value) { } number_literal *is_int() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_word() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_float() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_bool() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_char() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_nil() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } number_literal *is_string() override { if (std::is_same::value) { return reinterpret_cast *>(this); } else { return nullptr; } } void accept(parser_visitor *visitor) { visitor->visit(this); } }; class defer_statement : public statement { public: std::vector statements; defer_statement(const struct position position); void accept(parser_visitor *visitor); defer_statement *is_defer() override; virtual ~defer_statement() override; }; 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); void accept(parser_visitor *visitor); binary_expression *is_binary() 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); void accept(parser_visitor *visitor); unary_expression *is_unary() override; expression& operand(); unary_operator operation() const; virtual ~unary_expression() override; }; const char *print_binary_operator(const binary_operator operation); } }