#pragma once #include #include #include namespace elna::source { enum class binary_operator { sum, subtraction, multiplication, division, equals, not_equals, less, greater, less_equal, greater_equal }; enum class unary_operator { reference, dereference }; class declaration; class constant_definition; class procedure_definition; class call_statement; class compound_statement; class assign_statement; class if_statement; class while_statement; class block; class program; class binary_expression; class unary_expression; class type_expression; class variable_expression; class integer_literal; class boolean_literal; /** * Interface for AST visitors. */ struct parser_visitor { virtual void visit(declaration *) = 0; virtual void visit(constant_definition *) = 0; virtual void visit(procedure_definition *) = 0; virtual void visit(call_statement *) = 0; virtual void visit(compound_statement *) = 0; virtual void visit(assign_statement *) = 0; virtual void visit(if_statement *) = 0; virtual void visit(while_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(type_expression *) = 0; virtual void visit(variable_expression *) = 0; virtual void visit(integer_literal *) = 0; virtual void visit(boolean_literal *) = 0; }; /** * A visitor which visits all nodes but does nothing. */ struct empty_visitor : parser_visitor { virtual void visit(declaration *declaration) override; virtual void visit(constant_definition *definition) override; virtual void visit(procedure_definition *definition) override; virtual void visit(call_statement *statement) override; virtual void visit(compound_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(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(type_expression *variable) override; virtual void visit(variable_expression *variable) override; virtual void visit(integer_literal *number) override; virtual void visit(boolean_literal *boolean) override; }; /** * Operand representing a subexpression in the 3 address code. */ struct operand { public: virtual ~operand() noexcept = 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 noexcept; }; class variable_operand final : public operand { std::string m_name; public: explicit variable_operand(const std::string& name); const std::string& name() const noexcept; }; 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 noexcept; }; 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 noexcept; }; /** * AST node. */ class node { const struct position source_position; protected: /** * \param position Source code position. */ explicit node(const position position); public: virtual void accept(parser_visitor *) = 0; /** * \return Node position in the source code. */ const struct position& position() const noexcept; }; 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() noexcept; }; /** * Expression defining a composed type like pointer or an array. */ class type_expression : public node { std::string m_base; bool m_pointer{ false }; public: /** * \param position Source code position. * \param name Type name. * \param is_pointer Whether it is a pointer type. */ type_expression(const struct position position, const std::string& name, const bool is_pointer = false); virtual void accept(parser_visitor *visitor) override; /** * \return Name of the base type. */ const std::string& base() const noexcept; /** * \return Whether the type is a pointer. */ bool is_pointer() const noexcept; }; /** * Variable declaration. */ class declaration : public definition { std::unique_ptr 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. */ declaration(const struct position position, const std::string& identifier, std::unique_ptr&& type); virtual void accept(parser_visitor *visitor) override; type_expression& type() noexcept; }; /** * Constant definition. */ class constant_definition : public definition { std::unique_ptr 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, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; integer_literal& body(); }; /** * Procedure definition. */ class procedure_definition : public definition { std::unique_ptr m_body; std::vector> m_parameters; public: /** * \param position Source code position. * \param identifier Procedure name. * \param body Procedure body. */ procedure_definition(const struct position position, const std::string& identifier, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; block& body(); std::vector>& parameters() noexcept; }; /** * Call statement. */ class call_statement : public statement { std::string m_name; std::vector> m_arguments; public: /** * \param position Source code position. * \param name Callable's name. */ call_statement(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; std::string& name() noexcept; std::vector>& arguments() noexcept; }; class compound_statement : public statement { std::vector> m_statements; public: explicit compound_statement(const struct position position); virtual void accept(parser_visitor *visitor) override; std::vector>& statements(); }; class assign_statement : public statement { std::string m_lvalue; std::unique_ptr m_rvalue; public: /** * \param position Source code position. * \param lvalue Left-hand side. * \param rvalue Assigned expression. */ assign_statement(const struct position position, const std::string& lvalue, std::unique_ptr&& rvalue); virtual void accept(parser_visitor *visitor) override; std::string& lvalue() noexcept; expression& rvalue(); }; /** * If-statement. */ class if_statement : public statement { std::unique_ptr m_prerequisite; std::unique_ptr m_body; public: /** * \param position Source code position. * \param prerequisite Condition. * \param body Statement executed if the condition is met. */ if_statement(const struct position position, std::unique_ptr&& prerequisite, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); statement& body(); }; /** * While-statement. */ class while_statement : public statement { std::unique_ptr m_prerequisite; std::unique_ptr m_body; public: /** * \param position Source code position. * \param prerequisite Condition. * \param body Statement executed while the condition is met. */ while_statement(const struct position position, std::unique_ptr&& prerequisite, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); statement& body(); }; class block : public node { std::unique_ptr m_body; std::vector> m_definitions; std::vector> m_declarations; public: block(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; statement& body(); std::vector>& definitions() noexcept; std::vector>& declarations() noexcept; }; class program : public block { public: program(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; }; class integer_literal : public expression { std::int32_t m_number; public: integer_literal(const struct position position, const std::int32_t value); virtual void accept(parser_visitor *visitor) override; std::int32_t number() const noexcept; }; class boolean_literal : public expression { bool m_boolean; public: boolean_literal(const struct position position, const bool value); virtual void accept(parser_visitor *visitor) override; bool boolean() const noexcept; }; class variable_expression : public 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 noexcept; }; class binary_expression : public expression { std::unique_ptr m_lhs; std::unique_ptr m_rhs; binary_operator m_operator; public: binary_expression(const struct position position, std::unique_ptr&& lhs, std::unique_ptr&& rhs, const unsigned char operation); virtual void accept(parser_visitor *visitor) override; expression& lhs(); expression& rhs(); binary_operator operation() const noexcept; }; class unary_expression : public expression { std::unique_ptr m_operand; unary_operator m_operator; public: unary_expression(const struct position position, std::unique_ptr&& operand, const unsigned char operation); virtual void accept(parser_visitor *visitor) override; expression& operand(); unary_operator operation() const noexcept; }; class parser : boost::noncopyable { std::unique_ptr parse_unary_expression(); std::unique_ptr parse_factor(); std::unique_ptr parse_term(); std::unique_ptr parse_expression(); std::unique_ptr parse_condition(); std::unique_ptr parse_constant_definition(); std::unique_ptr parse_procedure_definition(); std::unique_ptr parse_type_expression(); std::unique_ptr parse_declaration(); std::unique_ptr parse_statement(); std::unique_ptr parse_call_statement(); std::unique_ptr parse_compound_statement(); std::unique_ptr parse_assign_statement(); std::unique_ptr parse_if_statement(); std::unique_ptr parse_while_statement(); std::vector> parse_constant_definitions(); std::vector> parse_procedure_definitions(); std::vector> parse_declarations(); std::unique_ptr parse_block(); lexer iterator; public: parser(lexer&& tokens); /** * Parses a source text. * * \return Parsed program or nothing if an error occurred. */ std::unique_ptr parse(); /** * Gets produced errors. * * \return Produced error list. */ const std::list>& errors() const noexcept; }; }