Commit 9932bacd authored by Kateřina Sloupová's avatar Kateřina Sloupová
Browse files

this should finally typecheck

parent 1ff54cfa
Loading
Loading
Loading
Loading
Loading
+11 −5
Original line number Original line Diff line number Diff line
@@ -9,7 +9,8 @@ def make_dfa(states: Set[str], characters: Set[str],


    new_init = State(init)
    new_init = State(init)
    new_states: Set[State] = set()
    new_states: Set[State] = set()
    dfa = DFA(new_states.add(new_init), set(), {}, new_init, set())
    new_states.add(new_init)
    dfa = DFA(new_states, set(), {}, new_init, set())


    for name in states:
    for name in states:
        state = State(name)
        state = State(name)
@@ -181,16 +182,21 @@ def main():
    print(parser.dfa_to_str(dfa_4, True))
    print(parser.dfa_to_str(dfa_4, True))
    print()
    print()
    dfareg = dfa_4.dfa_to_reg()
    dfareg = dfa_4.dfa_to_reg()
    print("DFA transformated to REG:")
    print("DFA transformed to REG:")
    print(parser.reg_to_str(dfareg, True))
    print(parser.reg_to_str(dfareg, True))
    print()
    print()
    regdfa = dfareg.reg_to_nfa()
    regdfa = dfareg.reg_to_nfa()
    print("REG transformated to NFA:")
    print("REG transformed to NFA:")
    print(parser.nfa_to_str(regdfa, True))
    print(parser.nfa_to_str(regdfa, True))
    print()
    print()


    #det = nfa1.determinize()
    print("__________________________________")
    #print(parser.dfa_to_str(det, True))
    print("NFA.determinize()")
    print("Determinization of NFA to DFA:")
    det = nfa1.determinize()
    print(parser.nfa_to_str(nfa1, True))
    print()
    print(parser.dfa_to_str(det, True))


    print("__________________________________")
    print("__________________________________")
    print("DFA.is_equivalent()")
    print("DFA.is_equivalent()")
+31 −38
Original line number Original line Diff line number Diff line
from __future__ import annotations
from __future__ import annotations
from typing import Set, List, Dict, Tuple, Deque, Optional, TypeVar
from typing import Set, FrozenSet, List, Dict, Union, Tuple, Deque, Optional, TypeVar
from enum import Enum
from enum import Enum
import enum
import enum
from copy import deepcopy
from copy import deepcopy
@@ -69,7 +69,7 @@ class State:




class REG:
class REG:
    Rules = Dict[Nonterminal, Set[Tuple[Terminal, Optional[Nonterminal]]]]
    Rules = Dict[Nonterminal, Set[Union[Terminal, Tuple[Terminal, Nonterminal]]]]
    type_var = TypeVar('type_var')
    type_var = TypeVar('type_var')


    # TODO should accept init -> epsilon
    # TODO should accept init -> epsilon
@@ -97,7 +97,7 @@ class REG:
        for nonterminal in self.rules:
        for nonterminal in self.rules:
            assert nonterminal in self.nonterminals, "unknown nonterminal " + nonterminal.name
            assert nonterminal in self.nonterminals, "unknown nonterminal " + nonterminal.name
            for rule in self.rules[nonterminal]:
            for rule in self.rules[nonterminal]:
                if type(rule) == Terminal:
                if isinstance(rule, Terminal):
                    assert rule in self.terminals, "unknown terminal " + rule.name
                    assert rule in self.terminals, "unknown terminal " + rule.name
                else:
                else:
                    assert rule[0] in self.terminals, "unknown terminal " + rule[0].name
                    assert rule[0] in self.terminals, "unknown terminal " + rule[0].name
@@ -129,7 +129,7 @@ class REG:
            for rule in self.rules[nonterminal]:
            for rule in self.rules[nonterminal]:


                # rule A -> a becomes d(A, a) = final
                # rule A -> a becomes d(A, a) = final
                if type(rule) == Terminal:  # TODO and a is not \eps
                if isinstance(rule, Terminal):  # TODO and a is not \eps
                    character = Character(rule.name)
                    character = Character(rule.name)
                    if (state, character) in transition:
                    if (state, character) in transition:
                        transition[state, character].add(final)
                        transition[state, character].add(final)
@@ -186,7 +186,8 @@ class DFA:
        for (state, character) in self.transition:
        for (state, character) in self.transition:
            assert state in self.states, "unknown state " + state.name
            assert state in self.states, "unknown state " + state.name
            assert character in self.characters, "unknown character " + character.name
            assert character in self.characters, "unknown character " + character.name
            assert self.transition[state, character] in self.states, "unknown state " + self.transition[state, character].name
            assert self.transition[state, character] in self.states, "unknown state " + self.transition[
                state, character].name


        assert self.init in self.states, "init not in states"
        assert self.init in self.states, "init not in states"
        for state in self.final:
        for state in self.final:
@@ -331,17 +332,8 @@ class DFA:


        return dfa
        return dfa


    # TODO sorted(set, key = lambda x: x.name) sorted_terminals
    def sort_characters(self) -> List[Character]:
    def sort_characters(self) -> List[Character]:
        to_sort = list(deepcopy(self.characters))
        return sorted(self.characters, key=lambda x: x.name)
        names = []
        for character in to_sort:
            names.append((character.name, character))
        names.sort()
        sorted_characters = []
        for name, character in names:
            sorted_characters.append(character)
        return sorted_characters


    def minimize(self) -> DFA:
    def minimize(self) -> DFA:
        dfa = deepcopy(self)
        dfa = deepcopy(self)
@@ -450,7 +442,7 @@ class DFA:
    def dfa_to_reg(self) -> REG:
    def dfa_to_reg(self) -> REG:
        nonterminals: Set[Nonterminal] = set()
        nonterminals: Set[Nonterminal] = set()
        terminals: Set[Terminal] = set()
        terminals: Set[Terminal] = set()
        rules: Dict[Nonterminal, Set[Tuple[Terminal, Optional[Nonterminal]]]] = dict()
        rules: Dict[Nonterminal, Set[Union[Terminal, Tuple[Terminal, Nonterminal]]]] = dict()


        for state in self.states:
        for state in self.states:
            nonterminal = Nonterminal(state.name)
            nonterminal = Nonterminal(state.name)
@@ -473,7 +465,7 @@ class DFA:
                else:
                else:
                    rules[init] = {(terminal, nonterminal2)}
                    rules[init] = {(terminal, nonterminal2)}
                if move in self.final:
                if move in self.final:
                    rules[init].add((terminal))
                    rules[init].add(terminal)
            else:
            else:
                nonterminal1 = Nonterminal(state.name)
                nonterminal1 = Nonterminal(state.name)
                nonterminal2 = Nonterminal(move.name)
                nonterminal2 = Nonterminal(move.name)
@@ -508,7 +500,7 @@ class DFA:


    # Ha!
    # Ha!
    def is_universal(self):
    def is_universal(self):
        return self.is_empty(self.complement())
        return self.complement().is_empty()


    def is_equivalent(self, dfa: DFA) -> bool:
    def is_equivalent(self, dfa: DFA) -> bool:
        self.complement()
        self.complement()
@@ -543,42 +535,43 @@ class NFA:
        self.final = self.set_or_none(final)
        self.final = self.set_or_none(final)


    def determinize(self) -> DFA:
    def determinize(self) -> DFA:
        states = set(frozenset({self.init}))
        states: Set[FrozenSet[State]] = set()
        states.add(frozenset({self.init}))
        transition = {}
        transition = {}
        final = set()
        final = set()
        done: Set[State] = set()
        done: Set[FrozenSet[State]] = set()


        todo = states.difference(done)
        while len(states.difference(done)) > 0:
        while len(todo) > 0:
            subset = (states.difference(done)).pop()  # arbitrary element from set
            subset = iter(todo).next()  # arbitrary element from set
            if len(subset.intersection(self.final)) > 0:
            if subset.difference(self.final) > 0:
                final.add(subset)
                final.add(subset)
            for character in self.characters:
            for character in self.characters:
                new_subset = set()
                new_subset: Set[State] = set()
                for state in subset:
                for state in subset:
                    if (state, character) in self.transition:
                    if (state, character) in self.transition:
                        new_subset.add(self.transition[state, character])
                        new_subset = new_subset.union(self.transition[state, character])
                states.add(new_subset)

                transition[subset, character] = new_subset
                states.add(frozenset(new_subset))
                transition[subset, character] = frozenset(new_subset)


            done.add(subset)
            done.add(subset)


        new_states: Set[State] = set()
        new_states: Set[State] = set()
        new_transition: Dict[Tuple[State, Character], State] = dict()
        new_transition: Dict[Tuple[State, Character], State] = dict()
        new_final: Set[State] = set()
        new_final: Set[State] = set()
        for state in states:

            new_states.add(self.unset(state))
        for state_set in states:
        for state in final:
            new_states.add(self.unset(state_set))
            new_final.add(self.unset(state))
        for state_set in final:
        for state, character in transition:
            new_final.add(self.unset(state_set))
            new_transition[self.unset(state), character] = self.unset(self.transition[state, character])
        for state_set, character in transition:
            new_transition[self.unset(state_set), character] = self.unset(transition[state_set, character])


        dfa = DFA(new_states, self.characters, new_transition, self.init, new_final)
        dfa = DFA(new_states, self.characters, new_transition, self.init, new_final)
        return dfa
        return dfa


    def unset(self, states: Set[State]) -> State:
    def unset(self, states: FrozenSet[State]) -> State:
        return State('_'.join(set(map(lambda x: x.name, states))))
        return State('_'.join(set(map(lambda x: x.name, sorted(states, key=lambda x: x.name)))))



    # would be function for in epsilon NFA
    # would be function for in epsilon NFA
    def eliminate_epsilon(self) -> NFA:
    def eliminate_epsilon(self) -> NFA:
+8 −8
Original line number Original line Diff line number Diff line
from typing import List, Dict, Tuple, Optional
from typing import List, Dict, Tuple, Optional
import re
import re
from objects import REG, DFA, Terminal
from objects import REG, DFA, NFA, Terminal




# TODO ask: commas at the ends of lines or not?
# TODO ask: commas at the ends of lines or not?
@@ -38,7 +38,7 @@ class Parser:


            out += (rule.name + "->")
            out += (rule.name + "->")
            for variant in rewrite:
            for variant in rewrite:
                if type(variant) == Terminal:
                if isinstance(variant, Terminal):
                    out += variant.name
                    out += variant.name
                else:
                else:
                    for i in range(len(variant)):
                    for i in range(len(variant)):
@@ -88,24 +88,24 @@ class Parser:
            return transition + "\n" + final
            return transition + "\n" + final




    def nfa_to_str(self, dfa: DFA, full : bool = False) -> str:
    def nfa_to_str(self, nfa: NFA, full : bool = False) -> str:


        # full - verbose description of DFA - only for development, dismiss later
        # full - verbose description of DFA - only for development, dismiss later


        states = "{"
        states = "{"
        for state in dfa.states:
        for state in nfa.states:
            states += state.name + ","
            states += state.name + ","
        states = states[:-1] + "}"
        states = states[:-1] + "}"


        # Vlada: states = ",".join(dfa.states) but I use it wrong or what
        # Vlada: states = ",".join(dfa.states) but I use it wrong or what


        characters = "{"
        characters = "{"
        for character in dfa.characters:
        for character in nfa.characters:
            characters += character.name + ","
            characters += character.name + ","
        characters = characters[:-1] + "}"
        characters = characters[:-1] + "}"


        transition = ""
        transition = ""
        for key, set_states in dfa.transition.items():
        for key, set_states in nfa.transition.items():
            state_1, terminal = key
            state_1, terminal = key
            transition += "(" + state_1.name + "," + terminal.name + ")={"
            transition += "(" + state_1.name + "," + terminal.name + ")={"
            for state in set_states:
            for state in set_states:
@@ -113,10 +113,10 @@ class Parser:
            transition = transition[:-1] + "}\n"
            transition = transition[:-1] + "}\n"
        transition = "{" + transition[:-1] + "}"
        transition = "{" + transition[:-1] + "}"


        init = dfa.init.name
        init = nfa.init.name


        final = "F={"
        final = "F={"
        for state in dfa.final:
        for state in nfa.final:
            final += state.name + ","
            final += state.name + ","
        final = final[:-1] + "}"
        final = final[:-1] + "}"