示例#1
0
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return(false);
            }

            ASTOpUnary other = obj as ASTOpUnary;

            return(this.value == other.value && this.ast.Equals(other.ast));
        }
示例#2
0
        private void Extract(AST astInCNF)
        {
            switch (astInCNF.GetType().Name)
            {
            case "ASTProp":
                char letter = (astInCNF as ASTProp).value;
                m_content.Add(new Component(letter));
                break;

            case "ASTOpUnary":
                ASTOpUnary astNeg = astInCNF as ASTOpUnary;
                if (astNeg.ast.GetType().Name != "ASTProp")
                {       // In CNF form, the negation can only refers to a simple proposition.
                    throw new Exception("Error creating a CnfOr : In CNF form, the negation can only refers to a simple proposition.");
                }
                letter = (astNeg.ast as ASTProp).value;
                m_content.Add(new Component(letter, true));
                break;

            case "ASTOpBinary":
                ASTOpBinary opBin = astInCNF as ASTOpBinary;
                switch (opBin.value)
                {
                case Language.Symbol.OU:                // Form (A|B).
                    Extract(opBin.left);
                    Extract(opBin.right);
                    break;

                case Language.Symbol.E:                // Form (A&B).
                case Language.Symbol.IMPLICA:          // Form (P->Q).
                case Language.Symbol.EQUIVALE:         // Form (P<->Q).
                    throw new Exception("Error creating a CnfOr : In CNF form, OR formulas can't contain other operators than OR.");
                }
                break;
            }
        }
示例#3
0
        /// <summary>
        /// Parsing recursive implementation.
        /// </summary>
        /// <param name="precede">does precedence must be considered in this recursive call?</param>
        /// <returns>the resulting AST node.</returns>
        AST Walk(bool precede = false)
        {
            // Increment the global index.
            m_idx++;
            if (m_idx >= Tokens.Count)
            {
                return(null);
            }

            // Read the current index's token value.
            Token token = Tokens[m_idx];

            AST ast = null;

            switch (token.type)
            {
            case Language.Symbol.PROP:              // a propositional letter.
                ast = new ASTProp(token.value);
                break;

            case Language.Symbol.NAO:               // negation operation.
                ast = new ASTOpUnary(Walk(true), token.type);
                break;

            case Language.Symbol.E:                 // conjunction operation.
            case Language.Symbol.OU:                // disjunction operation.
                ast = new ASTOpBinary(m_current, Walk(true), token.type);
                break;

            case Language.Symbol.IMPLICA:      // implication operation.
            case Language.Symbol.EQUIVALE:     // double implication operation.
                // double implication has lesser precedence over single implication.
                bool bi = token.type == Language.Symbol.EQUIVALE;
                // must continue to parse?
                bool forward =                           // we continue parsing if...
                               m_implFlag == 0 ||        // ... there is no implications awaiting or ...
                               (m_implFlag == 2 && !bi); // ... a double implication awaits and the current is a single implication.
                if (forward)
                {                                        // must continue the parsing.
                        // save current implication flag value...
                    int implications = m_implFlag;
                    // and update the global value.
                    m_implFlag = bi ? 2 : 1;
                    // enter another recursion.
                    ast = new ASTOpBinary(m_current, Walk(false), token.type);
                    // did the last recursive call finished precedence analysis?
                    if (m_implFlag == 0)
                    {
                        precede = false;
                    }
                    // restore previous (saved) implication flag value.
                    m_implFlag = implications;
                }
                else
                {       // must not continue and must return to the last call.
                    m_idx--;
                    ast        = m_current;
                    precede    = true;
                    m_implFlag = 0;
                    break;
                }
                break;

            case Language.Symbol.ABERTURA:          // opening expression symbol.
                // enter a new recursive call, as an AST node must come from the parenthesis' content analysis.
                while (Walk(precede) != null)
                {
                    ast = m_current;
                }
                break;

            case Language.Symbol.FECHAMENTO:        // closing expression symbol.
                return(null);
            }

            // update current AST node.
            m_current = ast;

            // continue the processing as long as there are tokens and no precedence.
            if (!precede && m_idx < Tokens.Count)
            {
                Walk();
            }

            return(m_current);
        }
示例#4
0
        }  // Extractor class

        #endregion Inner classes

        #region Public functions

        /// <summary>
        /// Convert the formula to conjuntive normal form.
        /// </summary>
        /// <param name="ast">original abstract syntatic tree representinf the formula.</param>
        /// <returns>formula in CNF.</returns>
        public static AST Convert(AST ast)
        {
            if (ast == null)
            {
                return(ast);
            }

            switch (ast.GetType().Name)
            {
            case "ASTProp":
                return(ast);

            case "ASTOpBinary":
                ASTOpBinary opBin = ast as ASTOpBinary;
                switch (opBin.value)
                {
                case Language.Symbol.E:                 // Form (P&Q).
                    AST left  = Convert(opBin.left);
                    AST right = Convert(opBin.right);
                    return(new ASTOpBinary(left, right, Language.Symbol.E));

                case Language.Symbol.OU:                // Form (P|Q).
                    left  = Convert(opBin.left);
                    right = Convert(opBin.right);
                    return(Distribute(left, right));

                case Language.Symbol.IMPLICA:           // Form (P->Q). Equivalent to (~P|Q)
                    return(Convert(
                               new ASTOpBinary(
                                   new ASTOpUnary(opBin.left, Language.Symbol.NAO),
                                   opBin.right, Language.Symbol.OU)
                               ));

                case Language.Symbol.EQUIVALE:         // Form (P<->Q). Equivalent to (P&Q)|(~P&~Q).
                    left  = new ASTOpBinary(opBin.left, opBin.right, Language.Symbol.E);
                    right = new ASTOpBinary(
                        new ASTOpUnary(opBin.left, Language.Symbol.NAO),
                        new ASTOpUnary(opBin.right, Language.Symbol.NAO),
                        Language.Symbol.E
                        );
                    return(Convert(new ASTOpBinary(left, right, Language.Symbol.OU)));
                }
                break;

            case "ASTOpUnary":
                AST p = (ast as ASTOpUnary).ast;
                switch (p.GetType().Name)
                {
                case "ASTProp":                 // Form ~P ... return ~P
                    return(ast);

                case "ASTOpUnary":              // Form ~(~P) - double negation ... return Convert(P)
                    return(Convert((p as ASTOpUnary).ast));

                case "ASTOpBinary":
                    opBin = (ASTOpBinary)p;
                    Language.Symbol op = opBin.value;
                    if (op != Language.Symbol.E && op != Language.Symbol.OU)
                    {         // Not yet in CNF.
                        AST pInNcf = Convert(p);
                        return(Convert(new ASTOpUnary(pInNcf, Language.Symbol.NAO)));
                    }
                    AST             left       = new ASTOpUnary(opBin.left, Language.Symbol.NAO);
                    AST             right      = new ASTOpUnary(opBin.right, Language.Symbol.NAO);
                    Language.Symbol deMorganOp = Language.Symbol.INVALIDO;
                    if (opBin.value == Language.Symbol.E)
                    {
                        // Form ~(P&Q): from DeMorgan's Law, return Convert(~P|~Q)
                        deMorganOp = Language.Symbol.OU;
                    }
                    else if (opBin.value == Language.Symbol.OU)
                    {
                        // Form ~(P|Q): from DeMorgan's Law, return Convert(~P&~Q)
                        deMorganOp = Language.Symbol.E;
                    }
                    return(Convert(new ASTOpBinary(left, right, deMorganOp)));
                }
                break;
            }

            return(null);
        }
示例#5
0
 public NegationProposition(ASTOpUnary ast) : base(ast)
 {
 }
示例#6
0
 // transitional constructor.
 public UnaryOperation(ASTOpUnary ast)
 {
     P = Proposition.FromAST(ast.ast);
 }