added domain model

This commit is contained in:
Borna Rajkovic 2022-03-31 23:20:41 +02:00
parent 18d84727ab
commit f4450494d8
43 changed files with 1903 additions and 234 deletions

View File

@ -9,6 +9,18 @@ CONFIG += c++17
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
comdel/domain/addressspace.cpp \
comdel/domain/attribute.cpp \
comdel/domain/bus.cpp \
comdel/domain/comdelgenerator.cpp \
comdel/domain/component.cpp \
comdel/domain/connection.cpp \
comdel/domain/display.cpp \
comdel/domain/functionsignature.cpp \
comdel/domain/library.cpp \
comdel/domain/pin.cpp \
comdel/domain/rule.cpp \
comdel/domain/value.cpp \
comdel/parser/assert.cpp \
comdel/parser/astnode.cpp \
comdel/parser/comdellexer.cpp \
@ -18,15 +30,22 @@ SOURCES += \
comdel/parser/sourceerror.cpp \
comdel/parser/token.cpp \
comdel/parser/tokenstype.cpp \
domain/schema/connectioninstance.cpp \
domain/schema/instance.cpp \
domain/schema/instanceattribute.cpp \
domain/schema/schema.cpp \
domain/schema/wireinstance.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
comdel/domain/addressspace.h \
comdel/domain/attribute.h \
comdel/domain/bus.h \
comdel/domain/comdelgenerator.h \
comdel/domain/component.h \
comdel/domain/connection.h \
comdel/domain/display.h \
comdel/domain/functionsignature.h \
comdel/domain/library.h \
comdel/domain/pin.h \
comdel/domain/rule.h \
comdel/domain/value.h \
comdel/parser/assert.h \
comdel/parser/astnode.h \
comdel/parser/comdellexer.h \
@ -39,11 +58,6 @@ HEADERS += \
comdel/parser/sourceerror.h \
comdel/parser/token.h \
comdel/parser/tokenstype.h \
domain/schema/connectioninstance.h \
domain/schema/instance.h \
domain/schema/instanceattribute.h \
domain/schema/schema.h \
domain/schema/wireinstance.h \
mainwindow.h
FORMS += \

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 6.0.2, 2022-03-29T08:16:57. -->
<!-- Written by QtCreator 6.0.2, 2022-03-30T08:39:47. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -0,0 +1,19 @@
#include "addressspace.h"
namespace domain {
AddressSpace::AddressSpace(std::string name, long long start, long long end):
name(name), start(start), end(end)
{}
std::string AddressSpace::getName() {
return name;
}
long long AddressSpace::getStart() {
return start;
}
long long AddressSpace::getEnd() {
return end;
}
} // namespace domain

View File

@ -0,0 +1,26 @@
#ifndef DOMAIN_ADDRESSSPACE_H
#define DOMAIN_ADDRESSSPACE_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();
long long getEnd();
};
} // namespace domain
#endif // DOMAIN_ADDRESSSPACE_H

View File

@ -0,0 +1,56 @@
#include "attribute.h"
namespace domain {
Enumeration::Enumeration(std::string name, Value value)
: name(name), value(value)
{}
std::string Enumeration::getName() {
return name;
}
Value Enumeration::getValue() {
return value;
}
Popup::Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration)
: title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), enumeration(enumeration)
{}
std::string Popup::getTitle() {
return title;
}
std::string Popup::getText() {
return text;
}
Popup::PopupType Popup::getType() {
return type;
}
std::vector<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)
: name(name), defaultValue(defaultValue), popup(popup)
{}
std::string Attribute::getName() {
return name;
}
Value Attribute::getDefault() {
return defaultValue;
}
std::optional<Popup> Attribute::getPopup() {
return popup;
}
} // namespace domain

65
comdel/domain/attribute.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef DOMAIN_ATTRIBUTE_H
#define DOMAIN_ATTRIBUTE_H
#include "rule.h"
#include "value.h"
#include <vector>
namespace domain {
class Enumeration {
std::string name;
Value value;
public:
Enumeration(std::string name, Value value);
std::string getName();
Value getValue();
};
class Popup {
public:
enum PopupType {
AUTOMATIC,
ON_DEMAND
};
private:
std::string title;
std::string text;
PopupType type;
bool enumerated;
std::vector<Enumeration> enumeration;
std::vector<Rule> rules;
public:
Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration);
std::string getTitle();
std::string getText();
PopupType getType();
std::vector<Rule> getRules();
bool isEnumerated();
std::vector<Enumeration> &getEnumeration();
};
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
#endif // DOMAIN_ATTRIBUTE_H

26
comdel/domain/bus.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "bus.h"
namespace domain {
Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display)
: name(name), tooltip(tooltip), type(type), count(count), display(display)
{}
std::string Bus::getName() {
return name;
}
std::string Bus::getTooltip() {
return tooltip;
}
Bus::BusType Bus::getType() {
return type;
}
std::pair<int, int> Bus::getCount() {
return count;
}
std::optional<Display> Bus::getDisplay() {
return display;
}
} // namespace domain

40
comdel/domain/bus.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef DOMAIN_BUS_H
#define DOMAIN_BUS_H
#include "display.h"
#include <string>
#include <optional>
namespace domain {
class Bus
{
public:
enum BusType {
AUTOMATIC,
REGULAR
};
private:
std::string name;
std::string tooltip;
BusType type;
std::pair<int, int> count;
std::optional<Display> display;
public:
Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display = std::nullopt);
std::string getName();
std::string getTooltip();
BusType getType();
std::pair<int, int> getCount();
std::optional<Display> getDisplay();
};
} // namespace domain
#endif // DOMAIN_BUS_H

View File

@ -0,0 +1,445 @@
#include "comdelgenerator.h"
#include<set>
namespace domain {
Component::ComponentType toType(ComponentNode::ComponentType type) {
if(type == ComponentNode::MEMORY) {
return Component::MEMORY;
} else if(type == ComponentNode::PROCESSOR) {
return Component::PROCESSOR;
}
return Component::OTHER;
}
Action::ActionType toType(ActionNode::ActionType type) {
if(type == ActionNode::ERROR) {
return Action::ERROR;
}
return Action::WARNING;
}
Value::ValueType toType(ValueNode::ValueType type) {
switch (type) {
case ValueNode::BOOL:
return Value::BOOL;
case ValueNode::WIRE:
return Value::WIRE_REFERENCE;
case ValueNode::STRING:
return Value::STRING;
case ValueNode::INT:
return Value::INT;
default:
return Value::UNDEFINED;
}
}
Value toType(ValueNode node) {
if(node.getType() == ValueNode::BOOL) {
return Value::fromBool(node.asBool());
} else if(node.getType() == ValueNode::INT) {
return Value::fromInt(node.asInt());
} else if(node.getType() == ValueNode::STRING) {
return Value::fromString(node.asString());
}
return Value::fromReference(node.asIdentifier(), Value::UNDEFINED);
}
Bus::BusType toType(BusNode::BusType type) {
if(type == BusNode::AUTOMATIC) {
return Bus::AUTOMATIC;
}
return Bus::REGULAR;
}
Pin::PinType toType(PinNode::PinType type) {
if(type == PinNode::IN) {
return Pin::IN;
} else if(type == PinNode::OUT) {
return Pin::OUT;
}
return Pin::IN_OUT;
}
PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type)
{
if(type == PinConnectionNode::AUTOMATICALLY) {
return PinConnection::AUTOMATICALLY;
}
return PinConnection::CHECK_ONLY;
}
Popup::PopupType toType(PopupNode::PopupType type)
{
if(type == PopupNode::AUTOMATIC) {
return Popup::AUTOMATIC;
}
return Popup::ON_DEMAND;
}
ComdelGenerator::ComdelGenerator(std::vector<FunctionSignature> signatures)
: signatures(signatures)
{}
std::optional<Library> ComdelGenerator::loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream)
{
// library fields
if(!node.name) {
errors.push_back(SourceError{node.span, "missing @name"});
return nullopt;
}
std::string name = node.name->asString();
if(!node.componentDirectory) {
errors.push_back(SourceError{node.span, "missing @componentDirectory"});
return nullopt;
}
std::string componentDirectory = node.componentDirectory->asString();
std::string header = node.header ? node.header->asString() : "";
std::string libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : "";
std::vector<AddressSpace> addressSpaces;
for(auto& as: node.addressSpaces) {
addressSpaces.push_back(*loadAddressSpace(as));
}
std::vector<Component> components;
for(auto& comp: node.components) {
std::optional<Component> component;
component = loadComponent(comp);
if(component) {
components.push_back(*component);
}
}
std::vector<Connection> connections;
for(uint i=0; i<node.connections.size(); i++) {
auto conn = loadConnection(node.connections[i]);
if(!conn) {
return nullopt;
}
connections.push_back(*conn);
}
std::map<std::string, std::string> messages;
for(uint i=0; i<node.messages.size(); i++) {
if(!node.messages[i].value.is(ValueNode::STRING)) {
errors.push_back(SourceError{node.messages[i].key.span, "expected `string`"});
return nullopt;
}
messages[node.messages[i].key.value] = node.messages[i].value.asString();
}
std::vector<Bus> buses;
for(uint i=0; i<node.buses.size(); i++) {
auto bus = loadBus(node.buses[i]);
if(!bus) {
return nullopt;
}
}
return Library(name, libraryInfo, header, componentDirectory, addressSpaces, components, buses, connections, messages);
}
std::optional<Bus> ComdelGenerator::loadBus(BusNode node)
{
std::string name = node.name.value;
auto count = std::make_pair<int, int>(1, 1);
if(node.count) {
count = std::make_pair<int, int>(node.count->first.value, node.count->second.value);
}
if(count.first > count.second || count.first < 0) {
errors.push_back(SourceError{node.count->span, "invalid @size (min, max) := min <= max && min >= 0"});
return nullopt;
}
auto type = toType(node.type);
if(!node.tooltip && type == Bus::REGULAR) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
return nullopt;
}
std::string tooltip = node.tooltip->asString();
if(!node.display && type == Bus::REGULAR) {
errors.push_back(SourceError{node.span, "missing @display"});
return nullopt;
}
if(node.display && type == Bus::AUTOMATIC) {
errors.push_back(SourceError{node.span, "automatic bus cannot have a @display"});
return nullopt;
}
optional<Display> display;
if(Bus::REGULAR) {
display = loadDisplay(*node.display);
if(!display) {
return nullopt;
}
}
return Bus(name, tooltip, type, count, display);
}
std::optional<AddressSpace> ComdelGenerator::loadAddressSpace(AddressSpaceNode node)
{
return AddressSpace(node.name.value, node.start.value, node.end.value);
}
std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
{
std::string component = node.component.value;
std::string pin = node.pin.value;
std::string bus = node.bus.value;
std::vector<Attribute> attributes;
for(uint i=0; i<node.attributes.size(); i++) {
auto attr = loadAttribute(node.attributes[i]);
if(!attr) {
return nullopt;
}
attributes.push_back(*attr);
}
std::set<std::string> attributeNames;
for(auto attribute: attributes) {
attributeNames.insert(attribute.getName());
}
std::vector<Value> wires;
for(uint i=0; i<node.wires.size(); i++) {
if(attributeNames.count(node.wires[i].value)) {
wires.push_back(Value::fromReference(node.wires[i].value, Value::ATTRIBUTE_REFERENCE));
} else {
wires.push_back(Value::fromReference(node.wires[i].value, Value::WIRE_REFERENCE));
}
}
return Connection(component, pin, bus, attributes, wires);
}
std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
{
std::string name = node.name.value;
if(!node.tooltip) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
return nullopt;
}
std::string tooltip = node.tooltip->asString();
if(!node.source) {
errors.push_back(SourceError{node.span, "missing @source"});
return nullopt;
}
std::string source = node.source->asString();
Component::ComponentType type = toType(node.type);
std::vector<Attribute> attributes;
for(auto& a: node.attributes) {
std::optional<Attribute> attribute = loadAttribute(a);
if(attribute) {
attributes.push_back(*attribute);
}
}
std::vector<Rule> rules;
for(auto& r: node.rules) {
std::optional<Rule> rule = loadRule(r);
if(rule) {
rules.push_back(*rule);
}
}
if(!node.instanceName) {
errors.push_back(SourceError{node.span, "missing @instanceName"});
return nullopt;
}
std::string instanceName = node.instanceName->asString();
auto count = std::make_pair<int, int>(1, 1);
if(node.count) {
count = std::make_pair<int, int>(node.count->first.value, node.count->second.value);
}
if(count.first > count.second || count.first < 0) {
errors.push_back(SourceError{node.count->first.span, "invalid @size"});
return nullopt;
}
if(!node.display) {
errors.push_back(SourceError{node.span, "missing @display"});
return nullopt;
}
optional<Display> display = loadDisplay(*node.display);
if(!display) {
return nullopt;
}
std::vector<Pin> pins;
for(uint i=0; i<node.pins.size(); i++) {
auto pin = loadPin(node.pins[i]);
if(!pin) {
return nullopt;
}
}
return Component(name, tooltip, source, type, rules, instanceName, count, *display, pins, attributes);
}
optional<Pin> ComdelGenerator::loadPin(PinNode node)
{
std::string name = node.name.value;
Pin::PinType type = toType(node.type);
if(!node.tooltip) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
return nullopt;
}
std::string tooltip = node.tooltip->asString();
if(!node.display) {
errors.push_back(SourceError{node.span, "missing @display"});
return nullopt;
}
std::vector<Attribute> attributes;
optional<Display> display = loadDisplay(*node.display);
if(!display) {
return nullopt;
}
if(!node.connection) {
errors.push_back(SourceError{node.span, "missing @connection"});
return nullopt;
}
auto connection = loadPinConnection(*node.connection);
return Pin(name, type, tooltip, connection, *display);
}
std::optional<Display> ComdelGenerator::loadDisplay(DisplayNode node)
{
return Display();
}
PinConnection ComdelGenerator::loadPinConnection(PinConnectionNode node)
{
std::string message = node.message.asString();
PinConnection::ConnectionType type = toType(node.type);
return PinConnection(message, type);
}
std::optional<Attribute> ComdelGenerator::loadAttribute(AttributeNode node)
{
std::string name = node.name.value;
Value value;
if(node.type == ValueNode::INT) {
value = Value::fromInt(node.defaultValue->asInt());
} else if (node.type == ValueNode::BOOL) {
value = Value::fromBool(node.defaultValue->asBool());
} else if (node.type == ValueNode::STRING) {
value = Value::fromString(node.defaultValue->asString());
} else if (node.type == ValueNode::WIRE) {
value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE);
}
std::optional<Popup> popup;
if(node.popup) {
popup = loadPopup(*node.popup, name, value.getType());
}
return Attribute(name, value, popup);
}
std::optional<Popup> ComdelGenerator::loadPopup(PopupNode node, std::string name, Value::ValueType type)
{
auto popupType = toType(*node.type);
if(!node.title) {
errors.push_back(SourceError{node.span, "missing @title"});
return nullopt;
}
std::string title = node.title->asString();
if(!node.text) {
errors.push_back(SourceError{node.span, "missing @text"});
return nullopt;
}
std::string text = node.text->asString();
std::vector<Attribute> attributes;
attributes.push_back(Attribute(name, Value::ofType(type)));
std::vector<Rule> rules;
for(auto& r: node.rules) {
std::optional<Rule> rule = loadRule(r);
if(rule) {
rules.push_back(*rule);
}
}
std::vector<Enumeration> enumeration;
if(node.enumerated) {
for(uint i=0; i<node.enumeration.size(); i++) {
if(toType(node.enumeration[i].value.getType()) != type) {
errors.push_back(SourceError{node.enumeration[i].span, "wrong type"});
return nullopt;
}
enumeration.push_back(Enumeration(node.enumeration[i].key.asString(),
toType(node.enumeration[i].value)));
}
}
return Popup(title, text, popupType, rules, enumeration);
}
std::optional<Rule> ComdelGenerator::loadRule(RuleNode node)
{
std::vector<IfStatement> statements;
for(auto& stmt: node.statements) {
auto condition = loadCondition(stmt.condition);
if(condition) {
statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type), stmt.action.message.asString())));
} else {
return nullopt;
}
}
return Rule(statements);
}
std::optional<Condition> ComdelGenerator::loadCondition(ConditionNode node)
{
std::string function = node.functionName.value;
for(uint i=0; i<signatures.size(); i++) {
if(signatures[i].name == function) {
if(signatures[i].params.size() == node.params.size()) {
std::vector<Value> params;
for(int j=0; j<signatures[i].params[i]; j++) {
params.push_back(toType(node.params[i]));
}
return Condition(function,params, node.negated);
}
}
}
return nullopt;
}
} // namespace domain

View File

@ -0,0 +1,41 @@
#ifndef DOMAIN_COMDELGENERATOR_H
#define DOMAIN_COMDELGENERATOR_H
#include "library.h"
#include <comdel/parser/astnode.h>
#include <comdel/parser/parsecontext.h>
#include <comdel/parser/presult.h>
namespace domain {
class ComdelGenerator
{
std::vector<SourceError> errors;
std::vector<FunctionSignature> signatures;
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<Pin> loadPin(PinNode pins);
PinConnection loadPinConnection(PinConnectionNode node);
std::optional<Connection> loadConnection(ConnectionNode node);
std::optional<Bus> loadBus(BusNode node);
public:
ComdelGenerator(std::vector<FunctionSignature> signatures);
std::vector<SourceError> getErrors() {
return errors;
}
std::optional<Library> loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream);
};
} // namespace domain
#endif // DOMAIN_COMDELGENERATOR_H

View File

@ -0,0 +1,62 @@
#include "component.h"
namespace domain {
Component::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)
: name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), count(count), display(display), pins(pins), attributes(attributes)
{}
std::string Component::getName() {
return name;
}
std::string Component::getTooltip() {
return tooltip;
}
std::string Component::getSource() {
return source;
}
Component::ComponentType Component::getType() {
return type;
}
std::vector<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();
}
std::vector<Attribute> Component::getAttributes() {
return attributes;
}
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();
}
} // namespace domain

63
comdel/domain/component.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef DOMAIN_COMPONENT_H
#define DOMAIN_COMPONENT_H
#include "pin.h"
#include "rule.h"
#include "display.h"
#include "attribute.h"
#include <string>
#include <vector>
namespace domain {
using namespace std;
class Component
{
public:
enum ComponentType {
OTHER,
PROCESSOR,
MEMORY
};
private:
std::string name;
std::string tooltip;
std::string source;
ComponentType type;
std::vector<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);
};
} // namespace domain
#endif // DOMAIN_COMPONENT_H

View File

@ -0,0 +1,39 @@
#include "connection.h"
namespace domain {
Connection::Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires)
: component(component), pin(pin), bus(bus), attributes(attributes), wires(wires)
{}
bool Connection::isConnecting(std::string component, std::string pin, std::string bus) {
return this->component == component && this->pin == pin && this->bus == bus;
}
std::string Connection::getComponent() {
return component;
}
std::string Connection::getPin() {
return pin;
}
std::string Connection::getBus() {
return bus;
}
std::vector<Attribute> Connection::getAttributes() {
return attributes;
}
std::vector<Value> Connection::getWires() {
return wires;
}
Attribute Connection::getAttribute(std::string name) {
for(uint i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == name) {
return attributes[i];
}
}
throw std::exception();
}
} // namespace domain

View File

@ -0,0 +1,36 @@
#ifndef DOMAIN_CONNECTION_H
#define DOMAIN_CONNECTION_H
#include "attribute.h"
#include <string>
#include <vector>
namespace domain {
class Connection
{
std::string component;
std::string pin;
std::string bus;
std::vector<Attribute> attributes;
std::vector<Value> wires;
public:
Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires);
bool isConnecting(std::string component, std::string pin, std::string bus);
std::string getComponent();
std::string getPin();
std::string getBus();
std::vector<Attribute> getAttributes();
std::vector<Value> getWires();
Attribute getAttribute(std::string name);
};
} // namespace domain
#endif // DOMAIN_CONNECTION_H

10
comdel/domain/display.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "display.h"
namespace domain {
Display::Display()
{
}
} // namespace domain

15
comdel/domain/display.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef DOMAIN_DISPLAY_H
#define DOMAIN_DISPLAY_H
namespace domain {
class Display
{
public:
Display();
};
} // namespace domain
#endif // DOMAIN_DISPLAY_H

View File

@ -0,0 +1,5 @@
#include "functionsignature.h"
namespace domain {
} // namespace domain

View File

@ -0,0 +1,20 @@
#ifndef DOMAIN_FUNCTIONSIGNATURE_H
#define DOMAIN_FUNCTIONSIGNATURE_H
#include<functional>
#include "value.h"
namespace domain {
typedef std::function<bool (std::vector<Value>)> FunctionCallback;
struct FunctionSignature {
std::string name;
std::vector<Value::ValueType> params;
FunctionSignature(std::string name, std::vector<Value::ValueType> params): name(name), params(params) {}
};
} // namespace domain
#endif // DOMAIN_FUNCTIONSIGNATURE_H

78
comdel/domain/library.cpp Normal file
View File

@ -0,0 +1,78 @@
#include "library.h"
namespace domain {
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)
: name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), addressSpaces(addressSpaces),
components(components), buses(buses), connections(connections), messages(messages)
{}
std::string Library::getName() {
return name;
}
std::string Library::getLibraryInfo() {
return libraryInfo;
}
std::string Library::getHeader() {
return header;
}
std::string Library::getComponentDirectory() {
return componentDirectory;
}
std::vector<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;
}
AddressSpace &Library::getAddressSpace(std::string addressSpace) {
for(uint i=0; i<addressSpaces.size(); i++) {
if(addressSpaces[i].getName() == addressSpace) {
return addressSpaces[i];
}
}
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();
}
std::optional<Connection> Library::getConnection(std::string component, std::string pin, std::string bus) {
for(uint i=0; i<connections.size(); i++) {
if(connections[i].isConnecting(component, pin, bus)) {
return connections[i];
}
}
return nullopt;
}
std::string Library::getMessage(std::string key) {
return messages[key];
}
} // namespace domain

58
comdel/domain/library.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef DOMAIN_LIBRARY_H
#define DOMAIN_LIBRARY_H
#include "addressspace.h"
#include "bus.h"
#include "component.h"
#include "connection.h"
#include <string>
#include <vector>
namespace domain {
using namespace std;
class Library
{
std::string name;
std::string libraryInfo;
std::string header;
std::string componentDirectory;
std::vector<AddressSpace> addressSpaces;
std::vector<Component> components;
std::vector<Bus> buses;
std::vector<Connection> connections;
std::map<std::string, std::string> messages;
public:
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::string getName();
std::string getLibraryInfo();
std::string getHeader();
std::string getComponentDirectory();
std::vector<AddressSpace> getAddressSpaces();
std::vector<Component> getComponents();
std::vector<Bus> getBuses();
std::vector<Connection> getConnections();
std::map<std::string, std::string> getMessages();
AddressSpace &getAddressSpace(std::string name);
Component &getComponent(std::string name);
Bus &getBus(std::string bus);
std::optional<Connection> getConnection(std::string component, std::string pin, std::string bus);
std::string getMessage(std::string key);
};
} // namespace domain
#endif // DOMAIN_LIBRARY_H

38
comdel/domain/pin.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "pin.h"
namespace domain {
PinConnection::PinConnection(std::string message, ConnectionType type)
: message(message), type(type)
{}
PinConnection::ConnectionType PinConnection::getType() {
return type;
}
std::string PinConnection::getMessage() {
return message;
}
Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display)
: name(name), type(type), tooltip(tooltip), connection(connection), display(display)
{}
std::string Pin::getName() {
return name;
}
Pin::PinType Pin::getType() {
return type;
}
std::string Pin::getTooltip() {
return tooltip;
}
Display &Pin::getDisplay() {
return display;
}
PinConnection &Pin::getConnection() {
return connection;
}
} // namespace domain

59
comdel/domain/pin.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef DOMAIN_PIN_H
#define DOMAIN_PIN_H
#include "display.h"
#include <string>
namespace domain {
class PinConnection
{
public:
enum ConnectionType {
CHECK_ONLY,
AUTOMATICALLY
};
private:
std::string message;
ConnectionType type;
public:
PinConnection(std::string message, ConnectionType type);
ConnectionType getType();
std::string getMessage();
};
class Pin
{
public:
enum PinType {
IN_OUT,
IN,
OUT
};
private:
std::string name;
PinType type;
std::string tooltip;
PinConnection connection;
Display display;
public:
Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display);
std::string getName();
PinType getType();
std::string getTooltip();
Display &getDisplay();
PinConnection &getConnection();
};
} // namespace domain
#endif // DOMAIN_PIN_H

60
comdel/domain/rule.cpp Normal file
View File

@ -0,0 +1,60 @@
#include "rule.h"
namespace domain {
Condition::Condition(std::string function, std::vector<Value> params, bool negated)
: negated(negated), function(function), params(params)
{}
bool Condition::evaluate(RuleContext &context) {
std::vector<Value> request;
for(uint i=0; i<params.size(); i++) {
if(params[i].isType(Value::ATTRIBUTE_REFERENCE)) {
request.push_back(context.attributes[params[i].asReference()]);
} else {
request.push_back(params[i]);
}
}
bool result = context.function[function](request);
return negated ? !result : result;
}
Action::Action(ActionType type, std::string message)
: type(type), message(message)
{}
Action::ActionType Action::getType() {
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)
: statements(statements)
{}
std::optional<Action> Rule::evaluate(RuleContext &context) {
for(uint i=0; i<statements.size(); i++) {
auto response = statements[i].evaluate(context);
if(response) {
return response;
}
}
return std::nullopt;
}
} // namespace domain

70
comdel/domain/rule.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef DOMAIN_RULE_H
#define DOMAIN_RULE_H
#include "addressspace.h"
#include "value.h"
#include "functionsignature.h"
#include <map>
#include <string>
#include <vector>
#include <optional>
namespace domain {
struct RuleContext {
std::map<std::string, AddressSpace> addressSpaces;
std::map<std::string, Value> attributes;
std::map<std::string, FunctionCallback> 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:
ActionType type;
std::string message;
public:
Action(ActionType type, std::string message);
ActionType getType();
std::string getMessage();
};
class IfStatement {
Condition condition;
Action action;
public:
IfStatement(Condition condition, Action action);
std::optional<Action> evaluate(RuleContext &context);
};
class Rule
{
std::vector<IfStatement> statements;
public:
Rule(std::vector<IfStatement> statements);
std::optional<Action> evaluate(RuleContext &context);
};
} // namespace domain
#endif // DOMAIN_RULE_H

82
comdel/domain/value.cpp Normal file
View File

@ -0,0 +1,82 @@
#include "value.h"
#include <string>
namespace domain {
Value::ValueType Value::getType() {
return type;
}
bool Value::isType(Value::ValueType type) {
return this->type == type;
}
long long Value::asInt() {
if(isType(Value::INT)) {
return intValue;
}
throw std::exception();
}
std::string Value::asString() {
if(isType(Value::STRING)) {
return stringValue;
}
throw std::exception();
}
bool Value::asBool() {
if(isType(Value::BOOL)) {
return boolValue;
}
throw std::exception();
}
AddressSpace Value::asAddressSpace() {
if(isType(Value::ADDRESS_SPACE)) {
return *addressSpace;
}
throw std::exception();
}
std::string Value::asReference() {
if(isType(Value::WIRE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE)) {
return reference;
}
throw std::exception();
}
Value Value::fromInt(long long value) {
Value val;
val.type = Value::INT;
val.intValue = value;
return val;
}
Value Value::fromString(std::string value) {
Value val;
val.type = Value::STRING;
val.stringValue = value;
return val;
}
Value Value::fromBool(bool value) {
Value val;
val.type = Value::BOOL;
val.boolValue = value;
return val;
}
Value Value::fromAddressSpace(AddressSpace addressSpace) {
Value val;
val.type = Value::ADDRESS_SPACE;
val.addressSpace = addressSpace;
return val;
}
Value Value::fromReference(std::string value, Value::ValueType type) {
Value val;
val.type = type;
val.reference = value;
return val;
}
Value Value::ofType(Value::ValueType type) {
Value val;
val.type = type;
return val;
}
} // namespace domain

58
comdel/domain/value.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef DOMAIN_VALUE_H
#define DOMAIN_VALUE_H
#include "addressspace.h"
#include <string>
#include <optional>
namespace domain {
class Value
{
public:
enum ValueType {
INT,
STRING,
BOOL,
ADDRESS_SPACE,
ATTRIBUTE_REFERENCE,
WIRE_REFERENCE,
UNDEFINED,
};
private:
long long intValue;
std::string stringValue;
bool boolValue;
std::optional<AddressSpace> addressSpace;
std::string reference;
ValueType type;
public:
Value() {
this->type = UNDEFINED;
}
ValueType getType();
bool isType(ValueType type);
long long asInt();
std::string asString();
bool asBool();
std::string asReference();
AddressSpace asAddressSpace();
static Value fromInt(long long value);
static Value fromString(std::string value);
static Value fromBool(bool value);
static Value fromAddressSpace(AddressSpace addressSpace);
static Value fromReference(std::string value, ValueType type);
static Value ofType(ValueType type);
};
} // namespace domain
#endif // DOMAIN_VALUE_H

View File

@ -31,6 +31,9 @@ public:
struct StringNode: public AstNode
{
std::string value;
std::string asString() {
return value.substr(1, value.length() - 2);
}
};
struct IdentifierNode: public AstNode
@ -44,6 +47,7 @@ struct NumberNode: public AstNode {
NumberNode(): value(0) {}
};
struct CountNode: public AstNode
{
NumberNode first;
@ -54,7 +58,7 @@ struct CountNode: public AstNode
};
struct AddressSpace: public AstNode
struct AddressSpaceNode: public AstNode
{
IdentifierNode name;
NumberNode start;
@ -62,13 +66,14 @@ struct AddressSpace: public AstNode
};
class Value: AstNode
class ValueNode: AstNode
{
public:
enum ValueType {
INT,
STRING,
BOOL,
WIRE,
IDENTIFIER
};
@ -81,6 +86,8 @@ private:
std::optional<std::string> identifierValue;
public:
ValueNode() {};
ValueType getType() {
return type;
}
@ -113,43 +120,50 @@ public:
return this->type == type;
}
static Value ofBool(bool _value) {
Value value;
static ValueNode ofBool(bool _value) {
ValueNode value;
value.type = BOOL;
value.boolValue = std::optional<bool>(_value);
return value;
}
static Value ofInt(long long _value) {
Value value;
static ValueNode ofInt(long long _value) {
ValueNode value;
value.type = INT;
value.intValue = std::optional<long long>(_value);
return value;
}
static Value ofString(std::string _value) {
Value value;
static ValueNode ofString(std::string _value) {
ValueNode value;
value.type = STRING;
value.stringValue = std::optional<std::string>(_value);
return value;
}
static Value ofIdentifier(std::string _value) {
Value value;
static ValueNode ofIdentifier(std::string _value) {
ValueNode value;
value.type = IDENTIFIER;
value.identifierValue = std::optional<std::string>(_value);
return value;
}
static ValueNode ofWire(std::string _value) {
ValueNode value;
value.type = WIRE;
value.identifierValue = std::optional<std::string>(_value);
return value;
}
};
struct Condition
struct ConditionNode
{
bool negated;
IdentifierNode functionName;
std::vector<Value> params;
std::vector<ValueNode> params;
};
class Action: AstNode {
class ActionNode: AstNode {
public:
enum ActionType {
ERROR,
@ -161,46 +175,47 @@ public:
};
struct IfStmt: AstNode
struct IfStatementnode: AstNode
{
Condition condition;
Action action;
ConditionNode condition;
ActionNode action;
};
struct Rule: AstNode
struct RuleNode: AstNode
{
std::vector<IfStmt> statements;
std::vector<IfStatementnode> statements;
};
struct EnumerationNode: AstNode
{
StringNode key;
Value value;
ValueNode value;
};
struct Popup: AstNode
struct PopupNode: AstNode
{
enum PopupType {
AUTOMATIC,
ON_DEMAND
};
PopupType type;
StringNode title;
StringNode text;
std::optional<PopupType> type;
std::optional<StringNode> title;
std::optional<StringNode> text;
bool enumerated;
std::vector<EnumerationNode> enumeration;
std::vector<Rule> rules;
std::vector<RuleNode> rules;
};
struct PropertyNode: public AstNode
{
IdentifierNode key;
Value value;
ValueNode value;
};
@ -239,11 +254,9 @@ struct PinNode: AstNode
IdentifierNode name;
PinType type;
StringNode tooltip;
PinConnectionNode connection;
DisplayNode display;
std::optional<StringNode> tooltip;
std::optional<PinConnectionNode> connection;
std::optional<DisplayNode> display;
};
@ -270,10 +283,10 @@ struct WireNode: public AstNode
struct AttributeNode: AstNode
{
Value::ValueType type;
ValueNode::ValueType type;
IdentifierNode name;
std::optional<Value> defaultValue;
std::optional<Popup> popup;
std::optional<ValueNode> defaultValue;
std::optional<PopupNode> popup;
};
struct ConnectionNode: AstNode
@ -295,14 +308,14 @@ struct ComponentNode: AstNode
};
IdentifierNode name;
StringNode tooltip;
StringNode source;
std::optional<StringNode> tooltip;
std::optional<StringNode> source;
ComponentType type;
std::vector<Rule> rules;
StringNode instanceName;
CountNode count;
DisplayNode display;
std::vector<PinNode> pin;
std::vector<RuleNode> rules;
std::optional<StringNode> instanceName;
std::optional<CountNode> count;
std::optional<DisplayNode> display;
std::vector<PinNode> pins;
std::vector<AttributeNode> attributes;
};
@ -316,21 +329,21 @@ struct BusNode: AstNode
BusType type;
IdentifierNode name;
StringNode tooltip;
CountNode count;
DisplayNode display;
std::optional<StringNode> tooltip;
std::optional<CountNode> count;
std::optional<DisplayNode> display;
std::vector<WireNode> wires;
};
struct LibraryNode: AstNode
{
StringNode name;
StringNode libraryInfo;
StringNode header;
StringNode componentDirectory;
std::optional<StringNode> name;
std::optional<StringNode> libraryInfo;
std::optional<StringNode> header;
std::optional<StringNode> componentDirectory;
std::vector<AddressSpace> addressSpaces;
std::vector<AddressSpaceNode> addressSpaces;
std::vector<ComponentNode> components;
std::vector<BusNode> buses;
@ -339,6 +352,54 @@ struct LibraryNode: AstNode
std::vector<PropertyNode> messages;
};
// SCHEMA models
struct WireInstanceNode: AstNode
{
IdentifierNode name;
std::optional<CountNode> position;
std::optional<DisplayNode> display;
};
struct InstanceAttributeNode: AstNode
{
IdentifierNode name;
ValueNode value;
};
struct InstanceNode: AstNode
{
IdentifierNode name;
IdentifierNode component;
std::optional<CountNode> position;
std::vector<InstanceAttributeNode> attributes;
std::optional<NumberNode> size;
};
struct ConnectionInstanceNode: AstNode
{
IdentifierNode instance;
IdentifierNode pin;
IdentifierNode bus;
std::optional<IdentifierNode> wire;
std::vector<InstanceAttributeNode> attributes;
};
struct SchemaNode: AstNode
{
std::optional<StringNode> source;
std::vector<InstanceNode> instances;
std::vector<WireInstanceNode> wires;
std::vector<ConnectionInstanceNode> connections;
std::optional<LibraryNode> library;
};
#endif // ASTNODE_H

View File

@ -360,7 +360,7 @@ PResult<PropertyNode> ComdelParser::parseProperty(std::optional<TokenType> value
return unexpected();
}
}
Value value;
ValueNode value;
ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON);
@ -374,14 +374,14 @@ PResult<PropertyNode> ComdelParser::parseProperty(std::optional<TokenType> value
/****************************************************************************
*
* AddressSpace := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")"
* AddressSpaceNode := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")"
*
****************************************************************************/
PResult<AddressSpace> ComdelParser::parseAddress()
PResult<AddressSpaceNode> ComdelParser::parseAddress()
{
auto spanner = getSpanner();
AddressSpace addressSpace{};
AddressSpaceNode addressSpace{};
RETURN_IF_NOT_TOKEN(TokenType::KW_ADDRESS);
@ -439,7 +439,7 @@ PResult<ComponentNode> ComdelParser::parseComponent()
} else if(check(TokenType::KW_DISPLAY)) {
ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay());
} else if(check(TokenType::KW_PIN)) {
APPEND_OR_RETURN_IF_ERR(component.pin, parsePin());
APPEND_OR_RETURN_IF_ERR(component.pins, parsePin());
} else if(check(TokenType::KW_ATTRIBUTE)) {
APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute());
} else if(check(TokenType::KW_RULE)) {
@ -697,13 +697,13 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
}
if(check(TokenType::INT_TYPE)) {
attribute.type = Value::INT;
attribute.type = ValueNode::INT;
} else if(check(TokenType::STRING_TYPE)) {
attribute.type = Value::STRING;
attribute.type = ValueNode::STRING;
} else if(check(TokenType::BOOL_TYPE)) {
attribute.type = Value::BOOL;
attribute.type = ValueNode::BOOL;
} else if(check(TokenType::WIRE_TYPE)) {
attribute.type = Value::IDENTIFIER;
attribute.type = ValueNode::IDENTIFIER;
} else {
return unexpected();
}
@ -711,32 +711,32 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
RETURN_IF_NOT_TOKEN(TokenType::DEFAULT);
if(attribute.type == Value::BOOL) {
if(attribute.type == ValueNode::BOOL) {
if(check(TokenType::TRUE)) {
attribute.defaultValue = Value::ofBool(true);
attribute.defaultValue = ValueNode::ofBool(true);
} else if(check(TokenType::FALSE)) {
attribute.defaultValue = Value::ofBool(false);
attribute.defaultValue = ValueNode::ofBool(false);
} else {
return unexpected();
}
} else if(attribute.type == Value::INT) {
} else if(attribute.type == ValueNode::INT) {
if(check(TokenType::NUMBER)) {
auto number = parseNumber();
attribute.defaultValue = Value::ofInt(number->value);
attribute.defaultValue = ValueNode::ofInt(number->value);
} else {
return unexpected();
}
} else if(attribute.type == Value::STRING) {
} else if(attribute.type == ValueNode::STRING) {
if(check(TokenType::STRING)) {
auto string = parseString();
attribute.defaultValue = Value::ofString(string->value);
attribute.defaultValue = ValueNode::ofString(string->value);
} else {
return unexpected();
}
} else if(attribute.type == Value::IDENTIFIER) {
} else if(attribute.type == ValueNode::IDENTIFIER) {
if(check(TokenType::IDENTIFIER)) {
auto identifier = parseIdentifier();
attribute.defaultValue = Value::ofIdentifier(identifier->value);
attribute.defaultValue = ValueNode::ofIdentifier(identifier->value);
} else {
return unexpected();
}
@ -744,14 +744,14 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
if(check(TokenType::LBRACE)) {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
Popup popup;
PopupNode popup;
if(!check(TokenType::KW_POPUP)) {
return unexpected();
}
ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup());
attribute.popup = std::optional<Popup>(popup);
attribute.popup = std::optional<PopupNode>(popup);
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
}
@ -770,7 +770,7 @@ PResult<EnumerationNode> ComdelParser::parseEnumeration() {
ASSIGN_OR_RETURN_IF_ERR(key, parseString());
RETURN_IF_NOT_TOKEN(TokenType::EQUALS);
Value value;
ValueNode value;
ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
EnumerationNode node;
@ -782,26 +782,26 @@ PResult<EnumerationNode> ComdelParser::parseEnumeration() {
/****************************************************************************
*
* Popup := "@popup " + ("automatic" | "on_demand") { POPUP BODY }
* PopupNode := "@popup " + ("automatic" | "on_demand") { POPUP BODY }
*
****************************************************************************/
PResult<Popup> ComdelParser::parsePopup() {
PResult<PopupNode> ComdelParser::parsePopup() {
auto spanner = getSpanner();
Popup popup;
PopupNode popup;
RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP);
if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier();
if(type.value().value == "automatic") {
popup.type = Popup::AUTOMATIC;
popup.type = PopupNode::AUTOMATIC;
} else if(type.value().value == "on_demand") {
popup.type = Popup::ON_DEMAND;
popup.type = PopupNode::ON_DEMAND;
} else {
return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"});
}
} else {
popup.type = Popup::ON_DEMAND;
popup.type = PopupNode::ON_DEMAND;
}
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
@ -880,12 +880,12 @@ PResult<ConnectionNode> ComdelParser::parseConnection() {
/****************************************************************************
*
* Rule := "@rule {" + if-else statements + "}"
* RuleNode := "@rule {" + if-else statements + "}"
*
****************************************************************************/
PResult<Rule> ComdelParser::parseRule() {
PResult<RuleNode> ComdelParser::parseRule() {
auto spanner = getSpanner();
Rule rule;
RuleNode rule;
RETURN_IF_NOT_TOKEN(TokenType::KW_RULE);
@ -910,9 +910,9 @@ PResult<Rule> ComdelParser::parseRule() {
* IfStatement := "if(!function(params...)) { error(MESSAGE) | warning(MESSAGE) }
*
****************************************************************************/
PResult<IfStmt> ComdelParser::parseIfStatement() {
PResult<IfStatementnode> ComdelParser::parseIfStatement() {
auto spanner = getSpanner();
IfStmt ifStatement;
IfStatementnode ifStatement;
RETURN_IF_NOT_TOKEN(TokenType::IF);
@ -927,7 +927,7 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.functionName, parseIdentifier());
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList<Value>(std::optional<TokenType>(TokenType::LPAREN),
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList<ValueNode>(std::optional<TokenType>(TokenType::LPAREN),
TokenType::RPAREN,
TokenType::COMMA,
false,
@ -939,9 +939,9 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
if(check(TokenType::ERROR)) {
ifStatement.action.type = Action::ERROR;
ifStatement.action.type = ActionNode::ERROR;
} else if(check(TokenType::WARNING)) {
ifStatement.action.type = Action::WARNING;
ifStatement.action.type = ActionNode::WARNING;
} else {
return unexpected();
}
@ -957,27 +957,208 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
return spanner(ifStatement);
}
PResult<Value> ComdelParser::parseValue() {
PResult<ValueNode> ComdelParser::parseValue() {
auto spanner = getSpanner();
Value value;
ValueNode value;
if(check(TokenType::IDENTIFIER)) {
value = Value::ofIdentifier(parseIdentifier()->value);
value = ValueNode::ofIdentifier(parseIdentifier()->value);
} else if(check(TokenType::STRING)) {
value = Value::ofString(parseString()->value);
value = ValueNode::ofString(parseString()->value);
} else if(check(TokenType::NUMBER)) {
value = Value::ofInt(parseNumber()->value);
value = ValueNode::ofInt(parseNumber()->value);
} else if(check(TokenType::TRUE)) {
value = Value::ofBool(true);
value = ValueNode::ofBool(true);
} else if(check(TokenType::FALSE)) {
value = Value::ofBool(false);
value = ValueNode::ofBool(false);
} else {
return unexpected();
}
return spanner(value);
//return spanner(value);
return value;
}
std::optional<SchemaNode> ComdelParser::parseSchema() {
auto spanner = getSpanner();
SchemaNode schema{};
if(check(TokenType::KW_SOURCE)) {
bump();
if(check(TokenType::STRING)) {
auto source = parseString();
schema.source = *source;
} else {
errors.push_back(SourceError{current().span, "expected `@source`"});
return std::nullopt;
}
} else {
errors.push_back(SourceError{current().span, "expected `@source`"});
return std::nullopt;
}
if(!check(TokenType::KW_SCHEMA)) {
errors.push_back(SourceError{current().span, "expected `@schema`"});
return std::nullopt;
}
bump();
if(!check(TokenType::LBRACE)) {
errors.push_back(SourceError{current().span, "expected `{`"});
return std::nullopt;
}
bump();
while ( ! check(TokenType::RBRACE) ) {
PResult<poly<AstNode>> err;
if(check(TokenType::KW_INSTANCE)){
APPEND_OR_SET_ERR(schema.instances, parseInstance());
} else if(check(TokenType::KW_WIRE)) {
APPEND_OR_SET_ERR(schema.wires, parseWireInstance());
} else if(check(TokenType::KW_CONNECTION)) {
APPEND_OR_SET_ERR(schema.connections, parseConnectionInstance());
} else {
err = unexpected();
}
if(!err.has_value()) {
errors.push_back(err.error());
break;
}
}
if(!check(TokenType::RBRACE)) {
errors.push_back(SourceError{current().span, "expected `}`"});
return std::nullopt;
} else {
bump();
}
if(!check(TokenType::END_OF_FILE)) {
errors.push_back(SourceError{current().span, "expected `EOF`"});
}
if (errors.size())
return std::nullopt;
return spanner(schema);
}
PResult<WireInstanceNode> ComdelParser::parseWireInstance() {
auto spanner = getSpanner();
WireInstanceNode wireInstance;
RETURN_IF_NOT_TOKEN(TokenType::KW_WIRE);
ASSIGN_OR_RETURN_IF_ERR(wireInstance.name, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) {
if(check(TokenType::KW_POSITION)) {
ASSIGN_OR_RETURN_IF_ERR(wireInstance.position, parsePosition());
} else if(check(TokenType::KW_DISPLAY)) {
ASSIGN_OR_RETURN_IF_ERR(wireInstance.display, parseDisplay());
} else {
return unexpected();
}
}
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
return spanner(wireInstance);
}
/****************************************************************************
*
* CountNode := "@position (" + NumberNode + "," + NumberNode + ")"
*
****************************************************************************/
PResult<CountNode> ComdelParser::parsePosition()
{
auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_POSITION);
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
auto first = parseNumber();
if(!first.has_value()) {
return PError(first.error());
}
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
auto second = parseNumber();
if(!second.has_value()) {
return PError(second.error());
}
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
return spanner(CountNode{first.value(), second.value()});
}
PResult<InstanceNode> ComdelParser::parseInstance() {
auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_INSTANCE);
InstanceNode instance;
ASSIGN_OR_RETURN_IF_ERR(instance.name, parseIdentifier());
ASSIGN_OR_RETURN_IF_ERR(instance.component, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) {
if(check(TokenType::KW_POSITION)) {
ASSIGN_OR_RETURN_IF_ERR(instance.position, parsePosition());
} else if(check(TokenType::KW_ATTRIBUTE)) {
APPEND_OR_RETURN_IF_ERR(instance.attributes, parseInstanceAttribute());
} else if(check(TokenType::KW_SIZE)) {
bump();
auto number = parseNumber();
RETURN_IF_ERR(number);
instance.size = *number;
} else {
return unexpected();
}
}
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
return spanner(instance);
}
PResult<InstanceAttributeNode> ComdelParser::parseInstanceAttribute() {
auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE);
InstanceAttributeNode attribute;
ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier());
ASSIGN_OR_RETURN_IF_ERR(attribute.value, parseValue());
return spanner(attribute);
}
PResult<ConnectionInstanceNode> ComdelParser::parseConnectionInstance() {
auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
ConnectionInstanceNode connection;
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
ASSIGN_OR_RETURN_IF_ERR(connection.instance, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::DOT);
ASSIGN_OR_RETURN_IF_ERR(connection.pin, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) {
if(check(TokenType::KW_WIRE)) {
bump();
ASSIGN_OR_RETURN_IF_ERR(connection.wire, parseIdentifier());
} else if(check(TokenType::KW_ATTRIBUTE)) {
APPEND_OR_RETURN_IF_ERR(connection.attributes, parseInstanceAttribute());
} else {
return unexpected();
}
}
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
return spanner(connection);
}

View File

@ -27,7 +27,7 @@ public:
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);
}
};
@ -71,22 +71,29 @@ private:
PResult<EnumerationNode> parseEnumeration();
PResult<ComponentNode> parseComponent();
PResult<AddressSpace> parseAddress();
PResult<AddressSpaceNode> parseAddress();
PResult<PinNode> parsePin();
PResult<DisplayNode> parseDisplay();
PResult<PinConnectionNode> parsePinConnection();
PResult<AttributeNode> parseAttribute();
PResult<Popup> parsePopup();
PResult<Rule> parseRule();
PResult<PopupNode> parsePopup();
PResult<RuleNode> parseRule();
PResult<BusNode> parseBus();
PResult<WireNode> parseWire();
PResult<ConnectionNode> parseConnection();
PResult<DisplayItemNode> parseDisplayItem();
PResult<IfStmt> parseIfStatement();
PResult<Value> parseValue();
PResult<IfStatementnode> parseIfStatement();
PResult<ValueNode> parseValue();
PResult<WireInstanceNode> parseWireInstance();
PResult<CountNode> parsePosition();
PResult<InstanceNode> parseInstance();
PResult<InstanceAttributeNode> parseInstanceAttribute();
PResult<ConnectionInstanceNode> parseConnectionInstance();
public:
ComdelParser(std::vector<Token> tokens);
std::optional<SchemaNode> parseSchema();
std::optional<LibraryNode> parse();
const std::vector<SourceError>& getErrors();
};

View File

@ -40,3 +40,44 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
return *unit;
}
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
const char* name,
std::ostream& stream)
{
std::ifstream in(name, std::ios::in | std::ios::binary);
if( ! in ) {
stream << "ERROR: cannot open file '" << name
<< "' (file does not exist or is unreadable)" << std::endl;
return std::nullopt;
}
std::string source((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
ComdelLexer lexer(name, source, parseContext);
LexerResult lexerResult = lexer.tokenize();
if (lexerResult.errors.size()) {
for (auto& error : lexerResult.errors) {
parseContext->formatError(error, stream, "ERROR: ");
}
return std::nullopt; // if lexer has found errors => don't parse
}
ComdelParser parser(lexerResult.tokens);
auto unit = parser.parseSchema();
if (!unit) {
for (auto& error : parser.getErrors()) {
parseContext->formatError(error, stream, "ERROR: ");
}
return std::nullopt;
}
if(unit->source) {
unit->library = loadLibraryFromFile(parseContext, unit->source->asString().c_str(), stream);
}
return *unit;
}

View File

@ -8,4 +8,8 @@ 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

@ -128,7 +128,7 @@ TokenTables::TokenTables() {
add( TokenType::PIN_OUT, "out", TOKENIZABLE),
add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE),
// Action types
// ActionNode types
add( TokenType::ERROR, "error", TOKENIZABLE),
add( TokenType::WARNING, "warning", TOKENIZABLE),

View File

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

View File

@ -1,22 +0,0 @@
#ifndef DOMAIN_SCHEMA_CONNECTIONINSTANCE_H
#define DOMAIN_SCHEMA_CONNECTIONINSTANCE_H
#include "instance.h"
#include "wireinstance.h"
#include <vector>
class ConnectionInstance: AstNode
{
Instance *instance;
std::string pin;
Instance *bus;
WireInstance *wireInstance;
std::vector<InstanceAttribute> attributes;
public:
ConnectionInstance();
};
#endif // DOMAIN_SCHEMA_CONNECTIONINSTANCE_H

View File

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

View File

@ -1,23 +0,0 @@
#ifndef DOMAIN_SCHEMA_INSTANCE_H
#define DOMAIN_SCHEMA_INSTANCE_H
#include "instanceattribute.h"
#include <string>
#include <vector>
class Instance: AstNode
{
std::string name;
std::string component;
std::pair<int, int> position;
std::vector<InstanceAttribute> attributes;
int size;
public:
Instance();
};
#endif // DOMAIN_SCHEMA_INSTANCE_H

View File

@ -1,5 +0,0 @@
#include "instanceattribute.h"
InstanceAttribute::InstanceAttribute()
{
}

View File

@ -1,14 +0,0 @@
#ifndef DOMAIN_SCHEMA_ATTRIBUTE_H
#define DOMAIN_SCHEMA_ATTRIBUTE_H
#include <comdel/parser/astnode.h>
class InstanceAttribute: AstNode
{
std::string name;
Value value;
public:
InstanceAttribute();
};
#endif // DOMAIN_SCHEMA_ATTRIBUTE_H

View File

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

View File

@ -1,19 +0,0 @@
#ifndef DOMAIN_SCHEMA_SCHEMA_H
#define DOMAIN_SCHEMA_SCHEMA_H
#include "connectioninstance.h"
#include "instance.h"
#include "wireinstance.h"
#include <vector>
class Schema: AstNode
{
std::vector<Instance> instances;
std::vector<WireInstance> wires;
std::vector<ConnectionInstance> connections;
public:
Schema();
};
#endif // DOMAIN_SCHEMA_SCHEMA_H

View File

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

View File

@ -1,17 +0,0 @@
#ifndef DOMAIN_SCHEMA_WIREINSTANCE_H
#define DOMAIN_SCHEMA_WIREINSTANCE_H
#include <string>
#include <comdel/parser/astnode.h>
class WireInstance: AstNode
{
std::string name;
std::pair<int, int> position;
DisplayNode display;
public:
WireInstance();
};
#endif // DOMAIN_SCHEMA_WIREINSTANCE_H

View File

@ -7,6 +7,8 @@
#include <comdel/parser/parsecontext.h>
#include <comdel/parser/parserutil.h>
#include <comdel/domain/comdelgenerator.h>
int main(int argc, char *argv[])
{
/*
@ -17,5 +19,17 @@ int main(int argc, char *argv[])
*/
ParseContext parseContext;
loadLibraryFromFile(&parseContext, "/home/bbr/Documents/personal/projects/modeler/frisc_library.csl", std::cout);
auto schema = loadSchemaFromFile(&parseContext, "/home/bbr/Documents/personal/projects/modeler/schema.csl", std::cout);
if(schema) {
std::vector<domain::FunctionSignature> signatures;
domain::ComdelGenerator generator(signatures);
generator.loadLibrary(*schema->library, &parseContext, std::cout);
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
}
}
}