From f4450494d828e92da2d2338a92162d5503e21c77 Mon Sep 17 00:00:00 2001 From: Borna Rajkovic Date: Thu, 31 Mar 2022 23:20:41 +0200 Subject: [PATCH] added domain model --- SchemeEditor.pro | 34 +- SchemeEditor.pro.user | 2 +- comdel/domain/addressspace.cpp | 19 ++ comdel/domain/addressspace.h | 26 ++ comdel/domain/attribute.cpp | 56 ++++ comdel/domain/attribute.h | 65 ++++ comdel/domain/bus.cpp | 26 ++ comdel/domain/bus.h | 40 +++ comdel/domain/comdelgenerator.cpp | 445 +++++++++++++++++++++++++++ comdel/domain/comdelgenerator.h | 41 +++ comdel/domain/component.cpp | 62 ++++ comdel/domain/component.h | 63 ++++ comdel/domain/connection.cpp | 39 +++ comdel/domain/connection.h | 36 +++ comdel/domain/display.cpp | 10 + comdel/domain/display.h | 15 + comdel/domain/functionsignature.cpp | 5 + comdel/domain/functionsignature.h | 20 ++ comdel/domain/library.cpp | 78 +++++ comdel/domain/library.h | 58 ++++ comdel/domain/pin.cpp | 38 +++ comdel/domain/pin.h | 59 ++++ comdel/domain/rule.cpp | 60 ++++ comdel/domain/rule.h | 70 +++++ comdel/domain/value.cpp | 82 +++++ comdel/domain/value.h | 58 ++++ comdel/parser/astnode.h | 157 +++++++--- comdel/parser/comdelparser.cpp | 267 +++++++++++++--- comdel/parser/comdelparser.h | 19 +- comdel/parser/parserutil.cpp | 41 +++ comdel/parser/parserutil.h | 4 + comdel/parser/tokenstype.cpp | 2 +- domain/schema/connectioninstance.cpp | 6 - domain/schema/connectioninstance.h | 22 -- domain/schema/instance.cpp | 6 - domain/schema/instance.h | 23 -- domain/schema/instanceattribute.cpp | 5 - domain/schema/instanceattribute.h | 14 - domain/schema/schema.cpp | 6 - domain/schema/schema.h | 19 -- domain/schema/wireinstance.cpp | 6 - domain/schema/wireinstance.h | 17 - main.cpp | 16 +- 43 files changed, 1903 insertions(+), 234 deletions(-) create mode 100644 comdel/domain/addressspace.cpp create mode 100644 comdel/domain/addressspace.h create mode 100644 comdel/domain/attribute.cpp create mode 100644 comdel/domain/attribute.h create mode 100644 comdel/domain/bus.cpp create mode 100644 comdel/domain/bus.h create mode 100644 comdel/domain/comdelgenerator.cpp create mode 100644 comdel/domain/comdelgenerator.h create mode 100644 comdel/domain/component.cpp create mode 100644 comdel/domain/component.h create mode 100644 comdel/domain/connection.cpp create mode 100644 comdel/domain/connection.h create mode 100644 comdel/domain/display.cpp create mode 100644 comdel/domain/display.h create mode 100644 comdel/domain/functionsignature.cpp create mode 100644 comdel/domain/functionsignature.h create mode 100644 comdel/domain/library.cpp create mode 100644 comdel/domain/library.h create mode 100644 comdel/domain/pin.cpp create mode 100644 comdel/domain/pin.h create mode 100644 comdel/domain/rule.cpp create mode 100644 comdel/domain/rule.h create mode 100644 comdel/domain/value.cpp create mode 100644 comdel/domain/value.h delete mode 100644 domain/schema/connectioninstance.cpp delete mode 100644 domain/schema/connectioninstance.h delete mode 100644 domain/schema/instance.cpp delete mode 100644 domain/schema/instance.h delete mode 100644 domain/schema/instanceattribute.cpp delete mode 100644 domain/schema/instanceattribute.h delete mode 100644 domain/schema/schema.cpp delete mode 100644 domain/schema/schema.h delete mode 100644 domain/schema/wireinstance.cpp delete mode 100644 domain/schema/wireinstance.h diff --git a/SchemeEditor.pro b/SchemeEditor.pro index 7c03bc8..a44ec17 100644 --- a/SchemeEditor.pro +++ b/SchemeEditor.pro @@ -9,6 +9,18 @@ CONFIG += c++17 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + comdel/domain/addressspace.cpp \ + comdel/domain/attribute.cpp \ + comdel/domain/bus.cpp \ + comdel/domain/comdelgenerator.cpp \ + comdel/domain/component.cpp \ + comdel/domain/connection.cpp \ + comdel/domain/display.cpp \ + comdel/domain/functionsignature.cpp \ + comdel/domain/library.cpp \ + comdel/domain/pin.cpp \ + comdel/domain/rule.cpp \ + comdel/domain/value.cpp \ comdel/parser/assert.cpp \ comdel/parser/astnode.cpp \ comdel/parser/comdellexer.cpp \ @@ -18,15 +30,22 @@ SOURCES += \ comdel/parser/sourceerror.cpp \ comdel/parser/token.cpp \ comdel/parser/tokenstype.cpp \ - domain/schema/connectioninstance.cpp \ - domain/schema/instance.cpp \ - domain/schema/instanceattribute.cpp \ - domain/schema/schema.cpp \ - domain/schema/wireinstance.cpp \ main.cpp \ mainwindow.cpp HEADERS += \ + comdel/domain/addressspace.h \ + comdel/domain/attribute.h \ + comdel/domain/bus.h \ + comdel/domain/comdelgenerator.h \ + comdel/domain/component.h \ + comdel/domain/connection.h \ + comdel/domain/display.h \ + comdel/domain/functionsignature.h \ + comdel/domain/library.h \ + comdel/domain/pin.h \ + comdel/domain/rule.h \ + comdel/domain/value.h \ comdel/parser/assert.h \ comdel/parser/astnode.h \ comdel/parser/comdellexer.h \ @@ -39,11 +58,6 @@ HEADERS += \ comdel/parser/sourceerror.h \ comdel/parser/token.h \ comdel/parser/tokenstype.h \ - domain/schema/connectioninstance.h \ - domain/schema/instance.h \ - domain/schema/instanceattribute.h \ - domain/schema/schema.h \ - domain/schema/wireinstance.h \ mainwindow.h FORMS += \ diff --git a/SchemeEditor.pro.user b/SchemeEditor.pro.user index 0681b03..0b6feb6 100644 --- a/SchemeEditor.pro.user +++ b/SchemeEditor.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/comdel/domain/addressspace.cpp b/comdel/domain/addressspace.cpp new file mode 100644 index 0000000..c46e91f --- /dev/null +++ b/comdel/domain/addressspace.cpp @@ -0,0 +1,19 @@ +#include "addressspace.h" + +namespace domain { + +AddressSpace::AddressSpace(std::string name, long long start, long long end): + name(name), start(start), end(end) +{} + +std::string AddressSpace::getName() { + return name; +} +long long AddressSpace::getStart() { + return start; +} +long long AddressSpace::getEnd() { + return end; +} + +} // namespace domain diff --git a/comdel/domain/addressspace.h b/comdel/domain/addressspace.h new file mode 100644 index 0000000..2dc3323 --- /dev/null +++ b/comdel/domain/addressspace.h @@ -0,0 +1,26 @@ +#ifndef DOMAIN_ADDRESSSPACE_H +#define DOMAIN_ADDRESSSPACE_H + +#include + + + +namespace domain { + +class AddressSpace +{ + std::string name; + long long start; + long long end; + +public: + AddressSpace(std::string name, long long start, long long end); + + std::string getName(); + long long getStart(); + long long getEnd(); +}; + +} // namespace domain + +#endif // DOMAIN_ADDRESSSPACE_H diff --git a/comdel/domain/attribute.cpp b/comdel/domain/attribute.cpp new file mode 100644 index 0000000..e57a930 --- /dev/null +++ b/comdel/domain/attribute.cpp @@ -0,0 +1,56 @@ +#include "attribute.h" + +namespace domain { + +Enumeration::Enumeration(std::string name, Value value) + : name(name), value(value) +{} + +std::string Enumeration::getName() { + return name; +} +Value Enumeration::getValue() { + return value; +} + + +Popup::Popup(std::string title, std::string text, PopupType type, std::vector rules, std::vector enumeration) + : title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), enumeration(enumeration) +{} + +std::string Popup::getTitle() { + return title; +} +std::string Popup::getText() { + return text; +} +Popup::PopupType Popup::getType() { + return type; +} +std::vector Popup::getRules() { + return rules; +} + +bool Popup::isEnumerated() { + return enumerated; +} +std::vector &Popup::getEnumeration() { + return enumeration; +} + + +Attribute::Attribute(std::string name, Value defaultValue, std::optional popup) + : name(name), defaultValue(defaultValue), popup(popup) +{} + +std::string Attribute::getName() { + return name; +} +Value Attribute::getDefault() { + return defaultValue; +} +std::optional Attribute::getPopup() { + return popup; +} + +} // namespace domain diff --git a/comdel/domain/attribute.h b/comdel/domain/attribute.h new file mode 100644 index 0000000..43e2960 --- /dev/null +++ b/comdel/domain/attribute.h @@ -0,0 +1,65 @@ +#ifndef DOMAIN_ATTRIBUTE_H +#define DOMAIN_ATTRIBUTE_H + +#include "rule.h" +#include "value.h" + +#include + +namespace domain { + +class Enumeration { + std::string name; + Value value; +public: + Enumeration(std::string name, Value value); + + std::string getName(); + Value getValue(); +}; + +class Popup { +public: + enum PopupType { + AUTOMATIC, + ON_DEMAND + }; + +private: + std::string title; + std::string text; + PopupType type; + + bool enumerated; + std::vector enumeration; + std::vector rules; + +public: + Popup(std::string title, std::string text, PopupType type, std::vector rules, std::vector enumeration); + + std::string getTitle(); + std::string getText(); + PopupType getType(); + std::vector getRules(); + + bool isEnumerated(); + std::vector &getEnumeration(); + +}; + +class Attribute +{ + std::string name; + Value defaultValue; + std::optional popup; +public: + Attribute(std::string name, Value defaultValue, std::optional popup = std::nullopt); + + std::string getName(); + Value getDefault(); + std::optional getPopup(); +}; + +} // namespace domain + +#endif // DOMAIN_ATTRIBUTE_H diff --git a/comdel/domain/bus.cpp b/comdel/domain/bus.cpp new file mode 100644 index 0000000..58fd5e2 --- /dev/null +++ b/comdel/domain/bus.cpp @@ -0,0 +1,26 @@ +#include "bus.h" + +namespace domain { + +Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::optional display) + : name(name), tooltip(tooltip), type(type), count(count), display(display) +{} + +std::string Bus::getName() { + return name; +} +std::string Bus::getTooltip() { + return tooltip; +} +Bus::BusType Bus::getType() { + return type; +} +std::pair Bus::getCount() { + return count; +} +std::optional Bus::getDisplay() { + return display; +} + + +} // namespace domain diff --git a/comdel/domain/bus.h b/comdel/domain/bus.h new file mode 100644 index 0000000..d66cc88 --- /dev/null +++ b/comdel/domain/bus.h @@ -0,0 +1,40 @@ +#ifndef DOMAIN_BUS_H +#define DOMAIN_BUS_H + +#include "display.h" + +#include +#include + + +namespace domain { + +class Bus +{ +public: + enum BusType { + AUTOMATIC, + REGULAR + }; +private: + std::string name; + std::string tooltip; + BusType type; + + std::pair count; + std::optional display; + +public: + Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::optional display = std::nullopt); + + std::string getName(); + std::string getTooltip(); + BusType getType(); + std::pair getCount(); + std::optional getDisplay(); + +}; + +} // namespace domain + +#endif // DOMAIN_BUS_H diff --git a/comdel/domain/comdelgenerator.cpp b/comdel/domain/comdelgenerator.cpp new file mode 100644 index 0000000..30b6407 --- /dev/null +++ b/comdel/domain/comdelgenerator.cpp @@ -0,0 +1,445 @@ +#include "comdelgenerator.h" + +#include + +namespace domain { + +Component::ComponentType toType(ComponentNode::ComponentType type) { + if(type == ComponentNode::MEMORY) { + return Component::MEMORY; + } else if(type == ComponentNode::PROCESSOR) { + return Component::PROCESSOR; + } + return Component::OTHER; +} + +Action::ActionType toType(ActionNode::ActionType type) { + if(type == ActionNode::ERROR) { + return Action::ERROR; + } + return Action::WARNING; +} + +Value::ValueType toType(ValueNode::ValueType type) { + switch (type) { + case ValueNode::BOOL: + return Value::BOOL; + case ValueNode::WIRE: + return Value::WIRE_REFERENCE; + case ValueNode::STRING: + return Value::STRING; + case ValueNode::INT: + return Value::INT; + default: + return Value::UNDEFINED; + } +} + + +Value toType(ValueNode node) { + if(node.getType() == ValueNode::BOOL) { + return Value::fromBool(node.asBool()); + } else if(node.getType() == ValueNode::INT) { + return Value::fromInt(node.asInt()); + } else if(node.getType() == ValueNode::STRING) { + return Value::fromString(node.asString()); + } + return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); +} + + +Bus::BusType toType(BusNode::BusType type) { + if(type == BusNode::AUTOMATIC) { + return Bus::AUTOMATIC; + } + return Bus::REGULAR; +} + + +Pin::PinType toType(PinNode::PinType type) { + if(type == PinNode::IN) { + return Pin::IN; + } else if(type == PinNode::OUT) { + return Pin::OUT; + } + return Pin::IN_OUT; +} + +PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type) +{ + if(type == PinConnectionNode::AUTOMATICALLY) { + return PinConnection::AUTOMATICALLY; + } + return PinConnection::CHECK_ONLY; +} + + +Popup::PopupType toType(PopupNode::PopupType type) +{ + if(type == PopupNode::AUTOMATIC) { + return Popup::AUTOMATIC; + } + return Popup::ON_DEMAND; +} + +ComdelGenerator::ComdelGenerator(std::vector signatures) + : signatures(signatures) +{} + +std::optional ComdelGenerator::loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream) +{ + // library fields + if(!node.name) { + errors.push_back(SourceError{node.span, "missing @name"}); + return nullopt; + } + std::string name = node.name->asString(); + + if(!node.componentDirectory) { + errors.push_back(SourceError{node.span, "missing @componentDirectory"}); + return nullopt; + } + std::string componentDirectory = node.componentDirectory->asString(); + + std::string header = node.header ? node.header->asString() : ""; + + std::string libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; + + std::vector addressSpaces; + for(auto& as: node.addressSpaces) { + addressSpaces.push_back(*loadAddressSpace(as)); + } + + std::vector components; + for(auto& comp: node.components) { + std::optional component; + component = loadComponent(comp); + if(component) { + components.push_back(*component); + } + } + + std::vector connections; + for(uint i=0; i messages; + for(uint i=0; i buses; + for(uint i=0; i ComdelGenerator::loadBus(BusNode node) +{ + std::string name = node.name.value; + + auto count = std::make_pair(1, 1); + if(node.count) { + count = std::make_pair(node.count->first.value, node.count->second.value); + } + if(count.first > count.second || count.first < 0) { + errors.push_back(SourceError{node.count->span, "invalid @size (min, max) := min <= max && min >= 0"}); + return nullopt; + } + + auto type = toType(node.type); + + if(!node.tooltip && type == Bus::REGULAR) { + errors.push_back(SourceError{node.span, "missing @tooltip"}); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if(!node.display && type == Bus::REGULAR) { + errors.push_back(SourceError{node.span, "missing @display"}); + return nullopt; + } + if(node.display && type == Bus::AUTOMATIC) { + errors.push_back(SourceError{node.span, "automatic bus cannot have a @display"}); + return nullopt; + } + + + optional display; + if(Bus::REGULAR) { + display = loadDisplay(*node.display); + if(!display) { + return nullopt; + } + } + + return Bus(name, tooltip, type, count, display); +} + + +std::optional ComdelGenerator::loadAddressSpace(AddressSpaceNode node) +{ + return AddressSpace(node.name.value, node.start.value, node.end.value); +} + +std::optional ComdelGenerator::loadConnection(ConnectionNode node) +{ + std::string component = node.component.value; + std::string pin = node.pin.value; + std::string bus = node.bus.value; + + std::vector attributes; + for(uint i=0; i attributeNames; + for(auto attribute: attributes) { + attributeNames.insert(attribute.getName()); + } + + std::vector wires; + for(uint i=0; i ComdelGenerator::loadComponent(ComponentNode node) +{ + std::string name = node.name.value; + + if(!node.tooltip) { + errors.push_back(SourceError{node.span, "missing @tooltip"}); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if(!node.source) { + errors.push_back(SourceError{node.span, "missing @source"}); + return nullopt; + } + std::string source = node.source->asString(); + + Component::ComponentType type = toType(node.type); + + std::vector attributes; + for(auto& a: node.attributes) { + std::optional attribute = loadAttribute(a); + if(attribute) { + attributes.push_back(*attribute); + } + } + + std::vector rules; + for(auto& r: node.rules) { + std::optional rule = loadRule(r); + if(rule) { + rules.push_back(*rule); + } + } + + if(!node.instanceName) { + errors.push_back(SourceError{node.span, "missing @instanceName"}); + return nullopt; + } + std::string instanceName = node.instanceName->asString(); + + auto count = std::make_pair(1, 1); + if(node.count) { + count = std::make_pair(node.count->first.value, node.count->second.value); + } + if(count.first > count.second || count.first < 0) { + errors.push_back(SourceError{node.count->first.span, "invalid @size"}); + return nullopt; + } + + if(!node.display) { + errors.push_back(SourceError{node.span, "missing @display"}); + return nullopt; + } + optional display = loadDisplay(*node.display); + if(!display) { + return nullopt; + } + + std::vector pins; + for(uint i=0; i ComdelGenerator::loadPin(PinNode node) +{ + std::string name = node.name.value; + Pin::PinType type = toType(node.type); + + if(!node.tooltip) { + errors.push_back(SourceError{node.span, "missing @tooltip"}); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if(!node.display) { + errors.push_back(SourceError{node.span, "missing @display"}); + return nullopt; + } + std::vector attributes; + optional display = loadDisplay(*node.display); + if(!display) { + return nullopt; + } + + if(!node.connection) { + errors.push_back(SourceError{node.span, "missing @connection"}); + return nullopt; + } + auto connection = loadPinConnection(*node.connection); + + return Pin(name, type, tooltip, connection, *display); +} + + +std::optional ComdelGenerator::loadDisplay(DisplayNode node) +{ + return Display(); +} + + +PinConnection ComdelGenerator::loadPinConnection(PinConnectionNode node) +{ + std::string message = node.message.asString(); + PinConnection::ConnectionType type = toType(node.type); + return PinConnection(message, type); +} + +std::optional ComdelGenerator::loadAttribute(AttributeNode node) +{ + std::string name = node.name.value; + Value value; + if(node.type == ValueNode::INT) { + value = Value::fromInt(node.defaultValue->asInt()); + } else if (node.type == ValueNode::BOOL) { + value = Value::fromBool(node.defaultValue->asBool()); + } else if (node.type == ValueNode::STRING) { + value = Value::fromString(node.defaultValue->asString()); + } else if (node.type == ValueNode::WIRE) { + value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE); + } + + std::optional popup; + if(node.popup) { + popup = loadPopup(*node.popup, name, value.getType()); + } + + return Attribute(name, value, popup); +} + +std::optional ComdelGenerator::loadPopup(PopupNode node, std::string name, Value::ValueType type) +{ + auto popupType = toType(*node.type); + + if(!node.title) { + errors.push_back(SourceError{node.span, "missing @title"}); + return nullopt; + } + std::string title = node.title->asString(); + + if(!node.text) { + errors.push_back(SourceError{node.span, "missing @text"}); + return nullopt; + } + std::string text = node.text->asString(); + + std::vector attributes; + attributes.push_back(Attribute(name, Value::ofType(type))); + + std::vector rules; + for(auto& r: node.rules) { + std::optional rule = loadRule(r); + if(rule) { + rules.push_back(*rule); + } + } + + std::vector enumeration; + if(node.enumerated) { + for(uint i=0; i ComdelGenerator::loadRule(RuleNode node) +{ + std::vector statements; + + for(auto& stmt: node.statements) { + auto condition = loadCondition(stmt.condition); + if(condition) { + statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type), stmt.action.message.asString()))); + } else { + return nullopt; + } + } + + return Rule(statements); +} + +std::optional ComdelGenerator::loadCondition(ConditionNode node) +{ + std::string function = node.functionName.value; + + for(uint i=0; i params; + for(int j=0; j +#include +#include + +namespace domain { + +class ComdelGenerator +{ + std::vector errors; + std::vector signatures; + + std::optional loadAddressSpace(AddressSpaceNode node); + std::optional loadComponent(ComponentNode node); + std::optional loadAttribute(AttributeNode node); + std::optional loadRule(RuleNode node); + std::optional loadCondition(ConditionNode node); + std::optional loadPopup(PopupNode node, std::string name, Value::ValueType type); + std::optional loadDisplay(DisplayNode node); + std::optional loadPin(PinNode pins); + PinConnection loadPinConnection(PinConnectionNode node); + std::optional loadConnection(ConnectionNode node); + std::optional loadBus(BusNode node); + +public: + ComdelGenerator(std::vector signatures); + + std::vector getErrors() { + return errors; + } + + std::optional loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream); +}; + +} // namespace domain + +#endif // DOMAIN_COMDELGENERATOR_H diff --git a/comdel/domain/component.cpp b/comdel/domain/component.cpp new file mode 100644 index 0000000..c8ad45c --- /dev/null +++ b/comdel/domain/component.cpp @@ -0,0 +1,62 @@ +#include "component.h" + +namespace domain { + +Component::Component(string name, string tooltip, string source, ComponentType type, + vector rules, string instanceName, pair count, Display display, + vector pins, vector attributes) + : name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), count(count), display(display), pins(pins), attributes(attributes) +{} + +std::string Component::getName() { + return name; +} +std::string Component::getTooltip() { + return tooltip; +} +std::string Component::getSource() { + return source; +} +Component::ComponentType Component::getType() { + return type; +} +std::vector Component::getRules() { + return rules; +} +std::string Component::getInstanceName() { + return instanceName; +} +std::pair Component::getCount() { + return count; +} +Display Component::getDisplay() { + return display; +} + +std::vector Component::getPins() { + return pins; +} +Pin Component::getPin(std::string pin) { + for(uint i=0; i Component::getAttributes() { + return attributes; +} +Attribute Component::getAttribute(std::string attribute) { + for(uint i=0; i +#include + +namespace domain { + +using namespace std; + +class Component +{ +public: + enum ComponentType { + OTHER, + PROCESSOR, + MEMORY + }; + +private: + std::string name; + std::string tooltip; + std::string source; + ComponentType type; + std::vector rules; + std::string instanceName; + std::pair count; + Display display; + + std::vector pins; + std::vector attributes; + +public: + + Component(string name, string tooltip, string source, ComponentType type, + vector rules, string instanceName, pair count, Display display, + vector pins, vector attributes); + + std::string getName(); + std::string getTooltip(); + std::string getSource(); + ComponentType getType(); + std::vector getRules(); + std::string getInstanceName(); + std::pair getCount(); + Display getDisplay(); + + std::vector getPins(); + Pin getPin(std::string pin); + + std::vector getAttributes(); + Attribute getAttribute(std::string attribute); + +}; + +} // namespace domain + +#endif // DOMAIN_COMPONENT_H diff --git a/comdel/domain/connection.cpp b/comdel/domain/connection.cpp new file mode 100644 index 0000000..ce37192 --- /dev/null +++ b/comdel/domain/connection.cpp @@ -0,0 +1,39 @@ +#include "connection.h" + +namespace domain { + +Connection::Connection(std::string component, std::string pin, std::string bus, std::vector attributes, std::vector wires) + : component(component), pin(pin), bus(bus), attributes(attributes), wires(wires) +{} + +bool Connection::isConnecting(std::string component, std::string pin, std::string bus) { + return this->component == component && this->pin == pin && this->bus == bus; +} + +std::string Connection::getComponent() { + return component; +} +std::string Connection::getPin() { + return pin; +} +std::string Connection::getBus() { + return bus; +} + +std::vector Connection::getAttributes() { + return attributes; +} +std::vector Connection::getWires() { + return wires; +} + +Attribute Connection::getAttribute(std::string name) { + for(uint i=0; i +#include + +namespace domain { + +class Connection +{ + std::string component; + std::string pin; + std::string bus; + + std::vector attributes; + std::vector wires; +public: + Connection(std::string component, std::string pin, std::string bus, std::vector attributes, std::vector wires); + + bool isConnecting(std::string component, std::string pin, std::string bus); + + std::string getComponent(); + std::string getPin(); + std::string getBus(); + + std::vector getAttributes(); + std::vector getWires(); + + Attribute getAttribute(std::string name); +}; + +} // namespace domain + +#endif // DOMAIN_CONNECTION_H diff --git a/comdel/domain/display.cpp b/comdel/domain/display.cpp new file mode 100644 index 0000000..6155c9c --- /dev/null +++ b/comdel/domain/display.cpp @@ -0,0 +1,10 @@ +#include "display.h" + +namespace domain { + +Display::Display() +{ + +} + +} // namespace domain diff --git a/comdel/domain/display.h b/comdel/domain/display.h new file mode 100644 index 0000000..d8c2435 --- /dev/null +++ b/comdel/domain/display.h @@ -0,0 +1,15 @@ +#ifndef DOMAIN_DISPLAY_H +#define DOMAIN_DISPLAY_H + + +namespace domain { + +class Display +{ +public: + Display(); +}; + +} // namespace domain + +#endif // DOMAIN_DISPLAY_H diff --git a/comdel/domain/functionsignature.cpp b/comdel/domain/functionsignature.cpp new file mode 100644 index 0000000..00ede9a --- /dev/null +++ b/comdel/domain/functionsignature.cpp @@ -0,0 +1,5 @@ +#include "functionsignature.h" + +namespace domain { + +} // namespace domain diff --git a/comdel/domain/functionsignature.h b/comdel/domain/functionsignature.h new file mode 100644 index 0000000..155071c --- /dev/null +++ b/comdel/domain/functionsignature.h @@ -0,0 +1,20 @@ +#ifndef DOMAIN_FUNCTIONSIGNATURE_H +#define DOMAIN_FUNCTIONSIGNATURE_H + +#include +#include "value.h" + +namespace domain { + +typedef std::function)> FunctionCallback; + +struct FunctionSignature { + std::string name; + std::vector params; + + FunctionSignature(std::string name, std::vector params): name(name), params(params) {} +}; + +} // namespace domain + +#endif // DOMAIN_FUNCTIONSIGNATURE_H diff --git a/comdel/domain/library.cpp b/comdel/domain/library.cpp new file mode 100644 index 0000000..40f0c5d --- /dev/null +++ b/comdel/domain/library.cpp @@ -0,0 +1,78 @@ +#include "library.h" + +namespace domain { + +Library::Library(string name, string libraryInfo, string header, string componentDirectory, + vector addressSpaces, vector components, vector buses, vector connections, map messages) + : name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), addressSpaces(addressSpaces), + components(components), buses(buses), connections(connections), messages(messages) +{} + +std::string Library::getName() { + return name; +} +std::string Library::getLibraryInfo() { + return libraryInfo; +} +std::string Library::getHeader() { + return header; +} +std::string Library::getComponentDirectory() { + return componentDirectory; +} + +std::vector Library::getAddressSpaces() { + return addressSpaces; +} +std::vector Library::getComponents() { + return components; +} +std::vector Library::getBuses() { + return buses; +} +std::vector Library::getConnections() { + return connections; +} + +std::map Library::getMessages() { + return messages; +} + +AddressSpace &Library::getAddressSpace(std::string addressSpace) { + for(uint i=0; i Library::getConnection(std::string component, std::string pin, std::string bus) { + for(uint i=0; i +#include + + + +namespace domain { + +using namespace std; + +class Library +{ + std::string name; + std::string libraryInfo; + std::string header; + std::string componentDirectory; + + std::vector addressSpaces; + std::vector components; + std::vector buses; + std::vector connections; + + std::map messages; + +public: + Library(string name, string libraryInfo, string header, string componentDirectory, + vector addressSpaces, vector components, vector buses, vector connection, map messages); + + std::string getName(); + std::string getLibraryInfo(); + std::string getHeader(); + std::string getComponentDirectory(); + + std::vector getAddressSpaces(); + std::vector getComponents(); + std::vector getBuses(); + std::vector getConnections(); + + std::map getMessages(); + + AddressSpace &getAddressSpace(std::string name); + Component &getComponent(std::string name); + Bus &getBus(std::string bus); + std::optional getConnection(std::string component, std::string pin, std::string bus); + std::string getMessage(std::string key); + +}; + +} // namespace domain + +#endif // DOMAIN_LIBRARY_H diff --git a/comdel/domain/pin.cpp b/comdel/domain/pin.cpp new file mode 100644 index 0000000..15046e1 --- /dev/null +++ b/comdel/domain/pin.cpp @@ -0,0 +1,38 @@ +#include "pin.h" + +namespace domain { + +PinConnection::PinConnection(std::string message, ConnectionType type) + : message(message), type(type) +{} + +PinConnection::ConnectionType PinConnection::getType() { + return type; +} +std::string PinConnection::getMessage() { + return message; +} + + +Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display) + : name(name), type(type), tooltip(tooltip), connection(connection), display(display) +{} + +std::string Pin::getName() { + return name; +} +Pin::PinType Pin::getType() { + return type; +} +std::string Pin::getTooltip() { + return tooltip; +} +Display &Pin::getDisplay() { + return display; +} +PinConnection &Pin::getConnection() { + return connection; +} + + +} // namespace domain diff --git a/comdel/domain/pin.h b/comdel/domain/pin.h new file mode 100644 index 0000000..4c28245 --- /dev/null +++ b/comdel/domain/pin.h @@ -0,0 +1,59 @@ +#ifndef DOMAIN_PIN_H +#define DOMAIN_PIN_H + +#include "display.h" + +#include + + + +namespace domain { + +class PinConnection +{ +public: + enum ConnectionType { + CHECK_ONLY, + AUTOMATICALLY + }; + +private: + std::string message; + ConnectionType type; + +public: + PinConnection(std::string message, ConnectionType type); + + ConnectionType getType(); + std::string getMessage(); +}; + +class Pin +{ +public: + enum PinType { + IN_OUT, + IN, + OUT + }; + +private: + std::string name; + PinType type; + std::string tooltip; + PinConnection connection; + Display display; + +public: + Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display); + + std::string getName(); + PinType getType(); + std::string getTooltip(); + Display &getDisplay(); + PinConnection &getConnection(); +}; + +} // namespace domain + +#endif // DOMAIN_PIN_H diff --git a/comdel/domain/rule.cpp b/comdel/domain/rule.cpp new file mode 100644 index 0000000..690f267 --- /dev/null +++ b/comdel/domain/rule.cpp @@ -0,0 +1,60 @@ +#include "rule.h" + +namespace domain { + +Condition::Condition(std::string function, std::vector params, bool negated) + : negated(negated), function(function), params(params) +{} + +bool Condition::evaluate(RuleContext &context) { + std::vector request; + for(uint i=0; i IfStatement::evaluate(RuleContext &context) { + if(condition.evaluate(context)) { + return action; + } + return std::nullopt; +} + +Rule::Rule(std::vector statements) + : statements(statements) +{} + +std::optional Rule::evaluate(RuleContext &context) { + for(uint i=0; i +#include +#include +#include + +namespace domain { + +struct RuleContext { + std::map addressSpaces; + std::map attributes; + std::map function; +}; + +class Condition { + bool negated; + std::string function; + std::vector params; + +public: + Condition(std::string function, std::vector params, bool negated); + + bool evaluate(RuleContext &context); +}; + +class Action { +public: + enum ActionType { + ERROR, + WARNING + }; + +private: + ActionType type; + std::string message; + +public: + Action(ActionType type, std::string message); + + ActionType getType(); + std::string getMessage(); +}; + +class IfStatement { + Condition condition; + Action action; +public: + IfStatement(Condition condition, Action action); + + std::optional evaluate(RuleContext &context); +}; + +class Rule +{ + std::vector statements; +public: + Rule(std::vector statements); + + std::optional evaluate(RuleContext &context); +}; + +} // namespace domain + +#endif // DOMAIN_RULE_H diff --git a/comdel/domain/value.cpp b/comdel/domain/value.cpp new file mode 100644 index 0000000..afc2bc4 --- /dev/null +++ b/comdel/domain/value.cpp @@ -0,0 +1,82 @@ +#include "value.h" + +#include + +namespace domain { + +Value::ValueType Value::getType() { + return type; +} +bool Value::isType(Value::ValueType type) { + return this->type == type; +} + +long long Value::asInt() { + if(isType(Value::INT)) { + return intValue; + } + throw std::exception(); +} +std::string Value::asString() { + if(isType(Value::STRING)) { + return stringValue; + } + throw std::exception(); +} +bool Value::asBool() { + if(isType(Value::BOOL)) { + return boolValue; + } + throw std::exception(); +} +AddressSpace Value::asAddressSpace() { + if(isType(Value::ADDRESS_SPACE)) { + return *addressSpace; + } + throw std::exception(); +} +std::string Value::asReference() { + if(isType(Value::WIRE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE)) { + return reference; + } + throw std::exception(); +} + +Value Value::fromInt(long long value) { + Value val; + val.type = Value::INT; + val.intValue = value; + return val; +} +Value Value::fromString(std::string value) { + Value val; + val.type = Value::STRING; + val.stringValue = value; + return val; +} +Value Value::fromBool(bool value) { + Value val; + val.type = Value::BOOL; + val.boolValue = value; + return val; +} +Value Value::fromAddressSpace(AddressSpace addressSpace) { + Value val; + val.type = Value::ADDRESS_SPACE; + val.addressSpace = addressSpace; + return val; +} +Value Value::fromReference(std::string value, Value::ValueType type) { + Value val; + val.type = type; + val.reference = value; + return val; +} +Value Value::ofType(Value::ValueType type) { + Value val; + val.type = type; + return val; + +} + +} // namespace domain diff --git a/comdel/domain/value.h b/comdel/domain/value.h new file mode 100644 index 0000000..0078c32 --- /dev/null +++ b/comdel/domain/value.h @@ -0,0 +1,58 @@ +#ifndef DOMAIN_VALUE_H +#define DOMAIN_VALUE_H + +#include "addressspace.h" + +#include +#include + +namespace domain { + +class Value +{ +public: + enum ValueType { + INT, + STRING, + BOOL, + ADDRESS_SPACE, + ATTRIBUTE_REFERENCE, + WIRE_REFERENCE, + UNDEFINED, + }; + +private: + long long intValue; + std::string stringValue; + bool boolValue; + std::optional addressSpace; + std::string reference; + + ValueType type; + +public: + + Value() { + this->type = UNDEFINED; + } + + ValueType getType(); + bool isType(ValueType type); + + long long asInt(); + std::string asString(); + bool asBool(); + std::string asReference(); + AddressSpace asAddressSpace(); + + static Value fromInt(long long value); + static Value fromString(std::string value); + static Value fromBool(bool value); + static Value fromAddressSpace(AddressSpace addressSpace); + static Value fromReference(std::string value, ValueType type); + static Value ofType(ValueType type); +}; + +} // namespace domain + +#endif // DOMAIN_VALUE_H diff --git a/comdel/parser/astnode.h b/comdel/parser/astnode.h index 116363a..f463277 100644 --- a/comdel/parser/astnode.h +++ b/comdel/parser/astnode.h @@ -31,6 +31,9 @@ public: struct StringNode: public AstNode { std::string value; + std::string asString() { + return value.substr(1, value.length() - 2); + } }; struct IdentifierNode: public AstNode @@ -44,6 +47,7 @@ struct NumberNode: public AstNode { NumberNode(): value(0) {} }; + struct CountNode: public AstNode { NumberNode first; @@ -54,7 +58,7 @@ struct CountNode: public AstNode }; -struct AddressSpace: public AstNode +struct AddressSpaceNode: public AstNode { IdentifierNode name; NumberNode start; @@ -62,13 +66,14 @@ struct AddressSpace: public AstNode }; -class Value: AstNode +class ValueNode: AstNode { public: enum ValueType { INT, STRING, BOOL, + WIRE, IDENTIFIER }; @@ -81,6 +86,8 @@ private: std::optional identifierValue; public: + ValueNode() {}; + ValueType getType() { return type; } @@ -113,43 +120,50 @@ public: return this->type == type; } - static Value ofBool(bool _value) { - Value value; + static ValueNode ofBool(bool _value) { + ValueNode value; value.type = BOOL; value.boolValue = std::optional(_value); return value; } - static Value ofInt(long long _value) { - Value value; + static ValueNode ofInt(long long _value) { + ValueNode value; value.type = INT; value.intValue = std::optional(_value); return value; } - static Value ofString(std::string _value) { - Value value; + static ValueNode ofString(std::string _value) { + ValueNode value; value.type = STRING; value.stringValue = std::optional(_value); return value; } - static Value ofIdentifier(std::string _value) { - Value value; + static ValueNode ofIdentifier(std::string _value) { + ValueNode value; value.type = IDENTIFIER; value.identifierValue = std::optional(_value); return value; } + + static ValueNode ofWire(std::string _value) { + ValueNode value; + value.type = WIRE; + value.identifierValue = std::optional(_value); + return value; + } }; -struct Condition +struct ConditionNode { bool negated; IdentifierNode functionName; - std::vector params; + std::vector params; }; -class Action: AstNode { +class ActionNode: AstNode { public: enum ActionType { ERROR, @@ -161,46 +175,47 @@ public: }; -struct IfStmt: AstNode +struct IfStatementnode: AstNode { - Condition condition; - Action action; + ConditionNode condition; + ActionNode action; }; -struct Rule: AstNode +struct RuleNode: AstNode { - std::vector statements; + std::vector statements; }; + struct EnumerationNode: AstNode { StringNode key; - Value value; + ValueNode value; }; -struct Popup: AstNode +struct PopupNode: AstNode { enum PopupType { AUTOMATIC, ON_DEMAND }; - PopupType type; - StringNode title; - StringNode text; + std::optional type; + std::optional title; + std::optional text; bool enumerated; std::vector enumeration; - std::vector rules; + std::vector rules; }; struct PropertyNode: public AstNode { IdentifierNode key; - Value value; + ValueNode value; }; @@ -239,11 +254,9 @@ struct PinNode: AstNode IdentifierNode name; PinType type; - StringNode tooltip; - - PinConnectionNode connection; - - DisplayNode display; + std::optional tooltip; + std::optional connection; + std::optional display; }; @@ -270,10 +283,10 @@ struct WireNode: public AstNode struct AttributeNode: AstNode { - Value::ValueType type; + ValueNode::ValueType type; IdentifierNode name; - std::optional defaultValue; - std::optional popup; + std::optional defaultValue; + std::optional popup; }; struct ConnectionNode: AstNode @@ -295,14 +308,14 @@ struct ComponentNode: AstNode }; IdentifierNode name; - StringNode tooltip; - StringNode source; + std::optional tooltip; + std::optional source; ComponentType type; - std::vector rules; - StringNode instanceName; - CountNode count; - DisplayNode display; - std::vector pin; + std::vector rules; + std::optional instanceName; + std::optional count; + std::optional display; + std::vector pins; std::vector attributes; }; @@ -316,21 +329,21 @@ struct BusNode: AstNode BusType type; IdentifierNode name; - StringNode tooltip; - CountNode count; - DisplayNode display; + std::optional tooltip; + std::optional count; + std::optional display; std::vector wires; }; struct LibraryNode: AstNode { - StringNode name; - StringNode libraryInfo; - StringNode header; - StringNode componentDirectory; + std::optional name; + std::optional libraryInfo; + std::optional header; + std::optional componentDirectory; - std::vector addressSpaces; + std::vector addressSpaces; std::vector components; std::vector buses; @@ -339,6 +352,54 @@ struct LibraryNode: AstNode std::vector messages; }; +// SCHEMA models +struct WireInstanceNode: AstNode +{ + IdentifierNode name; + std::optional position; + std::optional display; +}; + +struct InstanceAttributeNode: AstNode +{ + IdentifierNode name; + ValueNode value; +}; + +struct InstanceNode: AstNode +{ + IdentifierNode name; + IdentifierNode component; + + std::optional position; + std::vector attributes; + + std::optional size; +}; + + +struct ConnectionInstanceNode: AstNode +{ + IdentifierNode instance; + IdentifierNode pin; + IdentifierNode bus; + std::optional wire; + + std::vector attributes; +}; + + +struct SchemaNode: AstNode +{ + std::optional source; + + std::vector instances; + std::vector wires; + std::vector connections; + + std::optional library; +}; + #endif // ASTNODE_H diff --git a/comdel/parser/comdelparser.cpp b/comdel/parser/comdelparser.cpp index 4993aa2..bb11250 100644 --- a/comdel/parser/comdelparser.cpp +++ b/comdel/parser/comdelparser.cpp @@ -360,7 +360,7 @@ PResult ComdelParser::parseProperty(std::optional value return unexpected(); } } - Value value; + ValueNode value; ASSIGN_OR_RETURN_IF_ERR(value, parseValue()); RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON); @@ -374,14 +374,14 @@ PResult ComdelParser::parseProperty(std::optional value /**************************************************************************** * -* AddressSpace := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")" +* AddressSpaceNode := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")" * ****************************************************************************/ -PResult ComdelParser::parseAddress() +PResult ComdelParser::parseAddress() { auto spanner = getSpanner(); - AddressSpace addressSpace{}; + AddressSpaceNode addressSpace{}; RETURN_IF_NOT_TOKEN(TokenType::KW_ADDRESS); @@ -439,7 +439,7 @@ PResult ComdelParser::parseComponent() } else if(check(TokenType::KW_DISPLAY)) { ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay()); } else if(check(TokenType::KW_PIN)) { - APPEND_OR_RETURN_IF_ERR(component.pin, parsePin()); + APPEND_OR_RETURN_IF_ERR(component.pins, parsePin()); } else if(check(TokenType::KW_ATTRIBUTE)) { APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute()); } else if(check(TokenType::KW_RULE)) { @@ -697,13 +697,13 @@ PResult ComdelParser::parseAttribute() { } if(check(TokenType::INT_TYPE)) { - attribute.type = Value::INT; + attribute.type = ValueNode::INT; } else if(check(TokenType::STRING_TYPE)) { - attribute.type = Value::STRING; + attribute.type = ValueNode::STRING; } else if(check(TokenType::BOOL_TYPE)) { - attribute.type = Value::BOOL; + attribute.type = ValueNode::BOOL; } else if(check(TokenType::WIRE_TYPE)) { - attribute.type = Value::IDENTIFIER; + attribute.type = ValueNode::IDENTIFIER; } else { return unexpected(); } @@ -711,32 +711,32 @@ PResult ComdelParser::parseAttribute() { RETURN_IF_NOT_TOKEN(TokenType::DEFAULT); - if(attribute.type == Value::BOOL) { + if(attribute.type == ValueNode::BOOL) { if(check(TokenType::TRUE)) { - attribute.defaultValue = Value::ofBool(true); + attribute.defaultValue = ValueNode::ofBool(true); } else if(check(TokenType::FALSE)) { - attribute.defaultValue = Value::ofBool(false); + attribute.defaultValue = ValueNode::ofBool(false); } else { return unexpected(); } - } else if(attribute.type == Value::INT) { + } else if(attribute.type == ValueNode::INT) { if(check(TokenType::NUMBER)) { auto number = parseNumber(); - attribute.defaultValue = Value::ofInt(number->value); + attribute.defaultValue = ValueNode::ofInt(number->value); } else { return unexpected(); } - } else if(attribute.type == Value::STRING) { + } else if(attribute.type == ValueNode::STRING) { if(check(TokenType::STRING)) { auto string = parseString(); - attribute.defaultValue = Value::ofString(string->value); + attribute.defaultValue = ValueNode::ofString(string->value); } else { return unexpected(); } - } else if(attribute.type == Value::IDENTIFIER) { + } else if(attribute.type == ValueNode::IDENTIFIER) { if(check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); - attribute.defaultValue = Value::ofIdentifier(identifier->value); + attribute.defaultValue = ValueNode::ofIdentifier(identifier->value); } else { return unexpected(); } @@ -744,14 +744,14 @@ PResult ComdelParser::parseAttribute() { if(check(TokenType::LBRACE)) { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - Popup popup; + PopupNode popup; if(!check(TokenType::KW_POPUP)) { return unexpected(); } ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup()); - attribute.popup = std::optional(popup); + attribute.popup = std::optional(popup); RETURN_IF_NOT_TOKEN(TokenType::RBRACE); } @@ -770,7 +770,7 @@ PResult ComdelParser::parseEnumeration() { ASSIGN_OR_RETURN_IF_ERR(key, parseString()); RETURN_IF_NOT_TOKEN(TokenType::EQUALS); - Value value; + ValueNode value; ASSIGN_OR_RETURN_IF_ERR(value, parseValue()); EnumerationNode node; @@ -782,26 +782,26 @@ PResult ComdelParser::parseEnumeration() { /**************************************************************************** * -* Popup := "@popup " + ("automatic" | "on_demand") { POPUP BODY } +* PopupNode := "@popup " + ("automatic" | "on_demand") { POPUP BODY } * ****************************************************************************/ -PResult ComdelParser::parsePopup() { +PResult ComdelParser::parsePopup() { auto spanner = getSpanner(); - Popup popup; + PopupNode popup; RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP); if(check(TokenType::IDENTIFIER)) { auto type = parseIdentifier(); if(type.value().value == "automatic") { - popup.type = Popup::AUTOMATIC; + popup.type = PopupNode::AUTOMATIC; } else if(type.value().value == "on_demand") { - popup.type = Popup::ON_DEMAND; + popup.type = PopupNode::ON_DEMAND; } else { return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"}); } } else { - popup.type = Popup::ON_DEMAND; + popup.type = PopupNode::ON_DEMAND; } RETURN_IF_NOT_TOKEN(TokenType::LBRACE); @@ -880,12 +880,12 @@ PResult ComdelParser::parseConnection() { /**************************************************************************** * -* Rule := "@rule {" + if-else statements + "}" +* RuleNode := "@rule {" + if-else statements + "}" * ****************************************************************************/ -PResult ComdelParser::parseRule() { +PResult ComdelParser::parseRule() { auto spanner = getSpanner(); - Rule rule; + RuleNode rule; RETURN_IF_NOT_TOKEN(TokenType::KW_RULE); @@ -910,9 +910,9 @@ PResult ComdelParser::parseRule() { * IfStatement := "if(!function(params...)) { error(MESSAGE) | warning(MESSAGE) } * ****************************************************************************/ -PResult ComdelParser::parseIfStatement() { +PResult ComdelParser::parseIfStatement() { auto spanner = getSpanner(); - IfStmt ifStatement; + IfStatementnode ifStatement; RETURN_IF_NOT_TOKEN(TokenType::IF); @@ -927,7 +927,7 @@ PResult ComdelParser::parseIfStatement() { ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.functionName, parseIdentifier()); - ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList(std::optional(TokenType::LPAREN), + ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList(std::optional(TokenType::LPAREN), TokenType::RPAREN, TokenType::COMMA, false, @@ -939,9 +939,9 @@ PResult ComdelParser::parseIfStatement() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); if(check(TokenType::ERROR)) { - ifStatement.action.type = Action::ERROR; + ifStatement.action.type = ActionNode::ERROR; } else if(check(TokenType::WARNING)) { - ifStatement.action.type = Action::WARNING; + ifStatement.action.type = ActionNode::WARNING; } else { return unexpected(); } @@ -957,27 +957,208 @@ PResult ComdelParser::parseIfStatement() { return spanner(ifStatement); } -PResult ComdelParser::parseValue() { +PResult ComdelParser::parseValue() { auto spanner = getSpanner(); - Value value; + ValueNode value; if(check(TokenType::IDENTIFIER)) { - value = Value::ofIdentifier(parseIdentifier()->value); + value = ValueNode::ofIdentifier(parseIdentifier()->value); } else if(check(TokenType::STRING)) { - value = Value::ofString(parseString()->value); + value = ValueNode::ofString(parseString()->value); } else if(check(TokenType::NUMBER)) { - value = Value::ofInt(parseNumber()->value); + value = ValueNode::ofInt(parseNumber()->value); } else if(check(TokenType::TRUE)) { - value = Value::ofBool(true); + value = ValueNode::ofBool(true); } else if(check(TokenType::FALSE)) { - value = Value::ofBool(false); + value = ValueNode::ofBool(false); } else { return unexpected(); } - return spanner(value); + //return spanner(value); + return value; +} + +std::optional ComdelParser::parseSchema() { + auto spanner = getSpanner(); + SchemaNode schema{}; + + if(check(TokenType::KW_SOURCE)) { + bump(); + if(check(TokenType::STRING)) { + auto source = parseString(); + schema.source = *source; + } else { + errors.push_back(SourceError{current().span, "expected `@source`"}); + return std::nullopt; + } + } else { + errors.push_back(SourceError{current().span, "expected `@source`"}); + return std::nullopt; + } + + if(!check(TokenType::KW_SCHEMA)) { + errors.push_back(SourceError{current().span, "expected `@schema`"}); + return std::nullopt; + } + bump(); + if(!check(TokenType::LBRACE)) { + errors.push_back(SourceError{current().span, "expected `{`"}); + return std::nullopt; + } + bump(); + + while ( ! check(TokenType::RBRACE) ) { + PResult> err; + if(check(TokenType::KW_INSTANCE)){ + APPEND_OR_SET_ERR(schema.instances, parseInstance()); + } else if(check(TokenType::KW_WIRE)) { + APPEND_OR_SET_ERR(schema.wires, parseWireInstance()); + } else if(check(TokenType::KW_CONNECTION)) { + APPEND_OR_SET_ERR(schema.connections, parseConnectionInstance()); + } else { + err = unexpected(); + } + if(!err.has_value()) { + errors.push_back(err.error()); + break; + } + } + if(!check(TokenType::RBRACE)) { + errors.push_back(SourceError{current().span, "expected `}`"}); + return std::nullopt; + } else { + bump(); + } + + if(!check(TokenType::END_OF_FILE)) { + errors.push_back(SourceError{current().span, "expected `EOF`"}); + } + + if (errors.size()) + return std::nullopt; + + return spanner(schema); +} +PResult ComdelParser::parseWireInstance() { + auto spanner = getSpanner(); + WireInstanceNode wireInstance; + + RETURN_IF_NOT_TOKEN(TokenType::KW_WIRE); + ASSIGN_OR_RETURN_IF_ERR(wireInstance.name, parseIdentifier()); + RETURN_IF_NOT_TOKEN(TokenType::LBRACE); + + while(!check(TokenType::RBRACE)) { + if(check(TokenType::KW_POSITION)) { + ASSIGN_OR_RETURN_IF_ERR(wireInstance.position, parsePosition()); + } else if(check(TokenType::KW_DISPLAY)) { + ASSIGN_OR_RETURN_IF_ERR(wireInstance.display, parseDisplay()); + } else { + return unexpected(); + } + } + + RETURN_IF_NOT_TOKEN(TokenType::RBRACE); + + return spanner(wireInstance); + } +/**************************************************************************** +* +* CountNode := "@position (" + NumberNode + "," + NumberNode + ")" +* +****************************************************************************/ +PResult ComdelParser::parsePosition() +{ + auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_POSITION); + RETURN_IF_NOT_TOKEN(TokenType::LPAREN); + auto first = parseNumber(); + if(!first.has_value()) { + return PError(first.error()); + } + RETURN_IF_NOT_TOKEN(TokenType::COMMA); + auto second = parseNumber(); + if(!second.has_value()) { + return PError(second.error()); + } + RETURN_IF_NOT_TOKEN(TokenType::RPAREN); + + return spanner(CountNode{first.value(), second.value()}); +} + +PResult ComdelParser::parseInstance() { + auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_INSTANCE); + + InstanceNode instance; + + ASSIGN_OR_RETURN_IF_ERR(instance.name, parseIdentifier()); + ASSIGN_OR_RETURN_IF_ERR(instance.component, parseIdentifier()); + + RETURN_IF_NOT_TOKEN(TokenType::LBRACE); + + while(!check(TokenType::RBRACE)) { + if(check(TokenType::KW_POSITION)) { + ASSIGN_OR_RETURN_IF_ERR(instance.position, parsePosition()); + } else if(check(TokenType::KW_ATTRIBUTE)) { + APPEND_OR_RETURN_IF_ERR(instance.attributes, parseInstanceAttribute()); + } else if(check(TokenType::KW_SIZE)) { + bump(); + auto number = parseNumber(); + RETURN_IF_ERR(number); + instance.size = *number; + } else { + return unexpected(); + } + } + + RETURN_IF_NOT_TOKEN(TokenType::RBRACE); + + return spanner(instance); +} +PResult ComdelParser::parseInstanceAttribute() { + auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE); + InstanceAttributeNode attribute; + + ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier()); + ASSIGN_OR_RETURN_IF_ERR(attribute.value, parseValue()); + + return spanner(attribute); +} +PResult ComdelParser::parseConnectionInstance() { + auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); + + ConnectionInstanceNode connection; + + RETURN_IF_NOT_TOKEN(TokenType::LPAREN); + ASSIGN_OR_RETURN_IF_ERR(connection.instance, parseIdentifier()); + RETURN_IF_NOT_TOKEN(TokenType::DOT); + ASSIGN_OR_RETURN_IF_ERR(connection.pin, parseIdentifier()); + RETURN_IF_NOT_TOKEN(TokenType::COMMA); + ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier()); + RETURN_IF_NOT_TOKEN(TokenType::RPAREN); + + RETURN_IF_NOT_TOKEN(TokenType::LBRACE); + + while(!check(TokenType::RBRACE)) { + if(check(TokenType::KW_WIRE)) { + bump(); + ASSIGN_OR_RETURN_IF_ERR(connection.wire, parseIdentifier()); + } else if(check(TokenType::KW_ATTRIBUTE)) { + APPEND_OR_RETURN_IF_ERR(connection.attributes, parseInstanceAttribute()); + } else { + return unexpected(); + } + } + + RETURN_IF_NOT_TOKEN(TokenType::RBRACE); + + return spanner(connection); +} diff --git a/comdel/parser/comdelparser.h b/comdel/parser/comdelparser.h index 01858a7..c7704ad 100644 --- a/comdel/parser/comdelparser.h +++ b/comdel/parser/comdelparser.h @@ -27,7 +27,7 @@ public: template ::value>> typename std::remove_reference_t operator()(T&& astNode) const { - //astNode.span = lo.to(prevSpan); + astNode.span = lo.to(prevSpan); return std::move(astNode); } }; @@ -71,22 +71,29 @@ private: PResult parseEnumeration(); PResult parseComponent(); - PResult parseAddress(); + PResult parseAddress(); PResult parsePin(); PResult parseDisplay(); PResult parsePinConnection(); PResult parseAttribute(); - PResult parsePopup(); - PResult parseRule(); + PResult parsePopup(); + PResult parseRule(); PResult parseBus(); PResult parseWire(); PResult parseConnection(); PResult parseDisplayItem(); - PResult parseIfStatement(); - PResult parseValue(); + PResult parseIfStatement(); + PResult parseValue(); + + PResult parseWireInstance(); + PResult parsePosition(); + PResult parseInstance(); + PResult parseInstanceAttribute(); + PResult parseConnectionInstance(); public: ComdelParser(std::vector tokens); + std::optional parseSchema(); std::optional parse(); const std::vector& getErrors(); }; diff --git a/comdel/parser/parserutil.cpp b/comdel/parser/parserutil.cpp index 43b75e6..5811870 100644 --- a/comdel/parser/parserutil.cpp +++ b/comdel/parser/parserutil.cpp @@ -40,3 +40,44 @@ std::optional loadLibraryFromFile(ParseContext * parseContext, return *unit; } + + +std::optional loadSchemaFromFile(ParseContext * parseContext, + const char* name, + std::ostream& stream) +{ + std::ifstream in(name, std::ios::in | std::ios::binary); + if( ! in ) { + stream << "ERROR: cannot open file '" << name + << "' (file does not exist or is unreadable)" << std::endl; + return std::nullopt; + } + + std::string source((std::istreambuf_iterator(in)), + std::istreambuf_iterator()); + ComdelLexer lexer(name, source, parseContext); + LexerResult lexerResult = lexer.tokenize(); + + if (lexerResult.errors.size()) { + for (auto& error : lexerResult.errors) { + parseContext->formatError(error, stream, "ERROR: "); + } + return std::nullopt; // if lexer has found errors => don't parse + } + + ComdelParser parser(lexerResult.tokens); + auto unit = parser.parseSchema(); + if (!unit) { + for (auto& error : parser.getErrors()) { + parseContext->formatError(error, stream, "ERROR: "); + } + return std::nullopt; + } + + if(unit->source) { + unit->library = loadLibraryFromFile(parseContext, unit->source->asString().c_str(), stream); + } + + + return *unit; +} diff --git a/comdel/parser/parserutil.h b/comdel/parser/parserutil.h index 0c3c315..2794508 100644 --- a/comdel/parser/parserutil.h +++ b/comdel/parser/parserutil.h @@ -8,4 +8,8 @@ std::optional loadLibraryFromFile(ParseContext * parseContext, const char* name, std::ostream& stream); +std::optional loadSchemaFromFile(ParseContext * parseContext, + const char* name, + std::ostream& stream); + #endif // PARSERUTIL_H diff --git a/comdel/parser/tokenstype.cpp b/comdel/parser/tokenstype.cpp index 08858bd..196a698 100644 --- a/comdel/parser/tokenstype.cpp +++ b/comdel/parser/tokenstype.cpp @@ -128,7 +128,7 @@ TokenTables::TokenTables() { add( TokenType::PIN_OUT, "out", TOKENIZABLE), add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE), - // Action types + // ActionNode types add( TokenType::ERROR, "error", TOKENIZABLE), add( TokenType::WARNING, "warning", TOKENIZABLE), diff --git a/domain/schema/connectioninstance.cpp b/domain/schema/connectioninstance.cpp deleted file mode 100644 index c853a7d..0000000 --- a/domain/schema/connectioninstance.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "connectioninstance.h" - -ConnectionInstance::ConnectionInstance() -{ - -} diff --git a/domain/schema/connectioninstance.h b/domain/schema/connectioninstance.h deleted file mode 100644 index df79fb3..0000000 --- a/domain/schema/connectioninstance.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DOMAIN_SCHEMA_CONNECTIONINSTANCE_H -#define DOMAIN_SCHEMA_CONNECTIONINSTANCE_H - -#include "instance.h" -#include "wireinstance.h" - -#include - -class ConnectionInstance: AstNode -{ - Instance *instance; - std::string pin; - Instance *bus; - WireInstance *wireInstance; - - std::vector attributes; - -public: - ConnectionInstance(); -}; - -#endif // DOMAIN_SCHEMA_CONNECTIONINSTANCE_H diff --git a/domain/schema/instance.cpp b/domain/schema/instance.cpp deleted file mode 100644 index 05ef0ab..0000000 --- a/domain/schema/instance.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "instance.h" - -Instance::Instance() -{ - -} diff --git a/domain/schema/instance.h b/domain/schema/instance.h deleted file mode 100644 index d1b9ae0..0000000 --- a/domain/schema/instance.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef DOMAIN_SCHEMA_INSTANCE_H -#define DOMAIN_SCHEMA_INSTANCE_H - -#include "instanceattribute.h" - -#include -#include - -class Instance: AstNode -{ - std::string name; - std::string component; - - std::pair position; - std::vector attributes; - - int size; - -public: - Instance(); -}; - -#endif // DOMAIN_SCHEMA_INSTANCE_H diff --git a/domain/schema/instanceattribute.cpp b/domain/schema/instanceattribute.cpp deleted file mode 100644 index 20cf280..0000000 --- a/domain/schema/instanceattribute.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "instanceattribute.h" - -InstanceAttribute::InstanceAttribute() -{ -} diff --git a/domain/schema/instanceattribute.h b/domain/schema/instanceattribute.h deleted file mode 100644 index 267c956..0000000 --- a/domain/schema/instanceattribute.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DOMAIN_SCHEMA_ATTRIBUTE_H -#define DOMAIN_SCHEMA_ATTRIBUTE_H - -#include - -class InstanceAttribute: AstNode -{ - std::string name; - Value value; -public: - InstanceAttribute(); -}; - -#endif // DOMAIN_SCHEMA_ATTRIBUTE_H diff --git a/domain/schema/schema.cpp b/domain/schema/schema.cpp deleted file mode 100644 index 58e60fc..0000000 --- a/domain/schema/schema.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "schema.h" - -Schema::Schema() -{ - -} diff --git a/domain/schema/schema.h b/domain/schema/schema.h deleted file mode 100644 index b4790bc..0000000 --- a/domain/schema/schema.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef DOMAIN_SCHEMA_SCHEMA_H -#define DOMAIN_SCHEMA_SCHEMA_H - -#include "connectioninstance.h" -#include "instance.h" -#include "wireinstance.h" - -#include - -class Schema: AstNode -{ - std::vector instances; - std::vector wires; - std::vector connections; -public: - Schema(); -}; - -#endif // DOMAIN_SCHEMA_SCHEMA_H diff --git a/domain/schema/wireinstance.cpp b/domain/schema/wireinstance.cpp deleted file mode 100644 index 4b2d59b..0000000 --- a/domain/schema/wireinstance.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "wireinstance.h" - -WireInstance::WireInstance() -{ - -} diff --git a/domain/schema/wireinstance.h b/domain/schema/wireinstance.h deleted file mode 100644 index 413e090..0000000 --- a/domain/schema/wireinstance.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DOMAIN_SCHEMA_WIREINSTANCE_H -#define DOMAIN_SCHEMA_WIREINSTANCE_H - -#include -#include - -class WireInstance: AstNode -{ - std::string name; - std::pair position; - DisplayNode display; - -public: - WireInstance(); -}; - -#endif // DOMAIN_SCHEMA_WIREINSTANCE_H diff --git a/main.cpp b/main.cpp index 278e9ad..2864183 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,8 @@ #include #include +#include + int main(int argc, char *argv[]) { /* @@ -17,5 +19,17 @@ int main(int argc, char *argv[]) */ ParseContext parseContext; - loadLibraryFromFile(&parseContext, "/home/bbr/Documents/personal/projects/modeler/frisc_library.csl", std::cout); + auto schema = loadSchemaFromFile(&parseContext, "/home/bbr/Documents/personal/projects/modeler/schema.csl", std::cout); + + if(schema) { + std::vector signatures; + domain::ComdelGenerator generator(signatures); + generator.loadLibrary(*schema->library, &parseContext, std::cout); + + for (auto& error : generator.getErrors()) { + parseContext.formatError(error, std::cout, "ERROR: "); + } + + } + }