Fix: Parsing of mov instructions containing a constant, like "MOV 10, reg1"
This commit is contained in:
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ public:
|
||||
|
||||
[[nodiscard]] auto compile() const -> uint8_t override;
|
||||
|
||||
[[nodiscard]] auto getRegister() const -> uint8_t;
|
||||
|
||||
private:
|
||||
uint8_t reg;
|
||||
};
|
||||
|
@ -5,5 +5,5 @@
|
||||
#include "RootNode.h"
|
||||
|
||||
auto RootNode::compile() const -> uint8_t {
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user