Basic refactor

This commit is contained in:
Borna Rajković 2022-05-27 08:18:17 +02:00
parent aac972c6ca
commit 0c4afe87d9
89 changed files with 7110 additions and 6772 deletions

View File

@ -14,29 +14,28 @@ add_executable(SchemeEditor
comdel/domain/value.cpp comdel/domain/value.cpp
comdel/domain/schema.cpp comdel/domain/schema.cpp
comdel/domain/component.cpp comdel/domain/component.cpp
comdel/domain/connectioninstance.cpp comdel/domain/connection_instance.cpp
comdel/domain/rule.cpp comdel/domain/rule.cpp
comdel/domain/wireinstance.cpp comdel/domain/attribute.cpp
comdel/domain/attribute.cpp
comdel/domain/bus.cpp comdel/domain/bus.cpp
comdel/domain/pin.cpp comdel/domain/pin.cpp
comdel/domain/display.cpp comdel/domain/display.cpp
comdel/domain/library.cpp comdel/domain/library.cpp
comdel/domain/functionsignature.cpp comdel/domain/function_signature.cpp
comdel/domain/addressspace.cpp comdel/domain/address_space.cpp
comdel/domain/instanceattribute.cpp comdel/domain/instance_attribute.cpp
comdel/domain/connection.cpp comdel/domain/connection.cpp
comdel/domain/instance.cpp comdel/domain/instance.cpp
comdel/domain/schemacreator.cpp comdel/domain/schema_creator.cpp
comdel/parser/comdelparser.cpp comdel/parser/comdel_parser.cpp
comdel/parser/token.cpp comdel/parser/token.cpp
comdel/parser/sourceerror.cpp comdel/parser/source_error.cpp
comdel/parser/parsecontext.cpp comdel/parser/parse_context.cpp
comdel/parser/tokenstype.cpp comdel/parser/tokens_type.cpp
comdel/parser/astnode.cpp comdel/parser/ast_nodes.cpp
comdel/parser/parserutil.cpp comdel/parser/parser_util.cpp
comdel/parser/comdellexer.cpp comdel/parser/comdellexer.cpp
main.cpp main.cpp
mainwindow.ui mainwindow.ui
comdel/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h) comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h)
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)

View File

@ -7,55 +7,159 @@
namespace display { namespace display {
void AttributeDialog::onUpdate() { void AttributeDialog::onUpdate() {
auto oldValue = attributeValue->value; auto oldValue = attributeValue->value;
attributeValue->value = value; attributeValue->value = value;
domain::ComdelValidator validator(domain::getSupportedValidators()); domain::ComdelValidator validator(domain::getSupportedValidators());
domain::ValidationContext context; domain::ValidationContext context;
for (auto &addressSpace: MainWindow::getLibrary()->getAddressSpaces()) { for (auto &addressSpace: MainWindow::getLibrary()->getAddressSpaces()) {
context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace)); context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace));
}
auto validationErrors = validator.validateAttribute(attributeValue, context);
if(validationErrors.empty()) {
accept();
} else {
bool canAccept = true;
std::vector<domain::ValidationError> errors;
std::vector<domain::ValidationError> warnings;
for(auto& err: validationErrors) {
if(err.type == domain::Action::ERROR) {
errors.push_back(err);
} else {
warnings.push_back(err);
}
}
if(!errors.empty()) {
canAccept = false;
auto errorDialog = new ErrorDialog(errors);
errorDialog->exec();
} }
for(auto& warning: warnings) { auto validationErrors = validator.validateAttribute(attributeValue, context);
auto warningDialog = new WarningDialog(warning); if (validationErrors.empty()) {
int response = warningDialog->exec();
if(response == QDialog::Rejected) {
canAccept = false;
}
}
if(canAccept) {
accept(); accept();
} else { } else {
attributeValue->value = oldValue; bool canAccept = true;
std::vector<domain::ValidationError> errors;
std::vector<domain::ValidationError> warnings;
for (auto &err: validationErrors) {
if (err.type == domain::Action::ERROR) {
errors.push_back(err);
} else {
warnings.push_back(err);
}
}
if (!errors.empty()) {
canAccept = false;
auto errorDialog = new ErrorDialog(errors);
errorDialog->exec();
}
for (auto &warning: warnings) {
auto warningDialog = new WarningDialog(warning);
int response = warningDialog->exec();
if (response == QDialog::Rejected) {
canAccept = false;
}
}
if (canAccept) {
accept();
} else {
attributeValue->value = oldValue;
}
}
}
AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute) {
setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute;
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
auto popup = *attribute->attribute.getPopup();
layout->addWidget(new QLabel(popup.getTitle().c_str()));
layout->addWidget(new QLabel(popup.getText().c_str()));
auto type = attribute->attribute.getDefault().getType();
value = attribute->value;
if (attribute->attribute.getPopup()->isEnumerated()) {
auto *combo = new QComboBox(this);
auto enumeration = attribute->attribute.getPopup()->getEnumeration();
for (auto entry: enumeration) {
combo->addItem(QString::fromStdString(entry.getName()));
}
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&AttributeDialog::onEnumerationChanged);
layout->addWidget(combo);
for (int i = 0; i < enumeration.size(); i++) {
if (attributeValue->value.equals(enumeration[i].getValue())) {
combo->setCurrentIndex(i);
break;
}
}
} else if (!(type == domain::Value::ValueType::WIRE_REFERENCE || type == domain::Value::ValueType::BOOL)) {
auto edit = new QLineEdit(this);
connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged);
layout->addWidget(edit);
switch (attribute->attribute.getDefault().getType()) {
case domain::Value::ValueType::INT:
edit->setValidator(new QIntValidator(-10000000, 10000000, edit));
edit->insert(std::to_string(attribute->value.asInt()).c_str());
break;
case domain::Value::ValueType::STRING:
edit->insert(attribute->value.asString().c_str());
break;
default:
throw std::exception();
}
} else if (type == domain::Value::ValueType::BOOL) {
auto *group = new QGroupBox(this);
auto *radioLayout = new QHBoxLayout(group);
group->setLayout(radioLayout);
auto isTrue = new QRadioButton("true", group);
connect(isTrue, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(true);
});
auto isFalse = new QRadioButton("false", group);
connect(isFalse, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(false);
});
if (attribute->value.asBool()) {
isTrue->setChecked(true);
} else {
isFalse->setChecked(true);
}
radioLayout->addWidget(isTrue);
radioLayout->addWidget(isFalse);
layout->addWidget(group);
}
auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
layout->addWidget(button);
}
void AttributeDialog::onTextChanged(const QString &string) {
switch (value.getType()) {
case domain::Value::STRING:
value.setString(string.toStdString());
break;
case domain::Value::INT:
value = domain::Value::fromInt(parseInt(string.toStdString()));
break;
default:
throw std::exception();
} }
} }
} void AttributeDialog::onEnumerationChanged(int index) {
value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue();
}
void MemoryDialog::onUpdate() { void MemoryDialog::onUpdate() {
@ -63,4 +167,97 @@ void AttributeDialog::onUpdate() {
accept(); accept();
} }
MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute,
std::vector<std::shared_ptr<domain::ComponentInstance>> instances) {
memoryInstances = std::vector<std::string>();
setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute;
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
for (auto &instance: instances) {
if (instance->component.getType() == domain::Component::MEMORY) {
memoryInstances.push_back(instance->name);
}
}
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
auto popup = *attribute->attribute.getPopup();
layout->addWidget(new QLabel(popup.getTitle().c_str()));
layout->addWidget(new QLabel(popup.getText().c_str()));
value = attribute->value;
auto *combo = new QComboBox(this);
for (auto &entry: memoryInstances) {
combo->addItem(QString::fromStdString(entry));
}
combo->addItem("null");
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MemoryDialog::onMemoryChanged);
layout->addWidget(combo);
combo->setCurrentIndex(memoryInstances.size());
for (int i = 0; i < memoryInstances.size(); i++) {
if (attributeValue->value.asMemoryReference().has_value() &&
attributeValue->value.asMemoryReference() == memoryInstances[i]) {
combo->setCurrentIndex(i);
break;
}
}
auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
layout->addWidget(button);
}
void MemoryDialog::onMemoryChanged(int index) {
if (index == memoryInstances.size()) {
value = domain::Value::fromMemoryReference(std::nullopt);
} else {
value = domain::Value::fromMemoryReference(memoryInstances[index]);
}
}
ErrorDialog::ErrorDialog(std::vector<domain::ValidationError> errors) {
setAttribute(Qt::WA_DeleteOnClose);
this->setWindowTitle("Greške");
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
for (auto &err: errors) {
layout->addWidget(new QLabel(QString::fromStdString(err.message), this));
}
}
WarningDialog::WarningDialog(domain::ValidationError error) {
setAttribute(Qt::WA_DeleteOnClose);
this->setWindowTitle("Upozorenje");
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
layout->addWidget(new QLabel(QString::fromStdString(error.message), this));
auto buttonLayout = new QHBoxLayout(this);
auto okButton = new QPushButton("U redu", this);
auto cancelButton = new QPushButton("Odustani", this);
connect(okButton, &QPushButton::clicked, [this]() { accept(); });
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
layout->addItem(buttonLayout);
}
} }

View File

@ -11,257 +11,78 @@
#include <QLabel> #include <QLabel>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <utility> #include <utility>
#include <comdel/domain/instanceattribute.h> #include <comdel/domain/instance_attribute.h>
#include <comdel/domain/value.h> #include <comdel/domain/value.h>
#include "comdel/domain/comdelvalidator.h" #include "comdel/domain/comdel_validator.h"
namespace display { namespace display {
class AttributeDialog: public QDialog { class AttributeDialog : public QDialog {
domain::Value value;
long long int parseInt(std::string expression) {
try {
if (expression.size() > 2) {
if (expression.substr(0, 2) == "0x") {
return std::stoll(expression, 0, 16);
} else if (expression.substr(0, 2) == "0b") {
return std::stoll(expression, 0, 2);
} else {
return std::stoll(expression, 0, 10);
}
} else {
return std::stoll(expression, 0, 10);
}
} catch (std::exception &e) {
return 0;
}
}
domain::InstanceAttribute* attributeValue;
public:
AttributeDialog(domain::InstanceAttribute *attribute) {
setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute;
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
auto popup = *attribute->attribute.getPopup();
layout->addWidget(new QLabel(popup.getTitle().c_str()));
layout->addWidget(new QLabel(popup.getText().c_str()));
auto type = attribute->attribute.getDefault().getType();
value = attribute->value;
if(attribute->attribute.getPopup()->isEnumerated()) {
auto* combo = new QComboBox(this);
auto enumeration = attribute->attribute.getPopup()->getEnumeration();
for(auto entry: enumeration) {
combo->addItem(QString::fromStdString(entry.getName()));
}
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AttributeDialog::onEnumerationChanged);
layout->addWidget(combo);
for(int i=0; i<enumeration.size(); i++) {
if(attributeValue->value.equals(enumeration[i].getValue())) {
combo->setCurrentIndex(i);
break;
}
}
} else if(!(type == domain::Value::ValueType::WIRE_REFERENCE || type == domain::Value::ValueType::BOOL)) {
auto edit = new QLineEdit(this);
connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged);
layout->addWidget(edit);
switch (attribute->attribute.getDefault().getType()) {
case domain::Value::ValueType::INT:
edit->setValidator(new QIntValidator(-10000000, 10000000, edit));
edit->insert(std::to_string(attribute->value.asInt()).c_str());
break;
case domain::Value::ValueType::STRING:
edit->insert(attribute->value.asString().c_str());
break;
}
} else if(type == domain::Value::ValueType::BOOL) {
auto *group = new QGroupBox(this);
auto *radioLayout = new QHBoxLayout(group);
group->setLayout(radioLayout);
auto isTrue = new QRadioButton("true", group);
connect(isTrue, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(true);
});
auto isFalse = new QRadioButton("false", group);
connect(isFalse, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(false);
});
if(attribute->value.asBool()) {
isTrue->setChecked(true);
} else {
isFalse->setChecked(true);
}
radioLayout->addWidget(isTrue);
radioLayout->addWidget(isFalse);
layout->addWidget(group);
}
auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
layout->addWidget(button);
}
public slots:
void onTextChanged(const QString& string) {
switch (value.getType()) {
case domain::Value::STRING:
value.setString(string.toStdString());
break;
case domain::Value::INT:
value = domain::Value::fromInt(parseInt(string.toStdString()));
}
};
void onEnumerationChanged(int index) {
value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue();
}
void onUpdate();
};
class MemoryDialog: public QDialog {
domain::Value value; domain::Value value;
domain::InstanceAttribute* attributeValue; long long int parseInt(std::string expression) {
std::vector<std::string> memoryInstances; try {
if (expression.size() > 2) {
if (expression.substr(0, 2) == "0x") {
return std::stoll(expression, nullptr, 16);
} else if (expression.substr(0, 2) == "0b") {
return std::stoll(expression, nullptr, 2);
} else {
return std::stoll(expression, nullptr, 10);
}
} else {
return std::stoll(expression, nullptr, 10);
}
} catch (std::exception &e) {
return 0;
}
}
domain::InstanceAttribute *attributeValue;
public: public:
MemoryDialog(domain::InstanceAttribute *attribute, std::vector<std::shared_ptr<domain::ComponentInstance>> instances) { AttributeDialog(domain::InstanceAttribute *attribute);
memoryInstances = std::vector<std::string>();
setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute;
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
for(auto& instance: instances) {
if(instance->component.getType() == domain::Component::MEMORY) {
memoryInstances.push_back(instance->name);
}
}
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
auto popup = *attribute->attribute.getPopup();
layout->addWidget(new QLabel(popup.getTitle().c_str()));
layout->addWidget(new QLabel(popup.getText().c_str()));
value = attribute->value;
auto* combo = new QComboBox(this);
for(auto& entry: memoryInstances) {
combo->addItem(QString::fromStdString(entry));
}
combo->addItem("null");
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MemoryDialog::onMemoryChanged);
layout->addWidget(combo);
combo->setCurrentIndex(memoryInstances.size());
for(int i=0; i<memoryInstances.size(); i++) {
if(attributeValue->value.asMemoryReference().has_value() && attributeValue->value.asMemoryReference() == memoryInstances[i]) {
combo->setCurrentIndex(i);
break;
}
}
auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
layout->addWidget(button);
}
public slots: public slots:
void onMemoryChanged(int index) { void onTextChanged(const QString &string);
if(index == memoryInstances.size()) {
value = domain::Value::fromMemoryReference(std::nullopt); void onEnumerationChanged(int index);
} else {
value = domain::Value::fromMemoryReference(memoryInstances[index]);
}
}
void onUpdate(); void onUpdate();
}; };
class ErrorDialog: public QDialog { class MemoryDialog : public QDialog {
domain::Value value;
domain::InstanceAttribute *attributeValue;
std::vector<std::string> memoryInstances;
public: public:
ErrorDialog(std::vector<domain::ValidationError> errors) { MemoryDialog(domain::InstanceAttribute *attribute,
std::vector<std::shared_ptr<domain::ComponentInstance>> instances);
setAttribute(Qt::WA_DeleteOnClose); public slots:
this->setWindowTitle("Greške"); void onMemoryChanged(int index);
auto layout = new QVBoxLayout(this); void onUpdate();
this->setLayout(layout);
for(auto& err: errors) {
layout->addWidget(new QLabel(QString::fromStdString(err.message), this));
}
}
}; };
class WarningDialog: public QDialog {
class ErrorDialog : public QDialog {
public: public:
WarningDialog(domain::ValidationError error) { ErrorDialog(std::vector<domain::ValidationError> errors);
setAttribute(Qt::WA_DeleteOnClose);
this->setWindowTitle("Upozorenje");
auto layout = new QVBoxLayout(this);
this->setLayout(layout);
layout->addWidget(new QLabel(QString::fromStdString(error.message), this));
auto buttonLayout = new QHBoxLayout(this);
auto okButton = new QPushButton("U redu", this);
auto cancelButton = new QPushButton("Odustani", this);
connect(okButton, &QPushButton::clicked, [this]() { accept(); });
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
layout->addItem(buttonLayout);
}
}; };
class WarningDialog : public QDialog {
public:
WarningDialog(domain::ValidationError error);
};
} }

View File

@ -9,31 +9,37 @@
namespace display { namespace display {
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
menu.addAction("Izmjeni ime", [this](){ menu.addAction("Izmjeni ime", [this]() {
auto dialog = new NameDialog(this->instance.get()); auto dialog = new NameDialog(this->instance.get());
dialog->exec(); dialog->exec();
});
menu.addSeparator();
for(int i=0; i<this->instance->attributes.size(); i++) {
auto* attr = &this->instance->attributes[i];
bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
[attr]() {
if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
auto dialog = new MemoryDialog(attr, MainWindow::getSchema()->componentInstances);
dialog->exec();
} else {
auto dialog = new AttributeDialog(attr);
dialog->exec();
}
}); });
action->setEnabled(enabled); menu.addSeparator();
for (int i = 0; i < this->instance->attributes.size(); i++) {
auto *attr = &this->instance->attributes[i];
bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
[attr]() {
if (attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
auto dialog = new MemoryDialog(attr,
MainWindow::getSchema()->componentInstances);
dialog->exec();
} else {
auto dialog = new AttributeDialog(attr);
dialog->exec();
}
});
action->setEnabled(enabled);
}
menu.exec(event->screenPos());
}
Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) {
setFlag(ItemSendsGeometryChanges, true);
instance->component.getDisplay().render(this);
} }
menu.exec(event->screenPos());
}
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
@ -42,11 +48,13 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
} }
void Pin::mousePressEvent(QGraphicsSceneMouseEvent *event) { void Pin::mousePressEvent(QGraphicsSceneMouseEvent *event) {
if(event->button() == Qt::MouseButton::LeftButton) { if (event->button() == Qt::MouseButton::LeftButton) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]); auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
view->state = Schema::CREATING_CONNECTION; view->state = Schema::CREATING_CONNECTION;
view->context.pin = this; view->context.pin = this;
view->context.startingPoint = dynamic_cast<ComponentGroup*>(this->parentItem())->pos() + QPointF(pin.getDisplayPin().getConnectionX(), pin.getDisplayPin().getConnectionY()); view->context.startingPoint = dynamic_cast<ComponentGroup *>(this->parentItem())->pos() +
QPointF(pin.getDisplayPin().getConnectionX(),
pin.getDisplayPin().getConnectionY());
view->context.line = new QGraphicsLineItem(QLineF(view->context.startingPoint, event->scenePos())); view->context.line = new QGraphicsLineItem(QLineF(view->context.startingPoint, event->scenePos()));
this->scene()->addItem(view->context.line); this->scene()->addItem(view->context.line);
@ -55,8 +63,8 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
} }
void Pin::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { void Pin::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]); auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
if(view->state == Schema::CREATING_CONNECTION) { if (view->state == Schema::CREATING_CONNECTION) {
auto line = view->context.line->line(); auto line = view->context.line->line();
line.setP2(event->scenePos()); line.setP2(event->scenePos());
view->context.line->setLine(line); view->context.line->setLine(line);
@ -64,8 +72,8 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
} }
void Pin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void Pin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
if(event->button() == Qt::MouseButton::LeftButton) { if (event->button() == Qt::MouseButton::LeftButton) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]); auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
view->state = Schema::DEFAULT; view->state = Schema::DEFAULT;
this->scene()->removeItem(view->context.line); this->scene()->removeItem(view->context.line);
delete view->context.line; delete view->context.line;
@ -73,14 +81,30 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
} }
} }
domain::Pin &Pin::getPin() {
return pin;
}
domain::ComponentInstance *Pin::getComponentInstance() {
return componentInstance.get();
}
void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
menu.addAction("Izmjeni ime", [this](){ menu.addAction("Izmjeni ime", [this]() {
auto dialog = new NameDialog(this->busInstance.get()); auto dialog = new NameDialog(this->busInstance.get());
dialog->exec(); dialog->exec();
}); });
menu.exec(event->screenPos()); menu.exec(event->screenPos());
} }
Bus::Bus(const std::shared_ptr<domain::BusInstance> &instance): busInstance(instance) {
instance->bus.getDisplayBus()->render(this, instance->size);
}
domain::BusInstance *Bus::getBusInstance() {
{ return busInstance.get(); }
}
QVariant BusGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { QVariant BusGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) {
if (change == ItemPositionChange && scene()) { if (change == ItemPositionChange && scene()) {
@ -89,13 +113,13 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
busInstance->position.first = newPos.x(); busInstance->position.first = newPos.x();
busInstance->position.second = newPos.y(); busInstance->position.second = newPos.y();
auto view = dynamic_cast<Schema*>(scene()->views()[0]); auto view = dynamic_cast<Schema *>(scene()->views()[0]);
view->updateConnections(); view->updateConnections();
} }
return QGraphicsItem::itemChange(change, value); return QGraphicsItem::itemChange(change, value);
} }
BusGroup::BusGroup(const std::shared_ptr<domain::BusInstance> &instance): busInstance(instance) { BusGroup::BusGroup(const std::shared_ptr<domain::BusInstance> &instance) : busInstance(instance) {
setFlag(ItemIsMovable, true); setFlag(ItemIsMovable, true);
setFlag(ItemSendsGeometryChanges, true); setFlag(ItemSendsGeometryChanges, true);
@ -105,7 +129,7 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
addToGroup(bus); addToGroup(bus);
setPos(instance->position.first, instance->position.second); setPos(instance->position.first, instance->position.second);
} }
QVariant ComponentGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { QVariant ComponentGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) {
@ -115,36 +139,43 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
componentInstance->position.first = newPos.x(); componentInstance->position.first = newPos.x();
componentInstance->position.second = newPos.y(); componentInstance->position.second = newPos.y();
auto view = dynamic_cast<Schema*>(scene()->views()[0]); auto view = dynamic_cast<Schema *>(scene()->views()[0]);
view->updateConnections(); view->updateConnections();
} }
return QGraphicsItem::itemChange(change, value); return QGraphicsItem::itemChange(change, value);
} }
void BusConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { std::shared_ptr<domain::ComponentInstance> ComponentGroup::getComponentInstance() {
QMenu menu; return componentInstance;
menu.addAction("Ukloni poveznicu", [this](){});
menu.addSeparator();
for(int i=0; i<this->connection->attributes.size(); i++) {
auto* attr = &this->connection->attributes[i];
bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
[attr]() {
auto dialog = new AttributeDialog(attr);
dialog->exec();
});
action->setEnabled(enabled);
}
menu.exec(event->screenPos());
} }
void DirectConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { std::vector<display::Pin *> &ComponentGroup::getPins() {
return pins;
}
ComponentGroup::ComponentGroup(const std::shared_ptr<domain::ComponentInstance> &instance): componentInstance(
instance) {
setFlag(ItemIsMovable, true);
setFlag(ItemSendsGeometryChanges, true);
setHandlesChildEvents(false);
addToGroup(new display::Component(instance));
for (auto &pin: instance->component.getPins()) {
pins.push_back(new display::Pin(pin, componentInstance));
addToGroup(pins.back());
}
setPos(instance->position.first, instance->position.second);
}
void BusConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
menu.addAction("Ukloni poveznicu", [this](){}); menu.addAction("Ukloni poveznicu", [this]() {});
menu.addSeparator(); menu.addSeparator();
for(int i=0; i<this->connection->attributes.size(); i++) { for (int i = 0; i < this->connection->attributes.size(); i++) {
auto* attr = &this->connection->attributes[i]; auto *attr = &this->connection->attributes[i];
bool enabled = attr->attribute.getPopup().has_value(); bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
@ -157,4 +188,69 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
menu.exec(event->screenPos()); menu.exec(event->screenPos());
} }
BusConnection::BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus): connection(
connection), component(component), bus(bus) {
updateConnection();
setHandlesChildEvents(false);
}
void BusConnection::updateConnection() {
auto busPosition = bus->boundingRect();
auto pin = connection->instance->component.getPin(
connection->connection.getComponent().pin).getDisplayPin();
setLine(connection->instance->position.first + pin.getConnectionX(),
connection->instance->position.second + pin.getConnectionY(),
connection->bus->position.first + busPosition.width() / 2,
connection->bus->position.second + busPosition.height() / 2);
connection->start.first = connection->instance->position.first + pin.getConnectionX();
connection->start.second = connection->instance->position.second + pin.getConnectionY();
connection->end.first = connection->bus->position.first + busPosition.width() / 2;
connection->end.second = connection->bus->position.second + busPosition.height() / 2;
}
void DirectConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu;
menu.addAction("Ukloni poveznicu", [this]() {});
menu.addSeparator();
for (int i = 0; i < this->connection->attributes.size(); i++) {
auto *attr = &this->connection->attributes[i];
bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
[attr]() {
auto dialog = new AttributeDialog(attr);
dialog->exec();
});
action->setEnabled(enabled);
}
menu.exec(event->screenPos());
}
DirectConnection::DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first,
ComponentGroup *second): connection(connection), first(first), second(second) {
updateConnection();
setHandlesChildEvents(false);
}
void DirectConnection::updateConnection() {
auto pin1 = connection->instance->component.getPin(
connection->connection.getComponent().pin).getDisplayPin();
auto pin2 = connection->secondInstance->component.getPin(
connection->connection.getSecondComponent()->pin).getDisplayPin();
setLine(connection->instance->position.first + pin1.getConnectionX(),
connection->instance->position.second + pin1.getConnectionY(),
connection->secondInstance->position.first + pin2.getConnectionX(),
connection->secondInstance->position.second + pin2.getConnectionY());
connection->start.first = connection->instance->position.first + pin1.getConnectionX();
connection->start.second = connection->instance->position.second + pin1.getConnectionY();
connection->end.first = connection->secondInstance->position.first + pin2.getConnectionX();
connection->end.second = connection->secondInstance->position.second + pin2.getConnectionY();
}
} // namespace display } // namespace display

View File

@ -2,169 +2,116 @@
#define DISPLAY_COMPONENT_H #define DISPLAY_COMPONENT_H
#include <comdel/domain/instance.h> #include <comdel/domain/instance.h>
#include <comdel/domain/wireinstance.h>
#include <QGraphicsItemGroup> #include <QGraphicsItemGroup>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include "comdel/domain/connectioninstance.h" #include <utility>
#include "comdel/domain/connection_instance.h"
namespace display { namespace display {
class Pin: public QGraphicsItemGroup class Pin : public QGraphicsItemGroup {
{
private:
domain::Pin pin;
std::shared_ptr<domain::ComponentInstance> componentInstance;
public:
Pin(domain::Pin pin, std::shared_ptr<domain::ComponentInstance> componentInstance): pin(pin), componentInstance(componentInstance) {
pin.getDisplayPin().render(this);
}
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
domain::Pin& getPin() {
return pin;
}
domain::ComponentInstance* getComponentInstance() {
return componentInstance.get();
}
};
class Component: public QGraphicsItemGroup
{
private:
std::shared_ptr<domain::ComponentInstance> instance;
public:
Component(const std::shared_ptr<domain::ComponentInstance>& instance): instance(instance) {
setFlag(ItemSendsGeometryChanges, true);
instance->component.getDisplay().render(this);
}
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class Bus: public QGraphicsItemGroup
{
std::shared_ptr<domain::BusInstance> busInstance;
public:
Bus(const std::shared_ptr<domain::BusInstance>& instance): busInstance(instance) {
instance->bus.getDisplayBus()->render(this, instance->size);
}
domain::BusInstance *getBusInstance() { return busInstance.get(); }
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class ComponentGroup: public QGraphicsItemGroup
{
private:
std::shared_ptr<domain::ComponentInstance> componentInstance;
std::vector<display::Pin*> pins;
public:
std::shared_ptr<domain::ComponentInstance> getComponentInstance() { return componentInstance; }
std::vector<display::Pin*>& getPins() { return pins; }
explicit ComponentGroup(const std::shared_ptr<domain::ComponentInstance>& instance): componentInstance(instance) {
setFlag(ItemIsMovable, true);
setFlag(ItemSendsGeometryChanges, true);
setHandlesChildEvents(false);
addToGroup(new display::Component(instance));
for(auto &pin: instance->component.getPins()) {
pins.push_back(new display::Pin(pin, componentInstance));
addToGroup(pins.back());
}
setPos(instance->position.first, instance->position.second);
}
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
};
class BusGroup: public QGraphicsItemGroup
{
private:
std::shared_ptr<domain::BusInstance> busInstance;
display::Bus* bus;
public:
explicit BusGroup(const std::shared_ptr<domain::BusInstance>& instance);
display::Bus* getBus() { return bus; }
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
};
class BusConnection: public QGraphicsLineItem
{
private:
domain::BusConnectionInstance* connection;
ComponentGroup* component;
BusGroup* bus;
public:
BusConnection(domain::BusConnectionInstance* connection, ComponentGroup *component, BusGroup *bus): connection(connection), component(component), bus(bus) {
updateConnection();
setHandlesChildEvents(false);
}
void updateConnection() {
auto busPosition = bus->boundingRect();
auto pin = connection->instance->component.getPin(connection->connection.getComponent().pin).getDisplayPin();
setLine(connection->instance->position.first + pin.getConnectionX(), connection->instance->position.second + pin.getConnectionY(), connection->bus->position.first + busPosition.width()/2, connection->bus->position.second + busPosition.height()/2);
connection->start.first = connection->instance->position.first + pin.getConnectionX();
connection->start.second = connection->instance->position.second + pin.getConnectionY();
connection->end.first = connection->bus->position.first + busPosition.width()/2;
connection->end.second = connection->bus->position.second + busPosition.height()/2;
}
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class DirectConnection: public QGraphicsLineItem
{
private: private:
domain::DirectConnectionInstance* connection; domain::Pin pin;
ComponentGroup* first; std::shared_ptr<domain::ComponentInstance> componentInstance;
ComponentGroup* second;
public: public:
DirectConnection(domain::DirectConnectionInstance* connection, ComponentGroup *first, ComponentGroup *second): connection(connection), first(first), second(second) { Pin(domain::Pin pin, std::shared_ptr<domain::ComponentInstance> componentInstance) : pin(pin),
updateConnection(); componentInstance(std::move(
setHandlesChildEvents(false); componentInstance)) {
pin.getDisplayPin().render(this);
this->setToolTip(QString::fromStdString(pin.getTooltip()));
} }
void updateConnection() { void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
auto pin1 = connection->instance->component.getPin(connection->connection.getComponent().pin).getDisplayPin();
auto pin2 = connection->secondInstance->component.getPin(connection->connection.getSecondComponent()->pin).getDisplayPin();
setLine(connection->instance->position.first + pin1.getConnectionX(), connection->instance->position.second + pin1.getConnectionY(), void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
connection->secondInstance->position.first + pin2.getConnectionX(), connection->secondInstance->position.second + pin2.getConnectionY());
connection->start.first = connection->instance->position.first + pin1.getConnectionX(); void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
connection->start.second = connection->instance->position.second + pin1.getConnectionY();
connection->end.first = connection->secondInstance->position.first + pin2.getConnectionX();
connection->end.second = connection->secondInstance->position.second + pin2.getConnectionY();
} void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
domain::Pin &getPin();
domain::ComponentInstance *getComponentInstance();
};
class Component : public QGraphicsItemGroup {
private:
std::shared_ptr<domain::ComponentInstance> instance;
public:
explicit Component(const std::shared_ptr<domain::ComponentInstance> &instance);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class Bus : public QGraphicsItemGroup {
std::shared_ptr<domain::BusInstance> busInstance;
public:
explicit Bus(const std::shared_ptr<domain::BusInstance> &instance);
domain::BusInstance *getBusInstance();
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class ComponentGroup : public QGraphicsItemGroup {
private:
std::shared_ptr<domain::ComponentInstance> componentInstance;
std::vector<display::Pin *> pins;
public:
std::shared_ptr<domain::ComponentInstance> getComponentInstance();
std::vector<display::Pin *> &getPins();
explicit ComponentGroup(const std::shared_ptr<domain::ComponentInstance> &instance);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};
class BusGroup : public QGraphicsItemGroup {
private:
std::shared_ptr<domain::BusInstance> busInstance;
display::Bus *bus;
public:
explicit BusGroup(const std::shared_ptr<domain::BusInstance> &instance);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};
class BusConnection : public QGraphicsLineItem {
private:
domain::BusConnectionInstance *connection;
ComponentGroup *component;
BusGroup *bus;
public:
BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus);
void updateConnection();
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};
class DirectConnection : public QGraphicsLineItem {
private:
domain::DirectConnectionInstance *connection;
ComponentGroup *first;
ComponentGroup *second;
public:
DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first, ComponentGroup *second);
void updateConnection();
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
}; };

View File

@ -6,47 +6,47 @@
namespace display { namespace display {
Library::Library() Library::Library() {
{ auto layout = new QVBoxLayout();
auto layout = new QVBoxLayout(); this->setLayout(layout);
this->setLayout(layout);
componentList = new LibraryList(this); componentList = new LibraryList(this);
busList = new LibraryList(this); busList = new LibraryList(this);
layout->setMargin(4); layout->setMargin(4);
layout->addWidget(new QLabel("Components:")); layout->addWidget(new QLabel("Components:"));
layout->addWidget(componentList, 1); layout->addWidget(componentList, 1);
layout->addSpacing(8); layout->addSpacing(8);
layout->addWidget(new QLabel("Buses:")); layout->addWidget(new QLabel("Buses:"));
layout->addWidget(busList, 1); layout->addWidget(busList, 1);
setLibrary(library); setLibrary(library);
}
void Library::setLibrary(std::optional<domain::Library> library) {
componentList->clear();
busList->clear();
if(!library) {
return;
} }
for(auto& component: library->getComponents()) { void Library::setLibrary(std::optional<domain::Library> library) {
auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), componentList};
item->setToolTip(QString::fromStdString(component.getTooltip()));
componentList->addItem(item);
}
for(auto& bus: library->getBuses()) { componentList->clear();
if(bus.getType() == domain::Bus::REGULAR) { busList->clear();
auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList};
item->setToolTip(QString::fromStdString(bus.getTooltip())); if (!library) {
busList->addItem(item); return;
} }
}
} for (auto &component: library->getComponents()) {
auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(),
componentList};
item->setToolTip(QString::fromStdString(component.getTooltip()));
componentList->addItem(item);
}
for (auto &bus: library->getBuses()) {
if (bus.getType() == domain::Bus::REGULAR) {
auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList};
item->setToolTip(QString::fromStdString(bus.getTooltip()));
busList->addItem(item);
}
}
}
} // namespace display } // namespace display

View File

@ -9,20 +9,19 @@
namespace display { namespace display {
class Library: public QWidget class Library : public QWidget {
{ public:
public: Library();
Library();
void setLibrary(std::optional<domain::Library> library); void setLibrary(std::optional<domain::Library> library);
private: private:
std::optional<domain::Library> library; std::optional<domain::Library> library;
LibraryList *componentList; LibraryList *componentList;
LibraryList *busList; LibraryList *busList;
}; };
} // namespace display } // namespace display

View File

@ -10,22 +10,23 @@
namespace display { namespace display {
LibraryList::LibraryList(QWidget *parent): QListWidget(parent) { LibraryList::LibraryList(QWidget *parent) : QListWidget(parent) {
setDragDropMode(DragOnly); setDragDropMode(DragOnly);
} }
QMimeData *LibraryList::mimeData(const QList<QListWidgetItem *> items) const { QMimeData *LibraryList::mimeData(const QList<QListWidgetItem *> items) const {
for(auto qItem: items) { for (auto qItem: items) {
// we only allow one item to be dragged at a time // we only allow one item to be dragged at a time
auto item = dynamic_cast<LibraryListItem*>(qItem); auto item = dynamic_cast<LibraryListItem *>(qItem);
auto* md = new QMimeData(); auto *md = new QMimeData();
md->setData(QString::fromStdString(item->mimeType), QByteArray::fromStdString(item->value)); md->setData(QString::fromStdString(item->mimeType), QByteArray::fromStdString(item->value));
return md; return md;
} }
return nullptr; return nullptr;
} }
LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent): QListWidgetItem(parent), mimeType(mimeType), value(value) { LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent)
: QListWidgetItem(parent), mimeType(mimeType), value(value) {
setText(QString::fromStdString(title)); setText(QString::fromStdString(title));
} }
} // display } // display

View File

@ -11,16 +11,16 @@
namespace display { namespace display {
class LibraryList: public QListWidget { class LibraryList : public QListWidget {
Q_OBJECT Q_OBJECT
public: public:
LibraryList(QWidget *parent); LibraryList(QWidget *parent);
protected: protected:
QMimeData *mimeData(const QList<QListWidgetItem*> items) const override; QMimeData *mimeData(const QList<QListWidgetItem *> items) const override;
}; };
class LibraryListItem: public QListWidgetItem { class LibraryListItem : public QListWidgetItem {
public: public:
std::string mimeType; std::string mimeType;

View File

@ -3,3 +3,40 @@
// //
#include "name_dialog.h" #include "name_dialog.h"
display::NameDialog::NameDialog(domain::ComponentInstance *instance) : componentInstance(instance) {
auto *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("Izmjeni ime", this));
edit = new QLineEdit(this);
edit->insert(instance->name.c_str());
layout->addWidget(edit);
this->setWindowTitle("Izmjeni ime");
auto *button = new QPushButton("Ažuriraj", this);
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
layout->addWidget(button);
this->setLayout(layout);
}
display::NameDialog::NameDialog(domain::BusInstance *instance): busInstance(instance) {
auto *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("Izmjeni ime", this));
edit = new QLineEdit(this);
edit->insert(instance->name.c_str());
layout->addWidget(edit);
this->setWindowTitle("Izmjeni ime");
auto *button = new QPushButton("Ažuriraj", this);
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
layout->addWidget(button);
this->setLayout(layout);
}
void display::NameDialog::onNameChange() {
if (componentInstance != nullptr) {
componentInstance->name = this->edit->text().toStdString();
} else if (busInstance != nullptr) {
busInstance->name = this->edit->text().toStdString();
}
this->close();
}

View File

@ -11,52 +11,22 @@
namespace display { namespace display {
class NameDialog: public QDialog { class NameDialog : public QDialog {
QLineEdit *edit = nullptr; QLineEdit *edit = nullptr;
domain::ComponentInstance *componentInstance = nullptr; domain::ComponentInstance *componentInstance = nullptr;
domain::BusInstance *busInstance = nullptr; domain::BusInstance *busInstance = nullptr;
public: public:
NameDialog(domain::ComponentInstance *instance): componentInstance(instance) { NameDialog(domain::ComponentInstance *instance);
auto *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("Izmjeni ime", this));
edit = new QLineEdit(this); NameDialog(domain::BusInstance *instance);
edit->insert(instance->name.c_str());
layout->addWidget(edit);
this->setWindowTitle("Izmjeni ime");
auto *button = new QPushButton("Ažuriraj", this);
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
layout->addWidget(button);
this->setLayout(layout);
}
NameDialog(domain::BusInstance *instance): busInstance(instance) { public slots:
auto *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("Izmjeni ime", this));
edit = new QLineEdit(this); void onNameChange();
edit->insert(instance->name.c_str()); };
layout->addWidget(edit);
this->setWindowTitle("Izmjeni ime");
auto *button = new QPushButton("Ažuriraj", this);
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
layout->addWidget(button);
this->setLayout(layout);
}
public slots:
void onNameChange() {
if(componentInstance != nullptr) {
componentInstance->name = this->edit->text().toStdString();
} else if(busInstance != nullptr) {
busInstance->name = this->edit->text().toStdString();
}
this->close();
}
};
} }

View File

@ -7,96 +7,98 @@
namespace display { namespace display {
Schema::Schema() Schema::Schema() {
{ this->selectedBrush.setColor(QColor::fromRgb(20, 20, 125));
this->selectedBrush.setColor(QColor::fromRgb(20,20,125)); this->selectedPen.setColor(QColor::fromRgb(20, 20, 125));
this->selectedPen.setColor(QColor::fromRgb(20, 20, 125));
this->setScene(&scene); this->setScene(&scene);
this->setAcceptDrops(true); this->setAcceptDrops(true);
} }
void Schema::setSchema(domain::Schema* _schema, domain::Library* _library) void Schema::setSchema(domain::Schema *_schema, domain::Library *_library) {
{ components.clear();
components.clear(); buses.clear();
buses.clear();
scene.clear(); scene.clear();
busConnections.clear(); busConnections.clear();
this->schema = _schema; this->schema = _schema;
this->library = _library; this->library = _library;
if(schema != nullptr) { if (schema != nullptr) {
for(auto &instance: schema->componentInstances) { for (auto &instance: schema->componentInstances) {
auto group = new display::ComponentGroup(instance); auto group = new display::ComponentGroup(instance);
for(auto pin: group->getPins()) { for (auto pin: group->getPins()) {
display::Pin* p = pin; display::Pin *p = pin;
domain::ConnectionComponent connection{instance->name, p->getPin().getName()}; domain::ConnectionComponent connection{instance->name, p->getPin().getName()};
pins.insert(std::make_pair(connection, p)); pins.insert(std::make_pair(connection, p));
} }
components.insert(std::make_pair(instance->name, group)); components.insert(std::make_pair(instance->name, group));
scene.addItem(group);
}
for(auto &instance: schema->busInstances) {
if(instance->bus.getDisplayBus().has_value()) {
auto group = new display::BusGroup(instance);
buses.insert(std::make_pair(instance->name, group));
scene.addItem(group); scene.addItem(group);
} }
} for (auto &instance: schema->busInstances) {
for(auto &connection: schema->connections) { if (instance->bus.getDisplayBus().has_value()) {
auto busInstance = dynamic_cast<domain::BusConnectionInstance*>(connection.get()); auto group = new display::BusGroup(instance);
if(busInstance != nullptr) { buses.insert(std::make_pair(instance->name, group));
auto con = new display::BusConnection(busInstance, components[busInstance->instance->name], buses[busInstance->bus->name]); scene.addItem(group);
busConnections.push_back(con); }
scene.addItem(con);
} }
auto directInstance = dynamic_cast<domain::DirectConnectionInstance*>(connection.get()); for (auto &connection: schema->connections) {
if(directInstance != nullptr) { auto busInstance = dynamic_cast<domain::BusConnectionInstance *>(connection.get());
auto con = new display::DirectConnection(directInstance, components[directInstance->instance->name], components[directInstance->secondInstance->name]); if (busInstance != nullptr) {
directConnections.push_back(con); auto con = new display::BusConnection(busInstance, components[busInstance->instance->name],
scene.addItem(con); buses[busInstance->bus->name]);
busConnections.push_back(con);
scene.addItem(con);
}
auto directInstance = dynamic_cast<domain::DirectConnectionInstance *>(connection.get());
if (directInstance != nullptr) {
auto con = new display::DirectConnection(directInstance, components[directInstance->instance->name],
components[directInstance->secondInstance->name]);
directConnections.push_back(con);
scene.addItem(con);
}
} }
} }
} }
}
void Schema::updateConnections() { void Schema::updateConnections() {
if(schema != nullptr) { if (schema != nullptr) {
for(auto conn: busConnections) { for (auto conn: busConnections) {
conn->updateConnection(); conn->updateConnection();
} }
for(auto conn: directConnections) { for (auto conn: directConnections) {
conn->updateConnection(); conn->updateConnection();
}
} }
} }
}
void Schema::dragEnterEvent(QDragEnterEvent *event) { void Schema::dragEnterEvent(QDragEnterEvent *event) {
if(event->mimeData()->hasFormat("comdel/component") || if (event->mimeData()->hasFormat("comdel/component") ||
event->mimeData()->hasFormat("comdel/bus")) { event->mimeData()->hasFormat("comdel/bus")) {
event->acceptProposedAction(); event->acceptProposedAction();
} }
} }
void Schema::dropEvent(QDropEvent *event) { void Schema::dropEvent(QDropEvent *event) {
if(event->mimeData()->hasFormat("comdel/component")) { if (event->mimeData()->hasFormat("comdel/component")) {
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString()); auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
auto attributes = std::vector<domain::InstanceAttribute>(); auto attributes = std::vector<domain::InstanceAttribute>();
for(auto attr: component.getAttributes()) { for (auto attr: component.getAttributes()) {
attributes.emplace_back(attr.getName(), attr.getDefault(), attr); attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
} }
auto currentPos = this->mapToScene(event->pos()); auto currentPos = this->mapToScene(event->pos());
auto instance = std::make_shared<domain::ComponentInstance>(component.getInstanceName(), attributes, std::make_pair(currentPos.x(), currentPos.y()), component); auto instance = std::make_shared<domain::ComponentInstance>(component.getInstanceName(), attributes,
std::make_pair(currentPos.x(), currentPos.y()),
component);
schema->componentInstances.push_back(instance); schema->componentInstances.push_back(instance);
auto group = new display::ComponentGroup(instance); auto group = new display::ComponentGroup(instance);
scene.addItem(group); scene.addItem(group);
for(auto pin: group->getPins()) { for (auto pin: group->getPins()) {
display::Pin* p = pin; display::Pin *p = pin;
domain::ConnectionComponent connection{instance->name, p->getPin().getName()}; domain::ConnectionComponent connection{instance->name, p->getPin().getName()};
pins.insert(std::make_pair(connection, p)); pins.insert(std::make_pair(connection, p));
} }
@ -105,12 +107,13 @@ void Schema::updateConnections() {
event->acceptProposedAction(); event->acceptProposedAction();
} }
if(event->mimeData()->hasFormat("comdel/bus")) { if (event->mimeData()->hasFormat("comdel/bus")) {
auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString()); auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString());
auto currentPos = this->mapToScene(event->pos()); auto currentPos = this->mapToScene(event->pos());
auto instance = std::make_shared<domain::BusInstance>(bus.getName(), std::make_pair(currentPos.x(), currentPos.y()), bus); auto instance = std::make_shared<domain::BusInstance>(bus.getName(),
std::make_pair(currentPos.x(), currentPos.y()), bus);
schema->busInstances.push_back(instance); schema->busInstances.push_back(instance);
auto group = new display::BusGroup(instance); auto group = new display::BusGroup(instance);
@ -127,19 +130,19 @@ void Schema::updateConnections() {
void Schema::removeConnectable(QPointF endPoint) { void Schema::removeConnectable(QPointF endPoint) {
auto instance = context.pin->getComponentInstance(); auto instance = context.pin->getComponentInstance();
auto& pin = context.pin->getPin(); auto &pin = context.pin->getPin();
auto busInstances = getAvailableConnectionBusses(instance, pin); auto busInstances = getAvailableConnectionBusses(instance, pin);
for(auto &bus: busInstances) { for (auto &bus: busInstances) {
auto rect = buses[bus->name]->boundingRect(); auto rect = buses[bus->name]->boundingRect();
rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height()); rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height());
if(rect.contains(endPoint)) { if (rect.contains(endPoint)) {
auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName()); auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName());
if(con.has_value()) { if (con.has_value()) {
std::vector<domain::InstanceAttribute> attributes; std::vector<domain::InstanceAttribute> attributes;
for(auto attr: con->getAttributes()) { for (auto attr: con->getAttributes()) {
attributes.emplace_back(attr.getName(), attr.getDefault(), attr); attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
} }
@ -148,7 +151,7 @@ void Schema::updateConnections() {
if (conInstance != nullptr) { if (conInstance != nullptr) {
auto c = new display::BusConnection(conInstance.get(), components[conInstance->instance->name], auto c = new display::BusConnection(conInstance.get(), components[conInstance->instance->name],
buses[conInstance->bus->name]); buses[conInstance->bus->name]);
busConnections.push_back(c); busConnections.push_back(c);
scene.addItem(c); scene.addItem(c);
} }
@ -159,29 +162,35 @@ void Schema::updateConnections() {
auto pinInstances = getAvailableConnectionPins(instance, pin); auto pinInstances = getAvailableConnectionPins(instance, pin);
for(auto &pinInstance: pinInstances) { for (auto &pinInstance: pinInstances) {
auto rect = pins[pinInstance]->boundingRect(); auto rect = pins[pinInstance]->boundingRect();
rect.setX(pins[pinInstance]->scenePos().x()); rect.setX(pins[pinInstance]->scenePos().x());
rect.setY(pins[pinInstance]->scenePos().y()); rect.setY(pins[pinInstance]->scenePos().y());
if(rect.contains(endPoint)) { if (rect.contains(endPoint)) {
auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); auto name = components[pinInstance.component]->getComponentInstance()->component.getName();
auto con = library->getConnection({instance->component.getName(), pin.getName()}, {name, pinInstance.pin}); auto con = library->getConnection({instance->component.getName(), pin.getName()},
if(con.has_value()) { {name, pinInstance.pin});
if (con.has_value()) {
auto bus = library->getBus(con->getBus()); auto bus = library->getBus(con->getBus());
auto busInstance = std::make_shared<domain::BusInstance>(bus.getName(), bus); auto busInstance = std::make_shared<domain::BusInstance>(bus.getName(), bus);
schema->busInstances.push_back(busInstance); schema->busInstances.push_back(busInstance);
std::vector<domain::InstanceAttribute> attributes; std::vector<domain::InstanceAttribute> attributes;
for(auto attr: con->getAttributes()) { for (auto attr: con->getAttributes()) {
attributes.emplace_back(attr.getName(), attr.getDefault(), attr); attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
} }
auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance, components[pinInstance.component]->getComponentInstance().get(), attributes, busInstance.get(), *con); auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
components[pinInstance.component]->getComponentInstance().get(),
attributes, busInstance.get(),
*con);
schema->connections.push_back(conInstance); schema->connections.push_back(conInstance);
if (conInstance != nullptr) { if (conInstance != nullptr) {
auto c = new display::DirectConnection(conInstance.get(), components[conInstance->instance->name], components[conInstance->secondInstance->name]); auto c = new display::DirectConnection(conInstance.get(),
components[conInstance->instance->name],
components[conInstance->secondInstance->name]);
directConnections.push_back(c); directConnections.push_back(c);
scene.addItem(c); scene.addItem(c);
} }
@ -193,7 +202,7 @@ void Schema::updateConnections() {
updateConnections(); updateConnections();
for(auto& item: this->context.selectable) { for (auto &item: this->context.selectable) {
this->scene.removeItem(item); this->scene.removeItem(item);
delete item; delete item;
} }
@ -201,12 +210,12 @@ void Schema::updateConnections() {
} }
void Schema::showConnectable(Pin *domainPin) { void Schema::showConnectable(Pin *domainPin) {
auto& pin = domainPin->getPin(); auto &pin = domainPin->getPin();
auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin()); auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin());
for(auto bus: busInstances) { for (auto bus: busInstances) {
auto& group = buses[bus->name]; auto &group = buses[bus->name];
auto rect = new QGraphicsRectItem(group->boundingRect()); auto rect = new QGraphicsRectItem(group->boundingRect());
rect->setPen(selectedPen); rect->setPen(selectedPen);
rect->setPos(group->scenePos()); rect->setPos(group->scenePos());
@ -220,10 +229,11 @@ void Schema::updateConnections() {
scene.addItem(rect); scene.addItem(rect);
} }
std::vector<domain::ConnectionComponent> pinInstances = getAvailableConnectionPins(domainPin->getComponentInstance(), domainPin->getPin()); std::vector<domain::ConnectionComponent> pinInstances = getAvailableConnectionPins(
domainPin->getComponentInstance(), domainPin->getPin());
for(auto& pinInstance: pinInstances) { for (auto &pinInstance: pinInstances) {
auto& instance = pins[pinInstance]; auto &instance = pins[pinInstance];
auto rect = new QGraphicsRectItem(instance->boundingRect()); auto rect = new QGraphicsRectItem(instance->boundingRect());
rect->setPen(selectedPen); rect->setPen(selectedPen);
rect->setPos(instance->scenePos()); rect->setPos(instance->scenePos());
@ -239,22 +249,25 @@ void Schema::updateConnections() {
} }
std::vector<domain::BusInstance*> Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) { std::vector<domain::BusInstance *>
std::vector<domain::BusInstance*> instances; Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) {
for(const auto& bus: schema->busInstances) { std::vector<domain::BusInstance *> instances;
if(library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()}, bus->bus.getName())) { for (const auto &bus: schema->busInstances) {
if (library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()},
bus->bus.getName())) {
instances.push_back(bus.get()); instances.push_back(bus.get());
} }
} }
return instances; return instances;
} }
std::vector<domain::ConnectionComponent> Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) { std::vector<domain::ConnectionComponent>
Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) {
std::vector<domain::ConnectionComponent> instances; std::vector<domain::ConnectionComponent> instances;
domain::ConnectionComponent source{instance->component.getName(), pin.getName()}; domain::ConnectionComponent source{instance->component.getName(), pin.getName()};
for(const auto& entry: pins) { for (const auto &entry: pins) {
std::string name = components[entry.first.component]->getComponentInstance()->component.getName(); std::string name = components[entry.first.component]->getComponentInstance()->component.getName();
if(library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) { if (library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) {
instances.push_back(entry.first); instances.push_back(entry.first);
} }
} }

View File

@ -14,64 +14,67 @@ namespace display {
class BusConnection; class BusConnection;
class Schema: public QGraphicsView class Schema : public QGraphicsView {
{
Q_OBJECT Q_OBJECT
public: public:
QBrush selectedBrush; QBrush selectedBrush;
QPen selectedPen; QPen selectedPen;
enum State { enum State {
DEFAULT, DEFAULT,
CREATING_CONNECTION CREATING_CONNECTION
};
struct Context {
display::Pin *pin = nullptr;
QPointF startingPoint;
QGraphicsLineItem *line = nullptr;
std::vector<QGraphicsRectItem *> selectable;
};
std::map<std::string, display::ComponentGroup *> components;
std::map<std::string, display::BusGroup *> buses;
std::map<domain::ConnectionComponent, display::Pin *> pins;
State state = DEFAULT;
Context context;
Schema();
std::vector<BusConnection *> busConnections;
std::vector<DirectConnection *> directConnections;
void setSchema(domain::Schema *schema, domain::Library *library);
void updateConnections();
void removeConnectable(QPointF f);
void showConnectable(Pin *pin);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
private:
QGraphicsScene scene;
domain::Schema *schema;
domain::Library *library;
std::vector<domain::BusInstance *>
getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin);
std::vector<domain::ConnectionComponent>
getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin);
}; };
struct Context {
display::Pin *pin = nullptr;
QPointF startingPoint;
QGraphicsLineItem *line = nullptr;
std::vector<QGraphicsRectItem*> selectable;
};
std::map<std::string, display::ComponentGroup*> components;
std::map<std::string, display::BusGroup*> buses;
std::map<domain::ConnectionComponent, display::Pin*> pins;
State state = DEFAULT;
Context context;
Schema();
std::vector<BusConnection*> busConnections;
std::vector<DirectConnection*> directConnections;
void setSchema(domain::Schema* schema, domain::Library* library);
void updateConnections();
void removeConnectable(QPointF f);
void showConnectable(Pin *pin);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
private:
QGraphicsScene scene;
domain::Schema* schema;
domain::Library* library;
std::vector<domain::BusInstance*> getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin);
std::vector<domain::ConnectionComponent> getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin);
};
} // namespace display } // namespace display
#endif // DISPLAY_SCHEMA_H #endif // DISPLAY_SCHEMA_H

View File

@ -0,0 +1,29 @@
#include <algorithm>
#include "address_space.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() const {
return start;
}
long long AddressSpace::getEnd() const {
return end;
}
bool AddressSpace::contains(long long int address) {
return address >= start && address < end;
}
bool AddressSpace::contains(long long int pstart, long long int pend) {
return pstart >= start && pend < end;
}
} // namespace domain

View File

@ -0,0 +1,29 @@
#ifndef DOMAIN_ADDRESS_SPACE_H
#define DOMAIN_ADDRESS_SPACE_H
#include <string>
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() const;
long long getEnd() const;
bool contains(long long int address);
bool contains(long long int start, long long int end);
};
} // namespace domain
#endif // DOMAIN_ADDRESS_SPACE_H

View File

@ -1,28 +0,0 @@
#include <algorithm>
#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() const {
return start;
}
long long AddressSpace::getEnd() const {
return end;
}
bool AddressSpace::contains(long long int address) {
return address >= start && address < end;
}
bool AddressSpace::contains(long long int pstart, long long int pend) {
return pstart >= start && pend < end;
}
} // namespace domain

View File

@ -1,27 +0,0 @@
#ifndef DOMAIN_ADDRESS_SPACE_H
#define DOMAIN_ADDRESS_SPACE_H
#include <string>
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() const;
long long getEnd() const;
bool contains(long long int address);
bool contains(long long int start, long long int end);
};
} // namespace domain
#endif // DOMAIN_ADDRESS_SPACE_H

View File

@ -2,55 +2,61 @@
namespace domain { namespace domain {
Enumeration::Enumeration(std::string name, Value value) Enumeration::Enumeration(std::string name, Value value)
: name(name), value(value) : name(name), value(value) {}
{}
std::string& Enumeration::getName() { std::string &Enumeration::getName() {
return name; return name;
} }
Value Enumeration::getValue() {
return value; Value Enumeration::getValue() {
} return value;
}
Popup::Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration) Popup::Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules,
: title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), enumeration(enumeration) std::vector<Enumeration> enumeration)
{} : title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0),
enumeration(enumeration) {}
std::string Popup::getTitle() { std::string Popup::getTitle() {
return title; return title;
} }
std::string Popup::getText() {
return text;
}
Popup::PopupType Popup::getType() {
return type;
}
std::vector<Rule> Popup::getRules() {
return rules;
}
bool Popup::isEnumerated() { std::string Popup::getText() {
return enumerated; return text;
} }
std::vector<Enumeration> &Popup::getEnumeration() {
return enumeration; Popup::PopupType Popup::getType() {
} return type;
}
std::vector<Rule> Popup::getRules() {
return rules;
}
bool Popup::isEnumerated() {
return enumerated;
}
std::vector<Enumeration> &Popup::getEnumeration() {
return enumeration;
}
Attribute::Attribute(std::string name, Value defaultValue, std::optional<Popup> popup) Attribute::Attribute(std::string name, Value defaultValue, std::optional<Popup> popup)
: name(name), defaultValue(defaultValue), popup(popup) : name(name), defaultValue(defaultValue), popup(popup) {}
{}
std::string Attribute::getName() { std::string Attribute::getName() {
return name; return name;
} }
Value Attribute::getDefault() {
return defaultValue; Value Attribute::getDefault() {
} return defaultValue;
std::optional<Popup> Attribute::getPopup() { }
return popup;
} std::optional<Popup> Attribute::getPopup() {
return popup;
}
} // namespace domain } // namespace domain

View File

@ -9,62 +9,69 @@
namespace domain { namespace domain {
class Enumeration { class Enumeration {
std::string name; std::string name;
Value value; Value value;
public: public:
Enumeration(std::string name, Value value); Enumeration(std::string name, Value value);
std::string& getName(); std::string &getName();
Value getValue();
};
class Popup { Value getValue();
public:
enum PopupType {
AUTOMATIC,
ON_DEMAND
}; };
private: class Popup {
std::string title; public:
std::string text; enum PopupType {
PopupType type; AUTOMATIC,
ON_DEMAND
};
bool enumerated; private:
std::vector<Enumeration> enumeration; std::string title;
std::vector<Rule> rules; std::string text;
PopupType type;
public: bool enumerated;
Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration); std::vector<Enumeration> enumeration;
std::vector<Rule> rules;
std::string getTitle(); public:
std::string getText(); Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules,
PopupType getType(); std::vector<Enumeration> enumeration);
std::vector<Rule> getRules();
bool isEnumerated(); std::string getTitle();
std::vector<Enumeration> &getEnumeration();
void setEnumeration(std::vector<Enumeration> enums) { std::string getText();
enumerated = true;
enumeration = std::move(enums);
}
}; PopupType getType();
class Attribute std::vector<Rule> getRules();
{
std::string name;
Value defaultValue;
std::optional<Popup> popup;
public:
Attribute(std::string name, Value defaultValue, std::optional<Popup> popup = std::nullopt);
std::string getName(); bool isEnumerated();
Value getDefault();
std::optional<Popup> getPopup(); std::vector<Enumeration> &getEnumeration();
};
void setEnumeration(std::vector<Enumeration> enums) {
enumerated = true;
enumeration = std::move(enums);
}
};
class Attribute {
std::string name;
Value defaultValue;
std::optional<Popup> popup;
public:
Attribute(std::string name, Value defaultValue, std::optional<Popup> popup = std::nullopt);
std::string getName();
Value getDefault();
std::optional<Popup> getPopup();
};
} // namespace domain } // namespace domain

View File

@ -2,51 +2,60 @@
namespace domain { namespace domain {
Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith) Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith)
: name(name), type(type), width(width), hidden(hidden), hasTerminate(hasTerminate), terminateWith(terminateWith) : name(name), type(type), width(width), hidden(hidden), hasTerminate(hasTerminate),
{} terminateWith(terminateWith) {}
std::string Wire::getName() { std::string Wire::getName() {
return name; return name;
} }
int Wire::getWidth() {
return width;
}
bool Wire::isHidden() {
return hidden;
}
bool Wire::hasTerminateWith() { int Wire::getWidth() {
return hasTerminate; return width;
} }
Value Wire::getTerminateWith() {
return terminateWith;
}
Wire::WireType Wire::getType() {
return type;
}
Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires, std::optional<ui::Bus> displayBus) bool Wire::isHidden() {
: name(name), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) return hidden;
{} }
std::string Bus::getName() { bool Wire::hasTerminateWith() {
return name; return hasTerminate;
} }
std::string Bus::getTooltip() {
return tooltip; Value Wire::getTerminateWith() {
} return terminateWith;
Bus::BusType Bus::getType() { }
return type;
} Wire::WireType Wire::getType() {
std::pair<int, int> Bus::getCount() { return type;
return count; }
}
std::vector<Wire> Bus::getWires() { Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
return wires; std::optional<ui::Bus> displayBus)
} : name(name), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {}
std::optional<ui::Bus> Bus::getDisplayBus() {
return displayBus; std::string Bus::getName() {
} return name;
}
std::string Bus::getTooltip() {
return tooltip;
}
Bus::BusType Bus::getType() {
return type;
}
std::pair<int, int> Bus::getCount() {
return count;
}
std::vector<Wire> Bus::getWires() {
return wires;
}
std::optional<ui::Bus> Bus::getDisplayBus() {
return displayBus;
}
} // namespace domain } // namespace domain

View File

@ -11,63 +11,72 @@
namespace domain { namespace domain {
class Wire class Wire {
{ public:
public: enum WireType {
enum WireType { WIRE_DEFAULT,
WIRE_DEFAULT, WIRED_AND,
WIRED_AND, WIRED_OR,
WIRED_OR, R_WIRE
R_WIRE };
private:
std::string name;
WireType type;
int width;
bool hidden;
bool hasTerminate;
Value terminateWith;
public:
Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith);
std::string getName();
int getWidth();
bool isHidden();
bool hasTerminateWith();
Value getTerminateWith();
WireType getType();
}; };
class Bus {
public:
enum BusType {
AUTOMATIC,
REGULAR,
SINGLE_AUTOMATIC
};
private:
std::string name;
std::string tooltip;
BusType type;
private: std::pair<int, int> count;
std::string name; std::optional<ui::Bus> displayBus;
WireType type; std::vector<Wire> wires;
int width;
bool hidden;
bool hasTerminate;
Value terminateWith;
public: public:
Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith); Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
std::optional<ui::Bus> display = std::nullopt);
std::string getName(); std::string getName();
int getWidth();
bool isHidden();
bool hasTerminateWith();
Value getTerminateWith();
WireType getType();
};
class Bus std::string getTooltip();
{
public: BusType getType();
enum BusType {
AUTOMATIC, std::pair<int, int> getCount();
REGULAR,
SINGLE_AUTOMATIC std::vector<Wire> getWires();
std::optional<ui::Bus> getDisplayBus();
}; };
private:
std::string name;
std::string tooltip;
BusType type;
std::pair<int, int> count;
std::optional<ui::Bus> displayBus;
std::vector<Wire> wires;
public:
Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires, std::optional<ui::Bus> display = std::nullopt);
std::string getName();
std::string getTooltip();
BusType getType();
std::pair<int, int> getCount();
std::vector<Wire> getWires();
std::optional<ui::Bus> getDisplayBus();
};
} // namespace domain } // namespace domain

View File

@ -7,345 +7,361 @@
namespace domain { namespace domain {
void generateSchemaFile(std::string& librarySource, Schema *schema, std::ostream &buffer) { void generate_schema(std::string &librarySource, Schema *schema, std::ostream &buffer) {
buffer << "@source " << librarySource << std::endl << std::endl; buffer << "@source \"" << librarySource << "\"" << std::endl << std::endl;
buffer << "@schema {" << std::endl; buffer << "@schema {" << std::endl;
for(auto &componentInstance: schema->componentInstances) { for (auto &componentInstance: schema->componentInstances) {
buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() << " {" << std::endl; buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName()
buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " << componentInstance->position.second << ")" << std::endl; << " {" << std::endl;
buffer << "\t\t" << "@position (" << componentInstance->position.first << ", "
<< componentInstance->position.second << ")" << std::endl;
for(auto &attribute: componentInstance->attributes) { for (auto &attribute: componentInstance->attributes) {
buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl;
}
buffer << "\t}" << std::endl << std::endl;
}
for(auto &busInstance: schema->busInstances) {
buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {" << std::endl;
buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second << ")" << std::endl;
buffer << "\t\t" << "@size " << busInstance->size << std::endl;
buffer << "\t}" << std::endl << std::endl;
}
for(auto &conn: schema->connections) {
auto busConn = dynamic_cast<domain::BusConnectionInstance*>(conn.get());
if(busConn) {
buffer << "\t" << "@connection (" << busConn->instance->name << "." << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl;
for(auto attribute: busConn->attributes) {
buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl;
} }
buffer << "\t" << "}" << std::endl; buffer << "\t}" << std::endl << std::endl;
} }
auto dirConn = dynamic_cast<domain::DirectConnectionInstance*>(conn.get());
if(dirConn) {
buffer << "\t" << "@connection (" << dirConn->instance->name << "." << dirConn->connection.getComponent().pin << ", "
<< dirConn->bus->name << ", "
<< dirConn->secondInstance->name << "." << dirConn->connection.getSecondComponent()->pin
<< ") {" << std::endl;
for(auto attribute: dirConn->attributes) { for (auto &busInstance: schema->busInstances) {
buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {"
<< std::endl;
buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second
<< ")" << std::endl;
buffer << "\t\t" << "@size " << busInstance->size << std::endl;
buffer << "\t}" << std::endl << std::endl;
}
for (auto &conn: schema->connections) {
auto busConn = dynamic_cast<domain::BusConnectionInstance *>(conn.get());
if (busConn) {
buffer << "\t" << "@connection (" << busConn->instance->name << "."
<< busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl;
for (auto attribute: busConn->attributes) {
buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify()
<< std::endl;
}
buffer << "\t" << "}" << std::endl;
} }
auto dirConn = dynamic_cast<domain::DirectConnectionInstance *>(conn.get());
if (dirConn) {
buffer << "\t" << "@connection (" << dirConn->instance->name << "."
<< dirConn->connection.getComponent().pin << ", "
<< dirConn->bus->name << ", "
<< dirConn->secondInstance->name << "." << dirConn->connection.getSecondComponent()->pin
<< ") {" << std::endl;
buffer << "\t" << "}" << std::endl; for (auto attribute: dirConn->attributes) {
buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify()
<< std::endl;
}
buffer << "\t" << "}" << std::endl;
}
}
buffer << "}" << std::endl;
}
std::set<std::string> createImports(Schema *schema);
std::map<string, string> generateWires(Schema *schema, ostream &ostream);
void generateSubComponents(Schema *schema, map<string, string> &wires, ostream &buffer);
void generateDisplay(Schema *schema, ostream &buffer);
void generate_comdel(Schema *schema, Library &library, std::ostream &buffer) {
buffer << library.getHeader() << std::endl;
std::set<std::string> imports = createImports(schema);
for (auto &import: imports) {
buffer << "#include \"" << library.getComponentDirectory() << "\\" << import << "\"" << std::endl;
}
buffer << "\n\n" << std::endl;
buffer << "component System" << std::endl << "{" << std::endl;
if (library.getComponentHeader().has_value()) {
buffer << library.getComponentHeader().value() << endl;
}
auto wires = generateWires(schema, buffer);
generateSubComponents(schema, wires, buffer);
generateDisplay(schema, buffer);
buffer << "}";
}
void generateBus(BusInstance *bus, ostream &buffer);
void generateConnection(ConnectionInstance *connection, ostream &buffer);
void generateDisplay(Schema *schema, ostream &buffer) {
buffer << "\n\tdisplay {\n";
for (auto &component: schema->componentInstances) {
buffer << "\t\tcomponent { x: " << component->position.first << "; y: " << component->position.second
<< "; ref: \"" << component->name << "\"; }" << std::endl;
}
for (auto &bus: schema->busInstances) {
generateBus(bus.get(), buffer);
}
buffer << "\n";
for (auto &connection: schema->connections) {
generateConnection(connection.get(), buffer);
}
buffer << "\t}\n";
}
void generateConnection(ConnectionInstance *connection, ostream &buffer) {
buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " <<
"x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n";
}
void generateBus(BusInstance *bus, ostream &buffer) {
buffer << "\n";
buffer << "\t\t// " << bus->name << " bus\n\n";
if (bus->bus.getDisplayBus().has_value()) {
bus->bus.getDisplayBus()->comdel(buffer, bus->position.first, bus->position.second, bus->size);
} }
} }
buffer << "}" << std::endl; void generateWire(std::string &name, Wire &wire, ostream &buffer);
}
std::set<std::string> createImports(Schema *schema); std::map<string, string> generateWires(Schema *schema, ostream &buffer) {
std::set<string> usedNames;
std::map<string, string> usedMappings;
for (auto &bus: schema->busInstances) {
buffer << "\t//" << bus->name << std::endl;
for (auto &wire: bus->bus.getWires()) {
std::string name = wire.getName();
if (usedNames.count(wire.getName()) > 0) {
name = bus->name + "__" + wire.getName();
}
if (wire.isHidden()) {
name = "--" + name;
}
usedNames.insert(name);
usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name));
std::map<string, string> generateWires(Schema *schema, ostream &ostream); generateWire(name, wire, buffer);
void generateSubComponents(Schema *schema, map <string, string> &wires, ostream &buffer);
void generateDisplay(Schema *schema, ostream &buffer);
void generateComdelFile(Schema *schema, Library &library, std::ostream &buffer) {
buffer << library.getHeader() << std::endl;
std::set<std::string> imports = createImports(schema);
for(auto& import: imports) {
buffer << "#include \"" << library.getComponentDirectory() << "\\" << import << "\"" << std::endl;
}
buffer << "\n\n" << std::endl;
buffer << "component System" << std::endl << "{" << std::endl;
if(library.getComponentHeader().has_value()) {
buffer << library.getComponentHeader().value() << endl;
}
auto wires = generateWires(schema, buffer);
generateSubComponents(schema, wires, buffer);
generateDisplay(schema, buffer);
buffer << "}";
}
void generateBus(BusInstance *bus, ostream &buffer);
void generateConnection(ConnectionInstance *connection, ostream &buffer);
void generateDisplay(Schema *schema, ostream &buffer) {
buffer << "\n\tdisplay {\n";
for(auto &component: schema->componentInstances) {
buffer << "\t\tcomponent { x: " << component->position.first << "; y: " << component->position.second << "; ref: \"" << component->name << "\"; }" << std::endl;
}
for(auto &bus: schema->busInstances) {
generateBus(bus.get(), buffer);
}
buffer << "\n";
for(auto &connection: schema->connections) {
generateConnection(connection.get(), buffer);
}
buffer << "\t}\n";
}
void generateConnection(ConnectionInstance *connection, ostream &buffer) {
buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " <<
"x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n";
}
void generateBus(BusInstance *bus, ostream &buffer) {
buffer << "\n";
buffer << "\t\t// " << bus->name << " bus\n\n";
if(bus->bus.getDisplayBus().has_value()) {
bus->bus.getDisplayBus()->comdel(buffer, bus->position.first, bus->position.second, bus->size);
}
}
void generateWire(std::string &name, Wire& wire, ostream &buffer);
std::map<string, string> generateWires(Schema *schema, ostream &buffer) {
std::set<string> usedNames;
std::map<string, string> usedMappings;
for(auto &bus: schema->busInstances) {
buffer << "\t//" << bus->name << std::endl;
for(auto& wire: bus->bus.getWires()) {
std::string name = wire.getName();
if(usedNames.count(wire.getName()) > 0) {
name = bus->name + "__" + wire.getName();
} }
if(wire.isHidden()) { buffer << std::endl << std::endl;
name = "--" + name;
}
usedNames.insert(name);
usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name));
generateWire(name, wire, buffer);
} }
buffer << std::endl << std::endl; return usedMappings;
}
return usedMappings;
}
void generateWire(std::string &name, Wire& wire, ostream &buffer) {
buffer << "\t";
switch (wire.getType()) {
case Wire::R_WIRE:
buffer << "r_wire";
break;
case Wire::WIRED_AND:
buffer << "wired_and";
break;
case Wire::WIRED_OR:
buffer << "wired_or";
break;
default:
buffer << "wire";
} }
if(wire.getWidth() != 1) { void generateWire(std::string &name, Wire &wire, ostream &buffer) {
buffer << "<" << wire.getWidth() << ">"; buffer << "\t";
switch (wire.getType()) {
case Wire::R_WIRE:
buffer << "r_wire";
break;
case Wire::WIRED_AND:
buffer << "wired_and";
break;
case Wire::WIRED_OR:
buffer << "wired_or";
break;
default:
buffer << "wire";
}
if (wire.getWidth() != 1) {
buffer << "<" << wire.getWidth() << ">";
}
buffer << " " << name << ";" << std::endl;
} }
buffer << " " << name << ";" << std::endl;
}
std::set<std::string> createImports(Schema *schema) { std::set<std::string> createImports(Schema *schema) {
std::set<std::string> importSet; std::set<std::string> importSet;
for(auto &component: schema->componentInstances) { for (auto &component: schema->componentInstances) {
importSet.insert(component->component.getSource()); importSet.insert(component->component.getSource());
}
return importSet;
} }
return importSet;
}
void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames, stringstream &buffer); void
generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames,
stringstream &buffer);
void generateSingleAutomaticPin(DirectConnectionInstance *instance, string name, string pin, void generateSingleAutomaticPin(DirectConnectionInstance *instance, string name, string pin,
map <string, string> &wireNames, map<string, string> &wireNames,
stringstream &buffer); stringstream &buffer);
void generateComponent(Schema *schema, map <string, string> &wires, ostream &buffer, void generateComponent(Schema *schema, map<string, string> &wires, ostream &buffer,
shared_ptr <ComponentInstance> &component); shared_ptr<ComponentInstance> &component);
void generateSubComponents(Schema *schema, map<string, string> &wires, ostream &buffer) { void generateSubComponents(Schema *schema, map<string, string> &wires, ostream &buffer) {
buffer << "\t// components --------------------------------------------" << std::endl; buffer << "\t// components --------------------------------------------" << std::endl;
for(auto& component: schema->componentInstances) { for (auto &component: schema->componentInstances) {
if(component->component.getType() == Component::MEMORY) { if (component->component.getType() == Component::MEMORY) {
generateComponent(schema, wires, buffer, component); generateComponent(schema, wires, buffer, component);
}
} }
} for (auto &component: schema->componentInstances) {
for(auto& component: schema->componentInstances) { if (component->component.getType() != Component::MEMORY) {
if(component->component.getType() != Component::MEMORY) { generateComponent(schema, wires, buffer, component);
generateComponent(schema, wires, buffer, component); }
}
}
}
void generateComponent(Schema *schema, map <string, string> &wires, ostream &buffer,
shared_ptr <ComponentInstance> &component) {
buffer << "\tsubcomponent " << component->component.getName() << " " << component->name;
std::optional<InstanceAttribute> memory;
std::vector<InstanceAttribute> attributes;
for(auto& attr: component->attributes) {
if(attr.name != "_memory") {
attributes.push_back(attr);
} else if(attr.name == "_memory" && attr.value.asMemoryReference().has_value()) {
memory = attr;
} }
} }
if(!attributes.empty()) { void generateComponent(Schema *schema, map<string, string> &wires, ostream &buffer,
buffer << "<"; shared_ptr<ComponentInstance> &component) {
buffer << attributes[0].value.stringify(); buffer << "\tsubcomponent " << component->component.getName() << " " << component->name;
for(int i=1; i<attributes.size(); i++) {
buffer << ", " << attributes[i].value.stringify(); std::optional<InstanceAttribute> memory;
std::vector<InstanceAttribute> attributes;
for (auto &attr: component->attributes) {
if (attr.name != "_memory") {
attributes.push_back(attr);
} else if (attr.name == "_memory" && attr.value.asMemoryReference().has_value()) {
memory = attr;
}
} }
buffer << ">";
}
stringstream tempOutput; if (!attributes.empty()) {
buffer << "<";
buffer << attributes[0].value.stringify();
for (int i = 1; i < attributes.size(); i++) {
buffer << ", " << attributes[i].value.stringify();
}
buffer << ">";
}
for(auto &pin: component->component.getPins()) { stringstream tempOutput;
if(schema->hasConnection(component->name, pin.getName())) {
auto conn = schema->getConnection(component->name, pin.getName()); for (auto &pin: component->component.getPins()) {
auto busConn = dynamic_cast<BusConnectionInstance*>(conn); if (schema->hasConnection(component->name, pin.getName())) {
if(busConn != nullptr) { auto conn = schema->getConnection(component->name, pin.getName());
for(auto wire: busConn->connection.getWires()) { auto busConn = dynamic_cast<BusConnectionInstance *>(conn);
if(wire.isType(Value::ATTRIBUTE_REFERENCE)) { if (busConn != nullptr) {
auto attribute = busConn->getAttribute(wire.asReference()); for (auto wire: busConn->connection.getWires()) {
if(wire.isType(Value::WIRE_REFERENCE)) { if (wire.isType(Value::ATTRIBUTE_REFERENCE)) {
tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; auto attribute = busConn->getAttribute(wire.asReference());
} else if(wire.isType(Value::NIL)) { if (wire.isType(Value::WIRE_REFERENCE)) {
tempOutput << "*, "; tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", ";
} else if (wire.isType(Value::NIL)) {
tempOutput << "*, ";
} else {
tempOutput << attribute.value.stringify() << ", ";
}
} else { } else {
tempOutput << attribute.value.stringify() << ", "; if (wire.isType(Value::WIRE_REFERENCE)) {
} tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", ";
} else { } else if (wire.isType(Value::NIL)) {
if(wire.isType(Value::WIRE_REFERENCE)) { tempOutput << "*, ";
tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; } else {
} else if(wire.isType(Value::NIL)) { tempOutput << wire.stringify() << ", ";
tempOutput << "*, "; }
} else {
tempOutput << wire.stringify() << ", ";
} }
} }
} }
} auto dirConn = dynamic_cast<DirectConnectionInstance *>(conn);
auto dirConn = dynamic_cast<DirectConnectionInstance*>(conn); if (dirConn != nullptr) {
if(dirConn != nullptr) { if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) {
if(dirConn->bus->bus.getType() == Bus::AUTOMATIC) { generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput);
generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); } else {
} else { generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput);
generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); }
}
} else {
// if no connection exists than defaults must exist
for (auto &wire: *pin.getWires()) {
tempOutput << wire.stringify() << ", ";
} }
} }
}
auto wireList = tempOutput.str();
wireList.pop_back();
wireList.pop_back(); // remove last COMMA(", ")
buffer << "(" << wireList << ")";
if (memory.has_value()) {
buffer << " uses " << *memory->value.asMemoryReference();
}
buffer << ";" << std::endl;
}
void generateSingleAutomaticPin(DirectConnectionInstance *connection, string name, string pin,
map<string, string> &wireNames, stringstream &buffer) {
std::vector<Value> wires;
std::string selected;
std::vector<Value> defaults;
if (connection->instance->name == name && connection->connection.getComponent().pin == pin) {
wires = connection->connection.getWires();
selected = connection->attributes[0].value.asReference();
defaults = *connection->instance->component.getPin(pin).getWires();
} else { } else {
// if no connection exists than defaults must exist wires = *connection->connection.getSecondWires();
for(auto& wire: *pin.getWires()) { selected = connection->attributes[1].value.asReference();
tempOutput << wire.stringify() << ", "; defaults = *connection->secondInstance->component.getPin(pin).getWires();
}
for (int i = 0; i < wires.size(); i++) {
if (wires[i].isType(Value::STRING)) {
if (wires[i].asString() == selected) {
buffer << wireNames[connection->bus->name + "." + connection->bus->bus.getWires()[0].getName()]
<< ", ";
} else {
buffer << defaults[i].stringify();
}
} else {
buffer << wires[i].stringify() << ", ";
} }
} }
} }
auto wireList = tempOutput.str(); void
wireList.pop_back(); generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames,
wireList.pop_back(); // remove last COMMA(", ") stringstream &buffer) {
std::vector<Value> wires;
buffer << "(" << wireList << ")"; if (connection->instance->name == name && connection->connection.getComponent().pin == pin) {
wires = connection->connection.getWires();
if(memory.has_value()) {
buffer << " uses " << *memory->value.asMemoryReference();
}
buffer << ";" << std::endl;
}
void generateSingleAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map <string, string> &wireNames, stringstream &buffer) {
std::vector<Value> wires;
std::string selected;
std::vector<Value> defaults;
if(connection->instance->name == name && connection->connection.getComponent().pin == pin) {
wires = connection->connection.getWires();
selected = connection->attributes[0].value.asReference();
defaults = *connection->instance->component.getPin(pin).getWires();
} else {
wires = *connection->connection.getSecondWires();
selected = connection->attributes[1].value.asReference();
defaults = *connection->secondInstance->component.getPin(pin).getWires();
}
for(int i=0; i<wires.size(); i++) {
if(wires[i].isType(Value::STRING)) {
if(wires[i].asString() == selected) {
buffer << wireNames[connection->bus->name + "." + connection->bus->bus.getWires()[0].getName()] << ", ";
} else {
buffer << defaults[i].stringify();
}
} else { } else {
buffer << wires[i].stringify() << ", "; wires = *connection->connection.getSecondWires();
} }
} for (auto &wire: wires) {
} if (wire.isType(Value::ATTRIBUTE_REFERENCE)) {
auto attribute = connection->getAttribute(wire.asReference());
void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames, stringstream &buffer) { if (wire.isType(Value::WIRE_REFERENCE)) {
std::vector<Value> wires; buffer << wireNames[connection->bus->name + "." + attribute.value.asReference()] << ", ";
if(connection->instance->name == name && connection->connection.getComponent().pin == pin) { } else if (wire.isType(Value::NIL)) {
wires = connection->connection.getWires(); buffer << "*, ";
} else { } else {
wires = *connection->connection.getSecondWires(); buffer << attribute.value.stringify() << ", ";
} }
for(auto& wire: wires) {
if(wire.isType(Value::ATTRIBUTE_REFERENCE)) {
auto attribute = connection->getAttribute(wire.asReference());
if(wire.isType(Value::WIRE_REFERENCE)) {
buffer << wireNames[connection->bus->name + "." + attribute.value.asReference()] << ", ";
} else if(wire.isType(Value::NIL)) {
buffer << "*, ";
} else { } else {
buffer << attribute.value.stringify() << ", "; if (wire.isType(Value::WIRE_REFERENCE)) {
} buffer << wireNames[connection->bus->name + "." + wire.asReference()] << ", ";
} else { } else if (wire.isType(Value::NIL)) {
if(wire.isType(Value::WIRE_REFERENCE)) { buffer << "*, ";
buffer << wireNames[connection->bus->name + "." + wire.asReference()] << ", "; } else {
} else if(wire.isType(Value::NIL)) { buffer << wire.stringify() << ", ";
buffer << "*, "; }
} else {
buffer << wire.stringify() << ", ";
} }
} }
} }
}
} // domain } // domain

View File

@ -7,9 +7,9 @@
namespace domain { namespace domain {
void generateSchemaFile(std::string& librarySource, Schema *schema, std::ostream &buffer); void generate_schema(std::string &librarySource, Schema *schema, std::ostream &buffer);
void generateComdelFile(Schema *schema, Library &library, std::ostream &buffer); void generate_comdel(Schema *schema, Library &library, std::ostream &buffer);
} // domain } // domain

View File

@ -0,0 +1,206 @@
#include "comdel_validator.h"
#include "library.h"
namespace domain {
std::vector<ValidationError> ComdelValidator::validateSchema(Schema &schema, ValidationContext context) {
std::vector<ValidationError> errors;
context.instance = nullptr;
context.attribute = nullptr;
for (auto &instance: schema.componentInstances) {
auto result = validateComponent(instance.get(), context);
errors.insert(errors.end(), result.begin(), result.end());
}
return errors;
}
std::vector<ValidationError>
ComdelValidator::validateInstanceCount(Schema &schema, Library &library, ValidationContext context) {
std::vector<ValidationError> errors;
// validate instance count
std::map<std::string, int> instanceMap;
for (auto &inst: schema.componentInstances) {
instanceMap[inst->component.getName()]++;
}
for (auto comp: library.getComponents()) {
int count = instanceMap[comp.getName()];
context.attributes["componentName"] = Value::fromString(comp.getName());
context.attributes["min"] = Value::fromInt(comp.getCount().first);
context.attributes["max"] = Value::fromInt(comp.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if (count < comp.getCount().first) {
auto message = populateMessage(
"Not enough instances of component '{componentName}' required at least {min}, found {count}",
context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if (count > comp.getCount().second) {
auto message = populateMessage(
"To many instances of component '{componentName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
// validate bus instance count
std::map<std::string, int> busInstanceMap;
for (auto &inst: schema.busInstances) {
busInstanceMap[inst->bus.getName()]++;
}
for (auto bus: library.getBuses()) {
int count = busInstanceMap[bus.getName()];
context.attributes["busName"] = Value::fromString(bus.getName());
context.attributes["min"] = Value::fromInt(bus.getCount().first);
context.attributes["max"] = Value::fromInt(bus.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if (count < bus.getCount().first) {
auto message = populateMessage(
"Not enough instances of bus '{busName}' required at least {min}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if (count > bus.getCount().second) {
auto message = populateMessage(
"To many instances of bus '{busName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
return errors;
}
std::vector<ValidationError>
ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) {
std::vector<ValidationError> errors;
for (auto &inst: schema.componentInstances) {
for (auto &pin: inst->component.getPins()) {
if (pin.getConnection().getType() == PinConnection::REQUIRED) {
if (!connectionExists(schema, inst, pin)) {
context.instance = inst.get();
context.attributes["instanceName"] = Value::fromString(inst->name);
auto message = populateMessage(pin.getConnection().getMessage(), context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
}
}
return errors;
}
std::vector<ValidationError>
ComdelValidator::validateComponent(ComponentInstance *instance, ValidationContext context) {
std::vector<ValidationError> errors;
context.instance = instance;
context.attributes.clear();
for (auto &attribute: instance->attributes) {
context.attributes[attribute.name] = attribute.value;
}
for (auto &rule: instance->component.getRules()) {
auto result = validateRule(rule, context);
if (result) {
errors.push_back(*result);
}
}
for (auto &attribute: instance->attributes) {
auto result = validateAttribute(&attribute, context);
errors.insert(errors.end(), result.begin(), result.end());
}
return errors;
}
std::vector<ValidationError>
ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) {
std::vector<ValidationError> errors;
if (attribute->attribute.getPopup()) {
Popup popup = *attribute->attribute.getPopup();
context.attribute = attribute;
context.attributes = std::map<std::string, Value>{{attribute->name, attribute->value}};
for (auto &rule: popup.getRules()) {
auto result = validateRule(rule, context);
if (result) {
errors.push_back(*result);
}
}
}
return errors;
}
std::optional<ValidationError> ComdelValidator::validateRule(Rule rule, ValidationContext context) {
RuleContext ruleContext;
ruleContext.addressSpaces = context.addressSpaces;
ruleContext.attributes = context.attributes;
ruleContext.function = validators;
auto action = rule.evaluate(ruleContext);
if (action) {
std::string message = this->populateMessage(action->getMessage(), context);
return ValidationError{context.instance, context.attribute, action->getType(), message};
}
return nullopt;
}
std::string ComdelValidator::populateMessage(string source, ValidationContext context) {
for (auto &[key, value]: context.attributes) {
source = replacePlaceholder(source, key, value);
}
return source;
}
string ComdelValidator::replacePlaceholder(string source, string key, Value value) {
key = "{" + key + "}";
auto placeholderValue = value.string();
auto found = source.find(key);
while (found != string::npos) {
source.replace(found, key.length(), placeholderValue);
found = source.find(key);
}
return source;
}
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) {
for (auto conn: schema.connections) {
auto busConnection = dynamic_cast<BusConnectionInstance *>(conn.get());
if (busConnection != nullptr) {
if (busConnection->instance->name == component->name &&
busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
}
auto directConnection = dynamic_cast<DirectConnectionInstance *>(conn.get());
if (directConnection != nullptr) {
if (directConnection->instance->name == component->name &&
busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
if (directConnection->secondInstance->name == component->name &&
busConnection->connection.getSecondComponent()->pin == pin.getName()) {
return true;
}
}
}
return false;
}
ComdelValidator::ComdelValidator(std::vector<FunctionValidator *> validators) {
for (auto *validator: validators) {
validator->clear();
this->validators.insert(std::make_pair(validator->getName(), validator));
}
}
}

View File

@ -0,0 +1,52 @@
#ifndef COMDEL_VALIDATOR_H
#define COMDEL_VALIDATOR_H
#include "instance.h"
#include "schema.h"
#include "library.h"
namespace domain {
struct ValidationError {
ComponentInstance *instance;
InstanceAttribute *attribute;
Action::ActionType type;
std::string message;
};
struct ValidationContext {
ComponentInstance *instance;
InstanceAttribute *attribute;
std::map<std::string, AddressSpace> addressSpaces;
std::map<std::string, Value> attributes;
};
class ComdelValidator {
public:
std::vector<ValidationError> validateSchema(Schema &schema, ValidationContext context);
std::vector<ValidationError> validateComponent(ComponentInstance *instance, ValidationContext context);
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
std::vector<ValidationError> validateInstanceCount(Schema &schema, Library &library, ValidationContext context);
std::vector<ValidationError>
validatePinConnections(Schema &schema, Library &library, ValidationContext context);
ComdelValidator(std::vector<FunctionValidator *> validators);
private:
std::map<std::string, FunctionValidator *> validators;
std::string populateMessage(string message, ValidationContext context);
string replacePlaceholder(string message, const string name, Value value);
bool connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin);
};
}
#endif //COMDEL_VALIDATOR_H

View File

@ -1,187 +0,0 @@
#include "comdelvalidator.h"
#include "library.h"
namespace domain {
std::vector<ValidationError> ComdelValidator::validateSchema(Schema &schema, ValidationContext context) {
std::vector<ValidationError> errors;
context.instance = nullptr;
context.attribute = nullptr;
for(auto &instance: schema.componentInstances) {
auto result = validateComponent(instance.get(), context);
errors.insert(errors.end(), result.begin(), result.end());
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validateInstanceCount(Schema& schema, Library& library, ValidationContext context) {
std::vector<ValidationError> errors;
// validate instance count
std::map<std::string, int> instanceMap;
for(auto& inst: schema.componentInstances) {
instanceMap[inst->component.getName()]++;
}
for(auto comp: library.getComponents()) {
int count = instanceMap[comp.getName()];
context.attributes["componentName"] = Value::fromString(comp.getName());
context.attributes["min"] = Value::fromInt(comp.getCount().first);
context.attributes["max"] = Value::fromInt(comp.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if(count < comp.getCount().first) {
auto message = populateMessage("Not enough instances of component '{componentName}' required at least {min}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if(count > comp.getCount().second) {
auto message = populateMessage("To many instances of component '{componentName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
// validate bus instance count
std::map<std::string, int> busInstanceMap;
for(auto& inst: schema.busInstances) {
busInstanceMap[inst->bus.getName()]++;
}
for(auto bus: library.getBuses()) {
int count = busInstanceMap[bus.getName()];
context.attributes["busName"] = Value::fromString(bus.getName());
context.attributes["min"] = Value::fromInt(bus.getCount().first);
context.attributes["max"] = Value::fromInt(bus.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if(count < bus.getCount().first) {
auto message = populateMessage("Not enough instances of bus '{busName}' required at least {min}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if(count > bus.getCount().second) {
auto message = populateMessage("To many instances of bus '{busName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) {
std::vector<ValidationError> errors;
for(auto& inst: schema.componentInstances) {
for(auto& pin: inst->component.getPins()) {
if(pin.getConnection().getType() == PinConnection::REQUIRED) {
if(!connectionExists(schema, inst, pin)) {
context.instance = inst.get();
context.attributes["instanceName"] = Value::fromString(inst->name);
auto message = populateMessage(pin.getConnection().getMessage(), context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
}
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validateComponent(ComponentInstance* instance, ValidationContext context) {
std::vector<ValidationError> errors;
context.instance = instance;
context.attributes.clear();
for(auto &attribute: instance->attributes) {
context.attributes[attribute.name] = attribute.value;
}
for(auto &rule: instance->component.getRules()) {
auto result = validateRule(rule, context);
if(result) {
errors.push_back(*result);
}
}
for(auto &attribute: instance->attributes) {
auto result = validateAttribute(&attribute, context);
errors.insert(errors.end(), result.begin(), result.end());
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) {
std::vector<ValidationError> errors;
if(attribute->attribute.getPopup()) {
Popup popup = *attribute->attribute.getPopup();
context.attribute = attribute;
context.attributes = std::map<std::string, Value>{{attribute->name, attribute->value}};
for(auto &rule: popup.getRules()) {
auto result = validateRule(rule, context);
if(result) {
errors.push_back(*result);
}
}
}
return errors;
}
std::optional<ValidationError> ComdelValidator::validateRule(Rule rule, ValidationContext context) {
RuleContext ruleContext;
ruleContext.addressSpaces = context.addressSpaces;
ruleContext.attributes = context.attributes;
ruleContext.function = validators;
auto action = rule.evaluate(ruleContext);
if (action) {
std::string message = this->populateMessage(action->getMessage(), context);
return ValidationError{context.instance, context.attribute, action->getType(), message};
}
return nullopt;
}
std::string ComdelValidator::populateMessage(string source, ValidationContext context) {
for(auto &[key, value]: context.attributes) {
source = replacePlaceholder(source, key, value);
}
return source;
}
string ComdelValidator::replacePlaceholder(string source, string key, Value value) {
key = "{" + key + "}";
auto placeholderValue = value.string();
auto found = source.find(key);
while(found != string::npos) {
source.replace(found, key.length(), placeholderValue);
found = source.find(key);
}
return source;
}
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) {
for(auto conn: schema.connections) {
auto busConnection = dynamic_cast<BusConnectionInstance*>(conn.get());
if(busConnection != nullptr) {
if(busConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
}
auto directConnection = dynamic_cast<DirectConnectionInstance*>(conn.get());
if(directConnection != nullptr) {
if(directConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
if(directConnection->secondInstance->name == component->name && busConnection->connection.getSecondComponent()->pin == pin.getName()) {
return true;
}
}
}
return false;
}
}

View File

@ -1,54 +0,0 @@
#ifndef COMDEL_VALIDATOR_H
#define COMDEL_VALIDATOR_H
#include "instance.h"
#include "schema.h"
#include "library.h"
namespace domain {
struct ValidationError
{
ComponentInstance *instance;
InstanceAttribute *attribute;
Action::ActionType type;
std::string message;
};
struct ValidationContext {
ComponentInstance *instance;
InstanceAttribute *attribute;
std::map<std::string, AddressSpace> addressSpaces;
std::map<std::string, Value> attributes;
};
class ComdelValidator
{
public:
std::vector<ValidationError> validateSchema(Schema& schema, ValidationContext context);
std::vector<ValidationError> validateComponent(ComponentInstance *instance, ValidationContext context);
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
std::vector<ValidationError> validateInstanceCount(Schema &schema, Library& library, ValidationContext context);
std::vector<ValidationError> validatePinConnections(Schema &schema, Library& library, ValidationContext context);
ComdelValidator(std::vector<FunctionValidator*> validators) {
for(auto* validator: validators) {
validator->clear();
this->validators.insert(std::make_pair(validator->getName(), validator));
}
}
private:
std::map<std::string, FunctionValidator*> validators;
std::string populateMessage(string message, ValidationContext context);
string replacePlaceholder(string message, const string name, Value value);
bool connectionExists(Schema &schema, shared_ptr <ComponentInstance> &component, Pin &pin);
};
}
#endif //COMDEL_VALIDATOR_H

View File

@ -2,84 +2,97 @@
namespace domain { namespace domain {
Component::Component(string name, string tooltip, string source, ComponentType type, Component::Component(string name, string tooltip, string source, ComponentType type,
vector<Rule> rules, string instanceName, pair<int, int> count, Display display, vector<Rule> rules, string instanceName, pair<int, int> count, Display display,
vector<Pin> pins, vector<Attribute> attributes) vector<Pin> pins, vector<Attribute> attributes)
: name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), count(count), display(display), pins(pins), attributes(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() { std::string Component::getName() {
return name; return name;
}
std::string Component::getTooltip() {
return tooltip;
}
std::string Component::getSource() {
return source;
}
Component::ComponentType Component::getType() {
return type;
}
std::vector<Rule> Component::getRules() {
return rules;
}
std::string Component::getInstanceName() {
return instanceName;
}
std::pair<int, int> Component::getCount() {
return count;
}
Display Component::getDisplay() {
return display;
}
std::vector<Pin> Component::getPins() {
return pins;
}
Pin Component::getPin(std::string pin) {
for(uint i=0; i<pins.size(); i++) {
if(pins[i].getName() == pin) {
return pins[i];
}
} }
throw std::exception();
}
bool Component::hasPin(std::string name) { std::string Component::getTooltip() {
for(auto pin: pins) { return tooltip;
if(pin.getName() == name) {
return true;
}
} }
return false;
}
std::vector<Attribute> Component::getAttributes() { std::string Component::getSource() {
return attributes; return source;
}
Attribute Component::getAttribute(std::string attribute) {
for(uint i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == attribute) {
return attributes[i];
}
} }
throw std::exception();
}
bool Component::hasAttribute(std::string name, Value::ValueType type) {
for(uint i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == name && attributes[i].getDefault().getType() == type) {
return true;
}
if(attributes[i].getName() == name && (type == Value::NIL && (attributes[i].getDefault().getType() == Value::MEMORY_REFERENCE || attributes[i].getDefault().getType() == Value::WIRE_REFERENCE))) {
return true;
}
if(attributes[i].getName() == name && (type == Value::UNDEFINED && (attributes[i].getDefault().getType() == Value::MEMORY_REFERENCE || attributes[i].getDefault().getType() == Value::WIRE_REFERENCE))) {
return true;
}
}
return false;
}
Component::ComponentType Component::getType() {
return type;
}
std::vector<Rule> Component::getRules() {
return rules;
}
std::string Component::getInstanceName() {
return instanceName;
}
std::pair<int, int> Component::getCount() {
return count;
}
Display Component::getDisplay() {
return display;
}
std::vector<Pin> Component::getPins() {
return pins;
}
Pin Component::getPin(std::string pin) {
for (auto & p: pins) {
if (p.getName() == pin) {
return p;
}
}
throw std::exception();
}
bool Component::hasPin(std::string name) {
for (auto pin: pins) {
if (pin.getName() == name) {
return true;
}
}
return false;
}
std::vector<Attribute> Component::getAttributes() {
return attributes;
}
Attribute Component::getAttribute(std::string attribute) {
for (auto & attr : attributes) {
if (attr.getName() == attribute) {
return attr;
}
}
throw std::exception();
}
bool Component::hasAttribute(std::string name, Value::ValueType type) {
for (auto & attribute : attributes) {
if (attribute.getName() == name && attribute.getDefault().getType() == type) {
return true;
}
if (attribute.getName() == name && (type == Value::NIL &&
(attribute.getDefault().getType() == Value::MEMORY_REFERENCE ||
attribute.getDefault().getType() == Value::WIRE_REFERENCE))) {
return true;
}
if (attribute.getName() == name && (type == Value::UNDEFINED &&
(attribute.getDefault().getType() == Value::MEMORY_REFERENCE ||
attribute.getDefault().getType() == Value::WIRE_REFERENCE))) {
return true;
}
}
return false;
}
} // namespace domain } // namespace domain

View File

@ -11,56 +11,65 @@
namespace domain { namespace domain {
using namespace std; 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<Rule> rules;
std::string instanceName;
std::pair<int, int> count;
Display display;
std::vector<Pin> pins;
std::vector<Attribute> attributes;
public:
Component(string name, string tooltip, string source, ComponentType type,
vector<Rule> rules, string instanceName, pair<int, int> count, Display display,
vector<Pin> pins, vector<Attribute> attributes);
std::string getName();
std::string getTooltip();
std::string getSource();
ComponentType getType();
std::vector<Rule> getRules();
std::string getInstanceName();
std::pair<int, int> getCount();
Display getDisplay();
std::vector<Pin> getPins();
Pin getPin(std::string pin);
std::vector<Attribute> getAttributes();
Attribute getAttribute(std::string attribute);
bool hasAttribute(std::string name, Value::ValueType type);
bool hasPin(std::string name);
class Component
{
public:
enum ComponentType {
OTHER,
PROCESSOR,
MEMORY
}; };
private:
std::string name;
std::string tooltip;
std::string source;
ComponentType type;
std::vector<Rule> rules;
std::string instanceName;
std::pair<int, int> count;
Display display;
std::vector<Pin> pins;
std::vector<Attribute> attributes;
public:
Component(string name, string tooltip, string source, ComponentType type,
vector<Rule> rules, string instanceName, pair<int, int> count, Display display,
vector<Pin> pins, vector<Attribute> attributes);
std::string getName();
std::string getTooltip();
std::string getSource();
ComponentType getType();
std::vector<Rule> getRules();
std::string getInstanceName();
std::pair<int, int> getCount();
Display getDisplay();
std::vector<Pin> getPins();
Pin getPin(std::string pin);
std::vector<Attribute> getAttributes();
Attribute getAttribute(std::string attribute);
bool hasAttribute(std::string name, Value::ValueType type);
bool hasPin(std::string name);
};
} // namespace domain } // namespace domain
#endif // DOMAIN_COMPONENT_H #endif // DOMAIN_COMPONENT_H

View File

@ -2,74 +2,77 @@
namespace domain { namespace domain {
Connection::Connection(ConnectionComponent first, std::optional<ConnectionComponent> second, Connection::Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
std::string bus, std::vector<Attribute> attributes, std::string bus, std::vector<Attribute> attributes,
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires) std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires)
: first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires), secondWires(secondWires) : first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires),
{} secondWires(secondWires) {}
ConnectionComponent Connection::getComponent() { ConnectionComponent Connection::getComponent() {
return first; return first;
}
std::optional<ConnectionComponent> Connection::getSecondComponent() {
return second;
}
std::string Connection::getBus() {
return bus;
}
std::vector<Attribute> Connection::getAttributes() {
return attributes;
}
std::vector<Value> Connection::getWires() {
return firstWires;
}
std::optional<std::vector<Value>> Connection::getSecondWires() {
return secondWires;
}
Attribute Connection::getAttribute(std::string name) {
for(unsigned int i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == name) {
return attributes[i];
}
} }
throw std::exception();
}
bool Connection::hasAttribute(std::string name) { std::optional<ConnectionComponent> Connection::getSecondComponent() {
for(unsigned int i=0; i<attributes.size(); i++) { return second;
if(attributes[i].getName() == name) {
return true;
}
} }
return false;
}
bool Connection::isConnecting(ConnectionComponent component) { std::string Connection::getBus() {
return first == component || (second.has_value() && *second == component); return bus;
} }
bool Connection::isConnecting(ConnectionComponent component, std::string bus) { std::vector<Attribute> Connection::getAttributes() {
return this->bus == bus && (first == component || (second.has_value() && *second == component)); return attributes;
} }
bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { std::vector<Value> Connection::getWires() {
if(!second.has_value()) { return firstWires;
}
std::optional<std::vector<Value>> Connection::getSecondWires() {
return secondWires;
}
Attribute Connection::getAttribute(std::string name) {
for (unsigned int i = 0; i < attributes.size(); i++) {
if (attributes[i].getName() == name) {
return attributes[i];
}
}
throw std::exception();
}
bool Connection::hasAttribute(std::string name) {
for (unsigned int i = 0; i < attributes.size(); i++) {
if (attributes[i].getName() == name) {
return true;
}
}
return false; return false;
} }
return (this->first == component && this->bus == bus && this->second == secondComponent) ||
(this->first == secondComponent && this->bus == bus && this->second == component); bool Connection::isConnecting(ConnectionComponent component) {
} return first == component || (second.has_value() && *second == component);
}
bool Connection::isConnecting(ConnectionComponent component, std::string bus) {
return this->bus == bus && (first == component || (second.has_value() && *second == component));
}
bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
if (!second.has_value()) {
return false;
}
return (this->first == component && this->bus == bus && this->second == secondComponent) ||
(this->first == secondComponent && this->bus == bus && this->second == component);
}
bool Connection::isConnecting(ConnectionComponent component, ConnectionComponent secondComponent) { bool Connection::isConnecting(ConnectionComponent component, ConnectionComponent secondComponent) {
if(!second.has_value()) { if (!second.has_value()) {
return false; return false;
} }
return (this->first == component && this->second == secondComponent) || return (this->first == component && this->second == secondComponent) ||
(this->first == secondComponent && this->second == component); (this->first == secondComponent && this->second == component);
} }

View File

@ -8,65 +8,68 @@
namespace domain { namespace domain {
struct ConnectionComponent struct ConnectionComponent {
{ std::string component;
std::string component; std::string pin;
std::string pin;
bool operator==(const ConnectionComponent& rhs) const bool operator==(const ConnectionComponent &rhs) const {
{ return (component == rhs.component) && (pin == rhs.pin);
return (component == rhs.component) && (pin == rhs.pin);
}
bool operator!=(const ConnectionComponent& rhs) const
{
return !operator==(rhs);
}
bool operator<(const ConnectionComponent& rhs) const
{
if(component < rhs.component) {
return true;
} else if(component == rhs.component) {
if(pin < rhs.pin) {
return true;
}
} }
return false;
}
};
class Connection bool operator!=(const ConnectionComponent &rhs) const {
{ return !operator==(rhs);
ConnectionComponent first; }
std::optional<ConnectionComponent> second;
std::string bus;
std::vector<Attribute> attributes;
std::vector<Value> firstWires; bool operator<(const ConnectionComponent &rhs) const {
std::optional<std::vector<Value>> secondWires; if (component < rhs.component) {
public: return true;
Connection(ConnectionComponent first, std::optional<ConnectionComponent> second, } else if (component == rhs.component) {
std::string bus, std::vector<Attribute> attributes, if (pin < rhs.pin) {
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires); return true;
}
}
return false;
}
};
bool isConnecting(ConnectionComponent first); class Connection {
bool isConnecting(ConnectionComponent first, std::string bus); ConnectionComponent first;
bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second); std::optional<ConnectionComponent> second;
bool isConnecting(ConnectionComponent first, ConnectionComponent second); std::string bus;
std::vector<Attribute> attributes;
std::vector<Value> firstWires;
std::optional<std::vector<Value>> secondWires;
public:
Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
std::string bus, std::vector<Attribute> attributes,
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires);
bool isConnecting(ConnectionComponent first);
bool isConnecting(ConnectionComponent first, std::string bus);
bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second);
bool isConnecting(ConnectionComponent first, ConnectionComponent second);
ConnectionComponent getComponent(); ConnectionComponent getComponent();
std::optional<ConnectionComponent> getSecondComponent();
std::string getBus(); std::optional<ConnectionComponent> getSecondComponent();
std::vector<Attribute> getAttributes(); std::string getBus();
std::vector<Value> getWires(); std::vector<Attribute> getAttributes();
std::optional<std::vector<Value>> getSecondWires();
Attribute getAttribute(std::string name); std::vector<Value> getWires();
bool hasAttribute(std::string name);
}; std::optional<std::vector<Value>> getSecondWires();
Attribute getAttribute(std::string name);
bool hasAttribute(std::string name);
};
} // namespace domain } // namespace domain

View File

@ -0,0 +1,29 @@
#include "connection_instance.h"
namespace domain {
ConnectionInstance::ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes,
Connection connection)
: instance(instance), attributes(attributes), connection(connection) {}
InstanceAttribute ConnectionInstance::getAttribute(string attribute) {
for (auto &attr: attributes) {
if (attr.name == attribute) {
return attr;
}
}
throw std::exception();
}
BusConnectionInstance::BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes,
BusInstance *bus, Connection connection)
: ConnectionInstance(instance, attributes, connection), bus(bus) {}
DirectConnectionInstance::DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondInstance,
std::vector<InstanceAttribute> attributes, BusInstance *bus,
Connection connection)
: ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) {}
} // namespace domain

View File

@ -0,0 +1,49 @@
#ifndef DOMAIN_CONNECTION_INSTANCE_H
#define DOMAIN_CONNECTION_INSTANCE_H
#include "connection.h"
#include "instance.h"
namespace domain {
class ConnectionInstance {
public:
ComponentInstance *instance;
Connection connection;
virtual ~ConnectionInstance() = default;
std::vector<InstanceAttribute> attributes;
std::pair<int, int> start;
std::pair<int, int> end;
ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes,
Connection connection);
InstanceAttribute getAttribute(string attribute);
};
class BusConnectionInstance : public ConnectionInstance {
public:
BusInstance *bus;
BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes, BusInstance *bus,
Connection connection);
};
class DirectConnectionInstance : public ConnectionInstance {
public:
BusInstance *bus;
ComponentInstance *secondInstance;
DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance,
std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection);
};
} // namespace domain
#endif // DOMAIN_CONNECTIONINSTANCE_H

View File

@ -1,28 +0,0 @@
#include "connectioninstance.h"
namespace domain {
ConnectionInstance::ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes, Connection connection)
: instance(instance), attributes(attributes), connection(connection)
{}
InstanceAttribute ConnectionInstance::getAttribute(string attribute) {
for(auto& attr: attributes) {
if(attr.name == attribute) {
return attr;
}
}
throw std::exception();
}
BusConnectionInstance::BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection)
: ConnectionInstance(instance, attributes, connection), bus(bus)
{}
DirectConnectionInstance::DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondInstance, std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection)
: ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus)
{}
} // namespace domain

View File

@ -1,50 +0,0 @@
#ifndef DOMAIN_CONNECTION_INSTANCE_H
#define DOMAIN_CONNECTION_INSTANCE_H
#include "connection.h"
#include "instance.h"
#include "wireinstance.h"
namespace domain {
class ConnectionInstance
{
public:
ComponentInstance *instance;
Connection connection;
virtual ~ConnectionInstance() = default;
std::vector<InstanceAttribute> attributes;
std::pair<int, int> start;
std::pair<int, int> end;
ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes, Connection connection);
InstanceAttribute getAttribute(string attribute);
};
class BusConnectionInstance: public ConnectionInstance
{
public:
BusInstance *bus;
BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection);
};
class DirectConnectionInstance: public ConnectionInstance
{
public:
BusInstance *bus;
ComponentInstance *secondInstance;
DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection);
};
} // namespace domain
#endif // DOMAIN_CONNECTIONINSTANCE_H

View File

@ -2,6 +2,172 @@
namespace domain { namespace domain {
Display::Display(std::vector<ui::Item> items): items(items) {} Display::Display(std::vector<ui::Item> items) : items(items) {}
void Display::render(QGraphicsItemGroup *group) {
for (auto &item: items) {
item.render(group);
}
}
void Display::comdel(std::ostream &buffer, int x, int y, int size) {
for (auto &item: items) {
item.comdel(buffer, x, y, size);
}
}
void ui::Rect::render(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x, y, w, h));
}
void ui::Rect::comdel(std::ostream &buffer, int x, int y) {
buffer << "\t\trectangle {\n";
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
buffer << "\t\t\tw: " << w << "; h: " << h << ";\n";
buffer << "\t\t}\n\n";
}
void ui::Line::render(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsLineItem(x1, y1, x2, y2));
}
void ui::Line::comdel(std::ostream &buffer, int x, int y) {
buffer << "\t\tline {\n";
buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n";
buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n";
buffer << "\t\t}\n\n";
}
void ui::Bus::render(QGraphicsItemGroup *group, int size) {
if (orientation == HORIZONTAL) {
group->addToGroup(new QGraphicsRectItem(x, y, size, h));
} else {
group->addToGroup(new QGraphicsRectItem(x, y, w, size));
}
}
int ui::Bus::getDefaultSize() {
if (orientation == HORIZONTAL) {
return w;
} else {
return h;
}
}
void ui::Bus::comdel(std::ostream &buffer, int x, int y, int size) {
buffer << "\t\trectangle {\n";
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
if (orientation == HORIZONTAL) {
buffer << "\t\t\tw: " << size << "; h: " << h << ";\n";
} else {
buffer << "\t\t\tw: " << w << "; h: " << size << ";\n";
}
buffer << "\t\t}\n\n";
}
void ui::Pin::renderIn(QGraphicsItemGroup *group) {
QPolygon polygon;
switch (orientation) {
case PinOrientation::TOP:
polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w, y + h) << QPoint(x + w, y)
<< QPoint(x + w / 2, y + h / 2);
break;
case PinOrientation::BOTTOM:
polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w / 2, y + h / 2)
<< QPoint(x + w, y + h) << QPoint(x + w, y);
break;
case PinOrientation::LEFT:
polygon << QPoint(x, y) << QPoint(x + w / 2, y + h / 2) << QPoint(x, y + h)
<< QPoint(x + w, y + h) << QPoint(x + w, y);
break;
case PinOrientation::RIGHT:
polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w, y + h)
<< QPoint(x + w / 2, y + h / 2) << QPoint(x + w, y);
break;
}
group->addToGroup(new QGraphicsPolygonItem(polygon));
}
void ui::Pin::renderOut(QGraphicsItemGroup *group) {
QPolygon polygon;
switch (orientation) {
case PinOrientation::TOP:
polygon << QPoint(x, y + h / 2) << QPoint(x, y + h) << QPoint(x + w, y + h)
<< QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y);
break;
case PinOrientation::BOTTOM:
polygon << QPoint(x, y) << QPoint(x, y + h / 2) << QPoint(x + w / 2, y + h)
<< QPoint(x + w, y + h / 2) << QPoint(x + w, y);
break;
case PinOrientation::LEFT:
polygon << QPoint(x + w, y) << QPoint(x + w / 2, y) << QPoint(x, y + h / 2)
<< QPoint(x + w / 2, y + h) << QPoint(x + w, y + w);
break;
case PinOrientation::RIGHT:
polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w / 2, y + h)
<< QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y);
break;
}
group->addToGroup(new QGraphicsPolygonItem(polygon));
}
void ui::Pin::renderInOut(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x, y, w, h));
}
void ui::Pin::render(QGraphicsItemGroup *group) {
switch (pinType) {
case PinType::IN:
renderIn(group);
break;
case PinType::OUT:
renderOut(group);
break;
case PinType::IN_OUT:
renderInOut(group);
break;
}
}
int ui::Pin::getConnectionX() {
switch (orientation) {
case ui::PinOrientation::TOP:
case ui::PinOrientation::BOTTOM:
return x + w / 2;
case ui::PinOrientation::LEFT:
return x;
case ui::PinOrientation::RIGHT:
return x + w;
}
return 0;
}
int ui::Pin::getConnectionY() {
switch (orientation) {
case ui::PinOrientation::LEFT:
case ui::PinOrientation::RIGHT:
return y + h / 2;
case ui::PinOrientation::TOP:
return y;
case ui::PinOrientation::BOTTOM:
return y + h;
}
return 0;
}
void ui::Item::render(QGraphicsItemGroup *group, int size) {
if (rect) rect->render(group);
if (line) line->render(group);
if (pin) pin->render(group);
if (bus) bus->render(group, size);
}
void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) {
if (rect) rect->comdel(buffer, x, y);
if (line) line->comdel(buffer, x, y);
// pins aren't exported
if (bus) bus->comdel(buffer, x, y, size);
}
} // namespace domain } // namespace domain

View File

@ -8,237 +8,109 @@
namespace domain { namespace domain {
namespace ui { namespace ui {
class Rect { class Rect {
public: public:
int x, y, w, h; int x, y, w, h;
Rect(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {} Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}
void render(QGraphicsItemGroup *group);
void comdel(std::ostream &buffer, int x, int y);
};
class Line {
public:
int x1, y1, x2, y2;
Line(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {}
void render(QGraphicsItemGroup *group);
void comdel(std::ostream &buffer, int x, int y);
};
enum PinType {
IN, OUT, IN_OUT
};
enum PinOrientation {
LEFT, RIGHT, TOP, BOTTOM
};
enum BusOrientation {
VERTICAL, HORIZONTAL
};
class Bus {
public:
int x, y, w, h;
BusOrientation orientation;
Bus(int x, int y, int w, int h, BusOrientation orientation) : x(x), y(y), w(w), h(h),
orientation(orientation) {}
void render(QGraphicsItemGroup *group, int size);
int getDefaultSize();
void comdel(std::ostream &buffer, int x, int y, int size);
};
class Pin {
public:
PinOrientation orientation;
PinType pinType;
int x, y, w, h;
Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType) : x(x), y(y), w(w), h(h),
orientation(orientation),
pinType(pinType) {}
public:
void render(QGraphicsItemGroup *group);
int getConnectionX();
int getConnectionY();
private:
void renderIn(QGraphicsItemGroup *group);
void renderOut(QGraphicsItemGroup *group);
void renderInOut(QGraphicsItemGroup *group);
};
class Item {
public:
Item() : rect(std::nullopt), line(std::nullopt), pin(std::nullopt), bus(std::nullopt) {}
std::optional<Rect> rect = std::nullopt;
std::optional<Line> line = std::nullopt;
std::optional<Pin> pin = std::nullopt;
std::optional<Bus> bus = std::nullopt;
void render(QGraphicsItemGroup *group, int size = 0);
void comdel(std::ostream &buffer, int x, int y, int size = 0);
};
void render(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x,y,w,h));
} }
void comdel(std::ostream &buffer, int x, int y) { class Display {
buffer << "\t\trectangle {\n"; public:
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
buffer << "\t\t\tw: " << w << "; h: " << h << ";\n";
buffer << "\t\t}\n\n";
}
}; Display(std::vector<ui::Item> items);
class Line { void render(QGraphicsItemGroup *group);
public:
int x1, y1, x2, y2;
Line(int x1, int y1, int x2, int y2): x1(x1), y1(y1), x2(x2), y2(y2) {} void comdel(std::ostream &buffer, int x, int y, int size = 0);
void render(QGraphicsItemGroup *group) { std::vector<ui::Item> &getItems() { return items; }
group->addToGroup(new QGraphicsLineItem(x1, y1, x2, y2));
}
void comdel(std::ostream &buffer, int x, int y) { private:
buffer << "\t\tline {\n"; std::vector<ui::Item> items;
buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n"; };
buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n";
buffer << "\t\t}\n\n";
}
};
enum PinOrientation {
LEFT, RIGHT, TOP, BOTTOM
};
enum BusOrientation {
VERTICAL, HORIZONTAL
};
enum PinType {
IN, OUT, IN_OUT
};
class Bus {
public:
int x, y, w, h;
BusOrientation orientation;
Bus(int x, int y, int w, int h, BusOrientation orientation): x(x), y(y), w(w), h(h), orientation(orientation) {}
void render(QGraphicsItemGroup *group, int size) {
if(orientation == HORIZONTAL) {
group->addToGroup(new QGraphicsRectItem(x,y,size, h));
} else {
group->addToGroup(new QGraphicsRectItem(x,y,w,size));
}
}
int getDefaultSize() {
if(orientation == HORIZONTAL) {
return w;
} else {
return h;
}
}
void comdel(std::ostream &buffer, int x, int y, int size) {
buffer << "\t\trectangle {\n";
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
if(orientation == HORIZONTAL) {
buffer << "\t\t\tw: " << size << "; h: " << h << ";\n";
} else {
buffer << "\t\t\tw: " << w << "; h: " << size << ";\n";
}
buffer << "\t\t}\n\n";
}
};
class Pin {
public:
PinOrientation orientation;
PinType pinType;
int x, y, w, h;
Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType): x(x), y(y), w(w), h(h), orientation(orientation), pinType(pinType) {}
void renderIn(QGraphicsItemGroup *group) {
QPolygon polygon;
switch (orientation) {
case PinOrientation::TOP:
polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y) << QPoint(x+w/2, y+h/2);
break;
case PinOrientation::BOTTOM:
polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w/2, y+h/2) << QPoint(x+w, y+h) << QPoint(x+w, y);
break;
case PinOrientation::LEFT:
polygon << QPoint(x, y) << QPoint(x+w/2, y+h/2) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y);
break;
case PinOrientation::RIGHT:
polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w/2, y+h/2) << QPoint(x+w, y);
break;
}
group->addToGroup(new QGraphicsPolygonItem(polygon));
}
void renderOut(QGraphicsItemGroup *group) {
QPolygon polygon;
switch (orientation) {
case PinOrientation::TOP:
polygon << QPoint(x, y+h/2) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w/2, y);
break;
case PinOrientation::BOTTOM:
polygon << QPoint(x, y) << QPoint(x, y+h/2) << QPoint(x+w/2, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w, y);
break;
case PinOrientation::LEFT:
polygon << QPoint(x+w, y) << QPoint(x+w/2, y) << QPoint(x, y+h/2) << QPoint(x+w/2, y+h) << QPoint(x+w, y+w);
break;
case PinOrientation::RIGHT:
polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w/2, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w/2, y);
break;
}
group->addToGroup(new QGraphicsPolygonItem(polygon));
}
void renderInOut(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x, y ,w, h));
}
void render(QGraphicsItemGroup *group) {
switch (pinType) {
case PinType::IN:
renderIn(group);
break;
case PinType::OUT:
renderOut(group);
break;
case PinType::IN_OUT:
renderInOut(group);
break;
}
}
int getConnectionX() {
switch (orientation) {
case ui::PinOrientation::TOP:
case ui::PinOrientation::BOTTOM:
return x+w/2;
case ui::PinOrientation::LEFT:
return x;
case ui::PinOrientation::RIGHT:
return x+w;
}
return 0;
}
int getConnectionY() {
switch (orientation) {
case ui::PinOrientation::LEFT:
case ui::PinOrientation::RIGHT:
return y+h/2;
case ui::PinOrientation::TOP:
return y;
case ui::PinOrientation::BOTTOM:
return y+h;
}
return 0;
}
};
class Item {
public:
Item(): rect(std::nullopt), line(std::nullopt), pin(std::nullopt), bus(std::nullopt) {}
void render(QGraphicsItemGroup *group, int size = 0) {
if(rect) rect->render(group);
if(line) line->render(group);
if(pin) pin->render(group);
if(bus) bus->render(group, size);
}
std::optional<Rect> rect = std::nullopt;
std::optional<Line> line = std::nullopt;
std::optional<Pin> pin = std::nullopt;
std::optional<Bus> bus = std::nullopt;
void comdel(std::ostream &buffer, int x, int y, int size = 0) {
if(rect) rect->comdel(buffer, x, y);
if(line) line->comdel(buffer, x, y);
// pins aren't exported
if(bus) bus->comdel(buffer, x, y, size);
}
};
}
class Display
{
public:
Display(std::vector<ui::Item> items);
void render(QGraphicsItemGroup *group) {
for(auto &item: items) {
item.render(group);
}
}
void comdel(std::ostream &buffer, int x, int y, int size = 0) {
for(auto &item: items) {
item.comdel(buffer, x, y, size);
}
}
std::vector<ui::Item>& getItems() {return items;}
private:
std::vector<ui::Item> items;
};
} // namespace domain } // namespace domain

View File

@ -0,0 +1,166 @@
#include <map>
#include <utility>
#include "function_signature.h"
namespace domain {
class DivisibleValidator : public FunctionValidator {
public:
DivisibleValidator() : FunctionValidator("divisible", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return (first % second) == 0;
}
return false;
}
void clear() override {}
};
class LessThenValidator : public FunctionValidator {
public:
LessThenValidator() : FunctionValidator("less_then", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return first < second;
}
return false;
}
void clear() override {}
};
class GreaterThenValidator : public FunctionValidator {
public:
GreaterThenValidator() : FunctionValidator("greater_then", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return first > second;
}
return false;
}
void clear() override {}
};
class ContainsAddressValidator : public FunctionValidator {
public:
ContainsAddressValidator() : FunctionValidator("contains_address", {Value::ADDRESS_SPACE, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
AddressSpace space = values[0].asAddressSpace();
long long address = values[1].asInt();
return space.contains(address);
}
return false;
}
void clear() override {}
};
class ContainsValidator : public FunctionValidator {
public:
ContainsValidator() : FunctionValidator("contains", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
AddressSpace space = values[0].asAddressSpace();
long long start = values[1].asInt();
long long size = values[1].asInt();
return space.contains(start, start + size);
}
return false;
}
void clear() override {}
};
class UniqueValidator : public FunctionValidator {
private:
std::map<std::string, std::vector<std::pair<long long int, long long int>>> spaces;
bool overlaps(long long int start1, long long int end1, long long int start2, long long int end2) {
return std::max((long long int) 0, std::min(end1, end2) - std::max(start1, start2)) > 0;
}
public:
UniqueValidator() : FunctionValidator("unique", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if (validateSignature(values)) {
std::string space = values[0].asAddressSpace().getName();
long long int start = values[1].asInt();
long long int end = start + values[2].asInt();
if (spaces.count(space) == 0) {
spaces.insert(std::make_pair(space, std::vector<std::pair<long long int, long long int>>{}));
}
for (auto &s: spaces[space]) {
if (overlaps(s.first, s.second, start, end)) {
return false;
}
}
spaces[space].push_back(std::make_pair(start, end));
return true;
}
return false;
}
void clear() override {
spaces.clear();
}
};
std::vector<FunctionValidator *> getSupportedValidators() {
std::vector<FunctionValidator *> validators;
validators.push_back(new DivisibleValidator());
validators.push_back(new LessThenValidator());
validators.push_back(new GreaterThenValidator());
validators.push_back(new ContainsAddressValidator());
validators.push_back(new ContainsValidator());
validators.push_back(new UniqueValidator());
return validators;
}
FunctionValidator::FunctionValidator(std::string name, std::vector<Value::ValueType> signature)
: name(std::move(name)), signature(std::move(signature)) {}
std::string FunctionValidator::getName() {
return name;
}
std::vector<Value::ValueType> FunctionValidator::getSignature() {
return signature;
}
bool FunctionValidator::validateSignature(std::vector<Value> _signature) {
if (this->signature.size() != _signature.size()) {
return false;
}
for (int i = 0; i < this->signature.size(); i++) {
if (this->signature[i] != _signature[i].getType()) {
return false;
}
}
return true;
}
} // namespace domain

View File

@ -0,0 +1,36 @@
#ifndef DOMAIN_FUNCTION_VALIDATOR_H
#define DOMAIN_FUNCTION_VALIDATOR_H
#include<functional>
#include<vector>
#include "value.h"
namespace domain {
class FunctionValidator {
private:
std::string name;
std::vector<Value::ValueType> signature;
protected:
FunctionValidator(std::string name, std::vector<Value::ValueType> signature);
public:
std::string getName();
std::vector<Value::ValueType> getSignature();
bool validateSignature(std::vector<Value> signature);
virtual bool validate(std::vector<Value> values) = 0;
virtual void clear() = 0;
};
std::vector<FunctionValidator *> getSupportedValidators();
} // namespace domain
#endif // DOMAIN_FUNCTION_VALIDATOR_H

View File

@ -1,138 +0,0 @@
#include <map>
#include "functionsignature.h"
namespace domain {
class DivisibleValidator: public FunctionValidator {
public:
DivisibleValidator(): FunctionValidator("divisible", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return (first % second) == 0;
}
return false;
}
void clear() override {}
};
class LessThenValidator: public FunctionValidator {
public:
LessThenValidator(): FunctionValidator("less_then", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return first < second;
}
return false;
}
void clear() override {}
};
class GreaterThenValidator: public FunctionValidator {
public:
GreaterThenValidator(): FunctionValidator("greater_then", {Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
long long first = values[0].asInt();
long long second = values[1].asInt();
return first > second;
}
return false;
}
void clear() override {}
};
class ContainsAddressValidator: public FunctionValidator {
public:
ContainsAddressValidator(): FunctionValidator("contains_address", {Value::ADDRESS_SPACE, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
AddressSpace space = values[0].asAddressSpace();
long long address = values[1].asInt();
return space.contains(address);
}
return false;
}
void clear() override {}
};
class ContainsValidator: public FunctionValidator {
public:
ContainsValidator(): FunctionValidator("contains", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
AddressSpace space = values[0].asAddressSpace();
long long start = values[1].asInt();
long long size = values[1].asInt();
return space.contains(start, start + size);
}
return false;
}
void clear() override {}
};
class UniqueValidator: public FunctionValidator {
private:
std::map<std::string, std::vector<std::pair<long long int, long long int>>> spaces;
bool overlaps(long long int start1, long long int end1, long long int start2, long long int end2) {
return std::max((long long int)0, std::min(end1, end2) - std::max(start1, start2)) > 0;
}
public:
UniqueValidator(): FunctionValidator("unique", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
bool validate(std::vector<Value> values) override {
if(validateSignature(values)) {
std::string space = values[0].asAddressSpace().getName();
long long int start = values[1].asInt();
long long int end = start + values[2].asInt();
if(spaces.count(space) == 0) {
spaces.insert(std::make_pair(space, std::vector<std::pair<long long int, long long int>>{}));
}
for(auto& s: spaces[space]) {
if(overlaps(s.first, s.second, start, end)) {
return false;
}
}
spaces[space].push_back(std::make_pair(start, end));
return true;
}
return false;
}
void clear() override {
spaces.clear();
}
};
std::vector<FunctionValidator*> getSupportedValidators() {
std::vector<FunctionValidator*> validators;
validators.push_back(new DivisibleValidator());
validators.push_back(new LessThenValidator());
validators.push_back(new GreaterThenValidator());
validators.push_back(new ContainsAddressValidator());
validators.push_back(new ContainsValidator());
validators.push_back(new UniqueValidator());
return validators;
}
} // namespace domain

View File

@ -1,53 +0,0 @@
#ifndef DOMAIN_FUNCTION_VALIDATOR_H
#define DOMAIN_FUNCTION_VALIDATOR_H
#include<functional>
#include<vector>
#include "value.h"
namespace domain {
class FunctionValidator {
private:
std::string name;
std::vector<Value::ValueType> signature;
protected:
FunctionValidator(std::string name, std::vector<Value::ValueType> signature) {
this->name = name;
this->signature = signature;
}
public:
std::string getName() {
return name;
}
std::vector<Value::ValueType> getSignature() {
return signature;
}
bool validateSignature(std::vector<Value> signature) {
if(this->signature.size() != signature.size()) {
return false;
}
for(int i=0; i<this->signature.size(); i++) {
if(this->signature[i] != signature[i].getType()) {
return false;
}
}
return true;
}
virtual bool validate(std::vector<Value> values) = 0;
virtual void clear() = 0;
};
std::vector<FunctionValidator*> getSupportedValidators();
} // namespace domain
#endif // DOMAIN_FUNCTION_VALIDATOR_H

View File

@ -2,19 +2,18 @@
namespace domain { namespace domain {
BusInstance::BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size) BusInstance::BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size)
: name(name), position(position), bus(bus), size(size) : name(name), position(position), bus(bus), size(size) {
{ if (size < 0 && bus.getDisplayBus().has_value()) {
if(size < 0 && bus.getDisplayBus().has_value()) { this->size = bus.getDisplayBus()->getDefaultSize();
this->size = bus.getDisplayBus()->getDefaultSize(); }
} }
}
BusInstance::BusInstance(std::string name, Bus bus): name(name), bus(bus), position(0,0), size(0) {} BusInstance::BusInstance(std::string name, Bus bus) : name(name), bus(bus), position(0, 0), size(0) {}
ComponentInstance::ComponentInstance(std::string name, std::vector<InstanceAttribute> attributes, std::pair<int, int> position, Component component) ComponentInstance::ComponentInstance(std::string name, std::vector<InstanceAttribute> attributes,
: name(name), attributes(std::move(attributes)), position(position), component(component) std::pair<int, int> position, Component component)
{} : name(name), attributes(std::move(attributes)), position(position), component(component) {}
} // namespace domain } // namespace domain

View File

@ -3,44 +3,41 @@
#include "bus.h" #include "bus.h"
#include "component.h" #include "component.h"
#include "instanceattribute.h" #include "instance_attribute.h"
#include <string> #include <string>
#include <vector> #include <vector>
namespace domain { namespace domain {
class BusInstance class BusInstance {
{ public:
public: std::string name;
std::string name; std::pair<int, int> position;
std::pair<int, int> position;
Bus bus; Bus bus;
int size; int size;
BusInstance(std::string name, Bus bus); BusInstance(std::string name, Bus bus);
BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size = -1); BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size = -1);
virtual ~BusInstance() = default; virtual ~BusInstance() = default;
}; };
class ComponentInstance class ComponentInstance {
{ public:
public: std::string name;
std::string name; std::vector<InstanceAttribute> attributes;
std::vector<InstanceAttribute> attributes; std::pair<int, int> position;
std::pair<int, int> position;
Component component; Component component;
ComponentInstance(std::string name, std::vector<InstanceAttribute> attributes, std::pair<int, int> position, Component component); ComponentInstance(std::string name, std::vector<InstanceAttribute> attributes, std::pair<int, int> position, Component component);
virtual ~ComponentInstance() = default; virtual ~ComponentInstance() = default;
}; };
} // namespace domain } // namespace domain

View File

@ -0,0 +1,8 @@
#include "instance_attribute.h"
namespace domain {
InstanceAttribute::InstanceAttribute(std::string name, Value value, Attribute attribute)
: name(name), value(value), attribute(attribute) {}
} // namespace domain

View File

@ -0,0 +1,25 @@
#ifndef DOMAIN_INSTANCE_ATTRIBUTE_H
#define DOMAIN_INSTANCE_ATTRIBUTE_H
#include "attribute.h"
#include "value.h"
#include <string>
namespace domain {
class InstanceAttribute {
public:
InstanceAttribute(std::string name, Value value, Attribute attribute);
std::string name;
Value value;
Attribute attribute;
~InstanceAttribute() = default;
};
} // namespace domain
#endif // DOMAIN_INSTANCE_ATTRIBUTE_H

View File

@ -1,9 +0,0 @@
#include "instanceattribute.h"
namespace domain {
InstanceAttribute::InstanceAttribute(std::string name, Value value, Attribute attribute)
: name(name), value(value), attribute(attribute)
{}
} // namespace domain

View File

@ -1,27 +0,0 @@
#ifndef DOMAIN_INSTANCE_ATTRIBUTE_H
#define DOMAIN_INSTANCE_ATTRIBUTE_H
#include "attribute.h"
#include "value.h"
#include <string>
namespace domain {
class InstanceAttribute
{
public:
InstanceAttribute(std::string name, Value value, Attribute attribute);
std::string name = "";
Value value;
Attribute attribute;
~InstanceAttribute() = default;
};
} // namespace domain
#endif // DOMAIN_INSTANCE_ATTRIBUTE_H

View File

@ -2,116 +2,131 @@
namespace domain { namespace domain {
Library::Library(string name, string libraryInfo, string header, string componentDirectory, std::optional<std::string> componentHeader, Library::Library(string name, string libraryInfo, string header, string componentDirectory,
vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses, vector<Connection> connections, map<string, string> messages) std::optional<std::string> componentHeader,
: name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), componentHeader(componentHeader), addressSpaces(addressSpaces), vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses,
components(components), buses(buses), connections(connections), messages(messages) vector<Connection> connections, map<string, string> messages)
{} : name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory),
componentHeader(componentHeader), addressSpaces(addressSpaces),
components(components), buses(buses), connections(connections), messages(messages) {}
std::string Library::getName() { std::string Library::getName() {
return name; return name;
}
std::string Library::getLibraryInfo() {
return libraryInfo;
}
std::string Library::getHeader() {
return header;
}
std::string Library::getComponentDirectory() {
return componentDirectory;
}
std::optional<std::string> Library::getComponentHeader() {
return componentHeader;
}
std::vector<AddressSpace> Library::getAddressSpaces() {
return addressSpaces;
}
std::vector<Component> Library::getComponents() {
return components;
}
std::vector<Bus> Library::getBuses() {
return buses;
}
std::vector<Connection> Library::getConnections() {
return connections;
}
std::map<std::string, std::string> Library::getMessages() {
return messages;
}
bool Library::hasComponent(std::string name) {
for(uint i=0; i<components.size(); i++) {
if(components[i].getName() == name) {
return true;
}
} }
return false;
} std::string Library::getLibraryInfo() {
bool Library::hasBus(std::string name) { return libraryInfo;
for(uint i=0; i<buses.size(); i++) { }
if(buses[i].getName() == name) {
return true; std::string Library::getHeader() {
} return header;
}
std::string Library::getComponentDirectory() {
return componentDirectory;
}
std::optional<std::string> Library::getComponentHeader() {
return componentHeader;
}
std::vector<AddressSpace> Library::getAddressSpaces() {
return addressSpaces;
}
std::vector<Component> Library::getComponents() {
return components;
}
std::vector<Bus> Library::getBuses() {
return buses;
}
std::vector<Connection> Library::getConnections() {
return connections;
}
std::map<std::string, std::string> Library::getMessages() {
return messages;
}
bool Library::hasComponent(std::string name) {
for (uint i = 0; i < components.size(); i++) {
if (components[i].getName() == name) {
return true;
}
}
return false;
}
bool Library::hasBus(std::string name) {
for (uint i = 0; i < buses.size(); i++) {
if (buses[i].getName() == name) {
return true;
}
}
return false;
} }
return false;
}
AddressSpace &Library::getAddressSpace(std::string addressSpace) { AddressSpace &Library::getAddressSpace(std::string addressSpace) {
for(uint i=0; i<addressSpaces.size(); i++) { for (uint i = 0; i < addressSpaces.size(); i++) {
if(addressSpaces[i].getName() == addressSpace) { if (addressSpaces[i].getName() == addressSpace) {
return addressSpaces[i]; return addressSpaces[i];
}
} }
throw std::exception();
} }
throw std::exception();
}
Component &Library::getComponent(std::string component) {
for(uint i=0; i<components.size(); i++) {
if(components[i].getName() == component) {
return components[i];
}
}
throw std::exception();
}
Bus &Library::getBus(std::string bus) {
for(uint i=0; i<buses.size(); i++) {
if(buses[i].getName() == bus) {
return buses[i];
}
}
throw std::exception();
} Component &Library::getComponent(std::string component) {
for (uint i = 0; i < components.size(); i++) {
bool Library::hasConnection(ConnectionComponent component, std::string bus) { if (components[i].getName() == component) {
return getConnection(component, bus).has_value(); return components[i];
} }
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) {
for(uint i=0; i<connections.size(); i++) {
if(connections[i].isConnecting(component, bus)) {
return connections[i];
} }
throw std::exception();
} }
return nullopt;
}
bool Library::hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { Bus &Library::getBus(std::string bus) {
return getConnection(component, bus, secondComponent).has_value(); for (uint i = 0; i < buses.size(); i++) {
} if (buses[i].getName() == bus) {
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { return buses[i];
for(uint i=0; i<connections.size(); i++) { }
if(connections[i].isConnecting(component, bus, secondComponent)) {
return connections[i];
} }
} throw std::exception();
return nullopt;
}
std::string Library::getMessage(std::string key) { }
return messages[key];
} bool Library::hasConnection(ConnectionComponent component, std::string bus) {
return getConnection(component, bus).has_value();
}
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) {
for (uint i = 0; i < connections.size(); i++) {
if (connections[i].isConnecting(component, bus)) {
return connections[i];
}
}
return nullopt;
}
bool Library::hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
return getConnection(component, bus, secondComponent).has_value();
}
std::optional<Connection>
Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
for (uint i = 0; i < connections.size(); i++) {
if (connections[i].isConnecting(component, bus, secondComponent)) {
return connections[i];
}
}
return nullopt;
}
std::string Library::getMessage(std::string key) {
return messages[key];
}
bool Library::hasConnection(ConnectionComponent component, ConnectionComponent secondComponent) { bool Library::hasConnection(ConnectionComponent component, ConnectionComponent secondComponent) {
return getConnection(component, secondComponent).has_value(); return getConnection(component, secondComponent).has_value();
@ -119,8 +134,8 @@ std::string Library::getMessage(std::string key) {
std::optional<Connection> std::optional<Connection>
Library::getConnection(ConnectionComponent component, ConnectionComponent secondComponent) { Library::getConnection(ConnectionComponent component, ConnectionComponent secondComponent) {
for(auto & connection : connections) { for (auto &connection: connections) {
if(connection.isConnecting(component, secondComponent)) { if (connection.isConnecting(component, secondComponent)) {
return connection; return connection;
} }
} }

View File

@ -1,7 +1,7 @@
#ifndef DOMAIN_LIBRARY_H #ifndef DOMAIN_LIBRARY_H
#define DOMAIN_LIBRARY_H #define DOMAIN_LIBRARY_H
#include "addressspace.h" #include "address_space.h"
#include "bus.h" #include "bus.h"
#include "component.h" #include "component.h"
#include "connection.h" #include "connection.h"
@ -10,61 +10,75 @@
#include <vector> #include <vector>
namespace domain { namespace domain {
using namespace std; using namespace std;
class Library class Library {
{ std::string name;
std::string name; std::string libraryInfo;
std::string libraryInfo; std::string header;
std::string header; std::string componentDirectory;
std::string componentDirectory; std::optional<std::string> componentHeader;
std::optional<std::string> componentHeader;
std::vector<AddressSpace> addressSpaces; std::vector<AddressSpace> addressSpaces;
std::vector<Component> components; std::vector<Component> components;
std::vector<Bus> buses; std::vector<Bus> buses;
std::vector<Connection> connections; std::vector<Connection> connections;
std::map<std::string, std::string> messages; std::map<std::string, std::string> messages;
public: public:
Library(string name, string libraryInfo, string header, string componentDirectory, std::optional<string> componentHeader, Library(string name, string libraryInfo, string header, string componentDirectory,
vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses, vector<Connection> connection, map<string, string> messages); std::optional<string> componentHeader,
vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses,
vector<Connection> connection, map<string, string> messages);
std::string getName(); std::string getName();
std::string getLibraryInfo();
std::string getHeader();
std::string getComponentDirectory();
std::optional<std::string> getComponentHeader();
std::vector<AddressSpace> getAddressSpaces(); std::string getLibraryInfo();
std::vector<Component> getComponents();
std::vector<Bus> getBuses();
std::vector<Connection> getConnections();
bool hasComponent(std::string name); std::string getHeader();
bool hasBus(std::string name);
std::map<std::string, std::string> getMessages(); std::string getComponentDirectory();
AddressSpace &getAddressSpace(std::string name); std::optional<std::string> getComponentHeader();
Component &getComponent(std::string name);
Bus &getBus(std::string bus);
std::string getMessage(std::string key);
bool hasConnection(ConnectionComponent component, std::string bus); std::vector<AddressSpace> getAddressSpaces();
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus);
bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent); std::vector<Component> getComponents();
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
bool hasConnection(ConnectionComponent component, ConnectionComponent secondComponent); std::vector<Bus> getBuses();
std::optional<Connection> getConnection(ConnectionComponent component, ConnectionComponent secondComponent);
}; std::vector<Connection> getConnections();
bool hasComponent(std::string name);
bool hasBus(std::string name);
std::map<std::string, std::string> getMessages();
AddressSpace &getAddressSpace(std::string name);
Component &getComponent(std::string name);
Bus &getBus(std::string bus);
std::string getMessage(std::string key);
bool hasConnection(ConnectionComponent component, std::string bus);
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus);
bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
bool hasConnection(ConnectionComponent component, ConnectionComponent secondComponent);
std::optional<Connection> getConnection(ConnectionComponent component, ConnectionComponent secondComponent);
};
} // namespace domain } // namespace domain

View File

@ -2,40 +2,45 @@
namespace domain { namespace domain {
PinConnection::PinConnection(std::string message, ConnectionType type) PinConnection::PinConnection(std::string message, ConnectionType type)
: message(message), type(type) : message(message), type(type) {}
{}
PinConnection::ConnectionType PinConnection::getType() { PinConnection::ConnectionType PinConnection::getType() {
return type; return type;
} }
std::string PinConnection::getMessage() {
return message; std::string PinConnection::getMessage() {
} return message;
}
Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, std::optional<std::vector<Value>> wires) Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin,
: name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) std::optional<std::vector<Value>> wires)
{} : name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) {}
std::string &Pin::getName() { std::string &Pin::getName() {
return name; return name;
} }
Pin::PinType Pin::getType() {
return type; Pin::PinType Pin::getType() {
} return type;
std::string Pin::getTooltip() { }
return tooltip;
} std::string Pin::getTooltip() {
ui::Pin &Pin::getDisplayPin() { return tooltip;
return displayPin; }
}
PinConnection &Pin::getConnection() { ui::Pin &Pin::getDisplayPin() {
return connection; return displayPin;
} }
std::optional<std::vector<Value>> &Pin::getWires() {
return wires; PinConnection &Pin::getConnection() {
} return connection;
}
std::optional<std::vector<Value>> &Pin::getWires() {
return wires;
}
} // namespace domain } // namespace domain

View File

@ -7,57 +7,61 @@
#include <string> #include <string>
namespace domain { namespace domain {
class PinConnection class PinConnection {
{ public:
public: enum ConnectionType {
enum ConnectionType { REQUIRED,
REQUIRED, OPTIONAL
OPTIONAL };
private:
std::string message;
ConnectionType type;
public:
PinConnection(std::string message, ConnectionType type);
ConnectionType getType();
std::string getMessage();
}; };
private: class Pin {
std::string message; public:
ConnectionType type; enum PinType {
IN_OUT,
IN,
OUT
};
public: private:
PinConnection(std::string message, ConnectionType type); std::string name;
PinType type;
std::string tooltip;
PinConnection connection;
domain::ui::Pin displayPin;
ConnectionType getType(); std::optional<std::vector<Value>> wires;
std::string getMessage();
};
class Pin public:
{ Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin,
public: std::optional<std::vector<Value>> wires);
enum PinType {
IN_OUT, std::string &getName();
IN,
OUT PinType getType();
std::string getTooltip();
ui::Pin &getDisplayPin();
PinConnection &getConnection();
std::optional<std::vector<Value>> &getWires();
}; };
private:
std::string name;
PinType type;
std::string tooltip;
PinConnection connection;
domain::ui::Pin displayPin;
std::optional<std::vector<Value>> wires;
public:
Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, std::optional<std::vector<Value>> wires);
std::string &getName();
PinType getType();
std::string getTooltip();
ui::Pin &getDisplayPin();
PinConnection &getConnection();
std::optional<std::vector<Value>> &getWires();
};
} // namespace domain } // namespace domain
#endif // DOMAIN_PIN_H #endif // DOMAIN_PIN_H

View File

@ -1,62 +1,61 @@
#include "rule.h" #include "rule.h"
#include <utility>
namespace domain { namespace domain {
Condition::Condition(std::string function, std::vector<Value> params, bool negated) Condition::Condition(std::string function, std::vector<Value> params, bool negated)
: negated(negated), function(function), params(params) : negated(negated), function(std::move(function)), params(std::move(params)) {}
{}
bool Condition::evaluate(RuleContext &context) { bool Condition::evaluate(RuleContext &context) {
std::vector<Value> request; std::vector<Value> request;
for(unsigned int i=0; i<params.size(); i++) { for (auto & param : params) {
if(params[i].isType(Value::ADDRESS_SPACE_REFERENCE)) { if (param.isType(Value::ADDRESS_SPACE_REFERENCE)) {
request.push_back(Value::fromAddressSpace(context.addressSpaces.at(params[i].asReference()))); request.push_back(Value::fromAddressSpace(context.addressSpaces.at(param.asReference())));
} else if(params[i].isType(Value::ATTRIBUTE_REFERENCE)) { } else if (param.isType(Value::ATTRIBUTE_REFERENCE)) {
request.push_back(context.attributes[params[i].asReference()]); request.push_back(context.attributes[param.asReference()]);
} else { } else {
request.push_back(params[i]); request.push_back(param);
}
} }
bool result = context.function[function]->validate(request);
return negated ? !result : result;
} }
bool result = context.function[function]->validate(request);
return negated ? !result : result;
}
Action::Action(ActionType type, std::string message) Action::Action(ActionType type, std::string message)
: type(type), message(message) : type(type), message(std::move(message)) {}
{}
Action::ActionType Action::getType() { Action::ActionType Action::getType() {
return type; return type;
}
std::string Action::getMessage() {
return message;
}
IfStatement::IfStatement(Condition condition, Action action)
: condition(condition), action(action)
{}
std::optional<Action> IfStatement::evaluate(RuleContext &context) {
if(condition.evaluate(context)) {
return action;
} }
return std::nullopt;
}
Rule::Rule(std::vector<IfStatement> statements) std::string Action::getMessage() {
: statements(statements) return message;
{} }
std::optional<Action> Rule::evaluate(RuleContext &context) {
for(unsigned int i=0; i<statements.size(); i++) { IfStatement::IfStatement(Condition condition, Action action)
auto response = statements[i].evaluate(context); : condition(std::move(condition)), action(std::move(action)) {}
if(response) {
return response; std::optional<Action> IfStatement::evaluate(RuleContext &context) {
if (condition.evaluate(context)) {
return action;
} }
return std::nullopt;
}
Rule::Rule(std::vector<IfStatement> statements)
: statements(std::move(statements)) {}
std::optional<Action> Rule::evaluate(RuleContext &context) {
for (auto & statement : statements) {
auto response = statement.evaluate(context);
if (response) {
return response;
}
}
return std::nullopt;
} }
return std::nullopt;
}
} // namespace domain } // namespace domain

View File

@ -1,9 +1,9 @@
#ifndef DOMAIN_RULE_H #ifndef DOMAIN_RULE_H
#define DOMAIN_RULE_H #define DOMAIN_RULE_H
#include "addressspace.h" #include "address_space.h"
#include "value.h" #include "value.h"
#include "functionsignature.h" #include "function_signature.h"
#include <map> #include <map>
#include <string> #include <string>
@ -12,58 +12,58 @@
namespace domain { namespace domain {
struct RuleContext { struct RuleContext {
std::map<std::string, AddressSpace> addressSpaces; std::map<std::string, AddressSpace> addressSpaces;
std::map<std::string, Value> attributes; std::map<std::string, Value> attributes;
std::map<std::string, FunctionValidator*> function; std::map<std::string, FunctionValidator *> function;
};
class Condition {
bool negated;
std::string function;
std::vector<Value> params;
public:
Condition(std::string function, std::vector<Value> params, bool negated);
bool evaluate(RuleContext &context);
};
class Action {
public:
enum ActionType {
ERROR,
WARNING
}; };
private: class Condition {
ActionType type; bool negated;
std::string message; std::string function;
std::vector<Value> params;
public: public:
Action(ActionType type, std::string message); Condition(std::string function, std::vector<Value> params, bool negated);
ActionType getType(); bool evaluate(RuleContext &context);
std::string getMessage(); };
};
class IfStatement { class Action {
Condition condition; public:
Action action; enum ActionType {
public: ERROR,
IfStatement(Condition condition, Action action); WARNING
};
std::optional<Action> evaluate(RuleContext &context); private:
}; ActionType type;
std::string message;
class Rule public:
{ Action(ActionType type, std::string message);
std::vector<IfStatement> statements;
public:
Rule(std::vector<IfStatement> statements);
std::optional<Action> evaluate(RuleContext &context); ActionType getType();
};
std::string getMessage();
};
class IfStatement {
Condition condition;
Action action;
public:
IfStatement(Condition condition, Action action);
std::optional<Action> evaluate(RuleContext &context);
};
class Rule {
std::vector<IfStatement> statements;
public:
explicit Rule(std::vector<IfStatement> statements);
std::optional<Action> evaluate(RuleContext &context);
};
} // namespace domain } // namespace domain

View File

@ -2,27 +2,41 @@
namespace domain { namespace domain {
Schema::Schema() bool Schema::hasConnection(string &component, string &pin) {
{ return getConnection(component, pin) != nullptr;
} }
bool Schema::hasConnection(string& component, string& pin) { ConnectionInstance *Schema::getConnection(string &component, string &pin) {
return getConnection(component, pin) != nullptr; for (auto &conn: connections) {
} if (conn->instance->name == component && conn->connection.getComponent().pin == pin) {
return conn.get();
ConnectionInstance* Schema::getConnection(string& component, string& pin) { }
for(auto& conn: connections) { auto dirConn = dynamic_cast<DirectConnectionInstance *>(conn.get());
if(conn->instance->name == component && conn->connection.getComponent().pin == pin) { if (dirConn != nullptr) {
return conn.get(); if (dirConn->secondInstance->name == component && conn->connection.getSecondComponent()->pin == pin) {
} return dirConn;
auto dirConn = dynamic_cast<DirectConnectionInstance*>(conn.get()); }
if(dirConn != nullptr) {
if(dirConn->secondInstance->name == component && conn->connection.getSecondComponent()->pin == pin) {
return dirConn;
} }
} }
return nullptr;
}
BusInstance *Schema::getBusInstance(string &name) {
for (auto &instance: busInstances) {
if (instance->name == name) {
return instance.get();
}
}
return nullptr;
}
ComponentInstance *Schema::getComponentInstance(string &name) {
for (auto &instance: componentInstances) {
if (instance->name == name) {
return instance.get();
}
}
return nullptr;
} }
return nullptr;
}
} // namespace domain } // namespace domain

View File

@ -1,45 +1,27 @@
#ifndef DOMAIN_SCHEMA_H #ifndef DOMAIN_SCHEMA_H
#define DOMAIN_SCHEMA_H #define DOMAIN_SCHEMA_H
#include "connectioninstance.h" #include "connection_instance.h"
#include "instance.h" #include "instance.h"
#include "wireinstance.h"
#include <vector> #include <vector>
namespace domain { namespace domain {
class Schema { class Schema {
public: public:
Schema(); Schema() = default;
std::vector<shared_ptr<BusInstance>> busInstances; std::vector<shared_ptr<BusInstance>> busInstances;
std::vector<shared_ptr<ComponentInstance>> componentInstances; std::vector<shared_ptr<ComponentInstance>> componentInstances;
std::vector<shared_ptr<ConnectionInstance>> connections; std::vector<shared_ptr<ConnectionInstance>> connections;
BusInstance *getBusInstance(std::string &name) { BusInstance *getBusInstance(std::string &name);
for (auto &instance: busInstances) { ComponentInstance *getComponentInstance(std::string &name);
if (instance->name == name) { bool hasConnection(string &component, string &pin);
return instance.get(); ConnectionInstance *getConnection(string &component, string &pin);
} };
}
return nullptr;
}
ComponentInstance *getComponentInstance(std::string &name) {
for (auto &instance: componentInstances) {
if (instance->name == name) {
return instance.get();
}
}
return nullptr;
}
bool hasConnection(string &component, string &pin);
ConnectionInstance *getConnection(string &component, string &pin);
};
} // namespace domain } // namespace domain

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
#ifndef DOMAIN_COMDEL_GENERATOR_H
#define DOMAIN_COMDEL_GENERATOR_H
#include "library.h"
#include "schema.h"
#include <set>
#include <utility>
#include <comdel/parser/ast_nodes.h>
#include <comdel/parser/parse_context.h>
#include <comdel/parser/presult.h>
namespace domain {
struct ComdelContext {
std::vector<Attribute> attributes;
std::vector<std::string> wires;
std::string name;
bool inComponent;
bool inConnection;
bool inSingleAutomaticConnection;
bool inBus;
ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus);
bool doesAttributeExists(std::string name, Value::ValueType type);
bool doesWireExists(std::string name);
};
class SchemaCreator {
std::vector<ComdelContext> context;
std::string name;
std::string libraryInfo;
std::string header;
std::string componentDirectory;
std::optional<std::string> componentHeader = nullopt;
std::vector<AddressSpace> addressSpaces;
std::vector<Component> components;
std::vector<Bus> buses;
std::vector<Connection> connections;
std::map<std::string, std::string> messages;
std::vector<SourceError> errors;
std::vector<FunctionValidator *> validators;
std::optional<AddressSpace> loadAddressSpace(AddressSpaceNode node);
std::optional<Component> loadComponent(ComponentNode node);
std::optional<Attribute> loadAttribute(AttributeNode node);
std::optional<Rule> loadRule(RuleNode node);
std::optional<Condition> loadCondition(ConditionNode node);
std::optional<Popup> loadPopup(PopupNode node, std::string name, Value::ValueType type);
std::optional<Display> loadDisplay(DisplayNode node);
std::optional<Wire> loadWire(WireNode node);
std::optional<Pin> loadPin(PinNode pins);
PinConnection loadPinConnection(PinConnectionNode node);
std::optional<Connection> loadConnection(ConnectionNode node);
std::optional<Bus> loadBus(BusNode node);
std::shared_ptr<ComponentInstance> loadComponentInstance(InstanceNode instance, Library &library);
std::shared_ptr<BusInstance> loadBusInstance(InstanceNode instance, Library &library);
std::optional<Bus> getBus(std::string name);
std::optional<Pin> getComponentPin(std::string name, std::string pin);
bool hasAddressSpace(std::string name);
void push(ComdelContext context);
void pushAdditional(std::string name);
ComdelContext &current();
void pop();
std::optional<Attribute> createMemoryAttribute();
vector<Enumeration> createWireEnumeration(vector<Value> enumeration);
std::optional<Popup> createMemoryPopup();
public:
explicit SchemaCreator(std::vector<FunctionValidator *> validators);
std::vector<SourceError> getErrors();
std::optional<Library> loadLibrary(LibraryNode node);
Schema *loadSchema(SchemaNode node, Library &library);
};
} // namespace domain
#endif // DOMAIN_COMDEL_GENERATOR_H

File diff suppressed because it is too large Load Diff

View File

@ -1,153 +0,0 @@
#ifndef DOMAIN_COMDEL_GENERATOR_H
#define DOMAIN_COMDEL_GENERATOR_H
#include "library.h"
#include "schema.h"
#include <set>
#include <comdel/parser/astnode.h>
#include <comdel/parser/parsecontext.h>
#include <comdel/parser/presult.h>
namespace domain {
struct ComdelContext {
std::vector<Attribute> attributes;
std::vector<std::string> wires;
std::string name;
bool inComponent;
bool inConnection;
bool inSingleAutomaticConnection;
bool inBus;
ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus)
: name(name), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection), inBus(inBus)
{}
bool doesAttributeExists(std::string name, Value::ValueType type) {
for(auto &attribute: attributes) {
if(attribute.getDefault().getType() == type && attribute.getName() == name) {
return true;
}
}
return false;
}
bool doesWireExists(std::string name) {
for(auto &w: wires) {
if(w == name) {
return true;
}
}
return false;
}
};
class SchemaCreator
{
std::vector<ComdelContext> context;
std::string name;
std::string libraryInfo;
std::string header;
std::string componentDirectory;
std::optional<std::string> componentHeader = nullopt;
std::vector<AddressSpace> addressSpaces;
std::vector<Component> components;
std::vector<Bus> buses;
std::vector<Connection> connections;
std::map<std::string, std::string> messages;
std::vector<SourceError> errors;
std::vector<FunctionValidator*> validators;
std::optional<AddressSpace> loadAddressSpace(AddressSpaceNode node);
std::optional<Component> loadComponent(ComponentNode node);
std::optional<Attribute> loadAttribute(AttributeNode node);
std::optional<Rule> loadRule(RuleNode node);
std::optional<Condition> loadCondition(ConditionNode node);
std::optional<Popup> loadPopup(PopupNode node, std::string name, Value::ValueType type);
std::optional<Display> loadDisplay(DisplayNode node);
std::optional<Wire> loadWire(WireNode node);
std::optional<Pin> loadPin(PinNode pins);
PinConnection loadPinConnection(PinConnectionNode node);
std::optional<Connection> loadConnection(ConnectionNode node);
std::optional<Bus> loadBus(BusNode node);
std::shared_ptr<ComponentInstance> loadComponentInstance(InstanceNode instance, Library &library);
std::shared_ptr<BusInstance> loadBusInstance(InstanceNode instance, Library &library);
std::optional<Attribute> createMemoryAttribute();
std::optional<Bus> getBus(std::string name) {
for(auto &bus: buses) {
if(bus.getName() == name) {
return bus;
}
}
return std::nullopt;
}
std::optional<Pin> getComponentPin(std::string name, std::string pin) {
for(auto &c: components) {
if(c.getName() == name) {
for(auto &p: c.getPins()) {
if(p.getName() == pin) {
return p;
}
}
}
}
return nullopt;
}
bool hasAddressSpace(std::string name) {
for(auto &as: addressSpaces) {
if(as.getName() == name) {
return true;
}
}
return false;
}
void push(ComdelContext context) {
this->context.push_back(context);
}
void pushAdditional(std::string name) {
if(!this->context.empty()) {
this->context.push_back(current());
current().name = name;
} else {
ComdelContext con(name, false, false, false, false);
push(con);
}
}
ComdelContext &current() {
return this->context[this->context.size() - 1];
}
void pop() {
this->context.pop_back();
}
public:
SchemaCreator(std::vector<FunctionValidator*> validators);
std::vector<SourceError> getErrors() {
return errors;
}
std::optional<Library> loadLibrary(LibraryNode node);
Schema* loadSchema(SchemaNode node, Library &library);
vector <Enumeration> createWireEnumeration(vector<Value> vector1);
std::optional<Popup> createMemoryPopup();
};
} // namespace domain
#endif // DOMAIN_COMDEL_GENERATOR_H

View File

@ -4,173 +4,160 @@
namespace domain { namespace domain {
std::string Value::string() { std::string Value::string() {
switch (type) { switch (type) {
case INT: case INT:
return std::to_string(intValue); return std::to_string(intValue);
case BOOL: case BOOL:
return boolValue ? "true" : "false"; return boolValue ? "true" : "false";
case STRING: case STRING:
return stringValue;
case NIL:
return "null";
case UNDEFINED:
return "undefined";
case ADDRESS_SPACE:
return "AddressSpace::" + addressSpace->getName();
case WIRE_REFERENCE:
return "Wire::" + reference;
case ADDRESS_SPACE_REFERENCE:
return "AddressSpace::" + reference;
case ATTRIBUTE_REFERENCE:
return "Attribute::" + reference;
case MEMORY_REFERENCE:
if (memoryReference.has_value()) {
return "Memory::" + *memoryReference;
} else {
return "Memory::null";
}
default:
return "unknown";
}
}
Value::ValueType Value::getType() {
return type;
}
bool Value::isType(Value::ValueType _type) {
return 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; return stringValue;
case NIL: }
return "null"; throw std::exception();
case UNDEFINED:
return "undefined";
case ADDRESS_SPACE:
return "AddressSpace::" + addressSpace->getName();
case WIRE_REFERENCE:
return "Wire::" + reference;
case ADDRESS_SPACE_REFERENCE:
return "AddressSpace::" + reference;
case ATTRIBUTE_REFERENCE:
return "Attribute::" + reference;
default:
return "unknown";
} }
}
bool Value::asBool() {
if (isType(Value::BOOL)) {
return boolValue;
}
throw std::exception();
}
Value::ValueType Value::getType() { AddressSpace Value::asAddressSpace() {
return type; if (isType(Value::ADDRESS_SPACE)) {
} return *addressSpace;
bool Value::isType(Value::ValueType type) { }
return this->type == type; throw std::exception();
} }
long long Value::asInt() { std::string Value::asReference() {
if(isType(Value::INT)) { if (isType(Value::WIRE_REFERENCE) || isType(Value::ADDRESS_SPACE_REFERENCE) ||
return intValue; isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) {
return reference;
}
throw std::exception();
} }
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::ADDRESS_SPACE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) {
return reference;
}
throw std::exception();
}
std::optional<std::string> Value::asMemoryReference() {
std::optional<std::string> Value::asMemoryReference() { return memoryReference;
return memoryReference; }
}
domain::ComponentInstance *Value::asMemory() { domain::ComponentInstance *Value::asMemory() {
return memory; return memory;
} }
void Value::setInt(long long value) { void Value::setInt(long long value) {
if(isType(Value::INT)) { if (isType(Value::INT)) {
this->intValue = value; this->intValue = value;
}
throw std::exception();
} }
throw std::exception();
} void Value::setString(std::string value) {
void Value::setString(std::string value) { if (isType(Value::STRING)) {
if(isType(Value::STRING)) { this->stringValue = value;
this->stringValue = value; }
throw std::exception();
} }
throw std::exception();
} void Value::setBool(bool value) {
void Value::setBool(bool value) { if (isType(Value::BOOL)) {
if(isType(Value::BOOL)) { this->boolValue = value;
this->boolValue = value; }
throw std::exception();
} }
throw std::exception();
} void Value::setReference(std::string value) {
void Value::setReference(std::string value) { if (isType(Value::WIRE_REFERENCE)) {
if(isType(Value::WIRE_REFERENCE)) { this->reference = value;
this->reference = value; }
throw std::exception();
} }
throw std::exception();
}
Value Value::fromInt(long long value) { Value Value::fromInt(long long value) {
Value val; Value val;
val.type = Value::INT; val.type = Value::INT;
val.intValue = value; val.intValue = value;
return val; return val;
} }
Value Value::fromString(std::string value) {
Value val; Value Value::fromString(std::string value) {
val.type = Value::STRING; Value val;
val.stringValue = value; val.type = Value::STRING;
return val; val.stringValue = value;
} return val;
Value Value::fromBool(bool value) { }
Value val;
val.type = Value::BOOL; Value Value::fromBool(bool value) {
val.boolValue = value; Value val;
return val; val.type = Value::BOOL;
} val.boolValue = value;
Value Value::fromAddressSpace(AddressSpace addressSpace) { return val;
Value val; }
val.type = Value::ADDRESS_SPACE;
val.addressSpace = addressSpace; Value Value::fromAddressSpace(AddressSpace addressSpace) {
return val; Value val;
} val.type = Value::ADDRESS_SPACE;
Value Value::fromReference(std::string value, Value::ValueType type) { val.addressSpace = addressSpace;
Value val; return val;
val.type = type; }
val.reference = value;
return val; Value Value::fromReference(std::string value, Value::ValueType type) {
} Value val;
val.type = type;
Value Value::ofType(Value::ValueType type) { val.reference = value;
Value val; return val;
val.type = type; }
return val;
} Value Value::fromNull() {
Value val;
Value Value::fromNull() { val.type = Value::NIL;
Value val; return val;
val.type = Value::NIL;
return val;
}
std::string Value::stringify() {
switch (type) {
case INT:
return std::to_string(intValue);
case BOOL:
return boolValue ? "true" : "false";
case STRING:
return "\"" + stringValue + "\"";
case NIL:
return "null";
case WIRE_REFERENCE:
case ADDRESS_SPACE_REFERENCE:
case ATTRIBUTE_REFERENCE:
return reference;
case MEMORY_REFERENCE:
if(memoryReference.has_value()) {
return memoryReference.value();
} else {
return "null";
}
default:
throw std::exception();
} }
}
Value Value::fromMemoryReference(std::optional<std::string> value) { Value Value::fromMemoryReference(std::optional<std::string> value) {
Value val; Value val;
@ -179,10 +166,34 @@ std::string Value::stringify() {
return val; return val;
} }
Value Value::fromMemory(domain::ComponentInstance *memory) { std::string Value::stringify() {
switch (type) {
case INT:
return std::to_string(intValue);
case BOOL:
return boolValue ? "true" : "false";
case STRING:
return "\"" + stringValue + "\"";
case NIL:
return "null";
case WIRE_REFERENCE:
case ADDRESS_SPACE_REFERENCE:
case ATTRIBUTE_REFERENCE:
return reference;
case MEMORY_REFERENCE:
if (memoryReference.has_value()) {
return memoryReference.value();
} else {
return "null";
}
default:
throw std::exception();
}
}
Value Value::ofType(Value::ValueType type) {
Value val; Value val;
val.type = MEMORY; val.type = type;
val.memory = memory;
return val; return val;
} }

View File

@ -1,7 +1,7 @@
#ifndef DOMAIN_VALUE_H #ifndef DOMAIN_VALUE_H
#define DOMAIN_VALUE_H #define DOMAIN_VALUE_H
#include "addressspace.h" #include "address_space.h"
#include <string> #include <string>
#include <optional> #include <optional>
@ -11,96 +11,111 @@ namespace domain {
class ComponentInstance; class ComponentInstance;
class Value class Value {
{ public:
public: enum ValueType {
enum ValueType { INT,
INT, STRING,
STRING, BOOL,
BOOL, ADDRESS_SPACE,
ADDRESS_SPACE, ADDRESS_SPACE_REFERENCE,
ADDRESS_SPACE_REFERENCE, ATTRIBUTE_REFERENCE,
ATTRIBUTE_REFERENCE, MEMORY_REFERENCE,
MEMORY_REFERENCE, MEMORY,
MEMORY, WIRE_REFERENCE,
WIRE_REFERENCE, NIL,
NIL, UNDEFINED,
UNDEFINED, };
};
private: private:
long long intValue = 0; long long intValue = 0;
std::string stringValue; std::string stringValue;
bool boolValue = false; bool boolValue = false;
std::optional<AddressSpace> addressSpace = std::nullopt; std::optional<AddressSpace> addressSpace = std::nullopt;
std::string reference; std::string reference;
domain::ComponentInstance *memory = nullptr; domain::ComponentInstance *memory = nullptr;
std::optional<std::string> memoryReference = std::nullopt; std::optional<std::string> memoryReference = std::nullopt;
ValueType type = UNDEFINED; ValueType type = UNDEFINED;
public: public:
Value() {} Value() = default;
bool equals(Value value) { bool equals(Value value) {
if(value.getType() == type) { if (value.getType() == type) {
switch (type) { switch (type) {
case INT: case INT:
return value.asInt() == intValue; return value.asInt() == intValue;
case STRING: case STRING:
return value.asString() == stringValue; return value.asString() == stringValue;
case NIL: case NIL:
case UNDEFINED: case UNDEFINED:
return true; return true;
case WIRE_REFERENCE: case WIRE_REFERENCE:
case ATTRIBUTE_REFERENCE: case ATTRIBUTE_REFERENCE:
case ADDRESS_SPACE_REFERENCE: case ADDRESS_SPACE_REFERENCE:
return value.asReference() == reference; return value.asReference() == reference;
case MEMORY_REFERENCE: case MEMORY_REFERENCE:
return value.asMemoryReference() == memoryReference; return value.asMemoryReference() == memoryReference;
case MEMORY: case MEMORY:
return value.asMemory() == memory; return value.asMemory() == memory;
case BOOL: case BOOL:
return value.asBool() == boolValue; return value.asBool() == boolValue;
default: default:
return false; return false;
}
} }
return false;
} }
return false;
}
std::string string(); std::string string();
ValueType getType(); ValueType getType();
bool isType(ValueType type);
long long asInt(); bool isType(ValueType type);
std::string asString();
bool asBool();
std::string asReference();
std::optional<std::string> asMemoryReference();
domain::ComponentInstance* asMemory();
AddressSpace asAddressSpace();
void setInt(long long intValue); long long asInt();
void setString(std::string value);
void setBool(bool value);
void setReference(std::string value);
std::string stringify(); std::string asString();
static Value fromInt(long long value); bool asBool();
static Value fromString(std::string value);
static Value fromBool(bool value); std::string asReference();
static Value fromNull();
static Value fromAddressSpace(AddressSpace addressSpace); std::optional<std::string> asMemoryReference();
static Value fromReference(std::string value, ValueType type);
static Value ofType(ValueType type); domain::ComponentInstance *asMemory();
static Value fromMemoryReference(std::optional<std::string> memoryReference);
static Value fromMemory(domain::ComponentInstance *memory); AddressSpace asAddressSpace();
};
void setInt(long long intValue);
void setString(std::string value);
void setBool(bool value);
void setReference(std::string value);
std::string stringify();
static Value fromInt(long long value);
static Value fromString(std::string value);
static Value fromBool(bool value);
static Value fromNull();
static Value fromAddressSpace(AddressSpace addressSpace);
static Value fromReference(std::string value, ValueType type);
static Value fromMemoryReference(std::optional<std::string> memoryReference);
static Value ofType(ValueType type);
};
} // namespace domain } // namespace domain

View File

@ -1,10 +0,0 @@
#include "wireinstance.h"
namespace domain {
WireInstance::WireInstance(std::string name, Display display, std::pair<int, int> position)
: name(name), display(display), position(position)
{}
} // namespace domain

View File

@ -1,24 +0,0 @@
#ifndef DOMAIN_WIRE_INSTANCE_H
#define DOMAIN_WIRE_INSTANCE_H
#include "display.h"
#include <string>
namespace domain {
class WireInstance
{
public:
std::string name;
Display display;
std::pair<int, int> position;
WireInstance(std::string name, Display display, std::pair<int, int> position);
};
} // namespace domain
#endif // DOMAIN_WIREINSTANCE_H

View File

@ -1,4 +1,4 @@
#include "astnode.h" #include "ast_nodes.h"
/*************************** AST NODE ********************************/ /*************************** AST NODE ********************************/
@ -6,17 +6,17 @@ AstNode::~AstNode() = default;
/*************************** NUMBER NODE ********************************/ /*************************** NUMBER NODE ********************************/
NumberNode::NumberNode(const std::string& expression) { NumberNode::NumberNode(const std::string &expression) {
if(expression.size() > 2) { if (expression.size() > 2) {
if(expression.substr(0, 2) == "0x") { if (expression.substr(0, 2) == "0x") {
this->value = std::stoll(expression, 0, 16); this->value = std::stoll(expression, nullptr, 16);
} else if(expression.substr(0, 2) == "0b") { } else if (expression.substr(0, 2) == "0b") {
this->value = std::stoll(expression, 0, 2); this->value = std::stoll(expression, nullptr, 2);
} else { } else {
this->value = std::stoll(expression, 0, 10); this->value = std::stoll(expression, nullptr, 10);
} }
} else { } else {
this->value = std::stoll(expression, 0, 10); this->value = std::stoll(expression, nullptr, 10);
} }
} }
@ -29,28 +29,28 @@ std::string StringNode::asString() {
/*************************** VALUE NODE ********************************/ /*************************** VALUE NODE ********************************/
long long ValueNode::asInt() { long long ValueNode::asInt() {
if(is(INT)) { if (is(INT)) {
return intValue.value(); return intValue.value();
} }
return 0; return 0;
} }
std::string ValueNode::asString() { std::string ValueNode::asString() {
if(is(STRING)) { if (is(STRING)) {
return stringValue.value(); return stringValue.value();
} }
return ""; return "";
} }
std::string ValueNode::asIdentifier() { std::string ValueNode::asIdentifier() {
if(is(IDENTIFIER) || is(WIRE)) { if (is(IDENTIFIER) || is(WIRE)) {
return identifierValue.value(); return identifierValue.value();
} }
return ""; return "";
} }
bool ValueNode::asBool() { bool ValueNode::asBool() {
if(is(BOOL)) { if (is(BOOL)) {
return boolValue.value(); return boolValue.value();
} }
return false; return false;

View File

@ -2,8 +2,9 @@
#define AST_NODE_H #define AST_NODE_H
#include "token.h" #include "token.h"
#include "sourceerror.h" #include "source_error.h"
#include <optional> #include <optional>
#include <utility>
#include <vector> #include <vector>
/** /**
@ -19,58 +20,60 @@ public:
virtual ~AstNode(); virtual ~AstNode();
AstNode(AstNode&&) = default; AstNode(AstNode &&) = default;
AstNode& operator=(AstNode&&) = default;
AstNode(const AstNode&) = default; AstNode &operator=(AstNode &&) = default;
AstNode& operator=(const AstNode&) = default;
AstNode(const AstNode &) = default;
AstNode &operator=(const AstNode &) = default;
}; };
template <typename T> template<typename T>
struct EnumNode: public AstNode struct EnumNode : public AstNode {
{
EnumNode() = default; EnumNode() = default;
explicit EnumNode(T value): value(value) {}
explicit EnumNode(T value) : value(value) {}
T value; T value;
}; };
struct StringNode: public AstNode struct StringNode : public AstNode {
{
std::string value; std::string value;
std::string asString(); std::string asString();
}; };
struct IdentifierNode: public AstNode struct IdentifierNode : public AstNode {
{
std::string value; std::string value;
}; };
struct NumberNode: public AstNode { struct NumberNode : public AstNode {
long long int value; long long int value;
explicit NumberNode(const std::string& expression);
NumberNode(): value(0) {} explicit NumberNode(const std::string &expression);
NumberNode() : value(0) {}
}; };
struct CountNode: public AstNode struct CountNode : public AstNode {
{
NumberNode first; NumberNode first;
NumberNode second; NumberNode second;
CountNode(NumberNode first, NumberNode second): first(first), second(second) {} CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {}
CountNode() = default; CountNode() = default;
}; };
struct AddressSpaceNode: public AstNode struct AddressSpaceNode : public AstNode {
{
IdentifierNode name; IdentifierNode name;
NumberNode start; NumberNode start;
NumberNode end; NumberNode end;
}; };
class ValueNode: public AstNode class ValueNode : public AstNode {
{
public: public:
enum ValueType { enum ValueType {
INT, INT,
@ -92,33 +95,42 @@ private:
public: public:
ValueNode() = default; ValueNode() = default;
ValueType getType() { ValueType getType() const {
return type.value; return type.value;
} }
long long asInt(); long long asInt();
std::string asString(); std::string asString();
std::string asIdentifier(); std::string asIdentifier();
bool asBool(); bool asBool();
bool is(ValueType valueType); bool is(ValueType valueType);
static ValueNode ofBool(bool _value); static ValueNode ofBool(bool _value);
static ValueNode ofInt(long long _value); static ValueNode ofInt(long long _value);
static ValueNode ofString(std::string _value); static ValueNode ofString(std::string _value);
static ValueNode ofIdentifier(std::string _value); static ValueNode ofIdentifier(std::string _value);
static ValueNode ofMemory(std::optional<std::string> _value); static ValueNode ofMemory(std::optional<std::string> _value);
static ValueNode ofNull(); static ValueNode ofNull();
static ValueNode ofWire(std::optional<std::string> _value); static ValueNode ofWire(std::optional<std::string> _value);
}; };
struct ConditionNode struct ConditionNode {
{
bool negated; bool negated;
IdentifierNode functionName; IdentifierNode functionName;
std::vector<ValueNode> params; std::vector<ValueNode> params;
}; };
class ActionNode: public AstNode { class ActionNode : public AstNode {
public: public:
enum ActionType { enum ActionType {
ERROR, ERROR,
@ -130,25 +142,21 @@ public:
}; };
struct IfStatementNode: public AstNode struct IfStatementNode : public AstNode {
{
ConditionNode condition; ConditionNode condition;
ActionNode action; ActionNode action;
}; };
struct RuleNode: public AstNode struct RuleNode : public AstNode {
{
std::vector<IfStatementNode> statements; std::vector<IfStatementNode> statements;
}; };
struct EnumerationNode: public AstNode struct EnumerationNode : public AstNode {
{
StringNode key; StringNode key;
ValueNode value; ValueNode value;
}; };
struct PopupNode: public AstNode struct PopupNode : public AstNode {
{
enum PopupType { enum PopupType {
AUTOMATIC, AUTOMATIC,
ON_DEMAND ON_DEMAND
@ -164,24 +172,22 @@ struct PopupNode: public AstNode
std::vector<RuleNode> rules; std::vector<RuleNode> rules;
}; };
struct PropertyNode: public AstNode struct PropertyNode : public AstNode {
{
IdentifierNode key; IdentifierNode key;
ValueNode value; ValueNode value;
}; };
struct DisplayItemNode: public AstNode struct DisplayItemNode : public AstNode {
{
IdentifierNode type; IdentifierNode type;
std::vector<PropertyNode> values; std::vector<PropertyNode> values;
long long int asInt(std::vector<SourceError>* errors, const std::string& property, long long int _default = 0) { long long int asInt(std::vector<SourceError> *errors, const std::string &property, long long int _default = 0) {
for(auto& prop: values) { for (auto &prop: values) {
if(prop.key.value == property) { if (prop.key.value == property) {
if(prop.value.is(ValueNode::INT)) { if (prop.value.is(ValueNode::INT)) {
return prop.value.asInt(); return prop.value.asInt();
} else { } else {
if(errors != nullptr) { if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected number"); errors->emplace_back(prop.value.span, "expected number");
} }
} }
@ -190,13 +196,13 @@ struct DisplayItemNode: public AstNode
return _default; return _default;
} }
std::string asIdentifier(std::vector<SourceError>* errors, const std::string& property, std::string _default = "") { std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
for(auto& prop: values) { for (auto &prop: values) {
if(prop.key.value == property) { if (prop.key.value == property) {
if(prop.value.is(ValueNode::IDENTIFIER)) { if (prop.value.is(ValueNode::IDENTIFIER)) {
return prop.value.asIdentifier(); return prop.value.asIdentifier();
} else { } else {
if(errors != nullptr) { if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected identifier"); errors->emplace_back(prop.value.span, "expected identifier");
} }
} }
@ -206,13 +212,13 @@ struct DisplayItemNode: public AstNode
} }
std::string asString(std::vector<SourceError>* errors, const std::string& property, std::string _default = "") { std::string asString(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
for(auto& prop: values) { for (auto &prop: values) {
if(prop.key.value == property) { if (prop.key.value == property) {
if(prop.value.is(ValueNode::STRING)) { if (prop.value.is(ValueNode::STRING)) {
return prop.value.asString(); return prop.value.asString();
} else { } else {
if(errors != nullptr) { if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected string"); errors->emplace_back(prop.value.span, "expected string");
} }
} }
@ -222,13 +228,11 @@ struct DisplayItemNode: public AstNode
} }
}; };
struct DisplayNode: public AstNode struct DisplayNode : public AstNode {
{
std::vector<DisplayItemNode> items; std::vector<DisplayItemNode> items;
}; };
struct PinConnectionNode: public AstNode struct PinConnectionNode : public AstNode {
{
enum ConnectionType { enum ConnectionType {
REQUIRED, REQUIRED,
OPTIONAL OPTIONAL
@ -238,8 +242,7 @@ struct PinConnectionNode: public AstNode
EnumNode<ConnectionType> type; EnumNode<ConnectionType> type;
}; };
struct PinNode: public AstNode struct PinNode : public AstNode {
{
enum PinType { enum PinType {
IN_OUT, IN_OUT,
IN, IN,
@ -254,8 +257,7 @@ struct PinNode: public AstNode
std::optional<std::vector<ValueNode>> wires; std::optional<std::vector<ValueNode>> wires;
}; };
struct WireNode: public AstNode struct WireNode : public AstNode {
{
enum WireType { enum WireType {
WIRE, WIRE,
WIRED_AND, WIRED_AND,
@ -272,22 +274,19 @@ struct WireNode: public AstNode
ValueNode terminateWith; ValueNode terminateWith;
}; };
struct AttributeNode: public AstNode struct AttributeNode : public AstNode {
{
ValueNode::ValueType type; ValueNode::ValueType type;
IdentifierNode name; IdentifierNode name;
std::optional<ValueNode> defaultValue; std::optional<ValueNode> defaultValue;
std::optional<PopupNode> popup; std::optional<PopupNode> popup;
}; };
struct ConnectionComponentNode: public AstNode struct ConnectionComponentNode : public AstNode {
{
IdentifierNode component; IdentifierNode component;
IdentifierNode pin; IdentifierNode pin;
}; };
struct ConnectionNode: public AstNode struct ConnectionNode : public AstNode {
{
ConnectionComponentNode first; ConnectionComponentNode first;
std::optional<ConnectionComponentNode> second; std::optional<ConnectionComponentNode> second;
@ -298,8 +297,7 @@ struct ConnectionNode: public AstNode
std::optional<std::vector<ValueNode>> secondWires; std::optional<std::vector<ValueNode>> secondWires;
}; };
struct ComponentNode: public AstNode struct ComponentNode : public AstNode {
{
enum ComponentType { enum ComponentType {
OTHER, OTHER,
PROCESSOR, PROCESSOR,
@ -318,8 +316,7 @@ struct ComponentNode: public AstNode
std::vector<AttributeNode> attributes; std::vector<AttributeNode> attributes;
}; };
struct BusNode: public AstNode struct BusNode : public AstNode {
{
enum BusType { enum BusType {
AUTOMATIC, AUTOMATIC,
REGULAR, REGULAR,
@ -335,8 +332,7 @@ struct BusNode: public AstNode
std::vector<WireNode> wires; std::vector<WireNode> wires;
}; };
struct LibraryNode: public AstNode struct LibraryNode : public AstNode {
{
std::optional<StringNode> name; std::optional<StringNode> name;
std::optional<StringNode> libraryInfo; std::optional<StringNode> libraryInfo;
std::optional<StringNode> header; std::optional<StringNode> header;
@ -353,14 +349,12 @@ struct LibraryNode: public AstNode
}; };
// SCHEMA models // SCHEMA models
struct InstanceAttributeNode: public AstNode struct InstanceAttributeNode : public AstNode {
{
IdentifierNode name; IdentifierNode name;
ValueNode value; ValueNode value;
}; };
struct InstanceNode: public AstNode struct InstanceNode : public AstNode {
{
IdentifierNode name; IdentifierNode name;
IdentifierNode component; IdentifierNode component;
@ -370,14 +364,12 @@ struct InstanceNode: public AstNode
std::optional<NumberNode> size; std::optional<NumberNode> size;
}; };
struct ConnectionComponentInstance: public AstNode struct ConnectionComponentInstance : public AstNode {
{
IdentifierNode instance; IdentifierNode instance;
IdentifierNode pin; IdentifierNode pin;
}; };
struct ConnectionInstanceNode: public AstNode struct ConnectionInstanceNode : public AstNode {
{
ConnectionComponentInstance first; ConnectionComponentInstance first;
std::optional<ConnectionComponentInstance> second; std::optional<ConnectionComponentInstance> second;
@ -387,8 +379,7 @@ struct ConnectionInstanceNode: public AstNode
}; };
struct SchemaNode: public AstNode struct SchemaNode : public AstNode {
{
std::optional<StringNode> source; std::optional<StringNode> source;
std::vector<InstanceNode> instances; std::vector<InstanceNode> instances;

View File

@ -1,10 +1,10 @@
#ifndef COMDEL_PARSER_H #ifndef COMDEL_PARSER_H
#define COMDEL_PARSER_H #define COMDEL_PARSER_H
#include "sourceerror.h" #include "source_error.h"
#include "presult.h" #include "presult.h"
#include "token.h" #include "token.h"
#include "astnode.h" #include "ast_nodes.h"
#include <optional> #include <optional>
#include <set> #include <set>
@ -18,23 +18,21 @@
class Spanner { class Spanner {
// REFERENCE to the parser's prevSpan. After parsing a node this will // REFERENCE to the parser's prevSpan. After parsing a node this will
// "point" to the span of the last token contained in the node. // "point" to the span of the last token contained in the node.
const Span& prevSpan; const Span &prevSpan;
public: public:
const Span lo; // the low end of the span, beginning of the node const Span lo; // the low end of the span, beginning of the node
Spanner(Span lo, Span &prevSpan) : lo(lo), prevSpan(prevSpan) {}
Spanner(Span lo, Span& prevSpan) : lo(lo), prevSpan(prevSpan) {} template<typename T, typename = std::enable_if<std::is_base_of<AstNode, T>::value>>
typename std::remove_reference_t<T> operator()(T &&astNode) const {
template <typename T, typename = std::enable_if<std::is_base_of<AstNode, T>::value>>
typename std::remove_reference_t<T> operator()(T&& astNode) const {
astNode.span = lo.to(prevSpan); astNode.span = lo.to(prevSpan);
return std::move(astNode); return std::forward<T>(astNode);
} }
}; };
class ComdelParser class ComdelParser {
{
private: private:
std::vector<Token> tokens; std::vector<Token> tokens;
std::set<TokenType> expectedTokens; std::set<TokenType> expectedTokens;
@ -47,6 +45,7 @@ private:
void bump(); void bump();
bool consume(TokenType tokenType); bool consume(TokenType tokenType);
bool check(TokenType tokenType); bool check(TokenType tokenType);
void skipUntilNextKeyword(); void skipUntilNextKeyword();
@ -57,53 +56,79 @@ private:
template<typename T> template<typename T>
PResult<std::vector<T>> parseList(std::optional<TokenType> openDelim, PResult<std::vector<T>> parseList(std::optional<TokenType> openDelim,
TokenType closeDelim, TokenType closeDelim,
std::optional<TokenType> separator, std::optional<TokenType> separator,
bool allowTrailing, bool allowTrailing,
const std::function<PResult<T> ()> &parse_f); const std::function<PResult<T>()> &parse_f);
Spanner getSpanner(); Spanner getSpanner();
// used to parse library and schema
PResult<StringNode> parseString(); PResult<StringNode> parseString();
PResult<IdentifierNode> parseIdentifier(); PResult<IdentifierNode> parseIdentifier();
PResult<NumberNode> parseNumber(); PResult<NumberNode> parseNumber();
PResult<CountNode> parseCount(); PResult<CountNode> parseCount();
PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType); PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType);
PResult<EnumerationNode> parseEnumeration(); PResult<EnumerationNode> parseEnumeration();
PResult<ValueNode> parseConnectionWire(); PResult<ValueNode> parseConnectionWire();
PResult<ComponentNode> parseComponent(); PResult<ComponentNode> parseComponent();
PResult<AddressSpaceNode> parseAddress(); PResult<AddressSpaceNode> parseAddress();
PResult<PinNode> parsePin(); PResult<PinNode> parsePin();
PResult<DisplayNode> parseDisplay(); PResult<DisplayNode> parseDisplay();
PResult<PinConnectionNode> parsePinConnection(); PResult<PinConnectionNode> parsePinConnection();
PResult<AttributeNode> parseAttribute(); PResult<AttributeNode> parseAttribute();
PResult<PopupNode> parsePopup(); PResult<PopupNode> parsePopup();
PResult<RuleNode> parseRule(); PResult<RuleNode> parseRule();
PResult<BusNode> parseBus(); PResult<BusNode> parseBus();
PResult<WireNode> parseWire(); PResult<WireNode> parseWire();
PResult<ConnectionNode> parseConnection(); PResult<ConnectionNode> parseConnection();
PResult<DisplayItemNode> parseDisplayItem(); PResult<DisplayItemNode> parseDisplayItem();
PResult<IfStatementNode> parseIfStatement(); PResult<IfStatementNode> parseIfStatement();
PResult<ValueNode> parseValue(); PResult<ValueNode> parseValue();
// used to parse schema
PResult<CountNode> parsePosition(); PResult<CountNode> parsePosition();
PResult<InstanceNode> parseInstance();
PResult<InstanceAttributeNode> parseInstanceAttribute();
PResult<ConnectionInstanceNode> parseConnectionInstance();
public: PResult<InstanceNode> parseInstance();
ComdelParser(std::vector<Token> tokens);
std::optional<SchemaNode> parseSchema(); PResult<InstanceAttributeNode> parseInstanceAttribute();
std::optional<LibraryNode> parse();
const std::vector<SourceError>& getErrors(); PResult<ConnectionInstanceNode> parseConnectionInstance();
PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType(); PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType();
PResult<EnumNode<BusNode::BusType>> parseBusType(); PResult<EnumNode<BusNode::BusType>> parseBusType();
PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType(); PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType();
public:
explicit ComdelParser(std::vector<Token> tokens);
std::optional<SchemaNode> parseSchema();
std::optional<LibraryNode> parseLibrary();
const std::vector<SourceError> &getErrors();
}; };
#endif // COMDEL_PARSER_H #endif // COMDEL_PARSER_H

View File

@ -1,6 +1,6 @@
#include "comdellexer.h" #include "comdellexer.h"
#include "token.h" #include "token.h"
#include "tokenstype.h" #include "tokens_type.h"
#include <fstream> #include <fstream>
#include <cctype> #include <cctype>
@ -36,14 +36,13 @@ inline bool isWhitespace(char ch) {
*************************************************************************/ *************************************************************************/
ComdelLexer::ComdelLexer(std::string fileName, std::string source, ComdelLexer::ComdelLexer(std::string fileName, std::string source,
ParseContext* parseContext) ParseContext *parseContext)
: source(std::move(source)), : source(std::move(source)),
parseContext(parseContext), parseContext(parseContext),
// TODO Update this // TODO Update this
fileId(this->parseContext->addFile(fileName, this->source)), fileId(this->parseContext->addFile(fileName, this->source)),
position(this->fileId, 1, 1, 0), position(this->fileId, 1, 1, 0),
ch(this->source[0]) ch(this->source[0]) {}
{}
LexerResult ComdelLexer::tokenize() { LexerResult ComdelLexer::tokenize() {
@ -51,11 +50,11 @@ LexerResult ComdelLexer::tokenize() {
tokenBegin = position; tokenBegin = position;
auto tokenType = nextTokenType(); auto tokenType = nextTokenType();
if(!tokenType) { if (!tokenType) {
errors.push_back(tokenType.error()); errors.push_back(tokenType.error());
continue; continue;
} }
if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) { if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) {
continue; continue;
} }
@ -67,9 +66,9 @@ LexerResult ComdelLexer::tokenize() {
tokens.emplace_back(*tokenType, Span(tokenBegin, position), text); tokens.emplace_back(*tokenType, Span(tokenBegin, position), text);
} }
tokens.emplace_back( TokenType::END_OF_FILE, Span(position), ""); tokens.emplace_back(TokenType::END_OF_FILE, Span(position), "");
return LexerResult { tokens, errors }; return LexerResult{tokens, errors};
} }
@ -86,11 +85,11 @@ LexerResult ComdelLexer::tokenize() {
unsigned ComdelLexer::takeNumberInRadix(Radix radix) { unsigned ComdelLexer::takeNumberInRadix(Radix radix) {
unsigned digitsTaken = 0; unsigned digitsTaken = 0;
while(true) { while (true) {
if (digitIsValid(ch, radix)) { // skip and count real digits if (digitIsValid(ch, radix)) { // skip and count real digits
bump(); bump();
digitsTaken++; digitsTaken++;
} else if(ch == '_') { // skip underscores } else if (ch == '_') { // skip underscores
bump(); bump();
} else { // some other character => end of number } else { // some other character => end of number
return digitsTaken; return digitsTaken;
@ -103,26 +102,26 @@ bool ComdelLexer::digitIsValid(char ch, Radix radix) {
// Check valid digits // Check valid digits
// digit is 0..1 // digit is 0..1
if(ch == '1' || ch == '0') { if (ch == '1' || ch == '0') {
// OK for all radixes // OK for all radixes
return true; return true;
} }
//digit is 2..9 //digit is 2..9
if(isdigit(ch)) { if (isdigit(ch)) {
// OK for decimal and hex radixes // OK for decimal and hex radixes
return(radix != Radix::BIN_NUMBER); return (radix != Radix::BIN_NUMBER);
} }
// digit is a..f A..F // digit is a..f A..F
else if(isxdigit(ch)) { else if (isxdigit(ch)) {
// OK only for hex radix // OK only for hex radix
return(radix ==Radix::HEX_NUMBER); return (radix == Radix::HEX_NUMBER);
} }
// NOT 0..9 a..f A..F // NOT 0..9 a..f A..F
return false; return false;
} }
ComdelLexer::Radix ComdelLexer::takeRadix(){ ComdelLexer::Radix ComdelLexer::takeRadix() {
if (ch == '0') { if (ch == '0') {
char nextChar = peek(); char nextChar = peek();
if (nextChar == 'x' || nextChar == 'X') { if (nextChar == 'x' || nextChar == 'X') {
@ -141,7 +140,7 @@ ComdelLexer::Radix ComdelLexer::takeRadix(){
unsigned ComdelLexer::takeHexColor() { unsigned ComdelLexer::takeHexColor() {
unsigned digitsTaken = 0; unsigned digitsTaken = 0;
while(true) { while (true) {
if (digitIsValid(ch, Radix::HEX_NUMBER)) { // skip and count hex digits if (digitIsValid(ch, Radix::HEX_NUMBER)) { // skip and count hex digits
bump(); bump();
digitsTaken++; digitsTaken++;
@ -162,10 +161,10 @@ PResult<TokenType> ComdelLexer::takeString() {
// Check escape-sequences \t \n \\ \" but leave them in string. // Check escape-sequences \t \n \\ \" but leave them in string.
// They will be replaced in the constructor of StringLiteral AST-node. // They will be replaced in the constructor of StringLiteral AST-node.
while (ch != '"' && ch != '\n' && !eof()) { while (ch != '"' && ch != '\n' && !eof()) {
if(ch == '"') { if (ch == '"') {
// possible start of escape-sequence // possible start of escape-sequence
char nextCh = peek(); char nextCh = peek();
if(nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n') if (nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n')
bump(); // legal escape-sequence: skip backslash bump(); // legal escape-sequence: skip backslash
else else
return PError({Span(lo, position), "illegal escape-sequence (allowed: \\n \\\" \\\\ \\t"}); return PError({Span(lo, position), "illegal escape-sequence (allowed: \\n \\\" \\\\ \\t"});
@ -177,12 +176,11 @@ PResult<TokenType> ComdelLexer::takeString() {
return PError({Span(lo, position), "unterminated string"}); return PError({Span(lo, position), "unterminated string"});
} }
bump(); // skip closing " bump(); // skip closing "
return TokenType::STRING; return TokenType::STRING;
} }
PResult<TokenType> ComdelLexer::takeRawString() PResult<TokenType> ComdelLexer::takeRawString() {
{
Position lo = position; Position lo = position;
if (ch != '`') if (ch != '`')
@ -198,7 +196,7 @@ PResult<TokenType> ComdelLexer::takeRawString()
return PError({Span(lo, position), "unterminated string"}); return PError({Span(lo, position), "unterminated string"});
} }
bump(); // skip closing ' bump(); // skip closing '
return TokenType::STRING; return TokenType::STRING;
} }
@ -237,21 +235,16 @@ bool ComdelLexer::skipMultilineComment() {
PResult<TokenType> ComdelLexer::nextTokenType() { PResult<TokenType> ComdelLexer::nextTokenType() {
if (isWhitespace(ch)) if (isWhitespace(ch)) {
{
skipWhitespace(); skipWhitespace();
return TokenType::WHITESPACE; return TokenType::WHITESPACE;
} } else if (identifierStart(ch)) {
else if (identifierStart(ch))
{
bump(); bump();
while (identifierContinue(ch)) while (identifierContinue(ch))
bump(); bump();
return TokenType::IDENTIFIER; return TokenType::IDENTIFIER;
} } else if (numberStart(ch)) {
else if (numberStart(ch)) if (ch == '-') {
{
if(ch == '-') {
bump(); bump();
} }
unsigned takenDigits; unsigned takenDigits;
@ -259,145 +252,99 @@ PResult<TokenType> ComdelLexer::nextTokenType() {
takenDigits = takeNumberInRadix(radix); takenDigits = takeNumberInRadix(radix);
if (takenDigits == 0) { if (takenDigits == 0) {
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"no digits found for number, or misspelled number"}); "no digits found for number, or misspelled number"});
} }
if( isalnum(ch) ) { if (isalnum(ch)) {
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"illegal digit or letter found at the end of number"}); "illegal digit or letter found at the end of number"});
} }
return TokenType::NUMBER; return TokenType::NUMBER;
} } else if (ch == '!') {
else if (ch == '!')
{
bump(); bump();
return TokenType::NOT; return TokenType::NOT;
} } else if (ch == '<') {
else if (ch == '<')
{
bump(); bump();
return TokenType::LT; return TokenType::LT;
} } else if (ch == '>') {
else if (ch == '>')
{
bump(); bump();
return TokenType::GT; return TokenType::GT;
} } else if (ch == '#') {
else if (ch == '#')
{
bump(); bump();
if (digitIsValid(ch, Radix::HEX_NUMBER)) { if (digitIsValid(ch, Radix::HEX_NUMBER)) {
unsigned takenDigits = takeHexColor(); unsigned takenDigits = takeHexColor();
if (takenDigits != 6 && takenDigits != 8) { if (takenDigits != 6 && takenDigits != 8) {
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"hex-color must have 6 or 8 hex-digits"}); "hex-color must have 6 or 8 hex-digits"});
} }
if( isalnum(ch) ) { if (isalnum(ch)) {
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"illegal letter found at the end of hex-color"}); "illegal letter found at the end of hex-color"});
} }
return TokenType::COLOR; return TokenType::COLOR;
} else { } else {
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"unexpected #"}); "unexpected #"});
} }
} } else if (ch == '@') {
else if (ch == '@')
{
bump(); bump();
while (identifierContinue(ch)) while (identifierContinue(ch))
bump(); bump();
return TokenType::KEYWORD; return TokenType::KEYWORD;
} } else if (ch == '"') {
else if (ch == '"')
{
return takeString(); return takeString();
} } else if (ch == '`') {
else if (ch == '`')
{
return takeRawString(); return takeRawString();
} } else if (ch == '(') {
else if (ch == '(')
{
bump(); bump();
return TokenType::LPAREN; return TokenType::LPAREN;
} } else if (ch == ')') {
else if (ch == ')')
{
bump(); bump();
return TokenType::RPAREN; return TokenType::RPAREN;
} } else if (ch == '[') {
else if (ch == '[')
{
bump(); bump();
return TokenType::LBRACKET; return TokenType::LBRACKET;
} } else if (ch == ']') {
else if (ch == ']')
{
bump(); bump();
return TokenType::RBRACKET; return TokenType::RBRACKET;
} } else if (ch == '{') {
else if (ch == '{')
{
bump(); bump();
return TokenType::LBRACE; return TokenType::LBRACE;
} } else if (ch == '}') {
else if (ch == '}')
{
bump(); bump();
return TokenType::RBRACE; return TokenType::RBRACE;
} } else if (ch == '/') {
else if (ch == '/')
{
bump(); bump();
if (ch == '/') if (ch == '/') {
{
bump(); bump();
skipComment(); skipComment();
return TokenType::COMMENT; return TokenType::COMMENT;
} else if (ch == '*') } else if (ch == '*') {
{
bump(); bump();
if (!skipMultilineComment()) if (!skipMultilineComment()) {
{
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"unterminated multiline comment"}); "unterminated multiline comment"});
} }
return TokenType::COMMENT; return TokenType::COMMENT;
} }
return PError({Span(tokenBegin, position), return PError({Span(tokenBegin, position),
"unexpected /"}); "unexpected /"});
} } else if (ch == '.') {
else if (ch == '.')
{
bump(); bump();
return TokenType::DOT; return TokenType::DOT;
} } else if (ch == ':') {
else if (ch == ':')
{
bump(); bump();
return TokenType::COLON; return TokenType::COLON;
} } else if (ch == ';') {
else if (ch == ';')
{
bump(); bump();
return TokenType::SEMICOLON; return TokenType::SEMICOLON;
} } else if (ch == ',') {
else if (ch == ',')
{
bump(); bump();
return TokenType::COMMA; return TokenType::COMMA;
} } else if (ch == '=') {
else if (ch == '=')
{
bump(); bump();
return TokenType::EQUALS; return TokenType::EQUALS;
} } else {
else
{
std::stringstream message; std::stringstream message;
message << "unexpected character `" << ch << "`"; message << "unexpected character `" << ch << "`";
bump(); bump();
@ -409,11 +356,11 @@ PResult<TokenType> ComdelLexer::nextTokenType() {
// Move position to the new character in input file. // Move position to the new character in input file.
// Fetch the new character in 'ch' // Fetch the new character in 'ch'
void ComdelLexer::bump(unsigned count) { void ComdelLexer::bump(unsigned count) {
for (unsigned i=0; i < count && !eof(); i++) { for (unsigned i = 0; i < count && !eof(); i++) {
if (ch == '\n') { if (ch == '\n') {
position.line += 1; position.line += 1;
position.col = 1; position.col = 1;
parseContext->getFile(fileId).addLineOffset(position.offset+1); parseContext->getFile(fileId).addLineOffset(position.offset + 1);
} else { } else {
position.col += 1; position.col += 1;
} }
@ -427,10 +374,10 @@ void ComdelLexer::bump(unsigned count) {
// Fetch does not cross line boundary. // Fetch does not cross line boundary.
// Returns \n when next char does not exist (end of line or end of file) // Returns \n when next char does not exist (end of line or end of file)
char ComdelLexer::peek() { char ComdelLexer::peek() {
if(position.offset+1 == source.size()) // eof if (position.offset + 1 == source.size()) // eof
return '\n'; return '\n';
return source[position.offset+1]; return source[position.offset + 1];
} }

View File

@ -1,9 +1,9 @@
#ifndef COMDEL_LEXER_H #ifndef COMDEL_LEXER_H
#define COMDEL_LEXER_H #define COMDEL_LEXER_H
#include "parsecontext.h" #include "parse_context.h"
#include "presult.h" #include "presult.h"
#include "sourceerror.h" #include "source_error.h"
#include "token.h" #include "token.h"
@ -16,8 +16,7 @@ struct LexerResult {
std::vector<SourceError> errors; std::vector<SourceError> errors;
}; };
class ComdelLexer class ComdelLexer {
{
enum Radix { enum Radix {
BIN_NUMBER = 2, BIN_NUMBER = 2,
@ -28,19 +27,23 @@ class ComdelLexer
std::string source; std::string source;
std::vector<Token> tokens; std::vector<Token> tokens;
std::vector<SourceError> errors; std::vector<SourceError> errors;
ParseContext* parseContext; ParseContext *parseContext;
unsigned fileId; unsigned fileId;
public: public:
ComdelLexer(std::string fileName, std::string source, ParseContext* parseContext); ComdelLexer(std::string fileName, std::string source, ParseContext *parseContext);
LexerResult tokenize(); LexerResult tokenize();
private: private:
void skipWhitespace(); void skipWhitespace();
unsigned takeNumberInRadix(Radix radix); unsigned takeNumberInRadix(Radix radix);
unsigned takeHexColor(); unsigned takeHexColor();
bool digitIsValid(char ch, Radix radix); bool digitIsValid(char ch, Radix radix);
Radix takeRadix(); Radix takeRadix();
PResult<TokenType> nextTokenType(); PResult<TokenType> nextTokenType();
@ -50,13 +53,17 @@ private:
char ch; char ch;
void skipComment(); void skipComment();
bool skipMultilineComment(); bool skipMultilineComment();
PResult<TokenType> takeString(); PResult<TokenType> takeString();
PResult<TokenType> takeRawString(); PResult<TokenType> takeRawString();
void bump(unsigned count = 1); void bump(unsigned count = 1);
char peek(); char peek();
bool eof(); bool eof();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#include "parsecontext.h" #include "parse_context.h"
#include "assert.h" #include "assert.h"
#include <iostream> #include <iostream>
@ -6,31 +6,29 @@
#include <cmath> #include <cmath>
ParseContext::ParseContext() ParseContext::ParseContext() {
{
applicationDir = std::string(); applicationDir = std::string();
} }
unsigned ParseContext::addFile(const std::string& fileName, unsigned ParseContext::addFile(const std::string &fileName,
const std::string& source) const std::string &source) {
{ fileMap.emplace_back(fileName, source);
fileMap.push_back(SourceFile(fileName, source));
return fileMap.size(); return fileMap.size();
} }
SourceFile& ParseContext::getFile(unsigned fileId) SourceFile &ParseContext::getFile(unsigned fileId) {
{ return fileMap[fileId - 1];
return fileMap[fileId-1];
} }
struct pad { struct pad {
char ch; int count; char ch;
int count;
pad(char ch, int count) : ch(ch), count(count) {} pad(char ch, int count) : ch(ch), count(count) {}
}; };
std::ostream& operator<<(std::ostream& stream, const pad& p) { std::ostream &operator<<(std::ostream &stream, const pad &p) {
for (int i = 0; i < p.count; i++) { for (int i = 0; i < p.count; i++) {
stream << p.ch; stream << p.ch;
} }
@ -40,16 +38,13 @@ std::ostream& operator<<(std::ostream& stream, const pad& p) {
#define ATLAS_ASSERT(x) \ #define ATLAS_ASSERT(x) \
do {} while(0) do {} while(0)
void ParseContext::formatError(const SourceError& sourceError, void ParseContext::formatError(const SourceError &sourceError,
std::ostream& stream, std::ostream &stream,
const std::string& ErrorOrWarning) const std::string &errorOrWarning) {
{
ATLAS_ASSERT(sourceError.span.lo.col != 0 ATLAS_ASSERT(sourceError.span.lo.col != 0
&& sourceError.span.hi.col != 0); && sourceError.span.hi.col != 0);
SourceFile sourceFile = getFile(sourceError.span.lo.fileId); stream << errorOrWarning << sourceError.message << std::endl;
stream << ErrorOrWarning << sourceError.message << std::endl;
Span span = sourceError.span; Span span = sourceError.span;
@ -100,21 +95,17 @@ void ParseContext::formatError(const SourceError& sourceError,
} }
SourceFile::SourceFile(std::string fileName, std::string source) SourceFile::SourceFile(std::string fileName, std::string source)
: fileName(std::move(fileName)), source(std::move(source)) : fileName(std::move(fileName)), source(std::move(source)) {
{
lineOffsets.push_back(0); lineOffsets.push_back(0);
} }
const std::string& SourceFile::getFileName() const const std::string &SourceFile::getFileName() const {
{
return fileName; return fileName;
} }
const std::string SourceFile::getLine(unsigned line) const std::string SourceFile::getLine(unsigned line) const {
{ auto lineOffset = lineOffsets[line - 1];
auto lineOffset = lineOffsets[line-1];
auto nextLF = source.find('\n', lineOffset); auto nextLF = source.find('\n', lineOffset);
auto nextCR = source.find('\r', lineOffset); auto nextCR = source.find('\r', lineOffset);
auto nl = std::min(nextCR, nextLF); auto nl = std::min(nextCR, nextLF);
@ -122,7 +113,6 @@ const std::string SourceFile::getLine(unsigned line) const
return source.substr(lineOffset, nl - lineOffset); return source.substr(lineOffset, nl - lineOffset);
} }
void SourceFile::addLineOffset(unsigned offset) void SourceFile::addLineOffset(unsigned offset) {
{
lineOffsets.push_back(offset); lineOffsets.push_back(offset);
} }

View File

@ -2,40 +2,39 @@
#define PARSE_CONTEXT_H #define PARSE_CONTEXT_H
#include "sourceerror.h" #include "source_error.h"
#include <string> #include <string>
#include <vector> #include <vector>
class SourceFile { class SourceFile {
std::string fileName; std::string fileName;
std::string source; std::string source;
std::vector<unsigned> lineOffsets; std::vector<unsigned> lineOffsets;
public: public:
// qqq source je CIJELI comdel fajl,
// za inicijalizaciju source se koristi std::move, a možda treba biti referenca???
SourceFile(std::string fileName, std::string source); SourceFile(std::string fileName, std::string source);
const std::string& getFileName() const; const std::string &getFileName() const;
const std::string getLine(unsigned line) const;
std::string getLine(unsigned line) const;
void addLineOffset(unsigned offset); void addLineOffset(unsigned offset);
}; };
class ParseContext class ParseContext {
{
std::string applicationDir; std::string applicationDir;
std::vector<SourceFile> fileMap; std::vector<SourceFile> fileMap;
public: public:
ParseContext(); ParseContext();
unsigned addFile(const std::string& fileName, const std::string& source); unsigned addFile(const std::string &fileName, const std::string &source);
SourceFile& getFile(unsigned file);
void formatError(const SourceError &sourceError, std::ostream &stream, const std::string& ErrorOrWarning); SourceFile &getFile(unsigned file);
void formatError(const SourceError &sourceError, std::ostream &stream, const std::string &errorOrWarning);
}; };

View File

@ -1,18 +1,17 @@
#include "comdellexer.h" #include "comdellexer.h"
#include "comdelparser.h" #include "comdel_parser.h"
#include "parserutil.h" #include "parser_util.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <QDir> #include <QDir>
std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext, std::optional<LibraryNode> load_library_from_file(ParseContext *parseContext,
const char* name, const char *name,
std::ostream& stream) std::ostream &stream) {
{
std::ifstream in(name, std::ios::in | std::ios::binary); std::ifstream in(name, std::ios::in | std::ios::binary);
if( ! in ) { if (!in) {
stream << "ERROR: cannot open file '" << name stream << "ERROR: cannot open file '" << name
<< "' (file does not exist or is unreadable)" << std::endl; << "' (file does not exist or is unreadable)" << std::endl;
return std::nullopt; return std::nullopt;
@ -23,17 +22,17 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
ComdelLexer lexer(name, source, parseContext); ComdelLexer lexer(name, source, parseContext);
LexerResult lexerResult = lexer.tokenize(); LexerResult lexerResult = lexer.tokenize();
if (lexerResult.errors.size()) { if (!lexerResult.errors.empty()) {
for (auto& error : lexerResult.errors) { for (auto &error: lexerResult.errors) {
parseContext->formatError(error, stream, "ERROR: "); parseContext->formatError(error, stream, "ERROR: ");
} }
return std::nullopt; // if lexer has found errors => don't parse return std::nullopt; // if lexer has found errors => don't parseLibrary
} }
ComdelParser parser(lexerResult.tokens); ComdelParser parser(lexerResult.tokens);
auto unit = parser.parse(); auto unit = parser.parseLibrary();
if (!unit) { if (!unit) {
for (auto& error : parser.getErrors()) { for (auto &error: parser.getErrors()) {
parseContext->formatError(error, stream, "ERROR: "); parseContext->formatError(error, stream, "ERROR: ");
} }
return std::nullopt; return std::nullopt;
@ -43,12 +42,11 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
} }
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext, std::optional<SchemaNode> load_schema_from_file(ParseContext *parseContext,
const char* name, const char *name,
std::ostream& stream) std::ostream &stream) {
{
std::ifstream in(name, std::ios::in | std::ios::binary); std::ifstream in(name, std::ios::in | std::ios::binary);
if( ! in ) { if (!in) {
stream << "ERROR: cannot open file '" << name stream << "ERROR: cannot open file '" << name
<< "' (file does not exist or is unreadable)" << std::endl; << "' (file does not exist or is unreadable)" << std::endl;
return std::nullopt; return std::nullopt;
@ -59,32 +57,32 @@ std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
ComdelLexer lexer(name, source, parseContext); ComdelLexer lexer(name, source, parseContext);
LexerResult lexerResult = lexer.tokenize(); LexerResult lexerResult = lexer.tokenize();
if (lexerResult.errors.size()) { if (!lexerResult.errors.empty()) {
for (auto& error : lexerResult.errors) { for (auto &error: lexerResult.errors) {
parseContext->formatError(error, stream, "ERROR: "); parseContext->formatError(error, stream, "ERROR: ");
} }
return std::nullopt; // if lexer has found errors => don't parse return std::nullopt; // if lexer has found errors => don't parseLibrary
} }
ComdelParser parser(lexerResult.tokens); ComdelParser parser(lexerResult.tokens);
auto unit = parser.parseSchema(); auto unit = parser.parseSchema();
if (!unit) { if (!unit) {
for (auto& error : parser.getErrors()) { for (auto &error: parser.getErrors()) {
parseContext->formatError(error, stream, "ERROR: "); parseContext->formatError(error, stream, "ERROR: ");
} }
return std::nullopt; return std::nullopt;
} }
if(unit->source) { if (unit->source) {
QFileInfo info(name); QFileInfo info(name);
auto filepath = info.absolutePath(); auto filepath = info.absolutePath();
QDir dir; QDir::setCurrent(filepath);
dir.setCurrent(filepath);
QDir dir;
auto libraryPath = dir.absoluteFilePath(QString::fromStdString(unit->source->asString())); auto libraryPath = dir.absoluteFilePath(QString::fromStdString(unit->source->asString()));
unit->library = loadLibraryFromFile(parseContext, libraryPath.toUtf8().data(), stream); unit->library = load_library_from_file(parseContext, libraryPath.toUtf8().data(), stream);
if(unit->library == std::nullopt) { if (unit->library == std::nullopt) {
return std::nullopt; return std::nullopt;
} }
} }

View File

@ -0,0 +1,15 @@
#ifndef PARSER_UTIL_H
#define PARSER_UTIL_H
#include "ast_nodes.h"
#include "parse_context.h"
std::optional<LibraryNode> load_library_from_file(ParseContext *parseContext,
const char *name,
std::ostream &stream);
std::optional<SchemaNode> load_schema_from_file(ParseContext *parseContext,
const char *name,
std::ostream &stream);
#endif // PARSER_UTIL_H

View File

@ -1,15 +0,0 @@
#ifndef PARSER_UTIL_H
#define PARSER_UTIL_H
#include "astnode.h"
#include "parsecontext.h"
std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
const char* name,
std::ostream& stream);
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
const char* name,
std::ostream& stream);
#endif // PARSERUTIL_H

View File

@ -30,142 +30,119 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <type_traits> #include <type_traits>
#include <typeinfo> #include <typeinfo>
namespace detail namespace detail {
{
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Implementation detail classes // Implementation detail classes
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
template <class T> template<class T>
struct default_copy struct default_copy {
{ T *operator()(const T &t) const {
T* operator()(const T& t) const
{
return new T(t); return new T(t);
} }
}; };
template <class T> template<class T>
struct default_delete struct default_delete {
{ void operator()(const T *t) const {
void operator()(const T* t) const
{
delete t; delete t;
} }
}; };
template <class T> template<class T>
struct control_block struct control_block {
{
virtual ~control_block() = default; virtual ~control_block() = default;
virtual std::unique_ptr<control_block> clone() const = 0; virtual std::unique_ptr<control_block> clone() const = 0;
virtual T* ptr() = 0; virtual T *ptr() = 0;
}; };
template <class T, class U = T> template<class T, class U = T>
class direct_control_block : public control_block<T> class direct_control_block : public control_block<T> {
{
static_assert(!std::is_reference<U>::value, ""); static_assert(!std::is_reference<U>::value, "");
U u_; U u_;
public: public:
template <class... Ts> template<class... Ts>
explicit direct_control_block(Ts&&... ts) : u_(U(std::forward<Ts>(ts)...)) explicit direct_control_block(Ts &&... ts) : u_(U(std::forward<Ts>(ts)...)) {
{
} }
std::unique_ptr<control_block<T>> clone() const override std::unique_ptr<control_block<T>> clone() const override {
{
return std::make_unique<direct_control_block>(*this); return std::make_unique<direct_control_block>(*this);
} }
T* ptr() override T *ptr() override {
{
return std::addressof(u_); return std::addressof(u_);
} }
}; };
template <class T, class U, class C = default_copy<U>, template<class T, class U, class C = default_copy<U>,
class D = default_delete<U>> class D = default_delete<U>>
class pointer_control_block : public control_block<T>, public C class pointer_control_block : public control_block<T>, public C {
{
std::unique_ptr<U, D> p_; std::unique_ptr<U, D> p_;
public: public:
explicit pointer_control_block(U* u, C c = C{}, D d = D{}) explicit pointer_control_block(U *u, C c = C{}, D d = D{})
: C(std::move(c)), p_(u, std::move(d)) : C(std::move(c)), p_(u, std::move(d)) {
{
} }
explicit pointer_control_block(std::unique_ptr<U, D> p, C c = C{}) explicit pointer_control_block(std::unique_ptr<U, D> p, C c = C{})
: C(std::move(c)), p_(std::move(p)) : C(std::move(c)), p_(std::move(p)) {
{
} }
std::unique_ptr<control_block<T>> clone() const override std::unique_ptr<control_block<T>> clone() const override {
{
assert(p_); assert(p_);
return std::make_unique<pointer_control_block>( return std::make_unique<pointer_control_block>(
C::operator()(*p_), static_cast<const C&>(*this), p_.get_deleter()); C::operator()(*p_), static_cast<const C &>(*this), p_.get_deleter());
} }
T* ptr() override T *ptr() override {
{
return p_.get(); return p_.get();
} }
}; };
template <class T, class U> template<class T, class U>
class delegating_control_block : public control_block<T> class delegating_control_block : public control_block<T> {
{
std::unique_ptr<control_block<U>> delegate_; std::unique_ptr<control_block<U>> delegate_;
public: public:
explicit delegating_control_block(std::unique_ptr<control_block<U>> b) explicit delegating_control_block(std::unique_ptr<control_block<U>> b)
: delegate_(std::move(b)) : delegate_(std::move(b)) {
{
} }
std::unique_ptr<control_block<T>> clone() const override std::unique_ptr<control_block<T>> clone() const override {
{
return std::make_unique<delegating_control_block>(delegate_->clone()); return std::make_unique<delegating_control_block>(delegate_->clone());
} }
T* ptr() override T *ptr() override {
{ return static_cast<T *>(delegate_->ptr());
return static_cast<T*>(delegate_->ptr());
} }
}; };
} // end namespace detail } // end namespace detail
class bad_poly_construction : std::exception class bad_poly_construction : std::exception {
{
public: public:
bad_poly_construction() noexcept = default; bad_poly_construction() noexcept = default;
const char* what() const noexcept override const char *what() const noexcept override {
{
return "Dynamic and static type mismatch in poly " return "Dynamic and static type mismatch in poly "
"construction"; "construction";
} }
}; };
template <class T> template<class T>
class poly; class poly;
template <class T> template<class T>
struct is_poly : std::false_type struct is_poly : std::false_type {
{
}; };
template <class T> template<class T>
struct is_poly<poly<T>> : std::true_type struct is_poly<poly<T>> : std::true_type {
{
}; };
@ -173,23 +150,25 @@ struct is_poly<poly<T>> : std::true_type
// `poly` class definition // `poly` class definition
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <class T> template<class T>
class poly class poly {
{
static_assert(!std::is_union<T>::value, ""); static_assert(!std::is_union<T>::value, "");
static_assert(std::is_class<T>::value, ""); static_assert(std::is_class<T>::value, "");
template <class U> template<class U>
friend class poly; friend
class poly;
template <class T_, class U, class... Ts> template<class T_, class U, class... Ts>
friend poly<T_> make_poly(Ts&&... ts); friend poly<T_> make_poly(Ts &&... ts);
template <class T_, class... Ts>
friend poly<T_> make_poly(Ts&&... ts); template<class T_, class... Ts>
template <class T_, class U> friend poly<T_> make_poly(Ts &&... ts);
template<class T_, class U>
friend poly<T_> poly_cast(poly<U> p); friend poly<T_> poly_cast(poly<U> p);
T* ptr_ = nullptr; T *ptr_ = nullptr;
std::unique_ptr<detail::control_block<T>> cb_; std::unique_ptr<detail::control_block<T>> cb_;
public: public:
@ -204,17 +183,14 @@ public:
// Constructors // Constructors
// //
poly() poly() {
{
} }
template <class U, class C = detail::default_copy<U>, template<class U, class C = detail::default_copy<U>,
class D = detail::default_delete<U>, class D = detail::default_delete<U>,
class V = std::enable_if_t<std::is_convertible<U*, T*>::value>> class V = std::enable_if_t<std::is_convertible<U *, T *>::value>>
explicit poly(U* u, C copier = C{}, D deleter = D{}) explicit poly(U *u, C copier = C{}, D deleter = D{}) {
{ if (!u) {
if (!u)
{
return; return;
} }
@ -227,7 +203,7 @@ public:
std::unique_ptr<U, D> p(u, std::move(deleter)); std::unique_ptr<U, D> p(u, std::move(deleter));
cb_ = std::make_unique<detail::pointer_control_block<T, U, C, D>>( cb_ = std::make_unique<detail::pointer_control_block<T, U, C, D>>(
std::move(p), std::move(copier)); std::move(p), std::move(copier));
ptr_ = u; ptr_ = u;
} }
@ -236,10 +212,8 @@ public:
// Copy-constructors // Copy-constructors
// //
poly(const poly& p) poly(const poly &p) {
{ if (!p) {
if (!p)
{
return; return;
} }
auto tmp_cb = p.cb_->clone(); auto tmp_cb = p.cb_->clone();
@ -251,8 +225,7 @@ public:
// Move-constructors // Move-constructors
// //
poly(poly&& p) noexcept poly(poly &&p) noexcept {
{
ptr_ = p.ptr_; ptr_ = p.ptr_;
cb_ = std::move(p.cb_); cb_ = std::move(p.cb_);
p.ptr_ = nullptr; p.ptr_ = nullptr;
@ -262,25 +235,23 @@ public:
// Converting constructors // Converting constructors
// //
template <class U, template<class U,
class V = std::enable_if_t<!std::is_same<T, U>::value && class V = std::enable_if_t<!std::is_same<T, U>::value &&
std::is_convertible<U*, T*>::value>> std::is_convertible<U *, T *>::value>>
poly(const poly<U>& p) poly(const poly<U> &p) {
{
poly<U> tmp(p); poly<U> tmp(p);
ptr_ = tmp.ptr_; ptr_ = tmp.ptr_;
cb_ = std::make_unique<detail::delegating_control_block<T, U>>( cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
std::move(tmp.cb_)); std::move(tmp.cb_));
} }
template <class U, template<class U,
class V = std::enable_if_t<!std::is_same<T, U>::value && class V = std::enable_if_t<!std::is_same<T, U>::value &&
std::is_convertible<U*, T*>::value>> std::is_convertible<U *, T *>::value>>
poly(poly<U>&& p) poly(poly<U> &&p) {
{
ptr_ = p.ptr_; ptr_ = p.ptr_;
cb_ = std::make_unique<detail::delegating_control_block<T, U>>( cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
std::move(p.cb_)); std::move(p.cb_));
p.ptr_ = nullptr; p.ptr_ = nullptr;
} }
@ -288,14 +259,13 @@ public:
// Forwarding constructor // Forwarding constructor
// //
template <class U, class V = std::enable_if_t< template<class U, class V = std::enable_if_t<
std::is_convertible<std::decay_t<U>*, T*>::value && std::is_convertible<std::decay_t<U> *, T *>::value &&
!is_poly<std::decay_t<U>>::value>> !is_poly<std::decay_t<U>>::value>>
poly(U&& u) poly(U &&u)
: cb_(std::make_unique< : cb_(std::make_unique<
detail::direct_control_block<T, std::decay_t<U>>>( detail::direct_control_block<T, std::decay_t<U>>>(
std::forward<U>(u))) std::forward<U>(u))) {
{
ptr_ = cb_->ptr(); ptr_ = cb_->ptr();
} }
@ -303,15 +273,12 @@ public:
// Assignment // Assignment
// //
poly& operator=(const poly& p) poly &operator=(const poly &p) {
{ if (std::addressof(p) == this) {
if (std::addressof(p) == this)
{
return *this; return *this;
} }
if (!p) if (!p) {
{
cb_.reset(); cb_.reset();
ptr_ = nullptr; ptr_ = nullptr;
return *this; return *this;
@ -328,10 +295,8 @@ public:
// Move-assignment // Move-assignment
// //
poly& operator=(poly&& p) noexcept poly &operator=(poly &&p) noexcept {
{ if (std::addressof(p) == this) {
if (std::addressof(p) == this)
{
return *this; return *this;
} }
@ -346,8 +311,7 @@ public:
// Modifiers // Modifiers
// //
void swap(poly& p) noexcept void swap(poly &p) noexcept {
{
using std::swap; using std::swap;
swap(ptr_, p.ptr_); swap(ptr_, p.ptr_);
swap(cb_, p.cb_); swap(cb_, p.cb_);
@ -358,31 +322,26 @@ public:
// Observers // Observers
// //
explicit operator bool() const explicit operator bool() const {
{ return (bool) cb_;
return (bool)cb_;
} }
const T* operator->() const const T *operator->() const {
{
assert(ptr_); assert(ptr_);
return ptr_; return ptr_;
} }
const T& operator*() const const T &operator*() const {
{
assert(*this); assert(*this);
return *ptr_; return *ptr_;
} }
T* operator->() T *operator->() {
{
assert(*this); assert(*this);
return ptr_; return ptr_;
} }
T& operator*() T &operator*() {
{
assert(*this); assert(*this);
return *ptr_; return *ptr_;
} }
@ -391,18 +350,17 @@ public:
// //
// poly creation // poly creation
// //
template <class T, class... Ts> template<class T, class... Ts>
poly<T> make_poly(Ts&&... ts) poly<T> make_poly(Ts &&... ts) {
{
poly<T> p; poly<T> p;
p.cb_ = std::make_unique<detail::direct_control_block<T, T>>( p.cb_ = std::make_unique<detail::direct_control_block<T, T>>(
std::forward<Ts>(ts)...); std::forward<Ts>(ts)...);
p.ptr_ = p.cb_->ptr(); p.ptr_ = p.cb_->ptr();
return std::move(p); return std::move(p);
} }
template <class T, class U, class... Ts>
poly<T> make_poly(Ts&&... ts) template<class T, class U, class... Ts>
{ poly<T> make_poly(Ts &&... ts) {
poly<T> p; poly<T> p;
p.cb_ = std::make_unique<detail::direct_control_block<T, U>>( p.cb_ = std::make_unique<detail::direct_control_block<T, U>>(
std::forward<Ts>(ts)...); std::forward<Ts>(ts)...);
@ -410,32 +368,30 @@ poly<T> make_poly(Ts&&... ts)
return std::move(p); return std::move(p);
} }
template <class T, class U> template<class T, class U>
const T* poly_view(const poly<U>& p) { const T *poly_view(const poly<U> &p) {
if (p) { if (p) {
return dynamic_cast<const T*>(&*p); return dynamic_cast<const T *>(&*p);
} } else {
else {
return nullptr; return nullptr;
} }
} }
template <class T, class U> template<class T, class U>
T* poly_view(poly<U>& p) { T *poly_view(poly<U> &p) {
if (p) { if (p) {
return dynamic_cast<T*>(&*p); return dynamic_cast<T *>(&*p);
} } else {
else {
return nullptr; return nullptr;
} }
} }
template <class T, class U> template<class T, class U>
poly<T> poly_cast(poly<U> p) { poly<T> poly_cast(poly<U> p) {
poly<T> ret; poly<T> ret;
if (T* ptr = dynamic_cast<T*>(&*p)) { if (T *ptr = dynamic_cast<T *>(&*p)) {
ret.cb_ = std::make_unique<detail::delegating_control_block<T, U>>( ret.cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
std::move(p.cb_)); std::move(p.cb_));
ret.ptr_ = ret.cb_->ptr(); ret.ptr_ = ret.cb_->ptr();
} }
return ret; return ret;

View File

@ -2,7 +2,7 @@
#define PRESULT_H #define PRESULT_H
#include "expected.h" #include "expected.h"
#include "sourceerror.h" #include "source_error.h"
#include <optional> #include <optional>
@ -32,19 +32,18 @@ using PError = tl::unexpected<SourceError>;
/// Holds either an AST node or an error /// Holds either an AST node or an error
/// The value MUST be checked before usage, e.g. using RETURN_IF_ERR /// The value MUST be checked before usage, e.g. using RETURN_IF_ERR
template <typename T> template<typename T>
struct PResult : tl::expected<T, SourceError> { struct PResult : tl::expected<T, SourceError> {
using tl::expected<T, SourceError>::expected; using tl::expected<T, SourceError>::expected;
/// Implicit conversion from PResult<U> to PResult<T> /// Implicit conversion from PResult<U> to PResult<T>
/// if U is convertible to T /// if U is convertible to T
template <typename U, class V = std::enable_if_t<std::is_convertible<std::decay_t<U>, T>::value>> template<typename U, class V = std::enable_if_t<std::is_convertible<std::decay_t<U>, T>::value>>
PResult(PResult<U> presult) : PResult(PResult<U> presult) :
tl::expected<T, SourceError>(presult ? PResult<T>(*presult) : PError(presult.error())) tl::expected<T, SourceError>(presult ? PResult<T>(*presult) : PError(presult.error())) {}
{}
}; };
/// Alternative to PResult that is returned from parse* functions /// Alternative to PResult that is returned from parseLibrary* functions
/// that only consume one token so they can fail without affecting /// that only consume one token so they can fail without affecting
/// the parser state /// the parser state
template<typename T> template<typename T>

View File

@ -0,0 +1,5 @@
#include "source_error.h"
SourceError::SourceError(Span span, std::string message)
: span(span), message(std::move(message)) {}

View File

@ -1,6 +0,0 @@
#include "sourceerror.h"
SourceError::SourceError(Span span, std::string message)
: span(std::move(span)), message(std::move(message))
{}

View File

@ -4,32 +4,23 @@
Position::Position() Position::Position()
: fileId(0), line(0), col(0), offset(0) : fileId(0), line(0), col(0), offset(0) {}
{}
Position::Position(unsigned file, unsigned line, unsigned col, unsigned offset) Position::Position(unsigned file, unsigned line, unsigned col, unsigned offset)
: fileId(file), line(line), col(col), offset(offset) : fileId(file), line(line), col(col), offset(offset) {}
{}
Span::Span() Span::Span()
: lo(0, 0, 0, 0), hi(0, 0, 0, 0) : lo(0, 0, 0, 0), hi(0, 0, 0, 0) {}
{}
Span::Span(Position begin, Position end) Span::Span(Position begin, Position end)
: lo(begin), hi(end) : lo(begin), hi(end) {}
{}
Span::Span(Position begin) Span::Span(Position begin)
: Span(begin, Position(begin.fileId, begin.line, begin.col+1, begin.offset+1)) : Span(begin, Position(begin.fileId, begin.line, begin.col + 1, begin.offset + 1)) {}
{}
Span Span::to(const Span &span) const Span Span::to(const Span &span) const {
{ return {this->lo, span.hi};
return Span(this->lo, span.hi);
} }
Token::Token(TokenType type, Span span, std::string text) Token::Token(TokenType type, Span span, std::string text)
: type(type) : type(type), span(span), text(std::move(text)) {}
, span(std::move(span))
, text(std::move(text))
{}

View File

@ -12,6 +12,7 @@ struct Position {
unsigned offset; unsigned offset;
Position(); Position();
Position(unsigned fileId, unsigned line, unsigned col, unsigned offset); Position(unsigned fileId, unsigned line, unsigned col, unsigned offset);
}; };
@ -23,10 +24,12 @@ struct Span {
Position hi; Position hi;
Span(); Span();
Span(Position lo, Position hi); Span(Position lo, Position hi);
Span(Position lo); Span(Position lo);
Span to(const Span& span) const; Span to(const Span &span) const;
}; };
enum class TokenType { enum class TokenType {

View File

@ -0,0 +1,173 @@
#include "tokens_type.h"
enum TokenClass {
KEYWORD_NAME = 4,
TOKENIZABLE = 8
};
struct TokenInfo {
std::string text;
unsigned short attributes;
};
struct TokenTables {
std::unordered_map<TokenType, TokenInfo> allTokensInfo;
std::unordered_map<std::string, TokenType> keywords;
TokenType tokenize(std::string value, TokenType initial);
bool is_keyword(TokenType token);
void add(TokenType tokenType, const std::string &txt,
unsigned short attribs = 0);
TokenTables();
};
static TokenTables tokenTables;
void TokenTables::add(TokenType tokenType, const std::string &txt,
unsigned short attribs) {
allTokensInfo[tokenType] = TokenInfo{txt, attribs};
if (attribs & KEYWORD_NAME)
keywords[txt] = tokenType;
}
TokenTables::TokenTables() {
add(TokenType::IDENTIFIER, "identifier");
add(TokenType::KEYWORD, "keyword", KEYWORD_NAME);
// Literals (bool is not here, it has two keywords: false and true)
add(TokenType::NUMBER, "number");
add(TokenType::STRING, "string");
add(TokenType::COLOR, "color");
// Parentheses of all kinds
add(TokenType::LPAREN, "(");
add(TokenType::RPAREN, ")");
add(TokenType::LBRACKET, "[");
add(TokenType::RBRACKET, "]");
add(TokenType::LBRACE, "{");
add(TokenType::RBRACE, "}");
add(TokenType::LT, "<");
add(TokenType::GT, ">");
// assignments
add(TokenType::EQUALS, "=");
// miscellaneous
add(TokenType::DOT, ".");
add(TokenType::COLON, ":");
add(TokenType::SEMICOLON, ";");
add(TokenType::COMMA, ",");
add(TokenType::WHITESPACE, "whitespace");
add(TokenType::COMMENT, "comment");
add(TokenType::TRUE, "true", TOKENIZABLE);
add(TokenType::FALSE, "false", TOKENIZABLE);
add(TokenType::IF, "if", TOKENIZABLE);
add(TokenType::ELSE, "else", TOKENIZABLE);
add(TokenType::DEFAULT, "default", TOKENIZABLE);
add(TokenType::NIL, "null", TOKENIZABLE);
// all keywords
add(TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME);
add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME);
// All types
add(TokenType::INT_TYPE, "int", TOKENIZABLE);
add(TokenType::STRING_TYPE, "string", TOKENIZABLE);
add(TokenType::BOOL_TYPE, "bool", TOKENIZABLE);
add(TokenType::WIRE_TYPE, "wire", TOKENIZABLE);
// WireNode types
add(TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE);
add(TokenType::WIRE_AND, "wired_and", TOKENIZABLE);
add(TokenType::WIRE_OR, "wired_or", TOKENIZABLE);
add(TokenType::R_WIRE, "r_wire", TOKENIZABLE);
// ComponentNode types
add(TokenType::CT_MEMORY, "memory", TOKENIZABLE);
add(TokenType::CT_PROCESSOR, "processor", TOKENIZABLE);
// PinNode type
add(TokenType::PIN_IN, "in", TOKENIZABLE);
add(TokenType::PIN_OUT, "out", TOKENIZABLE);
add(TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE);
// ActionNode types
add(TokenType::ERROR, "error", TOKENIZABLE);
add(TokenType::WARNING, "warning", TOKENIZABLE);
// WireNode settings types
add(TokenType::HIDDEN, "hidden", TOKENIZABLE);
add(TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE);
// Miscelaneous
add(TokenType::END_OF_FILE, "eof");
}
const std::string &tokenTypeToString(TokenType tokenType) {
return tokenTables.allTokensInfo[tokenType].text;
}
TokenType TokenTables::tokenize(std::string value, TokenType initial) {
for (auto &[key, param]: allTokensInfo) {
if (param.attributes & TOKENIZABLE && param.text == value) {
return key;
}
}
return initial;
}
bool TokenTables::is_keyword(TokenType token) {
for (auto &[key, param]: allTokensInfo) {
if (param.attributes & KEYWORD_NAME && key == token) {
return true;
}
}
return false;
}
TokenType from_token(std::string value, TokenType initial) {
return tokenTables.tokenize(value, initial);
}
bool is_keyword(TokenType tokenType) {
return tokenTables.is_keyword(tokenType);
}

View File

@ -6,7 +6,7 @@
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
const std::string& tokenTypeToString(TokenType tokenType); const std::string &tokenTypeToString(TokenType tokenType);
TokenType from_token(std::string value, TokenType initial); TokenType from_token(std::string value, TokenType initial);

View File

@ -1,176 +0,0 @@
#include "tokenstype.h"
enum TokenClass {
BUILT_IN_FUNC = 1,
DATA_TYPE = 2,
KEYWORD_NAME = 4,
TOKENIZABLE = 8
};
struct TokenInfo {
std::string text;
unsigned short attributes;
};
struct TokenTables {
std::unordered_map<TokenType, TokenInfo> allTokensInfo;
std::unordered_map<std::string, TokenType> keywords;
TokenType tokenize(std::string value, TokenType initial);
bool is_keyword(TokenType token);
void add(TokenType tokenType, const std::string& txt,
unsigned short attribs = 0);
TokenTables();
};
static TokenTables tokenTables;
void TokenTables::add (TokenType tokenType, const std::string& txt,
unsigned short attribs)
{
allTokensInfo[tokenType] = TokenInfo{txt, attribs};
if(attribs & KEYWORD_NAME)
keywords[txt] = tokenType;
}
TokenTables::TokenTables() {
add( TokenType::IDENTIFIER, "identifier" );
add( TokenType::KEYWORD, "keyword" , KEYWORD_NAME);
// Literals (bool is not here, it has two keywords: false and true)
add( TokenType::NUMBER, "number");
add( TokenType::STRING, "string");
add( TokenType::COLOR, "color");
// Parentheses of all kinds
add( TokenType::LPAREN, "(" );
add( TokenType::RPAREN, ")" );
add( TokenType::LBRACKET, "[" );
add( TokenType::RBRACKET, "]" );
add( TokenType::LBRACE, "{" );
add( TokenType::RBRACE, "}" );
add( TokenType::LT, "<" );
add( TokenType::GT, ">" );
// assignments
add( TokenType::EQUALS, "=" );
// miscellaneous
add( TokenType::DOT, "." );
add( TokenType::COLON, ":" );
add( TokenType::SEMICOLON, ";" );
add( TokenType::COMMA, "," );
add( TokenType::WHITESPACE, "whitespace" );
add( TokenType::COMMENT, "comment" );
add( TokenType::TRUE, "true", TOKENIZABLE ),
add( TokenType::FALSE, "false", TOKENIZABLE),
add( TokenType::IF, "if", TOKENIZABLE ),
add( TokenType::ELSE, "else", TOKENIZABLE),
add( TokenType::DEFAULT, "default", TOKENIZABLE),
add( TokenType::NIL, "null", TOKENIZABLE),
// all keywords
add( TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME),
add( TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME),
// All types
add( TokenType::INT_TYPE, "int", TOKENIZABLE),
add( TokenType::STRING_TYPE, "string", TOKENIZABLE),
add( TokenType::BOOL_TYPE, "bool", TOKENIZABLE),
add( TokenType::WIRE_TYPE, "wire", TOKENIZABLE),
// WireNode types
add( TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE),
add( TokenType::WIRE_AND, "wired_and", TOKENIZABLE),
add( TokenType::WIRE_OR, "wired_or", TOKENIZABLE),
add( TokenType::R_WIRE, "r_wire", TOKENIZABLE),
// ComponentNode types
add( TokenType::CT_MEMORY, "memory", TOKENIZABLE),
add( TokenType::CT_PROCESSOR, "processor", TOKENIZABLE),
// PinNode type
add( TokenType::PIN_IN, "in", TOKENIZABLE),
add( TokenType::PIN_OUT, "out", TOKENIZABLE),
add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE),
// ActionNode types
add( TokenType::ERROR, "error", TOKENIZABLE),
add( TokenType::WARNING, "warning", TOKENIZABLE),
// WireNode settings types
add( TokenType::HIDDEN, "hidden", TOKENIZABLE),
add( TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE),
// Miscelaneous
add( TokenType::END_OF_FILE, "eof" );
}
const std::string &tokenTypeToString(TokenType tokenType) {
return tokenTables.allTokensInfo[tokenType].text;
}
TokenType TokenTables::tokenize(std::string value, TokenType initial) {
for(auto& [key, param]: allTokensInfo) {
if(param.attributes & TOKENIZABLE && param.text == value) {
return key;
}
}
return initial;
}
bool TokenTables::is_keyword(TokenType token) {
for(auto& [key, param]: allTokensInfo) {
if(param.attributes & KEYWORD_NAME && key == token) {
return true;
}
}
return false;
}
TokenType from_token(std::string value, TokenType initial) {
return tokenTables.tokenize(value, initial);
}
bool is_keyword(TokenType tokenType) {
return tokenTables.is_keyword(tokenType);
}

View File

@ -7,10 +7,6 @@
component System component System
{ {
clock 100MHz; clock 100MHz;
//directRam
wire INT;
//glavnaSabirnica //glavnaSabirnica
wire<32> ADR; wire<32> ADR;
wire<32> DATA; wire<32> DATA;
@ -27,27 +23,31 @@ component System
wire --BACK; wire --BACK;
//directRam
wire INT;
// components -------------------------------------------- // components --------------------------------------------
subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT); subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT);
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT) uses memorija; subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT) uses memorija;
display { display {
component { x: -12; y: 68; ref: "memorija"; } component { x: -582; y: -296; ref: "procesor"; }
component { x: -206; y: -76; ref: "procesor"; } component { x: -446; y: -12; ref: "memorija"; }
// directRam bus
// glavnaSabirnica bus // glavnaSabirnica bus
rectangle { rectangle {
x: -222; y: 130; x: -581; y: -37;
w: 100; h: 20; w: 100; h: 20;
} }
line {x1:-28; y1:96; x2:-90; y2:-26;} // directRam bus
line {x1:38; y1:52; x2:-171; y2:140;}
line {x1:-156; y1:40; x2:-171; y2:140;}
line {x1:-532; y1:-180; x2:-530; y2:-26;}
line {x1:-462; y1:16; x2:-466; y2:-246;}
line {x1:-396; y1:-28; x2:-530; y2:-26;}
} }
} }

View File

@ -1,8 +1,13 @@
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl" @source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
@schema { @schema {
@instance procesor FRISC {
@position (-76, -97)
@attribute _memory memorija
}
@instance memorija Memorija { @instance memorija Memorija {
@position (-12, 68) @position (52, 119)
@attribute sinkroniziran false @attribute sinkroniziran false
@attribute brzina 1 @attribute brzina 1
@attribute kapacitet 65536 @attribute kapacitet 65536
@ -10,9 +15,9 @@
@attribute pocetnaAdresa 0 @attribute pocetnaAdresa 0
} }
@instance procesor FRISC { @instance glavnaSabirnica glavnaSabirnica {
@position (-206, -76) @position (-78, 88)
@attribute _memory memorija @size 100
} }
@instance directRam directRam { @instance directRam directRam {
@ -20,15 +25,10 @@
@size 0 @size 0
} }
@instance glavnaSabirnica glavnaSabirnica {
@position (-222, 130)
@size 50
}
@connection (memorija.memDirect, directRam, procesor.memDirect) {
}
@connection (memorija.glavniPin, glavnaSabirnica) { @connection (memorija.glavniPin, glavnaSabirnica) {
} }
@connection (procesor.glavniPin, glavnaSabirnica) { @connection (procesor.glavniPin, glavnaSabirnica) {
} }
@connection (memorija.memDirect, directRam, procesor.memDirect) {
}
} }

View File

@ -4,13 +4,13 @@
#include <QFileDialog> #include <QFileDialog>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <comdel/parser/parsecontext.h> #include <comdel/parser/parse_context.h>
#include <comdel/parser/parserutil.h> #include <comdel/parser/parser_util.h>
#include <comdel/domain/schemacreator.h> #include <comdel/domain/schema_creator.h>
#include <iostream> #include <iostream>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <comdel/domain/comdelvalidator.h> #include <comdel/domain/comdel_validator.h>
#include <fstream> #include <fstream>
#include <comdel/domain/comdel_generator.h> #include <comdel/domain/comdel_generator.h>
@ -82,7 +82,7 @@ void MainWindow::onLoadLibrary() {
clear(); clear();
ParseContext parseContext; ParseContext parseContext;
auto libraryNode = loadLibraryFromFile(&parseContext, filename.toStdString().c_str(), buffer); auto libraryNode = load_library_from_file(&parseContext, filename.toStdString().c_str(), buffer);
if(libraryNode) { if(libraryNode) {
domain::SchemaCreator generator(validators); domain::SchemaCreator generator(validators);
library = generator.loadLibrary(*libraryNode); library = generator.loadLibrary(*libraryNode);
@ -119,13 +119,13 @@ void MainWindow::onLoadSchema() {
clear(); clear();
ParseContext parseContext; ParseContext parseContext;
auto schemaNode = loadSchemaFromFile(&parseContext, filename.toStdString().c_str(), buffer); auto schemaNode = load_schema_from_file(&parseContext, filename.toStdString().c_str(), buffer);
if(schemaNode) { if(schemaNode) {
domain::SchemaCreator generator(validators); domain::SchemaCreator generator(validators);
library = generator.loadLibrary(*schemaNode->library); library = generator.loadLibrary(*schemaNode->library);
librarySource = schemaNode->source->value; librarySource = schemaNode->source->asString();
for (auto& error : generator.getErrors()) { for (auto& error : generator.getErrors()) {
parseContext.formatError(error, buffer, "ERROR: "); parseContext.formatError(error, buffer, "ERROR: ");
@ -163,7 +163,7 @@ void MainWindow::onStoreScheme() {
std::ostringstream buffer; std::ostringstream buffer;
domain::generateSchemaFile(librarySource, schema, buffer); domain::generate_schema(librarySource, schema, buffer);
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
out<<buffer.str(); out<<buffer.str();
@ -180,7 +180,7 @@ void MainWindow::onGenerateComdel() {
std::ostringstream buffer; std::ostringstream buffer;
domain::generateComdelFile(schema, library.value(), buffer); domain::generate_comdel(schema, library.value(), buffer);
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
out<<buffer.str(); out<<buffer.str();

View File

@ -10,7 +10,7 @@
#include <comdel/domain/library.h> #include <comdel/domain/library.h>
#include <comdel/domain/schema.h> #include <comdel/domain/schema.h>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <comdel/domain/comdelvalidator.h> #include <comdel/domain/comdel_validator.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }