added domain model
This commit is contained in:
parent
18d84727ab
commit
f4450494d8
|
@ -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 += \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
#include "display.h"
|
||||
|
||||
namespace domain {
|
||||
|
||||
Display::Display()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace domain
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef DOMAIN_DISPLAY_H
|
||||
#define DOMAIN_DISPLAY_H
|
||||
|
||||
|
||||
namespace domain {
|
||||
|
||||
class Display
|
||||
{
|
||||
public:
|
||||
Display();
|
||||
};
|
||||
|
||||
} // namespace domain
|
||||
|
||||
#endif // DOMAIN_DISPLAY_H
|
|
@ -0,0 +1,5 @@
|
|||
#include "functionsignature.h"
|
||||
|
||||
namespace domain {
|
||||
|
||||
} // namespace domain
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#include "connectioninstance.h"
|
||||
|
||||
ConnectionInstance::ConnectionInstance()
|
||||
{
|
||||
|
||||
}
|
|
@ -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
|
|
@ -1,6 +0,0 @@
|
|||
#include "instance.h"
|
||||
|
||||
Instance::Instance()
|
||||
{
|
||||
|
||||
}
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
#include "instanceattribute.h"
|
||||
|
||||
InstanceAttribute::InstanceAttribute()
|
||||
{
|
||||
}
|
|
@ -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
|
|
@ -1,6 +0,0 @@
|
|||
#include "schema.h"
|
||||
|
||||
Schema::Schema()
|
||||
{
|
||||
|
||||
}
|
|
@ -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
|
|
@ -1,6 +0,0 @@
|
|||
#include "wireinstance.h"
|
||||
|
||||
WireInstance::WireInstance()
|
||||
{
|
||||
|
||||
}
|
|
@ -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
|
16
main.cpp
16
main.cpp
|
@ -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: ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue