diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp new file mode 100644 index 0000000..7cbabe9 --- /dev/null +++ b/src/parser/Parser.cpp @@ -0,0 +1,95 @@ +// +// Created by christoph on 20.03.23. +// + +#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 + +// ! Helper Functions + +// ! Public Functions + +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!"; + } + + // TODO: Put these functions in a map, mapped to the mnemonic name string + if (static_cast(peek()) == "MOV") { + root->addChild(std::move(mov())); + continue; + } + + if (static_cast(peek()) == "ADD") { + root->addChild(std::move(alu())); + continue; + } + } + + return std::move(root); +} + +// ! Private Functions + +auto Parser::peek() const -> const Token & { + return *position; +} + +auto Parser::get() -> const Token & { + return *(position++); +} + +auto Parser::mov() -> std::unique_ptr { + if (peek().getType() != Token::MNEMONIC || static_cast(peek()) != "MOV") { + throw "Parser Error: Expected 'MOV'!"; + } + get(); // Eat 'MOV' + + std::unique_ptr sourceNode; + if (peek().getType() == Token::NUMBER) { + sourceNode = std::make_unique(static_cast(peek())); + } else if (peek().getType() == Token::IDENTIFIER) { + sourceNode = std::make_unique(static_cast(peek())); + } 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") { + throw "Parser Error: Expected Register!"; + } + std::unique_ptr targetNode = std::make_unique(static_cast(reg)); + get(); // Eat target + + return std::move(std::make_unique(std::move(sourceNode), std::move(targetNode))); +} + +auto Parser::alu() -> std::unique_ptr { + std::map aluMap = {{"AND", AluNode::AND}, + {"OR", AluNode::OR}, + {"NAND", AluNode::NAND}, + {"NOR", AluNode::NOR}, + {"ADD", AluNode::ADD}, + {"SUB", AluNode::SUB}}; + + if (peek().getType() != Token::MNEMONIC) { + throw "Parser Error: Expected Mnemonic!"; + } + if (!aluMap.contains(static_cast(peek()))) { + throw "Parser Error: Invalid ALU operation!"; + } + + return std::move(std::make_unique(aluMap[static_cast(get())])); // Eat alu +} diff --git a/src/parser/Parser.h b/src/parser/Parser.h new file mode 100644 index 0000000..d9c68ca --- /dev/null +++ b/src/parser/Parser.h @@ -0,0 +1,36 @@ +// +// Created by christoph on 20.03.23. +// + +#ifndef LOGISIMASSEMBLER_PARSER_H +#define LOGISIMASSEMBLER_PARSER_H + +#include +#include +#include "../lexer/Token.h" +#include "../ast/Node.h" + +class Parser { +public: + Parser(const std::vector &tokens); + + Parser(std::vector &&tokens) = delete; + + auto parse() -> std::unique_ptr; + +private: + [[nodiscard]] auto peek() const -> const Token &; + + auto get() -> const Token &; + + auto mov() -> std::unique_ptr; + + auto alu() -> std::unique_ptr; + +private: + const std::vector &tokens; + + std::vector::const_iterator position; +}; + +#endif //LOGISIMASSEMBLER_PARSER_H