Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
GraphFsmInterpreter.cpp 6.38 KiB
#include "aidge/graphRegex/GraphFsmInterpreter.hpp"

using namespace Aidge; 


GraphFsmInterpreter::GraphFsmInterpreter(const std::string graphMatchExpr,std::vector<std::shared_ptr<ConditionalInterpreter>>&nodesCondition):mParser(graphMatchExpr){
    mActGroupe = 0;

    for (const auto &obj : nodesCondition) {
        if(mNodesCondition.find(obj->getKey()) ==mNodesCondition.end()){
             mNodesCondition[obj->getKey()] = obj;
        }else{
            throw std::logic_error("GraphFsmInterpreter Bad Key" );
        }
    }
}
std::shared_ptr<FsmGraph>  GraphFsmInterpreter::interpret(void){
    mActGroupe = 0;
    std::shared_ptr<AstNode<gRegexTokenTypes>> tree = mParser.parse();
    std::shared_ptr<FsmGraph> out = visit(tree);
    return out;
}

std::shared_ptr<FsmGraph> GraphFsmInterpreter::visit(std::shared_ptr<AstNode<gRegexTokenTypes>> AstTree){

    std::vector<std::shared_ptr<AstNode<gRegexTokenTypes>>> nextAstNodes = AstTree->getChilds();

    if(AstTree->getType() == gRegexTokenTypes::SEP){
        return sepF(visit(nextAstNodes[0]),visit(nextAstNodes[1]));
    }else if(AstTree->getType() == gRegexTokenTypes::NEXT){
        return nextF(visit(nextAstNodes[0]),visit(nextAstNodes[1]));
    }else if(AstTree->getType() == gRegexTokenTypes::QOM){
        return qomF(visit(nextAstNodes[0]));
    }else if(AstTree->getType() == gRegexTokenTypes::QZM){
        return qzmF(visit(nextAstNodes[0]));
    }else if(AstTree->getType() == gRegexTokenTypes::KEY || AstTree->getType() == gRegexTokenTypes::CKEY){
        return keyF(AstTree);
    }else if(AstTree->getType() == gRegexTokenTypes::LPAREN){
        mActGroupe += 1;
        std::shared_ptr<FsmGraph> out = visit(nextAstNodes[0]);
        mActGroupe -= 1;
        return out;
    }else{
        throw std::logic_error("visit Bad token type" );
    }
}




std::shared_ptr<FsmGraph> GraphFsmInterpreter::keyF(std::shared_ptr<AstNode<gRegexTokenTypes>> AstNode){
    

    std::shared_ptr<FsmNode>  start = std::make_shared<FsmNode>(false,true);
    std::shared_ptr<FsmNode>  valid = std::make_shared<FsmNode>(true,false);
    std::shared_ptr<FsmGraph> graph = std::make_shared<FsmGraph>(mParser.getQuery());
    std::shared_ptr<FsmEdge> edge;
    

    if(AstNode->getType() == gRegexTokenTypes::CKEY){
        edge = FsmEdgeFactory::make(start,valid,FsmEdgeTypes::COMMON,mNodesCondition,AstNode->getValue());
    }else if (AstNode->getType() == gRegexTokenTypes::KEY)
    {
        edge = FsmEdgeFactory::make(start,valid,FsmEdgeTypes::UNIQUE,mNodesCondition,AstNode->getValue());
    }else{

        throw std::logic_error("keyF Bad in AST" );
    }
    
    graph->addEdge(edge);
    graph->setGroupe(mActGroupe);
    return graph;
}

std::shared_ptr<FsmGraph> GraphFsmInterpreter::sepF(std::shared_ptr<FsmGraph> leftFsm,std::shared_ptr<FsmGraph> rigthFsm){

    size_t idxLeft = leftFsm->getNbSubFsm();
    rigthFsm->incOriginAllNodeBy(idxLeft);
    leftFsm->unionG(rigthFsm);
    //the rigthFsm is no longer usfull
    return leftFsm;
}

std::shared_ptr<FsmGraph> GraphFsmInterpreter::nextF(std::shared_ptr<FsmGraph> leftFsm,std::shared_ptr<FsmGraph> rigthFsm){
    /*
        combine the 2 Graph
        all valid node of A are  merge with Start B, Start B is un Start
        update the relative reference  

           A          B
        SA -> VA + SB -> VB
           A    B
        SA -> q -> VB
    */
    leftFsm->mergeOneStartOneValid(rigthFsm);
    //the rigthFsm is no longer usfull
    return leftFsm;
}

std::shared_ptr<FsmGraph> GraphFsmInterpreter::qomF(std::shared_ptr<FsmGraph> fsm){
    /*
        +
        valid node is connect to the child of Start with the same edge condition
            A
        S -> V

            A
        S -> V
          (E|R)
        V -> S
    */

    std::vector<std::shared_ptr<FsmNode>> allStart =  fsm->getStartNodes();
    std::set<std::shared_ptr<FsmNode>> allValid = fsm->getValidNodes();
    std::shared_ptr<FsmEdge> edge;

    if(allStart.size() != 1){
         throw std::logic_error("qomF Bad in AST" );
    }

    for(auto start : allStart ){
        for(auto edgeStart :start->getEdges() ){
            if (auto sharedEdge = edgeStart.lock()) {

                const std::map<size_t, int> commonRef = sharedEdge->getRelative();
                bool haveCommon = !commonRef.empty();

                for(auto valid : allValid){
                    if(haveCommon){
                        /*
                        the // quantif case 
                        get the go back and make a lexeme id(number)
                        we need to go back to the ref delta min #TODO
                        */
                        bool hasMinRef = false;
                        std::pair<size_t, int> minRef;
                        for (const auto& entry : commonRef) {
                            if (!hasMinRef || std::abs(minRef.second) > std::abs(entry.second)) {
                                hasMinRef = true;
                                minRef = entry;
                            }
                        }
                        std::stringstream lexem;
                        lexem << "(" << minRef.first << ", " << minRef.second << ")";
                        edge = FsmEdgeFactory::make(valid,start,FsmEdgeTypes::REF,mNodesCondition, lexem.str());
                    }else{
                        /*
                        the sequensial quantif case 
                        no reference to common 
                        */
                        edge = FsmEdgeFactory::make(valid,start,FsmEdgeTypes::EMPTY,mNodesCondition,"");

                    }
                    fsm->addEdge(edge);
                }
            }else{
                throw std::runtime_error("edgeStart weak pointer is expired" );
            }
        }
     
    }
    return fsm;

}

std::shared_ptr<FsmGraph> GraphFsmInterpreter::qzmF(std::shared_ptr<FsmGraph> fsm){
        /*
        qomf and a bypass empty start to valide 
        */
    fsm = qomF(fsm);

    std::vector<std::shared_ptr<FsmNode>> allStart =  fsm->getStartNodes();
    std::set<std::shared_ptr<FsmNode>> allValid = fsm->getValidNodes();
    std::shared_ptr<FsmEdge> edge;

    if(allStart.size() != 1){
         throw std::logic_error("qzmF Bad in AST" );
    }

    for(auto start : allStart ){
       
        for(auto valid : allValid){
            edge = FsmEdgeFactory::make(start,valid,FsmEdgeTypes::EMPTY,mNodesCondition,"");
            fsm->addEdge(edge);
        }
    }
        
    return fsm;


}