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
9932bacd
Commit
9932bacd
authored
Feb 27, 2020
by
Kateřina Sloupová
Browse files
this should finally typecheck
parent
1ff54cfa
Pipeline
#53974
failed with stage
in 19 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
demo.py
View file @
9932bacd
...
...
@@ -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 transform
at
ed to REG:"
)
print
(
"DFA transformed to REG:"
)
print
(
parser
.
reg_to_str
(
dfareg
,
True
))
print
()
regdfa
=
dfareg
.
reg_to_nfa
()
print
(
"REG transform
at
ed 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()"
)
...
...
objects.py
View file @
9932bacd
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
typ
e
(
rule
)
==
Terminal
:
if
isinstanc
e
(
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
typ
e
(
rule
)
==
Terminal
:
# TODO and a is not \eps
if
isinstanc
e
(
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
:
...
...
parser.py
View file @
9932bacd
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
typ
e
(
variant
)
==
Terminal
:
if
isinstanc
e
(
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
,
d
fa
:
D
FA
,
full
:
bool
=
False
)
->
str
:
def
nfa_to_str
(
self
,
n
fa
:
N
FA
,
full
:
bool
=
False
)
->
str
:
# full - verbose description of DFA - only for development, dismiss later
states
=
"{"
for
state
in
d
fa
.
states
:
for
state
in
n
fa
.
states
:
states
+=
state
.
name
+
","
states
=
states
[:
-
1
]
+
"}"
# Vlada: states = ",".join(dfa.states) but I use it wrong or what
characters
=
"{"
for
character
in
d
fa
.
characters
:
for
character
in
n
fa
.
characters
:
characters
+=
character
.
name
+
","
characters
=
characters
[:
-
1
]
+
"}"
transition
=
""
for
key
,
set_states
in
d
fa
.
transition
.
items
():
for
key
,
set_states
in
n
fa
.
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
=
d
fa
.
init
.
name
init
=
n
fa
.
init
.
name
final
=
"F={"
for
state
in
d
fa
.
final
:
for
state
in
n
fa
.
final
:
final
+=
state
.
name
+
","
final
=
final
[:
-
1
]
+
"}"
...
...
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