Added support for direct buses

This commit is contained in:
Borna Rajkovic 2022-04-09 19:44:02 +02:00
parent 7fcfb8c977
commit c65d12a2a1
7 changed files with 335 additions and 108 deletions

View File

@ -224,18 +224,22 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
{ {
push(ComdelContext("connection", false, true, false)); push(ComdelContext("connection", false, true, false));
std::string component = node.component.value;
std::string pin = node.pin.value;
std::string bus = node.bus.value; std::string bus = node.bus.value;
auto busInstance = getBus(bus);
if(!busInstance) {
errors.emplace_back(node.span, "bus does not exist");
}
auto componentInstance = getComponentPin(component, pin); if(busInstance->getType() == Bus::REGULAR) {
ConnectionComponent first{node.first.component.value, node.first.pin.value};
auto componentInstance = getComponentPin(first.component, first.pin);
if(!componentInstance) { if(!componentInstance) {
errors.emplace_back(node.span, "pin does not exist"); errors.emplace_back(node.span, "pin does not exist");
} }
auto busInstance = getBus(bus); if(node.second.has_value()) {
if(!busInstance) { errors.emplace_back(node.span, "regular bus doesn't allow direct connections");
errors.emplace_back(node.span, "bus does not exist");
} }
std::set<std::string> wireNames; std::set<std::string> wireNames;
@ -245,8 +249,8 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
} }
std::vector<Attribute> attributes; std::vector<Attribute> attributes;
for(uint i=0; i<node.attributes.size(); i++) { for(auto & attribute : node.attributes) {
auto attr = loadAttribute(node.attributes[i]); auto attr = loadAttribute(attribute);
if(!attr) { if(!attr) {
return nullopt; return nullopt;
} }
@ -259,27 +263,112 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
} }
std::vector<Value> wires; std::vector<Value> wires;
for(uint i=0; i<node.wires.size(); i++) { for(auto & firstWire : node.firstWires) {
if(node.wires[i].is(ValueNode::NIL)) { if(firstWire.is(ValueNode::NIL)) {
wires.push_back(Value::fromNull()); wires.push_back(Value::fromNull());
} else if(node.wires[i].is(ValueNode::INT)) { } else if(firstWire.is(ValueNode::INT)) {
wires.push_back(Value::fromInt(node.wires[i].asInt())); wires.push_back(Value::fromInt(firstWire.asInt()));
} else if(node.wires[i].is(ValueNode::IDENTIFIER)) { } else if(firstWire.is(ValueNode::IDENTIFIER)) {
if(attributeNames.count(node.wires[i].asIdentifier())) { if(attributeNames.count(firstWire.asIdentifier())) {
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::ATTRIBUTE_REFERENCE)); wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
} else if(wireNames.count(node.wires[i].asIdentifier())) { } else if(wireNames.count(firstWire.asIdentifier())) {
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::WIRE_REFERENCE)); wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE));
} else { } else {
errors.emplace_back(node.wires[i].span, "unknown identifier"); errors.emplace_back(firstWire.span, "unknown identifier");
} }
} else { } else {
errors.emplace_back(node.wires[i].span, "unknown value type"); errors.emplace_back(firstWire.span, "unknown value type");
} }
} }
pop(); pop();
return Connection(component, pin, bus, attributes, wires); 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");
} }
std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node) 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) { for(auto &conn: node.connections) {
auto component = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.instance.value)); auto firstComponent = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.first.instance.value));
if(component == NULL) { if(firstComponent == NULL) {
errors.push_back(SourceError{conn.instance.span, "unknown component"}); errors.push_back(SourceError{conn.first.instance.span, "unknown component"});
continue; continue;
} }
if(!component->component.hasPin(conn.pin.value)) { if(!firstComponent->component.hasPin(conn.first.pin.value)) {
errors.push_back(SourceError{conn.pin.span, "unknown pin"}); errors.push_back(SourceError{conn.first.pin.span, "unknown pin"});
continue; 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)); auto bus = dynamic_cast<BusInstance*>(schema.getInstance(conn.bus.value));
if(bus == NULL) { if(bus == NULL) {
errors.push_back(SourceError{conn.bus.span, "unknown bus"}); errors.push_back(SourceError{conn.bus.span, "unknown bus"});
continue; continue;
} }
if(!library.hasConnection(component->component.getName(), conn.pin.value, bus->bus.getName())) {
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"}); errors.push_back(SourceError{conn.span, "unknown connection"});
continue; continue;
} }
auto connection = *library.getConnection(component->component.getName(), conn.pin.value, bus->bus.getName()); } 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;
}
}
if(!conn.wire) { if(!conn.wire) {
errors.push_back(SourceError{conn.span, "missing @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; std::vector<InstanceAttribute*> attributes;
for(auto& attr: conn.attributes) { for(auto& attr: conn.attributes) {
if(connection.hasAttribute(attr.name.value)) { if(connection->hasAttribute(attr.name.value)) {
auto attribute = connection.getAttribute(attr.name.value); auto attribute = connection->getAttribute(attr.name.value);
auto value = toType(attr.value); auto value = toType(attr.value);
for(auto& en: attribute.getPopup()->getEnumeration()) { 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; return schema;

View File

@ -2,20 +2,19 @@
namespace domain { namespace domain {
Connection::Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires) Connection::Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
: component(component), pin(pin), bus(bus), attributes(attributes), wires(wires) 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) { ConnectionComponent Connection::getComponent() {
return this->component == component && this->pin == pin && this->bus == bus; 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() { std::string Connection::getBus() {
return bus; return bus;
} }
@ -24,7 +23,10 @@ std::vector<Attribute> Connection::getAttributes() {
return attributes; return attributes;
} }
std::vector<Value> Connection::getWires() { std::vector<Value> Connection::getWires() {
return wires; return firstWires;
}
std::optional<std::vector<Value>> Connection::getSecondWires() {
return secondWires;
} }
Attribute Connection::getAttribute(std::string name) { Attribute Connection::getAttribute(std::string name) {
@ -45,4 +47,20 @@ bool Connection::hasAttribute(std::string name) {
return false; 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 } // namespace domain

View File

@ -8,25 +8,49 @@
namespace domain { namespace domain {
class Connection struct ConnectionComponent
{ {
std::string component; std::string component;
std::string pin; 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::string bus;
std::vector<Attribute> attributes; std::vector<Attribute> attributes;
std::vector<Value> wires;
std::vector<Value> firstWires;
std::optional<std::vector<Value>> secondWires;
public: 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::string getBus();
std::vector<Attribute> getAttributes(); std::vector<Attribute> getAttributes();
std::vector<Value> getWires(); std::vector<Value> getWires();
std::optional<std::vector<Value>> getSecondWires();
Attribute getAttribute(std::string name); Attribute getAttribute(std::string name);
bool hasAttribute(std::string name); bool hasAttribute(std::string name);

View File

@ -81,16 +81,29 @@ Bus &Library::getBus(std::string bus) {
throw std::exception(); 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++) { 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 connections[i];
} }
} }
return nullopt; 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) { std::string Library::getMessage(std::string key) {

View File

@ -45,18 +45,19 @@ public:
bool hasComponent(std::string name); bool hasComponent(std::string name);
bool hasBus(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(); std::map<std::string, std::string> getMessages();
AddressSpace &getAddressSpace(std::string name); AddressSpace &getAddressSpace(std::string name);
Component &getComponent(std::string name); Component &getComponent(std::string name);
Bus &getBus(std::string bus); Bus &getBus(std::string bus);
std::optional<Connection> getConnection(std::string component, std::string pin, std::string bus);
std::string getMessage(std::string key); 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 } // namespace domain

View File

@ -170,7 +170,7 @@ struct ConditionNode
std::vector<ValueNode> params; std::vector<ValueNode> params;
}; };
class ActionNode: AstNode { class ActionNode: public AstNode {
public: public:
enum ActionType { enum ActionType {
ERROR, ERROR,
@ -182,27 +182,27 @@ public:
}; };
struct IfStatementNode: AstNode struct IfStatementNode: public AstNode
{ {
ConditionNode condition; ConditionNode condition;
ActionNode action; ActionNode action;
}; };
struct RuleNode: AstNode struct RuleNode: public AstNode
{ {
std::vector<IfStatementNode> statements; std::vector<IfStatementNode> statements;
}; };
struct EnumerationNode: AstNode struct EnumerationNode: public AstNode
{ {
StringNode key; StringNode key;
ValueNode value; ValueNode value;
}; };
struct PopupNode: AstNode struct PopupNode: public AstNode
{ {
enum PopupType { enum PopupType {
AUTOMATIC, AUTOMATIC,
@ -226,20 +226,20 @@ struct PropertyNode: public AstNode
}; };
struct DisplayItemNode: AstNode struct DisplayItemNode: public AstNode
{ {
IdentifierNode type; IdentifierNode type;
std::vector<PropertyNode> values; std::vector<PropertyNode> values;
}; };
struct DisplayNode: AstNode struct DisplayNode: public AstNode
{ {
std::vector<DisplayItemNode> items; std::vector<DisplayItemNode> items;
}; };
struct PinConnectionNode: AstNode struct PinConnectionNode: public AstNode
{ {
enum ConnectionType { enum ConnectionType {
CHECK_ONLY, CHECK_ONLY,
@ -251,7 +251,7 @@ struct PinConnectionNode: AstNode
}; };
struct PinNode: AstNode struct PinNode: public AstNode
{ {
enum PinType { enum PinType {
IN_OUT, IN_OUT,
@ -287,7 +287,7 @@ struct WireNode: public AstNode
}; };
struct AttributeNode: AstNode struct AttributeNode: public AstNode
{ {
ValueNode::ValueType type; ValueNode::ValueType type;
IdentifierNode name; IdentifierNode name;
@ -295,17 +295,25 @@ struct AttributeNode: AstNode
std::optional<PopupNode> popup; std::optional<PopupNode> popup;
}; };
struct ConnectionNode: AstNode struct ConnectionComponentNode: public AstNode
{ {
IdentifierNode component; IdentifierNode component;
IdentifierNode pin; 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 { enum ComponentType {
OTHER, OTHER,
@ -326,7 +334,7 @@ struct ComponentNode: AstNode
}; };
struct BusNode: AstNode struct BusNode: public AstNode
{ {
enum BusType { enum BusType {
AUTOMATIC, AUTOMATIC,
@ -342,7 +350,7 @@ struct BusNode: AstNode
std::vector<WireNode> wires; std::vector<WireNode> wires;
}; };
struct LibraryNode: AstNode struct LibraryNode: public AstNode
{ {
std::optional<StringNode> name; std::optional<StringNode> name;
std::optional<StringNode> libraryInfo; std::optional<StringNode> libraryInfo;
@ -361,20 +369,20 @@ struct LibraryNode: AstNode
// SCHEMA models // SCHEMA models
struct WireInstanceNode: AstNode struct WireInstanceNode: public AstNode
{ {
IdentifierNode name; IdentifierNode name;
std::optional<CountNode> position; std::optional<CountNode> position;
std::optional<DisplayNode> display; std::optional<DisplayNode> display;
}; };
struct InstanceAttributeNode: AstNode struct InstanceAttributeNode: public AstNode
{ {
IdentifierNode name; IdentifierNode name;
ValueNode value; ValueNode value;
}; };
struct InstanceNode: AstNode struct InstanceNode: public AstNode
{ {
IdentifierNode name; IdentifierNode name;
IdentifierNode component; IdentifierNode component;
@ -385,11 +393,16 @@ struct InstanceNode: AstNode
std::optional<NumberNode> size; std::optional<NumberNode> size;
}; };
struct ConnectionComponentInstance {
struct ConnectionInstanceNode: AstNode
{
IdentifierNode instance; IdentifierNode instance;
IdentifierNode pin; IdentifierNode pin;
};
struct ConnectionInstanceNode: public AstNode
{
ConnectionComponentInstance first;
std::optional<ConnectionComponentInstance> second;
IdentifierNode bus; IdentifierNode bus;
std::optional<IdentifierNode> wire; std::optional<IdentifierNode> wire;
@ -397,7 +410,7 @@ struct ConnectionInstanceNode: AstNode
}; };
struct SchemaNode: AstNode struct SchemaNode: public AstNode
{ {
std::optional<StringNode> source; std::optional<StringNode> source;

View File

@ -865,24 +865,44 @@ PResult<ConnectionNode> ComdelParser::parseConnection() {
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); 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); 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); RETURN_IF_NOT_TOKEN(TokenType::COMMA);
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier()); 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::RPAREN);
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
int wireCount = 0;
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
if (check(TokenType::KW_ATTRIBUTE)) { if (check(TokenType::KW_ATTRIBUTE)) {
APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute()); APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute());
} else if(check(TokenType::KW_WIRES)) { } else if(check(TokenType::KW_WIRES)) {
bump(); 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(); }); [this] { return parseConnectionWire(); });
RETURN_IF_ERR(wires); 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 { } else {
return unexpected(); return unexpected();
} }
@ -1158,11 +1178,21 @@ PResult<ConnectionInstanceNode> ComdelParser::parseConnectionInstance() {
ConnectionInstanceNode connection; ConnectionInstanceNode connection;
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); 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); 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); RETURN_IF_NOT_TOKEN(TokenType::COMMA);
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier()); 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::RPAREN);
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);