Compare commits

...

2 Commits

Author SHA1 Message Date
Borna Rajkovic d6c1023df2 Refactored state 2022-04-24 22:21:45 +02:00
Borna Rajkovic 9e2b0f6c3c WIP 2022-04-20 21:50:39 +02:00
26 changed files with 791 additions and 226 deletions

1
.vscode/configurationCache.log vendored Normal file
View File

@ -0,0 +1 @@
{"buildTargets":[],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}}

6
.vscode/dryrun.log vendored Normal file
View File

@ -0,0 +1,6 @@
make --dry-run --always-make --keep-going --print-directory
make: Entering directory '/home/bbr/SchemeEditor'
make: Leaving directory '/home/bbr/SchemeEditor'
make: *** No targets specified and no makefile found. Stop.

288
.vscode/targets.log vendored Normal file
View File

@ -0,0 +1,288 @@
make all --print-data-base --no-builtin-variables --no-builtin-rules --question
make: *** No rule to make target 'all'. Stop.
# GNU Make 4.3
# Built for x86_64-pc-linux-gnu
# Copyright (C) 1988-2020 Free Software Foundation, Inc.
# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.
# Make data base, printed on Sun Apr 24 22:18:48 2022
# Variables
# environment
GDK_BACKEND = x11
# environment
LC_ALL = C
# environment
NO_AT_BRIDGE = 1
# environment
VSCODE_IPC_HOOK_EXTHOST = /run/user/1000/vscode-ipc-378bef37-635c-4f71-808d-af9f8b80a929.sock
# environment
LC_NAME = hr_HR.UTF-8
# environment
LC_NUMERIC = hr_HR.UTF-8
# environment
VSCODE_CWD = /home/bbr
# environment
LC_ADDRESS = hr_HR.UTF-8
# default
MAKE_COMMAND := make
# environment
GTK3_MODULES = xapp-gtk3-module
# automatic
@D = $(patsubst %/,%,$(dir $@))
# environment
VSCODE_HANDLES_UNCAUGHT_ERRORS = true
# default
.VARIABLES :=
# environment
PWD = /home/bbr/SchemeEditor
# automatic
%D = $(patsubst %/,%,$(dir $%))
# environment
MAIL = /var/spool/mail/bbr
# environment
XDG_DATA_DIRS = /usr/local/share:/usr/share:/var/lib/snapd/desktop
# automatic
^D = $(patsubst %/,%,$(dir $^))
# environment
VSCODE_LOG_STACK = false
# automatic
%F = $(notdir $%)
# environment
VSCODE_CODE_CACHE_PATH = /home/bbr/.config/Code - OSS/CachedData/e18005f0f1b33c29e81d732535d8c0e47cafb0b5
# environment
XDG_SESSION_PATH = /org/freedesktop/DisplayManager/Session0
# environment
LANG = C
# environment
XAUTHORITY = /home/bbr/.Xauthority
# default
.LOADED :=
# default
.INCLUDE_DIRS = /usr/include /usr/local/include /usr/include
# makefile
MAKEFLAGS = pqrR
# makefile
CURDIR := /home/bbr/SchemeEditor
# environment
VSCODE_PIPE_LOGGING = true
# environment
APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true
# automatic
*D = $(patsubst %/,%,$(dir $*))
# environment
MFLAGS = -pqrR
# environment
SSH_AUTH_SOCK = /run/user/1000/keyring/ssh
# default
.SHELLFLAGS := -c
# automatic
+D = $(patsubst %/,%,$(dir $+))
# environment
XDG_SESSION_DESKTOP = budgie-desktop
# makefile
MAKEFILE_LIST :=
# automatic
@F = $(notdir $@)
# environment
VSCODE_VERBOSE_LOGGING = true
# environment
VSCODE_PID = 1877190
# environment
XDG_SESSION_TYPE = x11
# automatic
?D = $(patsubst %/,%,$(dir $?))
# environment
SESSION_MANAGER = local/bbr:@/tmp/.ICE-unix/1465,unix/bbr:/tmp/.ICE-unix/1465
# automatic
*F = $(notdir $*)
# environment
QT_QPA_PLATFORMTHEME = qt5ct
# environment
CHROME_DESKTOP = code-oss.desktop
# environment
DBUS_SESSION_BUS_ADDRESS = unix:path=/run/user/1000/bus
# automatic
<D = $(patsubst %/,%,$(dir $<))
# environment
VSCODE_NLS_CONFIG = {"locale":"en-gb","availableLanguages":{},"_languagePackSupport":true}
# default
MAKE_HOST := x86_64-pc-linux-gnu
# makefile
SHELL = /bin/sh
# default
MAKECMDGOALS := all
# environment
DOTNET_BUNDLE_EXTRACT_BASE_DIR = /home/bbr/.cache/dotnet_bundle_extract
# environment
SHLVL = 0
# environment
MAKELEVEL := 0
# default
MAKE = $(MAKE_COMMAND)
# environment
PATH = /home/bbr/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/home/bbr/.dotnet/tools:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin
# default
MAKEFILES :=
# environment
LC_MONETARY = hr_HR.UTF-8
# environment
MOTD_SHOWN = pam
# automatic
^F = $(notdir $^)
# environment
LC_TIME = hr_HR.UTF-8
# environment
GRADLE_HOME = /usr/share/java/gradle
# environment
VSCODE_LOG_NATIVE = false
# environment
LC_TELEPHONE = hr_HR.UTF-8
# automatic
?F = $(notdir $?)
# environment
XDG_CURRENT_DESKTOP = Budgie:GNOME
# automatic
+F = $(notdir $+)
# environment
XDG_SEAT_PATH = /org/freedesktop/DisplayManager/Seat0
# environment
DESKTOP_SESSION = budgie-desktop
# environment
ORIGINAL_XDG_CURRENT_DESKTOP = Budgie:GNOME
# 'override' directive
GNUMAKEFLAGS :=
# environment
LOGNAME = bbr
# environment
GIO_LAUNCHED_DESKTOP_FILE = /usr/share/applications/code-oss.desktop
# makefile
.DEFAULT_GOAL :=
# environment
EDITOR = /usr/bin/nano
# environment
DISPLAY = :0
# environment
GTK_MODULES = canberra-gtk-module
# environment
USER = bbr
# default
MAKE_VERSION := 4.3
# environment
LC_MEASUREMENT = hr_HR.UTF-8
# environment
GIO_LAUNCHED_DESKTOP_FILE_PID = 1877159
# environment
_ = /usr/bin/make
# environment
LC_PAPER = hr_HR.UTF-8
# environment
XDG_RUNTIME_DIR = /run/user/1000
# environment
XDG_SESSION_CLASS = user
# environment
VSCODE_AMD_ENTRYPOINT = vs/workbench/api/node/extensionHostProcess
# environment
GTK2_RC_FILES = /home/bbr/.gtkrc-2.0
# environment
HOME = /home/bbr
# environment
ELECTRON_RUN_AS_NODE = 1
# environment
VSCODE_IPC_HOOK = /run/user/1000/vscode-bb99a93f-1.66.0-main.sock
# default
.RECIPEPREFIX :=
# automatic
<F = $(notdir $<)
# default
SUFFIXES :=
# environment
VSCODE_CLI = 1
# environment
ELECTRON_NO_ATTACH_CONSOLE = 1
# environment
XDG_GREETER_DATA_DIR = /var/lib/lightdm-data/bbr
# default
.FEATURES := target-specific order-only second-expansion else-if shortest-stem undefine oneshell nocomment grouped-target extra-prereqs archives jobserver output-sync check-symlink guile load
# environment
XDG_MENU_PREFIX = gnome-
# environment
DOTNET_ROOT = /usr/share/dotnet
# environment
GDMSESSION = budgie-desktop
# environment
LC_IDENTIFICATION = hr_HR.UTF-8
# variable set hash-table stats:
# Load=102/1024=10%, Rehash=0, Collisions=5/129=4%
# Pattern-specific Variable Values
# No pattern-specific variable values.
# Directories
# . (device 66306, inode 9380506): 17 files, no impossibilities.
# 17 files, no impossibilities in 1 directories.
# Implicit Rules
# No implicit rules.
# Files
# Not a target:
Makefile:
# Implicit rule search has been done.
# File does not exist.
# File has been updated.
# Failed to be updated.
# Not a target:
.DEFAULT:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# Not a target:
all:
# Command line target.
# Implicit rule search has been done.
# File does not exist.
# File has not been updated.
# Not a target:
makefile:
# Implicit rule search has been done.
# File does not exist.
# File has been updated.
# Failed to be updated.
# Not a target:
GNUmakefile:
# Implicit rule search has been done.
# File does not exist.
# File has been updated.
# Failed to be updated.
# files hash-table stats:
# Load=6/1024=1%, Rehash=0, Collisions=0/15=0%
# VPATH Search Paths
# No 'vpath' search paths.
# No general ('VPATH' variable) search path.
# strcache buffers: 1 (0) / strings = 25 / storage = 264 B / avg = 10 B
# current buf: size = 8162 B / used = 264 B / count = 25 / avg = 10 B
# strcache performance: lookups = 28 / hit rate = 10%
# hash-table stats:
# Load=25/8192=0%, Rehash=0, Collisions=0/28=0%
# Finished Make data base on Sun Apr 24 22:18:48 2022

View File

@ -30,8 +30,7 @@ add_executable(SchemeEditor
comdel/domain/schemacreator.cpp
comdel/parser/comdelparser.cpp
comdel/parser/token.cpp
comdel/parser/parser_util.cpp
comdel/parser/sourceerror.cpp
comdel/parser/sourceerror.cpp
comdel/parser/parsecontext.cpp
comdel/parser/tokenstype.cpp
comdel/parser/astnode.cpp

View File

@ -2,6 +2,7 @@
#include <QMenu>
#include <QGraphicsSceneContextMenuEvent>
#include <QGraphicsScene>
#include <iostream>
#include "dialogmanager.h"
@ -34,10 +35,27 @@ ComponentWrapper *ComponentWrapper::ofBus(domain::BusInstance *instance) {
component->redraw();
return component;
}
void ComponentWrapper::redraw() {
void ComponentWrapper::clear() {
for(auto item: childItems()) {
this->removeFromGroup(item);
item->scene()->removeItem(item);
delete item;
}
if(componentInstance) {
componentItem->clear();
for(auto pinItem: pinItems) {
pinItem->clear();
}
}
}
void ComponentWrapper::redraw() {
if(componentInstance) {
addToGroup(componentItem);
componentItem->redraw();
for(auto pinItem: pinItems) {
addToGroup(pinItem);
pinItem->redraw();
}
this->addToGroup(new QGraphicsSimpleTextItem(QString::fromStdString(componentInstance->name)));
@ -60,17 +78,33 @@ ComponentItem::ComponentItem(domain::ComponentInstance *instance, QGraphicsItem
void ComponentItem::redraw() {
componentInstance->component.getDisplay().render(this);
}
void ComponentItem::clear() {
for(auto item: childItems()) {
this->removeFromGroup(item);
item->scene()->removeItem(item);
delete item;
}
}
void ComponentItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu;
auto componentInstance = this->componentInstance;
menu.addAction("Izmjeni ime", [componentInstance](){DialogManager::updateName(componentInstance);});
auto instance = this->componentInstance;
menu.addAction("Izmjeni ime", [instance, this](){
DialogManager::updateName(instance);
auto *wrapper = static_cast<ComponentWrapper*>(this->parentItem());
wrapper->clear();
wrapper->redraw();
});
menu.addSeparator();
for(auto attr: componentInstance->attributes) {
bool enabled = attr->attribute.getPopup().has_value();
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
[attr](){DialogManager::updateAttribute(attr);});
[attr, this]() {
DialogManager::updateAttribute(attr);
this->redraw();
});
action->setEnabled(enabled);
}
menu.exec(event->screenPos());
@ -84,4 +118,12 @@ PinItem::PinItem(domain::Pin pin, QGraphicsItem *parent): pin(pin) {
void PinItem::redraw() {
pin.getDisplay().render(this);
}
void PinItem::clear() {
for(auto item: childItems()) {
this->removeFromGroup(item);
item->scene()->removeItem(item);
delete item;
}
}
} // namespace display

View File

@ -13,6 +13,7 @@ class ComponentItem: public QGraphicsItemGroup
public:
ComponentItem(domain::ComponentInstance *instance, QGraphicsItem *parent);
void redraw();
void clear();
private:
domain::ComponentInstance *componentInstance;
@ -25,6 +26,7 @@ class PinItem: public QGraphicsItemGroup
public:
PinItem(domain::Pin pin, QGraphicsItem *parent);
void redraw();
void clear();
private:
domain::Pin pin;
};
@ -40,6 +42,23 @@ public:
this->setHandlesChildEvents(false);
}
void redraw();
void clear();
QVariant itemChange( GraphicsItemChange change, const QVariant &value ) override
{
auto response = QGraphicsItem::itemChange(change, value);
if (change == ItemPositionChange){
if(componentInstance != nullptr) {
componentInstance->position.first = (int)scenePos().x();
componentInstance->position.second = (int)scenePos().y();
} else if(busInstance != nullptr) {
busInstance->position.first = (int)scenePos().x();
busInstance->position.second = (int)scenePos().y();
}
}
return response;
}
private:
domain::ComponentInstance *componentInstance = nullptr;

View File

@ -1,23 +1,45 @@
//
// Created by bbr on 18. 04. 2022..
//
#ifndef NAME_DIALOG_H
#define NAME_DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <comdel/domain/instance.h>
namespace display {
class NameDialog: public QDialog {
public:
NameDialog(domain::ComponentInstance *instance) {
QLineEdit *edit;
domain::ComponentInstance *instance;
public:
NameDialog(domain::ComponentInstance *instance): instance(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);
}
public slots:
void onNameChange() {
instance->name = this->edit->text().toStdString();
this->close();
}
};
}
#endif //sNAME_DIALOG_H
#endif //NAME_DIALOG_H

View File

@ -9,10 +9,10 @@ AddressSpace::AddressSpace(std::string name, long long start, long long end):
std::string AddressSpace::getName() {
return name;
}
long long AddressSpace::getStart() {
long long AddressSpace::getStart() const {
return start;
}
long long AddressSpace::getEnd() {
long long AddressSpace::getEnd() const {
return end;
}

View File

@ -15,8 +15,8 @@ public:
AddressSpace(std::string name, long long start, long long end);
std::string getName();
long long getStart();
long long getEnd();
long long getStart() const;
long long getEnd() const;
bool contains(long long int address);
bool contains(long long int start, long long int end);

View File

@ -2,8 +2,8 @@
namespace domain {
Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTermination, long long ifUnterminated)
: name(name), type(type), width(width), hidden(hidden), hasTermination(hasTermination), ifUnterminated(ifUnterminated)
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)
{}
std::string Wire::getName() {
@ -15,18 +15,17 @@ int Wire::getWidth() {
bool Wire::isHidden() {
return hidden;
}
bool Wire::getHasTermination() {
return hasTermination;
bool Wire::hasTerminateWith() {
return hasTerminate;
}
long long Wire::getIfUnterminated() {
return ifUnterminated;
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<Display> display)
: name(name), tooltip(tooltip), type(type), count(count), wires(wires), display(display)
{}

View File

@ -2,6 +2,7 @@
#define DOMAIN_BUS_H
#include "display.h"
#include "value.h"
#include <string>
#include <optional>
@ -26,17 +27,17 @@ private:
WireType type;
int width;
bool hidden;
bool hasTermination;
long long ifUnterminated;
bool hasTerminate;
Value terminateWith;
public:
Wire(std::string name, WireType type, int width, bool hidden, bool hasTermination, long long ifUnterminated);
Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith);
std::string getName();
int getWidth();
bool isHidden();
bool getHasTermination();
long long getIfUnterminated();
bool hasTerminateWith();
Value getTerminateWith();
WireType getType();
};

View File

@ -16,6 +16,8 @@ public:
Connection connection;
WireInstance *wire;
virtual ~ConnectionInstance() = default;
std::vector<InstanceAttribute*> attributes;
ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute*> attributes, WireInstance *wire, Connection connection);

View File

@ -174,7 +174,7 @@ std::optional<Bus> SchemaCreator::loadBus(BusNode node)
return nullopt;
}
auto type = toType(node.type);
auto type = toType(node.type.value);
if(!node.tooltip && type == Bus::REGULAR) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
@ -392,7 +392,7 @@ std::optional<Component> SchemaCreator::loadComponent(ComponentNode node)
}
std::string source = node.source->asString();
Component::ComponentType type = toType(node.type);
Component::ComponentType type = toType(node.type.value);
std::vector<Attribute> attributes;
for(auto& a: node.attributes) {
@ -457,18 +457,18 @@ std::optional<Component> SchemaCreator::loadComponent(ComponentNode node)
std::optional<Wire> SchemaCreator::loadWire(WireNode node) {
return Wire(
node.name.value,
toType(node.type),
toType(node.type.value),
node.size.value,
node.hidden,
node.hasTermination,
node.isUnterminated
node.hasTerminateWith,
toType(node.terminateWith)
);
}
optional<Pin> SchemaCreator::loadPin(PinNode node)
{
std::string name = node.name.value;
Pin::PinType type = toType(node.type);
Pin::PinType type = toType(node.type.value);
if(!node.tooltip) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
@ -559,7 +559,7 @@ std::optional<Display> SchemaCreator::loadDisplay(DisplayNode node)
PinConnection SchemaCreator::loadPinConnection(PinConnectionNode node)
{
std::string message = node.message.asString();
PinConnection::ConnectionType type = toType(node.type);
PinConnection::ConnectionType type = toType(node.type.value);
return PinConnection(message, type);
}
@ -606,7 +606,7 @@ std::optional<Attribute> SchemaCreator::loadAttribute(AttributeNode node)
std::optional<Popup> SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type)
{
auto popupType = toType(*node.type);
auto popupType = toType(node.type.value().value);
pushAdditional(name);
@ -678,7 +678,7 @@ std::optional<Rule> SchemaCreator::loadRule(RuleNode node)
for(auto& stmt: node.statements) {
auto condition = loadCondition(stmt.condition);
if(condition) {
statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type), stmt.action.message.asString())));
statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type.value), stmt.action.message.asString())));
} else {
return nullopt;
}

View File

@ -137,4 +137,23 @@ Value Value::fromNull() {
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;
default:
throw std::exception();
}
}
} // namespace domain

View File

@ -55,6 +55,8 @@ public:
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);

View File

@ -1,8 +1,12 @@
#include "astnode.h"
/*************************** AST NODE ********************************/
AstNode::~AstNode() = default;
NumberNode::NumberNode(std::string expression) {
/*************************** NUMBER NODE ********************************/
NumberNode::NumberNode(const std::string& expression) {
if(expression.size() > 2) {
if(expression.substr(0, 2) == "0x") {
this->value = std::stoll(expression, 0, 16);
@ -15,3 +19,84 @@ NumberNode::NumberNode(std::string expression) {
this->value = std::stoll(expression, 0, 10);
}
}
/*************************** STRING NODE ********************************/
std::string StringNode::asString() {
return value.substr(1, value.length() - 2);
}
/*************************** VALUE NODE ********************************/
long long ValueNode::asInt() {
if(is(INT)) {
return intValue.value();
}
return 0;
}
std::string ValueNode::asString() {
if(is(STRING)) {
return stringValue.value();
}
return "";
}
std::string ValueNode::asIdentifier() {
if(is(IDENTIFIER) || is(WIRE)) {
return identifierValue.value();
}
return "";
}
bool ValueNode::asBool() {
if(is(BOOL)) {
return boolValue.value();
}
return false;
}
bool ValueNode::is(ValueNode::ValueType valueType) {
return type.value == valueType;
}
ValueNode ValueNode::ofBool(bool _value) {
ValueNode value;
value.type = EnumNode(BOOL);
value.boolValue = std::optional<bool>(_value);
return value;
}
ValueNode ValueNode::ofInt(long long int _value) {
ValueNode value;
value.type = EnumNode(INT);
value.intValue = std::optional<long long>(_value);
return value;
}
ValueNode ValueNode::ofString(std::string _value) {
ValueNode value;
value.type = EnumNode(STRING);
value.stringValue = std::optional<std::string>(_value);
return value;
}
ValueNode ValueNode::ofIdentifier(std::string _value) {
ValueNode value;
value.type = EnumNode(IDENTIFIER);
value.identifierValue = std::optional<std::string>(_value);
return value;
}
ValueNode ValueNode::ofNull() {
ValueNode value;
value.type = EnumNode(NIL);
return value;
}
ValueNode ValueNode::ofWire(std::string _value) {
ValueNode value;
value.type = EnumNode(WIRE);
value.identifierValue = std::optional<std::string>(_value);
return value;
}

View File

@ -16,24 +16,27 @@ public:
AstNode() = default;
virtual ~AstNode(); // this is defined in Ast.cpp just so that the
// compiler doesn't complain about not knowing which
// object file to include the vtable in
AstNode(AstNode&&) = default;
virtual ~AstNode();
AstNode(AstNode&&) = default;
AstNode& operator=(AstNode&&) = default;
AstNode(const AstNode&) = default;
AstNode& operator=(const AstNode&) = default;
};
template <typename T>
struct EnumNode: public AstNode
{
EnumNode() = default;
explicit EnumNode(T value): value(value) {}
T value;
};
struct StringNode: public AstNode
{
std::string value;
std::string asString() {
return value.substr(1, value.length() - 2);
}
std::string asString();
};
struct IdentifierNode: public AstNode
@ -43,7 +46,7 @@ struct IdentifierNode: public AstNode
struct NumberNode: public AstNode {
long long int value;
NumberNode(std::string expression);
explicit NumberNode(const std::string& expression);
NumberNode(): value(0) {}
};
@ -54,7 +57,7 @@ struct CountNode: public AstNode
NumberNode second;
CountNode(NumberNode first, NumberNode second): first(first), second(second) {}
CountNode() {}
CountNode() = default;
};
@ -65,7 +68,6 @@ struct AddressSpaceNode: public AstNode
NumberNode end;
};
class ValueNode: public AstNode
{
public:
@ -78,89 +80,32 @@ public:
NIL,
};
private:
ValueType type;
EnumNode<ValueType> type;
std::optional<long long> intValue;
std::optional<std::string> stringValue;
std::optional<bool> boolValue;
std::optional<std::string> identifierValue;
public:
ValueNode() {};
ValueNode() = default;;
ValueType getType() {
return type;
}
long long asInt() {
if(is(INT)) {
return intValue.value();
}
throw "cannot convert type to int";
}
std::string asString() {
if(is(STRING)) {
return stringValue.value();
}
throw "cannot convert type to string";
}
std::string asIdentifier() {
if(is(IDENTIFIER) || is(WIRE)) {
return identifierValue.value();
}
throw "cannot convert type to identifier";
}
bool asBool() {
if(is(BOOL)) {
return boolValue.value();
}
throw "cannot convert type to bool";
return type.value;
}
long long asInt();
std::string asString();
std::string asIdentifier();
bool asBool();
bool is(ValueType type) {
return this->type == type;
}
bool is(ValueType valueType);
static ValueNode ofBool(bool _value) {
ValueNode value;
value.type = BOOL;
value.boolValue = std::optional<bool>(_value);
return value;
}
static ValueNode ofInt(long long _value) {
ValueNode value;
value.type = INT;
value.intValue = std::optional<long long>(_value);
return value;
}
static ValueNode ofString(std::string _value) {
ValueNode value;
value.type = STRING;
value.stringValue = std::optional<std::string>(_value);
return value;
}
static ValueNode ofIdentifier(std::string _value) {
ValueNode value;
value.type = IDENTIFIER;
value.identifierValue = std::optional<std::string>(_value);
return value;
}
static ValueNode ofNull() {
ValueNode value;
value.type = NIL;
return value;
}
static ValueNode ofWire(std::string _value) {
ValueNode value;
value.type = WIRE;
value.identifierValue = std::optional<std::string>(_value);
return value;
}
static ValueNode ofBool(bool _value);
static ValueNode ofInt(long long _value);
static ValueNode ofString(std::string _value);
static ValueNode ofIdentifier(std::string _value);
static ValueNode ofNull();
static ValueNode ofWire(std::string _value);
};
struct ConditionNode
@ -177,7 +122,7 @@ public:
WARNING
};
ActionType type;
EnumNode<ActionType> type;
StringNode message;
};
@ -188,14 +133,11 @@ struct IfStatementNode: public AstNode
ActionNode action;
};
struct RuleNode: public AstNode
{
std::vector<IfStatementNode> statements;
};
struct EnumerationNode: public AstNode
{
StringNode key;
@ -209,7 +151,7 @@ struct PopupNode: public AstNode
ON_DEMAND
};
std::optional<PopupType> type;
std::optional<EnumNode<PopupType>> type;
std::optional<StringNode> title;
std::optional<StringNode> text;
@ -225,20 +167,17 @@ struct PropertyNode: public AstNode
ValueNode value;
};
struct DisplayItemNode: public AstNode
{
IdentifierNode type;
std::vector<PropertyNode> values;
};
struct DisplayNode: public AstNode
{
std::vector<DisplayItemNode> items;
};
struct PinConnectionNode: public AstNode
{
enum ConnectionType {
@ -247,10 +186,9 @@ struct PinConnectionNode: public AstNode
};
StringNode message;
ConnectionType type;
EnumNode<ConnectionType> type;
};
struct PinNode: public AstNode
{
enum PinType {
@ -260,14 +198,13 @@ struct PinNode: public AstNode
};
IdentifierNode name;
PinType type;
EnumNode<PinType> type;
std::optional<StringNode> tooltip;
std::optional<PinConnectionNode> connection;
std::optional<DisplayNode> display;
std::optional<std::vector<ValueNode>> wires;
};
struct WireNode: public AstNode
{
enum WireType {
@ -276,17 +213,16 @@ struct WireNode: public AstNode
WIRED_OR,
R_WIRE
};
WireType type;
EnumNode<WireType> type;
IdentifierNode name;
NumberNode size;
bool hidden;
bool hasTermination;
long long isUnterminated;
bool hasTerminateWith;
ValueNode terminateWith;
};
struct AttributeNode: public AstNode
{
ValueNode::ValueType type;
@ -324,7 +260,7 @@ struct ComponentNode: public AstNode
IdentifierNode name;
std::optional<StringNode> tooltip;
std::optional<StringNode> source;
ComponentType type;
EnumNode<ComponentType> type;
std::vector<RuleNode> rules;
std::optional<StringNode> instanceName;
std::optional<CountNode> count;
@ -333,7 +269,6 @@ struct ComponentNode: public AstNode
std::vector<AttributeNode> attributes;
};
struct BusNode: public AstNode
{
enum BusType {
@ -341,7 +276,7 @@ struct BusNode: public AstNode
REGULAR
};
BusType type;
EnumNode<BusType> type;
IdentifierNode name;
std::optional<StringNode> tooltip;
std::optional<CountNode> count;
@ -367,8 +302,6 @@ struct LibraryNode: public AstNode
};
// SCHEMA models
struct WireInstanceNode: public AstNode
{
IdentifierNode name;
@ -393,7 +326,8 @@ struct InstanceNode: public AstNode
std::optional<NumberNode> size;
};
struct ConnectionComponentInstance {
struct ConnectionComponentInstance: public AstNode
{
IdentifierNode instance;
IdentifierNode pin;
};

View File

@ -409,15 +409,7 @@ PResult<ComponentNode> ComdelParser::parseComponent()
ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier());
if(check(TokenType::CT_PROCESSOR)) {
bump();
component.type = ComponentNode::PROCESSOR;
} else if(check(TokenType::CT_MEMORY)) {
bump();
component.type = ComponentNode::MEMORY;
} else {
component.type = ComponentNode::OTHER;
}
auto type = parseComponentType();
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
@ -452,6 +444,23 @@ PResult<ComponentNode> ComdelParser::parseComponent()
return spanner(component);
}
PResult<EnumNode<ComponentNode::ComponentType>> ComdelParser::parseComponentType() {
EnumNode<ComponentNode::ComponentType> type;
auto spanner = getSpanner();
if(check(TokenType::CT_PROCESSOR)) {
bump();
type = EnumNode(ComponentNode::PROCESSOR);
} else if(check(TokenType::CT_MEMORY)) {
bump();
type = EnumNode(ComponentNode::MEMORY);
} else {
type = EnumNode(ComponentNode::OTHER);
}
return spanner(type);
}
/****************************************************************************
*
@ -509,18 +518,10 @@ PResult<BusNode> ComdelParser::parseBus() {
ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier());
if(check(TokenType::IDENTIFIER)) {
auto tokenType = parseIdentifier();
if(tokenType.value().value == "automatic") {
bus.type = BusNode::AUTOMATIC;
} else if(tokenType.value().value == "regular") {
bus.type = BusNode::REGULAR;
} else {
return PError(SourceError{current().span, "expected 'automatic' or 'regular'"});
}
} else {
return PError(SourceError{current().span, "expected 'automatic' or 'regular'"});
}
auto type = parseBusType();
RETURN_IF_ERR(type);
bus.type = *type;
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
@ -553,10 +554,28 @@ PResult<BusNode> ComdelParser::parseBus() {
return spanner(bus);
}
PResult<EnumNode<BusNode::BusType>> ComdelParser::parseBusType() {
PResult<EnumNode<BusNode::BusType>> type;
if(check(TokenType::IDENTIFIER)) {
auto tokenType = parseIdentifier();
if(tokenType.value().value == "automatic") {
type = EnumNode(BusNode::AUTOMATIC);
} else if(tokenType.value().value == "regular") {
type = EnumNode(BusNode::REGULAR);
} else {
type = PError(SourceError{current().span, "expected 'automatic' or 'regular'"});
}
} else {
type = PError(SourceError{current().span, "expected 'automatic' or 'regular'"});
}
return type;
}
/****************************************************************************
*
* WireNode := NAME(<SIZE>){0,1} TYPE)*
* WireNode := NAME(<SIZE>){0,1} TYPE [hidden | terminated_with (#number | null)])*
*
****************************************************************************/
PResult<WireNode> ComdelParser::parseWire() {
@ -574,20 +593,42 @@ PResult<WireNode> ComdelParser::parseWire() {
}
// default
wire.type = WireNode::WIRE;
wire.type = EnumNode(WireNode::WIRE);
if(check(TokenType::WIRE_DEFAULT)) {
bump();
wire.type = WireNode::WIRE;
wire.type = EnumNode(WireNode::WIRE);
} else if(check(TokenType::WIRE_AND)) {
bump();
wire.type = WireNode::WIRED_AND;
wire.type = EnumNode(WireNode::WIRED_AND);
} else if(check(TokenType::WIRE_OR)) {
bump();
wire.type = WireNode::WIRED_OR;
wire.type = EnumNode(WireNode::WIRED_OR);
} else if(check(TokenType::R_WIRE)) {
bump();
wire.type = WireNode::R_WIRE;
wire.type = EnumNode(WireNode::R_WIRE);
}
while(true) {
if(check(TokenType::HIDDEN)) {
bump();
wire.hidden = true;
} else if(check(TokenType::TERMINATE_WITH)) {
bump();
wire.hasTerminateWith = true;
if(check(TokenType::NIL)) {
bump();
wire.terminateWith = ValueNode::ofNull();
} else if(check(TokenType::NUMBER)) {
auto number = parseNumber();
wire.terminateWith = ValueNode::ofInt(number->value);
} else {
auto token = current();
return PError(SourceError{token.span, "unexpected token"});
}
} else {
break;
}
}
return spanner(wire);
@ -613,13 +654,13 @@ PResult<PinNode> ComdelParser::parsePin() {
if(check(TokenType::PIN_IN)) {
bump();
pin.type = PinNode::IN;
pin.type = EnumNode(PinNode::IN);
} else if(check(TokenType::PIN_OUT)) {
bump();
pin.type = PinNode::OUT;
pin.type = EnumNode(PinNode::OUT);
} else if(check(TokenType::PIN_IN_OUT)) {
bump();
pin.type = PinNode::IN_OUT;
pin.type = EnumNode(PinNode::IN_OUT);
} else {
return unexpected();
}
@ -662,18 +703,7 @@ PResult<PinConnectionNode> ComdelParser::parsePinConnection() {
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier();
if(type.value().value == "check_only") {
connection.type = PinConnectionNode::CHECK_ONLY;
} else if(type.value().value == "automatically") {
connection.type = PinConnectionNode::AUTOMATICALLY;
} else {
return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"});
}
} else {
return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"});
}
ASSIGN_OR_RETURN_IF_ERR(connection.type, parseConnectionType());
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
ASSIGN_OR_RETURN_IF_ERR(connection.message, parseString());
@ -682,6 +712,26 @@ PResult<PinConnectionNode> ComdelParser::parsePinConnection() {
return spanner(connection);
}
PResult<EnumNode<PinConnectionNode::ConnectionType>> ComdelParser::parseConnectionType() {
auto spanner = getSpanner();
EnumNode<PinConnectionNode::ConnectionType> type;
if(check(TokenType::IDENTIFIER)) {
auto identifier = parseIdentifier();
if(identifier.value().value == "check_only") {
type = EnumNode(PinConnectionNode::CHECK_ONLY);
} else if(identifier.value().value == "automatically") {
type = EnumNode(PinConnectionNode::AUTOMATICALLY);
} else {
return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"});
}
} else {
return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"});
}
return spanner(type);
}
/****************************************************************************
*
@ -808,16 +858,16 @@ PResult<PopupNode> ComdelParser::parsePopup() {
RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP);
if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier();
if(type.value().value == "automatic") {
popup.type = PopupNode::AUTOMATIC;
} else if(type.value().value == "on_demand") {
popup.type = PopupNode::ON_DEMAND;
auto identifier = parseIdentifier();
if(identifier.value().value == "automatic") {
popup.type = EnumNode(PopupNode::AUTOMATIC);
} else if(identifier.value().value == "on_demand") {
popup.type = EnumNode(PopupNode::ON_DEMAND);
} else {
return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"});
}
} else {
popup.type = PopupNode::ON_DEMAND;
popup.type = EnumNode(PopupNode::ON_DEMAND);
}
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
@ -975,9 +1025,9 @@ PResult<IfStatementNode> ComdelParser::parseIfStatement() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
if(check(TokenType::ERROR)) {
ifStatement.action.type = ActionNode::ERROR;
ifStatement.action.type = EnumNode(ActionNode::ERROR);
} else if(check(TokenType::WARNING)) {
ifStatement.action.type = ActionNode::WARNING;
ifStatement.action.type = EnumNode(ActionNode::WARNING);
} else {
return unexpected();
}
@ -1029,21 +1079,21 @@ std::optional<SchemaNode> ComdelParser::parseSchema() {
auto source = parseString();
schema.source = *source;
} else {
errors.push_back(SourceError{current().span, "expected `@source`"});
errors.emplace_back(current().span, "expected `@source`");
return std::nullopt;
}
} else {
errors.push_back(SourceError{current().span, "expected `@source`"});
errors.emplace_back(current().span, "expected `@source`");
return std::nullopt;
}
if(!check(TokenType::KW_SCHEMA)) {
errors.push_back(SourceError{current().span, "expected `@schema`"});
errors.emplace_back(current().span, "expected `@schema`");
return std::nullopt;
}
bump();
if(!check(TokenType::LBRACE)) {
errors.push_back(SourceError{current().span, "expected `{`"});
errors.emplace_back(current().span, "expected `{`");
return std::nullopt;
}
bump();
@ -1065,14 +1115,14 @@ std::optional<SchemaNode> ComdelParser::parseSchema() {
}
}
if(!check(TokenType::RBRACE)) {
errors.push_back(SourceError{current().span, "expected `}`"});
errors.emplace_back(current().span, "expected `}`");
return std::nullopt;
} else {
bump();
}
if(!check(TokenType::END_OF_FILE)) {
errors.push_back(SourceError{current().span, "expected `EOF`"});
errors.emplace_back(current().span, "expected `EOF`");
}
if (errors.size())

View File

@ -97,6 +97,12 @@ public:
std::optional<SchemaNode> parseSchema();
std::optional<LibraryNode> parse();
const std::vector<SourceError>& getErrors();
PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType();
PResult<EnumNode<BusNode::BusType>> parseBusType();
PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType();
};
#endif // COMDEL_PARSER_H

View File

@ -1,6 +0,0 @@
#include "parser_util.h"
parser_util::parser_util()
{
}

View File

@ -1,11 +0,0 @@
#ifndef PARSER_UTIL_H
#define PARSER_UTIL_H
class parser_util
{
public:
parser_util();
};
#endif // PARSER_UTIL_H

View File

@ -124,6 +124,10 @@ enum class TokenType {
ERROR,
WARNING,
// WIRE SETTINGS
HIDDEN,
TERMINATE_WITH,
// OTHER
END_OF_FILE
};

View File

@ -134,10 +134,10 @@ TokenTables::TokenTables() {
add( TokenType::WARNING, "warning", TOKENIZABLE),
// Built-in functions (they are also keywords)
/*
* TODO
*/
// WireNode settings types
add( TokenType::HIDDEN, "hidden", TOKENIZABLE),
add( TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE),
// Miscelaneous
add( TokenType::END_OF_FILE, "eof" );
}

View File

@ -0,0 +1,34 @@
@source "frisc_library.csl"
@schema {
@instance proc FRISC {
@position (0, 0)
}
@instance mem Memorija {
@position (0, 250)
@attribute kapacitet 1024
@attribute size 8
@attribute pocetnaAdresa 1023
}
@instance bus glavnaSabirnica {
@position (0, 200)
@size 100
}
@wire wire_001 {
@position (50, 116)
@display {}
}
@wire wire_002 {
@position (50, 220)
@display {}
}
@connection (proc.glavniPin, bus) {
@wire wire_001
}
@connection (mem.glavniPin, bus) {
@wire wire_002
}
}

View File

@ -12,6 +12,7 @@
#include <QPlainTextEdit>
#include <sstream>
#include <comdel/domain/comdelvalidator.h>
#include <fstream>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
@ -35,6 +36,7 @@ void MainWindow::setupUi()
// setup toolbar
ui->toolBar->addAction("Load library", this, &MainWindow::onLoadLibrary);
ui->toolBar->addAction("Load schema", this, &MainWindow::onLoadSchema);
ui->toolBar->addAction("Save schema", this, &MainWindow::onStoreScheme);
connect(ui->actionValidate, &QAction::triggered, this, &MainWindow::onValidateSchema);
@ -68,6 +70,8 @@ void MainWindow::onLoadLibrary() {
log->clear();
if(!filename.isEmpty()) {
librarySource = filename.toStdString();
clear();
ParseContext parseContext;
@ -77,7 +81,7 @@ void MainWindow::onLoadLibrary() {
library = generator.loadLibrary(*libraryNode);
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
parseContext.formatError(error, buffer, "ERROR: ");
}
if(generator.getErrors().empty()) {
@ -89,7 +93,7 @@ void MainWindow::onLoadLibrary() {
}
} else {
std::cout<<"Bad request"<<std::endl;
buffer<<"Bad request"<<std::endl;
}
}
@ -114,15 +118,17 @@ void MainWindow::onLoadSchema() {
domain::SchemaCreator generator(signatures);
library = generator.loadLibrary(*schemaNode->library);
librarySource = schemaNode->source->value;
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
parseContext.formatError(error, buffer, "ERROR: ");
}
if(library) {
schema = generator.loadSchema(*schemaNode, *library);
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
parseContext.formatError(error, buffer, "ERROR: ");
}
}
@ -136,6 +142,67 @@ void MainWindow::onLoadSchema() {
log->appendPlainText(QString::fromStdString(buffer.str()));
}
void MainWindow::onStoreScheme() {
if(schema == nullptr) {
return;
}
auto filename = QFileDialog::getSaveFileName(this,
tr("Save schema"), "/home", tr("Comdel schema (*.csl)"));
std::ostringstream buffer;
buffer << "@source " << this->librarySource << std::endl << std::endl;
buffer << "@schema {" << std::endl;
for(auto &instance: schema->instances) {
auto componentInstance = dynamic_cast<domain::ComponentInstance*>(instance);
if(componentInstance != NULL) {
buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() << " {" << std::endl;
buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " << componentInstance->position.second << ")" << std::endl;
for(auto &attribute: instance->attributes) {
buffer << "\t\t" << "@attribute " << attribute->name << " " << attribute->value.stringify() << std::endl;
}
buffer << "\t}" << std::endl << std::endl;
}
auto busInstance = dynamic_cast<domain::BusInstance*>(instance);
if(busInstance != NULL) {
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 &wire: schema->wires) {
buffer << "\t" << "@wire " << wire->name << " {" << std::endl;
buffer << "\t\t" << "@position (" << wire->position.first << ", " << wire->position.second << ")" << std::endl;
buffer << "\t\t" << "@display {}" << std::endl;
buffer << "\t" << "}" << std::endl;
}
for(auto &conn: schema->connections) {
auto busConn = dynamic_cast<domain::BusConnectionInstance*>(conn);
if(busConn) {
buffer << "\t" << "@connection (" << busConn->instance->name << "." << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl;
buffer << "\t\t"<< "@wire " << busConn->wire->name << std::endl;
buffer << "\t" << "}" << std::endl;
}
}
buffer << "}" << std::endl;
auto value = buffer.str();
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
out<<buffer.str();
out.close();
}
void MainWindow::onValidateSchema(bool /*toggled*/) {
if(schema == nullptr) {
return;
@ -201,4 +268,4 @@ void MainWindow::clear() {
MainWindow::~MainWindow()
{
delete ui;
}
}

View File

@ -39,8 +39,10 @@ private slots:
void onLoadLibrary();
void onLoadSchema();
void onValidateSchema(bool toggled);
void onStoreScheme();
private:
std::string librarySource;
Ui::MainWindow *ui;
QPlainTextEdit *log;
std::vector<domain::ValidationError> validationErrors;