예제 #1
0
 /** Constructor for a node containing an atomic proposition (index into APSet) */
 public LTLNode(int ap)
 {
     _type  = type_t.T_AP;
     _left  = null;
     _right = null;
     _ap    = ap;
 }
예제 #2
0
        public static LTLFormula parse(ltl2ba.Node LTLHeadNode, APSet predefined_apset)
        {
            //    boost::char_separator<char> sep(" ");
            //ltl_seperator sep; tokenizer tokens(formula, sep);

            APSet apset = new APSet();

            //tokenizer::iterator it = tokens.begin();

            //LTLNode ltl = parse(apset, predefined_apset);

            //if (it != tokens.end())
            //{
            //    THROW_EXCEPTION(Exception, "Unexpected character(s) at end of LTL formula: '" + *it + "'");
            //}


            LTLNode ltl = TranslateLTL(LTLHeadNode, apset, predefined_apset);

            APSet apset_ = predefined_apset ?? apset;

            return(new LTLFormula(ltl, apset_));
        }
예제 #3
0
 /**
  * Constructor
  * @param root the root node
  * @param apset the underlying APSet
  */
 public LTLFormula(LTLNode root, APSet apset)
 {
     _root  = root;
     _apset = apset;
 }
예제 #4
0
 public LTLNode(type_t type, LTLNode left) : this(type, left, null)
 {
 }
예제 #5
0
        /**
         * Generate formula in DNF. Formula has to have only
         * AND, OR, TRUE, FALSE, ! as operators, and has to
         * be in PNF
         */
        public LTLNode toDNF()
        {
            switch (_type)
            {
            case type_t.T_TRUE:
                return(new LTLNode(type_t.T_TRUE, null));

            case type_t.T_FALSE:
                return(new LTLNode(type_t.T_FALSE, null));

            case type_t.T_NOT:
                return(new LTLNode(type_t.T_NOT, getLeft().toDNF()));

            case type_t.T_AP:
                return(new LTLNode(getAP()));

            case type_t.T_OR:
                return(new LTLNode(type_t.T_OR,
                                   getLeft().toDNF(),
                                   getRight().toDNF()));

            case type_t.T_AND:
            {
                LTLNode left  = getLeft().toDNF();
                LTLNode right = getRight().toDNF();

                if (left.getType() == type_t.T_OR)
                {
                    LTLNode a = left.getLeft();
                    LTLNode b = left.getRight();

                    if (right.getType() == type_t.T_OR)
                    {
                        LTLNode c = right.getLeft();
                        LTLNode d = right.getRight();

                        LTLNode a_c = new LTLNode(type_t.T_AND, a, c),
                                b_c = new LTLNode(type_t.T_AND, b, c),
                                a_d = new LTLNode(type_t.T_AND, a, d),
                                b_d = new LTLNode(type_t.T_AND, b, d);

                        return(new LTLNode(type_t.T_OR,
                                           new LTLNode(type_t.T_OR, a_c, b_c).toDNF(),
                                           new LTLNode(type_t.T_OR, a_d, b_d).toDNF()));
                    }
                    else
                    {
                        LTLNode
                            a_c = new LTLNode(type_t.T_AND, a, right),
                            b_c = new LTLNode(type_t.T_AND, b, right);

                        return(new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF()));
                    }
                }
                else if (right.getType() == type_t.T_OR)
                {
                    LTLNode a, b;
                    a = right.getLeft();
                    b = right.getRight();

                    LTLNode
                        a_c = new LTLNode(type_t.T_AND, left, a),
                        b_c = new LTLNode(type_t.T_AND, left, b);

                    return(new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF()));
                }
                else
                {
                    return(new LTLNode(type_t.T_AND, left, right));
                }
            }

            default:
                throw new Exception("Illegal operator for DNF!");
            }
        }
예제 #6
0
 /**
  * Get a LTLFormula_ptr for the subformula rooted at subroot
  */
 public LTLFormula getSubFormula(LTLNode subroot)
 {
     LTLFormula sub = new LTLFormula(subroot, _apset);
     return sub;
 }
예제 #7
0
        public LTLNode toPNF(bool negate)
        {
            switch (_type)
            {
                case type_t.T_XOR:
                    throw new Exception("XOR not yet supported!");
                case type_t.T_IMPLICATE:
                    {
                        if (negate)
                        {
                            // ! (a->b) = !(!a | b) = (a & ! b)
                            return new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true));
                        }
                        else
                        {
                            // (a->b) = (!a | b)
                            return new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF());
                        }
                        break;
                    }
                case type_t.T_EQUIV:
                    {
                        if (negate)
                        {
                            // ! (a<->b) == (a & !b) || (!a & b)
                            return new
                                LTLNode(type_t.T_OR,
                                new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)),
                                new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF()));
                        }
                        else
                        {
                            // (a<->b) = (!a && !b) || (a && b)
                            return new LTLNode(type_t.T_OR,
                                               new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)),
                                               new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF()));
                        }
                    }
                case type_t.T_NOT:
                    if (negate)
                    {
                        // double negation
                        return getLeft().toPNF();////////////////////?? shouldn't be getRight().toPNF()?            !(!a) = a
                    }
                    else
                    {
                        if (getLeft().getType() == type_t.T_AP)
                        {
                            // we are in front of an AP, negation is ok
                            return new LTLNode(type_t.T_NOT, getLeft());
                        }
                        else
                        {
                            return getLeft().toPNF(true);
                        }
                    }
                case type_t.T_AP:
                    if (negate)
                    {
                        return new LTLNode(type_t.T_NOT, new LTLNode(_ap));
                    }
                    else
                    {
                        return new LTLNode(_ap);
                    }
                case type_t.T_TRUE:
                    if (negate)
                    {
                        return new LTLNode(type_t.T_FALSE, null);
                    }
                    else
                    {
                        return new LTLNode(type_t.T_TRUE, null);
                    }
                case type_t.T_FALSE:
                    if (negate)
                    {
                        return new LTLNode(type_t.T_TRUE, null);
                    }
                    else
                    {
                        return new LTLNode(type_t.T_FALSE, null);
                    }
                case type_t.T_AND:
                    // ! (a & b) = (!a | !b)
                    if (negate)
                    {
                        return new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF(true));
                    }
                    else
                    {
                        return new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF());
                    }
                case type_t.T_OR:
                    if (negate)
                    {
                        // ! (a | b) = (!a & !b)
                        return new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true));
                    }
                    else
                    {
                        return new LTLNode(type_t.T_OR, getLeft().toPNF(), getRight().toPNF());
                    }
                case type_t.T_NEXTSTEP:
                    // ! (X a) = X (!a)
                    if (negate)
                    {
                        return new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF(true));
                    }
                    else
                    {
                        return new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF());
                    }
                case type_t.T_FINALLY:
                    // ! (F a) = G (!a) = f V !a
                    if (negate)
                    {
                        return new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF(true));
                    }
                    else
                    { // F a = t U a
                        return new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF());
                    }
                case type_t.T_GLOBALLY:
                    // ! (G a) = F (!a) = t U ! a
                    if (negate)
                    {
                        return new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF(true));
                    }
                    else
                    { // f V a
                        return new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF());
                    }
                case type_t.T_UNTIL:
                    // ! (a U b) = (!a V !b)
                    if (negate)
                    {
                        return new LTLNode(type_t.T_RELEASE, getLeft().toPNF(true), getRight().toPNF(true));
                    }
                    else
                    {
                        return new LTLNode(type_t.T_UNTIL, getLeft().toPNF(), getRight().toPNF());
                    }
                case type_t.T_RELEASE:
                    // ! (a R b) = (!a U !b)
                    if (negate)
                    {
                        return new LTLNode(type_t.T_UNTIL, getLeft().toPNF(true), getRight().toPNF(true));
                    }
                    else
                    {
                        return new LTLNode(type_t.T_RELEASE,
                                       getLeft().toPNF(),
                                       getRight().toPNF());
                    }
                case type_t.T_WEAKUNTIL:
                    {
                        LTLNode weak_until = new LTLNode(type_t.T_UNTIL, getLeft(),
                                                         new LTLNode(type_t.T_OR, getRight(),
                                                              new LTLNode(type_t.T_GLOBALLY, getLeft(), null)));
                        return weak_until.toPNF(negate);
                    }
                case type_t.T_WEAKRELEASE:
                    throw new Exception("Operator WEAKRELEASE not yet supported");
                case type_t.T_BEFORE:
                    throw new Exception("Operator BEFORE not yet supported");
            }

            throw new Exception("Implementation error");
        }
예제 #8
0
        /**
         * Get a LTLFormula_ptr for the subformula rooted at subroot
         */
        public LTLFormula getSubFormula(LTLNode subroot)
        {
            LTLFormula sub = new LTLFormula(subroot, _apset);

            return(sub);
        }
예제 #9
0
 /** Constructor for an operator of type */
 public LTLNode(type_t type, LTLNode left, LTLNode right)
 {
     _type = type;
     _left = left;
     _right = right;
 }
예제 #10
0
        /**
           * Generate formula in DNF. Formula has to have only
           * AND, OR, TRUE, FALSE, ! as operators, and has to
           * be in PNF
           */
        public LTLNode toDNF()
        {
            switch (_type)
            {
                case type_t.T_TRUE:
                    return new LTLNode(type_t.T_TRUE, null);
                case type_t.T_FALSE:
                    return new LTLNode(type_t.T_FALSE, null);
                case type_t.T_NOT:
                    return new LTLNode(type_t.T_NOT, getLeft().toDNF());
                case type_t.T_AP:
                    return new LTLNode(getAP());
                case type_t.T_OR:
                    return new LTLNode(type_t.T_OR,
                               getLeft().toDNF(),
                               getRight().toDNF());
                case type_t.T_AND:
                    {
                        LTLNode left = getLeft().toDNF();
                        LTLNode right = getRight().toDNF();

                        if (left.getType() == type_t.T_OR)
                        {

                            LTLNode a = left.getLeft();
                            LTLNode b = left.getRight();

                            if (right.getType() == type_t.T_OR)
                            {

                                LTLNode c = right.getLeft();
                                LTLNode d = right.getRight();

                                LTLNode a_c = new LTLNode(type_t.T_AND, a, c),
                                  b_c = new LTLNode(type_t.T_AND, b, c),
                                  a_d = new LTLNode(type_t.T_AND, a, d),
                                  b_d = new LTLNode(type_t.T_AND, b, d);

                                return new LTLNode(type_t.T_OR,
                                           new LTLNode(type_t.T_OR, a_c, b_c).toDNF(),
                                           new LTLNode(type_t.T_OR, a_d, b_d).toDNF());
                            }
                            else
                            {
                                LTLNode
                                  a_c = new LTLNode(type_t.T_AND, a, right),
                                  b_c = new LTLNode(type_t.T_AND, b, right);

                                return new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF());
                            }
                        }
                        else if (right.getType() == type_t.T_OR)
                        {
                            LTLNode a, b;
                            a = right.getLeft();
                            b = right.getRight();

                            LTLNode
                              a_c = new LTLNode(type_t.T_AND, left, a),
                              b_c = new LTLNode(type_t.T_AND, left, b);

                            return new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF());
                        }
                        else
                        {
                            return new LTLNode(type_t.T_AND, left, right);
                        }
                    }
                default:
                    throw new Exception("Illegal operator for DNF!");
            }
        }
예제 #11
0
 public LTLNode(type_t type, LTLNode left)
     : this(type, left, null)
 {
 }
예제 #12
0
 /** Constructor for a node containing an atomic proposition (index into APSet) */
 public LTLNode(int ap)
 {
     _type = type_t.T_AP;
     _left = null;
     _right = null;
     _ap = ap;
 }
예제 #13
0
 /** Return an LTLFormula_ptr of the negation of this formula */
 public LTLFormula negate()
 {
     LTLNode new_root = new LTLNode(type_t.T_NOT, getRootNode());
     return new LTLFormula(new_root, _apset);
 }
예제 #14
0
 /** Copy constructor (not deep) */
 public LTLFormula(LTLFormula other)
 {
     _root  = other._root;
     _apset = other._apset;
 }
예제 #15
0
 /**
  * Constructor
  * @param root the root node
  * @param apset the underlying APSet
  */
 public LTLFormula(LTLNode root, APSet apset)
 {
     _root = root;
     _apset = apset;
 }
예제 #16
0
 /** Constructor for an operator of type */
 public LTLNode(type_t type, LTLNode left, LTLNode right)
 {
     _type  = type;
     _left  = left;
     _right = right;
 }
예제 #17
0
 /** Copy constructor (not deep) */
 public LTLFormula(LTLFormula other)
 {
     _root = other._root;
     _apset = other._apset;
 }
예제 #18
0
        /** Return an LTLFormula_ptr of the negation of this formula */
        public LTLFormula negate()
        {
            LTLNode new_root = new LTLNode(type_t.T_NOT, getRootNode());

            return(new LTLFormula(new_root, _apset));
        }
예제 #19
0
        public LTLNode toPNF(bool negate)
        {
            switch (_type)
            {
            case type_t.T_XOR:
                throw new Exception("XOR not yet supported!");

            case type_t.T_IMPLICATE:
            {
                if (negate)
                {
                    // ! (a->b) = !(!a | b) = (a & ! b)
                    return(new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)));
                }
                else
                {
                    // (a->b) = (!a | b)
                    return(new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF()));
                }
                break;
            }

            case type_t.T_EQUIV:
            {
                if (negate)
                {
                    // ! (a<->b) == (a & !b) || (!a & b)
                    return(new
                           LTLNode(type_t.T_OR,
                                   new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)),
                                   new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF())));
                }
                else
                {
                    // (a<->b) = (!a && !b) || (a && b)
                    return(new LTLNode(type_t.T_OR,
                                       new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)),
                                       new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF())));
                }
            }

            case type_t.T_NOT:
                if (negate)
                {
                    // double negation
                    return(getLeft().toPNF());   ////////////////////?? shouldn't be getRight().toPNF()?            !(!a) = a
                }
                else
                {
                    if (getLeft().getType() == type_t.T_AP)
                    {
                        // we are in front of an AP, negation is ok
                        return(new LTLNode(type_t.T_NOT, getLeft()));
                    }
                    else
                    {
                        return(getLeft().toPNF(true));
                    }
                }

            case type_t.T_AP:
                if (negate)
                {
                    return(new LTLNode(type_t.T_NOT, new LTLNode(_ap)));
                }
                else
                {
                    return(new LTLNode(_ap));
                }

            case type_t.T_TRUE:
                if (negate)
                {
                    return(new LTLNode(type_t.T_FALSE, null));
                }
                else
                {
                    return(new LTLNode(type_t.T_TRUE, null));
                }

            case type_t.T_FALSE:
                if (negate)
                {
                    return(new LTLNode(type_t.T_TRUE, null));
                }
                else
                {
                    return(new LTLNode(type_t.T_FALSE, null));
                }

            case type_t.T_AND:
                // ! (a & b) = (!a | !b)
                if (negate)
                {
                    return(new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF(true)));
                }
                else
                {
                    return(new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF()));
                }

            case type_t.T_OR:
                if (negate)
                {
                    // ! (a | b) = (!a & !b)
                    return(new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)));
                }
                else
                {
                    return(new LTLNode(type_t.T_OR, getLeft().toPNF(), getRight().toPNF()));
                }

            case type_t.T_NEXTSTEP:
                // ! (X a) = X (!a)
                if (negate)
                {
                    return(new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF(true)));
                }
                else
                {
                    return(new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF()));
                }

            case type_t.T_FINALLY:
                // ! (F a) = G (!a) = f V !a
                if (negate)
                {
                    return(new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF(true)));
                }
                else
                {     // F a = t U a
                    return(new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF()));
                }

            case type_t.T_GLOBALLY:
                // ! (G a) = F (!a) = t U ! a
                if (negate)
                {
                    return(new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF(true)));
                }
                else
                {     // f V a
                    return(new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF()));
                }

            case type_t.T_UNTIL:
                // ! (a U b) = (!a V !b)
                if (negate)
                {
                    return(new LTLNode(type_t.T_RELEASE, getLeft().toPNF(true), getRight().toPNF(true)));
                }
                else
                {
                    return(new LTLNode(type_t.T_UNTIL, getLeft().toPNF(), getRight().toPNF()));
                }

            case type_t.T_RELEASE:
                // ! (a R b) = (!a U !b)
                if (negate)
                {
                    return(new LTLNode(type_t.T_UNTIL, getLeft().toPNF(true), getRight().toPNF(true)));
                }
                else
                {
                    return(new LTLNode(type_t.T_RELEASE,
                                       getLeft().toPNF(),
                                       getRight().toPNF()));
                }

            case type_t.T_WEAKUNTIL:
            {
                LTLNode weak_until = new LTLNode(type_t.T_UNTIL, getLeft(),
                                                 new LTLNode(type_t.T_OR, getRight(),
                                                             new LTLNode(type_t.T_GLOBALLY, getLeft(), null)));
                return(weak_until.toPNF(negate));
            }

            case type_t.T_WEAKRELEASE:
                throw new Exception("Operator WEAKRELEASE not yet supported");

            case type_t.T_BEFORE:
                throw new Exception("Operator BEFORE not yet supported");
            }

            throw new Exception("Implementation error");
        }
예제 #20
0
        private static LTLNode TranslateLTL(ltl2ba.Node CurrentNode, APSet apset, APSet predefined_apset)
        {
            if (CurrentNode == null)
            {
                return(null);
            }

            type_t nodeType = type_t.T_TRUE;

            switch ((Operator)CurrentNode.ntyp)
            {
            case Operator.ALWAYS:
                nodeType = type_t.T_GLOBALLY;
                break;

            case Operator.AND:
                nodeType = type_t.T_AND;
                break;

            case Operator.EQUIV:
                nodeType = type_t.T_EQUIV;
                break;

            case Operator.EVENTUALLY:
                nodeType = type_t.T_FINALLY;
                break;

            case Operator.FALSE:
                nodeType = type_t.T_FALSE;
                break;

            case Operator.IMPLIES:
                nodeType = type_t.T_IMPLICATE;
                break;

            case Operator.NOT:
                nodeType = type_t.T_NOT;
                break;

            case Operator.OR:
                nodeType = type_t.T_OR;
                break;

            case Operator.TRUE:
                nodeType = type_t.T_TRUE;
                break;

            case Operator.U_OPER:
                nodeType = type_t.T_UNTIL;
                break;

            case Operator.V_OPER:
                nodeType = type_t.T_RELEASE;
                break;

            case Operator.NEXT:
                nodeType = type_t.T_NEXTSTEP;
                break;

            case Operator.PREDICATE:
                nodeType = type_t.T_AP;

                string ap = CurrentNode.sym.name;
                char   ch = ap[0];

                if (ch == '"')
                {
                    //	std::cerr << ap << std::endl;
                    Debug.Assert(ap[ap.Length - 1] == '"');     // last char is "

                    if (ap.Length <= 2)
                    {
                        // empty ap!
                        throw new Exception("LTL-Parse-Error: empty quoted string");
                    }


                    ap = ap.Substring(1, ap.Length - 2);     // cut quotes
                }
                else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
                {
                    // nop
                }
                else
                {
                    throw new Exception("LTL-Parse-Error");
                }

                int ap_i;     // the AP index

                if (predefined_apset != null)
                {
                    if ((ap_i = predefined_apset.find(ap)) != -1)
                    {
                        return(new LTLNode(ap_i));
                    }
                    else
                    {
                        // not found in predefined APSet!
                        //std::cerr << "[" << (int)s[2] << "]" << std::endl;
                        throw new Exception("Can't parse formula with this APSet!");
                    }
                }
                else
                {
                    if ((ap_i = apset.find(ap)) != -1)
                    {
                        // AP exists already
                        return(new LTLNode(ap_i));
                    }
                    else
                    {
                        // create new AP
                        ap_i = apset.addAP(ap);
                        return(new LTLNode(ap_i));
                    }
                }
                break;


            default:
                break;
            }



            LTLNode newNode = new LTLNode(nodeType, TranslateLTL(CurrentNode.lft, apset, predefined_apset),
                                          TranslateLTL(CurrentNode.rgt, apset, predefined_apset));


            return(newNode);
        }
예제 #21
0
        private static LTLNode TranslateLTL(ltl2ba.Node CurrentNode, APSet apset, APSet predefined_apset)
        {
            if (CurrentNode == null)
            {
                return null;
            }

            type_t nodeType = type_t.T_TRUE;
            switch ((Operator) CurrentNode.ntyp)
            {
                case Operator.ALWAYS:
                    nodeType = type_t.T_GLOBALLY;
                    break;
                case Operator.AND:
                    nodeType = type_t.T_AND;
                    break;
                case Operator.EQUIV:
                    nodeType = type_t.T_EQUIV;
                    break;
                case Operator.EVENTUALLY:
                    nodeType = type_t.T_FINALLY;
                    break;
                case Operator.FALSE:
                    nodeType = type_t.T_FALSE;
                    break;
                case Operator.IMPLIES:
                    nodeType = type_t.T_IMPLICATE;
                    break;
                case Operator.NOT:
                    nodeType = type_t.T_NOT;
                    break;
                case Operator.OR:
                    nodeType = type_t.T_OR;
                    break;
                case Operator.TRUE:
                    nodeType = type_t.T_TRUE;
                    break;
                case Operator.U_OPER:
                    nodeType = type_t.T_UNTIL;
                    break;
                case Operator.V_OPER:
                    nodeType = type_t.T_RELEASE;
                    break;
                case Operator.NEXT:
                    nodeType = type_t.T_NEXTSTEP;
                    break;
                case Operator.PREDICATE:
                    nodeType = type_t.T_AP;

                    string ap = CurrentNode.sym.name;
                    char ch = ap[0];

                    if (ch == '"')
                    {
                        //	std::cerr << ap << std::endl;
                        Debug.Assert(ap[ap.Length - 1] == '"'); // last char is "

                        if (ap.Length <= 2)
                        {
                            // empty ap!
                            throw new Exception("LTL-Parse-Error: empty quoted string");
                        }

                        ap = ap.Substring(1, ap.Length - 2); // cut quotes
                    }
                    else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
                    {
                        // nop
                    }
                    else
                    {
                        throw new Exception("LTL-Parse-Error");
                    }

                    int ap_i; // the AP index

                    if (predefined_apset != null)
                    {
                        if ((ap_i = predefined_apset.find(ap)) != -1)
                        {
                            return new LTLNode(ap_i);
                        }
                        else
                        {
                            // not found in predefined APSet!
                            //std::cerr << "[" << (int)s[2] << "]" << std::endl;
                            throw new Exception("Can't parse formula with this APSet!");
                        }
                    }
                    else
                    {
                        if ((ap_i = apset.find(ap)) != -1)
                        {
                            // AP exists already
                            return new LTLNode(ap_i);
                        }
                        else
                        {
                            // create new AP
                            ap_i = apset.addAP(ap);
                            return new LTLNode(ap_i);
                        }
                    }
                    break;

                default:
                    break;

            }

            LTLNode newNode = new LTLNode(nodeType, TranslateLTL(CurrentNode.lft, apset, predefined_apset),
                                          TranslateLTL(CurrentNode.rgt, apset, predefined_apset));

            return newNode;
        }