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> | ||||
|  | ||||
							
								
								
									
										19
									
								
								comdel/domain/addressspace.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								comdel/domain/addressspace.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| #include "addressspace.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| AddressSpace::AddressSpace(std::string name, long long start, long long end): | ||||
|     name(name), start(start), end(end) | ||||
| {} | ||||
| 
 | ||||
| std::string AddressSpace::getName() { | ||||
|     return name; | ||||
| } | ||||
| long long AddressSpace::getStart() { | ||||
|     return start; | ||||
| } | ||||
| long long AddressSpace::getEnd() { | ||||
|     return end; | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										26
									
								
								comdel/domain/addressspace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								comdel/domain/addressspace.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| #ifndef DOMAIN_ADDRESSSPACE_H | ||||
| #define DOMAIN_ADDRESSSPACE_H | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class AddressSpace | ||||
| { | ||||
|     std::string name; | ||||
|     long long start; | ||||
|     long long end; | ||||
| 
 | ||||
| public: | ||||
|     AddressSpace(std::string name, long long start, long long end); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     long long getStart(); | ||||
|     long long getEnd(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_ADDRESSSPACE_H
 | ||||
							
								
								
									
										56
									
								
								comdel/domain/attribute.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								comdel/domain/attribute.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| #include "attribute.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Enumeration::Enumeration(std::string name, Value value) | ||||
|     : name(name), value(value) | ||||
| {} | ||||
| 
 | ||||
| std::string Enumeration::getName() { | ||||
|     return name; | ||||
| } | ||||
| Value Enumeration::getValue() { | ||||
|     return value; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Popup::Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration) | ||||
|     : title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), enumeration(enumeration) | ||||
| {} | ||||
| 
 | ||||
| std::string Popup::getTitle() { | ||||
|     return title; | ||||
| } | ||||
| std::string Popup::getText() { | ||||
|     return text; | ||||
| } | ||||
| Popup::PopupType Popup::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::vector<Rule> Popup::getRules() { | ||||
|     return rules; | ||||
| } | ||||
| 
 | ||||
| bool Popup::isEnumerated() { | ||||
|     return enumerated; | ||||
| } | ||||
| std::vector<Enumeration> &Popup::getEnumeration() { | ||||
|     return enumeration; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Attribute::Attribute(std::string name, Value defaultValue, std::optional<Popup> popup) | ||||
|     : name(name), defaultValue(defaultValue), popup(popup) | ||||
| {} | ||||
| 
 | ||||
| std::string Attribute::getName() { | ||||
|     return name; | ||||
| } | ||||
| Value Attribute::getDefault() { | ||||
|     return defaultValue; | ||||
| } | ||||
| std::optional<Popup> Attribute::getPopup() { | ||||
|     return popup; | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										65
									
								
								comdel/domain/attribute.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								comdel/domain/attribute.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| #ifndef DOMAIN_ATTRIBUTE_H | ||||
| #define DOMAIN_ATTRIBUTE_H | ||||
| 
 | ||||
| #include "rule.h" | ||||
| #include "value.h" | ||||
| 
 | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class Enumeration { | ||||
|     std::string name; | ||||
|     Value value; | ||||
| public: | ||||
|     Enumeration(std::string name, Value value); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     Value getValue(); | ||||
| }; | ||||
| 
 | ||||
| class Popup { | ||||
| public: | ||||
|     enum PopupType { | ||||
|         AUTOMATIC, | ||||
|         ON_DEMAND | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     std::string title; | ||||
|     std::string text; | ||||
|     PopupType type; | ||||
| 
 | ||||
|     bool enumerated; | ||||
|     std::vector<Enumeration> enumeration; | ||||
|     std::vector<Rule> rules; | ||||
| 
 | ||||
| public: | ||||
|     Popup(std::string title, std::string text, PopupType type, std::vector<Rule> rules, std::vector<Enumeration> enumeration); | ||||
| 
 | ||||
|     std::string getTitle(); | ||||
|     std::string getText(); | ||||
|     PopupType getType(); | ||||
|     std::vector<Rule> getRules(); | ||||
| 
 | ||||
|     bool isEnumerated(); | ||||
|     std::vector<Enumeration> &getEnumeration(); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class Attribute | ||||
| { | ||||
|     std::string name; | ||||
|     Value defaultValue; | ||||
|     std::optional<Popup> popup; | ||||
| public: | ||||
|     Attribute(std::string name, Value defaultValue, std::optional<Popup> popup = std::nullopt); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     Value getDefault(); | ||||
|     std::optional<Popup> getPopup(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_ATTRIBUTE_H
 | ||||
							
								
								
									
										26
									
								
								comdel/domain/bus.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								comdel/domain/bus.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| #include "bus.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display) | ||||
|     : name(name), tooltip(tooltip), type(type), count(count), display(display) | ||||
| {} | ||||
| 
 | ||||
| std::string Bus::getName() { | ||||
|     return name; | ||||
| } | ||||
| std::string Bus::getTooltip() { | ||||
|     return tooltip; | ||||
| } | ||||
| Bus::BusType Bus::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::pair<int, int> Bus::getCount() { | ||||
|     return count; | ||||
| } | ||||
| std::optional<Display> Bus::getDisplay() { | ||||
|     return display; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										40
									
								
								comdel/domain/bus.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								comdel/domain/bus.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| #ifndef DOMAIN_BUS_H | ||||
| #define DOMAIN_BUS_H | ||||
| 
 | ||||
| #include "display.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <optional> | ||||
| 
 | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class Bus | ||||
| { | ||||
| public: | ||||
|     enum BusType { | ||||
|         AUTOMATIC, | ||||
|         REGULAR | ||||
|     }; | ||||
| private: | ||||
|     std::string name; | ||||
|     std::string tooltip; | ||||
|     BusType type; | ||||
| 
 | ||||
|     std::pair<int, int> count; | ||||
|     std::optional<Display> display; | ||||
| 
 | ||||
| public: | ||||
|     Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display = std::nullopt); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     std::string getTooltip(); | ||||
|     BusType getType(); | ||||
|     std::pair<int, int> getCount(); | ||||
|     std::optional<Display> getDisplay(); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_BUS_H
 | ||||
							
								
								
									
										445
									
								
								comdel/domain/comdelgenerator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										445
									
								
								comdel/domain/comdelgenerator.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,445 @@ | ||||
| #include "comdelgenerator.h" | ||||
| 
 | ||||
| #include<set> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Component::ComponentType toType(ComponentNode::ComponentType type) { | ||||
|     if(type == ComponentNode::MEMORY) { | ||||
|         return Component::MEMORY; | ||||
|     } else if(type == ComponentNode::PROCESSOR) { | ||||
|         return Component::PROCESSOR; | ||||
|     } | ||||
|     return Component::OTHER; | ||||
| } | ||||
| 
 | ||||
| Action::ActionType toType(ActionNode::ActionType type) { | ||||
|     if(type == ActionNode::ERROR) { | ||||
|         return Action::ERROR; | ||||
|     } | ||||
|     return Action::WARNING; | ||||
| } | ||||
| 
 | ||||
| Value::ValueType toType(ValueNode::ValueType type) { | ||||
|     switch (type) { | ||||
|     case ValueNode::BOOL: | ||||
|         return Value::BOOL; | ||||
|     case ValueNode::WIRE: | ||||
|         return Value::WIRE_REFERENCE; | ||||
|     case ValueNode::STRING: | ||||
|         return Value::STRING; | ||||
|     case ValueNode::INT: | ||||
|         return Value::INT; | ||||
|     default: | ||||
|         return Value::UNDEFINED; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Value toType(ValueNode node) { | ||||
|     if(node.getType() == ValueNode::BOOL) { | ||||
|         return Value::fromBool(node.asBool()); | ||||
|     } else if(node.getType() == ValueNode::INT) { | ||||
|         return Value::fromInt(node.asInt()); | ||||
|     } else if(node.getType() == ValueNode::STRING) { | ||||
|         return Value::fromString(node.asString()); | ||||
|     } | ||||
|     return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Bus::BusType toType(BusNode::BusType type) { | ||||
|     if(type == BusNode::AUTOMATIC) { | ||||
|         return Bus::AUTOMATIC; | ||||
|     } | ||||
|     return Bus::REGULAR; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Pin::PinType toType(PinNode::PinType type) { | ||||
|     if(type == PinNode::IN) { | ||||
|         return Pin::IN; | ||||
|     } else if(type == PinNode::OUT) { | ||||
|         return Pin::OUT; | ||||
|     } | ||||
|     return Pin::IN_OUT; | ||||
| } | ||||
| 
 | ||||
| PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type) | ||||
| { | ||||
|     if(type == PinConnectionNode::AUTOMATICALLY) { | ||||
|         return PinConnection::AUTOMATICALLY; | ||||
|     } | ||||
|     return PinConnection::CHECK_ONLY; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Popup::PopupType toType(PopupNode::PopupType type) | ||||
| { | ||||
|     if(type == PopupNode::AUTOMATIC) { | ||||
|         return Popup::AUTOMATIC; | ||||
|     } | ||||
|     return Popup::ON_DEMAND; | ||||
| } | ||||
| 
 | ||||
| ComdelGenerator::ComdelGenerator(std::vector<FunctionSignature> signatures) | ||||
|     : signatures(signatures) | ||||
| {} | ||||
| 
 | ||||
| std::optional<Library> ComdelGenerator::loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream) | ||||
| { | ||||
|     // library fields
 | ||||
|     if(!node.name) { | ||||
|         errors.push_back(SourceError{node.span, "missing @name"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string name = node.name->asString(); | ||||
| 
 | ||||
|     if(!node.componentDirectory) { | ||||
|         errors.push_back(SourceError{node.span, "missing @componentDirectory"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string componentDirectory = node.componentDirectory->asString(); | ||||
| 
 | ||||
|     std::string header = node.header ? node.header->asString() : ""; | ||||
| 
 | ||||
|     std::string libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; | ||||
| 
 | ||||
|     std::vector<AddressSpace> addressSpaces; | ||||
|     for(auto& as: node.addressSpaces) { | ||||
|         addressSpaces.push_back(*loadAddressSpace(as)); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Component> components; | ||||
|     for(auto& comp: node.components) { | ||||
|         std::optional<Component> component; | ||||
|         component = loadComponent(comp); | ||||
|         if(component) { | ||||
|             components.push_back(*component); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Connection> connections; | ||||
|     for(uint i=0; i<node.connections.size(); i++) { | ||||
|         auto conn = loadConnection(node.connections[i]); | ||||
|         if(!conn) { | ||||
|             return nullopt; | ||||
|         } | ||||
|         connections.push_back(*conn); | ||||
|     } | ||||
| 
 | ||||
|     std::map<std::string, std::string> messages; | ||||
|     for(uint i=0; i<node.messages.size(); i++) { | ||||
|         if(!node.messages[i].value.is(ValueNode::STRING)) { | ||||
|             errors.push_back(SourceError{node.messages[i].key.span, "expected `string`"}); | ||||
|             return nullopt; | ||||
|         } | ||||
|         messages[node.messages[i].key.value] = node.messages[i].value.asString(); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Bus> buses; | ||||
|     for(uint i=0; i<node.buses.size(); i++) { | ||||
|         auto bus = loadBus(node.buses[i]); | ||||
|         if(!bus) { | ||||
|             return nullopt; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Library(name, libraryInfo, header, componentDirectory, addressSpaces, components, buses, connections, messages); | ||||
| } | ||||
| 
 | ||||
| std::optional<Bus> ComdelGenerator::loadBus(BusNode node) | ||||
| { | ||||
|     std::string name = node.name.value; | ||||
| 
 | ||||
|     auto count = std::make_pair<int, int>(1, 1); | ||||
|     if(node.count) { | ||||
|         count = std::make_pair<int, int>(node.count->first.value, node.count->second.value); | ||||
|     } | ||||
|     if(count.first > count.second || count.first < 0) { | ||||
|         errors.push_back(SourceError{node.count->span, "invalid @size (min, max) := min <= max && min >= 0"}); | ||||
|         return nullopt; | ||||
|     } | ||||
| 
 | ||||
|     auto type = toType(node.type); | ||||
| 
 | ||||
|     if(!node.tooltip && type == Bus::REGULAR) { | ||||
|         errors.push_back(SourceError{node.span, "missing @tooltip"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string tooltip = node.tooltip->asString(); | ||||
| 
 | ||||
|     if(!node.display && type == Bus::REGULAR) { | ||||
|         errors.push_back(SourceError{node.span, "missing @display"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     if(node.display && type == Bus::AUTOMATIC) { | ||||
|         errors.push_back(SourceError{node.span, "automatic bus cannot have a @display"}); | ||||
|         return nullopt; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     optional<Display> display; | ||||
|     if(Bus::REGULAR) { | ||||
|         display = loadDisplay(*node.display); | ||||
|         if(!display) { | ||||
|             return nullopt; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Bus(name, tooltip, type, count, display); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| std::optional<AddressSpace> ComdelGenerator::loadAddressSpace(AddressSpaceNode node) | ||||
| { | ||||
|     return AddressSpace(node.name.value, node.start.value, node.end.value); | ||||
| } | ||||
| 
 | ||||
| std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node) | ||||
| { | ||||
|     std::string component = node.component.value; | ||||
|     std::string pin = node.pin.value; | ||||
|     std::string bus = node.bus.value; | ||||
| 
 | ||||
|     std::vector<Attribute> attributes; | ||||
|     for(uint i=0; i<node.attributes.size(); i++) { | ||||
|         auto attr = loadAttribute(node.attributes[i]); | ||||
|         if(!attr) { | ||||
|             return nullopt; | ||||
|         } | ||||
|         attributes.push_back(*attr); | ||||
|     } | ||||
| 
 | ||||
|     std::set<std::string> attributeNames; | ||||
|     for(auto attribute: attributes) { | ||||
|         attributeNames.insert(attribute.getName()); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Value> wires; | ||||
|     for(uint i=0; i<node.wires.size(); i++) { | ||||
|         if(attributeNames.count(node.wires[i].value)) { | ||||
|             wires.push_back(Value::fromReference(node.wires[i].value, Value::ATTRIBUTE_REFERENCE)); | ||||
|         } else { | ||||
|             wires.push_back(Value::fromReference(node.wires[i].value, Value::WIRE_REFERENCE)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Connection(component, pin, bus, attributes, wires); | ||||
| } | ||||
| 
 | ||||
| std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node) | ||||
| { | ||||
|     std::string name = node.name.value; | ||||
| 
 | ||||
|     if(!node.tooltip) { | ||||
|         errors.push_back(SourceError{node.span, "missing @tooltip"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string tooltip = node.tooltip->asString(); | ||||
| 
 | ||||
|     if(!node.source) { | ||||
|         errors.push_back(SourceError{node.span, "missing @source"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string source = node.source->asString(); | ||||
| 
 | ||||
|     Component::ComponentType type = toType(node.type); | ||||
| 
 | ||||
|     std::vector<Attribute> attributes; | ||||
|     for(auto& a: node.attributes) { | ||||
|         std::optional<Attribute> attribute = loadAttribute(a); | ||||
|         if(attribute) { | ||||
|             attributes.push_back(*attribute); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Rule> rules; | ||||
|     for(auto& r: node.rules) { | ||||
|         std::optional<Rule> rule = loadRule(r); | ||||
|         if(rule) { | ||||
|             rules.push_back(*rule); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(!node.instanceName) { | ||||
|         errors.push_back(SourceError{node.span, "missing @instanceName"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string instanceName = node.instanceName->asString(); | ||||
| 
 | ||||
|     auto count = std::make_pair<int, int>(1, 1); | ||||
|     if(node.count) { | ||||
|         count = std::make_pair<int, int>(node.count->first.value, node.count->second.value); | ||||
|     } | ||||
|     if(count.first > count.second || count.first < 0) { | ||||
|         errors.push_back(SourceError{node.count->first.span, "invalid @size"}); | ||||
|         return nullopt; | ||||
|     } | ||||
| 
 | ||||
|     if(!node.display) { | ||||
|         errors.push_back(SourceError{node.span, "missing @display"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     optional<Display> display = loadDisplay(*node.display); | ||||
|     if(!display) { | ||||
|         return nullopt; | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Pin> pins; | ||||
|     for(uint i=0; i<node.pins.size(); i++) { | ||||
|         auto pin = loadPin(node.pins[i]); | ||||
|         if(!pin) { | ||||
|             return nullopt; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Component(name, tooltip, source, type, rules, instanceName, count, *display, pins, attributes); | ||||
| } | ||||
| 
 | ||||
| optional<Pin> ComdelGenerator::loadPin(PinNode node) | ||||
| { | ||||
|     std::string name = node.name.value; | ||||
|     Pin::PinType type = toType(node.type); | ||||
| 
 | ||||
|     if(!node.tooltip) { | ||||
|         errors.push_back(SourceError{node.span, "missing @tooltip"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string tooltip = node.tooltip->asString(); | ||||
| 
 | ||||
|     if(!node.display) { | ||||
|         errors.push_back(SourceError{node.span, "missing @display"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::vector<Attribute> attributes; | ||||
|     optional<Display> display = loadDisplay(*node.display); | ||||
|     if(!display) { | ||||
|         return nullopt; | ||||
|     } | ||||
| 
 | ||||
|     if(!node.connection) { | ||||
|         errors.push_back(SourceError{node.span, "missing @connection"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     auto connection = loadPinConnection(*node.connection); | ||||
| 
 | ||||
|     return Pin(name, type, tooltip, connection, *display); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| std::optional<Display> ComdelGenerator::loadDisplay(DisplayNode node) | ||||
| { | ||||
|     return Display(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| PinConnection ComdelGenerator::loadPinConnection(PinConnectionNode node) | ||||
| { | ||||
|     std::string message = node.message.asString(); | ||||
|     PinConnection::ConnectionType type = toType(node.type); | ||||
|     return PinConnection(message, type); | ||||
| } | ||||
| 
 | ||||
| std::optional<Attribute> ComdelGenerator::loadAttribute(AttributeNode node) | ||||
| { | ||||
|     std::string name = node.name.value; | ||||
|     Value value; | ||||
|     if(node.type == ValueNode::INT) { | ||||
|         value = Value::fromInt(node.defaultValue->asInt()); | ||||
|     } else if (node.type == ValueNode::BOOL) { | ||||
|         value = Value::fromBool(node.defaultValue->asBool()); | ||||
|     } else if (node.type == ValueNode::STRING) { | ||||
|         value = Value::fromString(node.defaultValue->asString()); | ||||
|     } else if (node.type == ValueNode::WIRE) { | ||||
|         value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE); | ||||
|     } | ||||
| 
 | ||||
|     std::optional<Popup> popup; | ||||
|     if(node.popup) { | ||||
|         popup = loadPopup(*node.popup, name, value.getType()); | ||||
|     } | ||||
| 
 | ||||
|     return Attribute(name, value, popup); | ||||
| } | ||||
| 
 | ||||
| std::optional<Popup> ComdelGenerator::loadPopup(PopupNode node, std::string name, Value::ValueType type) | ||||
| { | ||||
|     auto popupType = toType(*node.type); | ||||
| 
 | ||||
|     if(!node.title) { | ||||
|         errors.push_back(SourceError{node.span, "missing @title"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string title = node.title->asString(); | ||||
| 
 | ||||
|     if(!node.text) { | ||||
|         errors.push_back(SourceError{node.span, "missing @text"}); | ||||
|         return nullopt; | ||||
|     } | ||||
|     std::string text = node.text->asString(); | ||||
| 
 | ||||
|     std::vector<Attribute> attributes; | ||||
|     attributes.push_back(Attribute(name, Value::ofType(type))); | ||||
| 
 | ||||
|     std::vector<Rule> rules; | ||||
|     for(auto& r: node.rules) { | ||||
|         std::optional<Rule> rule = loadRule(r); | ||||
|         if(rule) { | ||||
|             rules.push_back(*rule); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::vector<Enumeration> enumeration; | ||||
|     if(node.enumerated) { | ||||
|         for(uint i=0; i<node.enumeration.size(); i++) { | ||||
|             if(toType(node.enumeration[i].value.getType()) != type) { | ||||
|                 errors.push_back(SourceError{node.enumeration[i].span, "wrong type"}); | ||||
|                 return nullopt; | ||||
|             } | ||||
|             enumeration.push_back(Enumeration(node.enumeration[i].key.asString(), | ||||
|                                               toType(node.enumeration[i].value))); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Popup(title, text, popupType, rules, enumeration); | ||||
| } | ||||
| 
 | ||||
| std::optional<Rule> ComdelGenerator::loadRule(RuleNode node) | ||||
| { | ||||
|     std::vector<IfStatement> statements; | ||||
| 
 | ||||
|     for(auto& stmt: node.statements) { | ||||
|         auto condition = loadCondition(stmt.condition); | ||||
|         if(condition) { | ||||
|             statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type), stmt.action.message.asString()))); | ||||
|         } else { | ||||
|             return nullopt; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Rule(statements); | ||||
| } | ||||
| 
 | ||||
| std::optional<Condition> ComdelGenerator::loadCondition(ConditionNode node) | ||||
| { | ||||
|     std::string function = node.functionName.value; | ||||
| 
 | ||||
|     for(uint i=0; i<signatures.size(); i++) { | ||||
|         if(signatures[i].name == function) { | ||||
|             if(signatures[i].params.size() == node.params.size()) { | ||||
|                 std::vector<Value> params; | ||||
|                 for(int j=0; j<signatures[i].params[i]; j++) { | ||||
|                     params.push_back(toType(node.params[i])); | ||||
|                 } | ||||
|                 return Condition(function,params, node.negated); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return nullopt; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										41
									
								
								comdel/domain/comdelgenerator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								comdel/domain/comdelgenerator.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| #ifndef DOMAIN_COMDELGENERATOR_H | ||||
| #define DOMAIN_COMDELGENERATOR_H | ||||
| 
 | ||||
| #include "library.h" | ||||
| 
 | ||||
| #include <comdel/parser/astnode.h> | ||||
| #include <comdel/parser/parsecontext.h> | ||||
| #include <comdel/parser/presult.h> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class ComdelGenerator | ||||
| { | ||||
|     std::vector<SourceError> errors; | ||||
|     std::vector<FunctionSignature> signatures; | ||||
| 
 | ||||
|     std::optional<AddressSpace> loadAddressSpace(AddressSpaceNode node); | ||||
|     std::optional<Component> loadComponent(ComponentNode node); | ||||
|     std::optional<Attribute> loadAttribute(AttributeNode node); | ||||
|     std::optional<Rule> loadRule(RuleNode node); | ||||
|     std::optional<Condition> loadCondition(ConditionNode node); | ||||
|     std::optional<Popup> loadPopup(PopupNode node, std::string name, Value::ValueType type); | ||||
|     std::optional<Display> loadDisplay(DisplayNode node); | ||||
|     std::optional<Pin> loadPin(PinNode pins); | ||||
|     PinConnection loadPinConnection(PinConnectionNode node); | ||||
|     std::optional<Connection> loadConnection(ConnectionNode node); | ||||
|     std::optional<Bus> loadBus(BusNode node); | ||||
| 
 | ||||
| public: | ||||
|     ComdelGenerator(std::vector<FunctionSignature> signatures); | ||||
| 
 | ||||
|     std::vector<SourceError> getErrors() { | ||||
|         return errors; | ||||
|     } | ||||
| 
 | ||||
|     std::optional<Library> loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_COMDELGENERATOR_H
 | ||||
							
								
								
									
										62
									
								
								comdel/domain/component.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								comdel/domain/component.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| #include "component.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Component::Component(string name, string tooltip, string source, ComponentType type, | ||||
|           vector<Rule> rules, string instanceName, pair<int, int> count, Display display, | ||||
|           vector<Pin> pins, vector<Attribute> attributes) | ||||
|     : name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), count(count), display(display), pins(pins), attributes(attributes) | ||||
| {} | ||||
| 
 | ||||
| std::string Component::getName() { | ||||
|     return name; | ||||
| } | ||||
| std::string Component::getTooltip() { | ||||
|     return tooltip; | ||||
| } | ||||
| std::string Component::getSource() { | ||||
|     return source; | ||||
| } | ||||
| Component::ComponentType Component::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::vector<Rule> Component::getRules() { | ||||
|     return rules; | ||||
| } | ||||
| std::string Component::getInstanceName() { | ||||
|     return instanceName; | ||||
| } | ||||
| std::pair<int, int> Component::getCount() { | ||||
|     return count; | ||||
| } | ||||
| Display Component::getDisplay() { | ||||
|     return display; | ||||
| } | ||||
| 
 | ||||
| std::vector<Pin> Component::getPins() { | ||||
|     return pins; | ||||
| } | ||||
| Pin Component::getPin(std::string pin) { | ||||
|     for(uint i=0; i<pins.size(); i++) { | ||||
|         if(pins[i].getName() == pin) { | ||||
|             return pins[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| 
 | ||||
| std::vector<Attribute> Component::getAttributes() { | ||||
|     return attributes; | ||||
| } | ||||
| Attribute Component::getAttribute(std::string attribute) { | ||||
|     for(uint i=0; i<attributes.size(); i++) { | ||||
|         if(attributes[i].getName() == attribute) { | ||||
|             return attributes[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										63
									
								
								comdel/domain/component.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								comdel/domain/component.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| #ifndef DOMAIN_COMPONENT_H | ||||
| #define DOMAIN_COMPONENT_H | ||||
| 
 | ||||
| #include "pin.h" | ||||
| #include "rule.h" | ||||
| #include "display.h" | ||||
| #include "attribute.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| class Component | ||||
| { | ||||
| public: | ||||
|     enum ComponentType { | ||||
|         OTHER, | ||||
|         PROCESSOR, | ||||
|         MEMORY | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     std::string name; | ||||
|     std::string tooltip; | ||||
|     std::string source; | ||||
|     ComponentType type; | ||||
|     std::vector<Rule> rules; | ||||
|     std::string instanceName; | ||||
|     std::pair<int, int> count; | ||||
|     Display display; | ||||
| 
 | ||||
|     std::vector<Pin> pins; | ||||
|     std::vector<Attribute> attributes; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     Component(string name, string tooltip, string source, ComponentType type, | ||||
|               vector<Rule> rules, string instanceName, pair<int, int> count, Display display, | ||||
|               vector<Pin> pins, vector<Attribute> attributes); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     std::string getTooltip(); | ||||
|     std::string getSource(); | ||||
|     ComponentType getType(); | ||||
|     std::vector<Rule> getRules(); | ||||
|     std::string getInstanceName(); | ||||
|     std::pair<int, int> getCount(); | ||||
|     Display getDisplay(); | ||||
| 
 | ||||
|     std::vector<Pin> getPins(); | ||||
|     Pin getPin(std::string pin); | ||||
| 
 | ||||
|     std::vector<Attribute> getAttributes(); | ||||
|     Attribute getAttribute(std::string attribute); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_COMPONENT_H
 | ||||
							
								
								
									
										39
									
								
								comdel/domain/connection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								comdel/domain/connection.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| #include "connection.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Connection::Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires) | ||||
|     : component(component), pin(pin), bus(bus), attributes(attributes), wires(wires) | ||||
| {} | ||||
| 
 | ||||
| bool Connection::isConnecting(std::string component, std::string pin, std::string bus) { | ||||
|     return this->component == component && this->pin == pin && this->bus == bus; | ||||
| } | ||||
| 
 | ||||
| std::string Connection::getComponent() { | ||||
|     return component; | ||||
| } | ||||
| std::string Connection::getPin() { | ||||
|     return pin; | ||||
| } | ||||
| std::string Connection::getBus() { | ||||
|     return bus; | ||||
| } | ||||
| 
 | ||||
| std::vector<Attribute> Connection::getAttributes() { | ||||
|     return attributes; | ||||
| } | ||||
| std::vector<Value> Connection::getWires() { | ||||
|     return wires; | ||||
| } | ||||
| 
 | ||||
| Attribute Connection::getAttribute(std::string name) { | ||||
|     for(uint i=0; i<attributes.size(); i++) { | ||||
|         if(attributes[i].getName() == name) { | ||||
|             return attributes[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										36
									
								
								comdel/domain/connection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								comdel/domain/connection.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #ifndef DOMAIN_CONNECTION_H | ||||
| #define DOMAIN_CONNECTION_H | ||||
| 
 | ||||
| #include "attribute.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class Connection | ||||
| { | ||||
|     std::string component; | ||||
|     std::string pin; | ||||
|     std::string bus; | ||||
| 
 | ||||
|     std::vector<Attribute> attributes; | ||||
|     std::vector<Value> wires; | ||||
| public: | ||||
|     Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires); | ||||
| 
 | ||||
|     bool isConnecting(std::string component, std::string pin, std::string bus); | ||||
| 
 | ||||
|     std::string getComponent(); | ||||
|     std::string getPin(); | ||||
|     std::string getBus(); | ||||
| 
 | ||||
|     std::vector<Attribute> getAttributes(); | ||||
|     std::vector<Value> getWires(); | ||||
| 
 | ||||
|     Attribute getAttribute(std::string name); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_CONNECTION_H
 | ||||
							
								
								
									
										10
									
								
								comdel/domain/display.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								comdel/domain/display.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #include "display.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Display::Display() | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										15
									
								
								comdel/domain/display.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								comdel/domain/display.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| #ifndef DOMAIN_DISPLAY_H | ||||
| #define DOMAIN_DISPLAY_H | ||||
| 
 | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class Display | ||||
| { | ||||
| public: | ||||
|     Display(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_DISPLAY_H
 | ||||
							
								
								
									
										5
									
								
								comdel/domain/functionsignature.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								comdel/domain/functionsignature.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| #include "functionsignature.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										20
									
								
								comdel/domain/functionsignature.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								comdel/domain/functionsignature.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| #ifndef DOMAIN_FUNCTIONSIGNATURE_H | ||||
| #define DOMAIN_FUNCTIONSIGNATURE_H | ||||
| 
 | ||||
| #include<functional> | ||||
| #include "value.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| typedef std::function<bool (std::vector<Value>)> FunctionCallback; | ||||
| 
 | ||||
| struct FunctionSignature { | ||||
|     std::string name; | ||||
|     std::vector<Value::ValueType> params; | ||||
| 
 | ||||
|     FunctionSignature(std::string name, std::vector<Value::ValueType> params): name(name), params(params) {} | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_FUNCTIONSIGNATURE_H
 | ||||
							
								
								
									
										78
									
								
								comdel/domain/library.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								comdel/domain/library.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| #include "library.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Library::Library(string name, string libraryInfo, string header, string componentDirectory, | ||||
|         vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses, vector<Connection> connections, map<string, string> messages) | ||||
|     : name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), addressSpaces(addressSpaces), | ||||
|       components(components), buses(buses), connections(connections), messages(messages) | ||||
| {} | ||||
| 
 | ||||
| std::string Library::getName() { | ||||
|     return name; | ||||
| } | ||||
| std::string Library::getLibraryInfo() { | ||||
|     return libraryInfo; | ||||
| } | ||||
| std::string Library::getHeader() { | ||||
|     return header; | ||||
| } | ||||
| std::string Library::getComponentDirectory() { | ||||
|     return componentDirectory; | ||||
| } | ||||
| 
 | ||||
| std::vector<AddressSpace> Library::getAddressSpaces() { | ||||
|     return addressSpaces; | ||||
| } | ||||
| std::vector<Component> Library::getComponents() { | ||||
|     return components; | ||||
| } | ||||
| std::vector<Bus> Library::getBuses() { | ||||
|     return buses; | ||||
| } | ||||
| std::vector<Connection> Library::getConnections() { | ||||
|     return connections; | ||||
| } | ||||
| 
 | ||||
| std::map<std::string, std::string> Library::getMessages() { | ||||
|     return messages; | ||||
| } | ||||
| 
 | ||||
| AddressSpace &Library::getAddressSpace(std::string addressSpace) { | ||||
|     for(uint i=0; i<addressSpaces.size(); i++) { | ||||
|         if(addressSpaces[i].getName() == addressSpace) { | ||||
|             return addressSpaces[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| Component &Library::getComponent(std::string component) { | ||||
|     for(uint i=0; i<components.size(); i++) { | ||||
|         if(components[i].getName() == component) { | ||||
|             return components[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| Bus &Library::getBus(std::string bus) { | ||||
|     for(uint i=0; i<buses.size(); i++) { | ||||
|         if(buses[i].getName() == bus) { | ||||
|             return buses[i]; | ||||
|         } | ||||
|     } | ||||
|     throw std::exception(); | ||||
| 
 | ||||
| } | ||||
| std::optional<Connection> Library::getConnection(std::string component, std::string pin, std::string bus) { | ||||
|     for(uint i=0; i<connections.size(); i++) { | ||||
|         if(connections[i].isConnecting(component, pin, bus)) { | ||||
|             return connections[i]; | ||||
|         } | ||||
|     } | ||||
|     return nullopt; | ||||
| } | ||||
| std::string Library::getMessage(std::string key) { | ||||
|     return messages[key]; | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										58
									
								
								comdel/domain/library.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								comdel/domain/library.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| #ifndef DOMAIN_LIBRARY_H | ||||
| #define DOMAIN_LIBRARY_H | ||||
| 
 | ||||
| #include "addressspace.h" | ||||
| #include "bus.h" | ||||
| #include "component.h" | ||||
| #include "connection.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| class Library | ||||
| { | ||||
|     std::string name; | ||||
|     std::string libraryInfo; | ||||
|     std::string header; | ||||
|     std::string componentDirectory; | ||||
| 
 | ||||
|     std::vector<AddressSpace> addressSpaces; | ||||
|     std::vector<Component> components; | ||||
|     std::vector<Bus> buses; | ||||
|     std::vector<Connection> connections; | ||||
| 
 | ||||
|     std::map<std::string, std::string> messages; | ||||
| 
 | ||||
| public: | ||||
|     Library(string name, string libraryInfo, string header, string componentDirectory, | ||||
|             vector<AddressSpace> addressSpaces, vector<Component> components, vector<Bus> buses, vector<Connection> connection, map<string, string> messages); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     std::string getLibraryInfo(); | ||||
|     std::string getHeader(); | ||||
|     std::string getComponentDirectory(); | ||||
| 
 | ||||
|     std::vector<AddressSpace> getAddressSpaces(); | ||||
|     std::vector<Component> getComponents(); | ||||
|     std::vector<Bus> getBuses(); | ||||
|     std::vector<Connection> getConnections(); | ||||
| 
 | ||||
|     std::map<std::string, std::string> getMessages(); | ||||
| 
 | ||||
|     AddressSpace &getAddressSpace(std::string name); | ||||
|     Component &getComponent(std::string name); | ||||
|     Bus &getBus(std::string bus); | ||||
|     std::optional<Connection> getConnection(std::string component, std::string pin, std::string bus); | ||||
|     std::string getMessage(std::string key); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_LIBRARY_H
 | ||||
							
								
								
									
										38
									
								
								comdel/domain/pin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								comdel/domain/pin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| #include "pin.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| PinConnection::PinConnection(std::string message, ConnectionType type) | ||||
|     : message(message), type(type) | ||||
| {} | ||||
| 
 | ||||
| PinConnection::ConnectionType PinConnection::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::string PinConnection::getMessage() { | ||||
|     return message; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display) | ||||
|     : name(name), type(type), tooltip(tooltip), connection(connection), display(display) | ||||
| {} | ||||
| 
 | ||||
| std::string Pin::getName() { | ||||
|     return name; | ||||
| } | ||||
| Pin::PinType Pin::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::string Pin::getTooltip() { | ||||
|     return tooltip; | ||||
| } | ||||
| Display &Pin::getDisplay() { | ||||
|     return display; | ||||
| } | ||||
| PinConnection &Pin::getConnection() { | ||||
|     return connection; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										59
									
								
								comdel/domain/pin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								comdel/domain/pin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| #ifndef DOMAIN_PIN_H | ||||
| #define DOMAIN_PIN_H | ||||
| 
 | ||||
| #include "display.h" | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class PinConnection | ||||
| { | ||||
| public: | ||||
|     enum ConnectionType { | ||||
|         CHECK_ONLY, | ||||
|         AUTOMATICALLY | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     std::string message; | ||||
|     ConnectionType type; | ||||
| 
 | ||||
| public: | ||||
|     PinConnection(std::string message, ConnectionType type); | ||||
| 
 | ||||
|     ConnectionType getType(); | ||||
|     std::string getMessage(); | ||||
| }; | ||||
| 
 | ||||
| class Pin | ||||
| { | ||||
| public: | ||||
|     enum PinType { | ||||
|         IN_OUT, | ||||
|         IN, | ||||
|         OUT | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     std::string name; | ||||
|     PinType type; | ||||
|     std::string tooltip; | ||||
|     PinConnection connection; | ||||
|     Display display; | ||||
| 
 | ||||
| public: | ||||
|     Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, Display display); | ||||
| 
 | ||||
|     std::string getName(); | ||||
|     PinType getType(); | ||||
|     std::string getTooltip(); | ||||
|     Display &getDisplay(); | ||||
|     PinConnection &getConnection(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_PIN_H
 | ||||
							
								
								
									
										60
									
								
								comdel/domain/rule.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								comdel/domain/rule.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #include "rule.h" | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Condition::Condition(std::string function, std::vector<Value> params, bool negated) | ||||
|     : negated(negated), function(function), params(params) | ||||
| {} | ||||
| 
 | ||||
| bool Condition::evaluate(RuleContext &context) { | ||||
|     std::vector<Value> request; | ||||
|     for(uint i=0; i<params.size(); i++) { | ||||
|         if(params[i].isType(Value::ATTRIBUTE_REFERENCE)) { | ||||
|             request.push_back(context.attributes[params[i].asReference()]); | ||||
|         } else { | ||||
|             request.push_back(params[i]); | ||||
|         } | ||||
|     } | ||||
|     bool result = context.function[function](request); | ||||
|     return negated ? !result : result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Action::Action(ActionType type, std::string message) | ||||
|     : type(type), message(message) | ||||
| {} | ||||
| 
 | ||||
| Action::ActionType Action::getType() { | ||||
|     return type; | ||||
| } | ||||
| std::string Action::getMessage() { | ||||
|     return message; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| IfStatement::IfStatement(Condition condition, Action action) | ||||
|     : condition(condition), action(action) | ||||
| {} | ||||
| 
 | ||||
| std::optional<Action> IfStatement::evaluate(RuleContext &context) { | ||||
|     if(condition.evaluate(context)) { | ||||
|         return action; | ||||
|     } | ||||
|     return std::nullopt; | ||||
| } | ||||
| 
 | ||||
| Rule::Rule(std::vector<IfStatement> statements) | ||||
|     : statements(statements) | ||||
| {} | ||||
| 
 | ||||
| std::optional<Action> Rule::evaluate(RuleContext &context) { | ||||
|     for(uint i=0; i<statements.size(); i++) { | ||||
|         auto response = statements[i].evaluate(context); | ||||
|         if(response) { | ||||
|             return response; | ||||
|         } | ||||
|     } | ||||
|     return std::nullopt; | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										70
									
								
								comdel/domain/rule.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								comdel/domain/rule.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| #ifndef DOMAIN_RULE_H | ||||
| #define DOMAIN_RULE_H | ||||
| 
 | ||||
| #include "addressspace.h" | ||||
| #include "value.h" | ||||
| #include "functionsignature.h" | ||||
| 
 | ||||
| #include <map> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <optional> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| struct RuleContext { | ||||
|     std::map<std::string, AddressSpace> addressSpaces; | ||||
|     std::map<std::string, Value> attributes; | ||||
|     std::map<std::string, FunctionCallback> function; | ||||
| }; | ||||
| 
 | ||||
| class Condition { | ||||
|     bool negated; | ||||
|     std::string function; | ||||
|     std::vector<Value> params; | ||||
| 
 | ||||
| public: | ||||
|     Condition(std::string function, std::vector<Value> params, bool negated); | ||||
| 
 | ||||
|     bool evaluate(RuleContext &context); | ||||
| }; | ||||
| 
 | ||||
| class Action { | ||||
| public: | ||||
|     enum ActionType { | ||||
|         ERROR, | ||||
|         WARNING | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     ActionType type; | ||||
|     std::string message; | ||||
| 
 | ||||
| public: | ||||
|     Action(ActionType type, std::string message); | ||||
| 
 | ||||
|     ActionType getType(); | ||||
|     std::string getMessage(); | ||||
| }; | ||||
| 
 | ||||
| class IfStatement { | ||||
|     Condition condition; | ||||
|     Action action; | ||||
| public: | ||||
|     IfStatement(Condition condition, Action action); | ||||
| 
 | ||||
|     std::optional<Action> evaluate(RuleContext &context); | ||||
| }; | ||||
| 
 | ||||
| class Rule | ||||
| { | ||||
|     std::vector<IfStatement> statements; | ||||
| public: | ||||
|     Rule(std::vector<IfStatement> statements); | ||||
| 
 | ||||
|     std::optional<Action> evaluate(RuleContext &context); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_RULE_H
 | ||||
							
								
								
									
										82
									
								
								comdel/domain/value.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								comdel/domain/value.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| #include "value.h" | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| Value::ValueType Value::getType() { | ||||
|     return type; | ||||
| } | ||||
| bool Value::isType(Value::ValueType type) { | ||||
|     return this->type == type; | ||||
| } | ||||
| 
 | ||||
| long long Value::asInt() { | ||||
|     if(isType(Value::INT)) { | ||||
|         return intValue; | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| std::string Value::asString() { | ||||
|     if(isType(Value::STRING)) { | ||||
|         return stringValue; | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| bool Value::asBool() { | ||||
|     if(isType(Value::BOOL)) { | ||||
|         return boolValue; | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| AddressSpace Value::asAddressSpace() { | ||||
|     if(isType(Value::ADDRESS_SPACE)) { | ||||
|         return *addressSpace; | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| std::string Value::asReference() { | ||||
|     if(isType(Value::WIRE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE)) { | ||||
|         return reference; | ||||
|     } | ||||
|     throw std::exception(); | ||||
| } | ||||
| 
 | ||||
| Value Value::fromInt(long long value) { | ||||
|     Value val; | ||||
|     val.type = Value::INT; | ||||
|     val.intValue = value; | ||||
|     return val; | ||||
| } | ||||
| Value Value::fromString(std::string value) { | ||||
|     Value val; | ||||
|     val.type = Value::STRING; | ||||
|     val.stringValue = value; | ||||
|     return val; | ||||
| } | ||||
| Value Value::fromBool(bool value) { | ||||
|     Value val; | ||||
|     val.type = Value::BOOL; | ||||
|     val.boolValue = value; | ||||
|     return val; | ||||
| } | ||||
| Value Value::fromAddressSpace(AddressSpace addressSpace) { | ||||
|     Value val; | ||||
|     val.type = Value::ADDRESS_SPACE; | ||||
|     val.addressSpace = addressSpace; | ||||
|     return val; | ||||
| } | ||||
| Value Value::fromReference(std::string value, Value::ValueType type) { | ||||
|     Value val; | ||||
|     val.type = type; | ||||
|     val.reference = value; | ||||
|     return val; | ||||
| } | ||||
| Value Value::ofType(Value::ValueType type) { | ||||
|     Value val; | ||||
|     val.type = type; | ||||
|     return val; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| } // namespace domain
 | ||||
							
								
								
									
										58
									
								
								comdel/domain/value.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								comdel/domain/value.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| #ifndef DOMAIN_VALUE_H | ||||
| #define DOMAIN_VALUE_H | ||||
| 
 | ||||
| #include "addressspace.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <optional> | ||||
| 
 | ||||
| namespace domain { | ||||
| 
 | ||||
| class Value | ||||
| { | ||||
| public: | ||||
|     enum ValueType { | ||||
|         INT, | ||||
|         STRING, | ||||
|         BOOL, | ||||
|         ADDRESS_SPACE, | ||||
|         ATTRIBUTE_REFERENCE, | ||||
|         WIRE_REFERENCE, | ||||
|         UNDEFINED, | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|     long long intValue; | ||||
|     std::string stringValue; | ||||
|     bool boolValue; | ||||
|     std::optional<AddressSpace> addressSpace; | ||||
|     std::string reference; | ||||
| 
 | ||||
|     ValueType type; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     Value() { | ||||
|         this->type = UNDEFINED; | ||||
|     } | ||||
| 
 | ||||
|     ValueType getType(); | ||||
|     bool isType(ValueType type); | ||||
| 
 | ||||
|     long long asInt(); | ||||
|     std::string asString(); | ||||
|     bool asBool(); | ||||
|     std::string asReference(); | ||||
|     AddressSpace asAddressSpace(); | ||||
| 
 | ||||
|     static Value fromInt(long long value); | ||||
|     static Value fromString(std::string value); | ||||
|     static Value fromBool(bool value); | ||||
|     static Value fromAddressSpace(AddressSpace addressSpace); | ||||
|     static Value fromReference(std::string value, ValueType type); | ||||
|     static Value ofType(ValueType type); | ||||
| }; | ||||
| 
 | ||||
| } // namespace domain
 | ||||
| 
 | ||||
| #endif // DOMAIN_VALUE_H
 | ||||
| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user