Loading .gitignore +2 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,5 @@ *.swo *~ __pycache__ .idea .pytest_cache fja_checker.py +2 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ def dfa_transform(string: str, automaton_type: str) -> reg.DFA: except reg.ParsingError as ex: print("Chyba při parsování.") exit(1) except Exception as ex: #except Exception as ex: print("Chyba při parsování.") exit(1) Loading Loading @@ -211,7 +211,7 @@ def main(): task_prefix, teacher_string = teacher_string.split(":", 1) teacher_type, task = get_task(task_prefix) if teacher_type == "DFA": if teacher_type == "DFA" or teacher_type == "NFA": dfa_task(teacher_type=teacher_type, teacher_string=teacher_string, task=task, student_string=student_string) elif teacher_type == "CFG": Loading grammars.py +29 −20 Original line number Diff line number Diff line Loading @@ -23,12 +23,21 @@ class RegGrammar: assert self.check() @staticmethod def reggrammar_from_cfg(cfg: CFG) -> RegGrammar: try: def from_cfg(cfg: CFG) -> RegGrammar: if cfg.is_regular(): return RegGrammar(cfg.nonterminals, cfg.terminals, cfg.rules, cfg.init) except: # I don't know pass reg_rules : RegGrammar.Rules = {} for nonterminal in cfg.rules: for rule in cfg.rules[nonterminal]: new_rule = rule # rule of type Tuple[Terminal] becomes of type Terminal, others are OK if isinstance(rule, tuple) and len(rule) == 1: new_rule = rule[0] reg_rules.setdefault(nonterminal, set()).add(new_rule) return RegGrammar(cfg.nonterminals, cfg.terminals, reg_rules, cfg.init) # exception # unused formal requirements check, regular grammars specific (rule variants) def check(self) -> bool: Loading @@ -48,38 +57,38 @@ class RegGrammar: return True def reggrammar_to_nfa(self) -> NFA: init = State(self.init.name) states: Set[State] = set() for nonterminal in self.nonterminals: states.add(State(nonterminal.name)) final = State("new_final") # TODO assert that name is unique, as for hell in make_total states.add(final) init = State(self.init.name) characters: Set[Character] = set() for terminal in self.terminals: characters.add(Character(terminal.name)) final = State("new_final") # TODO assert that name is unique, as for hell in make_total states.add(final) transition: Dict[Tuple[State, Character], Set[State]] = dict() for nonterminal in self.rules: state = State(nonterminal.name) for rule in self.rules[nonterminal]: # rule A -> a becomes d(A, a) = final if isinstance(rule, Terminal): # TODO and a is not \eps if isinstance(rule, Terminal): character = Character(rule.name) transition.setdefault((state, character), set()).add(final) # rule A -> aB becomes d(A, a) = B elif (state, rule[0]) in transition: elif isinstance(rule, Tuple): character = Character(rule[0].name) transition[state, character].add(State(rule[1].name)) else: character = Character(rule[0].name) transition[state, character] = {State(rule[1].name)} transition.setdefault((state, character), set()).add(State(rule[1].name)) final_states = {final} for rule in self.rules[self.init]: if isinstance(rule, Eps): final_states.add(init) # TODO if init -> \eps: nfa.final.add(nfa.init) # I need to know how to treat \eps nfa = NFA(states, characters, transition, init, {final}) nfa = NFA(states, characters, transition, init, final_states) return nfa No newline at end of file grammars_cfg.py +2 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ class CFG: if nonterminal == self.init and not self.is_nonterminal_used(nonterminal): continue else: print("Gramatika není regulární: výskyt epsilon u neterminálu, který se vyskytuje na pravé straně některého pravidla.") #print("Gramatika není regulární: výskyt epsilon u neterminálu, který se vyskytuje na pravé straně některého pravidla.") return False if isinstance(rule, tuple): # TODO nicer Loading @@ -170,7 +170,7 @@ class CFG: (len(rule) == 2 and isinstance(rule[0], Terminal) and isinstance(rule[1], Nonterminal)): continue print("Gramatika není regulární: špatný tvar pravé strany některého z pravidel.") #print("Gramatika není regulární: špatný tvar pravé strany některého z pravidel.") return False return True Loading parser.py +7 −6 Original line number Diff line number Diff line Loading @@ -115,8 +115,9 @@ class Parser: return CFG(listener.nonterminals, listener.terminals, listener.rules, listener.init) def str_to_reggrammar(self): pass def str_to_reggrammar(self, string: str) -> RegGrammar: cfg = self.str_to_cfg(string) return RegGrammar.from_cfg(cfg) def str_to_dfa(self, string: str) -> DFA: listener = self.common_parse(string, DFALexer, DFAParser, DFAListener) Loading Loading @@ -205,6 +206,7 @@ class NFAListener(NFAListener): self.efa = False def exitInit(self, ctx): if ctx.statename() is not None: state = State(str(ctx.statename().STATE())) self.init = state self.states.add(state) Loading @@ -212,7 +214,6 @@ class NFAListener(NFAListener): def exitProduction(self, ctx): state = State(str(ctx.statename(0).STATE())) self.states.add(state) dest_states = set() i = 0 while ctx.stateset().statename(i) is not None: Loading Loading
.gitignore +2 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,5 @@ *.swo *~ __pycache__ .idea .pytest_cache
fja_checker.py +2 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ def dfa_transform(string: str, automaton_type: str) -> reg.DFA: except reg.ParsingError as ex: print("Chyba při parsování.") exit(1) except Exception as ex: #except Exception as ex: print("Chyba při parsování.") exit(1) Loading Loading @@ -211,7 +211,7 @@ def main(): task_prefix, teacher_string = teacher_string.split(":", 1) teacher_type, task = get_task(task_prefix) if teacher_type == "DFA": if teacher_type == "DFA" or teacher_type == "NFA": dfa_task(teacher_type=teacher_type, teacher_string=teacher_string, task=task, student_string=student_string) elif teacher_type == "CFG": Loading
grammars.py +29 −20 Original line number Diff line number Diff line Loading @@ -23,12 +23,21 @@ class RegGrammar: assert self.check() @staticmethod def reggrammar_from_cfg(cfg: CFG) -> RegGrammar: try: def from_cfg(cfg: CFG) -> RegGrammar: if cfg.is_regular(): return RegGrammar(cfg.nonterminals, cfg.terminals, cfg.rules, cfg.init) except: # I don't know pass reg_rules : RegGrammar.Rules = {} for nonterminal in cfg.rules: for rule in cfg.rules[nonterminal]: new_rule = rule # rule of type Tuple[Terminal] becomes of type Terminal, others are OK if isinstance(rule, tuple) and len(rule) == 1: new_rule = rule[0] reg_rules.setdefault(nonterminal, set()).add(new_rule) return RegGrammar(cfg.nonterminals, cfg.terminals, reg_rules, cfg.init) # exception # unused formal requirements check, regular grammars specific (rule variants) def check(self) -> bool: Loading @@ -48,38 +57,38 @@ class RegGrammar: return True def reggrammar_to_nfa(self) -> NFA: init = State(self.init.name) states: Set[State] = set() for nonterminal in self.nonterminals: states.add(State(nonterminal.name)) final = State("new_final") # TODO assert that name is unique, as for hell in make_total states.add(final) init = State(self.init.name) characters: Set[Character] = set() for terminal in self.terminals: characters.add(Character(terminal.name)) final = State("new_final") # TODO assert that name is unique, as for hell in make_total states.add(final) transition: Dict[Tuple[State, Character], Set[State]] = dict() for nonterminal in self.rules: state = State(nonterminal.name) for rule in self.rules[nonterminal]: # rule A -> a becomes d(A, a) = final if isinstance(rule, Terminal): # TODO and a is not \eps if isinstance(rule, Terminal): character = Character(rule.name) transition.setdefault((state, character), set()).add(final) # rule A -> aB becomes d(A, a) = B elif (state, rule[0]) in transition: elif isinstance(rule, Tuple): character = Character(rule[0].name) transition[state, character].add(State(rule[1].name)) else: character = Character(rule[0].name) transition[state, character] = {State(rule[1].name)} transition.setdefault((state, character), set()).add(State(rule[1].name)) final_states = {final} for rule in self.rules[self.init]: if isinstance(rule, Eps): final_states.add(init) # TODO if init -> \eps: nfa.final.add(nfa.init) # I need to know how to treat \eps nfa = NFA(states, characters, transition, init, {final}) nfa = NFA(states, characters, transition, init, final_states) return nfa No newline at end of file
grammars_cfg.py +2 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ class CFG: if nonterminal == self.init and not self.is_nonterminal_used(nonterminal): continue else: print("Gramatika není regulární: výskyt epsilon u neterminálu, který se vyskytuje na pravé straně některého pravidla.") #print("Gramatika není regulární: výskyt epsilon u neterminálu, který se vyskytuje na pravé straně některého pravidla.") return False if isinstance(rule, tuple): # TODO nicer Loading @@ -170,7 +170,7 @@ class CFG: (len(rule) == 2 and isinstance(rule[0], Terminal) and isinstance(rule[1], Nonterminal)): continue print("Gramatika není regulární: špatný tvar pravé strany některého z pravidel.") #print("Gramatika není regulární: špatný tvar pravé strany některého z pravidel.") return False return True Loading
parser.py +7 −6 Original line number Diff line number Diff line Loading @@ -115,8 +115,9 @@ class Parser: return CFG(listener.nonterminals, listener.terminals, listener.rules, listener.init) def str_to_reggrammar(self): pass def str_to_reggrammar(self, string: str) -> RegGrammar: cfg = self.str_to_cfg(string) return RegGrammar.from_cfg(cfg) def str_to_dfa(self, string: str) -> DFA: listener = self.common_parse(string, DFALexer, DFAParser, DFAListener) Loading Loading @@ -205,6 +206,7 @@ class NFAListener(NFAListener): self.efa = False def exitInit(self, ctx): if ctx.statename() is not None: state = State(str(ctx.statename().STATE())) self.init = state self.states.add(state) Loading @@ -212,7 +214,6 @@ class NFAListener(NFAListener): def exitProduction(self, ctx): state = State(str(ctx.statename(0).STATE())) self.states.add(state) dest_states = set() i = 0 while ctx.stateset().statename(i) is not None: Loading