Implement multiplication
This commit is contained in:
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
char *readSource(const char *source);
|
||||
int compile(const char *inFile, const char *outputFilename);
|
||||
int compile(const std::filesystem::path& in_file, const std::filesystem::path& out_file);
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
#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.
|
||||
@ -14,10 +17,10 @@ namespace elna
|
||||
class const_iterator
|
||||
{
|
||||
std::string::const_iterator m_buffer;
|
||||
Position m_position;
|
||||
elna::source::position m_position;
|
||||
|
||||
const_iterator(std::string::const_iterator buffer,
|
||||
const Position position = Position());
|
||||
const elna::source::position start_position = elna::source::position());
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
@ -26,7 +29,7 @@ namespace elna
|
||||
using pointer = const value_type *;
|
||||
using reference = const value_type&;
|
||||
|
||||
const Position& position() const noexcept;
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
reference operator*() const noexcept;
|
||||
pointer operator->() const noexcept;
|
||||
@ -54,20 +57,21 @@ namespace elna
|
||||
/**
|
||||
* Token type.
|
||||
*/
|
||||
enum Type : std::uint16_t
|
||||
enum class type : std::uint16_t
|
||||
{
|
||||
TOKEN_NUMBER = 0,
|
||||
TOKEN_OPERATOR = 1,
|
||||
TOKEN_LET = 2,
|
||||
TOKEN_IDENTIFIER = 3,
|
||||
TOKEN_EQUALS = 4,
|
||||
TOKEN_VAR = 5,
|
||||
TOKEN_SEMICOLON = 6,
|
||||
TOKEN_LEFT_PAREN = 7,
|
||||
TOKEN_RIGHT_PAREN = 8,
|
||||
TOKEN_BANG = 9,
|
||||
TOKEN_DOT = 10,
|
||||
TOKEN_COMMA = 11,
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -79,9 +83,9 @@ namespace elna
|
||||
const char *identifier;
|
||||
};
|
||||
|
||||
Token(Type of, Position position);
|
||||
Token(Type of, std::int32_t value, Position position);
|
||||
Token(Type of, const char *value, Position position);
|
||||
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();
|
||||
@ -89,21 +93,23 @@ namespace elna
|
||||
Token& operator=(const Token& that);
|
||||
Token& operator=(Token&& that);
|
||||
|
||||
Type of() const noexcept;
|
||||
type of() const noexcept;
|
||||
const char *identifier() const noexcept;
|
||||
std::int32_t number() const noexcept;
|
||||
const Position& position() const noexcept;
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
type m_type;
|
||||
Value m_value;
|
||||
Position m_position;
|
||||
elna::source::position m_position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split the source into tokens.
|
||||
*
|
||||
* \param buffer Source text.
|
||||
* \return Tokens or error.
|
||||
*/
|
||||
Token *lex(const char *buffer, CompileError *compile_error, std::size_t *length);
|
||||
elna::source::result<std::vector<Token>> lex(const char *buffer);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ namespace elna
|
||||
enum class BinaryOperator
|
||||
{
|
||||
sum,
|
||||
subtraction
|
||||
subtraction,
|
||||
multiplication,
|
||||
division
|
||||
};
|
||||
|
||||
class Node;
|
||||
@ -112,12 +114,12 @@ namespace elna
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
Expression *parseFactor(Token **tokens, std::size_t *length);
|
||||
Expression *parseTerm(Token **tokens, std::size_t *length);
|
||||
Expression *parseExpression(Token **tokens, std::size_t *length);
|
||||
Definition *parseDefinition(Token **tokens, std::size_t *length);
|
||||
Statement *parseStatement(Token **tokens, std::size_t *length);
|
||||
Definition **parseDefinitions(Token **tokens, std::size_t *length, std::size_t *resultLength);
|
||||
Block *parseBlock(Token **tokens, std::size_t *length);
|
||||
Block *parse(Token *tokenStream, std::size_t length);
|
||||
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,50 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/outcome.hpp>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <forward_list>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
/**
|
||||
* Position in the source text.
|
||||
*/
|
||||
struct Position
|
||||
namespace source
|
||||
{
|
||||
/// Line.
|
||||
std::size_t line = 1;
|
||||
|
||||
/// Column.
|
||||
std::size_t column = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A compilation error consists of an error message and position.
|
||||
*/
|
||||
struct CompileError
|
||||
{
|
||||
private:
|
||||
char const *message;
|
||||
Position position;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param message Error text.
|
||||
* @param position Error position in the source text.
|
||||
* Position in the source text.
|
||||
*/
|
||||
CompileError(char const *message, const Position position) noexcept;
|
||||
struct position
|
||||
{
|
||||
/// Line.
|
||||
std::size_t line = 1;
|
||||
|
||||
/// Error text.
|
||||
const char *what() const noexcept;
|
||||
/// Column.
|
||||
std::size_t column = 1;
|
||||
};
|
||||
|
||||
/// Error line in the source text.
|
||||
std::size_t line() const noexcept;
|
||||
/**
|
||||
* A compilation error consists of an error message and position.
|
||||
*/
|
||||
struct error
|
||||
{
|
||||
private:
|
||||
char const *message;
|
||||
source::position position;
|
||||
|
||||
/// Error column in the source text.
|
||||
std::size_t column() const noexcept;
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* \param message Error text.
|
||||
* \param position Error position in the source text.
|
||||
*/
|
||||
error(char const *message, const source::position position) noexcept;
|
||||
|
||||
template<typename T>
|
||||
using result = boost::outcome_v2::result<T, CompileError>;
|
||||
/// Error text.
|
||||
const char *what() const noexcept;
|
||||
|
||||
/// Error line in the source text.
|
||||
std::size_t line() const noexcept;
|
||||
|
||||
/// Error column in the source text.
|
||||
std::size_t column() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct result
|
||||
{
|
||||
using E = std::forward_list<source::error>;
|
||||
|
||||
template<typename... Args>
|
||||
explicit result(Args&&... arguments)
|
||||
: payload(std::forward<Args>(arguments)...)
|
||||
{
|
||||
}
|
||||
|
||||
explicit result(const char *message, const source::position position)
|
||||
: payload(E{ source::error(message, position) })
|
||||
{
|
||||
}
|
||||
|
||||
bool has_errors() const noexcept
|
||||
{
|
||||
return std::holds_alternative<E>(payload);
|
||||
}
|
||||
|
||||
bool is_success() const noexcept
|
||||
{
|
||||
return std::holds_alternative<T>(payload);
|
||||
}
|
||||
|
||||
T& success()
|
||||
{
|
||||
return std::get<T>(payload);
|
||||
}
|
||||
|
||||
E& errors()
|
||||
{
|
||||
return std::get<E>(payload);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<T, E> payload;
|
||||
};
|
||||
}
|
||||
|
||||
enum class Target
|
||||
{
|
||||
@ -64,8 +106,7 @@ namespace elna
|
||||
{
|
||||
Symbol(const char *name);
|
||||
const char *name;
|
||||
unsigned char *text;
|
||||
std::size_t length;
|
||||
std::vector<std::byte> text;
|
||||
Reference symbols[3];
|
||||
};
|
||||
}
|
||||
|
@ -87,6 +87,14 @@ namespace elna
|
||||
lbu = 0b100,
|
||||
lhu = 0b101,
|
||||
jalr = 0b000,
|
||||
mul = 000,
|
||||
mulh = 001,
|
||||
mulhsu = 010,
|
||||
mulhu = 011,
|
||||
div = 100,
|
||||
divu = 101,
|
||||
rem = 110,
|
||||
remu = 111
|
||||
};
|
||||
|
||||
enum class Funct12 : std::uint8_t
|
||||
@ -98,7 +106,8 @@ namespace elna
|
||||
enum class Funct7 : std::uint8_t
|
||||
{
|
||||
none = 0,
|
||||
sub = 0b0100000
|
||||
sub = 0b0100000,
|
||||
muldiv = 0b0000001
|
||||
};
|
||||
|
||||
enum class BaseOpcode : std::uint8_t
|
||||
@ -124,7 +133,9 @@ namespace elna
|
||||
Instruction& s(std::uint32_t imm1, Funct3 funct3, XRegister rs1, XRegister rs2);
|
||||
Instruction& r(XRegister rd, Funct3 funct3, XRegister rs1, XRegister rs2, Funct7 funct7 = Funct7::none);
|
||||
Instruction& u(XRegister rd, std::uint32_t imm);
|
||||
std::uint8_t *encode();
|
||||
|
||||
const std::byte *cbegin();
|
||||
const std::byte *cend();
|
||||
|
||||
private:
|
||||
std::uint32_t instruction{ 0 };
|
||||
|
Reference in New Issue
Block a user