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

this should finally typecheck

parent 1ff54cfa
Pipeline #53974 failed with stage
in 19 seconds
......@@ -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()")
......
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)
......@@ -500,7 +492,7 @@ class DFA:
actual = reached.popleft()
for character in self.characters:
if self.transition[actual, character] is not None and \
self.transition[actual, character] not in reachable:
self.transition[actual, character] not in reachable:
reached.append(self.transition[actual, character])
reachable.add(self.transition[actual, character])
......@@ -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:
......
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] + "}"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment