Commit 2e639286 authored by Kateřina Sloupová's avatar Kateřina Sloupová
Browse files

sorry, fixed

parent d0c52a0d
Loading
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -359,7 +359,8 @@ class DFA:

        return reg

    def terminating_states(self, states, pred):
    # support function: decides from which of reachable states there is a way to final state
    def terminating_states(self, states: Set[State], pred: Dict[State, Set[State]]) -> Set[State]:
        unknown: Set[State] = states.difference(self.final)
        to_add: Set[State] = states.intersection(self.final)
        terminate: Set[State] = set()
@@ -384,7 +385,7 @@ class DFA:
        # else should not happen really

    @staticmethod
    def one_of(collection: Set[Any]) -> Any:
    def one_of(collection: Set[type_var]) -> type_var:
        return next(iter(collection))

    def is_empty(self) -> IsEmptyResult:
@@ -443,7 +444,7 @@ class DFA:
        #print(','.join(set(map(lambda x: x.name, on_cycle))))

        if self.init in self.final:
            return IsEmptyResult('ε', True) if len(on_cycle.intersection(terminable)) > 0 else IsEmptyResult('ε')
            return IsEmptyResult('ε', len(on_cycle.intersection(terminable)) > 0)

        word: str = []
        state: State = self.init
@@ -457,7 +458,7 @@ class DFA:

        if len(on_cycle.intersection(terminable)) > 0:
            return IsEmptyResult(''.join(word), True)
        return IsEmptyResult(''.join(word))
        return IsEmptyResult(''.join(word), False)

    # Ha!
    def is_universal(self):
+9 −43
Original line number Diff line number Diff line
@@ -2,53 +2,11 @@ from __future__ import annotations
from typing import Set, Dict, Union, Tuple, TypeVar, List
from common import Terminal, Nonterminal, Character, State, Eps
from nfa import NFA
from grammars_cfg import CFG

# Typecheck is sufficient for grammar being a grammar of certain type
# with exception of Eps only within the init rule and not use of init elsewhere.

class CFG:
    Rules = Dict[Nonterminal, Set[Union[Eps, Tuple[Union[Terminal, Nonterminal], ...]]]]
    type_var = TypeVar('type_var')

    def __init__(self, nonterminals: Set[Nonterminal],
                 terminals: Set[Terminal],
                 rules: Rules,
                 init: Nonterminal):
        self.nonterminals = nonterminals
        self.terminals = terminals
        self.rules = rules
        self.init = init

    def is_nonterminal_used(self, nonterminal) -> bool:
        for nonterm in self.rules:
            for rule in self.rules[nonterm]:
                if not isinstance(rule, Eps) and nonterminal in rule:
                    return True
        return False

    def is_regular(self) -> bool:
        for nonterminal in self.rules:
            for rule in self.rules[nonterminal]:
                if isinstance(rule, Eps):
                    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.")
                        return False

                if isinstance(rule, tuple):  # TODO nicer
                    if (len(rule) == 1 and isinstance(rule[0], Terminal)) or \
                       (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.")
                return False
        return True

    def cfg_to_reggrammar(self) -> RegGrammar:
        if self.is_regular():
            return RegGrammar(self.nonterminals, self.terminals, self.rules, self.init)
        # TODO else?

class RegGrammar:
    Rules = Dict[Nonterminal, Set[Union[Terminal, Tuple[Terminal, Nonterminal]]]]
@@ -64,6 +22,14 @@ class RegGrammar:
        self.init = init
        assert self.check()

    @staticmethod
    def reggrammar_from_cfg(cfg: CFG) -> RegGrammar:
        try:
            if cfg.is_regular():
                return RegGrammar(cfg.nonterminals, cfg.terminals, cfg.rules, cfg.init)
        except: # I don't know
            pass

    # unused formal requirements check, regular grammars specific (rule variants)
    def check(self) -> bool:
        assert len(self.nonterminals) > 0, "empty grammar"
+26 −0
Original line number Diff line number Diff line
@@ -148,6 +148,32 @@ class CFG:
            del self.rules[src]
        self._check()

    def is_nonterminal_used(self, nonterminal) -> bool:
        for nonterm in self.rules:
            for rule in self.rules[nonterm]:
                if not isinstance(rule, Eps) and nonterminal in rule:
                    return True
        return False

    def is_regular(self) -> bool:
        for nonterminal in self.rules:
            for rule in self.rules[nonterminal]:
                if isinstance(rule, Eps):
                    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.")
                        return False

                if isinstance(rule, tuple):  # TODO nicer
                    if (len(rule) == 1 and isinstance(rule[0], Terminal)) or \
                       (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.")
                return False
        return True

    def productions(self) -> Iterable[Tuple[Nonterminal, CFG.Production]]:
        for src, prods in self.rules.items():
            for prod in prods:
+5 −1
Original line number Diff line number Diff line
@@ -112,8 +112,12 @@ class Parser:

    def str_to_cfg(self, string: str) -> CFG:
        listener = self.common_parse(string, CFGLexer, CFGParser, CFGListener)

        return CFG(listener.nonterminals, listener.terminals, listener.rules, listener.init)

    def str_to_reggrammar(self):
        pass

    def str_to_dfa(self, string: str) -> DFA:
        listener = self.common_parse(string, DFALexer, DFAParser, DFAListener)