Support compound statements
This commit is contained in:
@ -15,7 +15,7 @@ namespace elna::riscv
|
||||
|
||||
struct reference
|
||||
{
|
||||
const char* name;
|
||||
std::string name;
|
||||
std::size_t offset;
|
||||
address_t target;
|
||||
};
|
||||
@ -141,6 +141,7 @@ namespace elna::riscv
|
||||
|
||||
struct instruction
|
||||
{
|
||||
instruction() = default; // NOP = addi x0, x0, 0.
|
||||
instruction(base_opcode opcode);
|
||||
|
||||
instruction& i(x_register rd, funct3_t funct3, x_register rs1, std::uint32_t immediate);
|
||||
@ -155,17 +156,20 @@ namespace elna::riscv
|
||||
std::uint32_t representation{ 0 };
|
||||
};
|
||||
|
||||
class visitor : public source::parser_visitor
|
||||
class visitor final : public source::parser_visitor
|
||||
{
|
||||
public:
|
||||
std::vector<instruction> instructions;
|
||||
bool register_in_use{ true };
|
||||
std::uint32_t variable_counter = 1;
|
||||
reference references[3];
|
||||
std::vector<reference> references;
|
||||
std::unordered_map<std::string, std::int32_t> constants;
|
||||
|
||||
virtual void visit(source::declaration *declaration) override;
|
||||
virtual void visit(source::definition *definition) override;
|
||||
virtual void visit(source::bang_statement *statement) override;
|
||||
virtual void visit(source::compound_statement *statement) override;
|
||||
virtual void visit(source::assignment_statement *statement) override;
|
||||
virtual void visit(source::block *block) override;
|
||||
virtual void visit(source::variable_expression *variable) override;
|
||||
virtual void visit(source::integer_literal *number) override;
|
||||
|
@ -33,6 +33,7 @@ namespace elna::source
|
||||
text_iterator& operator++(int);
|
||||
bool operator==(const text_iterator& that) const noexcept;
|
||||
bool operator!=(const text_iterator& that) const noexcept;
|
||||
text_iterator operator+(std::size_t step);
|
||||
|
||||
friend std::pair<text_iterator, text_iterator> text_iterators(const std::string& buffer);
|
||||
};
|
||||
@ -50,19 +51,23 @@ namespace elna::source
|
||||
*/
|
||||
enum class type : std::uint16_t
|
||||
{
|
||||
number = 0,
|
||||
term_operator = 1,
|
||||
let = 2,
|
||||
identifier = 3,
|
||||
equals = 4,
|
||||
var = 5,
|
||||
semicolon = 6,
|
||||
left_paren = 7,
|
||||
right_paren = 8,
|
||||
bang = 9,
|
||||
dot = 10,
|
||||
comma = 11,
|
||||
factor_operator = 12,
|
||||
number,
|
||||
term_operator,
|
||||
let,
|
||||
identifier,
|
||||
equals,
|
||||
var,
|
||||
semicolon,
|
||||
left_paren,
|
||||
right_paren,
|
||||
bang,
|
||||
dot,
|
||||
comma,
|
||||
factor_operator,
|
||||
eof,
|
||||
begin,
|
||||
end,
|
||||
assignment
|
||||
};
|
||||
|
||||
/**
|
||||
@ -113,6 +118,16 @@ namespace elna::source
|
||||
std::string what() const override;
|
||||
};
|
||||
|
||||
class unexpected_token final : public error
|
||||
{
|
||||
token m_token;
|
||||
|
||||
public:
|
||||
explicit unexpected_token(const token& token);
|
||||
|
||||
std::string what() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split the source into tokens.
|
||||
*
|
||||
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <elna/source/lexer.hpp>
|
||||
|
||||
namespace elna::source
|
||||
@ -14,8 +16,11 @@ namespace elna::source
|
||||
division
|
||||
};
|
||||
|
||||
class declaration;
|
||||
class definition;
|
||||
class bang_statement;
|
||||
class compound_statement;
|
||||
class assignment_statement;
|
||||
class block;
|
||||
class binary_expression;
|
||||
class variable_expression;
|
||||
@ -23,8 +28,11 @@ namespace elna::source
|
||||
|
||||
struct parser_visitor
|
||||
{
|
||||
virtual void visit(declaration *) = 0;
|
||||
virtual void visit(definition *) = 0;
|
||||
virtual void visit(bang_statement *) = 0;
|
||||
virtual void visit(compound_statement *) = 0;
|
||||
virtual void visit(assignment_statement *) = 0;
|
||||
virtual void visit(block *) = 0;
|
||||
virtual void visit(binary_expression *) = 0;
|
||||
virtual void visit(variable_expression *) = 0;
|
||||
@ -48,6 +56,20 @@ namespace elna::source
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Variable declaration.
|
||||
*/
|
||||
class declaration : public node
|
||||
{
|
||||
std::string m_identifier;
|
||||
|
||||
public:
|
||||
declaration(const std::string& identifier);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
std::string& identifier() noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant definition.
|
||||
*/
|
||||
@ -57,7 +79,7 @@ namespace elna::source
|
||||
std::unique_ptr<integer_literal> m_body;
|
||||
|
||||
public:
|
||||
definition(std::string&& identifier, std::unique_ptr<integer_literal>&& body);
|
||||
definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
std::string& identifier() noexcept;
|
||||
@ -75,6 +97,25 @@ namespace elna::source
|
||||
expression& body();
|
||||
};
|
||||
|
||||
class compound_statement : public statement
|
||||
{
|
||||
std::vector<std::unique_ptr<statement>> m_statements;
|
||||
|
||||
public:
|
||||
compound_statement() = default;
|
||||
compound_statement(std::vector<std::unique_ptr<statement>>&& statements);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
std::vector<std::unique_ptr<statement>>& statements();
|
||||
};
|
||||
|
||||
class assignment_statement : public statement
|
||||
{
|
||||
std::unique_ptr<variable_expression> lvalue;
|
||||
std::unique_ptr<expression> rvalue;
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Block.
|
||||
*/
|
||||
@ -82,13 +123,17 @@ namespace elna::source
|
||||
{
|
||||
std::unique_ptr<statement> m_body;
|
||||
std::vector<std::unique_ptr<definition>> m_definitions;
|
||||
std::vector<std::unique_ptr<declaration>> m_declarations;
|
||||
|
||||
public:
|
||||
block(std::vector<std::unique_ptr<definition>>&& definitions, std::unique_ptr<statement>&& body);
|
||||
block(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 integer_literal : public expression
|
||||
@ -129,7 +174,7 @@ namespace elna::source
|
||||
binary_operator operation() const noexcept;
|
||||
};
|
||||
|
||||
struct parser
|
||||
struct parser : boost::noncopyable
|
||||
{
|
||||
parser(const std::vector<token>& tokens);
|
||||
|
||||
@ -140,11 +185,19 @@ namespace elna::source
|
||||
std::unique_ptr<expression> parse_term();
|
||||
std::unique_ptr<expression> parse_expression();
|
||||
std::unique_ptr<definition> parse_definition();
|
||||
std::unique_ptr<statement> parse_bang_statement();
|
||||
std::unique_ptr<declaration> parse_declaration();
|
||||
std::unique_ptr<statement> parse_statement();
|
||||
std::unique_ptr<bang_statement> parse_bang_statement();
|
||||
std::unique_ptr<compound_statement> parse_compound_statement();
|
||||
std::vector<std::unique_ptr<definition>> parse_definitions();
|
||||
std::vector<std::unique_ptr<declaration>> parse_declarations();
|
||||
std::unique_ptr<block> parse_block();
|
||||
|
||||
std::optional<std::reference_wrapper<const token>> advance(const token::type token_type);
|
||||
bool skip(const token::type token_type);
|
||||
|
||||
std::vector<token>::const_iterator tokens;
|
||||
std::vector<token>::const_iterator end;
|
||||
std::list<std::unique_ptr<error>> errors;
|
||||
};
|
||||
}
|
||||
|
@ -6,6 +6,17 @@
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
class name_collision final : public error
|
||||
{
|
||||
position previous;
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
name_collision(const std::string& name, const position current, const position previous);
|
||||
|
||||
std::string what() const override;
|
||||
};
|
||||
|
||||
class info
|
||||
{
|
||||
public:
|
||||
@ -27,8 +38,13 @@ namespace elna::source
|
||||
|
||||
class variable_info final : public info
|
||||
{
|
||||
std::size_t m_offset{ 0 };
|
||||
|
||||
public:
|
||||
variable_info(const std::size_t offset);
|
||||
~variable_info() override;
|
||||
|
||||
std::size_t offset() const noexcept;
|
||||
};
|
||||
|
||||
class symbol_table
|
||||
@ -44,8 +60,11 @@ namespace elna::source
|
||||
|
||||
class name_analysis_visitor final : public source::parser_visitor
|
||||
{
|
||||
void visit(declaration *declaration) override;
|
||||
void visit(definition *definition) override;
|
||||
void visit(bang_statement *statement) override;
|
||||
void visit(compound_statement *statement) override;
|
||||
void visit(assignment_statement *statement) override;
|
||||
void visit(block *block) override;
|
||||
void visit(integer_literal *number) override;
|
||||
void visit(variable_expression *variable) override;
|
||||
|
Reference in New Issue
Block a user