faster: gen closure iterative

This commit is contained in:
John Doty 2024-04-13 13:17:02 -07:00
parent e1240759eb
commit ade859d6a0

View file

@ -5,9 +5,9 @@ This version has some performance work done.
2023
"""
import functools
from collections import namedtuple
###############################################################################
# LR0
#
@ -113,6 +113,14 @@ class GenerateLR0(object):
# rule, and in the set of states and table and whatever the first
# element is always the starting state/position.
self.grammar = [('__start', [start])] + grammar
# Convert the grammar into fully immutable tuples so we can hash
# everything.
self.grammar = tuple(
(name, tuple(symbols))
for name, symbols in self.grammar
)
self.nonterminals = {rule[0] for rule in grammar}
self.terminals = {
sym
@ -155,21 +163,21 @@ class GenerateLR0(object):
if rule[0] == config.next
)
def gen_closure(self, config, closure):
"""Compute the closure for the specified config and unify it with the
existing closure.
If the provided config is already in the closure then nothing is
done. (We assume that the closure of the config is *also* already in
the closure.)
"""
def gen_closure(self, seeds):
"""Compute the closure for the specified configs. We have replaced a
recursive version with an iterative one."""
closure = set()
pending = list(seeds)
while len(pending) > 0:
config = pending.pop()
if config in closure:
return closure
else:
new_closure = tuple(closure) + (config,)
continue
closure.add(config)
for next_config in self.gen_closure_next(config):
new_closure = self.gen_closure(next_config, new_closure)
return new_closure
pending.append(next_config)
return tuple(closure) # TODO: Why tuple?
def gen_successor(self, config_set, symbol):
"""Compute the successor state for the given config set and the
@ -184,10 +192,7 @@ class GenerateLR0(object):
if config.at_symbol(symbol)
]
closure = ()
for seed in seeds:
closure = self.gen_closure(seed, closure)
closure = self.gen_closure(seeds)
return closure
def gen_all_successors(self, config_set):
@ -216,8 +221,7 @@ class GenerateLR0(object):
def gen_all_sets(self):
"""Generate all of the configuration sets for the grammar."""
initial_set = self.gen_closure(
Configuration.from_rule(self.grammar[0]),
(),
[ Configuration.from_rule(self.grammar[0]) ]
)
return self.gen_sets(initial_set, ())
@ -601,8 +605,7 @@ class GenerateLR1(GenerateSLR1):
symbol to '$'.
"""
initial_set = self.gen_closure(
Configuration.from_rule(self.grammar[0], lookahead=('$',)),
(),
[ Configuration.from_rule(self.grammar[0], lookahead=('$',)) ],
)
return self.gen_sets(initial_set, ())
@ -750,6 +753,7 @@ def examples():
gen = GenerateLR0('E', grammar_simple)
table = gen.gen_table()
print(format_table(gen, table))
tree = parse(table, ['id', '+', '(', 'id', ')'])
print(format_node(tree) + "\n")
print()