aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-06-04 15:33:44 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-06-04 15:33:44 +0200
commitbde4c3fe7885b66c0bb59b8407c74b350fc6b44d (patch)
tree564fa255e12f4d8318a760335909ff0fdc207933
parent6bf48a8fc00d76f712797a8f578445893de62791 (diff)
WIP parser
-rw-r--r--Parser.cpp101
-rw-r--r--Parser.h24
-rw-r--r--circuits/full-adder.txt12
-rw-r--r--main.cpp4
4 files changed, 124 insertions, 17 deletions
diff --git a/Parser.cpp b/Parser.cpp
index d76f11a..5774a0e 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -1,20 +1,105 @@
+#include <cstring>
+#include <sstream>
+#include <cstdarg>
+
#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<char>(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<string> nodes;
+ while ((content = strtok(content, ",")) != NULL) {
+ nodes.push_back(content);
+ content = NULL;
+ }
+
+ handle_line(label, nodes);
+ }
+}
+
+void Parser::handle_line(string label, vector<string> 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 <iostream>
#include <istream>
+#include <exception>
+#include <vector>
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<string> 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;
// }