From f384fdc3a9e4acccac2e4d322676e34115a168f7 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 12:13:52 +0200 Subject: WIP meer nadenk --- main.cpp | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'main.cpp') diff --git a/main.cpp b/main.cpp index 05ec033..01b78b2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,17 +1,39 @@ -#include -// #include "Observer.h" -#include "Net.h" -#include "Gate.h" +#include +#include +#include + +#include "Parser.h" +#include "Circuit.h" + +using std::cout; +using std::endl; +using std::fstream; +using std::exception; int main(int argc, char** argv) { - // Observer ob(); - Net n; - Gate *g = new GateAnd; - g->addInput(&n); - n.setLevel(HIGH); - int level = 22; - level = n.getLevel(); - printf("hello world! %d\n", level); - return 0; + Parser main_parser; + Circuit circuit; + + main_parser.setCircuit(circuit); + + fstream file{"circuits/full-adder.txt", file.out}; + + try { + main_parser << file; + } catch (exception e) { + cout << "Parser error: " << e.what() << endl; + return EXIT_FAILURE; + } + + try { + circuit.run(); + } catch (exception e) { + cout << "Circuit error: " << e.what() << endl; + return EXIT_FAILURE; + } + + cout << "Circuit output: " << circuit.getOutput() << endl; + + return EXIT_SUCCESS; } -- cgit v1.2.3 From 6ceea7d142619020e6b18aad97e21572cb9dd314 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 14:00:40 +0200 Subject: fix magic incantation for istream reader --- Parser.cpp | 20 ++++++++++++++++++++ Parser.h | 18 ++++++++++++++++++ docs/Parser.h | 16 ---------------- main.cpp | 40 +++++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 35 deletions(-) create mode 100644 Parser.cpp create mode 100644 Parser.h delete mode 100644 docs/Parser.h (limited to 'main.cpp') diff --git a/Parser.cpp b/Parser.cpp new file mode 100644 index 0000000..d76f11a --- /dev/null +++ b/Parser.cpp @@ -0,0 +1,20 @@ +#include "Parser.h" + +void Parser::parse(string input) const { + std::cout << input << std::endl; +} + +istream & Parser::parse(const Parser & parser, istream & s) const { + string temp(std::istreambuf_iterator(s), {}); + parse(temp); + return s; +} + +istream & operator >> (istream & s, const Parser & parser) { + return parser.parse(parser, s); +} + +istream & operator << (const Parser & parser, istream & s) { + return parser.parse(parser, s); +} + diff --git a/Parser.h b/Parser.h new file mode 100644 index 0000000..58d062f --- /dev/null +++ b/Parser.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +using std::istream; +using std::string; + +class Parser { +public: + void parse(string input) const; + +private: + istream & parse(const Parser & parser, istream & s) const; + friend istream & operator << (const Parser & parser, istream & s); + friend istream & operator >> (istream & s, const Parser & parser); +}; + diff --git a/docs/Parser.h b/docs/Parser.h deleted file mode 100644 index a7c90e9..0000000 --- a/docs/Parser.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include - -using std::ostream; - -class Parser { - - friend void operator >> (Parser& p, std::istream& filestream) { - // cout assigned to another object mycout - std::cout << "the file contains:\n" << filestream << std::endl; - mycout << "Value of dx and dy are \n"; - mycout << d.dx << " " << d.dy; - } -} diff --git a/main.cpp b/main.cpp index 01b78b2..cca0636 100644 --- a/main.cpp +++ b/main.cpp @@ -1,38 +1,40 @@ +#include #include #include #include #include "Parser.h" -#include "Circuit.h" +// #include "Circuit.h" using std::cout; using std::endl; -using std::fstream; using std::exception; +using std::ifstream; +using std::istream; int main(int argc, char** argv) { - Parser main_parser; - Circuit circuit; + Parser main_parser; + // Circuit circuit; - main_parser.setCircuit(circuit); + // main_parser.setCircuit(circuit); - fstream file{"circuits/full-adder.txt", file.out}; + ifstream file("circuits/full-adder.txt"); - try { - main_parser << file; - } catch (exception e) { - cout << "Parser error: " << e.what() << endl; - return EXIT_FAILURE; - } + try { + file >> main_parser; + } catch (exception e) { + cout << "Parser error: " << e.what() << endl; + return EXIT_FAILURE; + } - try { - circuit.run(); - } catch (exception e) { - cout << "Circuit error: " << e.what() << endl; - return EXIT_FAILURE; - } + // try { + // circuit.run(); + // } catch (exception e) { + // cout << "Circuit error: " << e.what() << endl; + // return EXIT_FAILURE; + // } - cout << "Circuit output: " << circuit.getOutput() << endl; + // cout << "Circuit output: " << circuit.getOutput() << endl; return EXIT_SUCCESS; } -- cgit v1.2.3 From bde4c3fe7885b66c0bb59b8407c74b350fc6b44d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 15:33:44 +0200 Subject: WIP parser --- Parser.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++---- Parser.h | 24 +++++++++++- circuits/full-adder.txt | 12 +++--- main.cpp | 4 +- 4 files changed, 124 insertions(+), 17 deletions(-) (limited to 'main.cpp') diff --git a/Parser.cpp b/Parser.cpp index d76f11a..5774a0e 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -1,20 +1,105 @@ +#include +#include +#include + #include "Parser.h" -void Parser::parse(string input) const { - std::cout << input << std::endl; +using std::getline; + +ParserException::ParserException(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + size_t sz = vsnprintf(NULL, 0, fmt, args) + 1; + if (error != NULL) free(error); + error = (char *) malloc(sz); + vsnprintf(error, sz, fmt, args); + va_end(args); } -istream & Parser::parse(const Parser & parser, istream & s) const { - string temp(std::istreambuf_iterator(s), {}); - parse(temp); - return s; +ParserException::~ParserException() { + if (error != NULL) + free(error); +} + +const char * ParserException::what() { + return error; +} + +size_t Parser::filter(char * input) { + size_t + len = strlen(input), + offset = 0, + i = 0; + + while (i < len) { + if(input[i] == '#') { + offset += len - i; + break; + } + + size_t skip = strspn(input + i, " \t\n"); + if (skip > 0) { + offset += skip; + i += skip; + continue; + } + + input[i - offset] = input[i]; + i++; + } + + input[len - offset] = '\0'; + return len - offset; +} + +void Parser::parse(istream & input) const { + unsigned linenum = 0; + string line_str; + while (getline(input, line_str)) { + linenum++; + char* line = line_str.data(); + size_t len = Parser::filter(line); + + if (len == 0) continue; // ignore empty lines + + char* label = strtok(line, ":"); + if (label == NULL) throw ParserException("syntax error on line %u", linenum); + + char* content = strtok(NULL, ";"); + if (content == NULL) throw ParserException("syntax error on line %u", linenum); + + vector nodes; + while ((content = strtok(content, ",")) != NULL) { + nodes.push_back(content); + content = NULL; + } + + handle_line(label, nodes); + } +} + +void Parser::handle_line(string label, vector nodes) const { + if (nodes.size() == 1) { + printf("node or net "); + } else { + printf("net "); + } + + printf("[%s]\n", label.c_str()); } istream & operator >> (istream & s, const Parser & parser) { - return parser.parse(parser, s); + parser.parse(s); + return s; } istream & operator << (const Parser & parser, istream & s) { - return parser.parse(parser, s); + parser.parse(s); + return s; +} + +void Parser::parse(string input) const { + std::istringstream s(input); + parse(s); } diff --git a/Parser.h b/Parser.h index 58d062f..2124eab 100644 --- a/Parser.h +++ b/Parser.h @@ -2,16 +2,38 @@ #include #include +#include +#include using std::istream; using std::string; +using std::vector; + +class ParserException : public std::exception { +public: + ParserException(const char * fmt, ...); + ~ParserException(); + const char * what(); + +private: + char * error = NULL; +}; class Parser { public: void parse(string input) const; + void parse(istream & input) const; + + /** + * \brief preprocess (filter) line of input + * + * normalize whitespace and remove comments + */ + static size_t filter(char * input); + + void handle_line(string label, vector nodes) const; private: - istream & parse(const Parser & parser, istream & s) const; friend istream & operator << (const Parser & parser, istream & s); friend istream & operator >> (istream & s, const Parser & parser); }; diff --git a/circuits/full-adder.txt b/circuits/full-adder.txt index d0c3854..9b85bc7 100644 --- a/circuits/full-adder.txt +++ b/circuits/full-adder.txt @@ -17,14 +17,14 @@ NODE9: AND; NODE10: AND; NODE11: OR; -Cin: NODE3,NODE7,NODE10; -A: NODE1,NODE2; -B: NODE1,NODE2; -NODE1: NODE3,NODE5; -NODE2: NODE4,NODE6; +Cin: NODE3, NODE7, NODE10; +A: NODE1, NODE2; +B: NODE1, NODE2; +NODE1: NODE3, NODE5; +NODE2: NODE4, NODE6; NODE3: NODE6; NODE4: NODE5; -NODE5: NODE8,NODE9; +NODE5: NODE8, NODE9; NODE6: Cout; NODE7: NODE9; NODE8: NODE10; diff --git a/main.cpp b/main.cpp index cca0636..2a15a39 100644 --- a/main.cpp +++ b/main.cpp @@ -22,14 +22,14 @@ int main(int argc, char** argv) { try { file >> main_parser; - } catch (exception e) { + } catch (ParserException & e) { cout << "Parser error: " << e.what() << endl; return EXIT_FAILURE; } // try { // circuit.run(); - // } catch (exception e) { + // } catch (exception& e) { // cout << "Circuit error: " << e.what() << endl; // return EXIT_FAILURE; // } -- cgit v1.2.3 From 9e1b22e12bb0915081c94e6266b9725251500dcd Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 7 Jun 2024 15:22:00 +0200 Subject: WIP begin writing factory --- .gitignore | 2 ++ Circuit.cpp | 19 +++++++++++++++++++ Circuit.h | 19 +++++++++++++++++++ GateAnd.cpp | 39 +++++++++++++++++++++++++++++++++++++++ GateAnd.h | 15 +++++++++++++++ Node.cpp | 36 ++++++------------------------------ Node.h | 30 +++++++++++++----------------- NodeFactory.cpp | 24 ++++++++++++++++++++++++ NodeFactory.h | 21 +++++++++++++++++++++ Parser.cpp | 24 ++++++++++-------------- Parser.h | 23 ++++++++++++++--------- docs/class-diag.puml | 2 +- main.cpp | 11 ++++------- makefile | 4 ++-- 14 files changed, 189 insertions(+), 80 deletions(-) create mode 100644 Circuit.cpp create mode 100644 Circuit.h create mode 100644 GateAnd.cpp create mode 100644 GateAnd.h create mode 100644 NodeFactory.cpp create mode 100644 NodeFactory.h (limited to 'main.cpp') diff --git a/.gitignore b/.gitignore index 4ce588c..1707139 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ main *.o .vscode +.cache +compile_commands.json diff --git a/Circuit.cpp b/Circuit.cpp new file mode 100644 index 0000000..f6229f1 --- /dev/null +++ b/Circuit.cpp @@ -0,0 +1,19 @@ +#include "Circuit.h" +#include "NodeFactory.h" + +void Circuit::create(string label, vector nodes) { + if (nodes.size() == 1 && NodeFactory::has_type(nodes[0])) + return new_node(label, nodes[0]); + + for (string node : nodes) + new_net(label, node); +} + +void Circuit::new_node(string label, string type) { + printf("[%s] (%s)\n", label.c_str(), type.c_str()); +} + +void Circuit::new_net(string label, string connection) { + printf("[%s] -> %s\n", label.c_str(), connection.c_str()); +} + diff --git a/Circuit.h b/Circuit.h new file mode 100644 index 0000000..249301d --- /dev/null +++ b/Circuit.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +using std::string; +using std::vector; + +class Circuit { +public: + Circuit() = default; + virtual ~Circuit() = default; + +public: + void create(string label, vector nodes); + void new_node(string label, string type); + void new_net(string label, string node); +}; + diff --git a/GateAnd.cpp b/GateAnd.cpp new file mode 100644 index 0000000..e48b21c --- /dev/null +++ b/GateAnd.cpp @@ -0,0 +1,39 @@ +#include + +#include "GateAnd.h" + +using std::cout; +using std::endl; + +GateAnd GateAnd::instance(GateAnd::type); + +GateAnd::GateAnd(const char * type) : Node(type) { + cout << __PRETTY_FUNCTION__ << endl; +} + +// Concrete Nodes: +void GateAnd::compare() { + SignalLevel new_out = HIGH; +// TODO fix segfault somewhere below +// for (int i = 0; i < this->inputs.size(); i++){ +// switch (this->inputs[i]->getLevel()){ +// case LOW: +// new_out = LOW; +// break; +// case HIGH: +// continue; +// break; +// case UNDEFINED: +// default: +// new_out = UNDEFINED; +// exit; +// break; +// } +// } + +// if (this->output->getLevel() == new_out){ +// /* do nothing */ +// } else { +// this->output->setLevel(new_out); +// } +} diff --git a/GateAnd.h b/GateAnd.h new file mode 100644 index 0000000..40e3927 --- /dev/null +++ b/GateAnd.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Node.h" + +class GateAnd : public Node { +public: + GateAnd(const char * type); + virtual ~GateAnd() = default; + virtual void compare(); + +private: + constexpr static const char * type = "and"; + static GateAnd instance; +}; + diff --git a/Node.cpp b/Node.cpp index 05ac5d6..5deaf03 100644 --- a/Node.cpp +++ b/Node.cpp @@ -2,11 +2,14 @@ #include -Node::Node(){} -Node::~Node(){} -void Node::addInput(Net* net){ +Node::Node(const char * type) { + +} + +void Node::addInput(Net* net) { net->attach(this); } + void Node::setOutput(Net* net){ this->output = net; } @@ -16,30 +19,3 @@ void Node::update(){ this->compare(); } -/*/ Concrete Nodes: /*/ - -void GateAnd::compare(){ - SignalLevel new_out = HIGH; -// TODO fix segfault somewhere below -// for (int i = 0; i < this->inputs.size(); i++){ -// switch (this->inputs[i]->getLevel()){ -// case LOW: -// new_out = LOW; -// break; -// case HIGH: -// continue; -// break; -// case UNDEFINED: -// default: -// new_out = UNDEFINED; -// exit; -// break; -// } -// } - -// if (this->output->getLevel() == new_out){ -// /* do nothing */ -// } else { -// this->output->setLevel(new_out); -// } -} diff --git a/Node.h b/Node.h index 8db9fe9..7f2d03d 100644 --- a/Node.h +++ b/Node.h @@ -6,26 +6,22 @@ #include "Observer.h" #include "Net.h" -class Node: Observer { -protected: - std::string label; - std::string type; - - std::vector inputs; - Net* output; +using std::string; +using std::vector; +class Node : Observer { public: - Node(/* args */); - virtual ~Node(); + Node(const char * type); + virtual ~Node() = default; void update(); - virtual void addInput(Net*); - virtual void setOutput(Net*); + virtual void addInput(Net *); + virtual void setOutput(Net *); virtual void compare() = 0; -}; -class GateAnd: public Node { -public: - GateAnd(){}; - ~GateAnd(){}; - void compare(); +protected: + string label; + + vector inputs; + Net * output; }; + diff --git a/NodeFactory.cpp b/NodeFactory.cpp new file mode 100644 index 0000000..da4cc72 --- /dev/null +++ b/NodeFactory.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "NodeFactory.h" + +bool NodeFactory::has_type(const char * type) { + return has_type(string(type)); +} + +bool NodeFactory::has_type(string type) { + std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); + + // TODO: query the map instead + if (type == "and") return true; + if (type == "not") return true; + if (type == "or") return true; + if (type == "input_high") return true; + if (type == "input_low") return true; + if (type == "probe") return true; + + return false; +} + diff --git a/NodeFactory.h b/NodeFactory.h new file mode 100644 index 0000000..b5757d4 --- /dev/null +++ b/NodeFactory.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "Node.h" + +using std::string; + +class NodeFactory { +public: + NodeFactory() = default; + virtual ~NodeFactory() = default; + +public: + static bool has_type(const char * type); + static bool has_type(string type); + +private: + friend Node; +}; + diff --git a/Parser.cpp b/Parser.cpp index 5774a0e..84c3217 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -52,7 +52,11 @@ size_t Parser::filter(char * input) { return len - offset; } -void Parser::parse(istream & input) const { +void Parser::set_circuit(Circuit & circuit) { + this->circuit = &circuit; +} + +void Parser::parse(istream & input) { unsigned linenum = 0; string line_str; while (getline(input, line_str)) { @@ -74,31 +78,23 @@ void Parser::parse(istream & input) const { content = NULL; } - handle_line(label, nodes); + if (circuit == nullptr) throw ParserException("circuit is not initialized!"); + circuit->create(label, nodes); } } -void Parser::handle_line(string label, vector nodes) const { - if (nodes.size() == 1) { - printf("node or net "); - } else { - printf("net "); - } - - printf("[%s]\n", label.c_str()); -} -istream & operator >> (istream & s, const Parser & parser) { +istream & operator >> (istream & s, Parser & parser) { parser.parse(s); return s; } -istream & operator << (const Parser & parser, istream & s) { +istream & operator << (Parser & parser, istream & s) { parser.parse(s); return s; } -void Parser::parse(string input) const { +void Parser::parse(string input) { std::istringstream s(input); parse(s); } diff --git a/Parser.h b/Parser.h index 2124eab..3a86eec 100644 --- a/Parser.h +++ b/Parser.h @@ -3,17 +3,17 @@ #include #include #include -#include + +#include "Circuit.h" using std::istream; using std::string; -using std::vector; class ParserException : public std::exception { public: ParserException(const char * fmt, ...); - ~ParserException(); - const char * what(); + virtual ~ParserException(); + virtual const char * what(); private: char * error = NULL; @@ -21,8 +21,11 @@ private: class Parser { public: - void parse(string input) const; - void parse(istream & input) const; + Parser() = default; + virtual ~Parser() = default; + + void parse(string input); + void parse(istream & input); /** * \brief preprocess (filter) line of input @@ -31,10 +34,12 @@ public: */ static size_t filter(char * input); - void handle_line(string label, vector nodes) const; + void set_circuit(Circuit & circuit); private: - friend istream & operator << (const Parser & parser, istream & s); - friend istream & operator >> (istream & s, const Parser & parser); + friend istream & operator << (Parser & parser, istream & s); + friend istream & operator >> (istream & s, Parser & parser); + + Circuit * circuit; }; diff --git a/docs/class-diag.puml b/docs/class-diag.puml index ea245cd..5efda1b 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -5,7 +5,7 @@ abstract class Node { /' (also ConcreteObserver) '/ + addInput(Net*) - inputs: Net*[] - output: Net* - - type: static constexpr const string + - type: static const char * string - minInputs: constexpr unsigned int - maxInputs: constexpr int } diff --git a/main.cpp b/main.cpp index 2a15a39..01ddeb7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,27 +1,24 @@ -#include #include -#include #include #include "Parser.h" -// #include "Circuit.h" +#include "Circuit.h" using std::cout; using std::endl; -using std::exception; using std::ifstream; -using std::istream; int main(int argc, char** argv) { Parser main_parser; - // Circuit circuit; + Circuit circuit; - // main_parser.setCircuit(circuit); + main_parser.set_circuit(circuit); ifstream file("circuits/full-adder.txt"); try { file >> main_parser; + // main_parser << file; } catch (ParserException & e) { cout << "Parser error: " << e.what() << endl; return EXIT_FAILURE; diff --git a/makefile b/makefile index 31bee7c..509e1e8 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ CC = g++ LD = g++ RM = rm -f -CFLAGS = -g -std=c++17 +CFLAGS = -g -std=c++20 LFLAGS = TARGET = main SRCS := $(wildcard *.cpp) @@ -18,5 +18,5 @@ $(TARGET): $(OBJS) clean: $(RM) $(TARGET) $(OBJS) -compile_commands: clean +compile_commands.json: compiledb make -Bn -- cgit v1.2.3