From 2e2e5d8ed38c5d4d5b7a5eab25d301b4156bb80f Mon Sep 17 00:00:00 2001 From: ChUrl Date: Tue, 21 Mar 2023 15:49:29 +0100 Subject: [PATCH] Fix: Parsing of mov instructions containing a constant, like "MOV 10, reg1" --- src/ast/Node.h | 5 +++++ src/ast/nodes/MovNode.cpp | 15 ++------------- src/ast/nodes/MovNode.h | 11 ++++++----- src/ast/nodes/RegNode.cpp | 4 ++++ src/ast/nodes/RegNode.h | 2 ++ src/ast/nodes/RootNode.cpp | 2 +- src/parser/Parser.cpp | 26 +++++++++++--------------- src/parser/Parser.h | 7 ++++--- 8 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/ast/Node.h b/src/ast/Node.h index 4d9e99c..d723637 100644 --- a/src/ast/Node.h +++ b/src/ast/Node.h @@ -25,6 +25,10 @@ public: void addChild(std::unique_ptr child); + // TODO: For more complex instructions, compile needs to return a vector + // 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> &; @@ -38,6 +42,7 @@ protected: }; protected: + // TODO: Currently the AST degrades to a list, but someday we'll need a real tree std::vector> children; }; diff --git a/src/ast/nodes/MovNode.cpp b/src/ast/nodes/MovNode.cpp index 398f1de..5528a3b 100644 --- a/src/ast/nodes/MovNode.cpp +++ b/src/ast/nodes/MovNode.cpp @@ -4,19 +4,8 @@ #include "MovNode.h" -MovNode::MovNode(std::unique_ptr source, std::unique_ptr 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); } diff --git a/src/ast/nodes/MovNode.h b/src/ast/nodes/MovNode.h index d56b8b3..5a05b06 100644 --- a/src/ast/nodes/MovNode.h +++ b/src/ast/nodes/MovNode.h @@ -6,18 +6,19 @@ #define LOGISIMASSEMBLER_MOVNODE_H #include "../Node.h" +#include "RegNode.h" class MovNode : public Node { public: - MovNode(std::unique_ptr source, std::unique_ptr 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 diff --git a/src/ast/nodes/RegNode.cpp b/src/ast/nodes/RegNode.cpp index fc88e33..2ffd3cf 100644 --- a/src/ast/nodes/RegNode.cpp +++ b/src/ast/nodes/RegNode.cpp @@ -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; } diff --git a/src/ast/nodes/RegNode.h b/src/ast/nodes/RegNode.h index 0833d03..fc9501f 100644 --- a/src/ast/nodes/RegNode.h +++ b/src/ast/nodes/RegNode.h @@ -15,6 +15,8 @@ public: [[nodiscard]] auto compile() const -> uint8_t override; + [[nodiscard]] auto getRegister() const -> uint8_t; + private: uint8_t reg; }; diff --git a/src/ast/nodes/RootNode.cpp b/src/ast/nodes/RootNode.cpp index 82fa134..eefd8c1 100644 --- a/src/ast/nodes/RootNode.cpp +++ b/src/ast/nodes/RootNode.cpp @@ -5,5 +5,5 @@ #include "RootNode.h" auto RootNode::compile() const -> uint8_t { - return 0; + return -1; } diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index 7cbabe9..35cea01 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -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 @@ -17,8 +15,6 @@ Parser::Parser(const std::vector &tokens) : tokens(tokens), position(tokens.begin()) {} auto Parser::parse() -> std::unique_ptr { - auto root = std::make_unique(); - 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 { // TODO: Put these functions in a map, mapped to the mnemonic name string if (static_cast(peek()) == "MOV") { - root->addChild(std::move(mov())); + mov(); continue; } if (static_cast(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 { +void Parser::mov() { if (peek().getType() != Token::MNEMONIC || static_cast(peek()) != "MOV") { throw "Parser Error: Expected 'MOV'!"; } get(); // Eat 'MOV' - std::unique_ptr sourceNode; + uint8_t source = 0; // Load from reg0 if (peek().getType() == Token::NUMBER) { - sourceNode = std::make_unique(static_cast(peek())); + ast->addChild(std::move(std::make_unique(static_cast(peek())))); // Load constant to reg0 } else if (peek().getType() == Token::IDENTIFIER) { - sourceNode = std::make_unique(static_cast(peek())); + source = static_cast(peek()); } else { throw "Parser Error: Expected Constant or Register!"; } @@ -70,13 +66,13 @@ auto Parser::mov() -> std::unique_ptr { if (peek().getType() != Token::IDENTIFIER || static_cast(identifier) != "reg") { throw "Parser Error: Expected Register!"; } - std::unique_ptr targetNode = std::make_unique(static_cast(reg)); + auto target = static_cast(reg); get(); // Eat target - return std::move(std::make_unique(std::move(sourceNode), std::move(targetNode))); + ast->addChild(std::move(std::make_unique(source, target))); } -auto Parser::alu() -> std::unique_ptr { +void Parser::alu() { std::map aluMap = {{"AND", AluNode::AND}, {"OR", AluNode::OR}, {"NAND", AluNode::NAND}, @@ -91,5 +87,5 @@ auto Parser::alu() -> std::unique_ptr { throw "Parser Error: Invalid ALU operation!"; } - return std::move(std::make_unique(aluMap[static_cast(get())])); // Eat alu + ast->addChild(std::move(std::make_unique(aluMap[static_cast(get())]))); // Eat alu } diff --git a/src/parser/Parser.h b/src/parser/Parser.h index d9c68ca..1fd4bad 100644 --- a/src/parser/Parser.h +++ b/src/parser/Parser.h @@ -9,6 +9,7 @@ #include #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; + void mov(); - auto alu() -> std::unique_ptr; + void alu(); private: const std::vector &tokens; - std::vector::const_iterator position; + std::unique_ptr ast = std::make_unique(); }; #endif //LOGISIMASSEMBLER_PARSER_H