From bfeeac6e4889d1e9a1083b3c7efc59652981b168 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Mon, 1 Aug 2016 08:20:23 +0200 Subject: o Moving the generation logic to Python, embedding a Python interpreter with the help of pybind11. o Adding install configuration to CMake to make it easier to reuse the project later on. o Splitting out the examples into its own project to make it easier to test the whole installation setup and python/template loading. o Trying to reorganize the code a bit, not very much better yet. --- core/kicad.cpp | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 core/kicad.cpp (limited to 'core/kicad.cpp') diff --git a/core/kicad.cpp b/core/kicad.cpp new file mode 100644 index 0000000..1a6ca2f --- /dev/null +++ b/core/kicad.cpp @@ -0,0 +1,194 @@ +#include "trygvis/kicad.h" +#include "trygvis/antlr.h" +#include "trygvis/string_utils.h" +#include +#include +#include +#include +#include + +using namespace std; +using namespace trygvis::antlr; +using namespace trygvis::string_utils; + +namespace trygvis { +namespace kicad { +namespace netlist { + +const node *net::node_for_ref(const std::string &ref) const { + for (auto &node: nodes) { + if (node.ref == ref) { + return &node; + } + } + + return nullptr; +} + +opt netlist::find_component(const string &ref) const { + for (const component &c :components) { + int x = c.ref.compare(ref); + if (x == 0) { + return &c; + } + } + return std::experimental::nullopt; +} + +vector netlist::find_usage_of(const string &ref) const { + vector usage; + + for (auto &net : nets) { + if (net.nodes.size() <= 1) { + continue; + } + + for (auto &node: net.nodes) { + if (node.ref == ref) { + usage.push_back(&net); + } + } + } + + return usage; +} + +static +int parse(const Ref &integer) { + unsigned long long i = strtoull(integer->getText().c_str(), NULL, 10); + + return static_cast(i); +} + +class KicadErrorListener : public BaseErrorListener { +public: + vector messages; + + void syntaxError(IRecognizer *recognizer, Token *offendingSymbol, size_t line, int charPositionInLine, + const string &msg, exception_ptr e) override { + static_cast(recognizer); + static_cast(offendingSymbol); + static_cast(e); + messages.push_back("line " + to_string(line) + ":" + to_string(charPositionInLine) + ": " + msg); + } +}; + +class kicad_main_listener : public KicadNetParserBaseListener { + +public: + vector components; + vector parts; + vector nets; + vector nodes; + + ParseTreeProperty strings; + + virtual void exitNet(KicadNetParser::NetContext *ctx) override { + auto code = parse(ctx->code()->INTEGER()); + auto name = strings.get(ctx->name()->string()); + + if (startsWith(name, "/")) { + name = name.substr(1); + } + +// cerr << "exitNet: " << "code=" << code << ", name=" << name << ", nodes=" << nodes.size() << endl; + +// if (nodes.size() > 1) { +// cerr << "Net#" << code << ": " << name << endl; +// for (auto &node: nodes) { +// cerr << " Node: " << node.ref << "#" << node.pin << endl; +// } +// } + nets.emplace_back(code, name, nodes); + nodes.clear(); + } + + virtual void exitNode(KicadNetParser::NodeContext *ctx) override { + auto ref = strings.get(ctx->ref()->string()); + auto pin = parse(ctx->pinRef()->INTEGER()); + +// cerr << "exitNode: " << "ref=" << ref << ", pin=" << pin << endl; + + nodes.emplace_back(ref, pin); + } + + virtual void exitComponent(KicadNetParser::ComponentContext *ctx) override { + auto ref = strings.get(ctx->ref()->string()); + auto value = strings.get(ctx->value()->string()); + + lib_source ls{strings.get(ctx->libsource()->lib()->string()), + strings.get(ctx->libsource()->part()->string())}; + + components.emplace_back(ref, value, ls); + } + + virtual void exitStringId(KicadNetParser::StringIdContext *ctx) override { + strings.put(ctx, ctx->getText()); + } + + virtual void exitStringInt(KicadNetParser::StringIntContext *ctx) override { + strings.put(ctx, ctx->getText()); + } + + virtual void exitStringText(KicadNetParser::StringTextContext *ctx) override { + auto s = ctx->getText(); + strings.put(ctx, s.substr(1, s.length() - 2)); + } +}; + +netlist kicad_net_loader::load(string path, ostream &err) { + + ANTLRFileStream input(path); + KicadNetLexer lexer(&input); + CommonTokenStream tokens(&lexer); + + tokens.fill(); + + if (debug_) { + for (auto token : tokens.getTokens()) { + err << token->toString() << endl; + } + } + + KicadNetParser parser(&tokens); + parser.removeErrorListeners(); + KicadErrorListener errorListener; + parser.addErrorListener(&errorListener); + + parser.file(); + + if (!errorListener.messages.empty()) { + throw kicad_parse_exception(errorListener.messages); + } + + parser.reset(); + + kicad_main_listener mainListener; + parser.addParseListener(&mainListener); + + auto file = parser.file(); + + if (debug_ && parser.getNumberOfSyntaxErrors() == 0) { + err << file->toStringTree(&parser) << endl; + } + + return netlist { + mainListener.components, + mainListener.parts, + mainListener.nets, + }; +} + +kicad_net_loader::kicad_net_loader() : debug_(false) { +} + +kicad_net_loader::~kicad_net_loader() { +} + +void kicad_net_loader::setDebug(bool debug) { + debug_ = debug; +} + +} // namespace netlist +} // namespace trygvis +} // namespace kicad -- cgit v1.2.3