Skip to content

Commit

Permalink
Merge pull request #434 from NikitaZotov/feat/skip_generating_type_arcs
Browse files Browse the repository at this point in the history
[memory][scs][parser] Don't generate arcs from sc-element classes
  • Loading branch information
NikitaZotov authored Jan 17, 2025
2 parents 4e06e5b + 4ec0854 commit 5b4a3d0
Show file tree
Hide file tree
Showing 23 changed files with 1,291 additions and 874 deletions.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ See documentation, to learn more about using new API.

### Changed

- SCsParser no longer generates sc-arcs from types of sc-elements to sc-elements
- Allow multiple instances of `ScLogger` class
- Rename `ScLog` to `ScLogger`
- Description of project in Readme
Expand Down
31 changes: 24 additions & 7 deletions sc-memory/sc-memory/include/sc-memory/scs/scs_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <stack>
#include <map>
#include <string>
#include <functional>
#include <unordered_set>

namespace scs
{
Expand Down Expand Up @@ -44,6 +46,7 @@ class ParsedElement
_SC_EXTERN ScType const & GetType() const;

_SC_EXTERN Visibility GetVisibility() const;
_SC_EXTERN bool IsElementType() const;

_SC_EXTERN std::string const & GetValue() const;

Expand All @@ -60,29 +63,33 @@ class ParsedElement
bool m_isReversed : 1; // flag used just for an connectors
std::string m_value; // string representation of content/link value
bool m_isURL : 1; // flag used to determine if ScLink value is an URL
bool m_isElementType; // flag denoting whether the element is an sc-element, denoting the type of sc-elements
};

class ElementHandle
{
public:
_SC_EXTERN explicit ElementHandle(ElementID id);
_SC_EXTERN ElementHandle();
_SC_EXTERN ElementHandle(ElementID id, bool isLocal);
_SC_EXTERN ElementHandle(ElementID id, Visibility visibility, bool IsElementType = false);
_SC_EXTERN ElementHandle(ElementHandle const & other) = default;

_SC_EXTERN ElementID operator*() const;
_SC_EXTERN Visibility GetVisibility() const;
_SC_EXTERN bool IsLocal() const;
_SC_EXTERN bool IsElementType() const;
_SC_EXTERN bool IsValid() const;
_SC_EXTERN bool operator==(ElementHandle const & other) const;
_SC_EXTERN bool operator!=(ElementHandle const & other) const;
_SC_EXTERN ElementHandle & operator=(ElementHandle const & other);
_SC_EXTERN bool operator<(ElementHandle const & other) const;

private:
static const ElementID INVALID_ID = std::numeric_limits<ElementID>::max();
static ElementID const INVALID_ID = std::numeric_limits<ElementID>::max();

ElementID m_id;
bool m_isLocal;
Visibility m_visibility;
bool m_isElementType;
};

struct ParsedTriple
Expand All @@ -104,7 +111,7 @@ class Parser
friend class scsParser;

// Number of parsed elements, to preallocate container
static const size_t PARSED_PREALLOC_NUM = 1024;
static size_t const PARSED_PREALLOC_NUM = 1024;

public:
using TripleVector = std::vector<ParsedTriple>;
Expand All @@ -115,8 +122,10 @@ class Parser
_SC_EXTERN Parser();

_SC_EXTERN bool Parse(std::string const & str);
_SC_EXTERN ParsedElement const & GetParsedElement(ElementHandle const & elID) const;
_SC_EXTERN ParsedElement const & GetParsedElement(ElementHandle const & handle) const;
_SC_EXTERN TripleVector const & GetParsedTriples() const;
_SC_EXTERN void ForEachTripleForGeneration(
std::function<void(ParsedElement const &, ParsedElement const &, ParsedElement const &)> const & callback) const;
_SC_EXTERN std::string const & GetParseError() const;
_SC_EXTERN AliasHandles const & GetAliases() const;

Expand All @@ -130,8 +139,9 @@ class Parser
}

protected:
ParsedElement & GetParsedElementRef(ElementHandle const & elID);
ParsedElement & GetParsedElementRef(ElementHandle const & handle);

bool IsElementTypeOutgoingBaseArc(ParsedElement const & element) const;
ElementHandle ResolveAlias(std::string const & name);
ElementHandle ProcessIdentifier(std::string const & name);
ElementHandle ProcessIdentifierLevel1(std::string const & type, std::string const & name);
Expand All @@ -144,10 +154,15 @@ class Parser
void ProcessContourBegin();
void ProcessContourEnd(ElementHandle const & contourHandle);

void ProcessTriple(ElementHandle const & source, ElementHandle const & connector, ElementHandle const & target);
void ProcessTriple(
ElementHandle const & sourceHandle,
ElementHandle const & connectorHandle,
ElementHandle const & targetHandle);
void ProcessAssign(std::string const & alias, ElementHandle const & value);

private:
ParsedElementVector & GetContainerByElementVisibilityRef(Visibility visibility);
ParsedElementVector const & GetContainerByElementVisibility(Visibility visibility) const;
ElementHandle AppendElement(
std::string idtf,
ScType const & type = ScType::Unknown,
Expand All @@ -169,6 +184,8 @@ class Parser
TripleVector m_parsedTriples;
IdtfToParsedElementMap m_idtfToParsedElement;
AliasHandles m_aliasHandles;
std::unordered_set<std::string> m_elementTypeOutgoingBaseArcs;
std::multimap<std::string, ElementHandle> m_elementTypeNotOutgoingBaseArcsToElementTypes;

std::string m_lastError;

Expand Down
4 changes: 2 additions & 2 deletions sc-memory/sc-memory/include/sc-memory/scs/scs_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ class TypeResolver final
static std::string GetSCsElementKeynode(ScType const & type);

static ScType const & GetConnectorType(std::string const & connectorAlias);
static ScType const & GetKeynodeType(std::string const & keynodeAlias);
static ScType const & GetElementType(std::string const & keynodeAlias);

static bool IsConnectorReversed(std::string const & connectorAlias);
static bool IsConst(std::string const & idtf);
static bool IsConnectorAttrConst(std::string const & attr);
static bool IsKeynodeType(std::string const & alias);
static bool IsElementType(std::string const & alias);
static bool IsUnnamed(std::string const & alias);

protected:
Expand Down
69 changes: 41 additions & 28 deletions sc-memory/sc-memory/src/sc_scs_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,38 @@ class StructGenerator
}

// generate triples
auto const & triples = parser.GetParsedTriples();
for (auto const & t : triples)
{
auto const & src = parser.GetParsedElement(t.m_source);
auto const & connector = parser.GetParsedElement(t.m_connector);
auto const & trg = parser.GetParsedElement(t.m_target);

auto const & srcAddrResult = ResolveElement(src);
auto const & trgAddrResult = ResolveElement(trg);
std::unordered_set<std::string> typeArcsCache;
parser.ForEachTripleForGeneration(
[&](scs::ParsedElement const & source,
scs::ParsedElement const & connector,
scs::ParsedElement const & target) -> void
{
auto const & sourceResult = ResolveElement(source);
auto const & targetResult = ResolveElement(target);

if (!connector.GetType().IsConnector())
SC_THROW_EXCEPTION(utils::ExceptionInvalidType, "Specified sc-connector in triple has incorrect type.");
ScType const & connectorType = connector.GetType();
std::string const & connectorIdtf = connector.GetIdtf();
if (!connectorType.IsConnector())
SC_THROW_EXCEPTION(
utils::ExceptionInvalidType,
"Specified in triple sc-connector `" << connectorIdtf << "` has incorrect type `"
<< std::string(connectorType) << "`.");

ScAddr const arcAddr = m_ctx.GenerateConnector(connector.GetType(), srcAddrResult.first, trgAddrResult.first);
m_idtfCache.insert({connector.GetIdtf(), arcAddr});
ScAddr const connectorAddr = m_ctx.GenerateConnector(connectorType, sourceResult.first, targetResult.first);
m_idtfCache.insert({connectorIdtf, connectorAddr});

if (m_outputStructure.IsValid())
{
AppendToOutputStructure(srcAddrResult.first, arcAddr, trgAddrResult.first);
AppendToOutputStructure(srcAddrResult.second);
AppendToOutputStructure(trgAddrResult.second);
}
}
if (m_outputStructure.IsValid())
{
AppendToOutputStructure(sourceResult.first, connectorAddr, targetResult.first);
AppendToOutputStructure(sourceResult.second);
AppendToOutputStructure(targetResult.second);
}
});

parser.ForEachParsedElement(
[this](scs::ParsedElement const & el)
{
if (m_idtfCache.find(el.GetIdtf()) == m_idtfCache.end() && !el.GetType().IsConnector()
&& !scs::TypeResolver::IsKeynodeType(el.GetIdtf()))
if (m_idtfCache.find(el.GetIdtf()) == m_idtfCache.cend() && !el.GetType().IsConnector())
ResolveElement(el);
});
}
Expand Down Expand Up @@ -160,14 +163,21 @@ class StructGenerator
{
if (type.IsLink())
{
// TODO(NikitaZotov): Throw exception if this sc-link is a sc-link with system identifier of sc-element
// denoting sc-elements type, and type of sc-element, for which this sc-link is specified as a system
// identifier, can't be extended to ScType::ConstNodeClass. See
// SCsHelperTest.GenerateBySCs_ContourWithExplicitlySpecifiedElementTypeSystemIdentifier.
resultAddr = m_ctx.GenerateLink(type);
SetupLinkContent(resultAddr, el);
}
else
resultAddr = m_ctx.GenerateNode(type);
}
else
SC_THROW_EXCEPTION(utils::ExceptionInvalidState, "Incorrect element type at this state.");
SC_THROW_EXCEPTION(
utils::ExceptionInvalidState,
"Element `" << el.GetIdtf() << "` can't be resolved, because it has not sc-node type `"
<< std::string(type) << "`.");

// setup system identifier
if (el.GetVisibility() == scs::Visibility::System)
Expand All @@ -177,9 +187,7 @@ class StructGenerator
result = {quintuple.addr2, quintuple.addr3, quintuple.addr4, quintuple.addr5};
}
else if (el.GetVisibility() == scs::Visibility::Global)
{
result = SetSCsGlobalIdtf(el.GetIdtf(), resultAddr);
}
}
else
{
Expand All @@ -190,12 +198,15 @@ class StructGenerator
if (oldType.CanExtendTo(newType))
m_ctx.SetElementSubtype(resultAddr, newType);
else if (!newType.CanExtendTo(oldType))
SC_THROW_EXCEPTION(utils::ExceptionInvalidType, "Duplicate element type for " + el.GetIdtf());
SC_THROW_EXCEPTION(
utils::ExceptionInvalidType,
"Can't extend type `" << std::string(oldType) << "` to type `" << std::string(newType)
<< "` for element `" << el.GetIdtf() << "`.");
}
}

// anyway save in cache
m_idtfCache.insert(std::make_pair(idtf, resultAddr));
m_idtfCache.insert({idtf, resultAddr});
}

return {resultAddr, result};
Expand Down Expand Up @@ -232,7 +243,8 @@ class StructGenerator
{
// check if it's a number format
std::regex const rNumber(
"^\\^\"(int8|int16|int32|int64|uint8|uint16|uint32|uint64|float|double)\\s*:\\s*([0-9]+|[0-9]+[.][0-9]+)\"$");
"^\\^\"(int8|int16|int32|int64|uint8|uint16|uint32|uint64|float|double)\\s*:\\s*([0-9]+|[0-9]+[.][0-9]+)"
"\"$");
std::smatch result;
if (std::regex_match(el.GetValue(), result, rNumber))
{
Expand Down Expand Up @@ -289,6 +301,7 @@ class StructGenerator
SCsHelper::SCsHelper(ScMemoryContext & ctx, SCsFileInterfacePtr fileInterface)
: m_ctx(ctx)
, m_fileInterface(std::move(fileInterface))

{
}

Expand Down
48 changes: 18 additions & 30 deletions sc-memory/sc-memory/src/sc_template_scs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,56 +36,44 @@ class ScTemplateBuilderFromScs
utils::ScKeynodeCache keynodes(m_ctx);
std::unordered_set<std::string> passed;

auto const MakeTemplItem = [&passed, &keynodes](scs::ParsedElement const & el, ScTemplateItem & outValue) -> bool
auto const MakeTemplItem = [&passed, &keynodes](scs::ParsedElement const & el, ScTemplateItem & outValue) -> void
{
std::string const & idtf = el.GetIdtf();
bool const isUnnamed = scs::TypeResolver::IsUnnamed(idtf);
bool const isPassed = passed.find(idtf) != passed.cend();

if (!isUnnamed && isPassed)
{
outValue.SetReplacement(idtf.c_str());
}
else
{
sc_char const * alias = (isUnnamed ? nullptr : idtf.c_str());
sc_char const * alias = isUnnamed ? nullptr : idtf.c_str();
ScAddr const addr = keynodes.GetKeynode(idtf);
if (addr.IsValid())
{
outValue.SetAddr(addr, alias);
}
else if (el.GetType().IsVar())
outValue.SetType(el.GetType(), alias);
else
{
if (el.GetType().IsVar())
{
outValue.SetType(el.GetType(), alias);
}
else
{
SC_THROW_EXCEPTION(utils::ExceptionInvalidState, "Can't find element " << idtf);
return false;
}
}
SC_THROW_EXCEPTION(
utils::ExceptionInvalidState,
"Specified element with system identifier `" << idtf << "` can't be found.");
}

passed.insert(idtf);

return true;
};

for (scs::ParsedTriple const & t : m_parser.GetParsedTriples())
{
scs::ParsedElement const & src = m_parser.GetParsedElement(t.m_source);
scs::ParsedElement const & connector = m_parser.GetParsedElement(t.m_connector);
scs::ParsedElement const & trg = m_parser.GetParsedElement(t.m_target);

ScTemplateItem srcItem, connectorItem, trgItem;
m_parser.ForEachTripleForGeneration(
[&](scs::ParsedElement const & source,
scs::ParsedElement const & connector,
scs::ParsedElement const & target) -> void
{
ScTemplateItem sourceItem, connectorItem, targetItem;

if (!MakeTemplItem(src, srcItem) || !MakeTemplItem(connector, connectorItem) || !MakeTemplItem(trg, trgItem))
break;
MakeTemplItem(source, sourceItem);
MakeTemplItem(connector, connectorItem);
MakeTemplItem(target, targetItem);

templ->Triple(srcItem, connectorItem, trgItem);
}
templ->Triple(sourceItem, connectorItem, targetItem);
});
}

private:
Expand Down
6 changes: 1 addition & 5 deletions sc-memory/sc-memory/src/scs/scs.g4
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,7 @@ idtf_set_elements [std::string setType]
locals [ElementHandle prevArc]
: {
std::string const setIdtf = "..set_" + std::to_string($ctx->start->getLine()) + "_" + std::to_string($ctx->start->getCharPositionInLine());
$ctx->handle = m_parser->ProcessIdentifier(setIdtf);
ElementHandle const typeArc = m_parser->ProcessConnector("->");
ElementHandle const typeClass = m_parser->ProcessIdentifier("sc_node_tuple");
m_parser->ProcessTriple(typeClass, typeArc, $ctx->handle);
$ctx->handle = m_parser->ProcessIdentifierLevel1("sc_node_tuple", setIdtf);
}
a1=attr_list? i1=idtf_common
{
Expand Down
Loading

0 comments on commit 5b4a3d0

Please sign in to comment.