Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
fja
eval
Commits
ef4e5e17
Commit
ef4e5e17
authored
Mar 17, 2020
by
Kateřina Sloupová
Browse files
tweaks according to a code review
parent
cd0fb1f1
Pipeline
#55726
failed with stage
in 20 seconds
Changes
5
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
demo.py
View file @
ef4e5e17
...
...
@@ -92,7 +92,7 @@ def dfa_eq(str1, str2):
print
(
parser
.
dfa_to_str
(
dfa1
))
dfa2
=
parser
.
str_to_dfa
(
str2
)
print
(
parser
.
dfa_to_str
(
dfa2
))
return
dfa1
.
is_equivalent
(
dfa2
)
return
DFA
.
is_equivalent
(
dfa1
,
dfa2
)
except
RecognitionException
as
re
:
print
(
re
)
...
...
@@ -229,7 +229,7 @@ def main():
"of DFA through intersections with complements."
)
print
()
print
(
"is dfa3 empty?"
,
dfa_3
.
is_empty
())
print
(
"dfa3 and canonical dfa3: "
,
dfa_3
.
is_equivalent
(
canonical
),
", should be True"
)
print
(
"dfa3 and canonical dfa3: "
,
DFA
.
is_equivalent
(
dfa_3
,
canonical
),
", should be True"
)
print
()
print
(
"__________________________________"
)
...
...
fja_checker.py
View file @
ef4e5e17
...
...
@@ -5,7 +5,8 @@ import sys
import
signal
def
parse
(
string
:
str
,
automaton_type
:
str
)
->
DFA
:
# TODO better name
def
parse_transform
(
string
:
str
,
automaton_type
:
str
)
->
DFA
:
try
:
parser
=
Parser
()
...
...
@@ -18,9 +19,10 @@ def parse(string: str, automaton_type: str) -> DFA:
except
ParsingError
as
message
:
print
(
"Parsing error:"
,
message
)
exit
(
1
)
except
AttributeError
as
message
:
print
(
"Parsing error:"
,
message
)
exit
(
1
)
def
check_task
(
dfa
:
DFA
,
task
:
str
)
->
bool
:
...
...
@@ -33,22 +35,22 @@ def check_task(dfa: DFA, task: str) -> bool:
print
(
"DFA není minimální."
)
return
False
not_
canonical
=
not
dfa
.
is_canonical
()
if
task
==
"CAN"
and
not
_
canonical
:
canonical
=
dfa
.
is_canonical
()
if
task
==
"CAN"
and
not
canonical
:
print
(
"DFA není kanonický."
)
return
False
if
task
==
"TOC"
and
(
not
dfa
.
is_total
()
or
not
_
canonical
):
if
task
==
"TOC"
and
(
not
dfa
.
is_total
()
or
not
canonical
):
if
not
dfa
.
is_total
():
print
(
"DFA není totální."
)
if
not
_
canonical
:
if
not
canonical
:
print
(
"DFA není kanonický."
)
return
False
if
task
==
"MIC"
and
(
not
dfa
.
is_minimal
()
or
not
_
canonical
):
if
task
==
"MIC"
and
(
not
dfa
.
is_minimal
()
or
not
canonical
):
if
not
dfa
.
is_minimal
():
print
(
"DFA není minimální."
)
if
not
_
canonical
:
if
not
canonical
:
print
(
"DFA není kanonický."
)
return
False
...
...
@@ -69,15 +71,15 @@ def main():
if
argument
[:
2
]
==
"-o"
:
teacher_solution
=
argument
[
2
:]
task_prefix
,
teacher_solution
=
teacher_solution
.
split
(
":"
,
1
)
assert
len
(
task_prefix
)
>=
7
,
"Teachers solution could not be parsed correctly."
automata_type
,
task
,
_
=
task_prefix
.
split
(
"-"
,
2
)
assert
len
(
automata_type
)
==
3
and
len
(
task
)
==
3
,
"Teachers solution could not be parsed correctly."
try
:
task_prefix
,
teacher_solution
=
teacher_solution
.
split
(
":"
,
1
)
assert
len
(
task_prefix
)
>=
7
,
"Teachers solution could not be parsed correctly."
automata_type
,
task
,
_
=
task_prefix
.
split
(
"-"
,
2
)
assert
len
(
automata_type
)
==
3
and
len
(
task
)
==
3
,
"Teachers solution could not be parsed correctly."
student_dfa
=
parse
(
student_solution
,
automata_type
)
teacher_dfa
=
parse
(
teacher_solution
,
automata_type
)
student_dfa
=
parse
_transform
(
student_solution
,
automata_type
)
teacher_dfa
=
parse
_transform
(
teacher_solution
,
automata_type
)
try
:
#
if
teacher_dfa
.
is_empty
()
and
student_dfa
.
is_empty
():
print
(
"Správné řešení."
)
...
...
@@ -89,7 +91,7 @@ def main():
print
(
"Nesprávné řešení."
)
exit
(
1
)
result
=
student_dfa
.
is_equivalent
(
teacher_dfa
)
result
=
DFA
.
is_equivalent
(
student_dfa
,
teacher_dfa
)
if
check_task
(
student_dfa
,
task
)
and
result
:
print
(
"Správné řešení."
)
exit
(
0
)
...
...
parser.py
View file @
ef4e5e17
from
typing
import
List
,
Dict
,
Tuple
,
Optional
,
Union
from
typing
import
List
,
Dict
,
Tuple
,
Optional
,
Union
,
Set
,
TypeVar
import
re
from
reg_automata
import
DFA
,
NFA
,
NFAE
,
State
,
Character
,
Eps
from
reg_grammars
import
REG
,
Terminal
from
reg_grammars
import
REG
,
Terminal
,
Nonterminal
import
antlr4
# type: ignore
from
DFA_grammarLexer
import
DFA_grammarLexer
from
DFA_grammarParser
import
DFA_grammarParser
...
...
@@ -15,17 +15,21 @@ class ParsingError(Exception):
self
.
message
=
message
class
Parser
:
def
__init__
(
self
):
pass
def
names_to_str
(
self
,
collection
:
Union
[
Set
[
State
],
Set
[
Character
],
Set
[
Terminal
],
Set
[
Nonterminal
]])
->
str
:
return
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
collection
)))
+
"}"
def
reg_to_str
(
self
,
reg
:
REG
,
full
:
bool
=
False
)
->
str
:
rules
=
self
.
rules_to_str
(
reg
.
rules
)
if
not
full
:
return
"P="
+
rules
# full - verbose description of DFA - only for development, dismiss later
nonterminals
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
reg
.
nonterminals
)
))
+
"}"
terminals
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
reg
.
terminals
)
))
+
"}"
nonterminals
=
self
.
names_to_str
(
reg
.
nonterminals
)
terminals
=
self
.
names_to_str
(
reg
.
terminals
)
out
=
"REG = ("
+
nonterminals
+
", "
+
terminals
+
", P,"
+
reg
.
init
.
name
+
")
\n
P="
out
+=
(
self
.
rules_to_str
(
reg
.
rules
))
...
...
@@ -56,22 +60,18 @@ class Parser:
def
dfa_to_str
(
self
,
dfa
:
DFA
,
full
:
bool
=
False
)
->
str
:
# full - verbose description of DFA - only for development, dismiss later
states
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
dfa
.
states
)))
+
"}"
characters
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
dfa
.
characters
)))
+
"}"
transition
=
""
for
key
,
state_2
in
dfa
.
transition
.
items
():
state_1
,
character
=
key
transition
+=
"("
+
state_1
.
name
+
","
+
character
.
name
+
")="
+
state_2
.
name
+
" "
init
=
"init="
+
dfa
.
init
.
name
final
=
"final=
{
"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
dfa
.
final
)
))
+
"}"
final
=
"final="
+
self
.
names_to_str
(
dfa
.
final
)
# full - verbose description of DFA - only for development, dismiss later
if
full
:
return
"DFA = ("
+
states
+
", "
+
characters
+
", d, "
+
\
init
+
", "
+
final
+
")
\n
"
+
transition
return
"DFA = ("
+
self
.
names_to_str
(
dfa
.
states
)
+
", "
+
self
.
names_to_str
(
dfa
.
characters
)
+
\
", d, "
+
init
+
", "
+
final
+
")
\n
"
+
transition
else
:
return
init
+
" "
+
transition
+
final
...
...
@@ -79,27 +79,19 @@ class Parser:
def
nfa_to_str
(
self
,
nfa
:
Union
[
NFA
,
NFAE
],
full
:
bool
=
False
)
->
str
:
# full - verbose description of DFA - only for development, dismiss later
states
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
nfa
.
states
)))
+
"}"
characters
=
"{"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
nfa
.
characters
)))
+
"}"
transition
=
""
for
key
,
set_states
in
nfa
.
transition
.
items
():
state
,
character
=
key
char
=
character
.
name
if
not
isinstance
(
character
,
Eps
)
else
"ε"
if
isinstance
(
character
,
Eps
)
and
isinstance
(
nfa
,
NFAE
):
dest_states
=
nfa
.
transition
[
state
,
character
]
elif
isinstance
(
character
,
Character
)
and
isinstance
(
nfa
,
NFA
):
dest_states
=
nfa
.
transition
[
state
,
character
]
transition
+=
"("
+
state
.
name
+
","
+
char
+
")={"
+
\
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
dest_states
)))
+
"} "
dest_states
=
nfa
.
transition
[
state
,
character
]
transition
+=
"("
+
state
.
name
+
","
+
char
+
")="
+
self
.
names_to_str
(
dest_states
)
+
" "
init
=
"init="
+
nfa
.
init
.
name
final
=
"final=
{
"
+
','
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
nfa
.
final
)
))
+
"}"
final
=
"final="
+
self
.
names_to_str
(
nfa
.
final
)
if
full
:
return
"
N
FA = ("
+
states
+
", "
+
characters
+
", d, "
+
\
init
+
", "
+
final
+
")
\n
"
+
transition
return
"
D
FA = ("
+
self
.
names_to_str
(
nfa
.
states
)
+
", "
+
self
.
names_to_str
(
nfa
.
characters
)
+
\
", d, "
+
init
+
", "
+
final
+
")
\n
"
+
transition
else
:
return
init
+
" "
+
transition
+
" "
+
final
...
...
reg_automata.py
View file @
ef4e5e17
...
...
@@ -42,9 +42,6 @@ class Character:
class
Eps
:
def
__init__
(
self
):
pass
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
Eps
)
...
...
@@ -79,29 +76,27 @@ class DFA:
self
.
transition
=
transition
self
.
init
=
init
self
.
final
=
final
assert
self
.
check
()
self
.
check
()
def
check
(
self
)
->
bool
:
def
check
(
self
):
assert
len
(
self
.
states
)
>
0
,
"empty automaton"
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
:
assert
state
in
self
.
states
,
"unknown state "
+
state
.
name
return
True
def
total
(
self
)
->
DFA
:
if
self
.
is_total
():
return
self
dfa
=
deepcopy
(
self
)
total
:
D
ict
[
Tuple
[
State
,
Character
],
State
]
=
{}
total
:
D
FA
.
Transition
=
{}
# check: consider import itertools
hell_id
=
0
...
...
@@ -129,8 +124,8 @@ class DFA:
return
True
def
accepts
(
self
,
word
:
Union
[
str
,
List
[
Character
]])
->
bool
:
evaluate
:
List
[
Character
]
=
[]
if
isinstance
(
word
,
str
):
evaluate
=
[]
for
letter
in
word
:
character
=
Character
(
letter
)
evaluate
.
append
(
character
)
...
...
@@ -152,27 +147,33 @@ class DFA:
dfa
.
final
=
dfa
.
states
.
difference
(
dfa
.
final
)
return
dfa
@
staticmethod
def
state_composition
(
state_1
:
State
,
state_2
:
State
)
->
State
:
return
State
(
f
"
{
state_1
.
name
}
_
{
state_2
.
name
}
"
)
@
staticmethod
def
composition
(
dfa_1
:
DFA
,
dfa_2
:
DFA
,
operation
:
Composition
)
->
DFA
:
"""Does not require input automata to have the same alphabet."""
# new characters
characters
=
dfa_1
.
characters
.
union
(
dfa_2
.
characters
)
dfa_1
.
characters
=
characters
dfa_2
.
characters
=
characters
if
not
dfa_1
.
is_total
():
dfa_1
=
dfa_1
.
total
()
if
not
dfa_2
.
is_total
():
dfa_2
=
dfa_2
.
total
()
# new characters
characters
=
dfa_1
.
characters
.
union
(
dfa_2
.
characters
)
# ATTENTION: terminals may differ -> make total at the end?
# new init
init
=
State
(
f
"
{
dfa_1
.
init
.
name
}
_
{
dfa_2
.
init
.
name
}
"
)
init
=
DFA
.
state_composition
(
dfa_1
.
init
,
dfa_2
.
init
)
# new states and transition
states
=
{
init
}
transition
:
Dict
[
Tuple
[
State
,
Character
],
State
]
=
dict
()
for
state_1
in
dfa_1
.
states
:
for
state_2
in
dfa_2
.
states
:
state
=
State
(
f
"
{
state_1
.
name
}
_
{
state_2
.
name
}
"
)
# TODO avoid conflicts!
state
=
DFA
.
state_composition
(
state_1
,
state_2
)
# TODO avoid conflicts!
states
.
add
(
state
)
# new transition
...
...
@@ -181,14 +182,14 @@ class DFA:
(
state_2
,
character
)
in
dfa_2
.
transition
:
dest_state_1
=
dfa_1
.
transition
[
state_1
,
character
]
dest_state_2
=
dfa_2
.
transition
[
state_2
,
character
]
dest_state
=
State
(
dest_state_1
.
name
+
"_"
+
dest_state_2
.
name
)
dest_state
=
DFA
.
state_composition
(
dest_state_1
,
dest_state_2
)
transition
[
state
,
character
]
=
dest_state
# new final
final
:
Set
[
State
]
=
set
()
for
state_1
in
dfa_1
.
final
:
for
state_2
in
dfa_2
.
final
:
state
=
State
(
f
"
{
state_1
.
name
}
_
{
state_2
.
name
}
"
)
state
=
DFA
.
state_composition
(
state_1
,
state_2
)
if
operation
==
Composition
.
Union
:
final
.
add
(
state
)
...
...
@@ -202,8 +203,7 @@ class DFA:
state_2
not
in
dfa_2
.
final
:
final
.
add
(
state
)
dfa
=
DFA
(
states
,
characters
,
transition
,
init
,
final
)
return
dfa
return
DFA
(
states
,
characters
,
transition
,
init
,
final
)
@
staticmethod
def
union
(
dfa_1
:
DFA
,
dfa_2
:
DFA
)
->
DFA
:
...
...
@@ -219,7 +219,6 @@ class DFA:
def
eliminate_unreachable
(
self
)
->
DFA
:
dfa
=
deepcopy
(
self
)
previous
:
Set
[
State
]
=
set
()
actual
=
{
self
.
init
}
...
...
@@ -239,25 +238,27 @@ class DFA:
return
dfa
def
sort_characters
(
self
)
->
List
[
Character
]:
def
sort
ed
_characters
(
self
)
->
List
[
Character
]:
return
sorted
(
self
.
characters
,
key
=
lambda
x
:
x
.
name
)
def
minimize
(
self
)
->
DFA
:
dfa
=
deepcopy
(
self
)
dfa
=
dfa
.
eliminate_unreachable
()
dfa
=
dfa
.
total
()
dfa
=
self
.
eliminate_unreachable
().
total
()
characters
=
self
.
sorted_characters
()
# bc I want to iterate always in same order
characters
=
self
.
sort_characters
()
# bc I want to iterate always in same order
previous
:
Optional
[
Dict
[
State
,
int
]]
=
None
actual
=
dict
()
previous
:
Dict
[
State
,
int
]
=
dict
()
actual
:
Dict
[
State
,
int
]
=
dict
()
for
state
in
dfa
.
states
:
if
state
in
dfa
.
final
:
actual
[
state
]
=
1
else
:
actual
[
state
]
=
0
while
previous
!=
actual
:
classes_prev
=
0
classes_new
=
1
if
len
(
self
.
final
)
>
0
else
0
if
len
(
self
.
states
.
difference
(
self
.
final
))
>
0
:
classes_new
+=
1
while
classes_prev
!=
classes_new
:
previous
=
deepcopy
(
actual
)
patterns
:
Dict
[
Tuple
[
int
,
...],
Set
[
State
]]
=
dict
()
actual
=
dict
()
...
...
@@ -272,13 +273,14 @@ class DFA:
else
:
patterns
[
tuple
(
pattern
)]
=
{
state
}
i
=
0
classes_prev
=
classes_new
classes_new
=
0
for
states
in
patterns
.
values
():
for
state
in
states
:
actual
[
state
]
=
i
i
+=
1
actual
[
state
]
=
classes_new
classes_new
+=
1
new_transition
:
D
ict
[
Tuple
[
State
,
Character
],
State
]
=
{}
new_transition
:
D
FA
.
Transition
=
{}
dfa
.
states
=
set
()
dfa
.
final
=
set
()
for
state
in
actual
:
...
...
@@ -328,10 +330,10 @@ class DFA:
def
canonize
(
self
)
->
DFA
:
dfa
=
deepcopy
(
self
)
remain
=
deepcopy
(
self
.
states
)
characters
=
dfa
.
sort_characters
()
characters
=
dfa
.
sort
ed
_characters
()
i
=
0
queue
=
deque
([
dfa
.
init
])
# TODO deque
queue
=
deque
([
dfa
.
init
])
while
len
(
queue
)
>
0
:
actual
=
queue
.
popleft
()
if
actual
in
remain
:
...
...
@@ -354,14 +356,11 @@ class DFA:
rules
:
Dict
[
Nonterminal
,
Set
[
Union
[
Terminal
,
Tuple
[
Terminal
,
Nonterminal
]]]]
=
dict
()
for
state
in
self
.
states
:
nonterminal
=
Nonterminal
(
state
.
name
)
nonterminals
.
add
(
nonterminal
)
nonterminals
.
add
(
Nonterminal
(
state
.
name
))
for
character
in
self
.
characters
:
terminal
=
Terminal
(
character
.
name
)
terminals
.
add
(
terminal
)
terminal
s
.
add
(
Terminal
(
character
.
name
)
)
init
=
Nonterminal
(
"new_init"
)
# TODO assert that name is unique, as for hell in make_total
init
=
init
nonterminals
.
add
(
init
)
for
state
,
character
in
self
.
transition
:
...
...
@@ -384,7 +383,7 @@ class DFA:
else
:
rules
[
nonterminal1
]
=
{(
terminal
,
nonterminal2
)}
if
dest_state
in
self
.
final
:
rules
[
nonterminal1
].
add
(
(
terminal
)
)
rules
[
nonterminal1
].
add
(
terminal
)
reg
=
REG
(
nonterminals
,
terminals
,
rules
,
init
)
if
self
.
init
in
self
.
final
:
...
...
@@ -427,40 +426,32 @@ class DFA:
def
is_universal
(
self
):
return
self
.
complement
().
is_empty
()
# returns: True or (1. what IS in first language (self) and NOT in second (dfa), 2. analogically)
def
is_equivalent
(
self
,
dfa
:
DFA
)
->
IsEquivalentResult
:
left_empty
=
self
.
intersection
(
self
,
dfa
.
complement
()).
is_empty
()
right_empty
=
self
.
intersection
(
self
.
complement
(),
dfa
).
is_empty
()
# returns: True or fst_empty: what IS in first language and NOT in second, snd_empty: analogically)
@
staticmethod
def
is_equivalent
(
fst
:
DFA
,
snd
:
DFA
)
->
IsEquivalentResult
:
fst_empty
=
DFA
.
intersection
(
fst
,
snd
.
complement
()).
is_empty
()
snd_empty
=
DFA
.
intersection
(
fst
.
complement
(),
snd
).
is_empty
()
if
le
ft_empty
and
right
_empty
:
if
f
s
t_empty
and
snd
_empty
:
result
=
IsEquivalentResult
()
else
:
result
=
IsEquivalentResult
(
le
ft_empty
.
counterexample
,
right
_empty
.
counterexample
)
result
=
IsEquivalentResult
(
f
s
t_empty
.
counterexample
,
snd
_empty
.
counterexample
)
return
result
def
is_part_identical
(
self
,
dfa
:
DFA
)
->
bool
:
# print(self.states == dfa.states)
# print(self.characters == dfa.characters)
# print(len(self.transition), len(dfa.transition))
# print(self.transition == dfa.transition)
# print(self.init == dfa.init)
# print(self.final == dfa.final)
return
self
.
states
==
dfa
.
states
and
self
.
characters
==
dfa
.
characters
and
\
self
.
transition
==
dfa
.
transition
and
self
.
init
==
dfa
.
init
and
\
self
.
final
==
dfa
.
final
@
staticmethod
def
is_part_identical
(
fst
:
DFA
,
snd
:
DFA
)
->
bool
:
return
fst
.
states
==
snd
.
states
and
fst
.
characters
==
snd
.
characters
and
\
fst
.
transition
==
snd
.
transition
and
fst
.
init
==
snd
.
init
and
\
fst
.
final
==
snd
.
final
def
is_minimal
(
self
)
->
bool
:
minimal
=
self
.
minimize
()
return
len
(
self
.
states
)
==
len
(
minimal
.
states
)
and
\
return
self
.
is_total
()
and
len
(
self
.
states
)
==
len
(
minimal
.
states
)
and
\
len
(
self
.
transition
)
==
len
(
minimal
.
transition
)
def
is_canonical
(
self
)
->
bool
:
canonic
=
self
.
canonize
()
#import parser as par
#parser = par.Parser()
#print(parser.dfa_to_str(self))
#print(parser.dfa_to_str(canonic))
return
self
.
is_part_identical
(
canonic
)
return
DFA
.
is_part_identical
(
self
,
canonic
)
class
NFA
:
Transition
=
Dict
[
Tuple
[
State
,
Character
],
Set
[
State
]]
...
...
@@ -511,8 +502,7 @@ class NFA:
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
return
DFA
(
new_states
,
self
.
characters
,
new_transition
,
self
.
init
,
new_final
)
def
unset
(
self
,
states
:
FrozenSet
[
State
])
->
State
:
return
State
(
'_'
.
join
(
set
(
map
(
lambda
x
:
x
.
name
,
sorted
(
states
,
key
=
lambda
x
:
x
.
name
)))))
...
...
@@ -558,8 +548,7 @@ class NFAE:
if
surroundings
[
self
.
init
].
intersection
(
self
.
final
):
new_final
.
add
(
self
.
init
)
nfa
=
NFA
(
self
.
states
,
self
.
characters
,
new_transition
,
self
.
init
,
new_final
)
return
nfa
return
NFA
(
self
.
states
,
self
.
characters
,
new_transition
,
self
.
init
,
new_final
)
def
epsilon_surroundings
(
self
,
state
:
State
)
->
Set
[
State
]:
reached
:
Deque
[
State
]
=
deque
([
state
])
...
...
reg_grammars.py
View file @
ef4e5e17
...
...
@@ -67,13 +67,11 @@ class REG:
init
=
State
(
self
.
init
.
name
)
states
:
Set
[
State
]
=
set
()
for
nonterminal
in
self
.
nonterminals
:
state
=
State
(
nonterminal
.
name
)
states
.
add
(
state
)
states
.
add
(
State
(
nonterminal
.
name
))
characters
:
Set
[
Character
]
=
set
()
for
terminal
in
self
.
terminals
:
character
=
Character
(
terminal
.
name
)
characters
.
add
(
character
)
characters
.
add
(
Character
(
terminal
.
name
))
final
=
State
(
"new_final"
)
# TODO assert that name is unique, as for hell in make_total
states
.
add
(
final
)
...
...
@@ -94,12 +92,10 @@ class REG:
# rule A -> aB becomes d(A, a) = B
elif
(
state
,
rule
[
0
])
in
transition
:
character
=
Character
(
rule
[
0
].
name
)
move
=
State
(
rule
[
1
].
name
)
transition
[
state
,
character
].
add
(
move
)
transition
[
state
,
character
].
add
(
State
(
rule
[
1
].
name
))
else
:
character
=
Character
(
rule
[
0
].
name
)
move
=
State
(
rule
[
1
].
name
)
transition
[
state
,
character
]
=
{
move
}
transition
[
state
,
character
]
=
{
State
(
rule
[
1
].
name
)}
# TODO if init -> \eps: nfa.final.add(nfa.init)
# I need to know how to treat \eps
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment