1

Fix: Parsing of mov instructions containing a constant, like "MOV 10, reg1"

This commit is contained in:
2023-03-21 15:49:29 +01:00
parent e92e7d2183
commit 2e2e5d8ed3
8 changed files with 35 additions and 37 deletions

View File

@ -25,6 +25,10 @@ public:
void addChild(std::unique_ptr<Node> child);
// TODO: For more complex instructions, compile needs to return a vector<uint8_t>
// TODO: In this case, the Observer may not traverse all nodes...
// The Observer is the wrong choice for compilation.
// I can just call compile on the root, and the root compiles its children.
[[nodiscard]] virtual auto compile() const -> uint8_t = 0;
[[nodiscard]] auto getChildren() const -> const std::vector<std::unique_ptr<Node>> &;
@ -38,6 +42,7 @@ protected:
};
protected:
// TODO: Currently the AST degrades to a list, but someday we'll need a real tree
std::vector<std::unique_ptr<Node>> children;
};

View File

@ -4,19 +4,8 @@
#include "MovNode.h"
MovNode::MovNode(std::unique_ptr<Node> source, std::unique_ptr<Node> target) {
children.push_back(std::move(source));
children.push_back(std::move(target));
}
auto MovNode::source() const -> Node & {
return *children[0];
}
auto MovNode::target() const -> Node & {
return *children[1];
}
MovNode::MovNode(uint8_t source, uint8_t target) : source(source), target(target) {}
auto MovNode::compile() const -> uint8_t {
return (COPY & 0b11) << 6 | (source().compile() & 0b111) << 3 | (target().compile() & 0b111);
return (COPY & 0b11) << 6 | (source & 0b111) << 3 | (target & 0b111);
}

View File

@ -6,18 +6,19 @@
#define LOGISIMASSEMBLER_MOVNODE_H
#include "../Node.h"
#include "RegNode.h"
class MovNode : public Node {
public:
MovNode(std::unique_ptr<Node> source, std::unique_ptr<Node> target);
MovNode(uint8_t source, uint8_t target);
~MovNode() override = default;
auto source() const -> Node &;
auto target() const -> Node &;
[[nodiscard]] auto compile() const -> uint8_t override;
private:
uint8_t source;
uint8_t target;
};
#endif //LOGISIMASSEMBLER_MOVNODE_H

View File

@ -11,5 +11,9 @@ auto RegNode::compile() const -> uint8_t {
throw "Compile Error: Invalid Register!";
}
return -1;
}
auto RegNode::getRegister() const -> uint8_t {
return reg;
}

View File

@ -15,6 +15,8 @@ public:
[[nodiscard]] auto compile() const -> uint8_t override;
[[nodiscard]] auto getRegister() const -> uint8_t;
private:
uint8_t reg;
};

View File

@ -5,5 +5,5 @@
#include "RootNode.h"
auto RootNode::compile() const -> uint8_t {
return 0;
return -1;
}

View File

@ -3,10 +3,8 @@
//
#include "Parser.h"
#include "../ast/nodes/RootNode.h"
#include "../ast/nodes/MovNode.h"
#include "../ast/nodes/ConstNode.h"
#include "../ast/nodes/RegNode.h"
#include "../ast/nodes/AluNode.h"
#include <map>
@ -17,8 +15,6 @@
Parser::Parser(const std::vector<Token> &tokens) : tokens(tokens), position(tokens.begin()) {}
auto Parser::parse() -> std::unique_ptr<Node> {
auto root = std::make_unique<RootNode>();
while (peek().getType() != Token::END) {
if (peek().getType() != Token::MNEMONIC) {
throw "Parser Error: Expected Mnemonic!";
@ -26,17 +22,17 @@ auto Parser::parse() -> std::unique_ptr<Node> {
// TODO: Put these functions in a map, mapped to the mnemonic name string
if (static_cast<std::string_view>(peek()) == "MOV") {
root->addChild(std::move(mov()));
mov();
continue;
}
if (static_cast<std::string_view>(peek()) == "ADD") {
root->addChild(std::move(alu()));
alu();
continue;
}
}
return std::move(root);
return std::move(ast);
}
// ! Private Functions
@ -49,17 +45,17 @@ auto Parser::get() -> const Token & {
return *(position++);
}
auto Parser::mov() -> std::unique_ptr<Node> {
void Parser::mov() {
if (peek().getType() != Token::MNEMONIC || static_cast<std::string_view>(peek()) != "MOV") {
throw "Parser Error: Expected 'MOV'!";
}
get(); // Eat 'MOV'
std::unique_ptr<Node> sourceNode;
uint8_t source = 0; // Load from reg0
if (peek().getType() == Token::NUMBER) {
sourceNode = std::make_unique<ConstNode>(static_cast<uint8_t>(peek()));
ast->addChild(std::move(std::make_unique<ConstNode>(static_cast<uint8_t>(peek())))); // Load constant to reg0
} else if (peek().getType() == Token::IDENTIFIER) {
sourceNode = std::make_unique<RegNode>(static_cast<uint8_t>(peek()));
source = static_cast<uint8_t>(peek());
} else {
throw "Parser Error: Expected Constant or Register!";
}
@ -70,13 +66,13 @@ auto Parser::mov() -> std::unique_ptr<Node> {
if (peek().getType() != Token::IDENTIFIER || static_cast<std::string_view>(identifier) != "reg") {
throw "Parser Error: Expected Register!";
}
std::unique_ptr<Node> targetNode = std::make_unique<RegNode>(static_cast<uint8_t>(reg));
auto target = static_cast<uint8_t>(reg);
get(); // Eat target
return std::move(std::make_unique<MovNode>(std::move(sourceNode), std::move(targetNode)));
ast->addChild(std::move(std::make_unique<MovNode>(source, target)));
}
auto Parser::alu() -> std::unique_ptr<Node> {
void Parser::alu() {
std::map<std::string, AluNode::AluOperation> aluMap = {{"AND", AluNode::AND},
{"OR", AluNode::OR},
{"NAND", AluNode::NAND},
@ -91,5 +87,5 @@ auto Parser::alu() -> std::unique_ptr<Node> {
throw "Parser Error: Invalid ALU operation!";
}
return std::move(std::make_unique<AluNode>(aluMap[static_cast<std::string>(get())])); // Eat alu
ast->addChild(std::move(std::make_unique<AluNode>(aluMap[static_cast<std::string>(get())]))); // Eat alu
}

View File

@ -9,6 +9,7 @@
#include <vector>
#include "../lexer/Token.h"
#include "../ast/Node.h"
#include "../ast/nodes/RootNode.h"
class Parser {
public:
@ -23,14 +24,14 @@ private:
auto get() -> const Token &;
auto mov() -> std::unique_ptr<Node>;
void mov();
auto alu() -> std::unique_ptr<Node>;
void alu();
private:
const std::vector<Token> &tokens;
std::vector<Token>::const_iterator position;
std::unique_ptr<Node> ast = std::make_unique<RootNode>();
};
#endif //LOGISIMASSEMBLER_PARSER_H