Skip to content

Commit

Permalink
Make iterations work in python 2 and 3.
Browse files Browse the repository at this point in the history
  • Loading branch information
rrozansk committed Mar 6, 2019
1 parent 719a27b commit 80fa2c2
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 444,7 @@ max-bool-expr=5
max-branches=22

# Maximum number of locals for function / method body
max-locals=33
max-locals=34

# Maximum number of parents for a class (see R0901).
max-parents=7
Expand Down
3 changes: 2 additions & 1 deletion spag/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 208,8 @@ def _verify_output(files):
if not files:
raise ValueError('generated files must be of non empty')

for name, content in files.items():
for name in files:
content = files[name]
if not isinstance(name, str):
raise TypeError('generated file name must be of type string')

Expand Down
3 changes: 2 additions & 1 deletion spag/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 101,8 @@ def __init__(self, name, productions, start):
raise ValueError('start production not present in given productions')

self._rules = []
for nonterminal, rhs in productions.items():
for nonterminal in productions:
rhs = productions[nonterminal]
if not isinstance(nonterminal, str):
raise TypeError('production nonterminal must be a string')

Expand Down
33 changes: 20 additions & 13 deletions spag/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 129,8 @@ def __init__(self, name, expressions):
self._expressions = {}

nfa = []
for identifier, pattern in expressions.items():
for identifier in expressions:
pattern = expressions[identifier]
if not isinstance(identifier, str):
raise TypeError('token name/type must be a string')

Expand Down Expand Up @@ -470,7 471,7 @@ def _expand_char_class_range(expr):
elif prange:
prange = False
_char = literals.pop()
literals.extend(map(chr, range(ord(min(_char, char)), ord(max(_char, char)) 1)))
literals.extend([chr(idx) for idx in range(ord(min(_char, char)), ord(max(_char, char)) 1)])
else:
literals.append(char)
else:
Expand Down Expand Up @@ -711,10 712,12 @@ def _merge_nfa(nfa):
V.update(_nfa[1])
T.update(_nfa[2])
E[S].add(_nfa[4])
for state, etransitions in _nfa[3].items():
for state in _nfa[3]:
etransitions = _nfa[3][state]
E[state] = E.get(state, set()) | etransitions
F.add(_nfa[5])
for name, state in _nfa[6].items():
for name in _nfa[6]:
state = _nfa[6][name]
G[name] = state
return Q, V, T, E, S, F, G

Expand Down Expand Up @@ -790,12 793,14 @@ def _dfa(Q, V, T, E, S, F, G):
if t[0] in in_state:
out_states = qps[t[1]] = qps.get(t[1], set())
out_states.update(RegularGrammar._e_closure(t[2], E, cache))
for alpha, out_state in qps.items():
for alpha in qps:
out_state = qps[alpha]
out_state = frozenset(out_state)
explore.add(out_state)
Tp.add((in_state, alpha, out_state))

for name, nfa_final in G.items():
for name in G:
nfa_final = G[name]
for dfa_final in Fp:
if nfa_final in dfa_final:
Gp[name] = Gp.get(name, set()) | set([dfa_final])
Expand Down Expand Up @@ -887,8 892,9 @@ def _hopcroft(Q, V, T, S, F, G):

while explore:
selection = explore.pop()
for v_idx in symbols.values():
_selection = {q for q, q_idx in states.items() if T[v_idx][q_idx] in selection}
for key in symbols:
v_idx = symbols[key]
_selection = {q for q in states if T[v_idx][states[q]] in selection}
_selection = frozenset(_selection)
_partitions = set()
for partition in partitions:
Expand All @@ -907,7 913,7 @@ def _hopcroft(Q, V, T, S, F, G):
_partitions.add(partition)
partitions = _partitions

_states = dict(zip(partitions, range(len(partitions))))
_states = {item:idx for idx, item in enumerate(partitions)}
Tp = [[None for _ in partitions] for symbol in V]
for source in states:
for symbol in V:
Expand All @@ -934,7 940,8 @@ def _hopcroft(Q, V, T, S, F, G):

Gp = dict()

for name, dfa_finals in G.items():
for name in G:
dfa_finals = G[name]
if name == '_sink': # special case (i.e not a final state)
Gp[name] = {part for part in partitions if part & G['_sink']}
continue
Expand Down Expand Up @@ -975,11 982,11 @@ def _alpha(Q, V, T, S, F, G):
dict[str, set[str]]: the updated token to final state mapping.
"""
rename = {q: RegularGrammar._state() for q in Q}
Qp = set(rename.values())
Qp = {rename[k] for k in rename}
(states, symbols, table) = T
states = {rename[state]:idx for state, idx in states.items()}
states = {rename[state]:states[state] for state in states}
Tp = (states, symbols, [[rename[col] for col in row] for row in table])
Sp = rename[S]
Fp = {rename[f] for f in F}
Gp = {g:set([rename[s] for s in states]) for g, states in G.items()}
Gp = {g:set([rename[s] for s in G[g]]) for g in G}
return Qp, V, Tp, Sp, Fp, Gp
6 changes: 4 additions & 2 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 17,8 @@ def _compare_first_sets(expected, actual):
"""
assert len(expected) == len(actual), 'Invalid first set size produced'

for elem, items in actual.items():
for elem in actual:
items = actual[elem]
assert expected.get(elem, None) == items, \
'Invalid first set produced'

Expand All @@ -28,7 29,8 @@ def _compare_follow_sets(expected, actual):
"""
assert len(expected) == len(actual), 'Invalid follow set size produced'

for elem, items in actual.items():
for elem in actual:
items = actual[elem]
assert expected.get(elem, None) == items, \
'Invalid follow set produced'

Expand Down
10 changes: 6 additions & 4 deletions tests/test_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 22,8 @@ def _compare_expressions(expected, actual):
assert set(expected.keys()) == set(actual.keys()), \
'Incorrect token name/type set produced'

for name, expected_pattern in expected.items():
for name in expected:
expected_pattern = expected[name]
actual_pattern = expected.get(name)

assert len(expected_pattern) == len(actual_pattern), \
Expand Down Expand Up @@ -68,14 69,15 @@ def _compare_dfa(expected, actual):
S = actual.start
Qp = expected['Q']

map_generator = (dict(zip(Q, perm)) for perm in permutations(Qp, len(Qp)))
perms = permutations(Qp, len(Qp))
map_generator = ({q:perm[idx] for idx, q in enumerate(Q)} for perm in perms)
for _map in map_generator:
if _map[S] != expected['S']:
continue
if not all([_map[f] in expected['F'] for f in F]):
continue
if not all([{_map[s] for s in types} == \
expected['G'].get(name, set()) for name, types in G.items()]):
if not all([{_map[s] for s in G[name]} == \
expected['G'].get(name, set()) for name in G]):
continue
if not all([all([_map[T[symbol[v]][state[q]]] == \
Tp[_symbol[v]][_state[_map[q]]] for q in Q]) for v in V]):
Expand Down

0 comments on commit 80fa2c2

Please sign in to comment.