faster: Iterative gen_sets
This commit is contained in:
parent
c5552ab36f
commit
066ad1e982
1 changed files with 31 additions and 26 deletions
|
|
@ -206,24 +206,25 @@ class GenerateLR0(object):
|
||||||
|
|
||||||
return tuple(next)
|
return tuple(next)
|
||||||
|
|
||||||
def gen_sets_recursive(self, config_set, F):
|
|
||||||
"""Recursively generate all configuration sets starting from the
|
|
||||||
provided set, and merge them with the provided set 'F'.
|
|
||||||
"""
|
|
||||||
if config_set in F:
|
|
||||||
return F
|
|
||||||
else:
|
|
||||||
new_F = F + (config_set,)
|
|
||||||
for successor in self.gen_all_successors(config_set):
|
|
||||||
new_F = self.gen_sets_recursive(successor, new_F)
|
|
||||||
|
|
||||||
return new_F
|
|
||||||
|
|
||||||
def gen_sets(self, config_set):
|
def gen_sets(self, config_set):
|
||||||
"""Recursively generate all configuration sets starting from the
|
"""Recursively generate all configuration sets starting from the
|
||||||
provided set, and merge them with the provided set 'F'.
|
provided set, and merge them with the provided set 'F'.
|
||||||
"""
|
"""
|
||||||
return self.gen_sets_recursive(config_set, ())
|
# NOTE: Not a set because we need to maintain insertion order!
|
||||||
|
# The first element in the dictionary needs to be the intial
|
||||||
|
# set.
|
||||||
|
F = {}
|
||||||
|
pending = [config_set]
|
||||||
|
while len(pending) > 0:
|
||||||
|
config_set = pending.pop()
|
||||||
|
if config_set in F:
|
||||||
|
continue
|
||||||
|
|
||||||
|
F[config_set] = len(F)
|
||||||
|
for successor in self.gen_all_successors(config_set):
|
||||||
|
pending.append(successor)
|
||||||
|
|
||||||
|
return tuple(F.keys())
|
||||||
|
|
||||||
|
|
||||||
def gen_all_sets(self):
|
def gen_all_sets(self):
|
||||||
|
|
@ -653,7 +654,7 @@ class GenerateLALR(GenerateLR1):
|
||||||
b_no_la = tuple(s.replace(lookahead=()) for s in b)
|
b_no_la = tuple(s.replace(lookahead=()) for s in b)
|
||||||
return a_no_la == b_no_la
|
return a_no_la == b_no_la
|
||||||
|
|
||||||
def gen_sets_recursive(self, config_set, F):
|
def gen_sets(self, config_set):
|
||||||
"""Recursively generate all configuration sets starting from the
|
"""Recursively generate all configuration sets starting from the
|
||||||
provided set, and merge them with the provided set 'F'.
|
provided set, and merge them with the provided set 'F'.
|
||||||
|
|
||||||
|
|
@ -663,19 +664,23 @@ class GenerateLALR(GenerateLR1):
|
||||||
then instead of returning F unchanged, we merge the two equal sets
|
then instead of returning F unchanged, we merge the two equal sets
|
||||||
and replace the set in F, returning the modified set.
|
and replace the set in F, returning the modified set.
|
||||||
"""
|
"""
|
||||||
config_set_no_la = tuple(s.replace(lookahead=()) for s in config_set)
|
F = {}
|
||||||
for index, existing in enumerate(F):
|
pending = [config_set]
|
||||||
existing_no_la = tuple(s.replace(lookahead=()) for s in existing)
|
while len(pending) > 0:
|
||||||
if config_set_no_la == existing_no_la:
|
config_set = pending.pop()
|
||||||
merged_set = self.merge_sets(config_set, existing)
|
config_set_no_la = tuple(s.replace(lookahead=()) for s in config_set)
|
||||||
return F[:index] + (merged_set,) + F[index+1:]
|
|
||||||
|
|
||||||
# No merge candidate found, proceed.
|
existing = F.get(config_set_no_la)
|
||||||
new_F = F + (config_set,)
|
if existing is not None:
|
||||||
for successor in self.gen_all_successors(config_set):
|
F[config_set_no_la] = self.merge_sets(config_set, existing)
|
||||||
new_F = self.gen_sets_recursive(successor, new_F)
|
else:
|
||||||
|
F[config_set_no_la] = config_set
|
||||||
|
for successor in self.gen_all_successors(config_set):
|
||||||
|
pending.append(successor)
|
||||||
|
|
||||||
return new_F
|
# NOTE: We count on insertion order here! The first element must be the
|
||||||
|
# starting state!
|
||||||
|
return tuple(F.values())
|
||||||
|
|
||||||
def find_set_index(self, sets, set):
|
def find_set_index(self, sets, set):
|
||||||
"""Find the specified set in the set of sets, and return the
|
"""Find the specified set in the set of sets, and return the
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue