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 Diff line number Diff line
@@ -9,7 +9,8 @@ def make_dfa(states: Set[str], characters: Set[str],

    new_init = State(init)
    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:
        state = State(name)
@@ -181,16 +182,21 @@ def main():
    print(parser.dfa_to_str(dfa_4, True))
    print()
    dfareg = dfa_4.dfa_to_reg()
    print("DFA transformated to REG:")
    print("DFA transformed to REG:")
    print(parser.reg_to_str(dfareg, True))
    print()
    regdfa = dfareg.reg_to_nfa()
    print("REG transformated to NFA:")
    print("REG transformed to NFA:")
    print(parser.nfa_to_str(regdfa, True))
    print()

    #det = nfa1.determinize()
    #print(parser.dfa_to_str(det, True))
    print("__________________________________")
    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("DFA.is_equivalent()")
+31 −38
Original line number Diff line number Diff line
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
import enum
from copy import deepcopy
@@ -69,7 +69,7 @@ class State:


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

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

                # 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)
                    if (state, character) in transition:
                        transition[state, character].add(final)
@@ -186,7 +186,8 @@ class DFA:
        for (state, character) in self.transition:
            assert state in self.states, "unknown state " + state.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"
        for state in self.final:
@@ -331,17 +332,8 @@ class DFA:

        return dfa

    # TODO sorted(set, key = lambda x: x.name) sorted_terminals
    def sort_characters(self) -> List[Character]:
        to_sort = list(deepcopy(self.characters))
        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
        return sorted(self.characters, key=lambda x: x.name)

    def minimize(self) -> DFA:
        dfa = deepcopy(self)
@@ -450,7 +442,7 @@ class DFA:
    def dfa_to_reg(self) -> REG:
        nonterminals: Set[Nonterminal] = 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:
            nonterminal = Nonterminal(state.name)
@@ -473,7 +465,7 @@ class DFA:
                else:
                    rules[init] = {(terminal, nonterminal2)}
                if move in self.final:
                    rules[init].add((terminal))
                    rules[init].add(terminal)
            else:
                nonterminal1 = Nonterminal(state.name)
                nonterminal2 = Nonterminal(move.name)
@@ -508,7 +500,7 @@ class DFA:

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

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

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

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

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

            done.add(subset)

        new_states: Set[State] = set()
        new_transition: Dict[Tuple[State, Character], State] = dict()
        new_final: Set[State] = set()
        for state in states:
            new_states.add(self.unset(state))
        for state in final:
            new_final.add(self.unset(state))
        for state, character in transition:
            new_transition[self.unset(state), character] = self.unset(self.transition[state, character])

        for state_set in states:
            new_states.add(self.unset(state_set))
        for state_set in final:
            new_final.add(self.unset(state_set))
        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)
        return dfa

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

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

    # would be function for in epsilon NFA
    def eliminate_epsilon(self) -> NFA:
+8 −8
Original line number Diff line number Diff line
from typing import List, Dict, Tuple, Optional
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?
@@ -38,7 +38,7 @@ class Parser:

            out += (rule.name + "->")
            for variant in rewrite:
                if type(variant) == Terminal:
                if isinstance(variant, Terminal):
                    out += variant.name
                else:
                    for i in range(len(variant)):
@@ -88,24 +88,24 @@ class Parser:
            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

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

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

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

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

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

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