diff --git a/src/ast/nodes/JumpNode.cpp b/src/ast/nodes/JumpNode.cpp new file mode 100644 index 0000000..c466b9f --- /dev/null +++ b/src/ast/nodes/JumpNode.cpp @@ -0,0 +1,11 @@ +// +// Created by christoph on 21.03.23. +// + +#include "JumpNode.h" + +JumpNode::JumpNode(JumpNode::JumpOperation operation) : operation(operation) {} + +uint8_t JumpNode::compile() const { + return (CONDITION & 0b11) << 6 | (operation & 0b111); +} diff --git a/src/ast/nodes/JumpNode.h b/src/ast/nodes/JumpNode.h new file mode 100644 index 0000000..6107fec --- /dev/null +++ b/src/ast/nodes/JumpNode.h @@ -0,0 +1,34 @@ +// +// Created by christoph on 21.03.23. +// + +#ifndef LOGISIMASSEMBLER_JUMPNODE_H +#define LOGISIMASSEMBLER_JUMPNODE_H + +#include "../Node.h" + +class JumpNode : public Node { +public: + enum JumpOperation : uint8_t { + NEVER, + EQUAL_ZERO, + LESS_ZERO, + LESS_EQUAL_ZERO, + ALWAYS, + NOT_ZERO, + GREATER_ZERO, + GREATER_EQUAL_ZERO + }; + +public: + JumpNode(JumpOperation operation); + + ~JumpNode() override = default; + + [[nodiscard]] auto compile() const -> uint8_t override; + +private: + JumpOperation operation; +}; + +#endif //LOGISIMASSEMBLER_JUMPNODE_H diff --git a/src/lexer/Lexer.cpp b/src/lexer/Lexer.cpp index 78d1d98..ef344bc 100644 --- a/src/lexer/Lexer.cpp +++ b/src/lexer/Lexer.cpp @@ -45,9 +45,10 @@ auto is_alphabetical(const char character) -> bool { } auto is_mnemonic(const Token &token) -> bool { - // TODO: Add other mnemonics + // TODO: Move this to a separate header const std::vector mnemonics = {"MOV", - "ADD"}; + "AND", "OR", "NAND", "NOR", "ADD", "SUB", + "JEQ", "JLE", "JLEQ", "JNEQ", "JGR", "JGEQ"}; return std::find(mnemonics.begin(), mnemonics.end(), static_cast(token)) != mnemonics.end(); diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index 35cea01..c0fb759 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -6,13 +6,13 @@ #include "../ast/nodes/MovNode.h" #include "../ast/nodes/ConstNode.h" #include "../ast/nodes/AluNode.h" -#include +#include "../ast/nodes/JumpNode.h" // ! Helper Functions // ! Public Functions -Parser::Parser(const std::vector &tokens) : tokens(tokens), position(tokens.begin()) {} +Parser::Parser(const std::vector &tokens) : position(tokens.begin()) {} auto Parser::parse() -> std::unique_ptr { while (peek().getType() != Token::END) { @@ -20,16 +20,7 @@ auto Parser::parse() -> std::unique_ptr { throw "Parser Error: Expected Mnemonic!"; } - // TODO: Put these functions in a map, mapped to the mnemonic name string - if (static_cast(peek()) == "MOV") { - mov(); - continue; - } - - if (static_cast(peek()) == "ADD") { - alu(); - continue; - } + eaters[static_cast(peek())](*this); } return std::move(ast); @@ -54,19 +45,17 @@ void Parser::mov() { uint8_t source = 0; // Load from reg0 if (peek().getType() == Token::NUMBER) { ast->addChild(std::move(std::make_unique(static_cast(peek())))); // Load constant to reg0 - } else if (peek().getType() == Token::IDENTIFIER) { - source = static_cast(peek()); + } else if (peek().getType() == Token::IDENTIFIER && static_cast(peek().subtoken(0, 3)) == "reg") { + source = static_cast(peek().subtoken(3, 1)); } else { throw "Parser Error: Expected Constant or Register!"; } get(); // Eat source - const Token identifier = peek().subtoken(0, 3); - const Token reg = peek().subtoken(3, 1); // Get reg number - if (peek().getType() != Token::IDENTIFIER || static_cast(identifier) != "reg") { + if (peek().getType() != Token::IDENTIFIER || static_cast(peek().subtoken(0, 3)) != "reg") { throw "Parser Error: Expected Register!"; } - auto target = static_cast(reg); + auto target = static_cast(peek().subtoken(3, 1)); get(); // Eat target ast->addChild(std::move(std::make_unique(source, target))); @@ -89,3 +78,21 @@ void Parser::alu() { ast->addChild(std::move(std::make_unique(aluMap[static_cast(get())]))); // Eat alu } + +void Parser::jmp() { + std::map jmpMap = {{"JEQ", JumpNode::EQUAL_ZERO}, + {"JLE", JumpNode::LESS_ZERO}, + {"JLEQ", JumpNode::LESS_EQUAL_ZERO}, + {"JNEQ", JumpNode::NOT_ZERO}, + {"JGR", JumpNode::GREATER_ZERO}, + {"JGEQ", JumpNode::GREATER_EQUAL_ZERO}}; + + if (peek().getType() != Token::MNEMONIC) { + throw "Parser Error: Expected Mnemonic!"; + } + if (!jmpMap.contains(static_cast(peek()))) { + throw "Parser Error: Invalid JMP operation!"; + } + + ast->addChild(std::move(std::make_unique(jmpMap[static_cast(get())]))); // Eat jmp +} diff --git a/src/parser/Parser.h b/src/parser/Parser.h index 1fd4bad..a5bdb87 100644 --- a/src/parser/Parser.h +++ b/src/parser/Parser.h @@ -7,6 +7,8 @@ #include #include +#include +#include #include "../lexer/Token.h" #include "../ast/Node.h" #include "../ast/nodes/RootNode.h" @@ -28,10 +30,25 @@ private: void alu(); + void jmp(); + private: - const std::vector &tokens; std::vector::const_iterator position; std::unique_ptr ast = std::make_unique(); + + std::map> eaters = {{"MOV", &Parser::mov}, + {"AND", &Parser::alu}, + {"OR", &Parser::alu}, + {"NAND", &Parser::alu}, + {"NOR", &Parser::alu}, + {"ADD", &Parser::alu}, + {"SUB", &Parser::alu}, + {"JEQ", &Parser::jmp}, + {"JLE", &Parser::jmp}, + {"JLEQ", &Parser::jmp}, + {"JNEQ", &Parser::jmp}, + {"JGR", &Parser::jmp}, + {"JGEQ", &Parser::jmp}}; }; #endif //LOGISIMASSEMBLER_PARSER_H