Added support for direct buses
This commit is contained in:
parent
7fcfb8c977
commit
c65d12a2a1
|
@ -224,62 +224,151 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
|
|||
{
|
||||
push(ComdelContext("connection", false, true, false));
|
||||
|
||||
std::string component = node.component.value;
|
||||
std::string pin = node.pin.value;
|
||||
std::string bus = node.bus.value;
|
||||
|
||||
auto componentInstance = getComponentPin(component, pin);
|
||||
if(!componentInstance) {
|
||||
errors.emplace_back(node.span, "pin does not exist");
|
||||
}
|
||||
|
||||
auto busInstance = getBus(bus);
|
||||
if(!busInstance) {
|
||||
errors.emplace_back(node.span, "bus does not exist");
|
||||
}
|
||||
|
||||
std::set<std::string> wireNames;
|
||||
for(auto &wire: busInstance->getWires()) {
|
||||
wireNames.insert(wire.getName());
|
||||
current().wires.push_back(wire.getName());
|
||||
}
|
||||
if(busInstance->getType() == Bus::REGULAR) {
|
||||
ConnectionComponent first{node.first.component.value, node.first.pin.value};
|
||||
|
||||
std::vector<Attribute> attributes;
|
||||
for(uint i=0; i<node.attributes.size(); i++) {
|
||||
auto attr = loadAttribute(node.attributes[i]);
|
||||
if(!attr) {
|
||||
return nullopt;
|
||||
auto componentInstance = getComponentPin(first.component, first.pin);
|
||||
if(!componentInstance) {
|
||||
errors.emplace_back(node.span, "pin does not exist");
|
||||
}
|
||||
attributes.push_back(*attr);
|
||||
}
|
||||
|
||||
std::set<std::string> attributeNames;
|
||||
for(auto attribute: attributes) {
|
||||
attributeNames.insert(attribute.getName());
|
||||
}
|
||||
if(node.second.has_value()) {
|
||||
errors.emplace_back(node.span, "regular bus doesn't allow direct connections");
|
||||
}
|
||||
|
||||
std::vector<Value> wires;
|
||||
for(uint i=0; i<node.wires.size(); i++) {
|
||||
if(node.wires[i].is(ValueNode::NIL)) {
|
||||
wires.push_back(Value::fromNull());
|
||||
} else if(node.wires[i].is(ValueNode::INT)) {
|
||||
wires.push_back(Value::fromInt(node.wires[i].asInt()));
|
||||
} else if(node.wires[i].is(ValueNode::IDENTIFIER)) {
|
||||
if(attributeNames.count(node.wires[i].asIdentifier())) {
|
||||
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::ATTRIBUTE_REFERENCE));
|
||||
} else if(wireNames.count(node.wires[i].asIdentifier())) {
|
||||
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::WIRE_REFERENCE));
|
||||
} else {
|
||||
errors.emplace_back(node.wires[i].span, "unknown identifier");
|
||||
std::set<std::string> wireNames;
|
||||
for(auto &wire: busInstance->getWires()) {
|
||||
wireNames.insert(wire.getName());
|
||||
current().wires.push_back(wire.getName());
|
||||
}
|
||||
|
||||
std::vector<Attribute> attributes;
|
||||
for(auto & attribute : node.attributes) {
|
||||
auto attr = loadAttribute(attribute);
|
||||
if(!attr) {
|
||||
return nullopt;
|
||||
}
|
||||
} else {
|
||||
errors.emplace_back(node.wires[i].span, "unknown value type");
|
||||
attributes.push_back(*attr);
|
||||
}
|
||||
|
||||
std::set<std::string> attributeNames;
|
||||
for(auto attribute: attributes) {
|
||||
attributeNames.insert(attribute.getName());
|
||||
}
|
||||
|
||||
std::vector<Value> wires;
|
||||
for(auto & firstWire : node.firstWires) {
|
||||
if(firstWire.is(ValueNode::NIL)) {
|
||||
wires.push_back(Value::fromNull());
|
||||
} else if(firstWire.is(ValueNode::INT)) {
|
||||
wires.push_back(Value::fromInt(firstWire.asInt()));
|
||||
} else if(firstWire.is(ValueNode::IDENTIFIER)) {
|
||||
if(attributeNames.count(firstWire.asIdentifier())) {
|
||||
wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
|
||||
} else if(wireNames.count(firstWire.asIdentifier())) {
|
||||
wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE));
|
||||
} else {
|
||||
errors.emplace_back(firstWire.span, "unknown identifier");
|
||||
}
|
||||
} else {
|
||||
errors.emplace_back(firstWire.span, "unknown value type");
|
||||
}
|
||||
}
|
||||
|
||||
pop();
|
||||
|
||||
return Connection(first, nullopt, bus, attributes, wires, nullopt);
|
||||
} else if(busInstance->getType() == Bus::AUTOMATIC || busInstance->getType() == Bus::AUTOMATIC_SINGLE) {
|
||||
ConnectionComponent first{node.first.component.value, node.first.pin.value};
|
||||
|
||||
if(!node.second.has_value()) {
|
||||
errors.emplace_back(node.span, "missing second component");
|
||||
}
|
||||
|
||||
ConnectionComponent second{node.second->component.value, node.second->pin.value};
|
||||
|
||||
auto firstComponentInstance = getComponentPin(first.component, first.pin);
|
||||
if(!firstComponentInstance) {
|
||||
errors.emplace_back(node.span, "pin does not exist");
|
||||
}
|
||||
|
||||
auto secondComponentInstance = getComponentPin(second.component, second.pin);
|
||||
if(!secondComponentInstance) {
|
||||
errors.emplace_back(node.span, "pin does not exist");
|
||||
}
|
||||
|
||||
std::set<std::string> wireNames;
|
||||
for(auto &wire: busInstance->getWires()) {
|
||||
wireNames.insert(wire.getName());
|
||||
current().wires.push_back(wire.getName());
|
||||
}
|
||||
|
||||
std::vector<Attribute> attributes;
|
||||
for(auto & attribute : node.attributes) {
|
||||
auto attr = loadAttribute(attribute);
|
||||
if(!attr) {
|
||||
return nullopt;
|
||||
}
|
||||
attributes.push_back(*attr);
|
||||
}
|
||||
|
||||
std::set<std::string> attributeNames;
|
||||
for(auto attribute: attributes) {
|
||||
attributeNames.insert(attribute.getName());
|
||||
}
|
||||
|
||||
std::vector<Value> firstWires;
|
||||
for(auto & firstWire : node.firstWires) {
|
||||
if(firstWire.is(ValueNode::NIL)) {
|
||||
firstWires.push_back(Value::fromNull());
|
||||
} else if(firstWire.is(ValueNode::INT)) {
|
||||
firstWires.push_back(Value::fromInt(firstWire.asInt()));
|
||||
} else if(firstWire.is(ValueNode::IDENTIFIER)) {
|
||||
if(attributeNames.count(firstWire.asIdentifier())) {
|
||||
firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
|
||||
} else if(wireNames.count(firstWire.asIdentifier())) {
|
||||
firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE));
|
||||
} else {
|
||||
errors.emplace_back(firstWire.span, "unknown identifier");
|
||||
}
|
||||
} else {
|
||||
errors.emplace_back(firstWire.span, "unknown value type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<Value> secondWires;
|
||||
for(auto & secondWire : *node.secondWires) {
|
||||
if(secondWire.is(ValueNode::NIL)) {
|
||||
secondWires.push_back(Value::fromNull());
|
||||
} else if(secondWire.is(ValueNode::INT)) {
|
||||
secondWires.push_back(Value::fromInt(secondWire.asInt()));
|
||||
} else if(secondWire.is(ValueNode::IDENTIFIER)) {
|
||||
if(attributeNames.count(secondWire.asIdentifier())) {
|
||||
secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
|
||||
} else if(wireNames.count(secondWire.asIdentifier())) {
|
||||
secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::WIRE_REFERENCE));
|
||||
} else {
|
||||
errors.emplace_back(secondWire.span, "unknown identifier");
|
||||
}
|
||||
} else {
|
||||
errors.emplace_back(secondWire.span, "unknown value type");
|
||||
}
|
||||
}
|
||||
|
||||
pop();
|
||||
|
||||
return Connection(first, second, bus, attributes, firstWires, secondWires);
|
||||
}
|
||||
|
||||
pop();
|
||||
errors.emplace_back(node.span, "unsupported connection type");
|
||||
|
||||
return Connection(component, pin, bus, attributes, wires);
|
||||
}
|
||||
|
||||
std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
|
||||
|
@ -659,25 +748,60 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
|
|||
}
|
||||
|
||||
for(auto &conn: node.connections) {
|
||||
auto component = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.instance.value));
|
||||
if(component == NULL) {
|
||||
errors.push_back(SourceError{conn.instance.span, "unknown component"});
|
||||
auto firstComponent = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.first.instance.value));
|
||||
if(firstComponent == NULL) {
|
||||
errors.push_back(SourceError{conn.first.instance.span, "unknown component"});
|
||||
continue;
|
||||
}
|
||||
if(!component->component.hasPin(conn.pin.value)) {
|
||||
errors.push_back(SourceError{conn.pin.span, "unknown pin"});
|
||||
if(!firstComponent->component.hasPin(conn.first.pin.value)) {
|
||||
errors.push_back(SourceError{conn.first.pin.span, "unknown pin"});
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ComponentInstance *secondComponent = NULL;
|
||||
if(conn.second.has_value()) {
|
||||
secondComponent = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.second->instance.value));
|
||||
if(secondComponent == NULL) {
|
||||
errors.push_back(SourceError{conn.second->instance.span, "unknown component"});
|
||||
continue;
|
||||
}
|
||||
if(!secondComponent->component.hasPin(conn.second->pin.value)) {
|
||||
errors.push_back(SourceError{conn.second->pin.span, "unknown pin"});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto bus = dynamic_cast<BusInstance*>(schema.getInstance(conn.bus.value));
|
||||
if(bus == NULL) {
|
||||
errors.push_back(SourceError{conn.bus.span, "unknown bus"});
|
||||
continue;
|
||||
}
|
||||
if(!library.hasConnection(component->component.getName(), conn.pin.value, bus->bus.getName())) {
|
||||
errors.push_back(SourceError{conn.span, "unknown connection"});
|
||||
continue;
|
||||
|
||||
std::optional<Connection> connection = std::nullopt;
|
||||
if(secondComponent != NULL) {
|
||||
ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value};
|
||||
ConnectionComponent secondConn{secondComponent->component.getName(), conn.second->pin.value};
|
||||
|
||||
if(library.hasConnection(firstConn,
|
||||
bus->bus.getName(),
|
||||
secondConn)) {
|
||||
connection = *library.getConnection(firstConn, bus->bus.getName(), secondConn);
|
||||
} else {
|
||||
errors.push_back(SourceError{conn.span, "unknown connection"});
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
ConnectionComponent firstConn{firstComponent->name, conn.first.pin.value};
|
||||
|
||||
if(library.hasConnection(firstConn,
|
||||
bus->bus.getName())) {
|
||||
connection = *library.getConnection(firstConn, bus->bus.getName());
|
||||
} else {
|
||||
errors.push_back(SourceError{conn.span, "unknown connection"});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto connection = *library.getConnection(component->component.getName(), conn.pin.value, bus->bus.getName());
|
||||
|
||||
if(!conn.wire) {
|
||||
errors.push_back(SourceError{conn.span, "missing @wire"});
|
||||
|
@ -692,8 +816,8 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
|
|||
|
||||
std::vector<InstanceAttribute*> attributes;
|
||||
for(auto& attr: conn.attributes) {
|
||||
if(connection.hasAttribute(attr.name.value)) {
|
||||
auto attribute = connection.getAttribute(attr.name.value);
|
||||
if(connection->hasAttribute(attr.name.value)) {
|
||||
auto attribute = connection->getAttribute(attr.name.value);
|
||||
auto value = toType(attr.value);
|
||||
|
||||
for(auto& en: attribute.getPopup()->getEnumeration()) {
|
||||
|
@ -711,7 +835,11 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
|
|||
}
|
||||
}
|
||||
|
||||
schema.connections.push_back(new BusConnectionInstance(component, attributes, bus, wire, connection));
|
||||
if(secondComponent == NULL) {
|
||||
schema.connections.push_back(new BusConnectionInstance(firstComponent, attributes, bus, wire, *connection));
|
||||
} else {
|
||||
schema.connections.push_back(new DirectConnectionInstance(firstComponent, secondComponent, attributes, bus, wire, *connection));
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
|
|
|
@ -2,20 +2,19 @@
|
|||
|
||||
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)
|
||||
Connection::Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
|
||||
std::string bus, std::vector<Attribute> attributes,
|
||||
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires)
|
||||
: first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires), secondWires(secondWires)
|
||||
{}
|
||||
|
||||
bool Connection::isConnecting(std::string component, std::string pin, std::string bus) {
|
||||
return this->component == component && this->pin == pin && this->bus == bus;
|
||||
ConnectionComponent Connection::getComponent() {
|
||||
return first;
|
||||
}
|
||||
std::optional<ConnectionComponent> Connection::getSecondComponent() {
|
||||
return second;
|
||||
}
|
||||
|
||||
std::string Connection::getComponent() {
|
||||
return component;
|
||||
}
|
||||
std::string Connection::getPin() {
|
||||
return pin;
|
||||
}
|
||||
std::string Connection::getBus() {
|
||||
return bus;
|
||||
}
|
||||
|
@ -24,7 +23,10 @@ std::vector<Attribute> Connection::getAttributes() {
|
|||
return attributes;
|
||||
}
|
||||
std::vector<Value> Connection::getWires() {
|
||||
return wires;
|
||||
return firstWires;
|
||||
}
|
||||
std::optional<std::vector<Value>> Connection::getSecondWires() {
|
||||
return secondWires;
|
||||
}
|
||||
|
||||
Attribute Connection::getAttribute(std::string name) {
|
||||
|
@ -45,4 +47,20 @@ bool Connection::hasAttribute(std::string name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Connection::isConnecting(ConnectionComponent component) {
|
||||
return first == component || (second.has_value() && *second == component);
|
||||
}
|
||||
|
||||
bool Connection::isConnecting(ConnectionComponent component, std::string bus) {
|
||||
return this->bus == bus && (first == component || (second.has_value() && *second == component));
|
||||
}
|
||||
|
||||
bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
|
||||
if(!second.has_value()) {
|
||||
return false;
|
||||
}
|
||||
return (this->first == component && this->bus == bus && this->second == secondComponent) ||
|
||||
(this->first == secondComponent && this->bus == bus && this->second == component);
|
||||
}
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -8,25 +8,49 @@
|
|||
|
||||
namespace domain {
|
||||
|
||||
class Connection
|
||||
struct ConnectionComponent
|
||||
{
|
||||
std::string component;
|
||||
std::string pin;
|
||||
|
||||
bool operator==(const ConnectionComponent& rhs) const
|
||||
{
|
||||
return (component == rhs.component) && (pin == rhs.pin);
|
||||
}
|
||||
bool operator!=(const ConnectionComponent& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
class Connection
|
||||
{
|
||||
ConnectionComponent first;
|
||||
std::optional<ConnectionComponent> second;
|
||||
std::string bus;
|
||||
|
||||
std::vector<Attribute> attributes;
|
||||
std::vector<Value> wires;
|
||||
|
||||
std::vector<Value> firstWires;
|
||||
std::optional<std::vector<Value>> secondWires;
|
||||
public:
|
||||
Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires);
|
||||
Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
|
||||
std::string bus, std::vector<Attribute> attributes,
|
||||
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires);
|
||||
|
||||
bool isConnecting(std::string component, std::string pin, std::string bus);
|
||||
bool isConnecting(ConnectionComponent first);
|
||||
bool isConnecting(ConnectionComponent first, std::string bus);
|
||||
bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second);
|
||||
|
||||
|
||||
ConnectionComponent getComponent();
|
||||
std::optional<ConnectionComponent> getSecondComponent();
|
||||
|
||||
std::string getComponent();
|
||||
std::string getPin();
|
||||
std::string getBus();
|
||||
|
||||
std::vector<Attribute> getAttributes();
|
||||
|
||||
std::vector<Value> getWires();
|
||||
std::optional<std::vector<Value>> getSecondWires();
|
||||
|
||||
Attribute getAttribute(std::string name);
|
||||
bool hasAttribute(std::string name);
|
||||
|
|
|
@ -81,16 +81,29 @@ Bus &Library::getBus(std::string bus) {
|
|||
throw std::exception();
|
||||
|
||||
}
|
||||
std::optional<Connection> Library::getConnection(std::string component, std::string pin, std::string bus) {
|
||||
|
||||
bool Library::hasConnection(ConnectionComponent component, std::string bus) {
|
||||
return getConnection(component, bus).has_value();
|
||||
}
|
||||
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) {
|
||||
for(uint i=0; i<connections.size(); i++) {
|
||||
if(connections[i].isConnecting(component, pin, bus)) {
|
||||
if(connections[i].isConnecting(component, bus)) {
|
||||
return connections[i];
|
||||
}
|
||||
}
|
||||
return nullopt;
|
||||
}
|
||||
bool Library::hasConnection(std::string component, std::string pin, std::string bus) {
|
||||
return getConnection(component, pin, bus).has_value();
|
||||
|
||||
bool Library::hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
|
||||
return getConnection(component, bus, secondComponent).has_value();
|
||||
}
|
||||
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
|
||||
for(uint i=0; i<connections.size(); i++) {
|
||||
if(connections[i].isConnecting(component, bus, secondComponent)) {
|
||||
return connections[i];
|
||||
}
|
||||
}
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
std::string Library::getMessage(std::string key) {
|
||||
|
|
|
@ -45,18 +45,19 @@ public:
|
|||
|
||||
bool hasComponent(std::string name);
|
||||
bool hasBus(std::string name);
|
||||
bool hasConnection(std::string component, std::string pin, std::string bus);
|
||||
|
||||
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);
|
||||
|
||||
bool hasConnection(ConnectionComponent component, std::string bus);
|
||||
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus);
|
||||
|
||||
|
||||
bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
|
||||
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
|
||||
};
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -170,7 +170,7 @@ struct ConditionNode
|
|||
std::vector<ValueNode> params;
|
||||
};
|
||||
|
||||
class ActionNode: AstNode {
|
||||
class ActionNode: public AstNode {
|
||||
public:
|
||||
enum ActionType {
|
||||
ERROR,
|
||||
|
@ -182,27 +182,27 @@ public:
|
|||
};
|
||||
|
||||
|
||||
struct IfStatementNode: AstNode
|
||||
struct IfStatementNode: public AstNode
|
||||
{
|
||||
ConditionNode condition;
|
||||
ActionNode action;
|
||||
};
|
||||
|
||||
|
||||
struct RuleNode: AstNode
|
||||
struct RuleNode: public AstNode
|
||||
{
|
||||
std::vector<IfStatementNode> statements;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct EnumerationNode: AstNode
|
||||
struct EnumerationNode: public AstNode
|
||||
{
|
||||
StringNode key;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct PopupNode: AstNode
|
||||
struct PopupNode: public AstNode
|
||||
{
|
||||
enum PopupType {
|
||||
AUTOMATIC,
|
||||
|
@ -226,20 +226,20 @@ struct PropertyNode: public AstNode
|
|||
};
|
||||
|
||||
|
||||
struct DisplayItemNode: AstNode
|
||||
struct DisplayItemNode: public AstNode
|
||||
{
|
||||
IdentifierNode type;
|
||||
std::vector<PropertyNode> values;
|
||||
};
|
||||
|
||||
|
||||
struct DisplayNode: AstNode
|
||||
struct DisplayNode: public AstNode
|
||||
{
|
||||
std::vector<DisplayItemNode> items;
|
||||
};
|
||||
|
||||
|
||||
struct PinConnectionNode: AstNode
|
||||
struct PinConnectionNode: public AstNode
|
||||
{
|
||||
enum ConnectionType {
|
||||
CHECK_ONLY,
|
||||
|
@ -251,7 +251,7 @@ struct PinConnectionNode: AstNode
|
|||
};
|
||||
|
||||
|
||||
struct PinNode: AstNode
|
||||
struct PinNode: public AstNode
|
||||
{
|
||||
enum PinType {
|
||||
IN_OUT,
|
||||
|
@ -287,7 +287,7 @@ struct WireNode: public AstNode
|
|||
};
|
||||
|
||||
|
||||
struct AttributeNode: AstNode
|
||||
struct AttributeNode: public AstNode
|
||||
{
|
||||
ValueNode::ValueType type;
|
||||
IdentifierNode name;
|
||||
|
@ -295,17 +295,25 @@ struct AttributeNode: AstNode
|
|||
std::optional<PopupNode> popup;
|
||||
};
|
||||
|
||||
struct ConnectionNode: AstNode
|
||||
struct ConnectionComponentNode: public AstNode
|
||||
{
|
||||
IdentifierNode component;
|
||||
IdentifierNode pin;
|
||||
IdentifierNode bus;
|
||||
std::vector<AttributeNode> attributes;
|
||||
std::vector<ValueNode> wires;
|
||||
};
|
||||
|
||||
struct ConnectionNode: public AstNode
|
||||
{
|
||||
ConnectionComponentNode first;
|
||||
std::optional<ConnectionComponentNode> second;
|
||||
|
||||
struct ComponentNode: AstNode
|
||||
IdentifierNode bus;
|
||||
std::vector<AttributeNode> attributes;
|
||||
|
||||
std::vector<ValueNode> firstWires;
|
||||
std::optional<std::vector<ValueNode>> secondWires;
|
||||
};
|
||||
|
||||
struct ComponentNode: public AstNode
|
||||
{
|
||||
enum ComponentType {
|
||||
OTHER,
|
||||
|
@ -326,7 +334,7 @@ struct ComponentNode: AstNode
|
|||
};
|
||||
|
||||
|
||||
struct BusNode: AstNode
|
||||
struct BusNode: public AstNode
|
||||
{
|
||||
enum BusType {
|
||||
AUTOMATIC,
|
||||
|
@ -342,7 +350,7 @@ struct BusNode: AstNode
|
|||
std::vector<WireNode> wires;
|
||||
};
|
||||
|
||||
struct LibraryNode: AstNode
|
||||
struct LibraryNode: public AstNode
|
||||
{
|
||||
std::optional<StringNode> name;
|
||||
std::optional<StringNode> libraryInfo;
|
||||
|
@ -361,20 +369,20 @@ struct LibraryNode: AstNode
|
|||
// SCHEMA models
|
||||
|
||||
|
||||
struct WireInstanceNode: AstNode
|
||||
struct WireInstanceNode: public AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
std::optional<CountNode> position;
|
||||
std::optional<DisplayNode> display;
|
||||
};
|
||||
|
||||
struct InstanceAttributeNode: AstNode
|
||||
struct InstanceAttributeNode: public AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct InstanceNode: AstNode
|
||||
struct InstanceNode: public AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
IdentifierNode component;
|
||||
|
@ -385,11 +393,16 @@ struct InstanceNode: AstNode
|
|||
std::optional<NumberNode> size;
|
||||
};
|
||||
|
||||
|
||||
struct ConnectionInstanceNode: AstNode
|
||||
{
|
||||
struct ConnectionComponentInstance {
|
||||
IdentifierNode instance;
|
||||
IdentifierNode pin;
|
||||
};
|
||||
|
||||
struct ConnectionInstanceNode: public AstNode
|
||||
{
|
||||
ConnectionComponentInstance first;
|
||||
std::optional<ConnectionComponentInstance> second;
|
||||
|
||||
IdentifierNode bus;
|
||||
std::optional<IdentifierNode> wire;
|
||||
|
||||
|
@ -397,7 +410,7 @@ struct ConnectionInstanceNode: AstNode
|
|||
};
|
||||
|
||||
|
||||
struct SchemaNode: AstNode
|
||||
struct SchemaNode: public AstNode
|
||||
{
|
||||
std::optional<StringNode> source;
|
||||
|
||||
|
|
|
@ -865,24 +865,44 @@ PResult<ConnectionNode> ComdelParser::parseConnection() {
|
|||
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.component, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.first.component, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DOT);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.pin, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.first.pin, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier());
|
||||
|
||||
if(check(TokenType::COMMA)) {
|
||||
auto conn = ConnectionComponentNode{};
|
||||
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
|
||||
ASSIGN_OR_RETURN_IF_ERR(conn.component, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DOT);
|
||||
ASSIGN_OR_RETURN_IF_ERR(conn.pin, parseIdentifier());
|
||||
connection.second = conn;
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
||||
int wireCount = 0;
|
||||
|
||||
while(!check(TokenType::RBRACE)) {
|
||||
if (check(TokenType::KW_ATTRIBUTE)) {
|
||||
APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute());
|
||||
} else if(check(TokenType::KW_WIRES)) {
|
||||
bump();
|
||||
auto wires = parseList<ValueNode>(std::optional<TokenType>(TokenType::LBRACE), TokenType::RBRACE, std::optional<TokenType>(TokenType::COMMA), false,
|
||||
auto wires = parseList<ValueNode>(TokenType::LBRACE, TokenType::RBRACE, TokenType::COMMA, false,
|
||||
[this] { return parseConnectionWire(); });
|
||||
RETURN_IF_ERR(wires);
|
||||
connection.wires = *wires;
|
||||
if(wireCount == 0) {
|
||||
connection.firstWires = *wires;
|
||||
} else if(wireCount == 1 && connection.second.has_value()) {
|
||||
connection.secondWires = *wires;
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
wireCount++;
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
|
@ -1158,11 +1178,21 @@ PResult<ConnectionInstanceNode> ComdelParser::parseConnectionInstance() {
|
|||
ConnectionInstanceNode connection;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.instance, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.first.instance, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DOT);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.pin, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.first.pin, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier());
|
||||
|
||||
if(check(TokenType::COMMA)) {
|
||||
bump();
|
||||
ConnectionComponentInstance second;
|
||||
ASSIGN_OR_RETURN_IF_ERR(second.instance, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DOT);
|
||||
ASSIGN_OR_RETURN_IF_ERR(second.pin, parseIdentifier());
|
||||
connection.second = second;
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
|
Loading…
Reference in New Issue