Beispiel #1
0
def test_new_set_methods(a, b):
	# A whole bunch of new methods were added to the FSM module to enable FSMs to
	# function exactly as if they were sets of strings (symbol lists), see:
	# https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
	# But do they work?
	assert len(a) == 1
	assert len((a | b) * 4) == 16
	try:
		len(a.star())
		assert False
	except OverflowError:
		pass

	# "in"
	assert "a" in a
	assert not "a" in b
	assert "a" not in b

	# List comprehension!
	four = (a | b) * 2
	for string in four:
		assert string == ["a", "a"]
		break
	assert [s for s in four] == [["a", "a"], ["a", "b"], ["b", "a"], ["b", "b"]]

	# set.union() imitation
	assert FSM.union(a, b) == a.union(b)
	assert len(FSM.union()) == 0
	assert FSM.intersection(a, b) == a.intersection(b)

	# This takes a little explaining. In general, `a & b & c` is equivalent to
	# `EVERYTHING & a & b & c` where `EVERYTHING` is an FSM accepting every
	# possible string. Similarly `a` is equivalent to `EVERYTHING & a`, and the
	# intersection of no sets at all is... `EVERYTHING`.
	# However, since we compute the union of alphabets, and there are no
	# alphabets, the union is the empty set. So the only string which `EVERYTHING`
	# actually recognises is the empty string, [] (or "" if you prefer).
	int_none = FSM.intersection()
	assert len(int_none) == 1
	assert [] in int_none

	assert (a | b).difference(a) == FSM.difference((a | b), a) == (a | b) - a == b
	assert (a | b).difference(a, b) == FSM.difference((a | b), a, b) == (a | b) - a - b == null("ab")
	assert a.symmetric_difference(b) == FSM.symmetric_difference(a, b) == a ^ b
	assert a.isdisjoint(b)
	assert a <= (a | b)
	assert a < (a | b)
	assert a != (a | b)
	assert (a | b) > a
	assert (a | b) >= a

	assert list(a.concatenate(a, a).strings()) == [["a", "a", "a"]]
	assert list(a.concatenate().strings()) == [["a"]]
	assert list(FSM.concatenate(b, a, b).strings()) == [["b", "a", "b"]]
	assert list(FSM.concatenate().strings()) == []
	assert not a.copy() is a
Beispiel #2
0
    def to_fsm(self, alphabet=None, prefix_postfix=None, flags=None) -> FSM:
        if alphabet is None:
            alphabet = self.alphabet
        if prefix_postfix is None:
            prefix_postfix = self.prefix_postfix

        all = _ALL.to_fsm(alphabet)
        all_star = all.star()
        fsm_parts = []
        current = [all.times(prefix_postfix[0])]
        for part in self.parts:
            if isinstance(part, _NonCapturing):
                inner = part.inner.to_fsm(alphabet, (0, 0), flags)
                if part.backwards:
                    raise NotImplementedError("lookbacks are not implemented")
                else:
                    # try:
                    #     inner.cardinality()
                    # except OverflowError:
                    #     raise NotImplementedError("Can not deal with infinite length lookaheads")
                    fsm_parts.append((None, current))
                    fsm_parts.append((part, inner))
                    current = []
            else:
                current.append(part.to_fsm(alphabet, (0, 0), flags))
        current.append(all.times(prefix_postfix[1]))
        result = FSM.concatenate(*current)
        for m, f in reversed(fsm_parts):
            if m is None:
                result = FSM.concatenate(*f, result)
            else:
                assert isinstance(m, _NonCapturing) and not m.backwards
                if m.negate:
                    result = result.difference(f)
                else:
                    result = result.intersection(f + all_star)
        return result
Beispiel #3
0
def test_concatenate_bug(a):
	# This exposes a defect in fsm.concatenate.
	assert FSM.concatenate(a, epsilon({"a"}), a).accepts("aa")
	assert FSM.concatenate(a, epsilon({"a"}), epsilon({"a"}), a).accepts("aa")