diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log new file mode 100644 index 0000000..bab9054 --- /dev/null +++ b/.vscode/configurationCache.log @@ -0,0 +1 @@ +{"buildTargets":[],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log new file mode 100644 index 0000000..5a412fa --- /dev/null +++ b/.vscode/dryrun.log @@ -0,0 +1,6 @@ +make --dry-run --always-make --keep-going --print-directory +make: Entering directory '/home/bbr/SchemeEditor' +make: Leaving directory '/home/bbr/SchemeEditor' + +make: *** No targets specified and no makefile found. Stop. + diff --git a/.vscode/targets.log b/.vscode/targets.log new file mode 100644 index 0000000..e74bdd5 --- /dev/null +++ b/.vscode/targets.log @@ -0,0 +1,288 @@ +make all --print-data-base --no-builtin-variables --no-builtin-rules --question +make: *** No rule to make target 'all'. Stop. + +# GNU Make 4.3 +# Built for x86_64-pc-linux-gnu +# Copyright (C) 1988-2020 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. + +# Make data base, printed on Sun Apr 24 22:18:48 2022 + +# Variables + +# environment +GDK_BACKEND = x11 +# environment +LC_ALL = C +# environment +NO_AT_BRIDGE = 1 +# environment +VSCODE_IPC_HOOK_EXTHOST = /run/user/1000/vscode-ipc-378bef37-635c-4f71-808d-af9f8b80a929.sock +# environment +LC_NAME = hr_HR.UTF-8 +# environment +LC_NUMERIC = hr_HR.UTF-8 +# environment +VSCODE_CWD = /home/bbr +# environment +LC_ADDRESS = hr_HR.UTF-8 +# default +MAKE_COMMAND := make +# environment +GTK3_MODULES = xapp-gtk3-module +# automatic +@D = $(patsubst %/,%,$(dir $@)) +# environment +VSCODE_HANDLES_UNCAUGHT_ERRORS = true +# default +.VARIABLES := +# environment +PWD = /home/bbr/SchemeEditor +# automatic +%D = $(patsubst %/,%,$(dir $%)) +# environment +MAIL = /var/spool/mail/bbr +# environment +XDG_DATA_DIRS = /usr/local/share:/usr/share:/var/lib/snapd/desktop +# automatic +^D = $(patsubst %/,%,$(dir $^)) +# environment +VSCODE_LOG_STACK = false +# automatic +%F = $(notdir $%) +# environment +VSCODE_CODE_CACHE_PATH = /home/bbr/.config/Code - OSS/CachedData/e18005f0f1b33c29e81d732535d8c0e47cafb0b5 +# environment +XDG_SESSION_PATH = /org/freedesktop/DisplayManager/Session0 +# environment +LANG = C +# environment +XAUTHORITY = /home/bbr/.Xauthority +# default +.LOADED := +# default +.INCLUDE_DIRS = /usr/include /usr/local/include /usr/include +# makefile +MAKEFLAGS = pqrR +# makefile +CURDIR := /home/bbr/SchemeEditor +# environment +VSCODE_PIPE_LOGGING = true +# environment +APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true +# automatic +*D = $(patsubst %/,%,$(dir $*)) +# environment +MFLAGS = -pqrR +# environment +SSH_AUTH_SOCK = /run/user/1000/keyring/ssh +# default +.SHELLFLAGS := -c +# automatic ++D = $(patsubst %/,%,$(dir $+)) +# environment +XDG_SESSION_DESKTOP = budgie-desktop +# makefile +MAKEFILE_LIST := +# automatic +@F = $(notdir $@) +# environment +VSCODE_VERBOSE_LOGGING = true +# environment +VSCODE_PID = 1877190 +# environment +XDG_SESSION_TYPE = x11 +# automatic +?D = $(patsubst %/,%,$(dir $?)) +# environment +SESSION_MANAGER = local/bbr:@/tmp/.ICE-unix/1465,unix/bbr:/tmp/.ICE-unix/1465 +# automatic +*F = $(notdir $*) +# environment +QT_QPA_PLATFORMTHEME = qt5ct +# environment +CHROME_DESKTOP = code-oss.desktop +# environment +DBUS_SESSION_BUS_ADDRESS = unix:path=/run/user/1000/bus +# automatic + count, std::vector wires, std::optional display) : name(name), tooltip(tooltip), type(type), count(count), wires(wires), display(display) {} diff --git a/comdel/domain/bus.h b/comdel/domain/bus.h index d2d7e0b..d422243 100644 --- a/comdel/domain/bus.h +++ b/comdel/domain/bus.h @@ -2,6 +2,7 @@ #define DOMAIN_BUS_H #include "display.h" +#include "value.h" #include #include @@ -26,17 +27,17 @@ private: WireType type; int width; bool hidden; - bool hasTermination; - long long ifUnterminated; + bool hasTerminate; + Value terminateWith; public: - Wire(std::string name, WireType type, int width, bool hidden, bool hasTermination, long long ifUnterminated); + Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith); std::string getName(); int getWidth(); bool isHidden(); - bool getHasTermination(); - long long getIfUnterminated(); + bool hasTerminateWith(); + Value getTerminateWith(); WireType getType(); }; diff --git a/comdel/domain/connectioninstance.h b/comdel/domain/connectioninstance.h index a9d5958..2d593a6 100644 --- a/comdel/domain/connectioninstance.h +++ b/comdel/domain/connectioninstance.h @@ -16,6 +16,8 @@ public: Connection connection; WireInstance *wire; + virtual ~ConnectionInstance() = default; + std::vector attributes; ConnectionInstance(ComponentInstance *instance, std::vector attributes, WireInstance *wire, Connection connection); diff --git a/comdel/domain/schemacreator.cpp b/comdel/domain/schemacreator.cpp index eae4383..35de60b 100644 --- a/comdel/domain/schemacreator.cpp +++ b/comdel/domain/schemacreator.cpp @@ -174,7 +174,7 @@ std::optional SchemaCreator::loadBus(BusNode node) return nullopt; } - auto type = toType(node.type); + auto type = toType(node.type.value); if(!node.tooltip && type == Bus::REGULAR) { errors.push_back(SourceError{node.span, "missing @tooltip"}); @@ -392,7 +392,7 @@ std::optional SchemaCreator::loadComponent(ComponentNode node) } std::string source = node.source->asString(); - Component::ComponentType type = toType(node.type); + Component::ComponentType type = toType(node.type.value); std::vector attributes; for(auto& a: node.attributes) { @@ -457,18 +457,18 @@ std::optional SchemaCreator::loadComponent(ComponentNode node) std::optional SchemaCreator::loadWire(WireNode node) { return Wire( node.name.value, - toType(node.type), + toType(node.type.value), node.size.value, node.hidden, - node.hasTermination, - node.isUnterminated + node.hasTerminateWith, + toType(node.terminateWith) ); } optional SchemaCreator::loadPin(PinNode node) { std::string name = node.name.value; - Pin::PinType type = toType(node.type); + Pin::PinType type = toType(node.type.value); if(!node.tooltip) { errors.push_back(SourceError{node.span, "missing @tooltip"}); @@ -559,7 +559,7 @@ std::optional SchemaCreator::loadDisplay(DisplayNode node) PinConnection SchemaCreator::loadPinConnection(PinConnectionNode node) { std::string message = node.message.asString(); - PinConnection::ConnectionType type = toType(node.type); + PinConnection::ConnectionType type = toType(node.type.value); return PinConnection(message, type); } @@ -606,7 +606,7 @@ std::optional SchemaCreator::loadAttribute(AttributeNode node) std::optional SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) { - auto popupType = toType(*node.type); + auto popupType = toType(node.type.value().value); pushAdditional(name); @@ -678,7 +678,7 @@ std::optional SchemaCreator::loadRule(RuleNode node) 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()))); + statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type.value), stmt.action.message.asString()))); } else { return nullopt; } diff --git a/comdel/domain/value.cpp b/comdel/domain/value.cpp index 2e10af1..08e5d37 100644 --- a/comdel/domain/value.cpp +++ b/comdel/domain/value.cpp @@ -137,4 +137,23 @@ Value Value::fromNull() { return val; } +std::string Value::stringify() { + switch (type) { + case INT: + return std::to_string(intValue); + case BOOL: + return boolValue ? "true" : "false"; + case STRING: + return "\"" + stringValue + "\""; + case NIL: + return "null"; + case WIRE_REFERENCE: + case ADDRESS_SPACE_REFERENCE: + case ATTRIBUTE_REFERENCE: + return reference; + default: + throw std::exception(); + } +} + } // namespace domain diff --git a/comdel/domain/value.h b/comdel/domain/value.h index b309862..6b1550c 100644 --- a/comdel/domain/value.h +++ b/comdel/domain/value.h @@ -55,6 +55,8 @@ public: void setBool(bool value); void setReference(std::string value); + std::string stringify(); + static Value fromInt(long long value); static Value fromString(std::string value); static Value fromBool(bool value); diff --git a/comdel/parser/astnode.cpp b/comdel/parser/astnode.cpp index 40a9670..bea8bd7 100644 --- a/comdel/parser/astnode.cpp +++ b/comdel/parser/astnode.cpp @@ -1,8 +1,12 @@ #include "astnode.h" +/*************************** AST NODE ********************************/ + AstNode::~AstNode() = default; -NumberNode::NumberNode(std::string expression) { +/*************************** NUMBER NODE ********************************/ + +NumberNode::NumberNode(const std::string& expression) { if(expression.size() > 2) { if(expression.substr(0, 2) == "0x") { this->value = std::stoll(expression, 0, 16); @@ -15,3 +19,84 @@ NumberNode::NumberNode(std::string expression) { this->value = std::stoll(expression, 0, 10); } } + +/*************************** STRING NODE ********************************/ + +std::string StringNode::asString() { + return value.substr(1, value.length() - 2); +} + +/*************************** VALUE NODE ********************************/ + +long long ValueNode::asInt() { + if(is(INT)) { + return intValue.value(); + } + return 0; +} + +std::string ValueNode::asString() { + if(is(STRING)) { + return stringValue.value(); + } + return ""; +} + +std::string ValueNode::asIdentifier() { + if(is(IDENTIFIER) || is(WIRE)) { + return identifierValue.value(); + } + return ""; +} + +bool ValueNode::asBool() { + if(is(BOOL)) { + return boolValue.value(); + } + return false; +} + +bool ValueNode::is(ValueNode::ValueType valueType) { + return type.value == valueType; +} + +ValueNode ValueNode::ofBool(bool _value) { + ValueNode value; + value.type = EnumNode(BOOL); + value.boolValue = std::optional(_value); + return value; +} + +ValueNode ValueNode::ofInt(long long int _value) { + ValueNode value; + value.type = EnumNode(INT); + value.intValue = std::optional(_value); + return value; +} + +ValueNode ValueNode::ofString(std::string _value) { + ValueNode value; + value.type = EnumNode(STRING); + value.stringValue = std::optional(_value); + return value; +} + +ValueNode ValueNode::ofIdentifier(std::string _value) { + ValueNode value; + value.type = EnumNode(IDENTIFIER); + value.identifierValue = std::optional(_value); + return value; +} + +ValueNode ValueNode::ofNull() { + ValueNode value; + value.type = EnumNode(NIL); + return value; +} + +ValueNode ValueNode::ofWire(std::string _value) { + ValueNode value; + value.type = EnumNode(WIRE); + value.identifierValue = std::optional(_value); + return value; +} diff --git a/comdel/parser/astnode.h b/comdel/parser/astnode.h index 80a718d..f96afec 100644 --- a/comdel/parser/astnode.h +++ b/comdel/parser/astnode.h @@ -16,24 +16,27 @@ public: AstNode() = default; - virtual ~AstNode(); // this is defined in Ast.cpp just so that the - // compiler doesn't complain about not knowing which - // object file to include the vtable in - AstNode(AstNode&&) = default; + virtual ~AstNode(); + AstNode(AstNode&&) = default; AstNode& operator=(AstNode&&) = default; AstNode(const AstNode&) = default; - AstNode& operator=(const AstNode&) = default; +}; +template +struct EnumNode: public AstNode +{ + EnumNode() = default; + explicit EnumNode(T value): value(value) {} + + T value; }; struct StringNode: public AstNode { std::string value; - std::string asString() { - return value.substr(1, value.length() - 2); - } + std::string asString(); }; struct IdentifierNode: public AstNode @@ -43,7 +46,7 @@ struct IdentifierNode: public AstNode struct NumberNode: public AstNode { long long int value; - NumberNode(std::string expression); + explicit NumberNode(const std::string& expression); NumberNode(): value(0) {} }; @@ -54,7 +57,7 @@ struct CountNode: public AstNode NumberNode second; CountNode(NumberNode first, NumberNode second): first(first), second(second) {} - CountNode() {} + CountNode() = default; }; @@ -65,7 +68,6 @@ struct AddressSpaceNode: public AstNode NumberNode end; }; - class ValueNode: public AstNode { public: @@ -78,89 +80,32 @@ public: NIL, }; - private: - ValueType type; + EnumNode type; std::optional intValue; std::optional stringValue; std::optional boolValue; std::optional identifierValue; public: - ValueNode() {}; + ValueNode() = default;; ValueType getType() { - return type; - } - long long asInt() { - if(is(INT)) { - return intValue.value(); - } - throw "cannot convert type to int"; - } - std::string asString() { - if(is(STRING)) { - return stringValue.value(); - } - throw "cannot convert type to string"; - } - std::string asIdentifier() { - if(is(IDENTIFIER) || is(WIRE)) { - return identifierValue.value(); - } - throw "cannot convert type to identifier"; - } - bool asBool() { - if(is(BOOL)) { - return boolValue.value(); - } - throw "cannot convert type to bool"; + return type.value; } + long long asInt(); + std::string asString(); + std::string asIdentifier(); + bool asBool(); - bool is(ValueType type) { - return this->type == type; - } + bool is(ValueType valueType); - static ValueNode ofBool(bool _value) { - ValueNode value; - value.type = BOOL; - value.boolValue = std::optional(_value); - return value; - } - - static ValueNode ofInt(long long _value) { - ValueNode value; - value.type = INT; - value.intValue = std::optional(_value); - return value; - } - - static ValueNode ofString(std::string _value) { - ValueNode value; - value.type = STRING; - value.stringValue = std::optional(_value); - return value; - } - - static ValueNode ofIdentifier(std::string _value) { - ValueNode value; - value.type = IDENTIFIER; - value.identifierValue = std::optional(_value); - return value; - } - - static ValueNode ofNull() { - ValueNode value; - value.type = NIL; - return value; - } - - static ValueNode ofWire(std::string _value) { - ValueNode value; - value.type = WIRE; - value.identifierValue = std::optional(_value); - return value; - } + static ValueNode ofBool(bool _value); + static ValueNode ofInt(long long _value); + static ValueNode ofString(std::string _value); + static ValueNode ofIdentifier(std::string _value); + static ValueNode ofNull(); + static ValueNode ofWire(std::string _value); }; struct ConditionNode @@ -177,7 +122,7 @@ public: WARNING }; - ActionType type; + EnumNode type; StringNode message; }; @@ -188,14 +133,11 @@ struct IfStatementNode: public AstNode ActionNode action; }; - struct RuleNode: public AstNode { std::vector statements; }; - - struct EnumerationNode: public AstNode { StringNode key; @@ -209,7 +151,7 @@ struct PopupNode: public AstNode ON_DEMAND }; - std::optional type; + std::optional> type; std::optional title; std::optional text; @@ -225,20 +167,17 @@ struct PropertyNode: public AstNode ValueNode value; }; - struct DisplayItemNode: public AstNode { IdentifierNode type; std::vector values; }; - struct DisplayNode: public AstNode { std::vector items; }; - struct PinConnectionNode: public AstNode { enum ConnectionType { @@ -247,10 +186,9 @@ struct PinConnectionNode: public AstNode }; StringNode message; - ConnectionType type; + EnumNode type; }; - struct PinNode: public AstNode { enum PinType { @@ -260,14 +198,13 @@ struct PinNode: public AstNode }; IdentifierNode name; - PinType type; + EnumNode type; std::optional tooltip; std::optional connection; std::optional display; std::optional> wires; }; - struct WireNode: public AstNode { enum WireType { @@ -276,17 +213,16 @@ struct WireNode: public AstNode WIRED_OR, R_WIRE }; - WireType type; + EnumNode type; IdentifierNode name; NumberNode size; bool hidden; - bool hasTermination; - long long isUnterminated; + bool hasTerminateWith; + ValueNode terminateWith; }; - struct AttributeNode: public AstNode { ValueNode::ValueType type; @@ -324,7 +260,7 @@ struct ComponentNode: public AstNode IdentifierNode name; std::optional tooltip; std::optional source; - ComponentType type; + EnumNode type; std::vector rules; std::optional instanceName; std::optional count; @@ -333,7 +269,6 @@ struct ComponentNode: public AstNode std::vector attributes; }; - struct BusNode: public AstNode { enum BusType { @@ -341,7 +276,7 @@ struct BusNode: public AstNode REGULAR }; - BusType type; + EnumNode type; IdentifierNode name; std::optional tooltip; std::optional count; @@ -367,8 +302,6 @@ struct LibraryNode: public AstNode }; // SCHEMA models - - struct WireInstanceNode: public AstNode { IdentifierNode name; @@ -393,7 +326,8 @@ struct InstanceNode: public AstNode std::optional size; }; -struct ConnectionComponentInstance { +struct ConnectionComponentInstance: public AstNode +{ IdentifierNode instance; IdentifierNode pin; }; diff --git a/comdel/parser/comdelparser.cpp b/comdel/parser/comdelparser.cpp index 197a1e9..13e4eb7 100644 --- a/comdel/parser/comdelparser.cpp +++ b/comdel/parser/comdelparser.cpp @@ -409,15 +409,7 @@ PResult ComdelParser::parseComponent() ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier()); - if(check(TokenType::CT_PROCESSOR)) { - bump(); - component.type = ComponentNode::PROCESSOR; - } else if(check(TokenType::CT_MEMORY)) { - bump(); - component.type = ComponentNode::MEMORY; - } else { - component.type = ComponentNode::OTHER; - } + auto type = parseComponentType(); RETURN_IF_NOT_TOKEN(TokenType::LBRACE); @@ -452,6 +444,23 @@ PResult ComdelParser::parseComponent() return spanner(component); } +PResult> ComdelParser::parseComponentType() { + EnumNode type; + + auto spanner = getSpanner(); + + if(check(TokenType::CT_PROCESSOR)) { + bump(); + type = EnumNode(ComponentNode::PROCESSOR); + } else if(check(TokenType::CT_MEMORY)) { + bump(); + type = EnumNode(ComponentNode::MEMORY); + } else { + type = EnumNode(ComponentNode::OTHER); + } + return spanner(type); +} + /**************************************************************************** * @@ -509,18 +518,10 @@ PResult ComdelParser::parseBus() { ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier()); - if(check(TokenType::IDENTIFIER)) { - auto tokenType = parseIdentifier(); - if(tokenType.value().value == "automatic") { - bus.type = BusNode::AUTOMATIC; - } else if(tokenType.value().value == "regular") { - bus.type = BusNode::REGULAR; - } else { - return PError(SourceError{current().span, "expected 'automatic' or 'regular'"}); - } - } else { - return PError(SourceError{current().span, "expected 'automatic' or 'regular'"}); - } + auto type = parseBusType(); + RETURN_IF_ERR(type); + + bus.type = *type; RETURN_IF_NOT_TOKEN(TokenType::LBRACE); @@ -553,10 +554,28 @@ PResult ComdelParser::parseBus() { return spanner(bus); } +PResult> ComdelParser::parseBusType() { + PResult> type; + + if(check(TokenType::IDENTIFIER)) { + auto tokenType = parseIdentifier(); + if(tokenType.value().value == "automatic") { + type = EnumNode(BusNode::AUTOMATIC); + } else if(tokenType.value().value == "regular") { + type = EnumNode(BusNode::REGULAR); + } else { + type = PError(SourceError{current().span, "expected 'automatic' or 'regular'"}); + } + } else { + type = PError(SourceError{current().span, "expected 'automatic' or 'regular'"}); + } + return type; +} + /**************************************************************************** * -* WireNode := NAME(){0,1} TYPE)* +* WireNode := NAME(){0,1} TYPE [hidden | terminated_with (#number | null)])* * ****************************************************************************/ PResult ComdelParser::parseWire() { @@ -574,20 +593,42 @@ PResult ComdelParser::parseWire() { } // default - wire.type = WireNode::WIRE; + wire.type = EnumNode(WireNode::WIRE); if(check(TokenType::WIRE_DEFAULT)) { bump(); - wire.type = WireNode::WIRE; + wire.type = EnumNode(WireNode::WIRE); } else if(check(TokenType::WIRE_AND)) { bump(); - wire.type = WireNode::WIRED_AND; + wire.type = EnumNode(WireNode::WIRED_AND); } else if(check(TokenType::WIRE_OR)) { bump(); - wire.type = WireNode::WIRED_OR; + wire.type = EnumNode(WireNode::WIRED_OR); } else if(check(TokenType::R_WIRE)) { bump(); - wire.type = WireNode::R_WIRE; + wire.type = EnumNode(WireNode::R_WIRE); + } + + while(true) { + if(check(TokenType::HIDDEN)) { + bump(); + wire.hidden = true; + } else if(check(TokenType::TERMINATE_WITH)) { + bump(); + wire.hasTerminateWith = true; + if(check(TokenType::NIL)) { + bump(); + wire.terminateWith = ValueNode::ofNull(); + } else if(check(TokenType::NUMBER)) { + auto number = parseNumber(); + wire.terminateWith = ValueNode::ofInt(number->value); + } else { + auto token = current(); + return PError(SourceError{token.span, "unexpected token"}); + } + } else { + break; + } } return spanner(wire); @@ -613,13 +654,13 @@ PResult ComdelParser::parsePin() { if(check(TokenType::PIN_IN)) { bump(); - pin.type = PinNode::IN; + pin.type = EnumNode(PinNode::IN); } else if(check(TokenType::PIN_OUT)) { bump(); - pin.type = PinNode::OUT; + pin.type = EnumNode(PinNode::OUT); } else if(check(TokenType::PIN_IN_OUT)) { bump(); - pin.type = PinNode::IN_OUT; + pin.type = EnumNode(PinNode::IN_OUT); } else { return unexpected(); } @@ -662,18 +703,7 @@ PResult ComdelParser::parsePinConnection() { RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); - if(check(TokenType::IDENTIFIER)) { - auto type = parseIdentifier(); - if(type.value().value == "check_only") { - connection.type = PinConnectionNode::CHECK_ONLY; - } else if(type.value().value == "automatically") { - connection.type = PinConnectionNode::AUTOMATICALLY; - } else { - return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); - } - } else { - return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); - } + ASSIGN_OR_RETURN_IF_ERR(connection.type, parseConnectionType()); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); ASSIGN_OR_RETURN_IF_ERR(connection.message, parseString()); @@ -682,6 +712,26 @@ PResult ComdelParser::parsePinConnection() { return spanner(connection); } +PResult> ComdelParser::parseConnectionType() { + auto spanner = getSpanner(); + + EnumNode type; + + if(check(TokenType::IDENTIFIER)) { + auto identifier = parseIdentifier(); + if(identifier.value().value == "check_only") { + type = EnumNode(PinConnectionNode::CHECK_ONLY); + } else if(identifier.value().value == "automatically") { + type = EnumNode(PinConnectionNode::AUTOMATICALLY); + } else { + return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); + } + } else { + return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); + } + + return spanner(type); +} /**************************************************************************** * @@ -808,16 +858,16 @@ PResult ComdelParser::parsePopup() { RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP); if(check(TokenType::IDENTIFIER)) { - auto type = parseIdentifier(); - if(type.value().value == "automatic") { - popup.type = PopupNode::AUTOMATIC; - } else if(type.value().value == "on_demand") { - popup.type = PopupNode::ON_DEMAND; + auto identifier = parseIdentifier(); + if(identifier.value().value == "automatic") { + popup.type = EnumNode(PopupNode::AUTOMATIC); + } else if(identifier.value().value == "on_demand") { + popup.type = EnumNode(PopupNode::ON_DEMAND); } else { return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"}); } } else { - popup.type = PopupNode::ON_DEMAND; + popup.type = EnumNode(PopupNode::ON_DEMAND); } RETURN_IF_NOT_TOKEN(TokenType::LBRACE); @@ -975,9 +1025,9 @@ PResult ComdelParser::parseIfStatement() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); if(check(TokenType::ERROR)) { - ifStatement.action.type = ActionNode::ERROR; + ifStatement.action.type = EnumNode(ActionNode::ERROR); } else if(check(TokenType::WARNING)) { - ifStatement.action.type = ActionNode::WARNING; + ifStatement.action.type = EnumNode(ActionNode::WARNING); } else { return unexpected(); } @@ -1029,21 +1079,21 @@ std::optional ComdelParser::parseSchema() { auto source = parseString(); schema.source = *source; } else { - errors.push_back(SourceError{current().span, "expected `@source`"}); + errors.emplace_back(current().span, "expected `@source`"); return std::nullopt; } } else { - errors.push_back(SourceError{current().span, "expected `@source`"}); + errors.emplace_back(current().span, "expected `@source`"); return std::nullopt; } if(!check(TokenType::KW_SCHEMA)) { - errors.push_back(SourceError{current().span, "expected `@schema`"}); + errors.emplace_back(current().span, "expected `@schema`"); return std::nullopt; } bump(); if(!check(TokenType::LBRACE)) { - errors.push_back(SourceError{current().span, "expected `{`"}); + errors.emplace_back(current().span, "expected `{`"); return std::nullopt; } bump(); @@ -1065,14 +1115,14 @@ std::optional ComdelParser::parseSchema() { } } if(!check(TokenType::RBRACE)) { - errors.push_back(SourceError{current().span, "expected `}`"}); + errors.emplace_back(current().span, "expected `}`"); return std::nullopt; } else { bump(); } if(!check(TokenType::END_OF_FILE)) { - errors.push_back(SourceError{current().span, "expected `EOF`"}); + errors.emplace_back(current().span, "expected `EOF`"); } if (errors.size()) diff --git a/comdel/parser/comdelparser.h b/comdel/parser/comdelparser.h index 25f4d3f..55f95f5 100644 --- a/comdel/parser/comdelparser.h +++ b/comdel/parser/comdelparser.h @@ -97,6 +97,12 @@ public: std::optional parseSchema(); std::optional parse(); const std::vector& getErrors(); + + PResult> parseComponentType(); + + PResult> parseBusType(); + + PResult> parseConnectionType(); }; #endif // COMDEL_PARSER_H diff --git a/comdel/parser/parser_util.cpp b/comdel/parser/parser_util.cpp deleted file mode 100644 index b87e3c8..0000000 --- a/comdel/parser/parser_util.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "parser_util.h" - -parser_util::parser_util() -{ - -} diff --git a/comdel/parser/parser_util.h b/comdel/parser/parser_util.h deleted file mode 100644 index c158f46..0000000 --- a/comdel/parser/parser_util.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef PARSER_UTIL_H -#define PARSER_UTIL_H - - -class parser_util -{ -public: - parser_util(); -}; - -#endif // PARSER_UTIL_H diff --git a/comdel/parser/token.h b/comdel/parser/token.h index 03023e7..29ab5f9 100644 --- a/comdel/parser/token.h +++ b/comdel/parser/token.h @@ -124,6 +124,10 @@ enum class TokenType { ERROR, WARNING, + // WIRE SETTINGS + HIDDEN, + TERMINATE_WITH, + // OTHER END_OF_FILE }; diff --git a/comdel/parser/tokenstype.cpp b/comdel/parser/tokenstype.cpp index 458b4eb..3134bdc 100644 --- a/comdel/parser/tokenstype.cpp +++ b/comdel/parser/tokenstype.cpp @@ -134,10 +134,10 @@ TokenTables::TokenTables() { add( TokenType::WARNING, "warning", TOKENIZABLE), - // Built-in functions (they are also keywords) - /* - * TODO - */ + // WireNode settings types + add( TokenType::HIDDEN, "hidden", TOKENIZABLE), + add( TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE), + // Miscelaneous add( TokenType::END_OF_FILE, "eof" ); } diff --git a/examples/simplified FRISC model/schema2.csl b/examples/simplified FRISC model/schema2.csl new file mode 100644 index 0000000..82346d4 --- /dev/null +++ b/examples/simplified FRISC model/schema2.csl @@ -0,0 +1,34 @@ +@source "frisc_library.csl" + +@schema { + @instance proc FRISC { + @position (0, 0) + } + + @instance mem Memorija { + @position (0, 250) + @attribute kapacitet 1024 + @attribute size 8 + @attribute pocetnaAdresa 1023 + } + + @instance bus glavnaSabirnica { + @position (0, 200) + @size 100 + } + + @wire wire_001 { + @position (50, 116) + @display {} + } + @wire wire_002 { + @position (50, 220) + @display {} + } + @connection (proc.glavniPin, bus) { + @wire wire_001 + } + @connection (mem.glavniPin, bus) { + @wire wire_002 + } +} diff --git a/mainwindow.cpp b/mainwindow.cpp index 94e3bc3..3926463 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -35,6 +36,7 @@ void MainWindow::setupUi() // setup toolbar ui->toolBar->addAction("Load library", this, &MainWindow::onLoadLibrary); ui->toolBar->addAction("Load schema", this, &MainWindow::onLoadSchema); + ui->toolBar->addAction("Save schema", this, &MainWindow::onStoreScheme); connect(ui->actionValidate, &QAction::triggered, this, &MainWindow::onValidateSchema); @@ -68,6 +70,8 @@ void MainWindow::onLoadLibrary() { log->clear(); if(!filename.isEmpty()) { + librarySource = filename.toStdString(); + clear(); ParseContext parseContext; @@ -77,7 +81,7 @@ void MainWindow::onLoadLibrary() { library = generator.loadLibrary(*libraryNode); for (auto& error : generator.getErrors()) { - parseContext.formatError(error, std::cout, "ERROR: "); + parseContext.formatError(error, buffer, "ERROR: "); } if(generator.getErrors().empty()) { @@ -89,7 +93,7 @@ void MainWindow::onLoadLibrary() { } } else { - std::cout<<"Bad request"<library); + librarySource = schemaNode->source->value; + for (auto& error : generator.getErrors()) { - parseContext.formatError(error, std::cout, "ERROR: "); + parseContext.formatError(error, buffer, "ERROR: "); } if(library) { schema = generator.loadSchema(*schemaNode, *library); for (auto& error : generator.getErrors()) { - parseContext.formatError(error, std::cout, "ERROR: "); + parseContext.formatError(error, buffer, "ERROR: "); } } @@ -136,6 +142,67 @@ void MainWindow::onLoadSchema() { log->appendPlainText(QString::fromStdString(buffer.str())); } +void MainWindow::onStoreScheme() { + if(schema == nullptr) { + return; + } + + auto filename = QFileDialog::getSaveFileName(this, + tr("Save schema"), "/home", tr("Comdel schema (*.csl)")); + + std::ostringstream buffer; + + buffer << "@source " << this->librarySource << std::endl << std::endl; + + buffer << "@schema {" << std::endl; + + for(auto &instance: schema->instances) { + auto componentInstance = dynamic_cast(instance); + if(componentInstance != NULL) { + buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() << " {" << std::endl; + buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " << componentInstance->position.second << ")" << std::endl; + + for(auto &attribute: instance->attributes) { + buffer << "\t\t" << "@attribute " << attribute->name << " " << attribute->value.stringify() << std::endl; + } + + buffer << "\t}" << std::endl << std::endl; + } + + auto busInstance = dynamic_cast(instance); + if(busInstance != NULL) { + buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {" << std::endl; + buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second << ")" << std::endl; + buffer << "\t\t" << "@size " << busInstance->size << std::endl; + buffer << "\t}" << std::endl << std::endl; + } + } + + for(auto &wire: schema->wires) { + buffer << "\t" << "@wire " << wire->name << " {" << std::endl; + buffer << "\t\t" << "@position (" << wire->position.first << ", " << wire->position.second << ")" << std::endl; + buffer << "\t\t" << "@display {}" << std::endl; + buffer << "\t" << "}" << std::endl; + } + + for(auto &conn: schema->connections) { + auto busConn = dynamic_cast(conn); + if(busConn) { + buffer << "\t" << "@connection (" << busConn->instance->name << "." << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl; + buffer << "\t\t"<< "@wire " << busConn->wire->name << std::endl; + buffer << "\t" << "}" << std::endl; + } + } + + buffer << "}" << std::endl; + + auto value = buffer.str(); + + std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); + out< validationErrors;