Get rid of the raw pointers in the parser
This commit is contained in:
		@@ -19,10 +19,10 @@ add_executable(elnsh shell/main.cpp
 | 
			
		||||
target_include_directories(elnsh PRIVATE include)
 | 
			
		||||
 | 
			
		||||
add_executable(elna source/main.cpp
 | 
			
		||||
	source/lexer.cpp include/elna/lexer.hpp
 | 
			
		||||
	source/lexer.cpp include/elna/source/lexer.hpp
 | 
			
		||||
	source/parser.cpp include/elna/source/parser.hpp
 | 
			
		||||
	source/result.cpp include/elna/result.hpp
 | 
			
		||||
	source/riscv.cpp include/elna/riscv.hpp
 | 
			
		||||
	source/parser.cpp include/elna/parser.hpp
 | 
			
		||||
	source/ir.cpp include/elna/ir.hpp
 | 
			
		||||
	source/cl.cpp include/elna/cl.hpp
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "elna/parser.hpp"
 | 
			
		||||
#include "elna/source/parser.hpp"
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
    class TransformVisitor final : public ParserVisitor
 | 
			
		||||
    class TransformVisitor final : public source::ParserVisitor
 | 
			
		||||
    {
 | 
			
		||||
        void visit(Node *node) override;
 | 
			
		||||
        void visit(Definition *definition) override;
 | 
			
		||||
        void visit(BangStatement *statement) override;
 | 
			
		||||
        void visit(Block *block) override;
 | 
			
		||||
        void visit(Expression *expression) override;
 | 
			
		||||
        void visit(Number *number) override;
 | 
			
		||||
        void visit(Variable *variable) override;
 | 
			
		||||
        void visit(BinaryExpression *binaryExpression) override;
 | 
			
		||||
        void visit(source::definition *definition) override;
 | 
			
		||||
        void visit(source::bang_statement *statement) override;
 | 
			
		||||
        void visit(source::block *block) override;
 | 
			
		||||
        void visit(source::integer_literal *number) override;
 | 
			
		||||
        void visit(source::variable *variable) override;
 | 
			
		||||
        void visit(source::binary_expression *binaryExpression) override;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "elna/result.hpp"
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace lex
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Range over the source text that keeps track of the current position.
 | 
			
		||||
     */
 | 
			
		||||
    struct source
 | 
			
		||||
    {
 | 
			
		||||
        class const_iterator
 | 
			
		||||
        {
 | 
			
		||||
            std::string::const_iterator m_buffer;
 | 
			
		||||
            elna::source::position m_position;
 | 
			
		||||
 | 
			
		||||
            const_iterator(std::string::const_iterator buffer,
 | 
			
		||||
                    const elna::source::position start_position = elna::source::position());
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
            using iterator_category = std::forward_iterator_tag;
 | 
			
		||||
            using difference_type = ptrdiff_t;
 | 
			
		||||
            using value_type = char;
 | 
			
		||||
            using pointer = const value_type *;
 | 
			
		||||
            using reference = const value_type&;
 | 
			
		||||
 | 
			
		||||
            const elna::source::position& position() const noexcept;
 | 
			
		||||
 | 
			
		||||
            reference operator*() const noexcept;
 | 
			
		||||
            pointer operator->() const noexcept;
 | 
			
		||||
            const_iterator& operator++();
 | 
			
		||||
            const_iterator& operator++(int);
 | 
			
		||||
            bool operator==(const const_iterator& that) const noexcept;
 | 
			
		||||
            bool operator!=(const const_iterator& that) const noexcept;
 | 
			
		||||
 | 
			
		||||
            friend source;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        source(const std::string& buffer);
 | 
			
		||||
        const_iterator begin() const;
 | 
			
		||||
        const_iterator end() const;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        const std::string m_buffer;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Union type representing a single token.
 | 
			
		||||
     */
 | 
			
		||||
    struct Token
 | 
			
		||||
    {
 | 
			
		||||
        /**
 | 
			
		||||
         * Token type.
 | 
			
		||||
         */
 | 
			
		||||
        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,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Type of the token value.
 | 
			
		||||
         */
 | 
			
		||||
        union Value
 | 
			
		||||
        {
 | 
			
		||||
            std::int32_t number;
 | 
			
		||||
            const char *identifier;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Token(type of, elna::source::position position);
 | 
			
		||||
        Token(type of, std::int32_t value, elna::source::position position);
 | 
			
		||||
        Token(type of, const char *value, elna::source::position position);
 | 
			
		||||
        Token(const Token& that);
 | 
			
		||||
        Token(Token&& that);
 | 
			
		||||
        ~Token();
 | 
			
		||||
 | 
			
		||||
        Token& operator=(const Token& that);
 | 
			
		||||
        Token& operator=(Token&& that);
 | 
			
		||||
 | 
			
		||||
        type of() const noexcept;
 | 
			
		||||
        const char *identifier() const noexcept;
 | 
			
		||||
        std::int32_t number() const noexcept;
 | 
			
		||||
        const elna::source::position& position() const noexcept;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        type m_type;
 | 
			
		||||
        Value m_value;
 | 
			
		||||
        elna::source::position m_position;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Split the source into tokens.
 | 
			
		||||
     *
 | 
			
		||||
     * \param buffer Source text.
 | 
			
		||||
     * \return Tokens or error.
 | 
			
		||||
     */
 | 
			
		||||
    elna::source::result<std::vector<Token>> lex(const char *buffer);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,125 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <elna/lexer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
    enum class BinaryOperator
 | 
			
		||||
    {
 | 
			
		||||
        sum,
 | 
			
		||||
        subtraction,
 | 
			
		||||
        multiplication,
 | 
			
		||||
        division
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Node;
 | 
			
		||||
    class Definition;
 | 
			
		||||
    class BangStatement;
 | 
			
		||||
    class Block;
 | 
			
		||||
    class Expression;
 | 
			
		||||
    class BinaryExpression;
 | 
			
		||||
    class Variable;
 | 
			
		||||
    class Number;
 | 
			
		||||
 | 
			
		||||
    struct ParserVisitor
 | 
			
		||||
    {
 | 
			
		||||
        virtual void visit(Node *) = 0;
 | 
			
		||||
        virtual void visit(Definition *) = 0;
 | 
			
		||||
        virtual void visit(BangStatement *) = 0;
 | 
			
		||||
        virtual void visit(Block *) = 0;
 | 
			
		||||
        virtual void visit(Expression *) = 0;
 | 
			
		||||
        virtual void visit(BinaryExpression *) = 0;
 | 
			
		||||
        virtual void visit(Variable *) = 0;
 | 
			
		||||
        virtual void visit(Number *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AST node.
 | 
			
		||||
     */
 | 
			
		||||
    class Node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void accept(ParserVisitor *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Statement : public Node
 | 
			
		||||
    {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constant definition.
 | 
			
		||||
     */
 | 
			
		||||
    class Definition : public Node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        Number *number;
 | 
			
		||||
        const char *identifier;
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class BangStatement : public Statement
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        Expression *expression;
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Block.
 | 
			
		||||
     */
 | 
			
		||||
    class Block : public Node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        Definition** definitions{ nullptr };
 | 
			
		||||
        size_t definitionsLength{ 0 };
 | 
			
		||||
        Statement *statement{ nullptr };
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Expression : public Node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Number : public Expression
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        std::int32_t value;
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Variable : public Expression
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        const char *identifier;
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class BinaryExpression : public Expression
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        Expression *lhs, *rhs;
 | 
			
		||||
        BinaryOperator _operator;
 | 
			
		||||
 | 
			
		||||
        BinaryExpression(Expression *lhs, Expression *rhs, unsigned char);
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Expression *parseFactor(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Expression *parseTerm(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Expression *parseExpression(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Definition *parseDefinition(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Statement *parseStatement(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Definition **parseDefinitions(lex::Token **tokens, std::size_t *length, std::size_t *resultLength);
 | 
			
		||||
    Block *parseBlock(lex::Token **tokens, std::size_t *length);
 | 
			
		||||
    Block *parse(lex::Token *tokenStream, std::size_t length);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include "elna/parser.hpp"
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include "elna/source/parser.hpp"
 | 
			
		||||
#include "elna/result.hpp"
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
@@ -141,7 +142,7 @@ namespace elna
 | 
			
		||||
        std::uint32_t instruction{ 0 };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class RiscVVisitor : public ParserVisitor
 | 
			
		||||
    class RiscVVisitor : public source::ParserVisitor
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        Instruction *instructions;
 | 
			
		||||
@@ -149,19 +150,15 @@ namespace elna
 | 
			
		||||
        bool registerInUse{ true };
 | 
			
		||||
        std::uint32_t variableCounter = 1;
 | 
			
		||||
        Reference references[3];
 | 
			
		||||
        std::int32_t *constValues{ nullptr };
 | 
			
		||||
        const char **constNames{ nullptr };
 | 
			
		||||
        std::size_t constCount{ 0 };
 | 
			
		||||
        std::unordered_map<std::string, std::int32_t> constants;
 | 
			
		||||
 | 
			
		||||
        virtual void visit(Node *) override;
 | 
			
		||||
        virtual void visit(Definition *definition) override;
 | 
			
		||||
        virtual void visit(BangStatement *statement) override;
 | 
			
		||||
        virtual void visit(Block *block) override;
 | 
			
		||||
        virtual void visit(Expression *operand) override;
 | 
			
		||||
        virtual void visit(Variable *variable) override;
 | 
			
		||||
        virtual void visit(Number *number) override;
 | 
			
		||||
        virtual void visit(BinaryExpression *expression) override;
 | 
			
		||||
        virtual void visit(source::definition *definition) override;
 | 
			
		||||
        virtual void visit(source::bang_statement *statement) override;
 | 
			
		||||
        virtual void visit(source::block *block) override;
 | 
			
		||||
        virtual void visit(source::variable *variable) override;
 | 
			
		||||
        virtual void visit(source::integer_literal *number) override;
 | 
			
		||||
        virtual void visit(source::binary_expression *expression) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Symbol writeNext(Block *ast);
 | 
			
		||||
    Symbol writeNext(source::block *ast);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								include/elna/source/lexer.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								include/elna/source/lexer.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "elna/result.hpp"
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace source
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Range over the source text that keeps track of the current position.
 | 
			
		||||
     */
 | 
			
		||||
    class text_iterator
 | 
			
		||||
    {
 | 
			
		||||
        std::string::const_iterator m_buffer;
 | 
			
		||||
        elna::source::position m_position;
 | 
			
		||||
 | 
			
		||||
        text_iterator(std::string::const_iterator buffer,
 | 
			
		||||
                const elna::source::position start_position = elna::source::position());
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        using iterator_category = std::forward_iterator_tag;
 | 
			
		||||
        using difference_type = ptrdiff_t;
 | 
			
		||||
        using value_type = char;
 | 
			
		||||
        using pointer = const value_type *;
 | 
			
		||||
        using reference = const value_type&;
 | 
			
		||||
 | 
			
		||||
        const elna::source::position& position() const noexcept;
 | 
			
		||||
 | 
			
		||||
        reference operator*() const noexcept;
 | 
			
		||||
        pointer operator->() const noexcept;
 | 
			
		||||
        text_iterator& operator++();
 | 
			
		||||
        text_iterator& operator++(int);
 | 
			
		||||
        bool operator==(const text_iterator& that) const noexcept;
 | 
			
		||||
        bool operator!=(const text_iterator& that) const noexcept;
 | 
			
		||||
 | 
			
		||||
        friend std::pair<text_iterator, text_iterator> text_iterators(const std::string& buffer);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::pair<text_iterator, text_iterator>
 | 
			
		||||
    text_iterators(const std::string &buffer);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Union type representing a single token.
 | 
			
		||||
     */
 | 
			
		||||
    struct token
 | 
			
		||||
    {
 | 
			
		||||
        /**
 | 
			
		||||
         * Token type.
 | 
			
		||||
         */
 | 
			
		||||
        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,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Type of the token value.
 | 
			
		||||
         */
 | 
			
		||||
        union value
 | 
			
		||||
        {
 | 
			
		||||
            value();
 | 
			
		||||
            value(std::int32_t value);
 | 
			
		||||
            value(const std::string& value);
 | 
			
		||||
            ~value();
 | 
			
		||||
 | 
			
		||||
            std::nullptr_t nil;
 | 
			
		||||
            std::int32_t number;
 | 
			
		||||
            std::string identifier;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        token(type of, elna::source::position position);
 | 
			
		||||
        token(type of, std::int32_t value, const elna::source::position position);
 | 
			
		||||
        token(type of, const std::string& value, const elna::source::position position);
 | 
			
		||||
        token(const token& that);
 | 
			
		||||
        token(token&& that);
 | 
			
		||||
        ~token();
 | 
			
		||||
 | 
			
		||||
        token& operator=(const token& that);
 | 
			
		||||
        token& operator=(token&& that);
 | 
			
		||||
 | 
			
		||||
        type of() const noexcept;
 | 
			
		||||
        const std::string& identifier() const;
 | 
			
		||||
        std::int32_t number() const;
 | 
			
		||||
        const elna::source::position& position() const noexcept;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        type m_type;
 | 
			
		||||
        value m_value;
 | 
			
		||||
        elna::source::position m_position;
 | 
			
		||||
 | 
			
		||||
        bool has_identifier() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Split the source into tokens.
 | 
			
		||||
     *
 | 
			
		||||
     * \param buffer Source text.
 | 
			
		||||
     * \return Tokens or error.
 | 
			
		||||
     */
 | 
			
		||||
    elna::source::result<std::vector<token>> lex(const std::string& buffer);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										153
									
								
								include/elna/source/parser.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								include/elna/source/parser.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <elna/source/lexer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace source
 | 
			
		||||
{
 | 
			
		||||
    enum class binary_operator
 | 
			
		||||
    {
 | 
			
		||||
        sum,
 | 
			
		||||
        subtraction,
 | 
			
		||||
        multiplication,
 | 
			
		||||
        division
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class definition;
 | 
			
		||||
    class bang_statement;
 | 
			
		||||
    class block;
 | 
			
		||||
    class binary_expression;
 | 
			
		||||
    class variable;
 | 
			
		||||
    class integer_literal;
 | 
			
		||||
 | 
			
		||||
    struct ParserVisitor
 | 
			
		||||
    {
 | 
			
		||||
        virtual void visit(definition *) = 0;
 | 
			
		||||
        virtual void visit(bang_statement *) = 0;
 | 
			
		||||
        virtual void visit(block *) = 0;
 | 
			
		||||
        virtual void visit(binary_expression *) = 0;
 | 
			
		||||
        virtual void visit(variable *) = 0;
 | 
			
		||||
        virtual void visit(integer_literal *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AST node.
 | 
			
		||||
     */
 | 
			
		||||
    class node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void accept(ParserVisitor *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class statement : public node
 | 
			
		||||
    {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class expression : public node
 | 
			
		||||
    {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constant definition.
 | 
			
		||||
     */
 | 
			
		||||
    class definition : public node
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_identifier;
 | 
			
		||||
        std::unique_ptr<integer_literal> m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        definition(std::string&& identifier, std::unique_ptr<integer_literal>&& body);
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::string& identifier() noexcept;
 | 
			
		||||
        integer_literal& body();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class bang_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<expression> m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        bang_statement(std::unique_ptr<expression>&& body);
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        expression& body();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Block.
 | 
			
		||||
     */
 | 
			
		||||
    class block : public node
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<statement> m_body;
 | 
			
		||||
        std::vector<std::unique_ptr<definition>> m_definitions;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        block(std::vector<std::unique_ptr<definition>>&& definitions, std::unique_ptr<statement>&& body);
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        statement& body();
 | 
			
		||||
        std::vector<std::unique_ptr<definition>>& definitions() noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class integer_literal : public expression
 | 
			
		||||
    {
 | 
			
		||||
        std::int32_t m_number;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        integer_literal(const std::int32_t value);
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        std::int32_t number() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class variable : public expression
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_name;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        variable(const std::string& name);
 | 
			
		||||
        virtual void accept(ParserVisitor *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(std::unique_ptr<expression>&& lhs,
 | 
			
		||||
                std::unique_ptr<expression>&& rhs, const unsigned char operation);
 | 
			
		||||
 | 
			
		||||
        virtual void accept(ParserVisitor *visitor) override;
 | 
			
		||||
        expression& lhs();
 | 
			
		||||
        expression& rhs();
 | 
			
		||||
        binary_operator operation() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct parser
 | 
			
		||||
    {
 | 
			
		||||
        parser(const std::vector<token>& tokens);
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<block> parse();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        std::unique_ptr<expression> parse_factor();
 | 
			
		||||
        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::vector<std::unique_ptr<definition>> parse_definitions();
 | 
			
		||||
        std::unique_ptr<block> parse_block();
 | 
			
		||||
 | 
			
		||||
        std::vector<token>::const_iterator tokens;
 | 
			
		||||
        std::vector<token>::const_iterator end;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace elna
 | 
			
		||||
            return 3;
 | 
			
		||||
        }
 | 
			
		||||
        size_t tokensCount{ 0 };
 | 
			
		||||
        auto lex_result = lex::lex(sourceText);
 | 
			
		||||
        auto lex_result = source::lex(sourceText);
 | 
			
		||||
        free(sourceText);
 | 
			
		||||
        if (lex_result.has_errors())
 | 
			
		||||
        {
 | 
			
		||||
@@ -51,12 +51,12 @@ namespace elna
 | 
			
		||||
            }
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
        auto ast = parse(lex_result.success().data(), tokensCount);
 | 
			
		||||
        auto ast = source::parser(lex_result.success()).parse();
 | 
			
		||||
        if (ast == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return 2;
 | 
			
		||||
        }
 | 
			
		||||
        auto program = writeNext(ast);
 | 
			
		||||
        auto program = writeNext(ast.get());
 | 
			
		||||
 | 
			
		||||
        // Create code section
 | 
			
		||||
        ELFIO::section* text_sec = writer.sections.add(".text");
 | 
			
		||||
 
 | 
			
		||||
@@ -4,42 +4,32 @@
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
    void TransformVisitor::visit(Node *node)
 | 
			
		||||
    void TransformVisitor::visit(source::definition *definition)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(Definition *definition)
 | 
			
		||||
    void TransformVisitor::visit(source::bang_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(BangStatement *statement)
 | 
			
		||||
    void TransformVisitor::visit(source::block *block)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(Block *block)
 | 
			
		||||
    void TransformVisitor::visit(source::integer_literal *number)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(Expression *expression)
 | 
			
		||||
    void TransformVisitor::visit(source::variable *variable)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(Number *number)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(Variable *variable)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void TransformVisitor::visit(BinaryExpression *binaryExpression)
 | 
			
		||||
    void TransformVisitor::visit(source::binary_expression *binaryExpression)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										195
									
								
								source/lexer.cpp
									
									
									
									
									
								
							
							
						
						
									
										195
									
								
								source/lexer.cpp
									
									
									
									
									
								
							@@ -1,54 +1,42 @@
 | 
			
		||||
#include "elna/lexer.hpp"
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "elna/source/lexer.hpp"
 | 
			
		||||
#include <variant>
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace lex
 | 
			
		||||
namespace source
 | 
			
		||||
{
 | 
			
		||||
    using source_position = elna::source::position;
 | 
			
		||||
    using source_error = elna::source::error;
 | 
			
		||||
    using source_result = elna::source::result<std::vector<Token>>;
 | 
			
		||||
    using source_result = elna::source::result<std::vector<token>>;
 | 
			
		||||
 | 
			
		||||
    source::source(const std::string& buffer)
 | 
			
		||||
        : m_buffer(buffer)
 | 
			
		||||
    std::pair<text_iterator, text_iterator> text_iterators(const std::string &buffer)
 | 
			
		||||
    {
 | 
			
		||||
        return std::make_pair<>(text_iterator(std::cbegin(buffer)),
 | 
			
		||||
                text_iterator(std::cend(buffer), position{0, 0}));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator source::begin() const
 | 
			
		||||
    {
 | 
			
		||||
        return source::const_iterator(std::cbegin(m_buffer));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator source::end() const
 | 
			
		||||
    {
 | 
			
		||||
        source_position end_position{ 0, 0 };
 | 
			
		||||
 | 
			
		||||
        return source::const_iterator(std::cend(m_buffer), end_position);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator::const_iterator(std::string::const_iterator buffer,
 | 
			
		||||
    text_iterator::text_iterator(std::string::const_iterator buffer,
 | 
			
		||||
            const source_position start_position)
 | 
			
		||||
        : m_buffer(buffer), m_position(start_position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const source_position& source::const_iterator::position() const noexcept
 | 
			
		||||
    const source_position& text_iterator::position() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return this->m_position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator::reference source::const_iterator::operator*() const noexcept
 | 
			
		||||
    text_iterator::reference text_iterator::operator*() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return *m_buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator::pointer source::const_iterator::operator->() const noexcept
 | 
			
		||||
    text_iterator::pointer text_iterator::operator->() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_buffer.base();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator& source::const_iterator::operator++()
 | 
			
		||||
    text_iterator& text_iterator::operator++()
 | 
			
		||||
    {
 | 
			
		||||
        if (*this->m_buffer == '\n')
 | 
			
		||||
        {
 | 
			
		||||
@@ -64,129 +52,156 @@ namespace lex
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source::const_iterator& source::const_iterator::operator++(int)
 | 
			
		||||
    text_iterator& text_iterator::operator++(int)
 | 
			
		||||
    {
 | 
			
		||||
        auto tmp = *this;
 | 
			
		||||
        ++(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool source::const_iterator::operator==(const source::const_iterator& that) const noexcept
 | 
			
		||||
    bool text_iterator::operator==(const text_iterator& that) const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return this->m_buffer == that.m_buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool source::const_iterator::operator!=(const source::const_iterator& that) const noexcept
 | 
			
		||||
    bool text_iterator::operator!=(const text_iterator& that) const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return !(*this == that);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::Token(const type of, const char *value, source_position position)
 | 
			
		||||
        : m_type(of), m_position(position)
 | 
			
		||||
    token::value::value()
 | 
			
		||||
        : nil(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        std::size_t value_length = strlen(value);
 | 
			
		||||
        char *buffer = reinterpret_cast<char *>(malloc(value_length + 1));
 | 
			
		||||
 | 
			
		||||
        std::memcpy(buffer, value, value_length);
 | 
			
		||||
        buffer[value_length] = 0;
 | 
			
		||||
 | 
			
		||||
        m_value.identifier = buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::Token(const type of, std::int32_t number, source_position position)
 | 
			
		||||
        : m_type(of), m_position(position)
 | 
			
		||||
    token::value::value(std::int32_t value)
 | 
			
		||||
        : number(value)
 | 
			
		||||
    {
 | 
			
		||||
        m_value.number = number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::Token(const type of, source_position position)
 | 
			
		||||
    token::value::value(const std::string& value)
 | 
			
		||||
        : identifier(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token::value::~value()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token::token(const type of, const std::string& value, const source_position position)
 | 
			
		||||
        : m_type(of), m_value(value), m_position(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token::token(const type of, std::int32_t number, const source_position position)
 | 
			
		||||
        : m_type(of), m_value(number), m_position(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token::token(const type of, source_position position)
 | 
			
		||||
        : m_type(of), m_position(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::Token(const Token& that)
 | 
			
		||||
    token::token(const token& that)
 | 
			
		||||
        : m_type(that.of()), m_position(that.position())
 | 
			
		||||
    {
 | 
			
		||||
        *this = that;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::Token(Token&& that)
 | 
			
		||||
    token::token(token&& that)
 | 
			
		||||
        : m_type(that.of()), m_position(that.position())
 | 
			
		||||
    {
 | 
			
		||||
        *this = std::move(that);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::~Token()
 | 
			
		||||
    token::~token()
 | 
			
		||||
    {
 | 
			
		||||
        if (m_type == type::identifier || m_type == type::term_operator || m_type == type::factor_operator)
 | 
			
		||||
        {
 | 
			
		||||
            std::free(const_cast<char*>(m_value.identifier));
 | 
			
		||||
            m_value.identifier.~basic_string();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token& Token::operator=(const Token& that)
 | 
			
		||||
    token& token::operator=(const token& that)
 | 
			
		||||
    {
 | 
			
		||||
        m_type = that.of();
 | 
			
		||||
        m_position = that.position();
 | 
			
		||||
        if (that.of() == type::identifier || that.of() == type::term_operator || m_type == type::factor_operator)
 | 
			
		||||
        {
 | 
			
		||||
            std::size_t value_length = strlen(that.identifier());
 | 
			
		||||
            char *buffer = reinterpret_cast<char *>(malloc(value_length + 1));
 | 
			
		||||
 | 
			
		||||
            std::memcpy(buffer, that.identifier(), value_length);
 | 
			
		||||
            buffer[value_length] = 0;
 | 
			
		||||
 | 
			
		||||
            m_value.identifier = buffer;
 | 
			
		||||
        }
 | 
			
		||||
        else if (that.of() == type::number)
 | 
			
		||||
        {
 | 
			
		||||
            m_value.number = that.number();
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token& Token::operator=(Token&& that)
 | 
			
		||||
    {
 | 
			
		||||
        m_type = that.of();
 | 
			
		||||
        m_position = that.position();
 | 
			
		||||
        if (that.of() == type::identifier || that.of() == type::term_operator || that.of() == type::factor_operator)
 | 
			
		||||
        if (that.has_identifier())
 | 
			
		||||
        {
 | 
			
		||||
            m_value.identifier = that.identifier();
 | 
			
		||||
            that.m_value.identifier = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        else if (that.of() == type::number)
 | 
			
		||||
        {
 | 
			
		||||
            m_value.number = that.number();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            m_value.nil = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::type Token::of() const noexcept
 | 
			
		||||
    token& token::operator=(token&& that)
 | 
			
		||||
    {
 | 
			
		||||
        m_type = that.of();
 | 
			
		||||
        m_position = that.position();
 | 
			
		||||
        if (that.has_identifier())
 | 
			
		||||
        {
 | 
			
		||||
            m_value.identifier = std::move(that.identifier());
 | 
			
		||||
        }
 | 
			
		||||
        else if (that.of() == type::number)
 | 
			
		||||
        {
 | 
			
		||||
            m_value.number = that.number();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            m_value.nil = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token::type token::of() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char *Token::identifier() const noexcept
 | 
			
		||||
    const std::string& token::identifier() const
 | 
			
		||||
    {
 | 
			
		||||
        if (!has_identifier())
 | 
			
		||||
        {
 | 
			
		||||
            throw std::bad_variant_access();
 | 
			
		||||
        }
 | 
			
		||||
        return m_value.identifier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::int32_t Token::number() const noexcept
 | 
			
		||||
    std::int32_t token::number() const
 | 
			
		||||
    {
 | 
			
		||||
        if (of() != type::number)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::bad_variant_access();
 | 
			
		||||
        }
 | 
			
		||||
        return m_value.number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const source_position& Token::position() const noexcept
 | 
			
		||||
    const source_position& token::position() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    source_result lex(const char *buffer)
 | 
			
		||||
    bool token::has_identifier() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<Token> tokens;
 | 
			
		||||
        source input{ buffer };
 | 
			
		||||
        return of() == type::identifier
 | 
			
		||||
            || of() == type::term_operator
 | 
			
		||||
            || of() == type::factor_operator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        for (auto iterator = input.begin(); iterator != input.end();)
 | 
			
		||||
    source_result lex(const std::string& buffer)
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<token> tokens;
 | 
			
		||||
        auto [iterator, text_end] = text_iterators(buffer);
 | 
			
		||||
 | 
			
		||||
        while (iterator != text_end)
 | 
			
		||||
        {
 | 
			
		||||
            if (*iterator == ' ' || *iterator == '\n')
 | 
			
		||||
            {
 | 
			
		||||
@@ -194,59 +209,59 @@ namespace lex
 | 
			
		||||
            else if (std::isdigit(*iterator))
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(
 | 
			
		||||
                        Token::type::number,
 | 
			
		||||
                        token::type::number,
 | 
			
		||||
                        static_cast<std::int32_t>(*iterator - '0'),
 | 
			
		||||
                        iterator.position()
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == '=')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::equals, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::equals, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == '(')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::left_paren, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::left_paren, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == ')')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::right_paren, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::right_paren, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == ';')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::semicolon, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::semicolon, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == ',')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::comma, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::comma, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == '!')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::bang, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::bang, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == '.')
 | 
			
		||||
            {
 | 
			
		||||
                tokens.emplace_back(Token::type::dot, iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::dot, iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (std::isalpha(*iterator))
 | 
			
		||||
            {
 | 
			
		||||
                std::string word;
 | 
			
		||||
                auto i = iterator;
 | 
			
		||||
                while (i != input.end() && std::isalpha(*i))
 | 
			
		||||
                while (i != text_end && std::isalpha(*i))
 | 
			
		||||
                {
 | 
			
		||||
                    word.push_back(*i);
 | 
			
		||||
                    ++i;
 | 
			
		||||
                }
 | 
			
		||||
                if (word == "const")
 | 
			
		||||
                {
 | 
			
		||||
                    tokens.emplace_back(Token::type::let, iterator.position());
 | 
			
		||||
                    tokens.emplace_back(token::type::let, iterator.position());
 | 
			
		||||
                }
 | 
			
		||||
                else if (word == "var")
 | 
			
		||||
                {
 | 
			
		||||
                    tokens.emplace_back(Token::type::var, iterator.position());
 | 
			
		||||
                    tokens.emplace_back(token::type::var, iterator.position());
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    tokens.emplace_back(Token::type::identifier, word.c_str(), iterator.position());
 | 
			
		||||
                    tokens.emplace_back(token::type::identifier, word.c_str(), iterator.position());
 | 
			
		||||
                }
 | 
			
		||||
                iterator = i;
 | 
			
		||||
                continue;
 | 
			
		||||
@@ -255,13 +270,13 @@ namespace lex
 | 
			
		||||
            {
 | 
			
		||||
                std::string _operator{ *iterator };
 | 
			
		||||
 | 
			
		||||
                tokens.emplace_back(Token::type::term_operator, _operator.c_str(), iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::term_operator, _operator.c_str(), iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iterator == '*' || *iterator == '/')
 | 
			
		||||
            {
 | 
			
		||||
                std::string _operator{ *iterator };
 | 
			
		||||
 | 
			
		||||
                tokens.emplace_back(Token::type::factor_operator, _operator.c_str(), iterator.position());
 | 
			
		||||
                tokens.emplace_back(token::type::factor_operator, _operator.c_str(), iterator.position());
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,254 +1,294 @@
 | 
			
		||||
#include "elna/parser.hpp"
 | 
			
		||||
#include "elna/source/parser.hpp"
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace source
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * AST node.
 | 
			
		||||
     */
 | 
			
		||||
    void Node::accept(ParserVisitor *)
 | 
			
		||||
    void node::accept(ParserVisitor *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Definition::accept(ParserVisitor *visitor)
 | 
			
		||||
    definition::definition(std::string&& identifier, std::unique_ptr<integer_literal>&& body)
 | 
			
		||||
        : m_identifier(std::move(identifier)), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void definition::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Block::accept(ParserVisitor *visitor)
 | 
			
		||||
    std::string& definition::identifier() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_identifier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    integer_literal& definition::body()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    block::block(std::vector<std::unique_ptr<definition>>&& definitions, std::unique_ptr<statement>&& body)
 | 
			
		||||
        : m_definitions(std::move(definitions)), m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void block::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Expression::accept(ParserVisitor *visitor)
 | 
			
		||||
    statement& block::body()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<std::unique_ptr<definition>>& block::definitions() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_definitions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    integer_literal::integer_literal(const std::int32_t value)
 | 
			
		||||
        : m_number(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void integer_literal::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Number::accept(ParserVisitor *visitor)
 | 
			
		||||
    std::int32_t integer_literal::number() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable::variable(const std::string& name)
 | 
			
		||||
        : m_name(name)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void variable::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Variable::accept(ParserVisitor *visitor)
 | 
			
		||||
    const std::string& variable::name() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
        return m_name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BinaryExpression::BinaryExpression(Expression *lhs, Expression *rhs, unsigned char _operator)
 | 
			
		||||
    binary_expression::binary_expression(std::unique_ptr<expression>&& lhs,
 | 
			
		||||
            std::unique_ptr<expression>&& rhs, const unsigned char operation)
 | 
			
		||||
        : m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
 | 
			
		||||
    {
 | 
			
		||||
        this->lhs = lhs;
 | 
			
		||||
        this->rhs = rhs;
 | 
			
		||||
 | 
			
		||||
        switch (_operator)
 | 
			
		||||
        switch (operation)
 | 
			
		||||
        {
 | 
			
		||||
            case '+':
 | 
			
		||||
                this->_operator = BinaryOperator::sum;
 | 
			
		||||
                this->m_operator = binary_operator::sum;
 | 
			
		||||
                break;
 | 
			
		||||
            case '-': 
 | 
			
		||||
                this->_operator = BinaryOperator::subtraction;
 | 
			
		||||
                this->m_operator = binary_operator::subtraction;
 | 
			
		||||
                break;
 | 
			
		||||
            case '*':
 | 
			
		||||
                this->_operator = BinaryOperator::multiplication;
 | 
			
		||||
                this->m_operator = binary_operator::multiplication;
 | 
			
		||||
                break;
 | 
			
		||||
            case '/':
 | 
			
		||||
                this->_operator = BinaryOperator::division;
 | 
			
		||||
                this->m_operator = binary_operator::division;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw std::logic_error("Invalid binary operator");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void BinaryExpression::accept(ParserVisitor *visitor)
 | 
			
		||||
    void binary_expression::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void BangStatement::accept(ParserVisitor *visitor)
 | 
			
		||||
    expression& binary_expression::lhs()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_lhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression& binary_expression::rhs()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    binary_operator binary_expression::operation() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_operator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bang_statement::bang_statement(std::unique_ptr<expression>&& body)
 | 
			
		||||
        : m_body(std::move(body))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void bang_statement::accept(ParserVisitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Block *parse(lex::Token *tokenStream, std::size_t length)
 | 
			
		||||
    expression& bang_statement::body()
 | 
			
		||||
    {
 | 
			
		||||
        return parseBlock(&tokenStream, &length);
 | 
			
		||||
        return *m_body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Expression *parseFactor(lex::Token **tokens, size_t *length)
 | 
			
		||||
    parser::parser(const std::vector<token>& tokens)
 | 
			
		||||
        : tokens(tokens.cbegin()), end(tokens.cend())
 | 
			
		||||
    {
 | 
			
		||||
        if ((*tokens)[0].of() == lex::Token::type::identifier)
 | 
			
		||||
        {
 | 
			
		||||
            auto variable = new Variable();
 | 
			
		||||
            variable->identifier = (*tokens)[0].identifier();
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
            return variable;
 | 
			
		||||
    }
 | 
			
		||||
        else if ((*tokens)[0].of() == lex::Token::Token::type::number)
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<block> parser::parse()
 | 
			
		||||
    {
 | 
			
		||||
            auto number = new Number();
 | 
			
		||||
            number->value = (*tokens)[0].number();
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
            return number;
 | 
			
		||||
        return parse_block();
 | 
			
		||||
    }
 | 
			
		||||
        else if ((*tokens)[0].of() == lex::Token::type::left_paren)
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_factor()
 | 
			
		||||
    {
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
        if (tokens->of() == source::token::type::identifier)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<variable>(tokens->identifier());
 | 
			
		||||
            ++tokens;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (tokens->of() == source::token::token::type::number)
 | 
			
		||||
        {
 | 
			
		||||
            auto result = std::make_unique<integer_literal>(tokens->number());
 | 
			
		||||
            ++tokens;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else if (tokens->of() == source::token::type::left_paren)
 | 
			
		||||
        {
 | 
			
		||||
            ++tokens;
 | 
			
		||||
 | 
			
		||||
            auto expression = parseExpression(tokens, length);
 | 
			
		||||
            auto expression = parse_expression();
 | 
			
		||||
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
            ++tokens;
 | 
			
		||||
 | 
			
		||||
            return expression;
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Expression *parseTerm(lex::Token **tokens, size_t *length)
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_term()
 | 
			
		||||
    {
 | 
			
		||||
        auto lhs = parseFactor(tokens, length);
 | 
			
		||||
        if (lhs == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::factor_operator)
 | 
			
		||||
        auto lhs = parse_factor();
 | 
			
		||||
        if (lhs == nullptr || tokens == end || tokens->of() != source::token::type::factor_operator)
 | 
			
		||||
        {
 | 
			
		||||
            return lhs;
 | 
			
		||||
        }
 | 
			
		||||
        auto _operator = (*tokens)[0].identifier()[0];
 | 
			
		||||
        ++(*tokens);
 | 
			
		||||
        --(*length);
 | 
			
		||||
        auto _operator = tokens->identifier()[0];
 | 
			
		||||
        ++tokens;
 | 
			
		||||
 | 
			
		||||
        auto rhs = parseFactor(tokens, length);
 | 
			
		||||
        auto rhs = parse_factor();
 | 
			
		||||
        if (rhs != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return new BinaryExpression(lhs, rhs, _operator);
 | 
			
		||||
            return std::make_unique<binary_expression>(std::move(lhs),
 | 
			
		||||
                    std::move(rhs), _operator);
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Expression *parseExpression(lex::Token **tokens, size_t *length)
 | 
			
		||||
    std::unique_ptr<expression> parser::parse_expression()
 | 
			
		||||
    {
 | 
			
		||||
        auto term = parseTerm(tokens, length);
 | 
			
		||||
        if (term == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::term_operator)
 | 
			
		||||
        auto term = parse_term();
 | 
			
		||||
        if (term == nullptr || tokens == end || tokens->of() != source::token::type::term_operator)
 | 
			
		||||
        {
 | 
			
		||||
            return term;
 | 
			
		||||
        }
 | 
			
		||||
        auto _operator = (*tokens)[0].identifier()[0];
 | 
			
		||||
        ++(*tokens);
 | 
			
		||||
        --(*length);
 | 
			
		||||
        auto _operator = tokens->identifier()[0];
 | 
			
		||||
        ++tokens;
 | 
			
		||||
 | 
			
		||||
        auto expression = parseExpression(tokens, length);
 | 
			
		||||
        auto rhs = parse_expression();
 | 
			
		||||
 | 
			
		||||
        if (expression != nullptr)
 | 
			
		||||
        if (rhs != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return new BinaryExpression(term, expression, _operator);
 | 
			
		||||
            return std::make_unique<binary_expression>(std::move(term),
 | 
			
		||||
                    std::move(rhs), _operator);
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Definition *parseDefinition(lex::Token **tokens, size_t *length)
 | 
			
		||||
    std::unique_ptr<definition> parser::parse_definition()
 | 
			
		||||
    {
 | 
			
		||||
        auto definition = new Definition();
 | 
			
		||||
        definition->identifier = (*tokens)[0].identifier(); // Copy.
 | 
			
		||||
        std::string definition_identifier = tokens->identifier(); // Copy.
 | 
			
		||||
 | 
			
		||||
        ++(*tokens);
 | 
			
		||||
        ++(*tokens); // Skip the equals sign.
 | 
			
		||||
        *length -= 2;
 | 
			
		||||
        ++tokens;
 | 
			
		||||
        ++tokens; // Skip the equals sign.
 | 
			
		||||
 | 
			
		||||
        if ((*tokens)[0].of() == lex::Token::type::number)
 | 
			
		||||
        if (tokens->of() == source::token::type::number)
 | 
			
		||||
        {
 | 
			
		||||
            auto number = new Number();
 | 
			
		||||
            number->value = (*tokens)[0].number();
 | 
			
		||||
            definition->number = number;
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
            return definition;
 | 
			
		||||
            auto result = std::make_unique<definition>(std::move(definition_identifier),
 | 
			
		||||
                    std::make_unique<integer_literal>(tokens->number()));
 | 
			
		||||
            ++tokens;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Statement *parseStatement(lex::Token **tokens, std::size_t *length)
 | 
			
		||||
    std::unique_ptr<statement> parser::parse_bang_statement()
 | 
			
		||||
    {
 | 
			
		||||
        if ((*tokens)[0].of() == lex::Token::type::bang)
 | 
			
		||||
        if (tokens->of() == source::token::type::bang)
 | 
			
		||||
        {
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
            auto statement = new BangStatement();
 | 
			
		||||
            auto expression = parseExpression(tokens, length);
 | 
			
		||||
            if (expression != nullptr)
 | 
			
		||||
            ++tokens;
 | 
			
		||||
            auto bang_body = parse_expression();
 | 
			
		||||
            if (bang_body != nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                statement->expression = expression;
 | 
			
		||||
                return std::make_unique<bang_statement>(std::move(bang_body));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return nullptr;
 | 
			
		||||
            }
 | 
			
		||||
            return statement;
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Definition **parseDefinitions(lex::Token **tokens, size_t *length, size_t *resultLength)
 | 
			
		||||
    std::vector<std::unique_ptr<definition>> parser::parse_definitions()
 | 
			
		||||
    {
 | 
			
		||||
        ++(*tokens); // Skip const.
 | 
			
		||||
        --(*length);
 | 
			
		||||
        ++tokens; // Skip const.
 | 
			
		||||
 | 
			
		||||
        Definition **definitions;
 | 
			
		||||
        *resultLength = 0;
 | 
			
		||||
        std::vector<std::unique_ptr<definition>> definitions;
 | 
			
		||||
 | 
			
		||||
        while (*length != 0)
 | 
			
		||||
        while (tokens != end)
 | 
			
		||||
        {
 | 
			
		||||
            auto definition = parseDefinition(tokens, length);
 | 
			
		||||
            if (definition == nullptr)
 | 
			
		||||
            auto parsed_definition = parse_definition();
 | 
			
		||||
            if (parsed_definition == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                return nullptr;
 | 
			
		||||
                return definitions;
 | 
			
		||||
            }
 | 
			
		||||
            definitions = reinterpret_cast<Definition **>(
 | 
			
		||||
                    realloc(definitions, (*resultLength + 1) * sizeof(Definition*)));
 | 
			
		||||
            definitions[(*resultLength)++] = definition;
 | 
			
		||||
            definitions.push_back(std::move(parsed_definition));
 | 
			
		||||
 | 
			
		||||
            if ((*tokens)[0].of() == lex::Token::type::semicolon)
 | 
			
		||||
            if (tokens->of() == source::token::type::semicolon)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if ((*tokens)[0].of() == lex::Token::type::comma)
 | 
			
		||||
            if (tokens->of() == source::token::type::comma)
 | 
			
		||||
            {
 | 
			
		||||
                ++(*tokens);
 | 
			
		||||
                --(*length);
 | 
			
		||||
                ++tokens;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return definitions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Block *parseBlock(lex::Token **tokens, std::size_t *length)
 | 
			
		||||
    std::unique_ptr<block> parser::parse_block()
 | 
			
		||||
    {
 | 
			
		||||
        auto block = new Block();
 | 
			
		||||
        if ((*tokens)[0].of() == lex::Token::type::let)
 | 
			
		||||
        std::vector<std::unique_ptr<definition>> definitions;
 | 
			
		||||
        if (tokens->of() == source::token::type::let)
 | 
			
		||||
        {
 | 
			
		||||
            size_t length_ = 0;
 | 
			
		||||
            auto constDefinitions = parseDefinitions(tokens, length, &length_);
 | 
			
		||||
            if (constDefinitions != nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                block->definitionsLength = length_;
 | 
			
		||||
                block->definitions = constDefinitions;
 | 
			
		||||
            definitions = parse_definitions();
 | 
			
		||||
            ++tokens;
 | 
			
		||||
        }
 | 
			
		||||
            else
 | 
			
		||||
        auto parsed_statement = parse_bang_statement();
 | 
			
		||||
        if (parsed_statement == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
            ++(*tokens);
 | 
			
		||||
            --(*length);
 | 
			
		||||
        }
 | 
			
		||||
        auto statement = parseStatement(tokens, length);
 | 
			
		||||
        if (statement != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            block->statement = statement;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return block;
 | 
			
		||||
        return std::make_unique<block>(std::move(definitions), std::move(parsed_statement));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
#include "elna/parser.hpp"
 | 
			
		||||
#include "elna/riscv.hpp"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
@@ -59,31 +58,22 @@ namespace elna
 | 
			
		||||
        return reinterpret_cast<std::byte *>(&this->instruction) + sizeof(this->instruction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Node *)
 | 
			
		||||
    void RiscVVisitor::visit(source::definition *definition)
 | 
			
		||||
    {
 | 
			
		||||
        constants[definition->identifier()] = definition->body().number();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Definition *definition)
 | 
			
		||||
    void RiscVVisitor::visit(source::block *block)
 | 
			
		||||
    {
 | 
			
		||||
        ++constCount;
 | 
			
		||||
        constNames = reinterpret_cast<const char **>(realloc(constNames, sizeof(const char *) * constCount));
 | 
			
		||||
        constValues = reinterpret_cast<std::int32_t *>(realloc(constValues, sizeof(std::int32_t) * constCount));
 | 
			
		||||
 | 
			
		||||
        constNames[constCount - 1] = definition->identifier;
 | 
			
		||||
        constValues[constCount - 1] = definition->number->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Block *block)
 | 
			
		||||
        for (const auto& block_definition : block->definitions())
 | 
			
		||||
        {
 | 
			
		||||
        for (std::size_t i = 0; i < block->definitionsLength; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            block->definitions[i]->accept(this);
 | 
			
		||||
            block_definition->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
        this->instructionsLength += 4;
 | 
			
		||||
        this->instructions = reinterpret_cast<Instruction *>(
 | 
			
		||||
                realloc(this->instructions, this->instructionsLength * sizeof(Instruction)));
 | 
			
		||||
 | 
			
		||||
        block->statement->accept(this);
 | 
			
		||||
        block->body().accept(this);
 | 
			
		||||
 | 
			
		||||
        // Prologue.
 | 
			
		||||
        const uint stackSize = static_cast<std::uint32_t>(variableCounter * 4 + 12);
 | 
			
		||||
@@ -137,44 +127,12 @@ namespace elna
 | 
			
		||||
            .i(XRegister::zero, Funct3::jalr, XRegister::ra, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(BangStatement *statement)
 | 
			
		||||
    void RiscVVisitor::visit(source::bang_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->expression->accept(this);
 | 
			
		||||
        statement->body().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Expression *operand)
 | 
			
		||||
    {
 | 
			
		||||
        if (dynamic_cast<Variable *>(operand) != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return dynamic_cast<Variable *>(operand)->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
        if (dynamic_cast<Number *>(operand) != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return dynamic_cast<Number *>(operand)->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Variable *variable)
 | 
			
		||||
    {
 | 
			
		||||
        std::size_t i = 0;
 | 
			
		||||
        for (; i < constCount; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            if (std::strcmp(variable->identifier, constNames[i]) == 0)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        const auto freeRegister = this->registerInUse ? XRegister::a0 : XRegister::t0;
 | 
			
		||||
 | 
			
		||||
        ++this->instructionsLength;
 | 
			
		||||
        this->instructions = reinterpret_cast<Instruction *>(
 | 
			
		||||
                realloc(this->instructions, this->instructionsLength * sizeof(Instruction)));
 | 
			
		||||
        this->instructions[this->instructionsLength - 1] =
 | 
			
		||||
            Instruction(BaseOpcode::opImm) // movl $x, %eax; where $x is a number.
 | 
			
		||||
                .i(freeRegister, Funct3::addi, XRegister::zero, constValues[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(Number *number)
 | 
			
		||||
    void RiscVVisitor::visit(source::variable *variable)
 | 
			
		||||
    {
 | 
			
		||||
        const auto freeRegister = this->registerInUse ? XRegister::a0 : XRegister::t0;
 | 
			
		||||
 | 
			
		||||
@@ -183,15 +141,27 @@ namespace elna
 | 
			
		||||
                realloc(this->instructions, this->instructionsLength * sizeof(Instruction)));
 | 
			
		||||
        this->instructions[this->instructionsLength - 1] =
 | 
			
		||||
            Instruction(BaseOpcode::opImm) // movl $x, %eax; where $x is a number.
 | 
			
		||||
                .i(freeRegister, Funct3::addi, XRegister::zero, number->value);
 | 
			
		||||
                .i(freeRegister, Funct3::addi, XRegister::zero, constants[variable->name()]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(BinaryExpression *expression)
 | 
			
		||||
    void RiscVVisitor::visit(source::integer_literal *number)
 | 
			
		||||
    {
 | 
			
		||||
        const auto freeRegister = this->registerInUse ? XRegister::a0 : XRegister::t0;
 | 
			
		||||
 | 
			
		||||
        ++this->instructionsLength;
 | 
			
		||||
        this->instructions = reinterpret_cast<Instruction *>(
 | 
			
		||||
                realloc(this->instructions, this->instructionsLength * sizeof(Instruction)));
 | 
			
		||||
        this->instructions[this->instructionsLength - 1] =
 | 
			
		||||
            Instruction(BaseOpcode::opImm) // movl $x, %eax; where $x is a number.
 | 
			
		||||
                .i(freeRegister, Funct3::addi, XRegister::zero, number->number());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RiscVVisitor::visit(source::binary_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        const auto lhs_register = this->registerInUse ? XRegister::a0 : XRegister::t0;
 | 
			
		||||
 | 
			
		||||
        this->registerInUse = true;
 | 
			
		||||
        expression->lhs->accept(this);
 | 
			
		||||
        expression->lhs().accept(this);
 | 
			
		||||
 | 
			
		||||
        ++this->instructionsLength;
 | 
			
		||||
        this->instructions = reinterpret_cast<Instruction *>(
 | 
			
		||||
@@ -202,7 +172,7 @@ namespace elna
 | 
			
		||||
        auto lhs_stack_position = ++this->variableCounter;
 | 
			
		||||
 | 
			
		||||
        this->registerInUse = false;
 | 
			
		||||
        expression->rhs->accept(this);
 | 
			
		||||
        expression->rhs().accept(this);
 | 
			
		||||
 | 
			
		||||
        this->instructionsLength += 2;
 | 
			
		||||
        this->instructions = reinterpret_cast<Instruction *>(
 | 
			
		||||
@@ -213,24 +183,24 @@ namespace elna
 | 
			
		||||
                static_cast<std::int8_t>((lhs_stack_position - 1) * 4));
 | 
			
		||||
 | 
			
		||||
        // Calculate the result and assign it to a variable on the stack.
 | 
			
		||||
        switch (expression->_operator)
 | 
			
		||||
        switch (expression->operation())
 | 
			
		||||
        {
 | 
			
		||||
            case BinaryOperator::sum:
 | 
			
		||||
            case source::binary_operator::sum:
 | 
			
		||||
                this->instructions[instructionsLength - 1] = Instruction(BaseOpcode::op)
 | 
			
		||||
                    .r(lhs_register, Funct3::add, XRegister::a0, XRegister::t0);
 | 
			
		||||
                break;
 | 
			
		||||
            case BinaryOperator::subtraction:
 | 
			
		||||
            case source::binary_operator::subtraction:
 | 
			
		||||
                this->instructions[instructionsLength - 1] = Instruction(BaseOpcode::op)
 | 
			
		||||
                    .r(lhs_register, Funct3::sub, XRegister::a0, XRegister::t0, Funct7::sub);
 | 
			
		||||
                break;
 | 
			
		||||
            case BinaryOperator::multiplication:
 | 
			
		||||
            case source::binary_operator::multiplication:
 | 
			
		||||
                this->instructions[instructionsLength - 1] = Instruction(BaseOpcode::op)
 | 
			
		||||
                    .r(lhs_register, Funct3::mul, XRegister::a0, XRegister::t0, Funct7::muldiv);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Symbol writeNext(Block *ast)
 | 
			
		||||
    Symbol writeNext(source::block *ast)
 | 
			
		||||
    {
 | 
			
		||||
        auto visitor = std::make_unique<RiscVVisitor>();
 | 
			
		||||
        visitor->visit(ast);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user