diff --git a/include/aidge/graphRegex/GraphParser.hpp b/include/aidge/graphRegex/GraphParser.hpp
index 06d098e995933e223146c37567f8d6895340e47d..018be1e44304f6189d1a0eb105fc4d8d1500a928 100644
--- a/include/aidge/graphRegex/GraphParser.hpp
+++ b/include/aidge/graphRegex/GraphParser.hpp
@@ -21,7 +21,7 @@ class GraphParser{
      */
     GraphParser(const std::string gRegexExpressions);
 
-    virtual ~GraphParser();
+    virtual ~GraphParser() = default;
 
     /**
      * @brief AST graph creation function 
diff --git a/include/aidge/graphRegex/GraphStrInterpreter.hpp b/include/aidge/graphRegex/GraphStrInterpreter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1fb5c2e2f4877179b07a7c7942da223247500ad
--- /dev/null
+++ b/include/aidge/graphRegex/GraphStrInterpreter.hpp
@@ -0,0 +1,40 @@
+#ifndef __AIDGE_GRAPH_FSM_INTERPRETER_H__
+#define __AIDGE_GRAPH_FSM_INTERPRETER_H__
+
+#include <iostream>
+#include <sstream>
+#include <memory>
+#include <algorithm>
+
+#include "aidge/utilsParsing/AstNode.hpp"
+#include "aidge/graphRegex/GraphRegexTypes.hpp"
+#include "aidge/graphRegex/GraphParser.hpp"
+#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"
+
+namespace Aidge {
+
+    class GraphStrInterpreter
+    {
+    private:
+        /* data */
+        GraphParser mParser;
+        std::string mToTest;
+    public:
+        GraphStrInterpreter(const std::string graphMatchExpr);
+        virtual ~GraphStrInterpreter() =default;
+
+
+        std::string interpret(void);
+
+        private:
+        
+
+         std::string visit(std::shared_ptr<AstNode<gRegexTokenTypes>> AstTree);
+    };
+
+
+
+}
+
+
+#endif //__AIDGE_GRAPH_STM_INTERPRETER_H__
\ No newline at end of file
diff --git a/include/aidge/graphRegex/matchFsm/FsmGraph.hpp b/include/aidge/graphRegex/matchFsm/FsmGraph.hpp
index d6ef8742d0a5a59947ad713d5dde0aebdd592796..94eafd051dab065be917446ee4b8ad60207b1c57 100644
--- a/include/aidge/graphRegex/matchFsm/FsmGraph.hpp
+++ b/include/aidge/graphRegex/matchFsm/FsmGraph.hpp
@@ -24,7 +24,7 @@ private:
     std::set<std::shared_ptr<FsmEdge>> mEdges;
 public:
     FsmGraph(/* args */);
-    virtual ~FsmGraph();// = default;
+    virtual ~FsmGraph() = default;
 
 std::shared_ptr<MatchResult> test(std::vector<NodePtr>& StartNodes);
 
diff --git a/include/aidge/graphRegex/matchFsm/FsmNode.hpp b/include/aidge/graphRegex/matchFsm/FsmNode.hpp
index 6a31c20fbbb98a51536dde4e217def22953372d2..18b78fe89cbcc480132c9b42859c5578123eda2f 100644
--- a/include/aidge/graphRegex/matchFsm/FsmNode.hpp
+++ b/include/aidge/graphRegex/matchFsm/FsmNode.hpp
@@ -57,7 +57,7 @@ namespace Aidge{
 
     public:
         FsmNode(bool isAValid,bool isAStart );
-        virtual ~FsmNode();// = default;
+        virtual ~FsmNode() = default;
         /**
          * @brief use to MAG the actual context , and return all the posible new context 
          * @details one input context can generate a multitude of contexts because a graph node
diff --git a/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp b/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
index 5c73f83be9c1f2ec09ed16153f41b49e02537464..f1fb4b02684901fb0576c864401e134ae1616a73 100644
--- a/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
+++ b/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
@@ -61,7 +61,7 @@ namespace Aidge{
         FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime);
         FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime,std::shared_ptr<FsmNode> actState ,NodePtr actOpNode );
 
-        virtual ~FsmRunTimeContext();//=default;
+        virtual ~FsmRunTimeContext()=default;
 
         /**
          * @defgroup FsmRunTimeContextRejected Function for managing rejected nodes
diff --git a/include/aidge/nodeTester/ConditionalParser.hpp b/include/aidge/nodeTester/ConditionalParser.hpp
index 59041a19f88e2895cf4e6e1f4d1266edd8bcb9fc..79eff676ee2a2687c6f604adff343ba7b114b4d5 100644
--- a/include/aidge/nodeTester/ConditionalParser.hpp
+++ b/include/aidge/nodeTester/ConditionalParser.hpp
@@ -36,7 +36,7 @@ class ConditionalParser{
      */
     ConditionalParser(const std::string ConditionalExpressions);
 
-    virtual ~ConditionalParser() ;// = default;
+    virtual ~ConditionalParser() = default;
     /**
      * @brief AST graph creation function 
      * @return The AST tree 
diff --git a/src/graphRegex/GraphLexer.cpp b/src/graphRegex/GraphLexer.cpp
index 437c45f5088f459613cb63bbbdb96b7ea4e09145..61214f96a090fef5d28cb0ce1a009644d9570880 100644
--- a/src/graphRegex/GraphLexer.cpp
+++ b/src/graphRegex/GraphLexer.cpp
@@ -88,7 +88,6 @@ std::shared_ptr<ParsingToken<gRegexTokenTypes>> GraphLexer::getNextToken(void){
                 mPosition++;
                 if (mPosition < mRegularExpressions.length()) currentChars += mRegularExpressions[mPosition];
                 
-
             }
             //we end the match 2 posibility 
             //we are at the end of the mConditionalExpressions and we need to ensure the match
@@ -99,7 +98,6 @@ std::shared_ptr<ParsingToken<gRegexTokenTypes>> GraphLexer::getNextToken(void){
                 {
                     throw badTokenError(currentChars,mPosition);
                 }
-                //mPosition++; // we stop all by going pos > lengt
             }
 
 
diff --git a/src/graphRegex/GraphParser.cpp b/src/graphRegex/GraphParser.cpp
index be7b6904023436c822bb1c6ab2c81d0b8de40f02..5aa653c482dae82c2e9fa02bfc36b2ffc821785f 100644
--- a/src/graphRegex/GraphParser.cpp
+++ b/src/graphRegex/GraphParser.cpp
@@ -54,11 +54,13 @@ std::shared_ptr<AstNode<gRegexTokenTypes>> GraphParser::constructAstExp(void)
         if (mCurrentToken->getType() == gRegexTokenTypes::KEY  ){
             ackToken(gRegexTokenTypes::KEY );
             if (mCurrentToken->getType() == gRegexTokenTypes::QOM  ){
+                token = mCurrentToken->copy();
                 ackToken(gRegexTokenTypes::QOM );
                 std::shared_ptr<AstNode<gRegexTokenTypes>> newNode = std::make_shared<AstNode<gRegexTokenTypes>>(token,
                 std::vector<std::shared_ptr<AstNode<gRegexTokenTypes>>>{node});
                 return newNode;
             }else if (mCurrentToken->getType() == gRegexTokenTypes::QZM  ){
+                token = mCurrentToken->copy();
                 ackToken(gRegexTokenTypes::QZM );
                 std::shared_ptr<AstNode<gRegexTokenTypes>> newNode = std::make_shared<AstNode<gRegexTokenTypes>>(token,
                 std::vector<std::shared_ptr<AstNode<gRegexTokenTypes>>>{node});
@@ -149,7 +151,7 @@ std::shared_ptr<AstNode<gRegexTokenTypes>> GraphParser::constructAstDomain(void)
 }
 
 /*
-        allExpr: seq (SEP allExpr)*
+        allExpr: seq (SEP allExpr)* | STOP
 */
 std::shared_ptr<AstNode<gRegexTokenTypes>> GraphParser::constructAstAllExpr(void)
 {
@@ -160,6 +162,11 @@ std::shared_ptr<AstNode<gRegexTokenTypes>> GraphParser::constructAstAllExpr(void
         {
             std::shared_ptr<ParsingToken<gRegexTokenTypes>> token = mCurrentToken->copy();
             ackToken(gRegexTokenTypes::SEP);
+
+            if(mCurrentToken->getType() == gRegexTokenTypes::STOP )
+            {
+                 return left;
+            } 
             std::shared_ptr<AstNode<gRegexTokenTypes>> newNode = std::make_shared<AstNode<gRegexTokenTypes>>(token,
             std::vector<std::shared_ptr<AstNode<gRegexTokenTypes>>>{left,constructAstAllExpr()});
             left = newNode;
diff --git a/src/graphRegex/GraphStrInterpreter.cpp b/src/graphRegex/GraphStrInterpreter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ad24b5b9b0fee5fba34dd7397132bec2410fd23
--- /dev/null
+++ b/src/graphRegex/GraphStrInterpreter.cpp
@@ -0,0 +1,38 @@
+#include "aidge/graphRegex/GraphStrInterpreter.hpp"
+
+using namespace Aidge; 
+
+GraphStrInterpreter::GraphStrInterpreter(const std::string graphMatchExpr):mParser(graphMatchExpr){
+    mToTest = graphMatchExpr;
+    mToTest.erase(std::remove_if(mToTest.begin(), mToTest.end(), ::isspace), mToTest.end());
+}
+
+
+std::string GraphStrInterpreter::visit(std::shared_ptr<AstNode<gRegexTokenTypes>> AstTree){
+
+    std::vector<std::shared_ptr<AstNode<gRegexTokenTypes>>> nextAstNodes = AstTree->getChilds();
+
+    if(AstTree->getType() == gRegexTokenTypes::SEP){
+        return visit(nextAstNodes[0])+";"+visit(nextAstNodes[1]);
+    }else if(AstTree->getType() == gRegexTokenTypes::NEXT){
+        return visit(nextAstNodes[0])+"->"+visit(nextAstNodes[1]);
+    }else if(AstTree->getType() == gRegexTokenTypes::QOM){
+        return visit(nextAstNodes[0])+"+";
+    }else if(AstTree->getType() == gRegexTokenTypes::QZM){
+        return visit(nextAstNodes[0])+"*";
+    }else if(AstTree->getType() == gRegexTokenTypes::KEY || AstTree->getType() == gRegexTokenTypes::CKEY){
+        return AstTree->getValue();
+    }else if(AstTree->getType() == gRegexTokenTypes::LPAREN){
+        return "("+visit(nextAstNodes[0])+")";
+    }else{
+        throw std::logic_error("visit Bad token type" );
+    }
+
+
+}
+
+
+std::string GraphStrInterpreter::interpret(void){
+    std::shared_ptr<AstNode<gRegexTokenTypes>> tree = mParser.parse();
+    return visit(tree);
+}
\ No newline at end of file
diff --git a/src/graphRegex/matchFsm/FsmEdge.cpp b/src/graphRegex/matchFsm/FsmEdge.cpp
index 19b6c356e63c1438c45bd85750f67a059918535c..593da06abe18576d435ae55718d379aa5b682d60 100644
--- a/src/graphRegex/matchFsm/FsmEdge.cpp
+++ b/src/graphRegex/matchFsm/FsmEdge.cpp
@@ -47,7 +47,7 @@ void FsmEdge::propagateRelativePos(void){
         myRelativeID.insert(kvp.first);
     }
 
-    for (const auto nextWeakEdge : mNodeDest->getEdges()){
+    for (const auto& nextWeakEdge : mNodeDest->getEdges()){
 
         if (auto nextEdge = nextWeakEdge.lock()) {
             
diff --git a/unit_tests/graphRegex/Test_FsmMatch.cpp b/unit_tests/graphRegex/Test_FsmMatch.cpp
index 132a8606e7eb26f651ea951f7879817dd7f0e244..d89b274b3c287b0ee3af97b899c6fbd22e973148 100644
--- a/unit_tests/graphRegex/Test_FsmMatch.cpp
+++ b/unit_tests/graphRegex/Test_FsmMatch.cpp
@@ -23,7 +23,7 @@ TEST_CASE("FsmMatch") {
         allTest["A"]->insertLambda("isConv",+[](NodePtr NodeOp){return NodeOp->type() == "Conv";});
         allTest["B"]->insertLambda("isConv",+[](NodePtr NodeOp){return NodeOp->type() == "Conv";});
 
-        std::shared_ptr<GraphFsmInterpreter>  fsmGenerator = std::make_shared<GraphFsmInterpreter>("A#->B",allTest);
+        std::shared_ptr<GraphFsmInterpreter>  fsmGenerator = std::make_shared<GraphFsmInterpreter>("A->A",allTest);
         std::shared_ptr<FsmGraph> fsm = fsmGenerator->interpret();
 
 
@@ -51,9 +51,38 @@ TEST_CASE("FsmMatch") {
         REQUIRE( result->getBiggerSolution() == std::set<NodePtr>{conv,conv1});
     }
 
-    SECTION("split"){
 
+    SECTION("2 branche graph"){
 
+        std::shared_ptr<GraphView> g1 = std::make_shared<GraphView>("TestGraph");
+        std::shared_ptr<Node> conv = GenericOperator("Conv", 1, 1, 1, "c");
+        std::shared_ptr<Node> conv1 = GenericOperator("Conv", 1, 1, 1, "c1");
+        std::shared_ptr<Node> conv2 = GenericOperator("Fc", 1, 1, 1, "c2");
+
+        g1->add(conv);
+        g1->addChild(conv1,conv);
+        g1->addChild(conv2,conv);
+        
+        REQUIRE(g1->getNodes() == std::set<std::shared_ptr<Node>>({conv,conv1,conv2}));
+        REQUIRE(g1->inputNodes() == std::set<std::shared_ptr<Node>>({conv}));
+        REQUIRE(g1->outputNodes() == std::set<std::shared_ptr<Node>>({conv1,conv2}));
+
+
+        /////////////
+
+        std::map<std::string,std::shared_ptr<ConditionalInterpreter>> allTest = {
+            {"A",std::make_shared<ConditionalInterpreter>("isConv($)==true")},
+            {"B",std::make_shared<ConditionalInterpreter>("isFc($)==true")}
+        };
+        allTest["A"]->insertLambda("isConv",+[](NodePtr NodeOp){return NodeOp->type() == "Conv";});
+        allTest["B"]->insertLambda("isFc",+[](NodePtr NodeOp){return NodeOp->type() == "Fc";});
+
+        std::shared_ptr<GraphFsmInterpreter>  fsmGenerator = std::make_shared<GraphFsmInterpreter>("A#->A; A#->B",allTest);
+        std::shared_ptr<FsmGraph> fsm = fsmGenerator->interpret();
+
+        std::vector<std::shared_ptr<Node>> startNodes = {conv,conv};
+        auto result = fsm->test(startNodes);
+        REQUIRE( result->getBiggerSolution() == std::set<NodePtr>{conv,conv1,conv2});
 
     }
 
diff --git a/unit_tests/graphRegex/Test_GraphLexer.cpp b/unit_tests/graphRegex/Test_GraphLexer.cpp
index 9b922e5bd70ee1537f54100a2b8e9c826ff5e0c2..1b8cc8e018546ebfe3f84202d9404db27b17449b 100644
--- a/unit_tests/graphRegex/Test_GraphLexer.cpp
+++ b/unit_tests/graphRegex/Test_GraphLexer.cpp
@@ -73,7 +73,7 @@ TEST_CASE("GraphRegex", "Lexer") {
         //////////////////
         //TEST GENERATOR
         //////////////////
-        const std::size_t numRandomElements = 1000;
+        const std::size_t numRandomElements = 10000;
         std::vector<std::tuple<gRegexTokenTypes, std::string>> testVector;
 
         std::string testString;
diff --git a/unit_tests/graphRegex/Test_GraphParser.cpp b/unit_tests/graphRegex/Test_GraphParser.cpp
index ff74b676598d5fe63fe47b5c5cd24ba123aca004..857caa06f4e5fa383e79ea22bfe1ca28ac0973c8 100644
--- a/unit_tests/graphRegex/Test_GraphParser.cpp
+++ b/unit_tests/graphRegex/Test_GraphParser.cpp
@@ -6,6 +6,8 @@
 
 
 using namespace Aidge;
+
+    //generative function ,
     std::string domain();
     std::string exp() {
         int randomValue = std::rand() % 3;
diff --git a/unit_tests/graphRegex/Test_graphRegexAST.cpp b/unit_tests/graphRegex/Test_graphRegexAST.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1cdb0bc1934983a26ab742bfe8879455077219cc
--- /dev/null
+++ b/unit_tests/graphRegex/Test_graphRegexAST.cpp
@@ -0,0 +1,71 @@
+#include <catch2/catch_test_macros.hpp>
+#include "aidge/graphRegex/GraphStrInterpreter.hpp"
+
+
+using namespace Aidge;
+TEST_CASE("GraphStrInterpreter") {
+
+
+
+    std::vector<std::string> tests = {
+           
+
+            //sequ
+            "A;",
+            "A->B",
+            "A->B->C",
+            //seq and common
+            "A#",
+            "A#->B",
+            "A#->B#",
+            "A#->B#->C",
+            "A#->B#->C#",
+            "A->B#->C",
+            //sequ quantif +
+            "A+",
+            "A+->B+",
+            "A->B+->C",
+            //sequ quantif *
+            "A*",
+            "A*->B*",
+            "A->B*->C",
+
+            //sequ quantif 
+            "A*",
+            "A*->B+",
+            "A+->B*->C",
+            //others
+
+            "(A#->B->C#)+",
+            "(A#->B)+;A#->B->C",
+            "B+->B->B",
+            "B#->R*",
+            "(B#->R)*",
+            "A->C->B#->B;B#->R",
+            "B#->R",
+            "A->C#;A->C#;A->C#;A->C#;A->C#;A->C#",
+            "B#->R;B#->R",
+            "A# -> C -> B#; B#->A#",
+            
+        // Add more test cases here
+    };
+
+    SECTION("AST Regex bijection") {
+
+        for (const std::string& test : tests) {
+            std::shared_ptr<GraphStrInterpreter>  strGenerator = std::make_shared<GraphStrInterpreter>(test);
+            std::string astString = strGenerator->interpret();
+            //supress space in the test becase erase in the AST
+            std::string testNoS = test;
+            testNoS.erase(std::remove_if(testNoS.begin(), testNoS.end(), ::isspace), testNoS.end());
+            //if the last char is ; (SEP) it will not in the AST and it's not a bug erase it
+            if (!testNoS.empty() && testNoS.back() == ';') {
+                // Remove the last character
+                testNoS.pop_back();
+            }
+            //test
+            REQUIRE(astString == testNoS);
+        }
+
+    }
+}
\ No newline at end of file