def test_de_morgans_law(self):
        t = '''
            ((not (and (a) (or (b) (not (c))))))
            '''

        actual = logical_expression.build(s_expression.parse(t))
        actual = logical_expression.convert_to_nnf(actual)

        # !(a && (b || !c)) -> !a || !(b || c) -> !a || (!b && c)

        expected = node_type.LogicalOp(
            op = node_type.OP_OR,
            children = [
                node_type.LogicalOp(
                    op = node_type.OP_NOT,
                    children = [
                        node_type.Atom(name='a')
                        ]),

                node_type.LogicalOp(
                    op = node_type.OP_AND,
                    children = [
                            node_type.LogicalOp(
                                op = node_type.OP_NOT,
                                children = [node_type.Atom(name='b')]),

                            node_type.Atom(name='c'),
                        ])
                ])

        self.assertEqual(expected, actual)
    def test_neg_neg_is_pos(self):
        t = '''
            ((not (not (a))))
            '''

        actual = logical_expression.build(s_expression.parse(t))
        actual = logical_expression.convert_to_nnf(actual)

        expected = node_type.Atom(name='a')

        self.assertEqual(expected, actual)
    def test_no_conversion_is_required(self):
        t = '''
            ((or (a) (b)))
            '''

        actual = logical_expression.build(s_expression.parse(t))
        actual = logical_expression.convert_to_nnf(actual)

        expected = node_type.LogicalOp(
            op = node_type.OP_OR,
            children = [
                node_type.Atom(name='a'),
                node_type.Atom(name='b'),
                ])

        self.assertEqual(expected, actual)