A little faster but I think I might be doing this wrong.
This commit is contained in:
parent
8d58c64040
commit
bde22a5c99
1 changed files with 35 additions and 35 deletions
70
parser.py
70
parser.py
|
|
@ -1390,41 +1390,18 @@ class GenerateLALR(GenerateLR1):
|
||||||
use a bunch of improvement, probably.)
|
use a bunch of improvement, probably.)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def merge_sets(
|
|
||||||
self,
|
|
||||||
config_set_a: typing.Tuple[Configuration, ...],
|
|
||||||
config_set_b: typing.Tuple[Configuration, ...],
|
|
||||||
):
|
|
||||||
"""Merge the two config sets, by keeping the item cores but merging
|
|
||||||
the lookahead sets for each item.
|
|
||||||
"""
|
|
||||||
assert len(config_set_a) == len(config_set_b)
|
|
||||||
merged = []
|
|
||||||
for index, a in enumerate(config_set_a):
|
|
||||||
b = config_set_b[index]
|
|
||||||
assert a.clear_lookahead() == b.clear_lookahead()
|
|
||||||
|
|
||||||
new_lookahead = a.lookahead + b.lookahead
|
|
||||||
new_lookahead = tuple(sorted(set(new_lookahead)))
|
|
||||||
merged.append(a.replace_lookahead(new_lookahead))
|
|
||||||
|
|
||||||
return tuple(merged)
|
|
||||||
|
|
||||||
def sets_equal(self, a, b):
|
|
||||||
a_no_la = tuple(s.clear_lookahead() for s in a)
|
|
||||||
b_no_la = tuple(s.clear_lookahead() for s in b)
|
|
||||||
return a_no_la == b_no_la
|
|
||||||
|
|
||||||
def gen_sets(self, config_set: typing.Tuple[Configuration, ...]) -> ConfigurationSetInfo:
|
def gen_sets(self, config_set: typing.Tuple[Configuration, ...]) -> ConfigurationSetInfo:
|
||||||
"""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.
|
||||||
|
|
||||||
The difference between this method and the one in GenerateLR0, where
|
The difference between this method and the one in GenerateLR0, where
|
||||||
this comes from, is in the part that stops recursion. In LALR we
|
this comes from, is that we're going to be keeping track of states
|
||||||
compare for set equality *ignoring lookahead*. If we find a match,
|
that we found that are equivalent in lookahead.
|
||||||
then instead of returning F unchanged, we merge the two equal sets
|
|
||||||
and replace the set in F, returning the modified set.
|
|
||||||
"""
|
"""
|
||||||
|
#
|
||||||
|
# First, do the actual walk. Don't merge yet: just keep track of all
|
||||||
|
# the config sets that need to be merged.
|
||||||
|
#
|
||||||
F = {}
|
F = {}
|
||||||
seen = set()
|
seen = set()
|
||||||
successors = []
|
successors = []
|
||||||
|
|
@ -1439,18 +1416,41 @@ class GenerateLALR(GenerateLR1):
|
||||||
|
|
||||||
existing = F.get(config_set_no_la)
|
existing = F.get(config_set_no_la)
|
||||||
if existing is not None:
|
if existing is not None:
|
||||||
F[config_set_no_la] = self.merge_sets(config_set, existing)
|
existing.append(config_set)
|
||||||
else:
|
else:
|
||||||
F[config_set_no_la] = config_set
|
F[config_set_no_la] = [config_set]
|
||||||
|
|
||||||
for symbol, successor in self.gen_all_successors(config_set):
|
for symbol, successor in self.gen_all_successors(config_set):
|
||||||
successor_no_la = tuple(s.clear_lookahead() for s in successor)
|
successor_no_la = tuple(s.clear_lookahead() for s in successor)
|
||||||
successors.append((config_set_no_la, symbol, successor_no_la))
|
successors.append((config_set_no_la, symbol, successor_no_la))
|
||||||
pending.append(successor)
|
pending.append(successor)
|
||||||
|
|
||||||
|
# Now we gathered the sets, merge them all.
|
||||||
|
final_sets = {}
|
||||||
|
for key, config_sets in F.items():
|
||||||
|
new_config_set = []
|
||||||
|
config_groupings = [[] for _ in range(len(config_sets[0]))]
|
||||||
|
for config_set in config_sets:
|
||||||
|
for i, config in enumerate(config_set):
|
||||||
|
config_groupings[i].append(config)
|
||||||
|
|
||||||
|
for config_group in config_groupings:
|
||||||
|
new_lookahead = [l for config in config_group for l in config.lookahead]
|
||||||
|
new_lookahead = tuple(sorted(set(new_lookahead)))
|
||||||
|
new_config_set.append(
|
||||||
|
Configuration(
|
||||||
|
name=config_group[0].name,
|
||||||
|
symbols=config_group[0].symbols,
|
||||||
|
position=config_group[0].position,
|
||||||
|
lookahead=new_lookahead,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
final_sets[key] = tuple(new_config_set)
|
||||||
|
|
||||||
# Register all the actually merged, final config sets.
|
# Register all the actually merged, final config sets.
|
||||||
result = ConfigurationSetInfo()
|
result = ConfigurationSetInfo()
|
||||||
for config_set in F.values():
|
for config_set in final_sets.values():
|
||||||
result.register_config_set(config_set)
|
result.register_config_set(config_set)
|
||||||
|
|
||||||
# Now record all the successors that we found. Of course, the actual
|
# Now record all the successors that we found. Of course, the actual
|
||||||
|
|
@ -1461,10 +1461,10 @@ class GenerateLALR(GenerateLR1):
|
||||||
# so we can find the final sets, then look them up in the registered
|
# so we can find the final sets, then look them up in the registered
|
||||||
# sets, and actually register the successor.
|
# sets, and actually register the successor.
|
||||||
for config_set_no_la, symbol, successor_no_la in successors:
|
for config_set_no_la, symbol, successor_no_la in successors:
|
||||||
actual_config_set = F[config_set_no_la]
|
actual_config_set = final_sets[config_set_no_la]
|
||||||
from_index = result.config_set_key[actual_config_set]
|
from_index = result.config_set_key[actual_config_set]
|
||||||
|
|
||||||
actual_successor = F[successor_no_la]
|
actual_successor = final_sets[successor_no_la]
|
||||||
to_index = result.config_set_key[actual_successor]
|
to_index = result.config_set_key[actual_successor]
|
||||||
|
|
||||||
result.add_successor(from_index, symbol, to_index)
|
result.add_successor(from_index, symbol, to_index)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue