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