-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9e698b8
commit ff80c98
Showing
14 changed files
with
216 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from codelimit.common.gsm.State import State | ||
|
||
|
||
class Automata: | ||
def __init__(self, start: State, accepting: State | list[State]): | ||
self.start = start | ||
self.accepting = accepting | ||
|
||
def is_accepting(self, state: State) -> bool: | ||
if isinstance(self.accepting, list): | ||
return state in self.accepting | ||
else: | ||
return state == self.accepting | ||
|
||
def __str__(self): | ||
return f'Automata(start={self.start}, accepting={self.accepting})' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
from codelimit.common.gsm.NFA import NFA | ||
from codelimit.common.gsm.Automata import Automata | ||
from codelimit.common.gsm.Operator import Operator | ||
|
||
|
||
class Concat(Operator): | ||
def apply(self, stack: list[NFA]): | ||
def apply(self, stack: list[Automata]): | ||
if len(stack) < 2: | ||
return | ||
nfa1 = stack.pop() | ||
nfa2 = stack.pop() | ||
nfa2.accepting.assign(nfa1.start) | ||
nfa = NFA(nfa2.start, nfa1.accepting) | ||
nfa = Automata(nfa2.start, nfa1.accepting) | ||
stack.append(nfa) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,79 @@ | ||
from codelimit.common.gsm.Atom import Atom | ||
from codelimit.common.gsm.Concat import Concat | ||
from codelimit.common.gsm.NFA import NFA | ||
from codelimit.common.gsm.Operator import Operator | ||
from typing import Iterable | ||
|
||
from codelimit.common.gsm.Atom import Atom | ||
from codelimit.common.gsm.Automata import Automata | ||
from codelimit.common.gsm.Concat import Concat | ||
from codelimit.common.gsm.Operator import Operator | ||
from codelimit.common.gsm.State import State | ||
|
||
def expression_to_nfa(expression: list[Operator | str]) -> NFA: | ||
|
||
def expression_to_nfa(expression: list[Operator | str]) -> Automata: | ||
op_expression = [Atom(item) if isinstance(item, str) else item for item in expression] | ||
nfa_stack = [] | ||
for item in op_expression: | ||
item.apply(nfa_stack) | ||
Concat().apply(nfa_stack) | ||
|
||
return nfa_stack.pop() | ||
|
||
|
||
def epsilon_closure(states: State | Iterable[State]) -> set[State]: | ||
result = set() | ||
if isinstance(states, State): | ||
states: set[State] = {states} | ||
for state in states: | ||
result.add(state) | ||
if state.epsilon_transitions: | ||
for s in state.epsilon_transitions: | ||
result.update(epsilon_closure(s)) | ||
return result | ||
|
||
|
||
def move(states: set[State], symbol: str) -> set[State]: | ||
result = set() | ||
for state in states: | ||
if state.transition and state.transition[0] == symbol: | ||
result.add(state.transition[1]) | ||
return result | ||
|
||
|
||
def state_set_transitions(states: set[State]) -> set[str]: | ||
result = set() | ||
for state in states: | ||
if state.transition: | ||
result.add(state.transition[0]) | ||
return result | ||
|
||
|
||
def state_set_id(states: set[State]) -> str: | ||
return ", ".join([str(id) for id in sorted([state.id for state in states])]) | ||
|
||
|
||
def nfa_to_dfa(nfa: Automata) -> Automata: | ||
start = State() | ||
stack = [(start, epsilon_closure(nfa.start))] | ||
states = {} | ||
accepting_states = [] | ||
marked_states = set() | ||
while stack: | ||
state, T = stack.pop() | ||
T_id = state_set_id(T) | ||
if T_id in marked_states: | ||
continue | ||
else: | ||
marked_states.add(T_id) | ||
if nfa.accepting in T: | ||
accepting_states.append(state) | ||
transitions = state_set_transitions(T) | ||
for atom in transitions: | ||
new_states = epsilon_closure(move(T, atom)) | ||
if state_set_id(new_states) in states: | ||
new_state = states[state_set_id(new_states)] | ||
else: | ||
new_state = State() | ||
states[state_set_id(new_states)] = new_state | ||
if state.transition is None: | ||
state.transition = [] | ||
state.transition.append((atom, new_state)) | ||
stack.append((new_state, new_states)) | ||
return Automata(start, accepting_states) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
from codelimit.common.gsm.NFA import NFA | ||
from codelimit.common.gsm.Automata import Automata | ||
|
||
|
||
class Operator(ABC): | ||
@abstractmethod | ||
def apply(self, stack: list[NFA]): | ||
def apply(self, stack: list[Automata]): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.