445 lines
13 KiB
C++
445 lines
13 KiB
C++
#pragma once
|
|
|
|
#include <boost/core/noncopyable.hpp>
|
|
#include <memory>
|
|
#include <elna/source/lexer.hpp>
|
|
|
|
namespace elna::source
|
|
{
|
|
enum class binary_operator
|
|
{
|
|
sum,
|
|
subtraction,
|
|
multiplication,
|
|
division,
|
|
equals,
|
|
not_equals,
|
|
less,
|
|
greater,
|
|
less_equal,
|
|
greater_equal
|
|
};
|
|
|
|
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 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(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(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;
|
|
};
|
|
|
|
/**
|
|
* 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
|
|
{
|
|
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;
|
|
};
|
|
|
|
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<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.
|
|
*/
|
|
declaration(const struct position position, const std::string& identifier,
|
|
std::unique_ptr<type_expression>&& type);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
type_expression& type() noexcept;
|
|
};
|
|
|
|
/**
|
|
* Constant definition.
|
|
*/
|
|
class constant_definition : public definition
|
|
{
|
|
std::unique_ptr<integer_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,
|
|
std::unique_ptr<integer_literal>&& body);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
integer_literal& body();
|
|
};
|
|
|
|
/**
|
|
* Procedure definition.
|
|
*/
|
|
class procedure_definition : public definition
|
|
{
|
|
std::unique_ptr<block> m_body;
|
|
std::vector<std::unique_ptr<declaration>> 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<block>&& body);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
block& body();
|
|
std::vector<std::unique_ptr<declaration>>& parameters() noexcept;
|
|
};
|
|
|
|
/**
|
|
* Call statement.
|
|
*/
|
|
class call_statement : public statement
|
|
{
|
|
std::string m_name;
|
|
std::vector<std::unique_ptr<expression>> 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<std::unique_ptr<expression>>& arguments() noexcept;
|
|
};
|
|
|
|
class compound_statement : public statement
|
|
{
|
|
std::vector<std::unique_ptr<statement>> m_statements;
|
|
|
|
public:
|
|
explicit compound_statement(const struct position position);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
std::vector<std::unique_ptr<statement>>& statements();
|
|
};
|
|
|
|
class assign_statement : public statement
|
|
{
|
|
std::string m_lvalue;
|
|
std::unique_ptr<expression> 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<expression>&& rvalue);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
std::string& lvalue() noexcept;
|
|
expression& rvalue();
|
|
};
|
|
|
|
/**
|
|
* If-statement.
|
|
*/
|
|
class if_statement : public statement
|
|
{
|
|
std::unique_ptr<expression> m_prerequisite;
|
|
std::unique_ptr<statement> 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<expression>&& prerequisite,
|
|
std::unique_ptr<statement>&& body);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
expression& prerequisite();
|
|
statement& body();
|
|
};
|
|
|
|
/**
|
|
* While-statement.
|
|
*/
|
|
class while_statement : public statement
|
|
{
|
|
std::unique_ptr<expression> m_prerequisite;
|
|
std::unique_ptr<statement> 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<expression>&& prerequisite,
|
|
std::unique_ptr<statement>&& body);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
expression& prerequisite();
|
|
statement& body();
|
|
};
|
|
|
|
class block : public node
|
|
{
|
|
std::unique_ptr<statement> m_body;
|
|
std::vector<std::unique_ptr<definition>> m_definitions;
|
|
std::vector<std::unique_ptr<declaration>> m_declarations;
|
|
|
|
public:
|
|
block(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
|
|
std::vector<std::unique_ptr<declaration>>&& declarations,
|
|
std::unique_ptr<statement>&& body);
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
|
|
statement& body();
|
|
std::vector<std::unique_ptr<definition>>& definitions() noexcept;
|
|
std::vector<std::unique_ptr<declaration>>& declarations() noexcept;
|
|
};
|
|
|
|
class program : public block
|
|
{
|
|
public:
|
|
program(const struct position position, std::vector<std::unique_ptr<definition>>&& definitions,
|
|
std::vector<std::unique_ptr<declaration>>&& declarations,
|
|
std::unique_ptr<statement>&& 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<expression> m_lhs;
|
|
std::unique_ptr<expression> m_rhs;
|
|
binary_operator m_operator;
|
|
|
|
public:
|
|
binary_expression(const struct position position, std::unique_ptr<expression>&& lhs,
|
|
std::unique_ptr<expression>&& rhs, const unsigned char operation);
|
|
|
|
virtual void accept(parser_visitor *visitor) override;
|
|
expression& lhs();
|
|
expression& rhs();
|
|
binary_operator operation() const noexcept;
|
|
};
|
|
|
|
class parser : boost::noncopyable
|
|
{
|
|
std::unique_ptr<expression> parse_factor();
|
|
std::unique_ptr<expression> parse_term();
|
|
std::unique_ptr<expression> parse_expression();
|
|
std::unique_ptr<expression> parse_condition();
|
|
std::unique_ptr<constant_definition> parse_constant_definition();
|
|
std::unique_ptr<procedure_definition> parse_procedure_definition();
|
|
std::unique_ptr<type_expression> parse_type_expression();
|
|
std::unique_ptr<declaration> parse_declaration();
|
|
std::unique_ptr<statement> parse_statement();
|
|
std::unique_ptr<call_statement> parse_call_statement();
|
|
std::unique_ptr<compound_statement> parse_compound_statement();
|
|
std::unique_ptr<assign_statement> parse_assign_statement();
|
|
std::unique_ptr<if_statement> parse_if_statement();
|
|
std::unique_ptr<while_statement> parse_while_statement();
|
|
std::vector<std::unique_ptr<constant_definition>> parse_constant_definitions();
|
|
std::vector<std::unique_ptr<procedure_definition>> parse_procedure_definitions();
|
|
std::vector<std::unique_ptr<declaration>> parse_declarations();
|
|
std::unique_ptr<block> parse_block();
|
|
|
|
lexer iterator;
|
|
|
|
public:
|
|
parser(lexer&& tokens);
|
|
|
|
/**
|
|
* Parses a source text.
|
|
*
|
|
* \return Parsed program or nothing if an error occurred.
|
|
*/
|
|
std::unique_ptr<program> parse();
|
|
|
|
/**
|
|
* Gets produced errors.
|
|
*
|
|
* \return Produced error list.
|
|
*/
|
|
const std::list<std::unique_ptr<error>>& errors() const noexcept;
|
|
};
|
|
}
|