Skip to content
Snippets Groups Projects
Commit 483dcace authored by vincent  lorrain's avatar vincent lorrain
Browse files

[graphRegex] init commit

parent 1b19726b
No related branches found
No related tags found
1 merge request!14Graph regex
Pipeline #31481 failed
Showing
with 1952 additions and 0 deletions
#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"
using namespace Aidge;
FsmGraph::FsmGraph(/* args */){
}
//TODO
std::vector<std::shared_ptr<MatchResult>> FsmGraph::test(std::vector<NodePtr>& startNodes){
std::vector<std::shared_ptr<Aidge::FsmNode>> startNodesFsm = getStartNodes();
if(startNodes.size() != startNodesFsm.size()){
throw std::runtime_error("bad number of Start nodes");
}
std::vector<std::shared_ptr<FsmRunTimeContext>> walks;
for(std::size_t i = 0; i < startNodes.size(); i++){
walks.push_back(std::make_shared<FsmRunTimeContext>(startNodesFsm[i],startNodes[i]));
}
std::vector<std::shared_ptr<FsmRunTimeContext>> allValidContext;
while (!walks.empty())
{
std::vector<std::shared_ptr<FsmRunTimeContext>> nextWalks;
for(auto fsmContext : walks){
//if we are in a valid st we save it
//it's one solution of the posible solution of the matching
if(fsmContext->isOnValidState()){
//TODO not push same fsm use are_equal
allValidContext.push_back(fsmContext);
}
std::vector<std::shared_ptr<FsmRunTimeContext>> tmpNextWalks = fsmContext->getActState()->test(fsmContext);
}
}
}
const std::set<std::shared_ptr<FsmEdge>>& FsmGraph::getEdge(void){
return mEdges;
}
void FsmGraph::addEdge(std::shared_ptr<FsmEdge> edge){
mEdges.insert(edge);
mAllOrigine.insert(edge->getDestNode()->getOrigine());
mAllOrigine.insert(edge->getSourceNode()->getOrigine());
}
const std::vector<std::shared_ptr<FsmNode>> FsmGraph::getStartNodes(void){
std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
std::vector<std::shared_ptr<FsmNode>> startNodes;
for(auto node :nodes){
if(node->isStart()){
startNodes.push_back(node);
}
}
return startNodes;
}
const std::set<std::shared_ptr<FsmNode>> FsmGraph::getValidNodes(void){
std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
std::set<std::shared_ptr<FsmNode>> ValidNodes;
for(auto node :nodes){
if(node->isValid()){
ValidNodes.insert(node);
}
}
//may short
return ValidNodes;
}
const std::set<std::shared_ptr<FsmNode>> FsmGraph::getNodes(void){
std::set<std::shared_ptr<FsmNode>> nodes;
for(auto edge : mEdges){
nodes.insert(edge->getDestNode());
nodes.insert(edge->getSourceNode());
}
return nodes;
}
void FsmGraph::setGroupe(std::size_t groupeIdx){
std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
for(auto node :nodes){
node->setGroupe(groupeIdx);
}
}
void FsmGraph::unionG(const std::shared_ptr<FsmGraph> fsmGraph){
for(auto edge : fsmGraph->getEdge()){
addEdge(edge);
}
}
void FsmGraph::mergeOneStartOneValid(const std::shared_ptr<FsmGraph> fsmGraph){
std::set<std::shared_ptr<FsmNode>> validNodes = getValidNodes();
std::vector<std::shared_ptr<FsmNode>> startNodes = fsmGraph->getStartNodes();
if (startNodes.size() != 1 || validNodes.size() != 1){
std::ostringstream errorMessage;
errorMessage <<"mergeOneStartOneValid start size: " << startNodes.size() << " valide size : " << validNodes.size()
<<" can only merge FSM 1 start 1 valide";
throw std::runtime_error(errorMessage.str());
}
unionG(fsmGraph);
//for loop useless but for future merge it's coudl be used
for(auto valid : validNodes){
valid->unValid();
for(auto start : startNodes){
start->unStart();
_mergeNode(start,valid);
}
}
}
std::size_t FsmGraph::getNbSubFsm(void){
return mAllOrigine.size();
}
void FsmGraph::incOrigineAllNodeBy(std::size_t incr){
std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
for(auto node :nodes){
node->incOrigine(incr);
}
for(auto origin : mAllOrigine){
origin += incr;
}
}
void FsmGraph::_mergeNode(std::shared_ptr<FsmNode> source,std::shared_ptr<FsmNode> dest){
std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
if(nodes.find(source) == nodes.end() || nodes.find(dest) == nodes.end()){
throw std::runtime_error("FsmGraph can not merge node not in the graph");
}
nodes.clear();
//probagate source attribut
if(source->isValid()){
dest->valid();
}
if(source->isStart()){
dest->start();
}
//merge source to dest by replace source by dest in all EDGE
for(auto edge : mEdges){
if(edge->getDestNode() == source ){
edge->reSetDestNode(dest);
}else if(edge->getSourceNode() == source ){
edge->reSetSouceNode(dest);
}
}
//check is source is not in graph
nodes = getNodes();
if(nodes.find(source) != nodes.end() ){
throw std::runtime_error("FsmGraph merge node not effective");
}
nodes.clear();
}
#include "aidge/graphRegex/matchFsm/FsmNode.hpp"
#include "aidge/graphRegex/matchFsm/FsmEdge.hpp"
#include "aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp"
using namespace Aidge;
FsmNode::FsmNode(bool isAValid,bool isAStart ){
mIsAStart =isAStart;
mIsAValid =isAValid;
}
const std::vector<std::shared_ptr<FsmRunTimeContext>> FsmNode::test( std::shared_ptr<FsmRunTimeContext> fsmContext){
std::vector<std::shared_ptr<FsmRunTimeContext>> out;
std::shared_ptr<FsmRunTimeContext> newFsmContext ;
for(auto edge : mEdges){
if (auto sharedEdge = edge.lock()) {
std::shared_ptr<FsmNode> nextState = sharedEdge->getDestNode();
newFsmContext = std::make_shared<FsmRunTimeContext>(fsmContext);
EdgeTestResult edgeRes = sharedEdge->test(newFsmContext);
if(edgeRes.success){
if(edgeRes.node.size() != 0){
for(auto nextNode :edgeRes.node ){
if(!newFsmContext->isAlreadyValid(nextNode) || newFsmContext->isCommonDefined(nextNode) ){
out.push_back( std::make_shared<FsmRunTimeContext>(newFsmContext,nextState,nextNode));
}else{
out.push_back( std::make_shared<FsmRunTimeContext>(newFsmContext,nextState,nullptr));
}
}
}
}
newFsmContext.reset();
}else{
throw std::runtime_error("test FsmNode weak pointer is expired" );
}
}
return out;
}
std::size_t FsmNode::getOrigine(void){
return mOrigineStm;
}
void FsmNode::incOrigine(std::size_t inc){
mOrigineStm += inc;
}
void FsmNode::rmEdge(std::shared_ptr<FsmEdge> edge){
mEdges.erase(edge);
}
void FsmNode::addEdge(std::shared_ptr<FsmEdge> edge){
mEdges.insert(edge);
}
const std::set<std::shared_ptr<FsmNode>> FsmNode::getChildNodes(void){
std::set<std::shared_ptr<FsmNode>> children;
for(auto edge : mEdges){
if (auto sharedEdge = edge.lock()) {
children.insert(sharedEdge->getDestNode());
}else{
throw std::runtime_error("getChildNodes FsmNode weak pointer is expired" );
}
}
return children;
}
const std::set<std::weak_ptr<FsmNode>,lex_compare<FsmNode>> FsmNode::getParentNodes(void){
return mParents;
}
const std::set<std::weak_ptr<FsmEdge>,lex_compare<FsmEdge>> FsmNode::getEdges(void){
return mEdges;
}
void FsmNode::setGroupe(std::size_t groupeIdx){
mGroupeStm = groupeIdx;
}
bool FsmNode::isValid(void){
return mIsAValid;
}
bool FsmNode::isStart(void){
return mIsAStart;
}
void FsmNode::unValid(void){
mIsAValid =false;
}
void FsmNode::valid(void){
mIsAValid =true;
}
void FsmNode::unStart(void){
mIsAStart =false;
}
void FsmNode::start(void){
mIsAStart =true;
}
void FsmNode::addParent(std::shared_ptr<FsmNode> node){
mParents.insert(node);
}
void FsmNode::rmParent(std::shared_ptr<FsmNode> node){
mParents.erase(node);
}
\ No newline at end of file
#include "aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp"
#include "aidge/graphRegex/matchFsm/FsmNode.hpp"
using namespace Aidge;
std::vector<std::set<NodePtr>> FsmRunTimeContext::mRejectedNodes;
FsmRunTimeContext::FsmRunTimeContext(std::shared_ptr<FsmNode> actState ,NodePtr actOpNode ,std::size_t idxRejeced ){
mActOpNode = actOpNode;
mActState = actState;
//not define case
if(idxRejeced == std::numeric_limits<std::size_t>::max()){
mLocalIdxRejeced = mRejectedNodes.size();
mRejectedNodes.push_back(std::set<NodePtr>());
}else{
if(idxRejeced > mRejectedNodes.size()-1 ){
throw std::runtime_error("FsmRunTimeContext idxRejeced");
}
mLocalIdxRejeced =idxRejeced;
}
}
FsmRunTimeContext::FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime){
mActOpNode = fsmRunTime->mActOpNode;
mActState = fsmRunTime->mActState;
mCommonNodes = fsmRunTime->mCommonNodes;
mValidNodes = fsmRunTime->mValidNodes;
mLocalIdxRejeced = fsmRunTime->mLocalIdxRejeced;
}
FsmRunTimeContext::FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime,std::shared_ptr<FsmNode> actState ,NodePtr actOpNode ){
mActOpNode = actOpNode;
mActState = actState;
mCommonNodes = fsmRunTime->mCommonNodes;
mValidNodes = fsmRunTime->mValidNodes;
mLocalIdxRejeced = fsmRunTime->mLocalIdxRejeced;
}
void FsmRunTimeContext::addRejectedNode(NodePtr node){
mRejectedNodes[mLocalIdxRejeced].insert(node);
}
std::set<NodePtr> FsmRunTimeContext::getRejectedNodes(void){
return mRejectedNodes[mLocalIdxRejeced];
}
bool FsmRunTimeContext::isOnValidState(void){
return mActState->isValid();
}
bool FsmRunTimeContext::isCommonDefined(NodePtr node){
return mCommonNodes.find(node) != mCommonNodes.end();
}
bool FsmRunTimeContext::isAlreadyValid(NodePtr node){
return getValidNodes().find(node) != getValidNodes().end();
}
bool FsmRunTimeContext::areCompatible(std::shared_ptr<FsmRunTimeContext> fsmContext){
/*
see if 2 context can be merge
it need to have different mValidNodes exept for common
and the same idx for the common
*/
//common node
for (const auto& ref : getCommon()) {
for (const auto& test : fsmContext->getCommon()) {
//same index
if(ref.second == test.second){
if(ref.first != test.first){
return false;
}
}
}
}
//valid nodes
std::set<NodePtr> commonElements;
std::set_intersection(
getValidNodesNoCommon().begin(), getValidNodesNoCommon().end(),
fsmContext->getValidNodesNoCommon().begin(), fsmContext->getValidNodesNoCommon().end(),
std::inserter(commonElements, commonElements.end())
);
if (!commonElements.empty()) {
return false;
}
return true;
}
bool FsmRunTimeContext::areEqual(std::shared_ptr<FsmRunTimeContext> fsmContext){
if(getActNode() != fsmContext->getActNode()){
return false;
}
if (getActState() != fsmContext->getActState()){
return false;
}
if (getValidNodes() != fsmContext->getValidNodes()){
return false;
}
if (getCommon() != fsmContext->getCommon()){
return false;
}
return true;
}
void FsmRunTimeContext::setCommon(NodePtr node,std::size_t commonIdx){
if(isCommonDefined(node)){
if (mCommonNodes.at(node) != commonIdx){
throw std::runtime_error("conflict idx in the Common node");
}
}else{
mCommonNodes[node] = commonIdx;
}
}
void FsmRunTimeContext::setValid(NodePtr node,std::shared_ptr<ConditionalInterpreter> tag){
//we already find a node of this type
if(mValidNodes.find(tag) != mValidNodes.end()){
if(isAlreadyValid(node) && !isCommonDefined(node) ){
throw std::runtime_error("setValid you valid tow time");
}
mValidNodes[tag].insert(node);
}else{
mValidNodes[tag] = {node};
}
}
std::size_t FsmRunTimeContext::getSubStmId(void){
return mActState->getOrigine();
}
NodePtr FsmRunTimeContext::getCommonNodeFromIdx(std::size_t commonIdx){
for (const auto& pair : mCommonNodes) {
if (pair.second == commonIdx) {
return pair.first; // Return the key when the value is found
}
}
throw std::runtime_error("getCommonNodeFromIdx Value not found in the map");
}
std::size_t FsmRunTimeContext::getCommonNodeIdx(NodePtr node){
if(isCommonDefined(node)){
return mCommonNodes.at(node);
}
throw std::runtime_error("getCommonNodeIdx node not found");
}
std::set<NodePtr> FsmRunTimeContext::getCommonNodes(void){
std::set<NodePtr> nodes;
// Iterate over the map and insert values into the set
for (const auto& pair : mCommonNodes) {
nodes.insert(pair.first);
}
return nodes;
}
std::map<NodePtr,std::size_t> FsmRunTimeContext::getCommon(void){
return mCommonNodes;
}
std::set<NodePtr> FsmRunTimeContext::getValidNodes(void){
// Create a set to store the values from the map
std::set<NodePtr> nodes;
// Iterate over the map and insert values into the set
for (const auto& pair : mValidNodes) {
nodes.insert(pair.second.begin(),pair.second.end());
}
return nodes;
}
std::set<NodePtr> FsmRunTimeContext::getValidNodesNoCommon(void){
std::set<NodePtr> differenceSet;
std::set_difference(getValidNodes().begin(), getValidNodes().end(), getCommonNodes().begin(), getCommonNodes().end(),std::inserter(differenceSet, differenceSet.end()));
return differenceSet;
}
std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>> FsmRunTimeContext::getValid(void){
return mValidNodes;
}
NodePtr FsmRunTimeContext::getActNode(void){
return mActOpNode;
}
std::shared_ptr<FsmNode> FsmRunTimeContext::getActState(){
return mActState;
}
void FsmRunTimeContext::rst(void){
mRejectedNodes.clear();
}
#include "aidge/graphRegex/matchFsm/MatchResult.hpp"
using namespace Aidge;
#include "aidge/nodeTester/ConditionalInterpreter.hpp"
using namespace Aidge;
///////////////////////////////
//ConditionalRegisterFunction
///////////////////////////////
ConditionalData* ConditionalRegisterFunction::run(const std::string key,std::vector<ConditionalData*> & datas){
auto lambdaIt = mWlambda.find(key);
if (lambdaIt != mWlambda.end()) {
return lambdaIt->second(datas);
}else {
throw std::runtime_error("can not run Lambda due to invalid key: " + key);
}
}
//////////////////////
//ConditionalInterpreter
///////////////////////
ConditionalInterpreter::ConditionalInterpreter(const std::string ConditionalExpressions)
:mLambdaRegiter()
{
ConditionalParser conditionalParser = ConditionalParser(ConditionalExpressions);
mTree = conditionalParser.parse();
///lambda by default
mLambdaRegiter.insert("getType",+[](NodePtr NodeOp){return NodeOp->type();});
}
bool ConditionalInterpreter::test( const NodePtr nodeOp)
{
try{
std::vector<ConditionalData*> r = visit({mTree},nodeOp);
if (r.size() != 1){
throw std::runtime_error("Multy output interpretation output");
}else{
if (!r[0]->isTypeEqualTo<bool>()){
throw std::runtime_error("TEST OUT MUST BE A BOOL ");
}else{
return r[0]->getValue<bool>();
}
}
}catch(const std::exception& e){
std::ostringstream errorMessage;
errorMessage << "Error in test " << "\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
}
void ConditionalInterpreter::insertLambda(const std::string key,std::function<bool(Aidge::NodePtr)> f){
mLambdaRegiter.insert<std::function<bool(Aidge::NodePtr)> >(key, f);
}
/////
std::vector<ConditionalData*> ConditionalInterpreter::visit(const ASTNodeCh& nodes, const NodePtr nodeOp ){
std::vector<ConditionalData*> dataVector;
for ( std::shared_ptr<AstNode<ConditionalTokenTypes>> node : nodes) {
try{
switch (node->getType()){
///////////////////////////////////
//OPERATOR
///////////////////////////////////
case ConditionalTokenTypes::NOT:
{
std::vector<ConditionalData*> tmp = fNot(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::AND:
{
std::vector<ConditionalData*> tmp = fAnd(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::OR:
{
std::vector<ConditionalData*> tmp = fOr(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::EQ:
{
std::vector<ConditionalData*> tmp = fEq(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::NEQ:
{
std::vector<ConditionalData*> tmp = fNeq(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
///////////////////////////////////
//VALUE
///////////////////////////////////
case ConditionalTokenTypes::KEY:
break;
case ConditionalTokenTypes::INTEGER:
{
std::vector<ConditionalData*> tmp = fStrToInteger(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::FLOAT:
{
std::vector<ConditionalData*> tmp = fStrToFloat(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::STRING:
{
std::vector<ConditionalData*> tmp = fStrToStr(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::NODE: //TODO
{
ConditionalData* data = new ConditionalData;
data->setValue<NodePtr>(nodeOp);
std::vector<ConditionalData*> tmp = {data};
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::LAMBDA:
{
std::vector<ConditionalData*> tmp = fLambda(node,visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::BOOL: //TODO
{
ConditionalData* data = new ConditionalData;
if(node->getValue() == "true"){
data->setValue<bool>(true);
}else{
data->setValue<bool>(false);
}
std::vector<ConditionalData*> tmp = {data};
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::ARGSEP:
case ConditionalTokenTypes::LPAREN:
case ConditionalTokenTypes::RPAREN:
case ConditionalTokenTypes::STOP:
default:
throw std::runtime_error("NODE TYPE NOT SUPORTED IN ConditionalInterpreter");
}
}catch(const std::exception& e){
std::ostringstream errorMessage;
errorMessage << "Error in visiting AST for node"<< nodeOp->name() << "\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
}
return dataVector;
}
//////////////////////
//value convertor
/////////////////////
std::vector<ConditionalData*> ConditionalInterpreter::fStrToInteger(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<int>(std::stoi(node->getValue()));
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fStrToFloat(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<float>(std::stof(node->getValue()));
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fStrToStr(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<std::string>(node->getValue());
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fLambda(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node,std::vector<ConditionalData*> datas)
{
//if the lambda have input
std::vector<ConditionalData*> dataVector;
ConditionalData* data;
try {
data = mLambdaRegiter.run(node->getValue(),datas);
} catch (const std::exception& e) {
std::ostringstream errorMessage;
errorMessage << "Error in conditional interpretation when run the "<< node->getValue() <<" Lambda\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fEq(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("EQ need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
if (a->getType() != b->getType()){
throw std::runtime_error("EQ Unsuported between type :" + a->getType() +" "+ b->getType());
}
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
if (a->isTypeEqualTo<int>()) {
data->setValue<bool>( a->getValue<int>() == b->getValue<int>());
}else if (a->isTypeEqualTo<float>()){
data->setValue<bool>( a->getValue<float>() == b->getValue<float>());
}else if (a->isTypeEqualTo<std::string>()){
data->setValue<bool>( a->getValue<std::string>() == b->getValue<std::string>());
}else if (a->isTypeEqualTo<bool>()){
data->setValue<bool>( a->getValue<bool>() == b->getValue<bool>());
}else{
throw std::runtime_error("EQ Unknown type encountered :" + a->getType() );
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fNeq(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("NEQ need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
if (a->getType() != b->getType()){
throw std::runtime_error("NEQ Unsuported between type :" + a->getType() +" "+ b->getType());
}
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
if (a->isTypeEqualTo<int>()) {
data->setValue<bool>( a->getValue<int>() != b->getValue<int>());
}else if (a->isTypeEqualTo<float>()){
data->setValue<bool>( a->getValue<float>() != b->getValue<float>());
}else if (a->isTypeEqualTo<std::string>()){
data->setValue<bool>( a->getValue<std::string>() != b->getValue<std::string>());
}else
{
throw std::runtime_error("NEQ Unknown type encountered :" + a->getType() );
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fAnd(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("AND need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name() || b->getType() != typeid(bool).name()){
throw std::runtime_error("AND Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( a->getValue<bool>() && b->getValue<bool>());
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fOr(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("OR need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name() || b->getType() != typeid(bool).name()){
throw std::runtime_error("OR Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( a->getValue<bool>() || b->getValue<bool>());
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fNot(std::vector<ConditionalData*> datas)
{
if (datas.size() != 1){
throw std::runtime_error("not need 1 arg and get :" + datas.size());
}
auto a = datas[0];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name()){
throw std::runtime_error("NOT Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( !a->getValue<bool>() );
dataVector.push_back(data);
datas.clear();
return dataVector;
}
#include "aidge/nodeTester/ConditionalLexer.hpp"
using namespace Aidge;
//////////////////
//ConditionalLexer
//////////////////
ConditionalLexer::ConditionalLexer( const std::string ConditionalExpressions):
mConditionalExpressions(ConditionalExpressions)
{
mPosition = 0;
}
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> ConditionalLexer::getNextToken(void){
std::string currentChars = "";
while (mPosition < mConditionalExpressions.length())
{
//erase all space
if (mConditionalExpressions[mPosition] != ' ')
{
currentChars += mConditionalExpressions[mPosition];
}
else
{
mPosition++;
continue;
}
//performe tokenisation, find a regex and make a new token
if (std::regex_match(currentChars,std::regex("\\&\\&")))// the AND TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::AND,"");
}
else if (std::regex_match(currentChars,std::regex("\\|\\|")))// the OR TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::OR,"");
}
else if (std::regex_match(currentChars,std::regex("\\!")))// the Not and not equ
{
mPosition++;
if ( mPosition < mConditionalExpressions.length()){
currentChars += mConditionalExpressions[mPosition];
if(std::regex_match(currentChars,std::regex("!="))){
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::NEQ,"");
}else{
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::NOT,"");
}
}
//a not at the end not ok but it's the parseur work
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::NOT,"");
}
else if (std::regex_match(currentChars,std::regex("==")))// the EQ TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::EQ,"");
}
else if (std::regex_match(currentChars,std::regex("\\(")))// the LPAREN TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::LPAREN,"");
}
else if (std::regex_match(currentChars,std::regex("\\)")))// the RPAREN TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::RPAREN,"");
}
else if (std::regex_match(currentChars,std::regex(",")))// the RPAREN TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::ARGSEP,"");
}
else if (std::regex_match(currentChars,std::regex("\\$")))// the ACTNode TOKEN
{
mPosition++;
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::NODE,"");
}
/////
//non const lent token
/////
//LAMBDA, KEY , bool //the fuction TAG
else if (std::regex_match(currentChars,std::regex("[A-Za-z_]")))// the KEY TOKEN (a char next )
{
//read all the key
bool isLambda = false;
std::regex keyRegex("[A-Za-z_0-9]+");
std::regex LambdaRegex("[A-Za-z_0-9]+\\(");
while ( mPosition < mConditionalExpressions.length()) {
if(!std::regex_match(currentChars,keyRegex) && !std::regex_match(currentChars,LambdaRegex))
{
currentChars.pop_back(); //the last char is the problemes
break;
}
else if (std::regex_match(currentChars,LambdaRegex)){
isLambda = true;
}
mPosition++;
if (mPosition < mConditionalExpressions.length()) currentChars += mConditionalExpressions[mPosition];
//currentChars += mConditionalExpressions[mPosition];
}
//we end the match 2 posibility
//we are at the end of the mConditionalExpressions and we need to ensure the match
//we are not we can continu
if (mPosition == mConditionalExpressions.length()-1)
{
if (!std::regex_match(currentChars,keyRegex) && !std::regex_match(currentChars,LambdaRegex))
{
throw badTokenError(currentChars,mPosition);
}
//mPosition++; // we stop all by going pos > lengt
}
if (std::regex_match(currentChars,std::regex("(true|false)"))){
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::BOOL,currentChars);
} else if (isLambda){
currentChars.pop_back();//pop the ( of the lambda
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::LAMBDA,currentChars);
} else{
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::KEY,currentChars);
}
}
//numeric value
else if (std::regex_match(currentChars,std::regex("[0-9]")))// the KEY TOKEN (a char next )
{
//read all the key
bool isFloat = false;
std::regex integerRegex("[0-9]+$");
std::regex floatRegex("[0-9]+\\.[0-9]*$");
while ( mPosition < mConditionalExpressions.length()) {
if(!std::regex_match(currentChars,integerRegex) && !std::regex_match(currentChars,floatRegex))
{
currentChars.pop_back(); // the last char match is not a good one
break;
}
else if (std::regex_match(currentChars,floatRegex)){
isFloat = true;
}
mPosition++;
if (mPosition < mConditionalExpressions.length()) currentChars += mConditionalExpressions[mPosition];
//currentChars += mConditionalExpressions[mPosition];
}
//we end the match 2 posibility
//we are at the end of the mConditionalExpressions and we need to ensure the match
//we are not we can continu
if (mPosition == mConditionalExpressions.length()-1)
{
if (!std::regex_match(currentChars,integerRegex) && !std::regex_match(currentChars,floatRegex))
{
throw badTokenError(currentChars,mPosition);
}
}
if(isFloat){
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::FLOAT,currentChars);
}else{
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::INTEGER,currentChars);
}
}
//string TODO
else if (std::regex_match(currentChars,std::regex("\'"))) // TODO ' or \'
{
std::regex strRegex("\'[A-Za-z_0-9\\s]*\'$");
while ( mPosition < mConditionalExpressions.length()) {
if(std::regex_match(currentChars,strRegex)){
break;
}
mPosition++;
if (mPosition < mConditionalExpressions.length()) currentChars += mConditionalExpressions[mPosition];
//currentChars += mConditionalExpressions[mPosition];
}
//test the end condition
if (mPosition == mConditionalExpressions.length()-1 ){
if (!std::regex_match(currentChars,strRegex)){
throw badTokenError(currentChars,mPosition);
}
//mPosition++; // we stop all by going pos > lengt
}
mPosition++; // go after the last "
//erase the " char
currentChars.pop_back();
currentChars.erase(0,1);
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::STRING,currentChars);
}
//Array TODO
mPosition++;
}
//no more to find no one match the currentChars
if (currentChars.empty()) {
return std::make_shared<ParsingToken<ConditionalTokenTypes>>(ConditionalTokenTypes::STOP,""); // Null shared pointer ;
}else{
//std::ostringstream errorMessage;
//errorMessage << "\nBad syntax " << currentChars << " :\n" << mConditionalExpressions;
throw badTokenError(currentChars,mPosition);
}
}
void ConditionalLexer::rstPosition(void){
if (isEnd()){
mPosition = 0;
}else{
throw badTokenError("end rst",mPosition);
}
}
bool ConditionalLexer::isEnd(void){
return mPosition >= mConditionalExpressions.length();
}
std::runtime_error ConditionalLexer::badTokenError(const std::string& currentChars,std::size_t position){
std::ostringstream errorMessage;
errorMessage << "\nBad syntax " << currentChars << " :\n" << mConditionalExpressions << "\n";
for (std::size_t i = 0; i < position; i++) {
errorMessage << ' ';
}
errorMessage << "^\n";
return std::runtime_error(errorMessage.str());
}
\ No newline at end of file
#include "aidge/nodeTester/ConditionalParser.hpp"
using namespace Aidge;
//////////////////////////////
//ConditionalParser
//////////////////////////////
ConditionalParser::ConditionalParser(const std::string ConditionalExpressions):mLexer(ConditionalExpressions){
mCurrentToken = mLexer.getNextToken();
}
void ConditionalParser::rstParser(void){
mLexer.rstPosition();
mCurrentToken = mLexer.getNextToken();
}
void ConditionalParser::ackToken(ConditionalTokenTypes tokenType){
if(mCurrentToken->getType() == tokenType ){
try {
mCurrentToken = mLexer.getNextToken();
} catch (const std::runtime_error& e) {
std::ostringstream errorMessage;
errorMessage << "Conditional Lexer error in Parser :\n"<< e.what() << std::endl;
throw std::runtime_error(errorMessage.str());
}
}else{
std::ostringstream errorMessage;
errorMessage << "Bad syntax ConditionalParser " << static_cast<int>(mCurrentToken->getType()) <<"!="<< static_cast<int>(tokenType) << "\n";
errorMessage << mLexer.rep();
throw std::runtime_error(errorMessage.str());
}
}
std::shared_ptr<AstNode<ConditionalTokenTypes>> ConditionalParser::constructAstVal(void){
/*
val : (KEY|INTEGER|FOAT|STRING|LAMBDA)
*/
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = mCurrentToken->copy();
if (token->getType() == ConditionalTokenTypes::KEY){
ackToken(ConditionalTokenTypes::KEY);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}
else if(token->getType() == ConditionalTokenTypes::INTEGER){
ackToken(ConditionalTokenTypes::INTEGER);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}
else if(token->getType() == ConditionalTokenTypes::FLOAT){
ackToken(ConditionalTokenTypes::FLOAT);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}
else if(token->getType() == ConditionalTokenTypes::BOOL){
ackToken(ConditionalTokenTypes::BOOL);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}
else if(token->getType() == ConditionalTokenTypes::STRING){
ackToken(ConditionalTokenTypes::STRING);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}else if(token->getType() == ConditionalTokenTypes::NODE){
ackToken(ConditionalTokenTypes::NODE);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token);
}else if(token->getType() == ConditionalTokenTypes::LAMBDA){
return constructAstLambda();
}
throw std::runtime_error("ConditionalParser unknow val type "+ token->rep().str() + "\n" + mLexer.rep());
}
std::shared_ptr<AstNode<ConditionalTokenTypes>> ConditionalParser::constructAstLambda(void){
/*
AstLambda : LAMBDA val (ARGSEP val)* RPAREN
*/
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> tokenLdb = mCurrentToken->copy();
ackToken(ConditionalTokenTypes::LAMBDA);
ASTNodeCh paramLambda;
//AT LEAST ONE VALUE AS INPUT OF A LAMBDA
paramLambda.push_back(constructAstVal());
while (mCurrentToken->getType() != ConditionalTokenTypes::RPAREN)
{
ackToken(ConditionalTokenTypes::ARGSEP);
paramLambda.push_back(constructAstVal());
}
ackToken(ConditionalTokenTypes::RPAREN);
return std::make_shared<AstNode<ConditionalTokenTypes>>(tokenLdb,paramLambda);
}
std::shared_ptr<AstNode<ConditionalTokenTypes>> ConditionalParser::constructAstCmpr(void){
/*
cmpr : val (EQ|NEQ) val | LPAREN expr RPAREN
NOT ir ?
*/
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = mCurrentToken->copy();
//we can check the type relation ir key (EQ|NEQ) val | val (EQ|NEQ) key , but val (EQ|NEQ) val is valid ?
if (token->getType() == ConditionalTokenTypes::LPAREN)
{
ackToken(ConditionalTokenTypes::LPAREN);
std::shared_ptr<AstNode<ConditionalTokenTypes>> node = constructAstExpr();
ackToken(ConditionalTokenTypes::RPAREN);
return node;
}else{
std::shared_ptr<AstNode<ConditionalTokenTypes>> node = constructAstVal();
token = mCurrentToken->copy();
if (token->getType() == ConditionalTokenTypes::EQ){
ackToken(ConditionalTokenTypes::EQ);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token,ASTNodeCh{node,constructAstVal()});
}else if(token->getType() == ConditionalTokenTypes::NEQ){
ackToken(ConditionalTokenTypes::NEQ);
return std::make_shared<AstNode<ConditionalTokenTypes>>(token,ASTNodeCh{node,constructAstVal()});
}else{
throw std::runtime_error("constructAstCmpr "+ token->rep().str() + "\n" + mLexer.rep());
}
}
}
std::shared_ptr<AstNode<ConditionalTokenTypes>> ConditionalParser::constructAstExpr(std::size_t precLimit /*= 0*/){
/*
expr : cmpr ((AND | OR) cmpr)*
the NOT is not binary OP can be use in pratt
precedence H to L: TODO
AND
OR
*/
//the not
std::shared_ptr<AstNode<ConditionalTokenTypes>> left;
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = mCurrentToken->copy();
if (mCurrentToken->getType() == ConditionalTokenTypes::NOT ){
ackToken(ConditionalTokenTypes::NOT );
left= std::make_shared<AstNode<ConditionalTokenTypes>>(token,ASTNodeCh{constructAstCmpr()});
}else{
left= constructAstCmpr();
}
//pratt
while (mCurrentToken->getType() != ConditionalTokenTypes::STOP ) //security
{
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = mCurrentToken->copy();
//if the token is not in the map is not a operator so we consider a prec of 0
if (ConditionalPrec.find(token->getType()) ==ConditionalPrec.end() ){
return left;
}
//if my actual operator have a prec <= of the last operator
std::size_t prec = ConditionalPrec.at(token->getType());
if (prec <= precLimit){
return left;
}
//Act all AND and OR
ackToken(token->getType());
std::shared_ptr<AstNode<ConditionalTokenTypes>> right = constructAstExpr(prec);
//i'm not sur what append to newNode
//std::shared_ptr<AstNode<ConditionalTokenTypes>> newNode = std::make_shared<AstNode<ConditionalTokenTypes>>(token,ASTNodeCh{left,constructAstCmpr()});
std::shared_ptr<AstNode<ConditionalTokenTypes>> newNode = std::make_shared<AstNode<ConditionalTokenTypes>>(token,ASTNodeCh{left,right});
left = newNode;
}
return left;
}
std::shared_ptr<AstNode<ConditionalTokenTypes>> ConditionalParser::parse(void){
/*
expr : cmpr ((AND | OR) cmpr)*
cmpr : val (EQ|NEQ) val | LPAREN expr RPAREN | BOOL | LAMBDA
val : (KEY|INTEGER|FOAT|STRING|LAMBDA)
lambda : LAMBDA val (ARGSEP val)* RPAREN
*/
std::shared_ptr<AstNode<ConditionalTokenTypes>> astTree = constructAstExpr();
rstParser();
return astTree;
}
\ No newline at end of file
#include <memory>
#include <catch2/catch_test_macros.hpp>
#include "aidge/nodeTester/ConditionalInterpreter.hpp"
#include "aidge/graphRegex/matchFsm/FsmNode.hpp"
#include "aidge/graphRegex/matchFsm/FsmEdge.hpp"
#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"
#include "aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp"
using namespace Aidge;
TEST_CASE("matchFSM", "FsmEdge") {
SECTION("FsmEdgeUnique constructor") {
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,true);
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
FsmEdgeUnique EdgeToTest(nodeA,nodeB,toTest);
REQUIRE(EdgeToTest.getSourceNode() == nodeA);
REQUIRE(EdgeToTest.getDestNode() == nodeB);
REQUIRE(EdgeToTest.isCommon() == false);
}
SECTION("FsmEdgeCommon constructor") {
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,true);
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
FsmEdgeCommon EdgeToTest(nodeA,nodeB,toTest,"A");
REQUIRE(EdgeToTest.getSourceNode() == nodeA);
REQUIRE(EdgeToTest.getDestNode() == nodeB);
REQUIRE(EdgeToTest.isCommon() == true);
}
SECTION("FsmEdgeRef constructor") {
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,true);
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
FsmEdgeRef EdgeToTest(nodeA,nodeB,0,-1);
REQUIRE(EdgeToTest.getSourceNode() == nodeA);
REQUIRE(EdgeToTest.getDestNode() == nodeB);
REQUIRE(EdgeToTest.isCommon() == false);
}
SECTION("FsmEdgeEmpty constructor") {
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,true);
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
FsmEdgeEmpty EdgeToTest(nodeA,nodeB);
REQUIRE(EdgeToTest.getSourceNode() == nodeA);
REQUIRE(EdgeToTest.getDestNode() == nodeB);
REQUIRE(EdgeToTest.isCommon() == false);
}
SECTION("FsmEdgeFactory"){
std::map<std::string, std::shared_ptr<ConditionalInterpreter>> allTest = {
{"A",std::make_shared<ConditionalInterpreter>("true==true")},
{"B",std::make_shared<ConditionalInterpreter>("true==true")},
{"C",std::make_shared<ConditionalInterpreter>("true==true")}
};
// make(std::shared_ptr<FsmNode> source, std::shared_ptr<FsmNode> dest,
// FsmEdgeTypes type,std::map<std::string, const std::shared_ptr<ConditionalInterpreter>> allTest,
// const std::string& lexeme = "");
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(false,true);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(true,false);
// EMPTY = 0,
// REF,
// COMMON,
// UNIQUE
std::shared_ptr<FsmEdge> edgeE = FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::EMPTY,allTest,"");
std::shared_ptr<FsmEdge> edgeU = FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::UNIQUE,allTest,"A");
std::shared_ptr<FsmEdge> edgeC = FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::COMMON,allTest,"A#");
std::shared_ptr<FsmEdge> edgeR = FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::REF,allTest,"(0,1)");
//test detection of bad syntax lexem
REQUIRE_THROWS(FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::EMPTY,allTest,"A"));
REQUIRE_THROWS(FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::UNIQUE,allTest,"A#"));
REQUIRE_THROWS(FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::COMMON,allTest,"A"));
REQUIRE_THROWS(FsmEdgeFactory::make(nodeA,nodeB,FsmEdgeTypes::REF,allTest,"A"));
REQUIRE(edgeE->getSourceNode() == nodeA);
REQUIRE(edgeE->getDestNode() == nodeB);
}
SECTION("graph constructor") {
//make the nodes
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,false);
std::shared_ptr<FsmNode> nodeC = std::make_shared<FsmNode>(false,true);
//make the edges
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
std::shared_ptr<FsmEdgeUnique> edgeAB = std::make_shared<FsmEdgeUnique>(nodeA,nodeB,toTest);
std::shared_ptr<FsmEdgeUnique> edgeBC = std::make_shared<FsmEdgeUnique>(nodeB,nodeC,toTest);
std::shared_ptr<FsmGraph> graph = std::make_shared<FsmGraph>();
graph->addEdge(edgeAB);
graph->addEdge(edgeBC);
REQUIRE(graph->getValidNodes() == std::set<std::shared_ptr<FsmNode>>{nodeA});
REQUIRE(graph->getStartNodes() == std::vector<std::shared_ptr<FsmNode>>{nodeC});
}
SECTION("graph merge") {
std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
//make the nodes
std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(false,true);
std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,false);
std::shared_ptr<FsmNode> nodeC = std::make_shared<FsmNode>(true,false);
//make the edges
std::shared_ptr<FsmEdgeUnique> edgeAB = std::make_shared<FsmEdgeUnique>(nodeA,nodeB,toTest);
std::shared_ptr<FsmEdgeUnique> edgeBC = std::make_shared<FsmEdgeUnique>(nodeB,nodeC,toTest);
std::shared_ptr<FsmGraph> graph = std::make_shared<FsmGraph>();
graph->addEdge(edgeAB);
graph->addEdge(edgeBC);
REQUIRE(graph->getValidNodes() == std::set<std::shared_ptr<FsmNode>>{nodeC});
REQUIRE(graph->getStartNodes() == std::vector<std::shared_ptr<FsmNode>>{nodeA});
REQUIRE(graph->getNodes() == std::set<std::shared_ptr<FsmNode>>{nodeA,nodeB,nodeC});
//make the nodes
std::shared_ptr<FsmNode> node2A = std::make_shared<FsmNode>(false,true);
std::shared_ptr<FsmNode> node2B = std::make_shared<FsmNode>(false,false);
std::shared_ptr<FsmNode> node2C = std::make_shared<FsmNode>(true,false);
std::shared_ptr<FsmEdgeUnique> edge2AB = std::make_shared<FsmEdgeUnique>(node2A,node2B,toTest);
std::shared_ptr<FsmEdgeUnique> edge2BC = std::make_shared<FsmEdgeUnique>(node2B,node2C,toTest);
std::shared_ptr<FsmGraph> graph2 = std::make_shared<FsmGraph>();
graph2->addEdge(edge2AB);
graph2->addEdge(edge2BC);
REQUIRE(graph2->getValidNodes() == std::set<std::shared_ptr<FsmNode>>{node2C});
REQUIRE(graph2->getStartNodes() == std::vector<std::shared_ptr<FsmNode>>{node2A});
REQUIRE(graph2->getNodes() == std::set<std::shared_ptr<FsmNode>>{node2A,node2B,node2C});
graph->mergeOneStartOneValid(graph2);
REQUIRE(graph->getValidNodes() == std::set<std::shared_ptr<FsmNode>>{node2C});
REQUIRE(graph->getStartNodes() == std::vector<std::shared_ptr<FsmNode>>{nodeA});
REQUIRE(graph->getNodes() == std::set<std::shared_ptr<FsmNode>>{nodeA,nodeB,nodeC,node2B,node2C});
}
}
// TEST_CASE("matchFSM", "FsmGraph") {
// SECTION("FsmEdgeUnique constructor") {
// //make the nodes
// std::shared_ptr<FsmNode> nodeA = std::make_shared<FsmNode>(true,false);
// std::shared_ptr<FsmNode> nodeB = std::make_shared<FsmNode>(false,true);
// //make the edges
// std::shared_ptr<ConditionalInterpreter> toTest = std::make_shared<ConditionalInterpreter>("true==true");
// std::shared_ptr<FsmEdgeUnique> edge = std::make_shared<FsmEdgeUnique>(nodeA,nodeB,toTest);
// std::shared_ptr<FsmGraph> graph = std::make_shared<FsmGraph>();
// graph->addEdge(edge);
// }
// }
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/graphRegex/GraphFsmInterpreter.hpp"
using namespace Aidge;
TEST_CASE("GraphFsmInterpreter", "GraphFsmInterpreter") {
SECTION("Construction") {
std::map<std::string,std::shared_ptr<ConditionalInterpreter>> allTest = {
{"A",std::make_shared<ConditionalInterpreter>("true==true")},
{"B",std::make_shared<ConditionalInterpreter>("true==true")},
{"C",std::make_shared<ConditionalInterpreter>("true==true")}
};
//GraphFsmInterpreter("A->B",allTest);
std::shared_ptr<GraphFsmInterpreter> fsmGenerator = std::make_shared<GraphFsmInterpreter>("A->B",allTest);
std::shared_ptr<FsmGraph> fsm = fsmGenerator->interpret();
REQUIRE(fsm->getNodes().size() == 3);
REQUIRE(fsm->getStartNodes().size() == 1);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/graphRegex/GraphLexer.hpp"
#include "aidge/graphRegex/GraphRegexTypes.hpp"
#include "aidge/utilsParsing/ParsingToken.hpp"
#include <iostream>
#include <map>
#include <functional>
using namespace Aidge;
// NEXT
// QOM
// QZM
// KEY
// CKEY
// SEP
// LPAREN
// RPAREN
TEST_CASE("GraphRegex", "Lexer") {
SECTION("RandomGenerateTest") {
std::map<gRegexTokenTypes, std::function<std::pair<std::string, std::string>()>> LexerTestMap{
{gRegexTokenTypes::NEXT, +[](){return std::pair<std::string, std::string>("-> ","");}},
{gRegexTokenTypes::QOM, +[](){return std::pair<std::string, std::string>("+ ","");}},
{gRegexTokenTypes::QZM, +[](){return std::pair<std::string, std::string>("* ","");}},
{gRegexTokenTypes::SEP, +[](){return std::pair<std::string, std::string>("; ","");}},
{gRegexTokenTypes::KEY, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+" ",key);}
},
{gRegexTokenTypes::CKEY, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_";
const std::string num = "1234567890";
std::size_t randomIndex = std::rand() % characters.size();
std::size_t randomNum = std::rand() % num.size();
std::string key;
std::string idx;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
idx += num[randomNum];
randomIndex = std::rand() % characters.size();
randomNum = std::rand() % num.size();
}
return std::pair<std::string, std::string>(key+"#"+idx+" ",key+"#"+idx);}
},
{gRegexTokenTypes::LPAREN, +[](){return std::pair<std::string, std::string>("( ","");}},
{gRegexTokenTypes::RPAREN, +[](){return std::pair<std::string, std::string>(") ","");}}
//{gRegexTokenTypes::STOP, +[](){return std::pair<std::string, std::string>("","");}}
};
//////////////////
//TEST GENERATOR
//////////////////
const std::size_t numRandomElements = 1000;
std::vector<std::tuple<gRegexTokenTypes, std::string>> testVector;
std::string testString;
for (std::size_t i = 0; i < numRandomElements; ++i) {
int randomIndex = std::rand() % LexerTestMap.size();
// Get an iterator to the random element in the map
auto it = std::next(LexerTestMap.begin(), randomIndex);
// Access the random key and lambda value separately using structured binding
gRegexTokenTypes randomKey = it->first;
std::function<std::pair<std::string, std::string>()> randomValue = it->second;
std::pair<std::string, std::string> result = randomValue();
testString += result.first;
testVector.emplace_back(randomKey, result.second);
}
GraphLexer graphLexer = GraphLexer(testString);
for (std::tuple<gRegexTokenTypes, std::string> testToken : testVector) {
gRegexTokenTypes tokenToFind = std::get<0>(testToken);
std::string lexemToFind = std::get<1>(testToken);
std::shared_ptr<ParsingToken<gRegexTokenTypes>> token = graphLexer.getNextToken();
std::ostringstream errorMessage;
errorMessage << "\n we whant :"<< lexemToFind << "\n we get : "<< token->getLexeme() <<"\n"<< "on \n" << testString << " :\n " ;
CAPTURE(errorMessage.str());
REQUIRE(token->getLexeme() == lexemToFind);
REQUIRE(token->getType() == tokenToFind);
}
std::shared_ptr<ParsingToken<gRegexTokenTypes>> token = graphLexer.getNextToken();
REQUIRE(token->getType() == gRegexTokenTypes::STOP);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/graphRegex/GraphParser.hpp"
#include "aidge/utilsParsing/AstNode.hpp"
#include <iostream>
using namespace Aidge;
std::string domain();
std::string exp() {
int randomValue = std::rand() % 3;
switch (randomValue) {
case 0:
return "A";
case 1 :
return "A#";
default:
return domain();
}
}
std::string seq() {
int randomValue = std::rand() % 2;
switch (randomValue) {
case 0:
return exp();
default:
return exp()+"->"+seq();
}
}
std::string domain() {
int randomValue = std::rand() % 2;
switch (randomValue) {
// case 0:
// return seq();
// case 1:
// return seq() + "->" +domain();
case 0:
return "("+ seq() +")*";
default:
return "("+ seq() +")+";
// case 4:
// return "("+ domain() +")*" + "->" +domain();
// default:
// return "("+ domain() +")+" + "->" +domain();
}
}
std::string allExpr() {
int randomValue = std::rand() % 2;
switch (randomValue) {
case 0:
return seq();
default :
return seq()+ ";" +allExpr();
}
}
/*
exp : KEY(QOM | QZM)? | CKEY | domain
seq :exp (NEXT seq)*
domain : LPAREN seq RPAREN (QOM | QZM)
allExpr: seq (SEP allExpr)*
*/
TEST_CASE("GraphParser", "Test_GraphParser") {
SECTION("Empty") {
for (int i = 0; i < 100; ++i) {
const std::string test = allExpr();
std::cout << test <<"\n";
GraphParser graphParser = GraphParser(test);
std::shared_ptr<AstNode<gRegexTokenTypes>> tree = graphParser.parse();
}
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/nodeTester/ConditionalInterpreter.hpp"
#include "aidge/operator/GenericOperator.hpp"
using namespace Aidge;
TEST_CASE("ConditionalInterpreter", "ConditionalInterpreter") {
SECTION("custom Lambda") {
const std::string test = " !toto($) == true " ;
ConditionalInterpreter conditionalParser = ConditionalInterpreter(test);
conditionalParser.insertLambda("toto",+[](NodePtr NodeOp){return false;});
std::shared_ptr<Node> nodeOp = GenericOperator("conv", 0, 0, 0, "Gop1");
bool result = conditionalParser.test(nodeOp);
REQUIRE(result == true);
}
SECTION("syntax error") {
const std::string test = "'A' == 'A' ,&& ";
REQUIRE_THROWS_AS( ConditionalInterpreter(test), std::runtime_error);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/nodeTester/ConditionalLexer.hpp"
#include "aidge/utilsParsing/ParsingToken.hpp"
#include <iostream>
#include <map>
#include <functional>
using namespace Aidge;
TEST_CASE("nodeTester", "Lexer") {
SECTION("RandomGenerateTest") {
std::map<ConditionalTokenTypes, std::function<std::pair<std::string, std::string>()>> LexerTestMap{
{ConditionalTokenTypes::AND, +[](){return std::pair<std::string, std::string>("&& ","");}},
{ConditionalTokenTypes::OR, +[](){return std::pair<std::string, std::string>("|| ","");}},
{ConditionalTokenTypes::EQ, +[](){return std::pair<std::string, std::string>("== ","");}},
{ConditionalTokenTypes::NEQ, +[](){return std::pair<std::string, std::string>("!= ","");}},
{ConditionalTokenTypes::KEY, +[](){return std::pair<std::string, std::string>("A ","A");}},
{ConditionalTokenTypes::BOOL, +[](){
std::size_t keyLen = (std::rand() % 2);
const std::vector<std::string> characters = {"true","false"};
return std::pair<std::string, std::string>(characters[keyLen]+" ",characters[keyLen]);}
},
{ConditionalTokenTypes::INTEGER, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "1234567890";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+" ",key);}
},
{ConditionalTokenTypes::FLOAT, +[](){
std::size_t keyLen = (std::rand() % 20)+2;
const std::string characters = "1234567890";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen/2; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
key += ".";
for (std::size_t i = 0; i < keyLen/2; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+" ",key);}
},
{ConditionalTokenTypes::STRING, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>("'"+key+"' ",key);}
},
{ConditionalTokenTypes::LAMBDA, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
const std::string Startchar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::size_t randomIndex = std::rand() % characters.size();
std::size_t randomStartIndex = std::rand() % Startchar.size();
std::string key;
key += Startchar[randomStartIndex];
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+"( ",key);}
},
{ConditionalTokenTypes::ARGSEP, +[](){return std::pair<std::string, std::string>(", ","");}},
{ConditionalTokenTypes::NODE, +[](){return std::pair<std::string, std::string>("$ ","");}},
{ConditionalTokenTypes::LPAREN, +[](){return std::pair<std::string, std::string>("( ","");}},
{ConditionalTokenTypes::RPAREN, +[](){return std::pair<std::string, std::string>(") ","");}}
//{ConditionalTokenTypes::STOP, +[](){return std::pair<std::string, std::string>("","");}}
};
//////////////////
//TEST GENERATOR
//////////////////
const std::size_t numRandomElements = 100;
std::vector<std::tuple<ConditionalTokenTypes, std::string>> testVector;
std::string testString;
for (std::size_t i = 0; i < numRandomElements; ++i) {
int randomIndex = std::rand() % LexerTestMap.size();
// Get an iterator to the random element in the map
auto it = std::next(LexerTestMap.begin(), randomIndex);
// Access the random key and lambda value separately using structured binding
ConditionalTokenTypes randomKey = it->first;
std::function<std::pair<std::string, std::string>()> randomValue = it->second;
std::pair<std::string, std::string> result = randomValue();
testString += result.first;
testVector.emplace_back(randomKey, result.second);
}
ConditionalLexer conditionalLexer = ConditionalLexer(testString);
for (std::tuple<ConditionalTokenTypes, std::string> testToken : testVector) {
ConditionalTokenTypes tokenToFind = std::get<0>(testToken);
std::string lexemToFind = std::get<1>(testToken);
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = conditionalLexer.getNextToken();
std::ostringstream errorMessage;
errorMessage << "\n we whant :"<< lexemToFind << "\n we get : "<< token->getLexeme() <<"\n"<< "on \n" << testString << " :\n " ;
CAPTURE(errorMessage.str());
REQUIRE(token->getLexeme() == lexemToFind);
REQUIRE(token->getType() == tokenToFind);
}
std::shared_ptr<ParsingToken<ConditionalTokenTypes>> token = conditionalLexer.getNextToken();
REQUIRE(token->getType() == ConditionalTokenTypes::STOP);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "aidge/nodeTester/ConditionalParser.hpp"
#include "aidge/utilsParsing/AstNode.hpp"
using namespace Aidge;
std::string gVal() {
int randomValue = std::rand() % 5;
switch (randomValue) {
case 0:
return std::to_string(std::rand() % 101);
case 1:
return std::to_string(std::rand() % 101)+"."+std::to_string(std::rand() % 101);
case 2:
return " 'toto' ";
case 3:
return " A ";
case 4:
return " A(10) ";
default:
return " true ";
}
}
std::string gExpr() ;
std::string gCmpr() {
int randomValue = std::rand() % 3;
switch (randomValue) {
case 0:
return gVal() + " == " +gVal();
case 1:
return "("+ gExpr() +")";
default:
return gVal() + " != " +gVal();
}
return gVal() + " == " +gVal();
}
std::string gExpr() {
std::string out = gCmpr();
int iterations = std::rand() % 100;
for (int i = 0; i < iterations; ++i) {
int randomValue = std::rand() % 2;
switch (randomValue) {
case 0:
return out +" && " + gCmpr();
break;
default:
return out +" || " + gCmpr();
break;
}
}
return out;
}
TEST_CASE("ConditionalParser", "ConditionalParser") {
SECTION("Empty") {
for (int i = 0; i < 100; ++i) {
const std::string test = gExpr();
ConditionalParser conditionalParser = ConditionalParser(test);
std::shared_ptr<AstNode<ConditionalTokenTypes>> tree = conditionalParser.parse();
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment